Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds view_closed support #276

Merged
merged 14 commits into from
Oct 7, 2019
27 changes: 13 additions & 14 deletions src/App.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,20 +437,19 @@ describe('App', () => {
respond: noop,
ack: noop,
},
// TODO: https://github.com/slackapi/bolt/issues/263
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we also can verify if the condition works by having the following lines in the test suite.

// add a new routing definition
app.view({callback_id: 'view_callback_id', type: 'view_closed'}, ({ }) => { viewFn(); })

// modify assert.equal(viewFn.callCount, 1); as below:
assert.equal(viewFn.callCount, 2);

// {
// body: {
// type: 'view_closed',
// channel: {},
// user: {},
// team: {},
// view: {
// callback_id: 'view_callback_id',
// }
// },
// respond: noop,
// ack: noop,
// },
{
body: {
type: 'view_closed',
channel: {},
user: {},
team: {},
view: {
callback_id: 'view_callback_id',
}
},
respond: noop,
ack: noop,
},
];
}

Expand Down
46 changes: 37 additions & 9 deletions src/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import {
onlyEvents,
matchEventType,
matchMessage,
onlyViewSubmits,
matchCallbackId,
onlyViewActions,
} from './middleware/builtin';
import { processMiddleware } from './middleware/process';
import { ConversationStore, conversationContext, MemoryStore } from './conversation-store';
Expand Down Expand Up @@ -90,6 +89,11 @@ export interface ActionConstraints {
callback_id?: string | RegExp;
}

export interface ViewConstraints {
callback_id?: string | RegExp;
type?: 'view_closed' | 'view_submission';
}

export interface ErrorHandler {
(error: CodedError): void;
}
Expand Down Expand Up @@ -312,9 +316,33 @@ export default class App {
);
}

