@microsoft/teams.apps
Version:
<p> <a href="https://www.npmjs.com/package/@microsoft/teams.apps" target="_blank"> <img src="https://img.shields.io/npm/v/@microsoft/teams.apps/latest" /> </a> <a href="https://www.npmjs.com/package/@microsoft/teams.apps?activeTab=code
1,441 lines • 171 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const stream_1 = require("stream");
const axios_1 = require("axios");
const teams_api_1 = require("@microsoft/teams.api");
const teams_common_1 = require("@microsoft/teams.common");
const activity_1 = require("./activity");
const missingTokenError = () => new axios_1.AxiosError('No token', '404', undefined, undefined, {
status: 404,
statusText: 'Not Found',
headers: {},
config: {},
data: {},
});
describe('ActivityContext', () => {
let mockSender;
let mockApiClient;
let mockLogger;
let mockStorage;
let mockRef;
let context;
beforeEach(() => {
mockSender = {
createStream: jest.fn().mockReturnValue({ write: jest.fn() }),
send: jest.fn(),
};
mockApiClient = {
users: {
getToken: jest.fn(),
signOut: jest.fn(),
},
conversations: {
create: jest.fn(),
},
bots: {
signIn: {
getResource: jest.fn(),
},
},
};
mockStorage = {};
const partialLogger = {
debug: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
trace: jest.fn(),
log: jest.fn(),
};
mockLogger = {
...partialLogger,
child: jest.fn().mockReturnValue(partialLogger),
};
mockRef = {
activityId: 'test-activity-id',
channelId: 'test-channel',
conversation: {
id: 'test-conversation',
conversationType: 'channel',
isGroup: false,
},
serviceUrl: 'https://test.com',
user: { id: 'test-user', name: 'Test User', role: 'user' },
bot: { id: 'bot-id', name: 'Bot', role: 'bot' },
};
});
const buildIncomingMessageActivity = (text, id) => {
return new teams_api_1.MessageActivity(text)
.withFrom({
id: 'test-user',
name: 'Test User',
role: 'user',
})
.withRecipient({
id: 'bot-id',
name: 'Bot',
role: 'bot',
})
.withChannelId('test-channel')
.withConversation({
id: 'test-conversation',
conversationType: 'channel',
isGroup: false,
})
.withId(id ?? 'test-activity-id');
};
const buildActivityContext = (activity, constructorArgs = {}) => {
return new activity_1.ActivityContext({
appId: 'test-app',
activity,
ref: mockRef,
log: mockLogger,
api: mockApiClient,
appGraph: {},
userGraph: {},
storage: mockStorage,
connectionName: 'test-connection',
next: jest.fn(),
activitySender: mockSender,
...constructorArgs,
});
};
describe('activity channelData accessors', () => {
// Inbound activities arrive as plain JSON objects off the wire, so the
// computed `channelData` getters (channel/team/meeting/notification/tenant)
// are not present on them. The ActivityContext must rehydrate the payload
// into an activity instance so those accessors resolve. A regression where
// the payload was flattened via `toInterface()` silently dropped these
// prototype getters, making them return `undefined`.
const buildInboundPayload = () => {
return {
type: 'message',
id: 'test-activity-id',
channelId: 'test-channel',
from: { id: 'test-user', name: 'Test User', role: 'user' },
recipient: { id: 'bot-id', name: 'Bot', role: 'bot' },
conversation: {
id: 'test-conversation',
conversationType: 'channel',
isGroup: false,
},
text: 'Hello world',
channelData: {
tenant: { id: 'tenant-id' },
channel: { id: 'channel-id' },
team: { id: 'team-id' },
meeting: { id: 'meeting-id' },
notification: { alert: true },
},
};
};
it('resolves computed channelData accessors on a flattened inbound payload', () => {
const ctx = buildActivityContext(buildInboundPayload());
expect(ctx.activity.channel?.id).toEqual('channel-id');
expect(ctx.activity.team?.id).toEqual('team-id');
expect(ctx.activity.meeting?.id).toEqual('meeting-id');
expect(ctx.activity.notification?.alert).toEqual(true);
// `tenant` is a class-only getter (not declared on the public interface),
// so read it through the concrete instance shape.
expect(ctx.activity.tenant?.id).toEqual('tenant-id');
});
});
describe('reply', () => {
it('stamps quotedReply entity with activity id', async () => {
const activity = buildIncomingMessageActivity('Hello world', '1793257586722');
context = buildActivityContext(activity);
await context.reply('What is up?');
expect(mockSender.send).toHaveBeenCalledTimes(1);
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.entities).toEqual(expect.arrayContaining([
expect.objectContaining({
type: 'quotedReply',
quotedReply: { messageId: '1793257586722' },
}),
]));
});
it('prepends placeholder to text', async () => {
const activity = buildIncomingMessageActivity('Hello world', '1793257586722');
context = buildActivityContext(activity);
await context.reply('What is up?');
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.text).toEqual('<quoted messageId="1793257586722"/> What is up?');
});
it('sets placeholder as text when reply text is empty', async () => {
const activity = buildIncomingMessageActivity('Hello world', '1793257586722');
context = buildActivityContext(activity);
await context.reply('');
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.text).toEqual('<quoted messageId="1793257586722"/>');
});
it('sets placeholder as text when reply has no text', async () => {
const activity = buildIncomingMessageActivity('Hello world', '1793257586722');
context = buildActivityContext(activity);
await context.reply({ type: 'message' });
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.text).toEqual('<quoted messageId="1793257586722"/>');
});
it('does not stamp entity when activity has no id', async () => {
const activity = buildIncomingMessageActivity('Hello world', '');
context = buildActivityContext(activity);
await context.reply('What is up?');
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.entities).toBeUndefined();
});
describe('quotability of the inbound activity', () => {
it('sends without a quote when the id is a service-generated f: id (card button message)', async () => {
const activity = buildIncomingMessageActivity('click', 'f:7be43fc9-1111-2222-3333-444455556666');
context = buildActivityContext(activity);
await context.reply('What is up?');
expect(mockSender.send).toHaveBeenCalledTimes(1);
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.entities).toBeUndefined();
expect(sentActivity.text).toEqual('What is up?');
});
it.each(['0', '00', '000', '123abc', '12:34', '-5', '12.5', 'abc'])('sends without a quote when the id is the non-message value %j', async (id) => {
const activity = buildIncomingMessageActivity('click', id);
context = buildActivityContext(activity);
await context.reply('What is up?');
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.entities).toBeUndefined();
expect(sentActivity.text).toEqual('What is up?');
});
it('quotes an invoke that carries a plain numeric id', async () => {
const activity = {
...buildIncomingMessageActivity('ignored', '1793257586722'),
type: 'invoke',
name: 'adaptiveCard/action',
};
context = buildActivityContext(activity);
await context.reply('What is up?');
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.text).toEqual('<quoted messageId="1793257586722"/> What is up?');
});
it('sends without a quote for an invoke that carries an f: id', async () => {
const activity = {
...buildIncomingMessageActivity('ignored', 'f:7be43fc9-1111-2222-3333-444455556666'),
type: 'invoke',
name: 'adaptiveCard/action',
};
context = buildActivityContext(activity);
await context.reply('What is up?');
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.entities).toBeUndefined();
expect(sentActivity.text).toEqual('What is up?');
});
it('sends to the same conversation reference as send', async () => {
const activity = buildIncomingMessageActivity('click', 'f:7be43fc9-1111-2222-3333-444455556666');
context = buildActivityContext(activity);
await context.reply('What is up?');
await context.send('What is up?');
const [replyCall, sendCall] = mockSender.send.mock.calls;
expect(replyCall[1]).toBe(sendCall[1]);
expect(replyCall[0]).toEqual(sendCall[0]);
});
it('still quotes a message with a decimal id', async () => {
const activity = buildIncomingMessageActivity('typed', '1793257586722');
context = buildActivityContext(activity);
await context.reply('What is up?');
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.text).toEqual('<quoted messageId="1793257586722"/> What is up?');
});
it.each(['messageUpdate', 'messageDelete', 'messageReaction'])('still quotes a %s activity with a decimal id', async (type) => {
const activity = {
...buildIncomingMessageActivity('edited', '1793257586722'),
type,
channelData: { eventType: type === 'messageUpdate' ? 'editMessage' : 'softDeleteMessage' },
};
context = buildActivityContext(activity);
await context.reply('What is up?');
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.text).toEqual('<quoted messageId="1793257586722"/> What is up?');
});
it('still lets quote stamp an explicit message id on an invoke', async () => {
const activity = {
...buildIncomingMessageActivity('ignored', 'f:7be43fc9-1111-2222-3333-444455556666'),
type: 'invoke',
};
context = buildActivityContext(activity);
await context.quote('1793257586722', 'What is up?');
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.text).toEqual('<quoted messageId="1793257586722"/> What is up?');
});
});
});
describe('quote', () => {
it('stamps quotedReply entity with given messageId', async () => {
const activity = buildIncomingMessageActivity('Hello world');
context = buildActivityContext(activity);
await context.quote('arbitrary-msg-id', 'some text');
expect(mockSender.send).toHaveBeenCalledTimes(1);
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.entities).toEqual(expect.arrayContaining([
expect.objectContaining({
type: 'quotedReply',
quotedReply: { messageId: 'arbitrary-msg-id' },
}),
]));
});
it('prepends placeholder to text', async () => {
const activity = buildIncomingMessageActivity('Hello world');
context = buildActivityContext(activity);
await context.quote('msg-42', 'reply text');
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.text).toEqual('<quoted messageId="msg-42"/> reply text');
});
it('sets placeholder as text when no text provided', async () => {
const activity = buildIncomingMessageActivity('Hello world');
context = buildActivityContext(activity);
await context.quote('msg-42', { type: 'message' });
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.text).toEqual('<quoted messageId="msg-42"/>');
});
it('reply to targeted message strips blockquote via addTargetedMessageInfo', async () => {
const activity = new teams_api_1.MessageActivity('Hello world')
.withFrom({ id: 'test-user', name: 'Test User', role: 'user' })
.withRecipient({ id: 'bot-id', name: 'Bot', role: 'bot' }, true)
.withChannelId('test-channel')
.withConversation({ id: 'test-conversation', conversationType: 'channel', isGroup: false })
.withId('1793257586722');
context = buildActivityContext(activity);
await context.reply('Here is your agenda');
expect(mockSender.send).toHaveBeenCalledTimes(1);
const sentActivity = mockSender.send.mock.calls[0][0];
// reply quotes the numeric inbound id, then send() strips the quotedReply entity
// and the <quoted .../> placeholder for targeted messages.
expect(sentActivity.entities).not.toEqual(expect.arrayContaining([expect.objectContaining({ type: 'quotedReply' })]));
expect(sentActivity.text).toEqual('Here is your agenda');
expect(sentActivity.text).not.toContain('<quoted');
expect(sentActivity.recipient).toEqual(expect.objectContaining({
id: 'test-user',
name: 'Test User',
role: 'user',
isTargeted: true,
}));
expect(sentActivity.entities).toEqual(expect.arrayContaining([
expect.objectContaining({
type: 'targetedMessageInfo',
messageId: '1793257586722',
}),
]));
});
});
describe('send', () => {
it('sends the activity to the sender plugin', async () => {
const activity = buildIncomingMessageActivity('Hello world');
context = buildActivityContext(activity);
await context.send('What is up?');
expect(mockSender.send).toHaveBeenCalledTimes(1);
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({
text: 'What is up?',
type: 'message',
}), mockRef);
});
it('accepts an omitted or undefined conversation reference', async () => {
const activity = buildIncomingMessageActivity('Hello world');
context = buildActivityContext(activity);
const maybeRef = undefined;
await context.send('forwarded', maybeRef);
await context.send('explicit', undefined);
expect(mockSender.send).toHaveBeenCalledTimes(2);
expect(mockSender.send).toHaveBeenNthCalledWith(1, expect.objectContaining({ text: 'forwarded' }), mockRef);
expect(mockSender.send).toHaveBeenNthCalledWith(2, expect.objectContaining({ text: 'explicit' }), mockRef);
});
describe('reply chain placement', () => {
const chatId = '19:user_bot@unq.gbl.spaces';
const channelId = '19:channel@thread.tacv2';
const buildInbound = (options) => {
const activity = new teams_api_1.MessageActivity('Hello world')
.withFrom({ id: 'test-user', name: 'Test User', role: 'user' })
.withRecipient({ id: 'bot-id', name: 'Bot', role: 'bot' })
.withChannelId('test-channel')
.withConversation({ id: options.conversationId, conversationType: options.conversationType, isGroup: false })
.withId(options.id)
.withChannelData(options.channelData ?? {});
return activity;
};
const refFor = (conversationId, conversationType) => ({
...mockRef,
conversation: { id: conversationId, conversationType, isGroup: false },
});
const lastCall = () => mockSender.send.mock.calls[0];
it('replies in the reply chain when the inbound is inside one, in a chat', async () => {
const ref = refFor('a:encrypted-conversation', 'personal');
context = buildActivityContext(buildInbound({
conversationType: 'personal',
conversationId: 'a:encrypted-conversation',
id: 'reply-2',
channelData: { chat: { id: chatId }, replyChain: { id: 'root-1' } },
}), { ref });
await context.send('hi');
const [params, sentRef, options] = lastCall();
expect(params).toEqual(expect.objectContaining({ text: 'hi', type: 'message' }));
expect(sentRef.conversation.id).toBe(chatId);
expect(options).toEqual({ replyChainId: 'root-1' });
});
it('does not fall back to the inbound conversation in a chat when the reply chain route is not found', async () => {
const ref = refFor('a:encrypted-conversation', 'personal');
context = buildActivityContext(buildInbound({
conversationType: 'personal',
conversationId: 'a:encrypted-conversation',
id: 'reply-2',
channelData: { chat: { id: chatId }, replyChain: { id: 'root-1' } },
}), { ref });
mockSender.send.mockRejectedValueOnce(Object.assign(new Error('Not Found'), { response: { status: 404 } }));
await expect(context.send('hi')).rejects.toThrow('Not Found');
expect(mockSender.send).toHaveBeenCalledTimes(1);
});
it('replies in the reply chain in a group chat by the shape of the payload', async () => {
const ref = refFor('19:group@thread.v2', 'groupChat');
context = buildActivityContext(buildInbound({
conversationType: 'groupChat',
conversationId: '19:group@thread.v2',
id: 'reply-2',
channelData: { chat: { id: '19:group@thread.v2' }, replyChain: { id: 'root-1' } },
}), { ref });
await context.send('hi');
const [, sentRef, options] = lastCall();
expect(sentRef.conversation.id).toBe('19:group@thread.v2');
expect(options).toEqual({ replyChainId: 'root-1' });
});
it('sends to the inbound conversation in a group chat when the payload carries no reply chain id', async () => {
const ref = refFor('19:group@thread.v2', 'groupChat');
context = buildActivityContext(buildInbound({
conversationType: 'groupChat',
conversationId: '19:group@thread.v2',
id: 'reply-2',
channelData: { chat: { id: '19:group@thread.v2' } },
}), { ref });
await context.send('hi');
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({ text: 'hi' }), ref);
});
it.each([
['a 404', 404],
['a 400', 400],
])('does not fall back in a group chat after %s from the reply chain route', async (_name, status) => {
const ref = refFor('19:group@thread.v2', 'groupChat');
context = buildActivityContext(buildInbound({
conversationType: 'groupChat',
conversationId: '19:group@thread.v2',
id: 'reply-2',
channelData: { chat: { id: '19:group@thread.v2' }, replyChain: { id: 'root-1' } },
}), { ref });
mockSender.send.mockRejectedValueOnce(Object.assign(new Error('Rejected'), { response: { status } }));
await expect(context.send('hi')).rejects.toThrow('Rejected');
expect(mockSender.send).toHaveBeenCalledTimes(1);
});
it('does not fall back in a chat after a 400 from the reply chain route', async () => {
const ref = refFor('a:encrypted-conversation', 'personal');
context = buildActivityContext(buildInbound({
conversationType: 'personal',
conversationId: 'a:encrypted-conversation',
id: 'reply-2',
channelData: { chat: { id: chatId }, replyChain: { id: 'root-1' } },
}), { ref });
mockSender.send.mockRejectedValueOnce(Object.assign(new Error('Bad Request'), { response: { status: 400 } }));
await expect(context.send('hi')).rejects.toThrow('Bad Request');
expect(mockSender.send).toHaveBeenCalledTimes(1);
});
it('replies in the reply chain in a meeting chat by the shape of the payload', async () => {
const ref = refFor('19:meeting_abc@thread.v2', 'groupChat');
context = buildActivityContext(buildInbound({
conversationType: 'groupChat',
conversationId: '19:meeting_abc@thread.v2',
id: 'reply-2',
channelData: {
chat: { id: '19:meeting_abc@thread.v2' },
replyChain: { id: 'root-1' },
meeting: { id: 'meeting-1' },
},
}), { ref });
await context.send('hi');
const [, sentRef, options] = lastCall();
expect(sentRef.conversation.id).toBe('19:meeting_abc@thread.v2');
expect(options).toEqual({ replyChainId: 'root-1' });
});
it('creates the stream in the reply chain when the inbound is inside one, in a chat', () => {
const ref = refFor('a:encrypted-conversation', 'personal');
mockSender.createStream.mockClear();
context = buildActivityContext(buildInbound({
conversationType: 'personal',
conversationId: 'a:encrypted-conversation',
id: 'reply-2',
channelData: { chat: { id: chatId }, replyChain: { id: 'root-1' } },
}), { ref });
expect(mockSender.createStream).toHaveBeenCalledWith(ref, {
replyChain: { chatOrChannelId: chatId, replyChainId: 'root-1' },
});
});
it('creates the stream without a reply chain for a top-level message in a chat and in a group chat', () => {
for (const conversationType of ['personal', 'groupChat']) {
const ref = refFor('a:conversation', conversationType);
mockSender.createStream.mockClear();
context = buildActivityContext(buildInbound({
conversationType,
conversationId: 'a:conversation',
id: 'root-1',
channelData: { chat: { id: chatId }, replyChain: { id: 'root-1' } },
}), { ref });
expect(mockSender.createStream).toHaveBeenCalledWith(ref, undefined);
}
});
it('creates the stream in the reply chain for a group chat by the shape of the payload', () => {
const ref = refFor('a:conversation', 'groupChat');
mockSender.createStream.mockClear();
context = buildActivityContext(buildInbound({
conversationType: 'groupChat',
conversationId: 'a:conversation',
id: 'reply-2',
channelData: { chat: { id: chatId }, replyChain: { id: 'root-1' } },
}), { ref });
expect(mockSender.createStream).toHaveBeenCalledWith(ref, {
replyChain: { chatOrChannelId: chatId, replyChainId: 'root-1' },
});
});
it('places nothing for an inbound activity that is not a message', async () => {
const ref = refFor('a:encrypted-conversation', 'personal');
mockSender.createStream.mockClear();
const inbound = {
...buildInbound({
conversationType: 'personal',
conversationId: 'a:encrypted-conversation',
id: 'reply-2',
channelData: { chat: { id: chatId }, replyChain: { id: 'root-1' } },
}),
type: 'event',
};
context = buildActivityContext(inbound, { ref });
expect(mockSender.createStream).toHaveBeenCalledWith(ref, undefined);
await context.send('hi');
const [, sentRef, options] = lastCall();
expect(sentRef.conversation.id).toBe('a:encrypted-conversation');
expect(options).toBeUndefined();
});
it('creates the stream in the reply chain in a meeting chat by the shape of the payload', () => {
const ref = refFor('19:meeting_abc@thread.v2', 'groupChat');
mockSender.createStream.mockClear();
context = buildActivityContext(buildInbound({
conversationType: 'groupChat',
conversationId: '19:meeting_abc@thread.v2',
id: 'reply-2',
channelData: {
chat: { id: chatId },
replyChain: { id: 'root-1' },
meeting: { id: 'meeting-1' },
},
}), { ref });
expect(mockSender.createStream).toHaveBeenCalledWith(ref, {
replyChain: { chatOrChannelId: chatId, replyChainId: 'root-1' },
});
});
it('sends to the inbound conversation when the inbound is a top-level message in a chat', async () => {
const ref = refFor('a:encrypted-conversation', 'personal');
context = buildActivityContext(buildInbound({
conversationType: 'personal',
conversationId: 'a:encrypted-conversation',
id: 'root-1',
channelData: { chat: { id: chatId }, replyChain: { id: 'root-1' } },
}), { ref });
await context.send('hi');
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({ text: 'hi' }), ref);
});
it('sends to the inbound conversation when the payload carries no reply chain id', async () => {
const ref = refFor(chatId, 'personal');
context = buildActivityContext(buildInbound({ conversationType: 'personal', conversationId: chatId, id: 'm-1', channelData: { chat: { id: chatId } } }), { ref });
await context.send('hi');
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({ text: 'hi' }), ref);
});
it('sends to the inbound conversation when the chat id is missing', async () => {
const ref = refFor('a:encrypted-conversation', 'personal');
context = buildActivityContext(buildInbound({
conversationType: 'personal',
conversationId: 'a:encrypted-conversation',
id: 'reply-2',
channelData: { replyChain: { id: 'root-1' } },
}), { ref });
await context.send('hi');
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({ text: 'hi' }), ref);
});
describe('in a channel', () => {
const suffixed = `${channelId};messageid=root-1`;
it('keeps sending to the inbound conversation when the payload has no reply chain id', async () => {
const ref = refFor(suffixed, 'channel');
context = buildActivityContext(buildInbound({
conversationType: 'channel',
conversationId: suffixed,
id: 'reply-2',
channelData: { channel: { id: channelId } },
}), { ref });
await context.send('hi');
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({ text: 'hi' }), ref);
expect(mockSender.send.mock.calls[0]).toHaveLength(2);
expect(mockSender.send.mock.calls[0][1].conversation.id).toBe(suffixed);
});
it.each([
['a thread reply', 'reply-2'],
['a root post', 'root-1'],
])('creates the stream in the reply chain of the thread for %s', (_name, id) => {
const ref = refFor(suffixed, 'channel');
mockSender.createStream.mockClear();
context = buildActivityContext(buildInbound({
conversationType: 'channel',
conversationId: suffixed,
id,
channelData: { channel: { id: channelId }, replyChain: { id: 'root-1' } },
}), { ref });
expect(mockSender.createStream).toHaveBeenCalledWith(ref, {
replyChain: { chatOrChannelId: channelId, replyChainId: 'root-1' },
});
});
it.each([
['a blank channel id', { channel: { id: ' ' }, replyChain: { id: 'root-1' } }],
['a blank reply chain id', { channel: { id: channelId }, replyChain: { id: ' ' } }],
])('sends to the inbound conversation and creates the stream there for %s', async (_name, channelData) => {
const ref = refFor(suffixed, 'channel');
mockSender.createStream.mockClear();
context = buildActivityContext(buildInbound({ conversationType: 'channel', conversationId: suffixed, id: 'reply-2', channelData }), { ref });
await context.send('hi');
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({ text: 'hi' }), ref);
expect(mockSender.send.mock.calls[0]).toHaveLength(2);
expect(mockSender.createStream).toHaveBeenCalledWith(ref, undefined);
});
it('replies in the reply chain of a root post', async () => {
const ref = refFor(`${channelId};messageid=root-1`, 'channel');
context = buildActivityContext(buildInbound({
conversationType: 'channel',
conversationId: `${channelId};messageid=root-1`,
id: 'root-1',
channelData: { channel: { id: channelId }, replyChain: { id: 'root-1' } },
}), { ref });
await context.send('hi');
const [, sentRef, options] = mockSender.send.mock.calls[0];
expect(sentRef.conversation.id).toBe(channelId);
expect(options).toEqual({ replyChainId: 'root-1' });
});
it('replies in the reply chain of the thread when the payload carries a reply chain id', async () => {
const ref = refFor(suffixed, 'channel');
context = buildActivityContext(buildInbound({
conversationType: 'channel',
conversationId: suffixed,
id: 'reply-2',
channelData: { channel: { id: channelId }, replyChain: { id: 'root-1' } },
}), { ref });
await context.send('hi');
const [, sentRef, options] = mockSender.send.mock.calls[0];
expect(sentRef.conversation.id).toBe(channelId);
expect(options).toEqual({ replyChainId: 'root-1' });
});
it('sends to the inbound conversation when the reply chain route is not found', async () => {
const ref = refFor(suffixed, 'channel');
context = buildActivityContext(buildInbound({
conversationType: 'channel',
conversationId: suffixed,
id: 'reply-2',
channelData: { channel: { id: channelId }, replyChain: { id: 'root-1' } },
}), { ref });
mockSender.send.mockRejectedValueOnce(Object.assign(new Error('Not Found'), { response: { status: 404 } }));
await context.send('hi');
expect(mockSender.send).toHaveBeenCalledTimes(2);
expect(mockSender.send.mock.calls[1]).toEqual([expect.objectContaining({ text: 'hi' }), ref]);
});
it('does not fall back for an error other than a missing route', async () => {
const ref = refFor(suffixed, 'channel');
context = buildActivityContext(buildInbound({
conversationType: 'channel',
conversationId: suffixed,
id: 'reply-2',
channelData: { channel: { id: channelId }, replyChain: { id: 'root-1' } },
}), { ref });
mockSender.send.mockRejectedValueOnce(Object.assign(new Error('Bad Request'), { response: { status: 400 } }));
await expect(context.send('hi')).rejects.toThrow('Bad Request');
expect(mockSender.send).toHaveBeenCalledTimes(1);
});
it('keeps sending to the inbound conversation for a channel reply with no channel id', async () => {
const ref = refFor(suffixed, 'channel');
context = buildActivityContext(buildInbound({
conversationType: 'channel',
conversationId: suffixed,
id: 'reply-2',
channelData: { replyChain: { id: 'root-1' } },
}), { ref });
await context.send('hi');
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({ text: 'hi' }), ref);
});
});
it.each([
['a blank chat id', { chat: { id: ' ' }, replyChain: { id: 'root-1' } }],
['a blank reply chain id', { chat: { id: chatId }, replyChain: { id: ' ' } }],
])('sends to the inbound conversation and creates the stream there in a chat for %s', async (_name, channelData) => {
const ref = refFor('a:encrypted-conversation', 'personal');
mockSender.createStream.mockClear();
context = buildActivityContext(buildInbound({ conversationType: 'personal', conversationId: 'a:encrypted-conversation', id: 'reply-2', channelData }), { ref });
await context.send('hi');
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({ text: 'hi' }), ref);
expect(mockSender.send.mock.calls[0]).toHaveLength(2);
expect(mockSender.createStream).toHaveBeenCalledWith(ref, undefined);
});
describe('for inbound cards, invokes and message events', () => {
const buildShape = (options) => {
const conversationType = options.conversationType ?? 'personal';
const conversationId = conversationType === 'channel' ? `${channelId};messageid=100` : 'a:encrypted-conversation';
const activity = {
type: options.type,
id: options.id ?? 'f:client-id',
replyToId: options.replyToId,
value: options.value,
channelId: 'test-channel',
from: { id: 'test-user', name: 'Test User', role: 'user' },
recipient: { id: 'bot-id', name: 'Bot', role: 'bot' },
conversation: { id: conversationId, conversationType, isGroup: false },
channelData: options.channelData ?? {},
};
return { activity, ref: refFor(conversationId, conversationType) };
};
const chatChannelData = (replyChainId, extra = {}) => ({
chat: { id: chatId },
replyChain: { id: replyChainId },
...extra,
});
const fromCard = { source: { name: 'message' } };
const sendFrom = async (shape) => {
context = buildActivityContext(shape.activity, { ref: shape.ref });
await context.send('hi');
const [, sentRef, options] = mockSender.send.mock.calls[0];
return { conversationId: sentRef.conversation.id, options };
};
it.each([
['a messageBack or Action.Submit message', { type: 'message', replyToId: '105' }, fromCard],
['an adaptiveCard/action invoke', { type: 'invoke', replyToId: '105' }, {}],
['a message action invoke', { type: 'invoke', value: { messagePayload: { id: '105' } } }, {}],
['a reaction', { type: 'messageReaction', id: 'f:9f78d1f3', replyToId: '105' }, {}],
['an edit', { type: 'messageUpdate', id: '105' }, {}],
['a delete', { type: 'messageDelete', id: '105' }, {}],
])('replies in the thread for %s on a message inside a thread', async (_name, shape, extra) => {
const result = await sendFrom(buildShape({ ...shape, channelData: chatChannelData('100', extra) }));
expect(result.conversationId).toBe(chatId);
expect(result.options).toEqual({ replyChainId: '100' });
});
it.each([
['a messageBack or Action.Submit message', { type: 'message', replyToId: '100' }, fromCard],
['an adaptiveCard/action invoke', { type: 'invoke', replyToId: '100' }, {}],
['a message action invoke', { type: 'invoke', value: { messagePayload: { id: '100' } } }, {}],
['a reaction', { type: 'messageReaction', id: 'f:9f78d1f3', replyToId: '100' }, {}],
['an edit', { type: 'messageUpdate', id: '100' }, {}],
['a delete', { type: 'messageDelete', id: '100' }, {}],
])('sends to the inbound conversation for %s on a top-level message', async (_name, shape, extra) => {
const result = await sendFrom(buildShape({ ...shape, channelData: chatChannelData('100', extra) }));
expect(result.conversationId).toBe('a:encrypted-conversation');
expect(result.options).toBeUndefined();
});
it('does not place a reaction that has no replyToId, and does not use its own id instead', async () => {
const result = await sendFrom(buildShape({ type: 'messageReaction', id: '105', channelData: chatChannelData('100') }));
expect(result.conversationId).toBe('a:encrypted-conversation');
expect(result.options).toBeUndefined();
});
it('compares a message action with the message payload id, not the reply id', async () => {
const result = await sendFrom(buildShape({
type: 'invoke',
replyToId: '100',
value: { messagePayload: { id: '105' } },
channelData: chatChannelData('100'),
}));
expect(result.options).toEqual({ replyChainId: '100' });
});
it.each([
['an encrypted replyToId', '1:abc'],
['a replyToId of 0', '0'],
['an all-zero replyToId', '000'],
['a replyToId with other characters', '12a'],
['a replyToId with a prefix before the digits', 'x105'],
['an empty replyToId', ''],
])('does not place a card message or invoke with %s', async (_name, replyToId) => {
for (const type of ['message', 'invoke']) {
mockSender.send.mockClear();
const result = await sendFrom(buildShape({ type, replyToId, channelData: chatChannelData('100', type === 'message' ? fromCard : {}) }));
expect(result.conversationId).toBe('a:encrypted-conversation');
expect(result.options).toBeUndefined();
}
});
it.each([
['null', null],
['a string', 'payload'],
['an object without a message payload', { action: { type: 'Action.Execute' } }],
['an object with an empty message payload', { messagePayload: null }],
])('compares an invoke whose value is %s with its replyToId', async (_name, value) => {
const inside = await sendFrom(buildShape({ type: 'invoke', replyToId: '105', value, channelData: chatChannelData('100') }));
expect(inside.conversationId).toBe(chatId);
expect(inside.options).toEqual({ replyChainId: '100' });
mockSender.send.mockClear();
const topLevel = await sendFrom(buildShape({ type: 'invoke', replyToId: '100', value, channelData: chatChannelData('100') }));
expect(topLevel.conversationId).toBe('a:encrypted-conversation');
expect(topLevel.options).toBeUndefined();
});
it('does not place a card message without a replyToId', async () => {
const result = await sendFrom(buildShape({ type: 'message', channelData: chatChannelData('100', fromCard) }));
expect(result.options).toBeUndefined();
});
it('places an invoke that is not tied to a message when the payload has a reply chain id', async () => {
const result = await sendFrom(buildShape({ type: 'invoke', channelData: chatChannelData('100') }));
expect(result.conversationId).toBe(chatId);
expect(result.options).toEqual({ replyChainId: '100' });
});
it('does not place an invoke that is not tied to a message when the payload has no reply chain id', async () => {
const result = await sendFrom(buildShape({ type: 'invoke', channelData: { chat: { id: chatId } } }));
expect(result.options).toBeUndefined();
});
it.each(['conversationUpdate', 'installationUpdate', 'event', 'typing'])('never places a %s', async (type) => {
const result = await sendFrom(buildShape({ type, id: '105', channelData: chatChannelData('100') }));
expect(result.conversationId).toBe('a:encrypted-conversation');
expect(result.options).toBeUndefined();
});
it.each(['message', 'invoke', 'messageReaction'])('places a %s in a group chat by the shape of the payload', async (type) => {
const result = await sendFrom(buildShape({ type, id: '105', replyToId: '105', conversationType: 'groupChat', channelData: chatChannelData('100') }));
expect(result.conversationId).toBe(chatId);
expect(result.options).toEqual({ replyChainId: '100' });
});
it('does not place a message in a channel when the payload has no reply chain id', async () => {
const result = await sendFrom(buildShape({
type: 'message',
id: '105',
conversationType: 'channel',
channelData: { channel: { id: channelId } },
}));
expect(result.conversationId).toBe(`${channelId};messageid=100`);
expect(result.options).toBeUndefined();
});
it('does not place an invoke or reaction in a channel', async () => {
for (const type of ['invoke', 'messageReaction']) {
mockSender.send.mockClear();
const result = await sendFrom(buildShape({
type,
id: '105',
replyToId: '105',
conversationType: 'channel',
channelData: { channel: { id: channelId }, replyChain: { id: '100' } },
}));
expect(result.conversationId).toBe(`${channelId};messageid=100`);
expect(result.options).toBeUndefined();
}
});
it('places a card message in a channel in the reply chain of the thread', async () => {
const result = await sendFrom(buildShape({
type: 'message',
replyToId: '105',
conversationType: 'channel',
channelData: { channel: { id: channelId }, replyChain: { id: '100' }, ...fromCard },
}));
expect(result.conversationId).toBe(channelId);
expect(result.options).toEqual({ replyChainId: '100' });
});
});
describe('when placement does not apply', () => {
const replyInChain = () => buildInbound({
conversationType: 'personal',
conversationId: 'a:encrypted-conversation',
id: 'reply-2',
channelData: { chat: { id: chatId }, replyChain: { id: 'root-1' } },
});
it('does not place an update of an existing message', async () => {
const ref = refFor('a:encrypted-conversation', 'personal');
context = buildActivityContext(replyInChain(), { ref });
await context.send({ type: 'message', text: 'edited', id: 'existing-1' });
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({ id: 'existing-1' }), ref);
});
it('does not place a typing activity', async () => {
const ref = refFor('a:encrypted-conversation', 'personal');
context = buildActivityContext(replyInChain(), { ref });
await context.send({ type: 'typing' });
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({ type: 'typing' }), ref);
});
it('does not place a send to a different conversation', async () => {
const ref = refFor('a:encrypted-conversation', 'personal');
context = buildActivityContext(replyInChain(), { ref });
const otherRef = refFor('other-conversation', 'personal');
await context.send('hi', otherRef);
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({ text: 'hi' }), otherRef);
});
it('places a send that names the same conversation as the inbound', async () => {
const ref = refFor('a:encrypted-conversation', 'personal');
context = buildActivityContext(replyInChain(), { ref });
await context.send('hi', refFor('a:encrypted-conversation', 'personal'));
expect(lastCall()[2]).toEqual({ replyChainId: 'root-1' });
});
});
it('keeps the quote when replying inside a reply chain', async () => {
const ref = refFor('a:encrypted-conversation', 'personal');
context = buildActivityContext(buildInbound({
conversationType: 'personal',
conversationId: 'a:encrypted-conversation',
id: '1793257586005',
channelData: { chat: { id: chatId }, replyChain: { id: 'root-1' } },
}), { ref });
await context.reply('hi');
const [params, sentRef, options] = lastCall();
expect(params.entities).toEqual(expect.arrayContaining([expect.objectContaining({ type: 'quotedReply' })]));
expect(sentRef.conversation.id).toBe(chatId);
expect(options).toEqual({ replyChainId: 'root-1' });
});
it('keeps a message targeted when it is placed in the reply chain of a targeted inbound message', async () => {
const ref = refFor('a:encrypted-conversation', 'personal');
const inbound = buildInbound({
conversationType: 'personal',
conversationId: 'a:encrypted-conversation',
id: 'reply-2',
channelData: { chat: { id: chatId }, replyChain: { id: 'root-1' } },
}).withRecipient({ id: 'bot-id', name: 'Bot', role: 'bot' }, true);
context = buildActivityContext(inbound, { ref });
await context.send('only for you');
const [params, sentRef, options] = lastCall();
expect(params.recipient).toEqual(expect.objectContaining({ id: 'test-user', isTargeted: true }));
expect(sentRef.conversation.id).toBe(chatId);
expect(options).toEqual({ replyChainId: 'root-1' });
});
});
describe('targeted messages', () => {
it('defaults send to targeted when inbound message is targeted', async () => {
const activity = new teams_api_1.MessageActivity('Hello world')
.withFrom({ id: 'test-user', name: 'Test User', role: 'user' })
.withRecipient({ id: 'bot-id', name: 'Bot', role: 'bot' }, true)
.withChannelId('test-channel')
.withConversation({ id: 'test-conversation', conversationType: 'channel', isGroup: false })
.withId('test-activity-id');
context = buildActivityContext(activity);
await context.send('Secret message');
expect(mockSender.send).toHaveBeenCalledTimes(1);
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({
text: 'Secret message',
type: 'message',
recipient: expect.objectContaining({ id: 'test-user', name: 'Test User', role: 'user', isTargeted: true }),
}), mockRef);
});
it('does not default send to targeted for a different conversation', async () => {
const activity = new teams_api_1.MessageActivity('Hello world')
.withFrom({ id: 'test-user', name: 'Test User', role: 'user' })
.withRecipient({ id: 'bot-id', name: 'Bot', role: 'bot' }, true)
.withChannelId('test-channel')
.withConversation({ id: 'test-conversation', conversationType: 'channel', isGroup: false })
.withId('test-activity-id');
context = buildActivityContext(activity);
const otherRef = {
...mockRef,
conversation: {
...mockRef.conversation,
id: 'other-conversation',
},
};
await context.send('Secret message', otherRef);
expect(mockSender.send).toHaveBeenCalledTimes(1);
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({
text: 'Secret message',
type: 'message',
}), otherRef);
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.recipient).toBeUndefined();
expect(sentActivity.entities).toBeUndefined();
});
it('does not default send to targeted when an explicit different recipient is supplied', async () => {
const activity = new teams_api_1.MessageActivity('Hello world')
.withFrom({ id: 'test-user', name: 'Test User', role: 'user' })
.withRecipient({ id: 'bot-id', name: 'Bot', role: 'bot' }, true)
.withChannelId('test-channel')
.withConversation({ id: 'test-conversation', conversationType: 'channel', isGroup: false })
.withId('test-activity-id');
context = buildActivityContext(activity);
const otherRecipient = { id: 'other-user', name: 'Other User', role: 'user' };
await context.send(new teams_api_1.MessageActivity('Public message').withRecipient(otherRecipient));
expect(mockSender.send).toHaveBeenCalledTimes(1);
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity).toEqual(expect.objectContaining({
text: 'Public message',
type: 'message',
recipient: expect.objectContaining(otherRecipient),
}));
expect(sentActivity.recipient.isTargeted).toBeUndefined();
expect(sentActivity.entities).toBeUndefined();
});
it('sends targeted message with recipient from incoming activity', async () => {
const activity = buildIncomingMessageActivity('Hello world');
context = buildActivityContext(activity);
const targetedActivity = new teams_api_1.MessageActivity('Secret message')
.withRecipient({ id: 'test-user', name: 'Test User', role: 'user' }, true);
await context.send(targetedActivity);
expect(mockSender.send).toHaveBeenCalledTimes(1);
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({
text: 'Secret message',
type: 'message',
recipient: expect.objectContaining({ id: 'test-user', name: 'Test User', role: 'user', isTargeted: true }),
}), mockRef);
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.entities).toBeUndefined();
});
it('allows explicitly public send from a targeted inbound message', async () => {
const activity = new teams_api_1.MessageActivity('Hello world')
.withFrom({ id: 'test-user', name: 'Test User', role: 'user' })
.withRecipient({ id: 'bot-id', name: 'Bot', role: 'bot' }, true)
.withChannelId('test-channel')
.withConversation({ id: 'test-conversation', conversationType: 'channel', isGroup: false })
.withId('test-activity-id');
context = buildActivityContext(activity);
await context.send(new teams_api_1.MessageActivity('Public message').withRecipient(activity.from));
expect(mockSender.send).toHaveBeenCalledTimes(1);
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity).toEqual(expect.objectContaining({
text: 'Public message',
type: 'message',
recipient: expect.objectContaining({ id: 'test-user', name: 'Test User', role: 'user' }),
}));
expect(sentActivity.recipient.isTargeted).toBeUndefined();
expect(sentActivity.entities).toBeUndefined();
});
it('keeps an explicit quote on a targeted send when the inbound message is not targeted', async () => {
context = buildActivityContext(buildIncomingMessageActivity('Hello world'));
await context.send(new teams_api_1.MessageActivity('Secret message')
.withRecipient({ id: 'explicit-user-id', name: '', role: 'user' }, true)
.addQuote('quoted-message-1'));
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.entities).toEqual(expect.arrayContaining([expect.objectContaining({ type: 'quotedReply', quotedReply: { messageId: 'quoted-message-1' } })]));
expect(sentActivity.entities).not.toEqual(expect.arrayContaining([expect.objectContaining({ type: 'targetedMessageInfo' })]));
expect(sentActivity.text).toContain('<quoted messageId="quoted-message-1"/>');
});
it('removes the quote of the inbound message when replying to a targeted message', async () => {
const activity = new teams_api_1.MessageActivity('Hello world')
.withFrom({ id: 'test-user', name: 'Test User', role: 'user' })
.withRecipient({ id: 'bot-id', name: 'Bot', role: 'bot' }, true)
.withChannelId('test-channel')
.withConversation({ id: 'test-conversation', conversationType: 'channel', isGroup: false })
.withId('1793257586005');
context = buildActivityContext(activity);
await context.reply('Here is your agenda');
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.entities).not.toEqual(expect.arrayContaining([expect.objectContaining({ type: 'quotedReply' })]));
expect(sentActivity.text).not.toContain('<quoted messageId="1793257586005"/>');
expect(sentActivity.entities).toEqual(expect.arrayContaining([expect.objectContaining({ type: 'targetedMessageInfo', messageId: '1793257586005' })]));
});
it('sends targeted message with explicit recipient id', async () => {
const activity = buildIncomingMessageActivity('Hello world');
context = buildActivityContext(activity);
const targetedActivity = new teams_api_1.MessageActivity('Secret message')
.withRecipient({ id: 'explicit-user-id', name: '', role: 'user' }, true);
await context.send(targetedActivity);
expect(mockSender.send).toHaveBeenCalledTimes(1);
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({
text: 'Secret message',
type: 'message',
recipient: expect.objectContaining({ id: 'explicit-user-id', name: '', role: 'user', isTargeted: true }),
}), mockRef);
});
it('does not set recipient for targeted message updates', async () => {
const activity = buildIncomingMessageActivity('Hello world');
context = buildActivityContext(activity);
const updateActivity = new teams_api_1.MessageActivity('Updated message')
.withId('existing-activity-id')
.withRecipient({ id: 'user-1', name: '', role: 'user' }, true);
await context.send(updateActivity);
expect(mockSender.send).toHaveBeenCalledTimes(1);
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.id).toBe('existing-activity-id');
expect(sentActivity.recipient.isTargeted).toBe(true);
});
});
describe('prompt preview', () => {
it('auto-populates targetedMessageInfo entity when incoming activity is targeted', async () => {
const activity = new teams_api_1.MessageActivity('Hello world')
.withFrom({ id: 'test-user', name: 'Test User', role: 'user' })
.withRecipient({ id: 'bot-id', name: 'Bot', role: 'bot' }, true)
.withChannelId('test-channel')
.withConversation({ id: 'test-conversation', conversationType: 'channel', isGroup: false })
.withId('1772129782775');
context = buildActivityContext(activity);
await context.send('Here is your agenda');
expect(mockSender.send).toHaveBeenCalledTimes(1);
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({
text: 'Here is your agenda',
type: 'message',
entities: expect.arrayContaining([
expect.objectContaining({
type: 'targetedMessageInfo',
messageId: '1772129782775',
}),
]),
}), mockRef);
});
it('does not auto-populate targetedMessageInfo when incoming activity is not targeted', async () => {
const activity = buildIncomingMessageActivity('Hello world');
context = buildActivityContext(activity);
await context.send('Response');
expect(mockSender.send).toHaveBeenCalledTimes(1);
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.entities).toBeUndefined();
});
it('does not overwrite existing targetedMessageInfo entity', async () => {
const activity = new teams_api_1.MessageActivity('Hello world')
.withFrom({ id: 'test-user', name: 'Test User', role: 'user' })
.withRecipient({ id: 'bot-id', name: 'Bot', role: 'bot' }, true)
.withChannelId('test-channel')
.withConversation({ id: 'test-conversation', conversationType: 'channel', isGroup: false })
.withId('1772129782775');
context = buildActivityContext(activity);
const outgoing = new teams_api_1.MessageActivity('Response')
.addTargetedMessageInfo('custom-message-id');
await context.send(outgoing);
expect(mockSender.send).toHaveBeenCalledTimes(1);
const sentActivity = mockSender.send.mock.calls[0][0];
const targetedEntities = sentActivity.entities.filter((e) => e.type === 'targetedMessageInfo');
expect(targetedEntities).toHaveLength(1);
expect(targetedEntities[0].messageId).toBe('custom-message-id');
});
it('auto-populates targetedMessageInfo on reply to targeted message', async () => {
const activity = new teams_api_1.MessageActivity('Hello world')
.withFrom({ id: 'test-user', name: 'Test User', role: 'user' })
.withRecipient({ id: 'bot-id', name: 'Bot', role: 'bot' }, true)
.withChannelId('test-channel')
.withConversation({ id: 'test-conversation', conversationType: 'channel', isGroup: false })
.withId('1772129782775');
context = buildActivityContext(activity);
await context.reply('Here is your agenda');
expect(mockSender.send).toHaveBeenCalledTimes(1);
expect(mockSender.send).toHaveBeenCalledWith(expect.objectContaining({
type: 'message',
entities: expect.arrayContaining([
expect.objectContaining({
type: 'targetedMessageInfo',
messageId: '1772129782775',
}),
]),
}), mockRef);
});
});
});
describe('signin/signout flow', () => {
beforeEach(() => {
context = buildActivityContext(buildIncomingMessageActivity('Test message'));
});
it('returns existing token if available', async () => {
const expectedToken = 'test-token';
mockApiClient.users.getToken.mockResolvedValueOnce({
token: expectedToken,
connectionName: 'test-connection',
channelId: 'test-channel',
expiration: new Date(Date.now() + 1000 * 60 * 60).getTime().toString(),
});
const result = await context.signin();
expect(result).toBe(expectedToken);
expect(mockApiClient.users.getToken).toHaveBeenCalledWith({
channelId: 'test-channel',
userId: 'test-user',
connectionName: 'test-connection',
});
});
it('creates oauth card for new signin in 1:1 chat', async () => {
context = new activity_1.ActivityContext({
...context,
activity: {
...buildIncomingMessageActivity('Test message'),
conversation: {
id: 'personal-conv',
conversationType: 'personal',
isGroup: false,
},
},
activitySender: mockSender,
});
mockApiClient.users.getToken.mockRejectedValueOnce(missingTokenError());
const mockResource = {
tokenExchangeResource: {
uri: 'my-token-exhcange-resource-uri',
},
tokenPostResource: {
sasUrl: 'my-token-post-resource-sas-url',
},
signInLink: 'https://login.url',
};
mockApiClient.bots.signIn.getResource.mockResolvedValueOnce(mockResource);
await context.signin();
// No 1:1 fallback conversation is created.
expect(mockApiClient.conversations.create).not.toHaveBeenCalled();
const sentActivity = mockSender.send.mock.calls[0][0];
// 1:1 sign-in cards are not targeted and keep the token exchange resource (SSO possible).
expect(sentActivity.recipient.isTargeted).toBeUndefined();
expect(sentActivity.attachments[0].content.tokenExchangeResource).toEqual({
uri: 'my-token-exhcange-resource-uri',
});
});
it('records pending attribution when deprecated signin sends a card', async () => {
const onOAuthSignInInitiated = jest.fn();
context = buildActivityContext(buildIncomingMessageActivity('Test message'), { onOAuthSignInInitiated });
mockApiClient.users.getToken.mockRejectedValueOnce(missingTokenError());
mockApiClient.bots.signIn.getResource.mockResolvedValueOnce({
tokenExchangeResource: {
uri: 'my-token-exchange-resource-uri',
},
tokenPostResource: {},
signInLink: 'https://login.url',
});
await context.signin({ connectionName: 'github' });
expect(onOAuthSignInInitiated).toHaveBeenCalledWith(expect.objectContaining({
activity: expect.objectContaining({
conversation: expect.objectContaining({ id: 'test-conversation' }),
}),
}), 'github', false);
});
it('rejects an undeclared connection before starting deprecated signin', async () => {
const error = new Error('No OAuth flow is registered for connection "github".');
const validateOAuthConnection = jest.fn(() => {
throw error;
});
context = buildActivityContext(buildIncomingMessageActivity('Test message'), { validateOAuthConnection });
await expect(context.signin({ connectionName: 'github' })).rejects.toBe(error);
expect(validateOAuthConnection).toHaveBeenCalledWith('github', true);
expect(mockApiClient.users.getToken).not.toHaveBeenCalled();
expect(mockApiClient.bots.signIn.getResource).not.toHaveBeenCalled();
expect(mockSender.send).not.toHaveBeenCalled();
});
it('sends a targeted oauth card in a group chat without creating a 1:1', async () => {
context = new activity_1.ActivityContext({
...context,
activity: {
...buildIncomingMessageActivity('Test message'),
conversation: {
id: 'group-conv',
conversationType: 'groupChat',
isGroup: true,
},
},
activitySender: mockSender,
});
mockApiClient.users.getToken.mockRejectedValueOnce(missingTokenError());
const mockResource = {
tokenExchangeResource: {
uri: 'my-token-exhcange-resource-uri',
},
tokenPostResource: {},
signInLink: 'https://login.url',
};
mockApiClient.bots.signIn.getResource.mockResolvedValueOnce(mockResource);
await context.signin();
// No 1:1 fallback; the card is sent directly in the group chat, targeted to the user.
expect(mockApiClient.conversations.create).not.toHaveBeenCalled();
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.recipient.isTargeted).toBe(true);
// SSO token exchange remains available in group chats.
expect(sentActivity.attachments[0].content.tokenExchangeResource).toEqual({
uri: 'my-token-exhcange-resource-uri',
});
});
it('sends a targeted oauth card and omits token exchange in a channel', async () => {
context = new activity_1.ActivityContext({
...context,
activity: {
...buildIncomingMessageActivity('Test message'),
conversation: {
id: 'channel-conv',
conversationType: 'channel',
isGroup: true,
},
},
activitySender: mockSender,
});
mockApiClient.users.getToken.mockRejectedValueOnce(missingTokenError());
const mockResource = {
tokenExchangeResource: {
uri: 'my-token-exhcange-resource-uri',
},
tokenPostResource: {},
signInLink: 'https://login.url',
};
mockApiClient.bots.signIn.getResource.mockResolvedValueOnce(mockResource);
await context.signin();
// No 1:1 fallback; card sent directly in the channel, targeted to the user.
expect(mockApiClient.conversations.create).not.toHaveBeenCalled();
const sentActivity = mockSender.send.mock.calls[0][0];
expect(sentActivity.recipient.isTargeted).toBe(true);
// Channels cannot do silent SSO, so the token exchange resource is omitted.
expect(sentActivity.attachments[0].content.tokenExchangeResource).toBeUndefined();
});
it('passes the channel-filtered token exchange resource to overrideSignInActivity', async () => {
context = new activity_1.ActivityContext({
...context,
activity: {
...buildIncomingMessageActivity('Test message'),
conversation: {
id: 'channel-conv',
conversationType: 'channel',
isGroup: true,
},
},
activitySender: mockSender,
});
mockApiClient.users.getToken.mockRejectedValueOnce(missingTokenError());
const mockResource = {
tokenExchangeResource: {
uri: 'my-token-exhcange-resource-uri',
},
tokenPostResource: { sasUrl: 'sas' },
signInLink: 'https://login.url',
};
mockApiClient.bots.signIn.getResource.mockResolvedValueOnce(mockResource);
const overrideSignInActivity = jest
.fn()
.mockReturnValue({ type: 'message', text: 'custom sign-in' });
await context.signin({ overrideSignInActivity });
// In channels the override callback receives no token exchange resource, so a
// custom override can't trigger a silent SSO exchange Teams can't complete.
expect(overrideSignInActivity).toHaveBeenCalledWith(undefined, mockResource.tokenPostResource, mockResource.signInLink);
});
it('propagates unexpected token lookup failures', async () => {
const error = new Error('token service unavailable');
mockApiClient.users.getToken.mockRejectedValueOnce(error);
await expect(context.signin()).rejects.toBe(error);
expect(mockApiClient.bots.signIn.getResource).not.toHaveBeenCalled();
});
it('forwards signout request to api client', async () => {
const validateOAuthConnection = jest.fn();
context = buildActivityContext(buildIncomingMessageActivity('Test message'), { validateOAuthConnection });
await context.signout();
expect(validateOAuthConnection).toHaveBeenCalledWith('test-connection', false);
expect(mockApiClient.users.signOut).toHaveBeenCalledWith({
channelId: 'test-channel',
userId: 'test-user',
connectionName: 'test-connection',
});
});
it('identifies an omitted signin connection for registered-flow validation', async () => {
const error = new Error('OAuth connection name is required when OAuth flows are registered.');
const validateOAuthConnection = jest.fn((_connectionName, connectionNameProvided) => {
if (!connectionNameProvided) {
throw error;
}
});
context = buildActivityContext(buildIncomingMessageActivity('Test message'), { validateOAuthConnection });
await expect(context.signin()).rejects.toBe(error);
expect(validateOAuthConnection).toHaveBeenCalledWith('test-connection', false);
expect(mockApiClient.users.getToken).not.toHaveBeenCalled();
});
});
describe('constructor — prototype method shadowing', () => {
it('drops context properties that would shadow prototype methods', () => {
const activity = buildIncomingMessageActivity('Hello world');
const malicious = {
send: jest.fn(),
reply: jest.fn(),
quote: jest.fn(),
signin: jest.fn(),
signout: jest.fn(),
};
const ctx = new activity_1.ActivityContext({
appId: 'test-app',
activity,
ref: mockRef,
log: mockLogger,
api: mockApiClient,
appGraph: {},
userGraph: {},
storage: mockStorage,
connectionName: 'test-connection',
next: jest.fn(),
activitySender: mockSender,
...malicious,
});
for (const name of ['send', 'reply', 'quote', 'signin', 'signout']) {
expect(Object.prototype.hasOwnProperty.call(ctx, name)).toBe(false);
expect(ctx[name]).toBe(activity_1.ActivityContext.prototype[name]);
}
});
it('still allows new properties from extra context', () => {
const activity = buildIncomingMessageActivity('Hello world');
const ctx = new activity_1.ActivityContext({
appId: 'test-app',
activity,
ref: mockRef,
log: mockLogger,
api: mockApiClient,
appGraph: {},
userGraph: {},
storage: mockStorage,
connectionName: 'test-connection',
next: jest.fn(),
activitySender: mockSender,
customField: 'still here',
});
expect(ctx.customField).toBe('still here');
});
it('routes ctx.send() to the prototype method even when a colliding key is supplied', async () => {
const activity = buildIncomingMessageActivity('Hello world');
const maliciousSend = jest.fn();
const ctx = new activity_1.ActivityContext({
appId: 'test-app',
activity,
ref: mockRef,
log: mockLogger,
api: mockApiClient,
appGraph: {},
userGraph: {},
storage: mockStorage,
connectionName: 'test-connection',
next: jest.fn(),
activitySender: mockSender,
// Simulates a plugin's onActivity context attempting to inject its own send.
send: maliciousSend,
});
await ctx.send({ type: 'message', text: 'real send' });
expect(maliciousSend).not.toHaveBeenCalled();
expect(mockSender.send).toHaveBeenCalledTimes(1);
});
});
describe('files accessor', () => {
// `ctx.files` must receive the app's HTTP client so file downloads inherit its
// User-Agent, middleware, and user-supplied configuration. The download path
// falls back to a bare global `fetch` when no client is present, so dropping
// it here would silently bypass the SDK's outbound pipeline instead of
// failing loudly. This asserts the hand-off at the context boundary.
it('passes the app HTTP client through to ctx.files', async () => {
const seen = [];
const client = new teams_common_1.Client();
client.use({
async invoke(mwContext, next) {
mwContext.config.adapter = async (config) => {
seen.push(String(config.url));
return {
status: 200,
statusText: '',
headers: {},
config,
data: stream_1.Readable.from([Buffer.from('bytes')]),
};
};
return next();
},
});
const activity = teams_api_1.MessageActivity.from({
type: 'message',
conversation: { id: 'test-conversation', conversationType: 'personal' },
attachments: [
{
contentType: teams_api_1.FILE_DOWNLOAD_INFO_CONTENT_TYPE,
name: 'report.pdf',
content: { downloadUrl: 'https://download.example/report.pdf?tempauth=abc' },
},
],
});
const ctx = new activity_1.ActivityContext({
appId: 'test-app',
activity,
ref: mockRef,
log: mockLogger,
api: mockApiClient,
client,
appGraph: {},
userGraph: {},
storage: mockStorage,
connectionName: 'test-connection',
next: jest.fn(),
activitySender: mockSender,
});
const file = await ctx.files.first();
expect(file).toBeDefined();
await file.download();
expect(seen).toEqual(['https://download.example/report.pdf?tempauth=abc']);
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aXZpdHkudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb250ZXh0cy9hY3Rpdml0eS50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbUNBQWtDO0FBRWxDLGlDQUFtQztBQUduQyxvREFROEI7QUFDOUIsMERBQWtGO0FBSWxGLHlDQUdvQjtBQUVwQixNQUFNLGlCQUFpQixHQUFHLEdBQUcsRUFBRSxDQUM3QixJQUFJLGtCQUFVLENBQUMsVUFBVSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFO0lBQ3RELE1BQU0sRUFBRSxHQUFHO0lBQ1gsVUFBVSxFQUFFLFdBQVc7SUFDdkIsT0FBTyxFQUFFLEVBQUU7SUFDWCxNQUFNLEVBQUUsRUFBVztJQUNuQixJQUFJLEVBQUUsRUFBRTtDQUNULENBQUMsQ0FBQztBQUVMLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRSxHQUFHLEVBQUU7SUFDL0IsSUFBSSxVQUF3RCxDQUFDO0lBQzdELElBQUksYUFBc0MsQ0FBQztJQUMzQyxJQUFJLFVBQW1CLENBQUM7SUFDeEIsSUFBSSxXQUFtQyxDQUFDO0lBQ3hDLElBQUksT0FBOEIsQ0FBQztJQUNuQyxJQUFJLE9BQXdCLENBQUM7SUFFN0IsVUFBVSxDQUFDLEdBQUcsRUFBRTtRQUNkLFVBQVUsR0FBRztZQUNYLFlBQVksRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDO1lBQzdELElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1NBQ2hCLENBQUM7UUFFRixhQUFhLEdBQUc7WUFDZCxLQUFLLEVBQUU7Z0JBQ0wsUUFBUSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7Z0JBQ25CLE9BQU8sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO2FBQ25CO1lBQ0QsYUFBYSxFQUFFO2dCQUNiLE1BQU0sRUFBRSxJ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