diff --git a/backend/src/modules/communication/communication.module.ts b/backend/src/modules/communication/communication.module.ts index e24ebfba7..5452cf1d9 100644 --- a/backend/src/modules/communication/communication.module.ts +++ b/backend/src/modules/communication/communication.module.ts @@ -21,7 +21,7 @@ import { SlackArchiveChannelConsumer } from 'src/modules/communication/consumers import { SlackCommunicationConsumer } from 'src/modules/communication/consumers/slack-communication.consumer'; import { SlackArchiveChannelProducer } from 'src/modules/communication/producers/slack-archive-channel.producer'; import { SlackCommunicationProducer } from 'src/modules/communication/producers/slack-communication.producer'; -import { SlackAddUserToChannelConsumer } from './consumers/slack-add-user-channel.consummer'; +import { SlackAddUserToChannelConsumer } from './consumers/slack-add-user-channel.consumer'; import { SlackMergeBoardConsumer } from './consumers/slack-merge-board.consumer'; import { SlackResponsibleConsumer } from './consumers/slack-responsible.consumer'; import { SlackSendMessageConsumer } from './consumers/slack-send-message.consumer'; diff --git a/backend/src/modules/communication/consumers/slack-add-user-channel.consumer.spec.ts b/backend/src/modules/communication/consumers/slack-add-user-channel.consumer.spec.ts new file mode 100644 index 000000000..78cc114fc --- /dev/null +++ b/backend/src/modules/communication/consumers/slack-add-user-channel.consumer.spec.ts @@ -0,0 +1,59 @@ +import { DeepMocked, createMock } from '@golevelup/ts-jest'; +import { Test, TestingModule } from '@nestjs/testing'; +import { TYPES } from 'src/modules/communication/interfaces/types'; +import { AddUserMainChannelType } from '../dto/types'; +import { Job } from 'bull'; +import { SlackAddUserToChannelConsumer } from './slack-add-user-channel.consumer'; +import { AddUserIntoChannelApplicationInterface } from '../interfaces/communication.application.interface copy'; +import { Logger } from '@nestjs/common'; + +const newUserMock = { + id: 1, + data: { + email: 'someEmail@gmail.com' + } +}; + +describe('SlackAddUserToChannelConsumer', () => { + let consumer: SlackAddUserToChannelConsumer; + let addUserIntoChannelAppMock: DeepMocked; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + SlackAddUserToChannelConsumer, + { + provide: TYPES.application.SlackAddUserIntoChannelApplication, + useValue: createMock() + } + ] + }).compile(); + consumer = module.get(SlackAddUserToChannelConsumer); + addUserIntoChannelAppMock = module.get(TYPES.application.SlackAddUserIntoChannelApplication); + }); + + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('should be defined', () => { + expect(consumer).toBeDefined(); + }); + + describe('communication', () => { + it('should call AddUserIntoChannelApplication.execute once with job.data', async () => { + await consumer.communication(newUserMock as unknown as Job); + expect(addUserIntoChannelAppMock.execute).toHaveBeenNthCalledWith(1, newUserMock.data.email); + }); + }); + + describe('onCompleted', () => { + it('should call Logger with string containing a email ', async () => { + const spyLogger = jest.spyOn(Logger.prototype, 'verbose'); + const result: boolean[] = [true]; + await consumer.onCompleted(newUserMock as unknown as Job, result); + expect(spyLogger).toHaveBeenNthCalledWith(1, expect.stringContaining('someEmail@gmail.com')); + }); + }); +}); diff --git a/backend/src/modules/communication/consumers/slack-add-user-channel.consummer.ts b/backend/src/modules/communication/consumers/slack-add-user-channel.consumer.ts similarity index 93% rename from backend/src/modules/communication/consumers/slack-add-user-channel.consummer.ts rename to backend/src/modules/communication/consumers/slack-add-user-channel.consumer.ts index ee5a3bd74..e77554472 100644 --- a/backend/src/modules/communication/consumers/slack-add-user-channel.consummer.ts +++ b/backend/src/modules/communication/consumers/slack-add-user-channel.consumer.ts @@ -41,8 +41,5 @@ export class SlackAddUserToChannelConsumer extends SlackCommunicationEventListen !result[0] ? 'not' : '' } added to the main channel` ); - this.saveLog( - `User with email: ${job.data.email} was ${!result[0] ? 'not' : ''} added to the main channel` - ); } } diff --git a/backend/src/modules/communication/consumers/slack-archive-channel.consumer.spec.ts b/backend/src/modules/communication/consumers/slack-archive-channel.consumer.spec.ts new file mode 100644 index 000000000..c800166aa --- /dev/null +++ b/backend/src/modules/communication/consumers/slack-archive-channel.consumer.spec.ts @@ -0,0 +1,67 @@ +import { DeepMocked, createMock } from '@golevelup/ts-jest'; +import { Test, TestingModule } from '@nestjs/testing'; +import { TYPES } from 'src/modules/communication/interfaces/types'; +import { ArchiveChannelData } from '../dto/types'; +import { Job } from 'bull'; +import { SlackArchiveChannelConsumer } from './slack-archive-channel.consumer'; +import { ArchiveChannelApplicationInterface } from '../interfaces/archive-channel.application.interface'; +import { Logger } from '@nestjs/common'; + +const archiveChannelDataMock = { + id: 1, + data: { + type: 'CHANNEL_ID', + data: { id: '1', slackChannelId: 'someSlackId' }, + cascade: true + } +}; + +describe('SlackArchiveChannelConsumer', () => { + let consumer: SlackArchiveChannelConsumer; + let archiveChannelAppMock: DeepMocked; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + SlackArchiveChannelConsumer, + { + provide: TYPES.application.SlackArchiveChannelApplication, + useValue: createMock() + } + ] + }).compile(); + consumer = module.get(SlackArchiveChannelConsumer); + archiveChannelAppMock = module.get(TYPES.application.SlackArchiveChannelApplication); + }); + + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('should be defined', () => { + expect(consumer).toBeDefined(); + }); + + describe('communication', () => { + it('should call ArchiveChannelApplication.execute once with job.data', async () => { + await consumer.communication(archiveChannelDataMock as unknown as Job); + + expect(archiveChannelAppMock.execute).toHaveBeenNthCalledWith(1, archiveChannelDataMock.data); + }); + + it('should call Logger when type CHANNEL_ID', async () => { + const spyLogger = jest.spyOn(Logger.prototype, 'verbose'); + //Type 'CHANNEL_ID' + await consumer.communication(archiveChannelDataMock as unknown as Job); + expect(spyLogger).toBeCalledTimes(1); + }); + it('should call Logger when type BOARD', async () => { + const spyLogger = jest.spyOn(Logger.prototype, 'verbose'); + archiveChannelDataMock.data.type = 'BOARD'; + //Type 'BOARD' + await consumer.communication(archiveChannelDataMock as unknown as Job); + expect(spyLogger).toBeCalledTimes(1); + }); + }); +}); diff --git a/backend/src/modules/communication/consumers/slack-communication-event-listeners.spec.ts b/backend/src/modules/communication/consumers/slack-communication-event-listeners.spec.ts new file mode 100644 index 000000000..6b087cc99 --- /dev/null +++ b/backend/src/modules/communication/consumers/slack-communication-event-listeners.spec.ts @@ -0,0 +1,53 @@ +import { Logger } from '@nestjs/common'; +import { Test, TestingModule } from '@nestjs/testing'; +import { Job } from 'bull'; +import { BoardType } from '../dto/types'; +import { SlackCommunicationEventListeners } from './slack-communication-event-listeners'; +import { TeamDto } from 'src/modules/communication/dto/team.dto'; + +const BoardTypeMock = { + id: 1, + data: {} +}; + +describe('SlackCommunicationEventListeners', () => { + let listener: SlackCommunicationEventListeners; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [SlackCommunicationEventListeners] + }).compile(); + listener = module.get>( + SlackCommunicationEventListeners + ); + + listener.logger = new Logger(); + }); + + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('should be defined', () => { + expect(listener).toBeDefined(); + }); + + it('should call logger.verbose onCompleted', () => { + const spyLogger = jest.spyOn(Logger.prototype, 'verbose'); + listener.onCompleted(BoardTypeMock as unknown as Job, undefined); + expect(spyLogger).toHaveBeenNthCalledWith(1, expect.stringContaining('1')); + }); + + it('should call logger.verbose onFailed', () => { + const spyLogger = jest.spyOn(Logger.prototype, 'error').mockImplementation(jest.fn()); + listener.onFailed(BoardTypeMock as unknown as Job, 'someError'); + expect(spyLogger).toHaveBeenCalledTimes(1); + }); + + it('should call logger.error onError', () => { + const spyLogger = jest.spyOn(Logger.prototype, 'error').mockImplementation(jest.fn()); + listener.onError(new Error('someError')); + expect(spyLogger).toHaveBeenCalledTimes(1); + }); +}); diff --git a/backend/src/modules/communication/consumers/slack-communication-event-listeners.ts b/backend/src/modules/communication/consumers/slack-communication-event-listeners.ts index eae9cc304..482d37d0f 100644 --- a/backend/src/modules/communication/consumers/slack-communication-event-listeners.ts +++ b/backend/src/modules/communication/consumers/slack-communication-event-listeners.ts @@ -2,7 +2,6 @@ import { OnQueueCompleted, OnQueueError, OnQueueFailed, Process } from '@nestjs/bull'; import { Logger } from '@nestjs/common'; import { Job } from 'bull'; -import { createWriteStream } from 'fs'; export class SlackCommunicationEventListeners { constructor(public logger: Logger) {} @@ -13,9 +12,8 @@ export class SlackCommunicationEventListeners { // https://github.com/OptimalBits/bull/blob/develop/REFERENCE.md#events @OnQueueCompleted() - async onCompleted(job: Job, result: R[]) { + async onCompleted(job: Job, _result: R[]) { this.logger.verbose(`Completed Job id: "${job.id}"`); - this.saveLog(result); } @OnQueueFailed() @@ -27,14 +25,4 @@ export class SlackCommunicationEventListeners { onError(error: Error) { this.logger.error(`Error on queue: "${JSON.stringify(error)}"`); } - - saveLog(data: any) { - try { - const stream = createWriteStream('slackLog.txt', { flags: 'a' }); - stream.write(`${JSON.stringify(data)}\n`); - stream.end(); - } catch (error) { - this.logger.error(error); - } - } } diff --git a/backend/src/modules/communication/consumers/slack-communication.consumer.spec.ts b/backend/src/modules/communication/consumers/slack-communication.consumer.spec.ts new file mode 100644 index 000000000..fd940d018 --- /dev/null +++ b/backend/src/modules/communication/consumers/slack-communication.consumer.spec.ts @@ -0,0 +1,104 @@ +import { DeepMocked, createMock } from '@golevelup/ts-jest'; +import { Test, TestingModule } from '@nestjs/testing'; +import { TYPES } from 'src/modules/communication/interfaces/types'; +import { TYPES as BOARD_TYPES } from 'src/modules/boards/interfaces/types'; +import { BoardType } from '../dto/types'; +import { Job } from 'bull'; +import { SlackCommunicationConsumer } from './slack-communication.consumer'; +import { CommunicationApplicationInterface } from '../interfaces/communication.application.interface'; +import { UpdateBoardServiceInterface } from 'src/modules/boards/interfaces/services/update.board.service.interface'; +import { Logger } from '@nestjs/common'; +import { UserFactory } from 'src/libs/test-utils/mocks/factories/user-factory'; +import { TeamDto } from 'src/modules/communication/dto/team.dto'; + +const BoardTypeMock = { + id: 1, + data: { + id: 'someId', + title: 'someTitle', + isSubBoard: true, + dividedBoards: 'BoardType[]', + team: null, + users: '', + slackChannelId: 'someSlackChannelId', + boardNumber: 1 + } +}; + +const result = [ + { + name: 'someName', + normalName: 'normalName', + boardId: 'someBoardId', + channelId: 'someChannelId', + type: 'team', + for: 'member', + participants: UserFactory.createMany(2), + teamNumber: 2 + } +]; + +describe('SlackCommunicationConsumer', () => { + let consumer: SlackCommunicationConsumer; + let communicationAppMock: DeepMocked; + let updateBoardServiceMock: DeepMocked; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + SlackCommunicationConsumer, + { + provide: TYPES.application.SlackCommunicationApplication, + useValue: createMock() + }, + { + provide: BOARD_TYPES.services.UpdateBoardService, + useValue: createMock() + } + ] + }).compile(); + consumer = module.get(SlackCommunicationConsumer); + communicationAppMock = module.get(TYPES.application.SlackCommunicationApplication); + updateBoardServiceMock = module.get(BOARD_TYPES.services.UpdateBoardService); + }); + + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('should be defined', () => { + expect(consumer).toBeDefined(); + }); + + describe('communication', () => { + it('should call application.execute once with job.data', async () => { + await consumer.communication(BoardTypeMock as unknown as Job); + expect(communicationAppMock.execute).toHaveBeenNthCalledWith(1, BoardTypeMock.data); + }); + + it('should call Logger when type BOARD', async () => { + const spyLogger = jest.spyOn(Logger.prototype, 'verbose'); + await consumer.communication(BoardTypeMock as unknown as Job); + expect(spyLogger).toBeCalledTimes(1); + }); + }); + + describe('onCompleted', () => { + it('should call Logger once', async () => { + const spyLogger = jest.spyOn(Logger.prototype, 'verbose'); + await consumer.onCompleted( + BoardTypeMock as unknown as Job, + result as unknown as TeamDto[] + ); + expect(spyLogger).toBeCalledTimes(1); + }); + it('should call updateBoardService once', async () => { + await consumer.onCompleted( + BoardTypeMock as unknown as Job, + result as unknown as TeamDto[] + ); + expect(updateBoardServiceMock.updateChannelId).toBeCalledTimes(1); + }); + }); +}); diff --git a/backend/src/modules/communication/consumers/slack-communication.consumer.ts b/backend/src/modules/communication/consumers/slack-communication.consumer.ts index 257847a08..095f46254 100644 --- a/backend/src/modules/communication/consumers/slack-communication.consumer.ts +++ b/backend/src/modules/communication/consumers/slack-communication.consumer.ts @@ -43,6 +43,5 @@ export class SlackCommunicationConsumer extends SlackCommunicationEventListeners override async onCompleted(job: Job, result: TeamDto[]) { this.logger.verbose(`Completed Job id: "${job.id}"`); this.updateBoardService.updateChannelId(result); - this.saveLog(result); } } diff --git a/backend/src/modules/communication/consumers/slack-merge-board.consumer.spec.ts b/backend/src/modules/communication/consumers/slack-merge-board.consumer.spec.ts new file mode 100644 index 000000000..6c8f4aa9d --- /dev/null +++ b/backend/src/modules/communication/consumers/slack-merge-board.consumer.spec.ts @@ -0,0 +1,51 @@ +import { DeepMocked, createMock } from '@golevelup/ts-jest'; +import { Test, TestingModule } from '@nestjs/testing'; +import { TYPES } from 'src/modules/communication/interfaces/types'; +import { MergeBoardType } from '../dto/types'; +import { Job } from 'bull'; +import { SlackMergeBoardConsumer } from './slack-merge-board.consumer'; +import { MergeBoardApplicationInterface } from '../interfaces/merge-board.application.interface'; + +const mergeBoardTypeMock = { + id: 1, + data: { + teamNumber: 1, + responsiblesChannelId: 'someResponsiblesChannelId', + isLastSubBoard: true, + boardId: 'someBoardId', + mainBoardId: 'mainBoardId' + } +}; + +describe('SlackMergeBoardConsumer', () => { + let consumer: SlackMergeBoardConsumer; + let applicationMock: DeepMocked; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + SlackMergeBoardConsumer, + { + provide: TYPES.application.SlackMergeBoardApplication, + useValue: createMock() + } + ] + }).compile(); + consumer = module.get(SlackMergeBoardConsumer); + applicationMock = module.get(TYPES.application.SlackMergeBoardApplication); + }); + + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('should be defined', () => { + expect(consumer).toBeDefined(); + }); + + it('should call application.execute once with job.data', async () => { + await consumer.communication(mergeBoardTypeMock as unknown as Job); + expect(applicationMock.execute).toHaveBeenNthCalledWith(1, mergeBoardTypeMock.data); + }); +}); diff --git a/backend/src/modules/communication/consumers/slack-responsible.consumer.spec.ts b/backend/src/modules/communication/consumers/slack-responsible.consumer.spec.ts new file mode 100644 index 000000000..62a5e2802 --- /dev/null +++ b/backend/src/modules/communication/consumers/slack-responsible.consumer.spec.ts @@ -0,0 +1,55 @@ +import { DeepMocked, createMock } from '@golevelup/ts-jest'; +import { Test, TestingModule } from '@nestjs/testing'; +import { ResponsibleApplicationInterface } from '../interfaces/responsible.application.interface'; +import { TYPES } from 'src/modules/communication/interfaces/types'; +import { SlackResponsibleConsumer } from './slack-responsible.consumer'; +import { ChangeResponsibleType } from '../dto/types'; +import { Job } from 'bull'; + +const changeResponsibleMock = { + id: 1, + data: { + newResponsibleEmail: 'newResponsible@gmail.com', + previousResponsibleEmail: 'previousResponsible@gmail.com', + subTeamChannelId: 'C99CQSJC1M5', + email: 'someEmail@gmail.com', + teamNumber: 2, + responsiblesChannelId: 'C03CLDK1M2', + mainChannelId: 'C03CQSJC1M2' + } +}; + +describe('SlackResponsibleConsumer', () => { + let consumer: SlackResponsibleConsumer; + let responsibleApplicationMock: DeepMocked; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + SlackResponsibleConsumer, + { + provide: TYPES.application.SlackResponsibleApplication, + useValue: createMock() + } + ] + }).compile(); + consumer = module.get(SlackResponsibleConsumer); + responsibleApplicationMock = module.get(TYPES.application.SlackResponsibleApplication); + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should be defined', () => { + expect(consumer).toBeDefined(); + }); + + it('should call application.execute once with job.data', async () => { + await consumer.communication(changeResponsibleMock as unknown as Job); + expect(responsibleApplicationMock.execute).toHaveBeenNthCalledWith( + 1, + changeResponsibleMock.data + ); + }); +}); diff --git a/backend/src/modules/communication/consumers/slack-send-message.consumer.spec.ts b/backend/src/modules/communication/consumers/slack-send-message.consumer.spec.ts index 4f3e99e12..4b980ebaa 100644 --- a/backend/src/modules/communication/consumers/slack-send-message.consumer.spec.ts +++ b/backend/src/modules/communication/consumers/slack-send-message.consumer.spec.ts @@ -39,7 +39,7 @@ describe('SlackSendMessageConsumer', () => { expect(consumer).toBeDefined(); }); - it('should call sendMessageApplication.execute with job.data 1 time', async () => { + it('should call application.execute once with job.data', async () => { await consumer.communication(slackMessageMock as unknown as Job); expect(sendMessageApplicationMock.execute).toHaveBeenNthCalledWith(1, slackMessageMock.data); });