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

feat: zowe bot should have a callable API to send DMs #17

Open
wants to merge 20 commits into
base: user/markackert/tls-options
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e7dfe6b
add dm capabilities for all supported chat tools
MarkAckert Feb 15, 2023
de15319
chore: api; add sendDirectMessage to bot
MarkAckert Feb 15, 2023
ad107d2
stash wip test
MarkAckert Feb 24, 2023
2e85dc0
chore: write mock tests, minor tslint/jest config fixes
MarkAckert Mar 1, 2023
8f67911
Merge branch 'user/markackert/tls-options' into user/markackert/send-dms
MarkAckert Mar 16, 2023
a5623bb
feat: sendDirectMessage for all 3 chat apps
MarkAckert Apr 4, 2023
65546dc
chore: fix broken test, consistent return type for sendDm
MarkAckert Apr 5, 2023
c222db3
chore: address sonar duplication
MarkAckert Apr 5, 2023
f3c6983
chore: add some msteams unit tests
MarkAckert Apr 10, 2023
6b9d7e3
chore: exclude __tests__ folder from coverage
MarkAckert Apr 10, 2023
d244da5
chore: add more tests, fix slack dm bug
MarkAckert Apr 17, 2023
6dc5124
Merge branch 'user/markackert/tls-options' into user/markackert/send-dms
MarkAckert Apr 17, 2023
7683998
chore: disable apiCalls in slack unit tests
MarkAckert Apr 18, 2023
ea60999
chore: restore all mocks after tests as precaution
MarkAckert Apr 18, 2023
d2ef1be
chore: more test cases, fix bug in object assign
MarkAckert Apr 18, 2023
564cde8
Merge branch 'user/markackert/tls-options' into user/markackert/send-dms
MarkAckert Apr 19, 2023
3f5b0dd
chore: init msteams sendDirect unit tests
MarkAckert Apr 20, 2023
e931b4a
chore: test case coverage
MarkAckert Apr 20, 2023
a89bd2c
chore: cover some more conditions/lines
MarkAckert Apr 20, 2023
7727cf4
chore: add thrown errors
MarkAckert Apr 20, 2023
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
7 changes: 7 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,12 @@ module.exports = {
sourceType: 'module',
},
},
{
files: [' *.test.ts', '*.test.tsx', 'gulpfile.js', 'jest.config.ts'],
rules: {
'node/no-unpublished-import': 'off',
'@typescript-eslint/ban-ts-comment': 'warn',
},
},
],
};
22 changes: 11 additions & 11 deletions __tests__/__integration__/mock.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*/
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*/

describe('jest executes integration test', () => {
it('assert 1=1', async () => {
expect(1).toBe(1);
});
it('assert 1=1', async () => {
expect(1).toBe(1);
});
});
53 changes: 53 additions & 0 deletions __tests__/common/mocks/MockCommonBot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*/

import { CommonBot } from '../../../src/CommonBot';
import { IChatToolType, IBotOption } from '../../../src/types';

export class MockCommonBot {
public static MSTEAMS_BOT: CommonBot = (() => {
const bot: CommonBot = jest.createMockFromModule('../../../src/CommonBot');
bot.getOption = () => {
return {
chatTool: {
type: IChatToolType.MSTEAMS,
option: {
botId: 'dummybot',
},
},
} as IBotOption;
};
return bot;
})();

public static MATTERMOST_BOT: CommonBot = (() => {
const bot: CommonBot = jest.createMockFromModule('../../../src/CommonBot');
bot.getOption = () => {
return {
chatTool: {
type: IChatToolType.MATTERMOST,
},
} as IBotOption;
};
return bot;
})();

public static SLACK_BOT: CommonBot = (() => {
const bot: CommonBot = jest.createMockFromModule('../../../src/CommonBot');
bot.getOption = () => {
return {
chatTool: {
type: IChatToolType.SLACK,
},
} as IBotOption;
};
return bot;
})();
}
70 changes: 70 additions & 0 deletions __tests__/common/mocks/MockContexts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*/

import { CommonBot } from '../../../src/CommonBot';
import { IChatContextData, IChattingContext, IChattingType, IPayload, IPayloadType, IUser } from '../../../src/types';

export class MockContexts {
private static mockMsg: IPayload = {
type: IPayloadType.MESSAGE,
data: 'mock_message',
};

private static mockUser: IUser = {
id: '123abc_def',
name: 'mock_user',
email: 'mock_user@mocks.me',
};

private static publicChatting: IChattingContext = {
bot: {} as CommonBot,
type: IChattingType.PUBLIC_CHANNEL,
user: this.mockUser,
channel: { name: 'mock_chan', id: '123_team_chan_321' },
tenant: { name: 'mock_tenant', id: '123_mock_tentant_id_321' },
team: { name: 'mock_team', id: '123_mock_team_id_321' },
};

/**
* Provides a simple Mattermost bot with all fields populated by some mocked defaults.
*
* Automation wishing to test specific IChatContextData values should use this as a base and then modify the respective properties
*
* @param bot
* @returns
*/
static SIMPLE_MM_CTX: IChatContextData = {
payload: this.mockMsg,
context: {
chatting: this.publicChatting,
chatTool: {
rootId: 'mock_root_id',
},
},
};

static SIMPLE_SLACK_CTX: IChatContextData = {
payload: this.mockMsg,
context: {
chatting: this.publicChatting,
chatTool: {
rootId: 'mock_root_id',
},
},
};

static SIMPLE_MSTEAMS_CTX: IChatContextData = {
payload: this.mockMsg,
context: {
chatting: this.publicChatting,
chatTool: undefined,
},
};
}
66 changes: 66 additions & 0 deletions __tests__/plugins/mattermost/__unit__/MattermostMiddleware.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*/

