-
Notifications
You must be signed in to change notification settings - Fork 15
Add support for multiple attachments #8
base: master
Are you sure you want to change the base?
Conversation
@lingz one area I could use your input on is how to make sure that the output is still friendly when a response fails to match |
Hey Joe, Thanks a lot for this, I will do a full review tomorrow but cursory inspection looks good. A quick idea I have would be,
Something like this might work? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Joe this looks really nice to me, apart from small comments, the only suggestion would be to make the breaking change now to prevent technical debt accumulation, since the number of users is relatively low. I'll increment the major version number to let people know, but if you add the note to README.md, that would be great. If you fix these, I can merge this and release on npm.
README.md
Outdated
|
||
Tag | Meaning | ||
--- | --- | ||
`<CARDS>` | Any card attachment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the docs here. I would just add a comment here that includes buttons, as this might not be obvious to them.
README.md
Outdated
--- | --- | ||
`<CARDS>` | Any card attachment | ||
`<IMAGE>` | Any image attachment | ||
`<OTHER>` | Any other type of attachment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add some examples below here.
src/runner.ts
Outdated
@@ -156,7 +156,7 @@ export class Runner { | |||
if (response !== null) { | |||
if (program.verbose) { | |||
const timing = (new Date().getTime() - this.timing) || 0; | |||
if (response.messageTypes.includes(MessageType.Text)) { | |||
if (response.attachments.length === 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems wrong? Should be if (response.text)
. Also, for printing, we should probably print the attachments if they exist like:
Bot: Here you go: <IMAGE> <BUTTON> <BUTTON>
I know this is not how it is before but this would bring it into consistency with the new formatting style.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good catch, thanks.
src/spec/response.ts
Outdated
this.textMatchChecker = new RegExp(Response.transformTags(this.original)); | ||
this.bodyText = this.original; | ||
|
||
// Construct a list of attachments from the attachment wildcards at the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this solution, it's nice. Though I wonder why you constrain it to happening at the end of the line? Seems a bit artificial to me?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In principle they could go anywhere, but I’m not sure what the use case would be. For example:
Dialogue:
- Human: How is my campaign doing?
- Bot: According to <IMAGE> and <IMAGE>, it’s going great!
This doesn’t make any sense in bot framework per se, because it doesn’t define a mechanism for embedding attachments inline with the text. Presumably you would expect attachments
to be [Attachment.Image, Attachment.Image]
, but is text
supposed to be 'According to'
, or 'According to and , it’s going great!
, or something else?
You can imagine a client which does support this (e.g. one that uses $0
, $1
, … to reference attachments in the attachments
array), in which case you could check that text === 'According to $0 and $1, it’s going great!'
, and that attachments[0] === Attachment.Image
and attachments[1] === Attachment.Image
; but in the absence of an established convention I’m not sure how useful this would be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually you are right that the botbuilder platform specifically limits this ordering. However, for other platforms like Slack, it is allowed to have intermingled text + attachments, so for that reason it might be good to allow the tags anywhere, and just concatenate the text.
It could lead to this edge case where someone sends
Hi <IMAGE> there <IMAGE>
and it validates against:
HI there <IMAGE> <IMAGE>
However at the same time, we could introduce this fix as a separate PR as you don't have any example connector right now, so it would be hard to test. For now we can concatenate and it will work for most practical use cases I think.
So to summarize I think for now a good compromise is to just drop the ordering condition (remove the $
on the regex parser).
src/spec/response.ts
Outdated
// simple array of strings. | ||
|
||
// Check that we have the right number of attachments. | ||
if (JSON.stringify(this.attachments) !== JSON.stringify(message.attachments)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stringify has this tricky behavior where ordering of keys is only guaranteed in Node environment IF the object is the same (same pointer). Even if two objects look the same, they will not necessarily get stringified in the same way.
Use https://github.com/substack/json-stable-stringify to do a sort before the stringify.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. I assumed that stringifying an Array<String> would be safe. If you like I can just revert ac0dd3b to avoid bringing in another library?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that sounds like a good idea
src/test/spec/response.ts
Outdated
})).to.be.true; | ||
}); | ||
it('should ignore text with <IMAGE> if no text is expected', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I think this should be a breaking change, and we can increment the major version of autobot to suggest this, and put a note in README.md
src/test/spec/response.ts
Outdated
attachments: [Attachment.Image], | ||
})).to.be.true; | ||
}); | ||
it('should ignore text with <CARDS> if no text is expected', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, so I would reverse the test condition, and make it .to.be.false
This changeset allows responses to be checked for multiple attachments, sensitive to their number, order, and type. It also allows for the text body sent along with the attachments to be (optionally) checked just like it is for a plain response, and makes it trivial to add support for more attachment types in the future.
The YAML syntax is unchanged (save for the addition of an
<OTHER>
attachment type as a catch-all), and these changes should be fully backwards compatible. To achieve this, I made two compromises, which I think are fairly natural for users: (1) attachments must come at the end of the message spec; and (2) the text body of a response is not checked if the message spec consists only of attachments.