require('dotenv').config() import * as path from "path"; import * as os from "os"; import * as fs from "fs"; import waitForExpect from 'wait-for-expect' import { createClient, WebStorageSessionStore, mockClient, mockRegisterRequest, mockInitCrypto, mockStartClient, mockSetPowerLevel, mockCreateRoom, mockLeave, mockDeactivateAccount, mockStopClient, mockClearStores, mockOn, mockOnce, mockSendTextMessage, mockLogin, mockGetDevices, mockGetDeviceId, mockDeleteMultipleDevices, mockGetJoinedRooms, mockSetDeviceVerified, mockInvite, mockKick, mockGetJoinedRoomMembers, mockGetUser } from "matrix-js-sdk"; import OcrccBot from './bot' const mockAppendFileSync = jest.fn() fs.appendFileSync = mockAppendFileSync describe('OcrccBot', () => { beforeEach(() => { createClient.mockClear() mockInitCrypto.mockClear() mockStartClient.mockClear() mockRegisterRequest.mockClear() mockSetPowerLevel.mockClear() mockCreateRoom.mockClear() mockLeave.mockClear() mockDeactivateAccount.mockClear() mockStopClient.mockClear() mockClearStores.mockClear() mockOnce.mockClear() mockOn.mockClear() mockLogin.mockClear() mockGetDevices.mockClear() mockGetDeviceId.mockClear() mockDeleteMultipleDevices.mockClear() mockGetJoinedRooms.mockClear() mockSetDeviceVerified.mockClear() mockInvite.mockClear() mockKick.mockClear() mockGetJoinedRoomMembers.mockClear() mockGetUser.mockClear() mockSendTextMessage.mockClear() mockAppendFileSync.mockClear() }) test('constructor should inititialize matrix client', () => { const bot = new OcrccBot() expect(createClient).toHaveBeenCalledWith(process.env.MATRIX_SERVER_URL) expect(bot.joinedRooms).toEqual([]) expect(bot.awaitingFacilitator).toEqual({}) expect(bot.activeChatrooms).toEqual({}) }) test('#createLocalStorage should have correct storage location', () => { const bot = new OcrccBot() const localStorage = bot.createLocalStorage() const localStoragePath = path.resolve(path.join(os.homedir(), ".local-storage", `matrix-chatbot-${process.env.BOT_USERNAME}`)); expect(localStorage._location).toBe(localStoragePath) }) test('#sendMessage should send a text message', () => { const bot = new OcrccBot() bot.start() waitForExpect(() => { expect(mockStartClient).toHaveBeenCalled() }) const testRoom = 'room_id_1234' const testMsg = 'test message' bot.sendMessage(testRoom, testMsg) waitForExpect(() => { expect(mockSetDeviceVerified).toHaveBeenCalledTimes(2) }) waitForExpect(() => { expect(mockSendTextMessage).toHaveBeenCalledWith(testRoom, testMsg) }) }) test('#inviteUserToRoom should add member to room and retry on rate limit error', () => { const bot = new OcrccBot() bot.start() waitForExpect(() => { expect(mockStartClient).toHaveBeenCalled() }) bot.inviteUserToRoom(bot.client, 'room_id_1234', process.env.BOT_USERNAME) waitForExpect(() => { expect(mockInvite).toHaveBeenCalledTimes(2) }) }) test('#kickUserFromRoom should remove member from room and retry on rate limit error', () => { const bot = new OcrccBot() bot.start() waitForExpect(() => { expect(mockStartClient).toHaveBeenCalled() }) bot.kickUserFromRoom(bot.client, 'room_id_1234', process.env.BOT_USERNAME) waitForExpect(() => { expect(mockKick).toHaveBeenCalledTimes(2) }) }) test('#inviteFacilitators should invite all members from Facilitator room', () => { const bot = new OcrccBot() bot.start() waitForExpect(() => { expect(mockStartClient).toHaveBeenCalled() }) bot.inviteFacilitators() waitForExpect(() => { expect(mockGetJoinedRoomMembers).toHaveBeenCalledWith(process.env.FACILITATOR_ROOM_ID) }) waitForExpect(() => { expect(mockGetUser).toHaveBeenCalledTimes(2) }) waitForExpect(() => { expect(mockInvite).toHaveBeenCalledTimes(2) }) }) test('#uninviteFacilitators should remove all members that have not accepted the invite', () => { const bot = new OcrccBot() bot.start() waitForExpect(() => { expect(mockStartClient).toHaveBeenCalled() }) bot.uninviteFacilitators() waitForExpect(() => { expect(mockGetJoinedRoomMembers).toHaveBeenCalledWith(process.env.FACILITATOR_ROOM_ID) }) waitForExpect(() => { expect(mockGetJoinedRoomMembers).toHaveBeenCalledWith('room_id_1234') }) waitForExpect(() => { expect(mockKick).toHaveBeenCalled() }) }) test('#handleBotCrash should notify rooms', () => { const bot = new OcrccBot() bot.start() waitForExpect(() => { expect(mockStartClient).toHaveBeenCalled() }) bot.handleBotCrash('test_room_id', 'test error message') waitForExpect(() => { expect(mockSendTextMessage).toHaveBeenCalledWith('test_room_id', "Something went wrong on our end, please restart the chat and try again.") }) waitForExpect(() => { expect(mockSendTextMessage).toHaveBeenCalledWith(process.env.FACILITATOR_ROOM_ID, `The Help Bot ran into an error: test error message. Please verify that the chat service is working.`) }) }) test('#writeToTranscript should parse event and write to transcript file', () => { const bot = new OcrccBot() bot.start() bot.activeChatrooms['test_room_id'] = { transcriptFile: '__mocks__/test_transcript.txt' } waitForExpect(() => { expect(mockStartClient).toHaveBeenCalled() }) const mockEvent = { getSender: () => 'test_sender', getRoomId: () => 'test_room_id', getContent: () => { return { body: 'test content' }}, getDate: () => { return new Date(2020,2,17,0,0,0,0) } } bot.writeToTranscript(mockEvent) waitForExpect(() => { expect(mockAppendFileSync).toHaveBeenCalledWith('__mocks__/test_transcript.txt', 'test_sender [00:00:00]: test content', 'utf8') }) }) test('#deleteOldDevices should delete old sessions', () => { const bot = new OcrccBot() bot.start() waitForExpect(() => { expect(mockStartClient).toHaveBeenCalled() }) bot.deleteOldDevices() waitForExpect(() => { expect(mockGetDevices).toHaveBeenCalled() }) waitForExpect(() => { expect(mockGetDevicdId).toHaveBeenCalled() }) waitForExpect(() => { expect(deleteMultipleDevices).toHaveBeenCalled() }) }) // TODO test listeners for membership events and message events test('#start should start bot and set up listeners', () => { const bot = new OcrccBot() bot.start() waitForExpect(() => { expect(mockLogin).toHaveBeenCalled() }) waitForExpect(() => { expect(WebStorageSessionStore).toHaveBeenCalled() }) waitForExpect(() => { expect(createClient).toHaveBeenCalled() }) waitForExpect(() => { expect(mockGetDevices).toHaveBeenCalled() }) waitForExpect(() => { expect(mockGetDeviceId).toHaveBeenCalled() }) waitForExpect(() => { expect(mockDeleteMultipleDevices).toHaveBeenCalled() }) waitForExpect(() => { expect(mockInitCrypto).toHaveBeenCalled() }) waitForExpect(() => { expect(mockGetJoinedRooms).toHaveBeenCalled() }) waitForExpect(() => { expect(mockOn).toHaveBeenCalled() }) waitForExpect(() => { expect(mockStartClient).toHaveBeenCalled() }) }) })