import { MattermostClient } from '../../../../src/plugins/mattermost/MattermostClient';
import { MattermostMiddleware } from '../../../../src/plugins/mattermost/MattermostMiddleware';
import { IChannel, IChattingType, IMattermostOption, IMessageType } from '../../../../src/types';
import { MockCommonBot } from '../../../common/mocks/MockCommonBot';
import { MockContexts } from '../../../common/mocks/MockContexts';

describe('Middleware Tests', () => {
it('Mattermost DirectMessage', async () => {
const ctx = MockContexts.SIMPLE_MM_CTX;
const testMsg = {
type: IMessageType.PLAIN_TEXT,
message: 'Test DM',
};
const testChanId: IChannel = {
id: 'mock_id',
name: 'mock_name',
chattingType: IChattingType.PERSONAL,
};

const middleware = new MattermostMiddleware(MockCommonBot.MATTERMOST_BOT);
const client = new MattermostClient(middleware, {
protocol: 'https',
tlsCertificate: '',
} as IMattermostOption);

client.createDmChannel = jest.fn(() => {
return new Promise<IChannel>((resolve) => {
resolve(testChanId);
});
});
client.sendMessage = jest.fn(() => {
return new Promise((resolve) => {
resolve();
});
});

(middleware as any).client = client;

await middleware.sendDirectMessage(ctx, [testMsg]);
expect(client.createDmChannel).toHaveBeenCalledWith(ctx.context.chatting.user, null);
expect(client.sendMessage).toHaveBeenCalledWith(testMsg.message, testChanId.id, ctx.context.chatTool.rootId);

// Case where CreateDm fails
jest.clearAllMocks();

client.createDmChannel = jest.fn(() => {
return new Promise<IChannel>((resolve) => {
resolve(null as any);
});
});

await middleware.sendDirectMessage(ctx, [testMsg]);
expect(client.createDmChannel).toHaveBeenCalledWith(ctx.context.chatting.user, null);
expect(client.sendMessage).toHaveBeenCalledTimes(0);
});
});
122 changes: 122 additions & 0 deletions __tests__/plugins/msteams/__unit__/MsteamsMiddleware.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*/

import { Activity, Attachment, ChannelInfo } from 'botbuilder';
import { BotActivityHandler } from '../../../../src/plugins/msteams/BotActivityHandler';
import { MsteamsMiddleware } from '../../../../src/plugins/msteams/MsteamsMiddleware';
import { IMessage, IMessageType } from '../../../../src/types';
import { MockCommonBot } from '../../../common/mocks/MockCommonBot';

describe('MsTeams Middleware Tests', () => {
// TODO: This is a copy of structure in source, remove it? Remove tests?
type MessageData = {
textMessage?: string;
mentions?: Record<string, any>;
attachments?: Attachment[];
};

const middlewareMock: {
botActivityHandler: BotActivityHandler;
buildActivity: (msgData: MessageData) => Partial<Activity>;
processMessages: (messages: IMessage[]) => MessageData;
} = new MsteamsMiddleware(MockCommonBot.MSTEAMS_BOT) as any;

it('MsTeams buildActivity', async () => {
const testCases: MessageData[] = [
{
textMessage: 'test',
},
{
textMessage: 'two',
mentions: { user: 'mock_user' },
},
{
attachments: [
{
contentType: 'mimetype/gif',
content: 'abcdef',
},
],
},
{
textMessage: '',
attachments: [
{
contentType: 'mimetype/gif',
content: 'abcdef',
},
],
},
{
textMessage: 'with a text message',
attachments: [
{
contentType: 'mimetype/gif',
content: 'abcdef',
},
],
},
{
attachments: [
{
contentType: 'mimetype/gif',
content: 'abcdef',
},
],
mentions: { user: 'mock_user' },
},
{
textMessage: '',
mentions: { user: 'mock_user' },
},
];

for (const message of testCases) {
const activ = middlewareMock.buildActivity(message);
expect(activ).toMatchSnapshot();
}
});

it('MSTeams processMessages', async () => {
// Basic test cases
const testCases: IMessage[][] = [
[
{ type: IMessageType.PLAIN_TEXT, message: 'hi' },
{ type: IMessageType.PLAIN_TEXT, message: 'over' },
],
[
{ type: IMessageType.PLAIN_TEXT, message: 'there', mentions: [{ mentioned: { id: 'mock_id' } }] },
{ type: IMessageType.PLAIN_TEXT, message: 'name', mentions: [{ mentioned: { id: 'another_id', name: 'mock_name' } }] },
],
[{ type: IMessageType.PLAIN_TEXT, message: 'there', mentions: [{ mentioned: { id: '', name: 'mock_name' } }] }],
[{ type: IMessageType.MSTEAMS_DIALOG_OPEN, message: 'open the dialog', mentions: [{ mentioned: { id: 'mock_id' } }] }],
[],
];

for (const test of testCases) {
const msgData = middlewareMock.processMessages(test);
expect(msgData).toMatchSnapshot();
}

// Cases where there's valid channelIds
middlewareMock.botActivityHandler.findChannelByName = jest.fn((name) => {
return { id: 'mocked_found_id', name: name + '_echo' };
});

middlewareMock.botActivityHandler.findChannelById = jest.fn((id) => {
return { id: id + '_echo', name: 'mocked_found_name' };
});

for (const test of testCases) {
const msgData = middlewareMock.processMessages(test);
expect(msgData).toMatchSnapshot();
}
});
});
Loading