Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions packages/apps/src/router/router.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,89 @@ describe('Router', () => {
} as any)).toHaveLength(1);
});

it('should select dialog open sub-routes by dialog_id', () => {
const router = new Router();
const handler = jest.fn();

router.on('invoke', handler);
router.on('dialog.open', handler);
router.on('dialog.open.simple_form' as any, handler);
Comment thread
heyitsaamir marked this conversation as resolved.
Outdated

// Matches invoke + dialog.open + dialog.open.simple_form
expect(router.select({
type: 'invoke',
name: 'task/fetch',
value: { data: { dialog_id: 'simple_form' } }
} as any)).toHaveLength(3);

// Matches invoke + dialog.open but NOT dialog.open.simple_form
expect(router.select({
type: 'invoke',
name: 'task/fetch',
value: { data: { dialog_id: 'other_form' } }
} as any)).toHaveLength(2);

// Matches invoke + dialog.open (no data at all)
expect(router.select({
type: 'invoke',
name: 'task/fetch',
value: {}
} as any)).toHaveLength(2);
});

it('should select dialog submit sub-routes by action', () => {
const router = new Router();
const handler = jest.fn();

router.on('invoke', handler);
router.on('dialog.submit', handler);
router.on('dialog.submit.submit_form' as any, handler);
Comment thread
heyitsaamir marked this conversation as resolved.
Outdated

// Matches invoke + dialog.submit + dialog.submit.submit_form
expect(router.select({
type: 'invoke',
name: 'task/submit',
value: { data: { action: 'submit_form' } }
} as any)).toHaveLength(3);

// Matches invoke + dialog.submit but NOT dialog.submit.submit_form
expect(router.select({
type: 'invoke',
name: 'task/submit',
value: { data: { action: 'other_action' } }
} as any)).toHaveLength(2);
});

it('should select card action sub-routes by action', () => {
const router = new Router();
const handler = jest.fn();

router.on('invoke', handler);
router.on('card.action', handler);
router.on('card.action.save_profile' as any, handler);
Comment thread
heyitsaamir marked this conversation as resolved.
Outdated

// Matches invoke + card.action + card.action.save_profile
expect(router.select({
type: 'invoke',
name: 'adaptiveCard/action',
value: { action: { type: 'Action.Execute', data: { action: 'save_profile' } } }
} as any)).toHaveLength(3);

// Matches invoke + card.action but NOT card.action.save_profile
expect(router.select({
type: 'invoke',
name: 'adaptiveCard/action',
value: { action: { type: 'Action.Execute', data: { action: 'other_action' } } }
} as any)).toHaveLength(2);

// Does not match sub-route when no action field in data
expect(router.select({
type: 'invoke',
name: 'adaptiveCard/action',
value: { action: { type: 'Action.Execute', data: { name: 'test' } } }
} as any)).toHaveLength(2);
});

it('should select message submit action routes', () => {
const router = new Router();
const handler = jest.fn();
Expand Down
24 changes: 24 additions & 0 deletions packages/apps/src/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,30 @@ export class Router<TExtraCtx extends Record<string, any> = Record<string, any>>
if (activity.name === 'message/submitAction') {
return event === `message.submit.${activity.value.actionName}`;
}

// dialog.open.{dialogId} → matches value.data.dialog_id
if (activity.name === 'task/fetch') {
const prefix = 'dialog.open.';
if (typeof event === 'string' && (event as string).startsWith(prefix)) {
return activity.value?.data?.dialog_id === (event as string).slice(prefix.length);
}
}

// dialog.submit.{action} → matches value.data.action
if (activity.name === 'task/submit') {
const prefix = 'dialog.submit.';
if (typeof event === 'string' && (event as string).startsWith(prefix)) {
return activity.value?.data?.action === (event as string).slice(prefix.length);
}
}

// card.action.{action} → matches value.action.data.action
if (activity.name === 'adaptiveCard/action') {
const prefix = 'card.action.';
if (typeof event === 'string' && (event as string).startsWith(prefix)) {
return activity.value?.action?.data?.action === (event as string).slice(prefix.length);
Comment thread
heyitsaamir marked this conversation as resolved.
Outdated
}
}
}

// custom routes
Expand Down
11 changes: 11 additions & 0 deletions packages/apps/src/routes/invoke/card-action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IAdaptiveCardActionInvokeActivity, InvokeResponse } from '@microsoft/teams.api';