public view(callbackId: string | RegExp, ...listeners: Middleware<SlackViewMiddlewareArgs>[]): void {
public view(
callbackId: string | RegExp,
...listeners: Middleware<SlackViewMiddlewareArgs>[]
): void;
public view(
constraints: ViewConstraints,
...listeners: Middleware<SlackViewMiddlewareArgs>[]
): void;
public view(
callbackIdOrConstraints: string | RegExp | ViewConstraints,
...listeners: Middleware<SlackViewMiddlewareArgs>[]): void {
const constraints: ViewConstraints =
(typeof callbackIdOrConstraints === 'string' || util.types.isRegExp(callbackIdOrConstraints)) ?
{ callback_id: callbackIdOrConstraints, type: 'view_submission' } : callbackIdOrConstraints;

// Fail early if the constraints contain invalid keys
const unknownConstraintKeys = Object.keys(constraints)
.filter(k => (k !== 'callback_id' && k !== 'type'));
aoberoi marked this conversation as resolved.
Show resolved Hide resolved
if (unknownConstraintKeys.length > 0) {
this.logger.error(
`View listener cannot be attached using unknown constraint keys: ${unknownConstraintKeys.join(', ')}`,
);
return;
}

this.listeners.push(
[onlyViewSubmits, matchCallbackId(callbackId), ...listeners] as Middleware<AnyMiddlewareArgs>[],
[onlyViewActions, matchConstraints(constraints), ...listeners] as Middleware<AnyMiddlewareArgs>[],
);
}

Expand Down Expand Up @@ -378,7 +406,7 @@ export default class App {
payload:
(type === IncomingEventType.Event) ?
(bodyArg as SlackEventMiddlewareArgs['body']).event :
(type === IncomingEventType.ViewSubmitAction) ?
(type === IncomingEventType.ViewAction) ?
(bodyArg as SlackViewMiddlewareArgs['body']).view :
(type === IncomingEventType.Action &&
isBlockActionOrInteractiveMessageBody(bodyArg as SlackActionMiddlewareArgs['body'])) ?
Expand Down Expand Up @@ -406,7 +434,7 @@ export default class App {
} else if (type === IncomingEventType.Options) {
const optionListenerArgs = listenerArgs as SlackOptionsMiddlewareArgs<OptionsSource>;
optionListenerArgs.options = optionListenerArgs.payload;
} else if (type === IncomingEventType.ViewSubmitAction) {
} else if (type === IncomingEventType.ViewAction) {
const viewListenerArgs = listenerArgs as SlackViewMiddlewareArgs;
viewListenerArgs.view = viewListenerArgs.payload;
}
Expand Down Expand Up @@ -485,11 +513,11 @@ function buildSource(
const source: AuthorizeSourceData = {
teamId:
((type === IncomingEventType.Event || type === IncomingEventType.Command) ? (body as (SlackEventMiddlewareArgs | SlackCommandMiddlewareArgs)['body']).team_id as string :
(type === IncomingEventType.Action || type === IncomingEventType.Options || type === IncomingEventType.ViewSubmitAction) ? (body as (SlackActionMiddlewareArgs | SlackOptionsMiddlewareArgs | SlackViewMiddlewareArgs)['body']).team.id as string :
(type === IncomingEventType.Action || type === IncomingEventType.Options || type === IncomingEventType.ViewAction) ? (body as (SlackActionMiddlewareArgs | SlackOptionsMiddlewareArgs | SlackViewMiddlewareArgs)['body']).team.id as string :
assertNever(type)),
enterpriseId:
((type === IncomingEventType.Event || type === IncomingEventType.Command) ? (body as (SlackEventMiddlewareArgs | SlackCommandMiddlewareArgs)['body']).enterprise_id as string :
(type === IncomingEventType.Action || type === IncomingEventType.Options || type === IncomingEventType.ViewSubmitAction) ? (body as (SlackActionMiddlewareArgs | SlackOptionsMiddlewareArgs | SlackViewMiddlewareArgs)['body']).team.enterprise_id as string :
(type === IncomingEventType.Action || type === IncomingEventType.Options || type === IncomingEventType.ViewAction) ? (body as (SlackActionMiddlewareArgs | SlackOptionsMiddlewareArgs | SlackViewMiddlewareArgs)['body']).team.enterprise_id as string :
undefined),
userId:
((type === IncomingEventType.Event) ?
Expand All @@ -498,7 +526,7 @@ function buildSource(
((body as SlackEventMiddlewareArgs['body']).event.channel !== undefined && (body as SlackEventMiddlewareArgs['body']).event.channel.creator !== undefined) ? (body as SlackEventMiddlewareArgs['body']).event.channel.creator as string :
((body as SlackEventMiddlewareArgs['body']).event.subteam !== undefined && (body as SlackEventMiddlewareArgs['body']).event.subteam.created_by !== undefined) ? (body as SlackEventMiddlewareArgs['body']).event.subteam.created_by as string :
undefined) :
(type === IncomingEventType.Action || type === IncomingEventType.Options || type === IncomingEventType.ViewSubmitAction) ? (body as (SlackActionMiddlewareArgs | SlackOptionsMiddlewareArgs | SlackViewMiddlewareArgs)['body']).user.id as string :
(type === IncomingEventType.Action || type === IncomingEventType.Options || type === IncomingEventType.ViewAction) ? (body as (SlackActionMiddlewareArgs | SlackOptionsMiddlewareArgs | SlackViewMiddlewareArgs)['body']).user.id as string :
(type === IncomingEventType.Command) ? (body as SlackCommandMiddlewareArgs['body']).user_id as string :
undefined),
conversationId: channelId,
Expand Down
30 changes: 30 additions & 0 deletions src/helpers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ describe('getTypeAndConversation()', () => {
});
});

describe('view types', () => {
// Arrange
const dummyViewBodies = createFakeViews();

dummyViewBodies.forEach((viewBody) => {
it(`should find Action type for ${viewBody.type}`, () => {
// Act
const typeAndConversation = getTypeAndConversation(viewBody);

// Assert
assert(typeAndConversation.type === IncomingEventType.ViewAction);
});
});
});

describe('invalid events', () => {
// Arrange
const fakeEventBody = {
Expand Down Expand Up @@ -150,3 +165,18 @@ function createFakeOptions(conversationId: string): any[] {
},
];
}

function createFakeViews(): any[] {
return [
// Body for a view_submission event
{
type: 'view_submission',
view: { id: 'V123' },
},
// Body for a view_closed event
{
type: 'view_closed',
view: { id: 'V456' },
},
];
}
6 changes: 3 additions & 3 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export enum IncomingEventType {
Action,
Command,
Options,
ViewSubmitAction,
ViewAction,
}

/**
Expand Down Expand Up @@ -54,9 +54,9 @@ export function getTypeAndConversation(body: any): { type?: IncomingEventType, c
conversationId: actionBody.channel !== undefined ? actionBody.channel.id : undefined,
};
}
if (body.type === 'view_submission') {
if (body.type === 'view_submission' || body.type === 'view_closed') {
return {
type: IncomingEventType.ViewSubmitAction,
type: IncomingEventType.ViewAction,
};
}
return {};
Expand Down
Loading