import { IActivityContext } from '../../contexts';
import { RouteHandler } from '../../types';

export type CardActionSubRoutes<TExtraCtx extends Record<string, any> = Record<string, any>> = {
[K in `card.action.${string}`]?: RouteHandler<
IActivityContext<IAdaptiveCardActionInvokeActivity, TExtraCtx>,
InvokeResponse<'adaptiveCard/action'> | InvokeResponse<'adaptiveCard/action'>['body']
>;
};
11 changes: 11 additions & 0 deletions packages/apps/src/routes/invoke/dialog-open.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ITaskFetchInvokeActivity, InvokeResponse } from '@microsoft/teams.api';

import { IActivityContext } from '../../contexts';
import { RouteHandler } from '../../types';

export type DialogOpenSubRoutes<TExtraCtx extends Record<string, any> = Record<string, any>> = {
[K in `dialog.open.${string}`]?: RouteHandler<
IActivityContext<ITaskFetchInvokeActivity, TExtraCtx>,
InvokeResponse<'task/fetch'> | InvokeResponse<'task/fetch'>['body']
>;
};
11 changes: 11 additions & 0 deletions packages/apps/src/routes/invoke/dialog-submit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ITaskSubmitInvokeActivity, InvokeResponse } from '@microsoft/teams.api';

import { IActivityContext } from '../../contexts';
import { RouteHandler } from '../../types';

export type DialogSubmitSubRoutes<TExtraCtx extends Record<string, any> = Record<string, any>> = {
[K in `dialog.submit.${string}`]?: RouteHandler<
IActivityContext<ITaskSubmitInvokeActivity, TExtraCtx>,
InvokeResponse<'task/submit'> | InvokeResponse<'task/submit'>['body']
>;
};
11 changes: 10 additions & 1 deletion packages/apps/src/routes/invoke/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { InvokeActivity, InvokeResponse } from '@microsoft/teams.api';
import { IActivityContext } from '../../contexts';
import { RouteHandler } from '../../types';

import { CardActionSubRoutes } from './card-action';
Comment thread
heyitsaamir marked this conversation as resolved.
import { DialogOpenSubRoutes } from './dialog-open';
import { DialogSubmitSubRoutes } from './dialog-submit';
import { FileConsentActivityRoutes } from './file-consent';
import { MessageExtensionSubmitActivityRoutes } from './message-extension-submit';
import { MessageSubmitActivityRoutes } from './message-submit';
Expand All @@ -14,7 +17,10 @@ export type InvokeActivityRoutes<TExtraCtx extends Record<string, any> = Record<
>;
} & FileConsentActivityRoutes &
MessageExtensionSubmitActivityRoutes &
MessageSubmitActivityRoutes;
MessageSubmitActivityRoutes &
DialogOpenSubRoutes<TExtraCtx> &
DialogSubmitSubRoutes<TExtraCtx> &
CardActionSubRoutes<TExtraCtx>;

type InvokeAliases = {
'config/fetch': 'config.open';
Expand Down Expand Up @@ -68,6 +74,9 @@ export const INVOKE_ALIASES: InvokeAliases = {
'adaptiveCard/action': 'card.action',
};

export * from './card-action';
export * from './dialog-open';
export * from './dialog-submit';
export * from './file-consent';
export * from './message-extension-submit';
export * from './message-submit';
Expand Down
Loading