From ac770154f5dc70ac5efe72aea44db2c5f9bd2344 Mon Sep 17 00:00:00 2001 From: yassinedorbozgithub Date: Sun, 23 Mar 2025 08:52:19 +0100 Subject: [PATCH] feat: add unit tests global provider config --- .../controllers/bot-stats.controller.spec.ts | 23 +++----- .../repositories/bot-stats.repository.spec.ts | 24 ++++----- .../services/bot-stats.service.spec.ts | 23 +++----- .../controllers/attachment.controller.spec.ts | 26 +++++---- .../guards/attachment-ability.guard.spec.ts | 17 +++--- .../chat/controllers/block.controller.spec.ts | 18 +++---- .../controllers/category.contoller.spec.ts | 17 +++--- .../context-var.controller.spec.ts | 24 ++++----- .../chat/controllers/label.controller.spec.ts | 18 +++---- .../controllers/message.controller.spec.ts | 23 ++++---- .../controllers/subscriber.controller.spec.ts | 25 ++++----- .../repositories/block.repository.spec.ts | 19 +++---- .../repositories/label.repository.spec.ts | 24 ++++----- .../repositories/message.repository.spec.ts | 24 ++++----- .../subscriber.repository.spec.ts | 35 ++++++------ api/src/chat/services/block.service.spec.ts | 31 ++++++----- api/src/chat/services/bot.service.spec.ts | 22 ++++---- api/src/chat/services/label.service.spec.ts | 19 +++---- api/src/chat/services/message.service.spec.ts | 24 ++++----- .../chat/services/subscriber.service.spec.ts | 24 ++++----- .../content-type.controller.spec.ts | 25 ++++----- .../controllers/content.controller.spec.ts | 18 +++---- .../cms/controllers/menu.controller.spec.ts | 18 +++---- .../content-type.repository.spec.ts | 28 ++++------ .../repositories/content.repository.spec.ts | 22 ++++---- .../cms/repositories/menu.reporsitory.spec.ts | 18 +++---- .../cms/services/content-type.service.spec.ts | 29 +++++----- api/src/cms/services/content.service.spec.ts | 22 ++++---- api/src/cms/services/menu.service.spec.ts | 23 ++++---- .../channels/web/__test__/index.spec.ts | 16 +++--- .../channels/web/__test__/wrapper.spec.ts | 16 ++---- .../controllers/language.controller.spec.ts | 19 +++---- .../translation.controller.spec.ts | 19 +++---- .../i18n/services/translation.service.spec.ts | 20 ++++--- api/src/migration/migration.service.spec.ts | 17 +++--- .../controllers/nlp-entity.controller.spec.ts | 26 ++++----- .../controllers/nlp-sample.controller.spec.ts | 38 ++++++------- .../controllers/nlp-value.controller.spec.ts | 25 ++++----- .../nlp-entity.repository.spec.ts | 20 ++++--- .../nlp-sample-entity.repository.spec.ts | 25 ++++----- .../nlp-sample.repository.spec.ts | 25 ++++----- .../repositories/nlp-value.repository.spec.ts | 22 ++++---- .../nlp/services/nlp-entity.service.spec.ts | 23 ++++---- .../nlp-sample-entity.service.spec.ts | 32 +++++------ .../nlp/services/nlp-sample.service.spec.ts | 42 +++++++-------- .../nlp/services/nlp-value.service.spec.ts | 25 +++++---- api/src/plugins/plugins.service.spec.ts | 23 ++++---- .../controllers/setting.controller.spec.ts | 19 +++---- .../repositories/setting.repository.spec.ts | 23 ++++---- .../setting/services/setting.service.spec.ts | 17 +++--- .../user/controllers/auth.controller.spec.ts | 30 +++++------ .../user/controllers/model.controller.spec.ts | 20 ++++--- .../controllers/permission.controller.spec.ts | 27 ++++------ .../user/controllers/role.controller.spec.ts | 25 ++++----- .../user/controllers/user.controller.spec.ts | 34 ++++++------ .../invitation.repository.spec.ts | 34 +++++------- .../repositories/model.repository.spec.ts | 20 +++---- .../permission.repository.spec.ts | 26 ++++----- .../user/repositories/role.repository.spec.ts | 24 ++++----- .../user/repositories/user.repository.spec.ts | 20 ++++--- api/src/user/services/auth.service.spec.ts | 18 +++---- .../user/services/invitation.service.spec.ts | 37 ++++++------- api/src/user/services/model.service.spec.ts | 25 ++++----- .../services/passwordReset.service.spec.ts | 25 ++++----- .../user/services/permission.service.spec.ts | 26 ++++----- api/src/user/services/role.service.spec.ts | 24 ++++----- api/src/user/services/user.service.spec.ts | 20 ++++--- .../services/validate-account.service.spec.ts | 25 ++++----- .../utils/generics/base-repository.spec.ts | 14 ++--- api/src/utils/generics/base-service.spec.ts | 13 ++--- api/src/utils/test/utils.ts | 53 +++++++++++++++++++ api/src/websocket/websocket.gateway.spec.ts | 12 ++--- api/test/app.e2e-spec.ts | 11 ++-- 73 files changed, 809 insertions(+), 909 deletions(-) create mode 100644 api/src/utils/test/utils.ts diff --git a/api/src/analytics/controllers/bot-stats.controller.spec.ts b/api/src/analytics/controllers/bot-stats.controller.spec.ts index 636c3aef..c5b2456a 100644 --- a/api/src/analytics/controllers/bot-stats.controller.spec.ts +++ b/api/src/analytics/controllers/bot-stats.controller.spec.ts @@ -1,16 +1,13 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; -import { LoggerService } from '@/logger/logger.service'; import { botstatsFixtures, installBotStatsFixtures, @@ -19,6 +16,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { BotStatsRepository } from '../repositories/bot-stats.repository'; import { BotStatsModel, BotStatsType } from '../schemas/bot-stats.schema'; @@ -30,25 +28,18 @@ describe('BotStatsController', () => { let botStatsController: BotStatsController; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [BotStatsController], imports: [ rootMongooseTestModule(installBotStatsFixtures), MongooseModule.forFeature([BotStatsModel]), ], - providers: [ - LoggerService, - BotStatsService, - BotStatsRepository, - EventEmitter2, - ], - }).compile(); - botStatsController = module.get(BotStatsController); + providers: [BotStatsService, BotStatsRepository], + }); + [botStatsController] = await getMocks([BotStatsController]); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/analytics/repositories/bot-stats.repository.spec.ts b/api/src/analytics/repositories/bot-stats.repository.spec.ts index 76f1606a..87373ee5 100644 --- a/api/src/analytics/repositories/bot-stats.repository.spec.ts +++ b/api/src/analytics/repositories/bot-stats.repository.spec.ts @@ -1,17 +1,14 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; -import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; +import { getModelToken, MongooseModule } from '@nestjs/mongoose'; import { Model } from 'mongoose'; -import { LoggerService } from '@/logger/logger.service'; import { botstatsFixtures, installBotStatsFixtures, @@ -20,6 +17,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { BotStats, @@ -34,20 +32,20 @@ describe('BotStatsRepository', () => { let botStatsModel: Model; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installBotStatsFixtures), MongooseModule.forFeature([BotStatsModel]), ], - providers: [LoggerService, BotStatsRepository, EventEmitter2], - }).compile(); - botStatsRepository = module.get(BotStatsRepository); - botStatsModel = module.get>(getModelToken('BotStats')); + providers: [BotStatsRepository], + }); + [botStatsRepository, botStatsModel] = await getMocks([ + BotStatsRepository, + getModelToken(BotStats.name), + ]); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/analytics/services/bot-stats.service.spec.ts b/api/src/analytics/services/bot-stats.service.spec.ts index 1d320848..7af66b9e 100644 --- a/api/src/analytics/services/bot-stats.service.spec.ts +++ b/api/src/analytics/services/bot-stats.service.spec.ts @@ -1,16 +1,13 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; -import { LoggerService } from '@/logger/logger.service'; import { botstatsFixtures, installBotStatsFixtures, @@ -19,6 +16,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { BotStatsRepository } from '../repositories/bot-stats.repository'; import { BotStatsModel, BotStatsType } from '../schemas/bot-stats.schema'; @@ -29,24 +27,17 @@ describe('BotStatsService', () => { let botStatsService: BotStatsService; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installBotStatsFixtures), MongooseModule.forFeature([BotStatsModel]), ], - providers: [ - LoggerService, - BotStatsService, - BotStatsRepository, - EventEmitter2, - ], - }).compile(); - botStatsService = module.get(BotStatsService); + providers: [BotStatsService, BotStatsRepository], + }); + [botStatsService] = await getMocks([BotStatsService]); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/attachment/controllers/attachment.controller.spec.ts b/api/src/attachment/controllers/attachment.controller.spec.ts index eb13cdb1..d2f22a04 100644 --- a/api/src/attachment/controllers/attachment.controller.spec.ts +++ b/api/src/attachment/controllers/attachment.controller.spec.ts @@ -11,9 +11,7 @@ import fs from 'fs'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { BadRequestException } from '@nestjs/common/exceptions'; import { NotFoundException } from '@nestjs/common/exceptions/not-found.exception'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { Request } from 'express'; import LocalStorageHelper from '@/extensions/helpers/local-storage/index.helper'; @@ -40,6 +38,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { attachment, attachmentFile } from '../mocks/attachment.mock'; import { AttachmentRepository } from '../repositories/attachment.repository'; @@ -59,10 +58,9 @@ describe('AttachmentController', () => { let attachmentToDelete: Attachment; let helperService: HelperService; let settingService: SettingService; - let loggerService: LoggerService; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks, resolveMocks } = await buildTestingMocks({ controllers: [AttachmentController], imports: [ rootMongooseTestModule(async () => { @@ -84,8 +82,6 @@ describe('AttachmentController', () => { SettingRepository, ModelService, ModelRepository, - LoggerService, - EventEmitter2, SettingSeeder, SettingService, HelperService, @@ -98,18 +94,20 @@ describe('AttachmentController', () => { }, }, ], - }).compile(); - attachmentController = - module.get(AttachmentController); - attachmentService = module.get(AttachmentService); + }); + [attachmentController, attachmentService, helperService, settingService] = + await getMocks([ + AttachmentController, + AttachmentService, + HelperService, + SettingService, + ]); + const [loggerService] = await resolveMocks([LoggerService]); + attachmentToDelete = (await attachmentService.findOne({ name: 'store1.jpg', }))!; - helperService = module.get(HelperService); - settingService = module.get(SettingService); - loggerService = await module.resolve(LoggerService); - helperService.register( new LocalStorageHelper(settingService, helperService, loggerService), ); diff --git a/api/src/attachment/guards/attachment-ability.guard.spec.ts b/api/src/attachment/guards/attachment-ability.guard.spec.ts index 395163ae..3629d26c 100644 --- a/api/src/attachment/guards/attachment-ability.guard.spec.ts +++ b/api/src/attachment/guards/attachment-ability.guard.spec.ts @@ -7,13 +7,13 @@ */ import { BadRequestException, ExecutionContext } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; import { Model } from '@/user/schemas/model.schema'; import { Permission } from '@/user/schemas/permission.schema'; import { ModelService } from '@/user/services/model.service'; import { PermissionService } from '@/user/services/permission.service'; import { Action } from '@/user/types/action.type'; +import { buildTestingMocks } from '@/utils/test/utils'; import { attachment } from '../mocks/attachment.mock'; import { Attachment } from '../schemas/attachment.schema'; @@ -29,7 +29,7 @@ describe('AttachmentGuard', () => { let attachmentService: AttachmentService; beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ providers: [ AttachmentGuard, { @@ -45,12 +45,15 @@ describe('AttachmentGuard', () => { useValue: { findOne: jest.fn() }, }, ], - }).compile(); + }); - guard = module.get(AttachmentGuard); - permissionService = module.get(PermissionService); - modelService = module.get(ModelService); - attachmentService = module.get(AttachmentService); + [guard, permissionService, modelService, attachmentService] = + await getMocks([ + AttachmentGuard, + PermissionService, + ModelService, + AttachmentService, + ]); }); describe('canActivate', () => { diff --git a/api/src/chat/controllers/block.controller.spec.ts b/api/src/chat/controllers/block.controller.spec.ts index 74e73021..7315ae3a 100644 --- a/api/src/chat/controllers/block.controller.spec.ts +++ b/api/src/chat/controllers/block.controller.spec.ts @@ -8,9 +8,7 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { NotFoundException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; @@ -22,7 +20,6 @@ import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { LanguageModel } from '@/i18n/schemas/language.schema'; import { I18nService } from '@/i18n/services/i18n.service'; import { LanguageService } from '@/i18n/services/language.service'; -import { LoggerService } from '@/logger/logger.service'; import { PluginService } from '@/plugins/plugins.service'; import { SettingService } from '@/setting/services/setting.service'; import { InvitationRepository } from '@/user/repositories/invitation.repository'; @@ -46,6 +43,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { BlockCreateDto, BlockUpdateDto } from '../dto/block.dto'; import { BlockRepository } from '../repositories/block.repository'; @@ -79,7 +77,7 @@ describe('BlockController', () => { ]; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [BlockController], imports: [ rootMongooseTestModule(installBlockFixtures), @@ -117,7 +115,6 @@ describe('BlockController', () => { PermissionService, LanguageService, PluginService, - LoggerService, { provide: I18nService, useValue: { @@ -133,7 +130,6 @@ describe('BlockController', () => { getSettings: jest.fn(() => ({})), }, }, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -143,10 +139,12 @@ describe('BlockController', () => { }, }, ], - }).compile(); - blockController = module.get(BlockController); - blockService = module.get(BlockService); - categoryService = module.get(CategoryService); + }); + [blockController, blockService, categoryService] = await getMocks([ + BlockController, + BlockService, + CategoryService, + ]); category = (await categoryService.findOne({ label: 'default' }))!; block = (await blockService.findOne({ name: 'first' }))!; blockToDelete = (await blockService.findOne({ name: 'buttons' }))!; diff --git a/api/src/chat/controllers/category.contoller.spec.ts b/api/src/chat/controllers/category.contoller.spec.ts index 6fd1966e..f8a8063b 100644 --- a/api/src/chat/controllers/category.contoller.spec.ts +++ b/api/src/chat/controllers/category.contoller.spec.ts @@ -7,9 +7,7 @@ */ import { BadRequestException, NotFoundException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; @@ -18,7 +16,6 @@ import { ContentRepository } from '@/cms/repositories/content.repository'; import { ContentModel } from '@/cms/schemas/content.schema'; import { ContentService } from '@/cms/services/content.service'; import { I18nService } from '@/i18n/services/i18n.service'; -import { LoggerService } from '@/logger/logger.service'; import { PluginService } from '@/plugins/plugins.service'; import { SettingService } from '@/setting/services/setting.service'; import { @@ -31,6 +28,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { CategoryCreateDto, CategoryUpdateDto } from '../dto/category.dto'; import { BlockRepository } from '../repositories/block.repository'; @@ -50,7 +48,7 @@ describe('CategoryController', () => { let categoryToDelete: Category; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [CategoryController], imports: [ rootMongooseTestModule(installCategoryFixtures), @@ -75,7 +73,6 @@ describe('CategoryController', () => { provide: PluginService, useValue: {}, }, - LoggerService, { provide: I18nService, useValue: { @@ -97,11 +94,12 @@ describe('CategoryController', () => { findOne: jest.fn(), }, }, - EventEmitter2, ], - }).compile(); - categoryService = module.get(CategoryService); - categoryController = module.get(CategoryController); + }); + [categoryService, categoryController] = await getMocks([ + CategoryService, + CategoryController, + ]); category = (await categoryService.findOne({ label: 'test category 1', })) as Category; @@ -111,6 +109,7 @@ describe('CategoryController', () => { }); afterEach(jest.clearAllMocks); + afterAll(closeInMongodConnection); describe('findPage', () => { diff --git a/api/src/chat/controllers/context-var.controller.spec.ts b/api/src/chat/controllers/context-var.controller.spec.ts index 0f07f985..0ac9d023 100644 --- a/api/src/chat/controllers/context-var.controller.spec.ts +++ b/api/src/chat/controllers/context-var.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,11 +7,8 @@ */ import { BadRequestException, NotFoundException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; -import { LoggerService } from '@/logger/logger.service'; import { getUpdateOneError } from '@/utils/test/errors/messages'; import { contextVarFixtures, @@ -23,6 +20,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { ContextVarCreateDto, @@ -41,22 +39,18 @@ describe('ContextVarController', () => { let contextVarToDelete: ContextVar; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [ContextVarController], imports: [ rootMongooseTestModule(installContextVarFixtures), MongooseModule.forFeature([ContextVarModel]), ], - providers: [ - LoggerService, - ContextVarService, - ContextVarRepository, - EventEmitter2, - ], - }).compile(); - contextVarController = - module.get(ContextVarController); - contextVarService = module.get(ContextVarService); + providers: [ContextVarService, ContextVarRepository], + }); + [contextVarController, contextVarService] = await getMocks([ + ContextVarController, + ContextVarService, + ]); contextVar = (await contextVarService.findOne({ label: 'test context var 1', }))!; diff --git a/api/src/chat/controllers/label.controller.spec.ts b/api/src/chat/controllers/label.controller.spec.ts index 56e0fd34..1136cf40 100644 --- a/api/src/chat/controllers/label.controller.spec.ts +++ b/api/src/chat/controllers/label.controller.spec.ts @@ -7,14 +7,11 @@ */ import { BadRequestException, NotFoundException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; -import { LoggerService } from '@/logger/logger.service'; import { InvitationRepository } from '@/user/repositories/invitation.repository'; import { RoleRepository } from '@/user/repositories/role.repository'; import { UserRepository } from '@/user/repositories/user.repository'; @@ -35,6 +32,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { LabelCreateDto, LabelUpdateDto } from '../dto/label.dto'; import { LabelRepository } from '../repositories/label.repository'; @@ -55,7 +53,7 @@ describe('LabelController', () => { let subscriberService: SubscriberService; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [LabelController], imports: [ rootMongooseTestModule(installSubscriberFixtures), @@ -70,7 +68,6 @@ describe('LabelController', () => { ]), ], providers: [ - LoggerService, LabelController, LabelService, LabelRepository, @@ -81,14 +78,15 @@ describe('LabelController', () => { InvitationRepository, SubscriberService, SubscriberRepository, - EventEmitter2, AttachmentService, AttachmentRepository, ], - }).compile(); - labelService = module.get(LabelService); - subscriberService = module.get(SubscriberService); - labelController = module.get(LabelController); + }); + [labelService, subscriberService, labelController] = await getMocks([ + LabelService, + SubscriberService, + LabelController, + ]); label = (await labelService.findOne({ name: 'TEST_TITLE_1' })) as Label; labelToDelete = (await labelService.findOne({ name: 'TEST_TITLE_2', diff --git a/api/src/chat/controllers/message.controller.spec.ts b/api/src/chat/controllers/message.controller.spec.ts index fb506d9d..0bc9e2a5 100644 --- a/api/src/chat/controllers/message.controller.spec.ts +++ b/api/src/chat/controllers/message.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,9 +7,7 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; @@ -19,7 +17,6 @@ import { MenuRepository } from '@/cms/repositories/menu.repository'; import { MenuModel } from '@/cms/schemas/menu.schema'; import { MenuService } from '@/cms/services/menu.service'; import { I18nService } from '@/i18n/services/i18n.service'; -import { LoggerService } from '@/logger/logger.service'; import { NlpService } from '@/nlp/services/nlp.service'; import { SettingService } from '@/setting/services/setting.service'; import { InvitationRepository } from '@/user/repositories/invitation.repository'; @@ -40,6 +37,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { MessageRepository } from '../repositories/message.repository'; import { SubscriberRepository } from '../repositories/subscriber.repository'; @@ -64,7 +62,7 @@ describe('MessageController', () => { let allSubscribers: Subscriber[]; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [MessageController], imports: [ rootMongooseTestModule(installMessageFixtures), @@ -116,7 +114,6 @@ describe('MessageController', () => { getSettings: jest.fn(() => ({})), }, }, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -125,13 +122,15 @@ describe('MessageController', () => { set: jest.fn(), }, }, - LoggerService, ], - }).compile(); - messageService = module.get(MessageService); - userService = module.get(UserService); - subscriberService = module.get(SubscriberService); - messageController = module.get(MessageController); + }); + [messageService, userService, subscriberService, messageController] = + await getMocks([ + MessageService, + UserService, + SubscriberService, + MessageController, + ]); message = (await messageService.findOne({ mid: 'mid-1' }))!; sender = (await subscriberService.findOne(message.sender!))!; recipient = (await subscriberService.findOne(message.recipient!))!; diff --git a/api/src/chat/controllers/subscriber.controller.spec.ts b/api/src/chat/controllers/subscriber.controller.spec.ts index 17d1020a..32361be8 100644 --- a/api/src/chat/controllers/subscriber.controller.spec.ts +++ b/api/src/chat/controllers/subscriber.controller.spec.ts @@ -1,19 +1,16 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; -import { LoggerService } from '@/logger/logger.service'; import { InvitationRepository } from '@/user/repositories/invitation.repository'; import { RoleRepository } from '@/user/repositories/role.repository'; import { UserRepository } from '@/user/repositories/user.repository'; @@ -32,6 +29,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { SocketEventDispatcherService } from '@/websocket/services/socket-event-dispatcher.service'; import { WebsocketGateway } from '@/websocket/websocket.gateway'; @@ -56,7 +54,7 @@ describe('SubscriberController', () => { let allUsers: User[]; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [SubscriberController], imports: [ rootMongooseTestModule(installSubscriberFixtures), @@ -71,7 +69,6 @@ describe('SubscriberController', () => { ]), ], providers: [ - LoggerService, SubscriberRepository, SubscriberService, LabelService, @@ -83,17 +80,17 @@ describe('SubscriberController', () => { RoleService, RoleRepository, InvitationRepository, - EventEmitter2, AttachmentService, AttachmentRepository, ], - }).compile(); - subscriberService = module.get(SubscriberService); - labelService = module.get(LabelService); - userService = module.get(UserService); - - subscriberController = - module.get(SubscriberController); + }); + [subscriberService, labelService, userService, subscriberController] = + await getMocks([ + SubscriberService, + LabelService, + UserService, + SubscriberController, + ]); subscriber = (await subscriberService.findOne({ first_name: 'Jhon', }))!; diff --git a/api/src/chat/repositories/block.repository.spec.ts b/api/src/chat/repositories/block.repository.spec.ts index e37d7d62..7a799faf 100644 --- a/api/src/chat/repositories/block.repository.spec.ts +++ b/api/src/chat/repositories/block.repository.spec.ts @@ -1,14 +1,12 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { Model } from 'mongoose'; import { @@ -19,6 +17,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { Block, BlockModel } from '../schemas/block.schema'; import { Category, CategoryModel } from '../schemas/category.schema'; @@ -39,16 +38,18 @@ describe('BlockRepository', () => { let blockValidIds: string[]; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installBlockFixtures), MongooseModule.forFeature([BlockModel, CategoryModel, LabelModel]), ], - providers: [BlockRepository, CategoryRepository, EventEmitter2], - }).compile(); - blockRepository = module.get(BlockRepository); - categoryRepository = module.get(CategoryRepository); - blockModel = module.get>(getModelToken('Block')); + providers: [BlockRepository, CategoryRepository], + }); + [blockRepository, categoryRepository, blockModel] = await getMocks([ + BlockRepository, + CategoryRepository, + getModelToken(Block.name), + ]); validIds = ['64abc1234def567890fedcba', '64abc1234def567890fedcbc']; validCategory = '64def5678abc123490fedcba'; diff --git a/api/src/chat/repositories/label.repository.spec.ts b/api/src/chat/repositories/label.repository.spec.ts index cd3d3ab5..a04eb2bc 100644 --- a/api/src/chat/repositories/label.repository.spec.ts +++ b/api/src/chat/repositories/label.repository.spec.ts @@ -6,12 +6,9 @@ * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { Model } from 'mongoose'; -import { LoggerService } from '@/logger/logger.service'; import { labelFixtures } from '@/utils/test/fixtures/label'; import { installSubscriberFixtures } from '@/utils/test/fixtures/subscriber'; import { getPageQuery } from '@/utils/test/pagination'; @@ -20,6 +17,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { Label, LabelFull, LabelModel } from '../schemas/label.schema'; import { Subscriber, SubscriberModel } from '../schemas/subscriber.schema'; @@ -34,22 +32,18 @@ describe('LabelRepository', () => { let users: Subscriber[]; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installSubscriberFixtures), MongooseModule.forFeature([LabelModel, SubscriberModel]), ], - providers: [ - LabelRepository, - SubscriberRepository, - EventEmitter2, - LoggerService, - ], - }).compile(); - labelRepository = module.get(LabelRepository); - subscriberRepository = - module.get(SubscriberRepository); - labelModel = module.get>(getModelToken('Label')); + providers: [LabelRepository, SubscriberRepository], + }); + [labelRepository, subscriberRepository, labelModel] = await getMocks([ + LabelRepository, + SubscriberRepository, + getModelToken(Label.name), + ]); users = await subscriberRepository.findAll(); }); diff --git a/api/src/chat/repositories/message.repository.spec.ts b/api/src/chat/repositories/message.repository.spec.ts index f817f2a9..784df2cd 100644 --- a/api/src/chat/repositories/message.repository.spec.ts +++ b/api/src/chat/repositories/message.repository.spec.ts @@ -1,14 +1,12 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { Model } from 'mongoose'; import { UserRepository } from '@/user/repositories/user.repository'; @@ -22,6 +20,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { Message, MessageModel } from '../schemas/message.schema'; import { SubscriberModel } from '../schemas/subscriber.schema'; @@ -37,23 +36,20 @@ describe('MessageRepository', () => { let messageModel: Model; beforeAll(async () => { - const testModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installMessageFixtures), MongooseModule.forFeature([MessageModel, SubscriberModel, UserModel]), ], - providers: [ + providers: [MessageRepository, SubscriberRepository, UserRepository], + }); + [messageRepository, userRepository, subscriberRepository, messageModel] = + await getMocks([ MessageRepository, - SubscriberRepository, UserRepository, - EventEmitter2, - ], - }).compile(); - messageRepository = testModule.get(MessageRepository); - userRepository = testModule.get(UserRepository); - subscriberRepository = - testModule.get(SubscriberRepository); - messageModel = testModule.get>(getModelToken('Message')); + SubscriberRepository, + getModelToken(Message.name), + ]); }); afterEach(jest.clearAllMocks); diff --git a/api/src/chat/repositories/subscriber.repository.spec.ts b/api/src/chat/repositories/subscriber.repository.spec.ts index 21d77f60..2b2c925f 100644 --- a/api/src/chat/repositories/subscriber.repository.spec.ts +++ b/api/src/chat/repositories/subscriber.repository.spec.ts @@ -8,7 +8,6 @@ import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { Model } from 'mongoose'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; @@ -17,7 +16,6 @@ import { AttachmentModel, } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; -import { LoggerService } from '@/logger/logger.service'; import { UserRepository } from '@/user/repositories/user.repository'; import { User, UserModel } from '@/user/schemas/user.schema'; import { @@ -30,6 +28,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { Label, LabelModel } from '../schemas/label.schema'; import { @@ -55,7 +54,7 @@ describe('SubscriberRepository', () => { let eventEmitter: EventEmitter2; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installSubscriberFixtures), MongooseModule.forFeature([ @@ -69,21 +68,26 @@ describe('SubscriberRepository', () => { SubscriberRepository, LabelRepository, UserRepository, - EventEmitter2, - LoggerService, AttachmentService, AttachmentRepository, ], - }).compile(); - subscriberRepository = - module.get(SubscriberRepository); - labelRepository = module.get(LabelRepository); - userRepository = module.get(UserRepository); - attachmentRepository = - module.get(AttachmentRepository); - subscriberModel = module.get>( - getModelToken('Subscriber'), - ); + }); + [ + subscriberRepository, + labelRepository, + userRepository, + attachmentRepository, + subscriberModel, + eventEmitter, + ] = await getMocks([ + SubscriberRepository, + LabelRepository, + UserRepository, + AttachmentRepository, + getModelToken(Subscriber.name), + EventEmitter2, + ]); + allLabels = await labelRepository.findAll(); allSubscribers = await subscriberRepository.findAll(); allUsers = await userRepository.findAll(); @@ -95,7 +99,6 @@ describe('SubscriberRepository', () => { allUsers.find(({ id }) => subscriber.assignedTo === id) || null, avatar: allAttachments.find(({ id }) => subscriber.avatar === id) || null, })); - eventEmitter = module.get(EventEmitter2); }); afterEach(jest.clearAllMocks); diff --git a/api/src/chat/services/block.service.spec.ts b/api/src/chat/services/block.service.spec.ts index eb15829f..7fc116a9 100644 --- a/api/src/chat/services/block.service.spec.ts +++ b/api/src/chat/services/block.service.spec.ts @@ -7,9 +7,7 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; @@ -33,7 +31,6 @@ import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { LanguageModel } from '@/i18n/schemas/language.schema'; import { I18nService } from '@/i18n/services/i18n.service'; import { LanguageService } from '@/i18n/services/language.service'; -import { LoggerService } from '@/logger/logger.service'; import { PluginService } from '@/plugins/plugins.service'; import { SettingService } from '@/setting/services/setting.service'; import { @@ -58,6 +55,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { BlockRepository } from '../repositories/block.repository'; import { Block, BlockModel } from '../schemas/block.schema'; @@ -85,7 +83,7 @@ describe('BlockService', () => { let settings: Settings; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(async () => { await installContentFixtures(); @@ -118,7 +116,6 @@ describe('BlockService', () => { provide: PluginService, useValue: {}, }, - LoggerService, { provide: I18nService, useValue: { @@ -138,7 +135,6 @@ describe('BlockService', () => { })), }, }, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -148,13 +144,22 @@ describe('BlockService', () => { }, }, ], - }).compile(); - blockService = module.get(BlockService); - contentService = module.get(ContentService); - settingService = module.get(SettingService); - contentTypeService = module.get(ContentTypeService); - categoryRepository = module.get(CategoryRepository); - blockRepository = module.get(BlockRepository); + }); + [ + blockService, + contentService, + settingService, + contentTypeService, + categoryRepository, + blockRepository, + ] = await getMocks([ + BlockService, + ContentService, + SettingService, + ContentTypeService, + CategoryRepository, + BlockRepository, + ]); category = (await categoryRepository.findOne({ label: 'default' }))!; hasPreviousBlocks = (await blockRepository.findOne({ name: 'hasPreviousBlocks', diff --git a/api/src/chat/services/bot.service.spec.ts b/api/src/chat/services/bot.service.spec.ts index 94aca978..794f6420 100644 --- a/api/src/chat/services/bot.service.spec.ts +++ b/api/src/chat/services/bot.service.spec.ts @@ -10,7 +10,6 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { JwtModule } from '@nestjs/jwt'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; @@ -34,7 +33,6 @@ import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { LanguageModel } from '@/i18n/schemas/language.schema'; import { I18nService } from '@/i18n/services/i18n.service'; import { LanguageService } from '@/i18n/services/language.service'; -import { LoggerService } from '@/logger/logger.service'; import { PluginService } from '@/plugins/plugins.service'; import { SettingService } from '@/setting/services/setting.service'; import { installBlockFixtures } from '@/utils/test/fixtures/block'; @@ -44,6 +42,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { SocketEventDispatcherService } from '@/websocket/services/socket-event-dispatcher.service'; import { WebsocketGateway } from '@/websocket/websocket.gateway'; @@ -81,7 +80,7 @@ describe('BlockService', () => { let eventEmitter: EventEmitter2; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(async () => { await installSubscriberFixtures(); @@ -105,7 +104,6 @@ describe('BlockService', () => { JwtModule, ], providers: [ - EventEmitter2, BlockRepository, CategoryRepository, WebsocketGateway, @@ -141,7 +139,6 @@ describe('BlockService', () => { provide: PluginService, useValue: {}, }, - LoggerService, { provide: I18nService, useValue: { @@ -168,12 +165,15 @@ describe('BlockService', () => { }, }, ], - }).compile(); - subscriberService = module.get(SubscriberService); - botService = module.get(BotService); - blockService = module.get(BlockService); - eventEmitter = module.get(EventEmitter2); - handler = module.get(WebChannelHandler); + }); + [subscriberService, botService, blockService, eventEmitter, handler] = + await getMocks([ + SubscriberService, + BotService, + BlockService, + EventEmitter2, + WebChannelHandler, + ]); }); afterEach(jest.clearAllMocks); diff --git a/api/src/chat/services/label.service.spec.ts b/api/src/chat/services/label.service.spec.ts index 0164160d..589bd33f 100644 --- a/api/src/chat/services/label.service.spec.ts +++ b/api/src/chat/services/label.service.spec.ts @@ -6,14 +6,11 @@ * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; -import { LoggerService } from '@/logger/logger.service'; import { installLabelFixtures, labelFixtures, @@ -24,6 +21,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { LabelRepository } from '../repositories/label.repository'; import { Label, LabelFull, LabelModel } from '../schemas/label.schema'; @@ -42,7 +40,7 @@ describe('LabelService', () => { let labelsWithUsers: LabelFull[]; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installLabelFixtures), MongooseModule.forFeature([ @@ -52,20 +50,19 @@ describe('LabelService', () => { ]), ], providers: [ - LoggerService, LabelService, LabelRepository, SubscriberService, AttachmentService, AttachmentRepository, SubscriberRepository, - EventEmitter2, ], - }).compile(); - labelService = module.get(LabelService); - labelRepository = module.get(LabelRepository); - subscriberRepository = - module.get(SubscriberRepository); + }); + [labelService, labelRepository, subscriberRepository] = await getMocks([ + LabelService, + LabelRepository, + SubscriberRepository, + ]); allSubscribers = await subscriberRepository.findAll(); allLabels = await labelRepository.findAll(); labelsWithUsers = allLabels.map((label) => ({ diff --git a/api/src/chat/services/message.service.spec.ts b/api/src/chat/services/message.service.spec.ts index fc48b8d1..8952c244 100644 --- a/api/src/chat/services/message.service.spec.ts +++ b/api/src/chat/services/message.service.spec.ts @@ -1,19 +1,16 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; -import { LoggerService } from '@/logger/logger.service'; import { InvitationRepository } from '@/user/repositories/invitation.repository'; import { RoleRepository } from '@/user/repositories/role.repository'; import { UserRepository } from '@/user/repositories/user.repository'; @@ -33,6 +30,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { MessageRepository } from '../repositories/message.repository'; import { Message, MessageModel } from '../schemas/message.schema'; @@ -57,7 +55,7 @@ describe('MessageService', () => { let user: User; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installMessageFixtures), MongooseModule.forFeature([ @@ -71,7 +69,6 @@ describe('MessageService', () => { ]), ], providers: [ - LoggerService, AttachmentService, AttachmentRepository, UserService, @@ -83,14 +80,15 @@ describe('MessageService', () => { SubscriberRepository, MessageService, MessageRepository, - EventEmitter2, ], - }).compile(); - messageService = module.get(MessageService); - messageRepository = module.get(MessageRepository); - subscriberRepository = - module.get(SubscriberRepository); - userRepository = module.get(UserRepository); + }); + [messageService, messageRepository, subscriberRepository, userRepository] = + await getMocks([ + MessageService, + MessageRepository, + SubscriberRepository, + UserRepository, + ]); allSubscribers = await subscriberRepository.findAll(); allUsers = await userRepository.findAll(); allMessages = await messageRepository.findAll(); diff --git a/api/src/chat/services/subscriber.service.spec.ts b/api/src/chat/services/subscriber.service.spec.ts index 69e38946..3bd3104c 100644 --- a/api/src/chat/services/subscriber.service.spec.ts +++ b/api/src/chat/services/subscriber.service.spec.ts @@ -1,19 +1,16 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; -import { LoggerService } from '@/logger/logger.service'; import { InvitationRepository } from '@/user/repositories/invitation.repository'; import { RoleRepository } from '@/user/repositories/role.repository'; import { UserRepository } from '@/user/repositories/user.repository'; @@ -30,6 +27,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { LabelRepository } from '../repositories/label.repository'; import { SubscriberRepository } from '../repositories/subscriber.repository'; @@ -49,7 +47,7 @@ describe('SubscriberService', () => { let allUsers: User[]; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installSubscriberFixtures), MongooseModule.forFeature([ @@ -72,17 +70,17 @@ describe('SubscriberService', () => { RoleService, RoleRepository, InvitationRepository, - LoggerService, - EventEmitter2, AttachmentService, AttachmentRepository, ], - }).compile(); - labelRepository = module.get(LabelRepository); - userRepository = module.get(UserRepository); - subscriberService = module.get(SubscriberService); - subscriberRepository = - module.get(SubscriberRepository); + }); + [labelRepository, userRepository, subscriberService, subscriberRepository] = + await getMocks([ + LabelRepository, + UserRepository, + SubscriberService, + SubscriberRepository, + ]); allSubscribers = await subscriberRepository.findAll(); allLabels = await labelRepository.findAll(); allUsers = await userRepository.findAll(); diff --git a/api/src/cms/controllers/content-type.controller.spec.ts b/api/src/cms/controllers/content-type.controller.spec.ts index 88dd5e74..14dc871c 100644 --- a/api/src/cms/controllers/content-type.controller.spec.ts +++ b/api/src/cms/controllers/content-type.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,15 +7,12 @@ */ import { NotFoundException } from '@nestjs/common/exceptions'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; import { BlockService } from '@/chat/services/block.service'; -import { LoggerService } from '@/logger/logger.service'; import { NOT_FOUND_ID } from '@/utils/constants/mock'; import { getUpdateOneError } from '@/utils/test/errors/messages'; import { installContentFixtures } from '@/utils/test/fixtures/content'; @@ -25,6 +22,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { ContentTypeCreateDto } from '../dto/contentType.dto'; import { ContentTypeRepository } from '../repositories/content-type.repository'; @@ -44,7 +42,7 @@ describe('ContentTypeController', () => { let blockService: BlockService; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [ContentTypeController], imports: [ rootMongooseTestModule(installContentFixtures), @@ -61,8 +59,6 @@ describe('ContentTypeController', () => { ContentTypeService, ContentService, AttachmentService, - LoggerService, - EventEmitter2, { provide: BlockService, useValue: { @@ -70,13 +66,14 @@ describe('ContentTypeController', () => { }, }, ], - }).compile(); - blockService = module.get(BlockService); - contentTypeController = module.get( - ContentTypeController, - ); - contentTypeService = module.get(ContentTypeService); - contentService = module.get(ContentService); + }); + [blockService, contentTypeController, contentTypeService, contentService] = + await getMocks([ + BlockService, + ContentTypeController, + ContentTypeService, + ContentService, + ]); contentType = await contentTypeService.findOne({ name: 'Product' })!; }); diff --git a/api/src/cms/controllers/content.controller.spec.ts b/api/src/cms/controllers/content.controller.spec.ts index b2fc47a5..8d8c11a0 100644 --- a/api/src/cms/controllers/content.controller.spec.ts +++ b/api/src/cms/controllers/content.controller.spec.ts @@ -7,11 +7,8 @@ */ import { NotFoundException } from '@nestjs/common/exceptions'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; -import { LoggerService } from '@/logger/logger.service'; import { NOT_FOUND_ID } from '@/utils/constants/mock'; import { PageQueryDto } from '@/utils/pagination/pagination-query.dto'; import { IGNORED_TEST_FIELDS } from '@/utils/test/constants'; @@ -25,6 +22,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { ContentCreateDto } from '../dto/content.dto'; import { ContentTypeRepository } from '../repositories/content-type.repository'; @@ -46,24 +44,24 @@ describe('ContentController', () => { let pageQuery: PageQueryDto; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [ContentController], imports: [ rootMongooseTestModule(installContentFixtures), MongooseModule.forFeature([ContentTypeModel, ContentModel]), ], providers: [ - LoggerService, ContentTypeService, ContentService, ContentRepository, ContentTypeRepository, - EventEmitter2, ], - }).compile(); - contentController = module.get(ContentController); - contentService = module.get(ContentService); - contentTypeService = module.get(ContentTypeService); + }); + [contentController, contentService, contentTypeService] = await getMocks([ + ContentController, + ContentService, + ContentTypeService, + ]); contentType = await contentTypeService.findOne({ name: 'Product' }); content = await contentService.findOne({ title: 'Jean', diff --git a/api/src/cms/controllers/menu.controller.spec.ts b/api/src/cms/controllers/menu.controller.spec.ts index 37464af3..67f00259 100644 --- a/api/src/cms/controllers/menu.controller.spec.ts +++ b/api/src/cms/controllers/menu.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,11 +7,8 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; -import { LoggerService } from '@/logger/logger.service'; import { installMenuFixtures, offerMenuFixture, @@ -22,6 +19,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { MenuRepository } from '../repositories/menu.repository'; import { MenuModel } from '../schemas/menu.schema'; @@ -35,7 +33,7 @@ describe('MenuController', () => { let menuController: MenuController; let menuService: MenuService; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installMenuFixtures), MongooseModule.forFeature([MenuModel]), @@ -43,7 +41,6 @@ describe('MenuController', () => { providers: [ MenuRepository, MenuService, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -52,12 +49,13 @@ describe('MenuController', () => { set: jest.fn(), }, }, - LoggerService, ], controllers: [MenuController], - }).compile(); - menuController = module.get(MenuController); - menuService = module.get(MenuService); + }); + [menuController, menuService] = await getMocks([ + MenuController, + MenuService, + ]); }); afterAll(closeInMongodConnection); diff --git a/api/src/cms/repositories/content-type.repository.spec.ts b/api/src/cms/repositories/content-type.repository.spec.ts index cb8f380a..e3b84f87 100644 --- a/api/src/cms/repositories/content-type.repository.spec.ts +++ b/api/src/cms/repositories/content-type.repository.spec.ts @@ -1,14 +1,12 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { Model } from 'mongoose'; import { BlockRepository } from '@/chat/repositories/block.repository'; @@ -18,11 +16,11 @@ import { ContentType, ContentTypeModel, } from '@/cms/schemas/content-type.schema'; -import { LoggerService } from '@/logger/logger.service'; import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { Content, ContentModel } from '../schemas/content.schema'; @@ -37,13 +35,12 @@ describe('ContentTypeRepository', () => { let blockService: BlockService; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installContentFixtures), MongooseModule.forFeature([ContentTypeModel, ContentModel, BlockModel]), ], providers: [ - LoggerService, ContentRepository, ContentTypeRepository, BlockService, @@ -54,18 +51,15 @@ describe('ContentTypeRepository', () => { findOne: jest.fn(), }, }, - EventEmitter2, ], - }).compile(); - blockService = module.get(BlockService); - contentTypeRepository = module.get( - ContentTypeRepository, - ); - contentTypeModel = module.get>( - getModelToken('ContentType'), - ); - - contentModel = module.get>(getModelToken('Content')); + }); + [blockService, contentTypeRepository, contentTypeModel, contentModel] = + await getMocks([ + BlockService, + ContentTypeRepository, + getModelToken(ContentType.name), + getModelToken(Content.name), + ]); }); afterAll(closeInMongodConnection); diff --git a/api/src/cms/repositories/content.repository.spec.ts b/api/src/cms/repositories/content.repository.spec.ts index 9c26495f..29fc1a4c 100644 --- a/api/src/cms/repositories/content.repository.spec.ts +++ b/api/src/cms/repositories/content.repository.spec.ts @@ -1,27 +1,25 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { Model } from 'mongoose'; import { ContentType, ContentTypeModel, } from '@/cms/schemas/content-type.schema'; -import { LoggerService } from '@/logger/logger.service'; import { contentTypeFixtures } from '@/utils/test/fixtures/contenttype'; import { getPageQuery } from '@/utils/test/pagination'; import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { Content, ContentModel } from '../schemas/content.schema'; @@ -37,18 +35,18 @@ describe('ContentRepository', () => { let contentTypeModel: Model; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installContentFixtures), MongooseModule.forFeature([ContentTypeModel, ContentModel]), ], - providers: [LoggerService, ContentRepository, EventEmitter2], - }).compile(); - contentRepository = module.get(ContentRepository); - contentModel = module.get>(getModelToken('Content')); - contentTypeModel = module.get>( - getModelToken('ContentType'), - ); + providers: [ContentRepository], + }); + [contentRepository, contentModel, contentTypeModel] = await getMocks([ + ContentRepository, + getModelToken(Content.name), + getModelToken(ContentType.name), + ]); }); afterAll(closeInMongodConnection); diff --git a/api/src/cms/repositories/menu.reporsitory.spec.ts b/api/src/cms/repositories/menu.reporsitory.spec.ts index 688d81c3..8909c15d 100644 --- a/api/src/cms/repositories/menu.reporsitory.spec.ts +++ b/api/src/cms/repositories/menu.reporsitory.spec.ts @@ -1,14 +1,12 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { installMenuFixtures, @@ -18,6 +16,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { MenuModel } from '../schemas/menu.schema'; import { MenuType } from '../schemas/types/menu'; @@ -27,19 +26,18 @@ import { MenuRepository } from './menu.repository'; describe('MenuRepository', () => { let menuRepository: MenuRepository; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installMenuFixtures), MongooseModule.forFeature([MenuModel]), ], - providers: [MenuRepository, EventEmitter2], - }).compile(); - menuRepository = module.get(MenuRepository); - }); - afterAll(async () => { - await closeInMongodConnection(); + providers: [MenuRepository], + }); + [menuRepository] = await getMocks([MenuRepository]); }); + afterAll(closeInMongodConnection); + afterEach(jest.clearAllMocks); describe('findOneAndPopulate', () => { diff --git a/api/src/cms/services/content-type.service.spec.ts b/api/src/cms/services/content-type.service.spec.ts index b8c529d7..4abbf29e 100644 --- a/api/src/cms/services/content-type.service.spec.ts +++ b/api/src/cms/services/content-type.service.spec.ts @@ -1,25 +1,23 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; import { BlockService } from '@/chat/services/block.service'; -import { LoggerService } from '@/logger/logger.service'; import { installContentFixtures } from '@/utils/test/fixtures/content'; import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { ContentTypeRepository } from '../repositories/content-type.repository'; import { ContentRepository } from '../repositories/content.repository'; @@ -36,7 +34,7 @@ describe('ContentTypeService', () => { let blockService: BlockService; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installContentFixtures), MongooseModule.forFeature([ @@ -52,8 +50,6 @@ describe('ContentTypeService', () => { ContentTypeService, ContentService, AttachmentService, - LoggerService, - EventEmitter2, { provide: BlockService, useValue: { @@ -61,18 +57,17 @@ describe('ContentTypeService', () => { }, }, ], - }).compile(); - blockService = module.get(BlockService); - contentTypeService = module.get(ContentTypeService); - contentService = module.get(ContentService); - contentTypeRepository = module.get( - ContentTypeRepository, - ); + }); + [blockService, contentTypeService, contentService, contentTypeRepository] = + await getMocks([ + BlockService, + ContentTypeService, + ContentService, + ContentTypeRepository, + ]); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/cms/services/content.service.spec.ts b/api/src/cms/services/content.service.spec.ts index 901fb8b7..ec2bcd8a 100644 --- a/api/src/cms/services/content.service.spec.ts +++ b/api/src/cms/services/content.service.spec.ts @@ -6,13 +6,10 @@ * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { OutgoingMessageFormat } from '@/chat/schemas/types/message'; import { ContentOptions } from '@/chat/schemas/types/options'; -import { LoggerService } from '@/logger/logger.service'; import { IGNORED_TEST_FIELDS } from '@/utils/test/constants'; import { contentFixtures, @@ -23,6 +20,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { ContentTypeRepository } from '../repositories/content-type.repository'; import { ContentRepository } from '../repositories/content.repository'; @@ -38,7 +36,7 @@ describe('ContentService', () => { let contentRepository: ContentRepository; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installContentFixtures), MongooseModule.forFeature([ContentTypeModel, ContentModel]), @@ -48,18 +46,16 @@ describe('ContentService', () => { ContentRepository, ContentTypeService, ContentService, - LoggerService, - EventEmitter2, ], - }).compile(); - contentService = module.get(ContentService); - contentTypeService = module.get(ContentTypeService); - contentRepository = module.get(ContentRepository); + }); + [contentService, contentTypeService, contentRepository] = await getMocks([ + ContentService, + ContentTypeService, + ContentRepository, + ]); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/cms/services/menu.service.spec.ts b/api/src/cms/services/menu.service.spec.ts index 40cc2503..5883a4eb 100644 --- a/api/src/cms/services/menu.service.spec.ts +++ b/api/src/cms/services/menu.service.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -8,11 +8,8 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { NotFoundException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; -import { LoggerService } from '@/logger/logger.service'; import { installMenuFixtures, rootMenuFixtures, @@ -21,6 +18,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { MenuRepository } from '../repositories/menu.repository'; import { MenuModel } from '../schemas/menu.schema'; @@ -33,7 +31,7 @@ describe('MenuService', () => { let menuService: MenuService; let menuRepository: MenuRepository; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installMenuFixtures), MongooseModule.forFeature([MenuModel]), @@ -41,7 +39,6 @@ describe('MenuService', () => { providers: [ MenuRepository, MenuService, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -50,16 +47,16 @@ describe('MenuService', () => { set: jest.fn(), }, }, - LoggerService, ], - }).compile(); - menuService = module.get(MenuService); - menuRepository = module.get(MenuRepository); - }); - afterAll(async () => { - await closeInMongodConnection(); + }); + [menuService, menuRepository] = await getMocks([ + MenuService, + MenuRepository, + ]); }); + afterAll(closeInMongodConnection); + afterEach(jest.clearAllMocks); describe('create', () => { it('should create the menu successfully', async () => { diff --git a/api/src/extensions/channels/web/__test__/index.spec.ts b/api/src/extensions/channels/web/__test__/index.spec.ts index 548f2969..a977b03b 100644 --- a/api/src/extensions/channels/web/__test__/index.spec.ts +++ b/api/src/extensions/channels/web/__test__/index.spec.ts @@ -7,10 +7,8 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { JwtModule } from '@nestjs/jwt'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { Request } from 'express'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; @@ -36,7 +34,6 @@ import { MenuRepository } from '@/cms/repositories/menu.repository'; import { MenuModel } from '@/cms/schemas/menu.schema'; import { MenuService } from '@/cms/services/menu.service'; import { I18nService } from '@/i18n/services/i18n.service'; -import { LoggerService } from '@/logger/logger.service'; import { SettingService } from '@/setting/services/setting.service'; import { UserModel } from '@/user/schemas/user.schema'; import { installMessageFixtures } from '@/utils/test/fixtures/message'; @@ -44,6 +41,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { SocketEventDispatcherService } from '@/websocket/services/socket-event-dispatcher.service'; import { SocketRequest } from '@/websocket/utils/socket-request'; import { SocketResponse } from '@/websocket/utils/socket-response'; @@ -66,7 +64,7 @@ describe('WebChannelHandler', () => { const webSettings = {}; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(async () => { await installMessageFixtures(); @@ -105,8 +103,6 @@ describe('WebChannelHandler', () => { MenuService, MenuRepository, WebChannelHandler, - EventEmitter2, - LoggerService, { provide: I18nService, useValue: { @@ -122,9 +118,11 @@ describe('WebChannelHandler', () => { }, }, ], - }).compile(); - subscriberService = module.get(SubscriberService); - handler = module.get(WebChannelHandler); + }); + [subscriberService, handler] = await getMocks([ + SubscriberService, + WebChannelHandler, + ]); jest .spyOn(handler, 'getPublicUrl') diff --git a/api/src/extensions/channels/web/__test__/wrapper.spec.ts b/api/src/extensions/channels/web/__test__/wrapper.spec.ts index d219834b..4f6d5ca7 100644 --- a/api/src/extensions/channels/web/__test__/wrapper.spec.ts +++ b/api/src/extensions/channels/web/__test__/wrapper.spec.ts @@ -7,10 +7,8 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { JwtModule } from '@nestjs/jwt'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { @@ -33,7 +31,6 @@ import { MenuRepository } from '@/cms/repositories/menu.repository'; import { MenuModel } from '@/cms/schemas/menu.schema'; import { MenuService } from '@/cms/services/menu.service'; import { I18nService } from '@/i18n/services/i18n.service'; -import { LoggerService } from '@/logger/logger.service'; import { NlpService } from '@/nlp/services/nlp.service'; import { SettingService } from '@/setting/services/setting.service'; import { installSubscriberFixtures } from '@/utils/test/fixtures/subscriber'; @@ -41,6 +38,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { SocketEventDispatcherService } from '@/websocket/services/socket-event-dispatcher.service'; import { WebsocketGateway } from '@/websocket/websocket.gateway'; @@ -54,11 +52,9 @@ describe(`Web event wrapper`, () => { let handler: WebChannelHandler; const webSettings = {}; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ - rootMongooseTestModule(async () => { - await installSubscriberFixtures(); - }), + rootMongooseTestModule(installSubscriberFixtures), MongooseModule.forFeature([ SubscriberModel, AttachmentModel, @@ -97,8 +93,6 @@ describe(`Web event wrapper`, () => { MenuService, MenuRepository, WebChannelHandler, - EventEmitter2, - LoggerService, { provide: I18nService, useValue: { @@ -114,8 +108,8 @@ describe(`Web event wrapper`, () => { }, }, ], - }).compile(); - handler = module.get(WebChannelHandler); + }); + [handler] = await getMocks([WebChannelHandler]); }); afterAll(async () => { diff --git a/api/src/i18n/controllers/language.controller.spec.ts b/api/src/i18n/controllers/language.controller.spec.ts index e8aaf8df..d2c29039 100644 --- a/api/src/i18n/controllers/language.controller.spec.ts +++ b/api/src/i18n/controllers/language.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -8,12 +8,9 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { BadRequestException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { I18nService } from '@/i18n/services/i18n.service'; -import { LoggerService } from '@/logger/logger.service'; import { NOT_FOUND_ID } from '@/utils/constants/mock'; import { getUpdateOneError } from '@/utils/test/errors/messages'; import { @@ -25,6 +22,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { LanguageUpdateDto } from '../dto/language.dto'; import { LanguageRepository } from '../repositories/language.repository'; @@ -39,7 +37,7 @@ describe('LanguageController', () => { let language: Language; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installLanguageFixtures), MongooseModule.forFeature([LanguageModel]), @@ -48,7 +46,6 @@ describe('LanguageController', () => { LanguageController, LanguageService, LanguageRepository, - LoggerService, { provide: I18nService, useValue: { @@ -64,12 +61,12 @@ describe('LanguageController', () => { set: jest.fn(), }, }, - LoggerService, - EventEmitter2, ], - }).compile(); - languageService = module.get(LanguageService); - languageController = module.get(LanguageController); + }); + [languageService, languageController] = await getMocks([ + LanguageService, + LanguageController, + ]); language = (await languageService.findOne({ code: 'en' })) as Language; }); diff --git a/api/src/i18n/controllers/translation.controller.spec.ts b/api/src/i18n/controllers/translation.controller.spec.ts index 70fbdcf0..06dabf28 100644 --- a/api/src/i18n/controllers/translation.controller.spec.ts +++ b/api/src/i18n/controllers/translation.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,9 +7,7 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; @@ -32,7 +30,6 @@ import { MenuModel } from '@/cms/schemas/menu.schema'; import { ContentService } from '@/cms/services/content.service'; import { MenuService } from '@/cms/services/menu.service'; import { I18nService } from '@/i18n/services/i18n.service'; -import { LoggerService } from '@/logger/logger.service'; import { NlpService } from '@/nlp/services/nlp.service'; import { PluginService } from '@/plugins/plugins.service'; import { SettingService } from '@/setting/services/setting.service'; @@ -47,6 +44,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { TranslationUpdateDto } from '../dto/translation.dto'; import { LanguageRepository } from '../repositories/language.repository'; @@ -64,7 +62,7 @@ describe('TranslationController', () => { let translation: Translation; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [MessageController], imports: [ rootMongooseTestModule(installTranslationFixtures), @@ -115,8 +113,6 @@ describe('TranslationController', () => { provide: PluginService, useValue: {}, }, - EventEmitter2, - LoggerService, { provide: I18nService, useValue: { @@ -132,15 +128,14 @@ describe('TranslationController', () => { set: jest.fn(), }, }, - LoggerService, LanguageService, LanguageRepository, ], - }).compile(); - translationService = module.get(TranslationService); - translationController = module.get( + }); + [translationService, translationController] = await getMocks([ + TranslationService, TranslationController, - ); + ]); translation = (await translationService.findOne({ str: 'Welcome', })) as Translation; diff --git a/api/src/i18n/services/translation.service.spec.ts b/api/src/i18n/services/translation.service.spec.ts index 9e7a0565..b3bc3e17 100644 --- a/api/src/i18n/services/translation.service.spec.ts +++ b/api/src/i18n/services/translation.service.spec.ts @@ -6,15 +6,13 @@ * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; -import { Test, TestingModule } from '@nestjs/testing'; - import { I18nService } from '@/i18n/services/i18n.service'; import { BasePlugin } from '@/plugins/base-plugin.service'; import { PluginService } from '@/plugins/plugins.service'; import { PluginBlockTemplate } from '@/plugins/types'; import { SettingType } from '@/setting/schemas/types'; import { SettingService } from '@/setting/services/setting.service'; +import { buildTestingMocks } from '@/utils/test/utils'; import { Block } from '../../chat/schemas/block.schema'; import { BlockOptions } from '../../chat/schemas/types/options'; @@ -24,11 +22,11 @@ import { TranslationService } from '../services/translation.service'; describe('TranslationService', () => { let service: TranslationService; - let i18nService: I18nService; + let i18nService: I18nService; let pluginService: PluginService; beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ providers: [ TranslationService, { @@ -106,13 +104,13 @@ describe('TranslationService', () => { refreshDynamicTranslations: jest.fn(), }, }, - EventEmitter2, ], - }).compile(); - - service = module.get(TranslationService); - i18nService = module.get(I18nService); - pluginService = module.get(PluginService); + }); + [service, i18nService, pluginService] = await getMocks([ + TranslationService, + I18nService, + PluginService, + ]); }); it('should call refreshDynamicTranslations with translations from findAll', async () => { diff --git a/api/src/migration/migration.service.spec.ts b/api/src/migration/migration.service.spec.ts index 1abd7464..d58ddcbf 100644 --- a/api/src/migration/migration.service.spec.ts +++ b/api/src/migration/migration.service.spec.ts @@ -10,9 +10,7 @@ import fs from 'fs'; import { HttpService } from '@nestjs/axios'; import { ModuleRef } from '@nestjs/core'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { getModelToken, MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { AttachmentService } from '@/attachment/services/attachment.service'; import { LoggerService } from '@/logger/logger.service'; @@ -23,6 +21,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { Migration, MigrationModel } from './migration.schema'; import { MigrationService } from './migration.service'; @@ -34,7 +33,7 @@ describe('MigrationService', () => { let metadataService: MetadataService; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks, resolveMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(async () => await Promise.resolve()), MongooseModule.forFeature([MetadataModel, MigrationModel]), @@ -43,7 +42,6 @@ describe('MigrationService', () => { MetadataRepository, MetadataService, MigrationService, - EventEmitter2, { provide: LoggerService, useValue: { @@ -74,11 +72,12 @@ describe('MigrationService', () => { useValue: jest.fn(), }, ], - }).compile(); - - service = module.get(MigrationService); - loggerService = await module.resolve(LoggerService); - metadataService = module.get(MetadataService); + }); + [service, metadataService] = await getMocks([ + MigrationService, + MetadataService, + ]); + [loggerService] = await resolveMocks([LoggerService]); }); afterEach(jest.clearAllMocks); diff --git a/api/src/nlp/controllers/nlp-entity.controller.spec.ts b/api/src/nlp/controllers/nlp-entity.controller.spec.ts index d678dcac..c1334ef9 100644 --- a/api/src/nlp/controllers/nlp-entity.controller.spec.ts +++ b/api/src/nlp/controllers/nlp-entity.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -11,11 +11,8 @@ import { MethodNotAllowedException, NotFoundException, } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; -import { LoggerService } from '@/logger/logger.service'; import { IGNORED_TEST_FIELDS } from '@/utils/test/constants'; import { nlpEntityFixtures } from '@/utils/test/fixtures/nlpentity'; import { @@ -28,6 +25,7 @@ import { rootMongooseTestModule, } from '@/utils/test/test'; import { TFixtures } from '@/utils/test/types'; +import { buildTestingMocks } from '@/utils/test/utils'; import { NlpEntityCreateDto } from '../dto/nlp-entity.dto'; import { NlpEntityRepository } from '../repositories/nlp-entity.repository'; @@ -53,7 +51,7 @@ describe('NlpEntityController', () => { let buitInEntityId: string | null; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [NlpEntityController], imports: [ rootMongooseTestModule(installNlpValueFixtures), @@ -64,19 +62,18 @@ describe('NlpEntityController', () => { ]), ], providers: [ - LoggerService, NlpEntityService, NlpEntityRepository, NlpValueService, NlpSampleEntityRepository, NlpValueRepository, - EventEmitter2, ], - }).compile(); - nlpEntityController = module.get(NlpEntityController); - nlpValueService = module.get(NlpValueService); - nlpEntityService = module.get(NlpEntityService); - + }); + [nlpEntityController, nlpValueService, nlpEntityService] = await getMocks([ + NlpEntityController, + NlpValueService, + NlpEntityService, + ]); intentEntityId = ( await nlpEntityService.findOne({ @@ -90,9 +87,8 @@ describe('NlpEntityController', () => { }) )?.id || null; }); - afterAll(async () => { - await closeInMongodConnection(); - }); + + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/nlp/controllers/nlp-sample.controller.spec.ts b/api/src/nlp/controllers/nlp-sample.controller.spec.ts index 832e21da..3a5e9c3e 100644 --- a/api/src/nlp/controllers/nlp-sample.controller.spec.ts +++ b/api/src/nlp/controllers/nlp-sample.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -8,16 +8,13 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { BadRequestException, NotFoundException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { HelperService } from '@/helper/helper.service'; import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { Language, LanguageModel } from '@/i18n/schemas/language.schema'; import { I18nService } from '@/i18n/services/i18n.service'; import { LanguageService } from '@/i18n/services/language.service'; -import { LoggerService } from '@/logger/logger.service'; import { SettingRepository } from '@/setting/repositories/setting.repository'; import { SettingModel } from '@/setting/schemas/setting.schema'; import { SettingSeeder } from '@/setting/seeds/setting.seed'; @@ -32,6 +29,7 @@ import { rootMongooseTestModule, } from '@/utils/test/test'; import { TFixtures } from '@/utils/test/types'; +import { buildTestingMocks } from '@/utils/test/utils'; import { NlpSampleDto } from '../dto/nlp-sample.dto'; import { NlpEntityRepository } from '../repositories/nlp-entity.repository'; @@ -65,7 +63,7 @@ describe('NlpSampleController', () => { let languages: Language[]; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [NlpSampleController], imports: [ rootMongooseTestModule(async () => { @@ -82,7 +80,6 @@ describe('NlpSampleController', () => { ]), ], providers: [ - LoggerService, NlpSampleRepository, NlpSampleEntityRepository, NlpEntityService, @@ -93,7 +90,6 @@ describe('NlpSampleController', () => { NlpSampleEntityService, LanguageRepository, LanguageService, - EventEmitter2, HelperService, SettingRepository, SettingService, @@ -113,26 +109,32 @@ describe('NlpSampleController', () => { }, }, ], - }).compile(); - nlpSampleController = module.get(NlpSampleController); - nlpSampleEntityService = module.get( + }); + [ + nlpSampleController, + nlpSampleEntityService, + nlpSampleService, + nlpEntityService, + nlpValueService, + languageService, + ] = await getMocks([ + NlpSampleController, NlpSampleEntityService, - ); - nlpSampleService = module.get(NlpSampleService); - nlpEntityService = module.get(NlpEntityService); - nlpValueService = module.get(NlpValueService); + NlpSampleService, + NlpEntityService, + NlpValueService, + LanguageService, + ]); byeJhonSampleId = ( await nlpSampleService.findOne({ text: 'Bye Jhon', }) )?.id || null; - languageService = module.get(LanguageService); languages = await languageService.findAll(); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/nlp/controllers/nlp-value.controller.spec.ts b/api/src/nlp/controllers/nlp-value.controller.spec.ts index d78b336f..9fa0d4c5 100644 --- a/api/src/nlp/controllers/nlp-value.controller.spec.ts +++ b/api/src/nlp/controllers/nlp-value.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,11 +7,8 @@ */ import { BadRequestException, NotFoundException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; -import { LoggerService } from '@/logger/logger.service'; import { getUpdateOneError } from '@/utils/test/errors/messages'; import { nlpEntityFixtures } from '@/utils/test/fixtures/nlpentity'; import { @@ -24,6 +21,7 @@ import { rootMongooseTestModule, } from '@/utils/test/test'; import { TFixtures } from '@/utils/test/types'; +import { buildTestingMocks } from '@/utils/test/utils'; import { NlpValueCreateDto } from '../dto/nlp-value.dto'; import { NlpEntityRepository } from '../repositories/nlp-entity.repository'; @@ -50,7 +48,7 @@ describe('NlpValueController', () => { let negativeValue: NlpValue | null; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [NlpValueController], imports: [ rootMongooseTestModule(installNlpValueFixtures), @@ -61,25 +59,24 @@ describe('NlpValueController', () => { ]), ], providers: [ - LoggerService, NlpValueRepository, NlpValueService, NlpSampleEntityRepository, NlpEntityService, NlpEntityRepository, - EventEmitter2, ], - }).compile(); - nlpValueController = module.get(NlpValueController); - nlpValueService = module.get(NlpValueService); - nlpEntityService = module.get(NlpEntityService); + }); + [nlpValueController, nlpValueService, nlpEntityService] = await getMocks([ + NlpValueController, + NlpValueService, + NlpEntityService, + ]); jhonNlpValue = await nlpValueService.findOne({ value: 'jhon' }); positiveValue = await nlpValueService.findOne({ value: 'positive' }); negativeValue = await nlpValueService.findOne({ value: 'negative' }); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/nlp/repositories/nlp-entity.repository.spec.ts b/api/src/nlp/repositories/nlp-entity.repository.spec.ts index a4bd2a17..7f9bccd3 100644 --- a/api/src/nlp/repositories/nlp-entity.repository.spec.ts +++ b/api/src/nlp/repositories/nlp-entity.repository.spec.ts @@ -1,14 +1,12 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { nlpEntityFixtures } from '@/utils/test/fixtures/nlpentity'; import { installNlpValueFixtures } from '@/utils/test/fixtures/nlpvalue'; @@ -17,6 +15,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { NlpEntity, NlpEntityModel } from '../schemas/nlp-entity.schema'; import { NlpSampleEntityModel } from '../schemas/nlp-sample-entity.schema'; @@ -32,7 +31,7 @@ describe('NlpEntityRepository', () => { let firstNameNlpEntity: NlpEntity | null; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installNlpValueFixtures), MongooseModule.forFeature([ @@ -45,19 +44,18 @@ describe('NlpEntityRepository', () => { NlpEntityRepository, NlpValueRepository, NlpSampleEntityRepository, - EventEmitter2, ], - }).compile(); - nlpEntityRepository = module.get(NlpEntityRepository); - nlpValueRepository = module.get(NlpValueRepository); + }); + [nlpEntityRepository, nlpValueRepository] = await getMocks([ + NlpEntityRepository, + NlpValueRepository, + ]); firstNameNlpEntity = await nlpEntityRepository.findOne({ name: 'first_name', }); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/nlp/repositories/nlp-sample-entity.repository.spec.ts b/api/src/nlp/repositories/nlp-sample-entity.repository.spec.ts index 50494a7b..4295c791 100644 --- a/api/src/nlp/repositories/nlp-sample-entity.repository.spec.ts +++ b/api/src/nlp/repositories/nlp-sample-entity.repository.spec.ts @@ -1,14 +1,12 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { Language, LanguageModel } from '@/i18n/schemas/language.schema'; @@ -24,6 +22,7 @@ import { rootMongooseTestModule, } from '@/utils/test/test'; import { TFixtures } from '@/utils/test/types'; +import { buildTestingMocks } from '@/utils/test/utils'; import { NlpEntity, NlpEntityModel } from '../schemas/nlp-entity.schema'; import { @@ -47,7 +46,7 @@ describe('NlpSampleEntityRepository', () => { let languages: Language[]; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installNlpSampleEntityFixtures), MongooseModule.forFeature([ @@ -63,22 +62,20 @@ describe('NlpSampleEntityRepository', () => { NlpEntityRepository, NlpValueRepository, LanguageRepository, - EventEmitter2, ], - }).compile(); - nlpSampleEntityRepository = module.get( - NlpSampleEntityRepository, - ); - nlpEntityRepository = module.get(NlpEntityRepository); - languageRepository = module.get(LanguageRepository); + }); + [nlpSampleEntityRepository, nlpEntityRepository, languageRepository] = + await getMocks([ + NlpSampleEntityRepository, + NlpEntityRepository, + LanguageRepository, + ]); nlpSampleEntities = await nlpSampleEntityRepository.findAll(); nlpEntities = await nlpEntityRepository.findAll(); languages = await languageRepository.findAll(); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/nlp/repositories/nlp-sample.repository.spec.ts b/api/src/nlp/repositories/nlp-sample.repository.spec.ts index 4c2d00c8..7aea6bc1 100644 --- a/api/src/nlp/repositories/nlp-sample.repository.spec.ts +++ b/api/src/nlp/repositories/nlp-sample.repository.spec.ts @@ -1,14 +1,12 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { Language, LanguageModel } from '@/i18n/schemas/language.schema'; @@ -20,6 +18,7 @@ import { rootMongooseTestModule, } from '@/utils/test/test'; import { TFixtures } from '@/utils/test/types'; +import { buildTestingMocks } from '@/utils/test/utils'; import { NlpSampleEntity, @@ -43,7 +42,7 @@ describe('NlpSampleRepository', () => { let languages: Language[]; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installNlpSampleEntityFixtures), MongooseModule.forFeature([ @@ -56,14 +55,14 @@ describe('NlpSampleRepository', () => { NlpSampleRepository, NlpSampleEntityRepository, LanguageRepository, - EventEmitter2, ], - }).compile(); - nlpSampleRepository = module.get(NlpSampleRepository); - nlpSampleEntityRepository = module.get( - NlpSampleEntityRepository, - ); - languageRepository = module.get(LanguageRepository); + }); + [nlpSampleRepository, nlpSampleEntityRepository, languageRepository] = + await getMocks([ + NlpSampleRepository, + NlpSampleEntityRepository, + LanguageRepository, + ]); noNlpSample = await nlpSampleRepository.findOne({ text: 'No' }); nlpSampleEntity = await nlpSampleEntityRepository.findOne({ sample: noNlpSample!.id, @@ -71,9 +70,7 @@ describe('NlpSampleRepository', () => { languages = await languageRepository.findAll(); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/nlp/repositories/nlp-value.repository.spec.ts b/api/src/nlp/repositories/nlp-value.repository.spec.ts index 0b3a7ce7..179f0e76 100644 --- a/api/src/nlp/repositories/nlp-value.repository.spec.ts +++ b/api/src/nlp/repositories/nlp-value.repository.spec.ts @@ -1,14 +1,12 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { nlpEntityFixtures } from '@/utils/test/fixtures/nlpentity'; import { installNlpSampleEntityFixtures } from '@/utils/test/fixtures/nlpsampleentity'; @@ -19,6 +17,7 @@ import { rootMongooseTestModule, } from '@/utils/test/test'; import { TFixtures } from '@/utils/test/types'; +import { buildTestingMocks } from '@/utils/test/utils'; import { NlpEntityModel } from '../schemas/nlp-entity.schema'; import { NlpSampleEntityModel } from '../schemas/nlp-sample-entity.schema'; @@ -37,7 +36,7 @@ describe('NlpValueRepository', () => { let nlpValues: NlpValue[]; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installNlpSampleEntityFixtures), MongooseModule.forFeature([ @@ -46,18 +45,17 @@ describe('NlpValueRepository', () => { NlpEntityModel, ]), ], - providers: [NlpValueRepository, NlpSampleEntityRepository, EventEmitter2], - }).compile(); - nlpValueRepository = module.get(NlpValueRepository); - nlpSampleEntityRepository = module.get( + providers: [NlpValueRepository, NlpSampleEntityRepository], + }); + [nlpValueRepository, nlpSampleEntityRepository] = await getMocks([ + NlpValueRepository, NlpSampleEntityRepository, - ); + ]); + nlpValues = await nlpValueRepository.findAll(); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/nlp/services/nlp-entity.service.spec.ts b/api/src/nlp/services/nlp-entity.service.spec.ts index 76b78233..53118e95 100644 --- a/api/src/nlp/services/nlp-entity.service.spec.ts +++ b/api/src/nlp/services/nlp-entity.service.spec.ts @@ -1,14 +1,12 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { nlpEntityFixtures } from '@/utils/test/fixtures/nlpentity'; import { installNlpValueFixtures } from '@/utils/test/fixtures/nlpvalue'; @@ -17,6 +15,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { NlpEntityRepository } from '../repositories/nlp-entity.repository'; import { NlpSampleEntityRepository } from '../repositories/nlp-sample-entity.repository'; @@ -34,7 +33,7 @@ describe('nlpEntityService', () => { let nlpValueRepository: NlpValueRepository; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installNlpValueFixtures), MongooseModule.forFeature([ @@ -49,17 +48,17 @@ describe('nlpEntityService', () => { NlpValueService, NlpValueRepository, NlpSampleEntityRepository, - EventEmitter2, ], - }).compile(); - nlpEntityService = module.get(NlpEntityService); - nlpEntityRepository = module.get(NlpEntityRepository); - nlpValueRepository = module.get(NlpValueRepository); + }); + [nlpEntityService, nlpEntityRepository, nlpValueRepository] = + await getMocks([ + NlpEntityService, + NlpEntityRepository, + NlpValueRepository, + ]); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/nlp/services/nlp-sample-entity.service.spec.ts b/api/src/nlp/services/nlp-sample-entity.service.spec.ts index dd40e848..ed2be6f1 100644 --- a/api/src/nlp/services/nlp-sample-entity.service.spec.ts +++ b/api/src/nlp/services/nlp-sample-entity.service.spec.ts @@ -6,9 +6,7 @@ * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { Language, LanguageModel } from '@/i18n/schemas/language.schema'; @@ -24,6 +22,7 @@ import { rootMongooseTestModule, } from '@/utils/test/test'; import { TFixtures } from '@/utils/test/types'; +import { buildTestingMocks } from '@/utils/test/utils'; import { NlpSampleEntityCreateDto } from '../dto/nlp-sample-entity.dto'; import { NlpEntityRepository } from '../repositories/nlp-entity.repository'; @@ -58,7 +57,7 @@ describe('NlpSampleEntityService', () => { let nlpValueService: NlpValueService; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installNlpSampleEntityFixtures), MongooseModule.forFeature([ @@ -77,22 +76,25 @@ describe('NlpSampleEntityService', () => { NlpSampleEntityService, NlpEntityService, NlpValueService, - EventEmitter2, ], - }).compile(); - nlpSampleEntityService = module.get( + }); + [ + nlpSampleEntityService, + nlpSampleEntityRepository, + nlpEntityRepository, + languageRepository, + nlpSampleEntityService, + nlpEntityService, + nlpValueService, + ] = await getMocks([ NlpSampleEntityService, - ); - nlpSampleEntityRepository = module.get( NlpSampleEntityRepository, - ); - nlpEntityRepository = module.get(NlpEntityRepository); - languageRepository = module.get(LanguageRepository); - nlpSampleEntityService = module.get( + NlpEntityRepository, + LanguageRepository, NlpSampleEntityService, - ); - nlpEntityService = module.get(NlpEntityService); - nlpValueService = module.get(NlpValueService); + NlpEntityService, + NlpValueService, + ]); nlpSampleEntities = await nlpSampleEntityRepository.findAll(); nlpEntities = await nlpEntityRepository.findAll(); languages = await languageRepository.findAll(); diff --git a/api/src/nlp/services/nlp-sample.service.spec.ts b/api/src/nlp/services/nlp-sample.service.spec.ts index ce93beb7..e24e4b47 100644 --- a/api/src/nlp/services/nlp-sample.service.spec.ts +++ b/api/src/nlp/services/nlp-sample.service.spec.ts @@ -8,14 +8,11 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { BadRequestException, NotFoundException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { Language, LanguageModel } from '@/i18n/schemas/language.schema'; import { LanguageService } from '@/i18n/services/language.service'; -import { LoggerService } from '@/logger/logger.service'; import { nlpSampleFixtures } from '@/utils/test/fixtures/nlpsample'; import { installNlpSampleEntityFixtures } from '@/utils/test/fixtures/nlpsampleentity'; import { getPageQuery } from '@/utils/test/pagination'; @@ -23,6 +20,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { NlpSampleEntityCreateDto } from '../dto/nlp-sample-entity.dto'; import { NlpEntityRepository } from '../repositories/nlp-entity.repository'; @@ -63,7 +61,7 @@ describe('NlpSampleService', () => { let languages: Language[]; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installNlpSampleEntityFixtures), MongooseModule.forFeature([ @@ -85,8 +83,7 @@ describe('NlpSampleService', () => { NlpEntityService, NlpValueService, LanguageService, - EventEmitter2, - LoggerService, + { provide: CACHE_MANAGER, useValue: { @@ -96,21 +93,26 @@ describe('NlpSampleService', () => { }, }, ], - }).compile(); - nlpEntityService = module.get(NlpEntityService); - nlpSampleService = module.get(NlpSampleService); - nlpSampleEntityService = module.get( + }); + [ + nlpEntityService, + nlpSampleService, + nlpSampleEntityService, + nlpSampleRepository, + nlpSampleEntityRepository, + nlpSampleEntityRepository, + languageService, + languageRepository, + ] = await getMocks([ + NlpEntityService, + NlpSampleService, NlpSampleEntityService, - ); - nlpSampleRepository = module.get(NlpSampleRepository); - nlpSampleEntityRepository = module.get( + NlpSampleRepository, NlpSampleEntityRepository, - ); - nlpSampleEntityRepository = module.get( NlpSampleEntityRepository, - ); - languageService = module.get(LanguageService); - languageRepository = module.get(LanguageRepository); + LanguageService, + LanguageRepository, + ]); noNlpSample = await nlpSampleService.findOne({ text: 'No' }); nlpSampleEntity = await nlpSampleEntityRepository.findOne({ sample: noNlpSample!.id, @@ -118,9 +120,7 @@ describe('NlpSampleService', () => { languages = await languageRepository.findAll(); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/nlp/services/nlp-value.service.spec.ts b/api/src/nlp/services/nlp-value.service.spec.ts index f62ed7cb..3f999144 100644 --- a/api/src/nlp/services/nlp-value.service.spec.ts +++ b/api/src/nlp/services/nlp-value.service.spec.ts @@ -1,14 +1,12 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { BaseSchema } from '@/utils/generics/base-schema'; import { nlpEntityFixtures } from '@/utils/test/fixtures/nlpentity'; @@ -21,6 +19,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { NlpEntityRepository } from '../repositories/nlp-entity.repository'; import { NlpSampleEntityRepository } from '../repositories/nlp-sample-entity.repository'; @@ -44,7 +43,7 @@ describe('NlpValueService', () => { let nlpValues: NlpValue[]; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installNlpValueFixtures), MongooseModule.forFeature([ @@ -59,13 +58,19 @@ describe('NlpValueService', () => { NlpEntityRepository, NlpValueService, NlpEntityService, - EventEmitter2, ], - }).compile(); - nlpValueService = module.get(NlpValueService); - nlpEntityService = module.get(NlpEntityService); - nlpValueRepository = module.get(NlpValueRepository); - nlpEntityRepository = module.get(NlpEntityRepository); + }); + [ + nlpValueService, + nlpEntityService, + nlpValueRepository, + nlpEntityRepository, + ] = await getMocks([ + NlpValueService, + NlpEntityService, + NlpValueRepository, + NlpEntityRepository, + ]); nlpValues = await nlpValueRepository.findAll(); }); diff --git a/api/src/plugins/plugins.service.spec.ts b/api/src/plugins/plugins.service.spec.ts index bb9f42e4..8d64f0cf 100644 --- a/api/src/plugins/plugins.service.spec.ts +++ b/api/src/plugins/plugins.service.spec.ts @@ -1,15 +1,14 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { Test } from '@nestjs/testing'; - import { LoggerModule } from '@/logger/logger.module'; import { DummyPlugin } from '@/utils/test/dummy/dummy.plugin'; +import { buildTestingMocks } from '@/utils/test/utils'; import { BaseBlockPlugin } from './base-block-plugin'; import { PluginService } from './plugins.service'; @@ -17,17 +16,21 @@ import { PluginType } from './types'; describe('PluginsService', () => { let pluginsService: PluginService; + let dummyPlugin: DummyPlugin; + beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ providers: [PluginService, DummyPlugin], imports: [LoggerModule], - }).compile(); - pluginsService = module.get(PluginService); - await module.get(DummyPlugin).onModuleInit(); - }); - afterAll(async () => { - jest.clearAllMocks(); + }); + [pluginsService, dummyPlugin] = await getMocks([ + PluginService, + DummyPlugin, + ]); + await dummyPlugin.onModuleInit(); }); + + afterAll(jest.clearAllMocks); describe('getAll', () => { it('should return an array of instances of base plugin', () => { const result = pluginsService.getAllByType(PluginType.block); diff --git a/api/src/setting/controllers/setting.controller.spec.ts b/api/src/setting/controllers/setting.controller.spec.ts index 156ed87c..afd5dc78 100644 --- a/api/src/setting/controllers/setting.controller.spec.ts +++ b/api/src/setting/controllers/setting.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,12 +7,9 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { I18nService } from '@/i18n/services/i18n.service'; -import { LoggerService } from '@/logger/logger.service'; import { installSettingFixtures, settingFixtures, @@ -21,6 +18,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { SettingRepository } from '../repositories/setting.repository'; import { Setting, SettingModel } from '../schemas/setting.schema'; @@ -34,7 +32,7 @@ describe('SettingController', () => { let settingService: SettingService; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [SettingController], imports: [ rootMongooseTestModule(installSettingFixtures), @@ -44,8 +42,6 @@ describe('SettingController', () => { SettingService, SettingRepository, SettingSeeder, - LoggerService, - EventEmitter2, { provide: I18nService, useValue: { @@ -61,10 +57,11 @@ describe('SettingController', () => { }, }, ], - }).compile(); - - settingController = module.get(SettingController); - settingService = module.get(SettingService); + }); + [settingController, settingService] = await getMocks([ + SettingController, + SettingService, + ]); }); afterAll(closeInMongodConnection); diff --git a/api/src/setting/repositories/setting.repository.spec.ts b/api/src/setting/repositories/setting.repository.spec.ts index f471483f..c5ec5c82 100644 --- a/api/src/setting/repositories/setting.repository.spec.ts +++ b/api/src/setting/repositories/setting.repository.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -8,7 +8,6 @@ import { EventEmitter2 } from '@nestjs/event-emitter'; import { getModelToken, MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { Model } from 'mongoose'; import { installSettingFixtures } from '@/utils/test/fixtures/setting'; @@ -16,6 +15,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { Setting, SettingModel } from '../schemas/setting.schema'; import { SettingType } from '../schemas/types'; @@ -28,22 +28,21 @@ describe('SettingRepository', () => { let eventEmitter: EventEmitter2; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installSettingFixtures), MongooseModule.forFeature([SettingModel]), ], - providers: [SettingRepository, EventEmitter2], - }).compile(); - - settingRepository = module.get(SettingRepository); - settingModel = module.get>(getModelToken(Setting.name)); - eventEmitter = module.get(EventEmitter2); + providers: [SettingRepository], + }); + [settingRepository, settingModel, eventEmitter] = await getMocks([ + SettingRepository, + getModelToken(Setting.name), + EventEmitter2, + ]); }); - afterEach(() => { - jest.clearAllMocks(); - }); + afterEach(jest.clearAllMocks); afterAll(closeInMongodConnection); diff --git a/api/src/setting/services/setting.service.spec.ts b/api/src/setting/services/setting.service.spec.ts index 3c741738..e3fac80e 100644 --- a/api/src/setting/services/setting.service.spec.ts +++ b/api/src/setting/services/setting.service.spec.ts @@ -7,12 +7,9 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; import { I18nService } from '@/i18n/services/i18n.service'; -import { LoggerService } from '@/logger/logger.service'; import { installSettingFixtures, settingFixtures, @@ -21,6 +18,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { SettingRepository } from '../repositories/setting.repository'; import { Setting, SettingModel } from '../schemas/setting.schema'; @@ -40,7 +38,7 @@ describe('SettingService', () => { }; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installSettingFixtures), MongooseModule.forFeature([SettingModel]), @@ -49,7 +47,6 @@ describe('SettingService', () => { SettingService, SettingRepository, SettingSeeder, - EventEmitter2, { provide: I18nService, useValue: { @@ -64,12 +61,12 @@ describe('SettingService', () => { set: jest.fn(), }, }, - LoggerService, ], - }).compile(); - - settingService = module.get(SettingService); - settingRepository = module.get(SettingRepository); + }); + [settingService, settingRepository] = await getMocks([ + SettingService, + SettingRepository, + ]); }); afterAll(closeInMongodConnection); diff --git a/api/src/user/controllers/auth.controller.spec.ts b/api/src/user/controllers/auth.controller.spec.ts index 15858d6e..0ddd26a1 100644 --- a/api/src/user/controllers/auth.controller.spec.ts +++ b/api/src/user/controllers/auth.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -12,10 +12,8 @@ import { UnauthorizedException, } from '@nestjs/common'; import { BadRequestException } from '@nestjs/common/exceptions/bad-request.exception'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { JwtService } from '@nestjs/jwt'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { ISendMailOptions, MailerService } from '@nestjs-modules/mailer'; import { SentMessageInfo } from 'nodemailer'; @@ -26,7 +24,6 @@ import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { LanguageModel } from '@/i18n/schemas/language.schema'; import { I18nService } from '@/i18n/services/i18n.service'; import { LanguageService } from '@/i18n/services/language.service'; -import { LoggerService } from '@/logger/logger.service'; import { getRandom } from '@/utils/helpers/safeRandom'; import { installLanguageFixtures } from '@/utils/test/fixtures/language'; import { installUserFixtures } from '@/utils/test/fixtures/user'; @@ -34,6 +31,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { SocketEventDispatcherService } from '@/websocket/services/socket-event-dispatcher.service'; import { WebsocketGateway } from '@/websocket/websocket.gateway'; @@ -64,7 +62,7 @@ describe('AuthController', () => { let baseUser: UserCreateDto; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [LocalAuthController], imports: [ rootMongooseTestModule(async () => { @@ -81,14 +79,12 @@ describe('AuthController', () => { ]), ], providers: [ - LoggerService, UserService, WebsocketGateway, SocketEventDispatcherService, AttachmentService, AttachmentRepository, UserRepository, - LoggerService, PermissionService, RoleService, RoleRepository, @@ -114,7 +110,6 @@ describe('AuthController', () => { set: jest.fn(), }, }, - EventEmitter2, ValidateAccountService, { provide: I18nService, @@ -123,12 +118,15 @@ describe('AuthController', () => { }, }, ], - }).compile(); - authController = module.get(LocalAuthController); - userService = module.get(UserService); - invitationService = module.get(InvitationService); - roleService = module.get(RoleService); - jwtService = module.get(JwtService); + }); + [authController, userService, invitationService, roleService, jwtService] = + await getMocks([ + LocalAuthController, + UserService, + InvitationService, + RoleService, + JwtService, + ]); role = await roleService.findOne({}); baseUser = { email: 'test@testing.com', @@ -142,9 +140,7 @@ describe('AuthController', () => { await invitationService.create(baseUser); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/user/controllers/model.controller.spec.ts b/api/src/user/controllers/model.controller.spec.ts index 840adbcb..743d7d3c 100644 --- a/api/src/user/controllers/model.controller.spec.ts +++ b/api/src/user/controllers/model.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,14 +7,11 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; -import { LoggerService } from '@/logger/logger.service'; import { installModelFixtures, modelFixtures, @@ -23,6 +20,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { InvitationRepository } from '../repositories/invitation.repository'; import { ModelRepository } from '../repositories/model.repository'; @@ -47,7 +45,7 @@ describe('ModelController', () => { let permissionService: PermissionService; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [ModelController], imports: [ rootMongooseTestModule(installModelFixtures), @@ -61,7 +59,6 @@ describe('ModelController', () => { ]), ], providers: [ - LoggerService, PermissionService, AttachmentService, AttachmentRepository, @@ -73,7 +70,6 @@ describe('ModelController', () => { RoleRepository, InvitationRepository, PermissionRepository, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -83,10 +79,12 @@ describe('ModelController', () => { }, }, ], - }).compile(); - modelController = module.get(ModelController); - modelService = module.get(ModelService); - permissionService = module.get(PermissionService); + }); + [modelController, modelService, permissionService] = await getMocks([ + ModelController, + ModelService, + PermissionService, + ]); }); afterAll(closeInMongodConnection); diff --git a/api/src/user/controllers/permission.controller.spec.ts b/api/src/user/controllers/permission.controller.spec.ts index 4fcf1916..4869dccb 100644 --- a/api/src/user/controllers/permission.controller.spec.ts +++ b/api/src/user/controllers/permission.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -8,16 +8,14 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { NotFoundException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test } from '@nestjs/testing'; -import { LoggerService } from '@/logger/logger.service'; import { installPermissionFixtures } from '@/utils/test/fixtures/permission'; import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { PermissionCreateDto } from '../dto/permission.dto'; import { InvitationRepository } from '../repositories/invitation.repository'; @@ -51,7 +49,7 @@ describe('PermissionController', () => { let allPermissions: Permission[]; beforeAll(async () => { - const permissionModuleRef = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [PermissionController], imports: [ rootMongooseTestModule(installPermissionFixtures), @@ -63,7 +61,6 @@ describe('PermissionController', () => { ]), ], providers: [ - LoggerService, RoleService, ModelService, PermissionService, @@ -71,7 +68,6 @@ describe('PermissionController', () => { RoleRepository, InvitationRepository, ModelRepository, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -81,15 +77,14 @@ describe('PermissionController', () => { }, }, ], - }).compile(); - - permissionController = - permissionModuleRef.get(PermissionController); - roleService = permissionModuleRef.get(RoleService); - modelService = permissionModuleRef.get(ModelService); - permissionService = - permissionModuleRef.get(PermissionService); - + }); + [permissionController, roleService, modelService, permissionService] = + await getMocks([ + PermissionController, + RoleService, + ModelService, + PermissionService, + ]); allPermissions = await permissionService.findAll(); adminRole = (await roleService.findOne({ name: 'admin' })) as Role; contentModel = (await modelService.findOne({ name: 'Content' })) as Model; diff --git a/api/src/user/controllers/role.controller.spec.ts b/api/src/user/controllers/role.controller.spec.ts index ae444686..19ad536d 100644 --- a/api/src/user/controllers/role.controller.spec.ts +++ b/api/src/user/controllers/role.controller.spec.ts @@ -8,15 +8,12 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { ForbiddenException, NotFoundException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { Request } from 'express'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; -import { LoggerService } from '@/logger/logger.service'; import { installPermissionFixtures } from '@/utils/test/fixtures/permission'; import { roleFixtures } from '@/utils/test/fixtures/role'; import { getPageQuery } from '@/utils/test/pagination'; @@ -24,6 +21,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { RoleCreateDto, RoleUpdateDto } from '../dto/role.dto'; import { InvitationRepository } from '../repositories/invitation.repository'; @@ -49,7 +47,7 @@ describe('RoleController', () => { let rolePublic: Role; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [RoleController], imports: [ rootMongooseTestModule(installPermissionFixtures), @@ -62,7 +60,6 @@ describe('RoleController', () => { ]), ], providers: [ - LoggerService, PermissionService, UserService, UserRepository, @@ -70,7 +67,6 @@ describe('RoleController', () => { RoleRepository, InvitationRepository, PermissionRepository, - EventEmitter2, AttachmentService, AttachmentRepository, { @@ -82,18 +78,19 @@ describe('RoleController', () => { }, }, ], - }).compile(); - roleController = module.get(RoleController); - roleService = module.get(RoleService); - permissionService = module.get(PermissionService); - userService = module.get(UserService); + }); + [roleController, roleService, permissionService, userService] = + await getMocks([ + RoleController, + RoleService, + PermissionService, + UserService, + ]); roleAdmin = (await roleService.findOne({ name: 'admin' })) as Role; rolePublic = (await roleService.findOne({ name: 'public' })) as Role; }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/user/controllers/user.controller.spec.ts b/api/src/user/controllers/user.controller.spec.ts index c7f5d889..cb1cc277 100644 --- a/api/src/user/controllers/user.controller.spec.ts +++ b/api/src/user/controllers/user.controller.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -8,10 +8,8 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { ForbiddenException, NotFoundException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { JwtModule, JwtService } from '@nestjs/jwt'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { ISendMailOptions, MailerService } from '@nestjs-modules/mailer'; import { Session as ExpressSession } from 'express-session'; import { SentMessageInfo } from 'nodemailer'; @@ -23,7 +21,6 @@ import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { LanguageModel } from '@/i18n/schemas/language.schema'; import { I18nService } from '@/i18n/services/i18n.service'; import { LanguageService } from '@/i18n/services/language.service'; -import { LoggerService } from '@/logger/logger.service'; import { IGNORED_TEST_FIELDS } from '@/utils/test/constants'; import { installLanguageFixtures } from '@/utils/test/fixtures/language'; import { installPermissionFixtures } from '@/utils/test/fixtures/permission'; @@ -33,6 +30,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { InvitationCreateDto } from '../dto/invitation.dto'; import { @@ -69,7 +67,7 @@ describe('UserController', () => { let passwordResetService: PasswordResetService; let jwtService: JwtService; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [ReadWriteUserController], imports: [ rootMongooseTestModule(async () => { @@ -87,7 +85,6 @@ describe('UserController', () => { JwtModule, ], providers: [ - LoggerService, RoleService, UserService, InvitationService, @@ -105,7 +102,6 @@ describe('UserController', () => { RoleRepository, PermissionRepository, InvitationRepository, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -126,19 +122,25 @@ describe('UserController', () => { }, }, ], - }).compile(); - userController = module.get( + }); + [ + userController, + userService, + roleService, + invitationService, + jwtService, + passwordResetService, + ] = await getMocks([ ReadWriteUserController, - ); - userService = module.get(UserService); - roleService = module.get(RoleService); - invitationService = module.get(InvitationService); + UserService, + RoleService, + InvitationService, + JwtService, + PasswordResetService, + ]); role = await roleService.findOne({ name: 'admin' }); roles = await roleService.findAll(); user = await userService.findOne({ username: 'admin' }); - jwtService = module.get(JwtService); - passwordResetService = - module.get(PasswordResetService); }); const IGNORED_FIELDS = [...IGNORED_TEST_FIELDS, 'resetToken']; diff --git a/api/src/user/repositories/invitation.repository.spec.ts b/api/src/user/repositories/invitation.repository.spec.ts index 0f61ef0b..09715dbf 100644 --- a/api/src/user/repositories/invitation.repository.spec.ts +++ b/api/src/user/repositories/invitation.repository.spec.ts @@ -1,17 +1,14 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { Model } from 'mongoose'; -import { LoggerService } from '@/logger/logger.service'; import { PageQueryDto } from '@/utils/pagination/pagination-query.dto'; import { installInvitationFixtures, @@ -22,6 +19,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { Invitation, @@ -40,7 +38,7 @@ describe('InvitationRepository', () => { let invitationRepository: InvitationRepository; let invitationModel: Model; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installInvitationFixtures), MongooseModule.forFeature([ @@ -49,25 +47,17 @@ describe('InvitationRepository', () => { InvitationModel, ]), ], - providers: [ - RoleRepository, - InvitationRepository, - PermissionRepository, - LoggerService, - EventEmitter2, - ], - }).compile(); - roleRepository = module.get(RoleRepository); - invitationRepository = - module.get(InvitationRepository); - invitationModel = module.get>( - getModelToken('Invitation'), - ); - }); - afterAll(async () => { - await closeInMongodConnection(); + providers: [RoleRepository, InvitationRepository, PermissionRepository], + }); + [roleRepository, invitationRepository, invitationModel] = await getMocks([ + RoleRepository, + InvitationRepository, + getModelToken(Invitation.name), + ]); }); + afterAll(closeInMongodConnection); + afterEach(jest.clearAllMocks); describe('findOneAndPopulate', () => { diff --git a/api/src/user/repositories/model.repository.spec.ts b/api/src/user/repositories/model.repository.spec.ts index 0679d34f..0d809179 100644 --- a/api/src/user/repositories/model.repository.spec.ts +++ b/api/src/user/repositories/model.repository.spec.ts @@ -1,14 +1,12 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { Model } from 'mongoose'; import { modelFixtures } from '@/utils/test/fixtures/model'; @@ -17,6 +15,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { ModelRepository } from '../repositories/model.repository'; import { PermissionRepository } from '../repositories/permission.repository'; @@ -33,17 +32,18 @@ describe('ModelRepository', () => { let permissions: Permission[]; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installPermissionFixtures), MongooseModule.forFeature([ModelModel, PermissionModel]), ], - providers: [ModelRepository, PermissionRepository, EventEmitter2], - }).compile(); - permissionRepository = - module.get(PermissionRepository); - modelRepository = module.get(ModelRepository); - modelModel = module.get>(getModelToken('Model')); + providers: [ModelRepository, PermissionRepository], + }); + [permissionRepository, modelRepository, modelModel] = await getMocks([ + PermissionRepository, + ModelRepository, + getModelToken(Model.name), + ]); model = await modelRepository.findOne({ name: 'ContentType' }); permissions = await permissionRepository.find({ model: model!.id }); }); diff --git a/api/src/user/repositories/permission.repository.spec.ts b/api/src/user/repositories/permission.repository.spec.ts index 12da8738..5a32ad19 100644 --- a/api/src/user/repositories/permission.repository.spec.ts +++ b/api/src/user/repositories/permission.repository.spec.ts @@ -6,9 +6,7 @@ * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { Model } from 'mongoose'; import { @@ -19,6 +17,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { ModelRepository } from '../repositories/model.repository'; import { PermissionRepository } from '../repositories/permission.repository'; @@ -44,7 +43,7 @@ describe('PermissionRepository', () => { let permissionToDelete: Permission; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installPermissionFixtures), MongooseModule.forFeature([ @@ -59,16 +58,15 @@ describe('PermissionRepository', () => { RoleRepository, PermissionRepository, InvitationRepository, - EventEmitter2, ], - }).compile(); - roleRepository = module.get(RoleRepository); - modelRepository = module.get(ModelRepository); - permissionRepository = - module.get(PermissionRepository); - permissionModel = module.get>( - getModelToken('Permission'), - ); + }); + [roleRepository, modelRepository, permissionRepository, permissionModel] = + await getMocks([ + RoleRepository, + ModelRepository, + PermissionRepository, + getModelToken(Permission.name), + ]); permission = (await permissionRepository.findOne({ action: Action.CREATE, })) as Permission; @@ -77,9 +75,7 @@ describe('PermissionRepository', () => { })) as Permission; }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/user/repositories/role.repository.spec.ts b/api/src/user/repositories/role.repository.spec.ts index 50728b48..da573eb7 100644 --- a/api/src/user/repositories/role.repository.spec.ts +++ b/api/src/user/repositories/role.repository.spec.ts @@ -6,9 +6,7 @@ * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { Model } from 'mongoose'; import { installPermissionFixtures } from '@/utils/test/fixtures/permission'; @@ -17,6 +15,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { PermissionRepository } from '../repositories/permission.repository'; import { RoleRepository } from '../repositories/role.repository'; @@ -39,7 +38,7 @@ describe('RoleRepository', () => { let roleToDelete: Role; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installPermissionFixtures), MongooseModule.forFeature([ @@ -54,14 +53,15 @@ describe('RoleRepository', () => { RoleRepository, InvitationRepository, PermissionRepository, - EventEmitter2, ], - }).compile(); - roleRepository = module.get(RoleRepository); - userRepository = module.get(UserRepository); - permissionRepository = - module.get(PermissionRepository); - roleModel = module.get>(getModelToken('Role')); + }); + [roleRepository, userRepository, permissionRepository, roleModel] = + await getMocks([ + RoleRepository, + UserRepository, + PermissionRepository, + getModelToken(Role.name), + ]); role = (await roleRepository.findOne({ name: 'admin' })) as Role; users = (await userRepository.findAll()).filter((user) => user.roles.includes(role.id), @@ -71,9 +71,7 @@ describe('RoleRepository', () => { })) as Role; }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/user/repositories/user.repository.spec.ts b/api/src/user/repositories/user.repository.spec.ts index 139a1a16..4f148491 100644 --- a/api/src/user/repositories/user.repository.spec.ts +++ b/api/src/user/repositories/user.repository.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,13 +7,10 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { Model } from 'mongoose'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; -import { LoggerService } from '@/logger/logger.service'; import { IGNORED_TEST_FIELDS } from '@/utils/test/constants'; import { installPermissionFixtures } from '@/utils/test/fixtures/permission'; import { userFixtures } from '@/utils/test/fixtures/user'; @@ -22,6 +19,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { PermissionRepository } from '../repositories/permission.repository'; import { RoleRepository } from '../repositories/role.repository'; @@ -53,7 +51,7 @@ describe('UserRepository', () => { ]; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installPermissionFixtures), MongooseModule.forFeature([ @@ -65,12 +63,10 @@ describe('UserRepository', () => { ]), ], providers: [ - LoggerService, UserRepository, RoleRepository, InvitationRepository, PermissionRepository, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -80,10 +76,12 @@ describe('UserRepository', () => { }, }, ], - }).compile(); - roleRepository = module.get(RoleRepository); - userRepository = module.get(UserRepository); - userModel = module.get>(getModelToken('User')); + }); + [roleRepository, userRepository, userModel] = await getMocks([ + RoleRepository, + UserRepository, + getModelToken(User.name), + ]); user = await userRepository.findOne({ username: 'admin' }); allRoles = await roleRepository.findAll(); }); diff --git a/api/src/user/services/auth.service.spec.ts b/api/src/user/services/auth.service.spec.ts index b3f0dd59..5eb04552 100644 --- a/api/src/user/services/auth.service.spec.ts +++ b/api/src/user/services/auth.service.spec.ts @@ -1,25 +1,23 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { JwtService } from '@nestjs/jwt'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; -import { LoggerService } from '@/logger/logger.service'; import { installUserFixtures } from '@/utils/test/fixtures/user'; import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { InvitationRepository } from '../repositories/invitation.repository'; import { RoleRepository } from '../repositories/role.repository'; @@ -38,7 +36,7 @@ describe('AuthService', () => { let userRepository: UserRepository; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installUserFixtures), MongooseModule.forFeature([ @@ -50,7 +48,6 @@ describe('AuthService', () => { ]), ], providers: [ - LoggerService, AuthService, UserService, UserRepository, @@ -58,13 +55,14 @@ describe('AuthService', () => { RoleRepository, InvitationRepository, JwtService, - EventEmitter2, AttachmentService, AttachmentRepository, ], - }).compile(); - authService = module.get(AuthService); - userRepository = module.get(UserRepository); + }); + [authService, userRepository] = await getMocks([ + AuthService, + UserRepository, + ]); jest.spyOn(userRepository, 'findOne'); }); diff --git a/api/src/user/services/invitation.service.spec.ts b/api/src/user/services/invitation.service.spec.ts index 7672fc1d..9c245a56 100644 --- a/api/src/user/services/invitation.service.spec.ts +++ b/api/src/user/services/invitation.service.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -8,10 +8,8 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Logger } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { JwtModule, JwtService } from '@nestjs/jwt'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { ISendMailOptions, MailerService } from '@nestjs-modules/mailer'; import { SentMessageInfo } from 'nodemailer'; @@ -19,7 +17,6 @@ import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { LanguageModel } from '@/i18n/schemas/language.schema'; import { I18nService } from '@/i18n/services/i18n.service'; import { LanguageService } from '@/i18n/services/language.service'; -import { LoggerService } from '@/logger/logger.service'; import { IGNORED_TEST_FIELDS } from '@/utils/test/constants'; import { installInvitationFixtures, @@ -30,6 +27,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { InvitationCreateDto } from '../dto/invitation.dto'; import { InvitationRepository } from '../repositories/invitation.repository'; @@ -52,7 +50,7 @@ describe('InvitationService', () => { const IGNORED_FIELDS = ['iat', 'exp', 'token', ...IGNORED_TEST_FIELDS]; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(async () => { await installLanguageFixtures(); @@ -67,7 +65,6 @@ describe('InvitationService', () => { JwtModule, ], providers: [ - LoggerService, PermissionService, RoleService, RoleRepository, @@ -76,7 +73,6 @@ describe('InvitationService', () => { InvitationService, LanguageRepository, LanguageService, - JwtService, Logger, { provide: I18nService, @@ -94,7 +90,6 @@ describe('InvitationService', () => { ), }, }, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -104,18 +99,24 @@ describe('InvitationService', () => { }, }, ], - }).compile(); - roleRepository = module.get(RoleRepository); - invitationService = module.get(InvitationService); - invitationRepository = - module.get(InvitationRepository); - jwtService = module.get(JwtService); - mailerService = module.get(MailerService); - }); - afterAll(async () => { - await closeInMongodConnection(); + }); + [ + roleRepository, + invitationService, + invitationRepository, + jwtService, + mailerService, + ] = await getMocks([ + RoleRepository, + InvitationService, + InvitationRepository, + JwtService, + MailerService, + ]); }); + afterAll(closeInMongodConnection); + afterEach(jest.clearAllMocks); describe('sign', () => { diff --git a/api/src/user/services/model.service.spec.ts b/api/src/user/services/model.service.spec.ts index ec1c13af..61b29466 100644 --- a/api/src/user/services/model.service.spec.ts +++ b/api/src/user/services/model.service.spec.ts @@ -1,14 +1,12 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { modelFixtures } from '@/utils/test/fixtures/model'; import { installPermissionFixtures } from '@/utils/test/fixtures/permission'; @@ -16,6 +14,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { ModelRepository } from '../repositories/model.repository'; import { PermissionRepository } from '../repositories/permission.repository'; @@ -32,22 +31,18 @@ describe('ModelService', () => { let permissions: Permission[]; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installPermissionFixtures), MongooseModule.forFeature([ModelModel, PermissionModel]), ], - providers: [ - ModelService, - ModelRepository, - PermissionRepository, - EventEmitter2, - ], - }).compile(); - modelService = module.get(ModelService); - permissionRepository = - module.get(PermissionRepository); - modelRepository = module.get(ModelRepository); + providers: [ModelService, ModelRepository, PermissionRepository], + }); + [modelService, permissionRepository, modelRepository] = await getMocks([ + ModelService, + PermissionRepository, + ModelRepository, + ]); model = await modelRepository.findOne({ name: 'ContentType' }); permissions = await permissionRepository.find({ model: model!.id }); }); diff --git a/api/src/user/services/passwordReset.service.spec.ts b/api/src/user/services/passwordReset.service.spec.ts index c5f18c6b..e7c66c59 100644 --- a/api/src/user/services/passwordReset.service.spec.ts +++ b/api/src/user/services/passwordReset.service.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -8,10 +8,8 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { NotFoundException } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { JwtModule, JwtService } from '@nestjs/jwt'; import { MongooseModule, getModelToken } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { ISendMailOptions, MailerService } from '@nestjs-modules/mailer'; import { compareSync } from 'bcryptjs'; import { Model } from 'mongoose'; @@ -24,13 +22,13 @@ import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { LanguageModel } from '@/i18n/schemas/language.schema'; import { I18nService } from '@/i18n/services/i18n.service'; import { LanguageService } from '@/i18n/services/language.service'; -import { LoggerService } from '@/logger/logger.service'; import { installLanguageFixtures } from '@/utils/test/fixtures/language'; import { installUserFixtures, users } from '@/utils/test/fixtures/user'; import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { InvitationRepository } from '../repositories/invitation.repository'; import { RoleRepository } from '../repositories/role.repository'; @@ -50,7 +48,7 @@ describe('PasswordResetService', () => { let jwtService: JwtService; let userModel: Model; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(async () => { await installLanguageFixtures(); @@ -76,9 +74,7 @@ describe('PasswordResetService', () => { InvitationRepository, LanguageService, LanguageRepository, - LoggerService, PasswordResetService, - JwtService, { provide: MailerService, useValue: { @@ -94,7 +90,6 @@ describe('PasswordResetService', () => { t: jest.fn().mockImplementation((t) => t), }, }, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -104,12 +99,14 @@ describe('PasswordResetService', () => { }, }, ], - }).compile(); - passwordResetService = - module.get(PasswordResetService); - mailerService = module.get(MailerService); - jwtService = module.get(JwtService); - userModel = module.get>(getModelToken('User')); + }); + [passwordResetService, mailerService, jwtService, userModel] = + await getMocks([ + PasswordResetService, + MailerService, + JwtService, + getModelToken(User.name), + ]); }); afterAll(closeInMongodConnection); diff --git a/api/src/user/services/permission.service.spec.ts b/api/src/user/services/permission.service.spec.ts index 1547acc1..7f70ad9a 100644 --- a/api/src/user/services/permission.service.spec.ts +++ b/api/src/user/services/permission.service.spec.ts @@ -7,11 +7,8 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; -import { LoggerService } from '@/logger/logger.service'; import { installPermissionFixtures, permissionFixtures, @@ -20,6 +17,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { InvitationRepository } from '../repositories/invitation.repository'; import { ModelRepository } from '../repositories/model.repository'; @@ -45,7 +43,7 @@ describe('PermissionService', () => { let permission: Permission; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installPermissionFixtures), MongooseModule.forFeature([ @@ -61,7 +59,6 @@ describe('PermissionService', () => { RoleRepository, InvitationRepository, PermissionRepository, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -70,22 +67,21 @@ describe('PermissionService', () => { set: jest.fn(), }, }, - LoggerService, ], - }).compile(); - permissionService = module.get(PermissionService); - roleRepository = module.get(RoleRepository); - modelRepository = module.get(ModelRepository); - permissionRepository = - module.get(PermissionRepository); + }); + [permissionService, roleRepository, modelRepository, permissionRepository] = + await getMocks([ + PermissionService, + RoleRepository, + ModelRepository, + PermissionRepository, + ]); permission = (await permissionRepository.findOne({ action: Action.CREATE, })) as Permission; }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/user/services/role.service.spec.ts b/api/src/user/services/role.service.spec.ts index de6533a7..9d46651f 100644 --- a/api/src/user/services/role.service.spec.ts +++ b/api/src/user/services/role.service.spec.ts @@ -6,9 +6,7 @@ * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { installPermissionFixtures } from '@/utils/test/fixtures/permission'; import { getPageQuery } from '@/utils/test/pagination'; @@ -16,6 +14,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { InvitationRepository } from '../repositories/invitation.repository'; import { PermissionRepository } from '../repositories/permission.repository'; @@ -39,7 +38,7 @@ describe('RoleService', () => { let permissions: Permission[]; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installPermissionFixtures), MongooseModule.forFeature([ @@ -55,14 +54,15 @@ describe('RoleService', () => { RoleRepository, InvitationRepository, PermissionRepository, - EventEmitter2, ], - }).compile(); - roleService = module.get(RoleService); - roleRepository = module.get(RoleRepository); - userRepository = module.get(UserRepository); - permissionRepository = - module.get(PermissionRepository); + }); + [roleService, roleRepository, userRepository, permissionRepository] = + await getMocks([ + RoleService, + RoleRepository, + UserRepository, + PermissionRepository, + ]); role = (await roleRepository.findOne({ name: 'admin' })) as Role; users = (await userRepository.findAll()).filter((user) => user.roles.includes(role.id), @@ -71,9 +71,7 @@ describe('RoleService', () => { permissions = await permissionRepository.find({ role: role.id }); }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); diff --git a/api/src/user/services/user.service.spec.ts b/api/src/user/services/user.service.spec.ts index 7b357984..b5b4b882 100644 --- a/api/src/user/services/user.service.spec.ts +++ b/api/src/user/services/user.service.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,14 +7,11 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { AttachmentRepository } from '@/attachment/repositories/attachment.repository'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; -import { LoggerService } from '@/logger/logger.service'; import { IGNORED_TEST_FIELDS } from '@/utils/test/constants'; import { installPermissionFixtures } from '@/utils/test/fixtures/permission'; import { userFixtures } from '@/utils/test/fixtures/user'; @@ -23,6 +20,7 @@ import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { InvitationRepository } from '../repositories/invitation.repository'; import { PermissionRepository } from '../repositories/permission.repository'; @@ -56,7 +54,7 @@ describe('UserService', () => { ]; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(installPermissionFixtures), MongooseModule.forFeature([ @@ -68,7 +66,6 @@ describe('UserService', () => { ]), ], providers: [ - LoggerService, UserService, AttachmentService, AttachmentRepository, @@ -78,7 +75,6 @@ describe('UserService', () => { RoleRepository, InvitationRepository, PermissionRepository, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -88,10 +84,12 @@ describe('UserService', () => { }, }, ], - }).compile(); - userService = module.get(UserService); - roleRepository = module.get(RoleRepository); - userRepository = module.get(UserRepository); + }); + [userService, roleRepository, userRepository] = await getMocks([ + UserService, + RoleRepository, + UserRepository, + ]); user = await userRepository.findOne({ username: 'admin' }); allRoles = await roleRepository.findAll(); }); diff --git a/api/src/user/services/validate-account.service.spec.ts b/api/src/user/services/validate-account.service.spec.ts index 84bad094..cae6ab77 100644 --- a/api/src/user/services/validate-account.service.spec.ts +++ b/api/src/user/services/validate-account.service.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,10 +7,8 @@ */ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { JwtModule } from '@nestjs/jwt'; import { MongooseModule } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { ISendMailOptions, MailerService } from '@nestjs-modules/mailer'; import { SentMessageInfo } from 'nodemailer'; @@ -21,13 +19,13 @@ import { LanguageRepository } from '@/i18n/repositories/language.repository'; import { LanguageModel } from '@/i18n/schemas/language.schema'; import { I18nService } from '@/i18n/services/i18n.service'; import { LanguageService } from '@/i18n/services/language.service'; -import { LoggerService } from '@/logger/logger.service'; import { installLanguageFixtures } from '@/utils/test/fixtures/language'; import { installUserFixtures, users } from '@/utils/test/fixtures/user'; import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { InvitationRepository } from '../repositories/invitation.repository'; import { RoleRepository } from '../repositories/role.repository'; @@ -45,7 +43,7 @@ describe('ValidateAccountService', () => { let validateAccountService: ValidateAccountService; let mailerService: MailerService; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [ rootMongooseTestModule(async () => { await installLanguageFixtures(); @@ -71,7 +69,6 @@ describe('ValidateAccountService', () => { InvitationRepository, LanguageService, LanguageRepository, - LoggerService, { provide: MailerService, useValue: { @@ -81,7 +78,6 @@ describe('ValidateAccountService', () => { ), }, }, - EventEmitter2, ValidateAccountService, { provide: I18nService, @@ -98,18 +94,17 @@ describe('ValidateAccountService', () => { }, }, ], - }).compile(); - validateAccountService = module.get( + }); + [validateAccountService, mailerService] = await getMocks([ ValidateAccountService, - ); + MailerService, + ]); + }); - mailerService = module.get(MailerService); - }); - afterAll(async () => { - await closeInMongodConnection(); - }); + afterAll(closeInMongodConnection); afterEach(jest.clearAllMocks); + describe('sendConfirmationEmail', () => { it('should send an email with a token', async () => { const sendMailSpy = jest.spyOn(mailerService, 'sendMail'); diff --git a/api/src/utils/generics/base-repository.spec.ts b/api/src/utils/generics/base-repository.spec.ts index 06241861..95d19fdb 100644 --- a/api/src/utils/generics/base-repository.spec.ts +++ b/api/src/utils/generics/base-repository.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,7 +7,6 @@ */ import { getModelToken } from '@nestjs/mongoose'; -import { Test, TestingModule } from '@nestjs/testing'; import { Model, Types } from 'mongoose'; import { DummyRepository } from '@/utils/test/dummy/repositories/dummy.repository'; @@ -15,6 +14,7 @@ import { closeInMongodConnection } from '@/utils/test/test'; import { DummyModule } from '../test/dummy/dummy.module'; import { Dummy } from '../test/dummy/schemas/dummy.schema'; +import { buildTestingMocks } from '../test/utils'; describe('BaseRepository', () => { let dummyModel: Model; @@ -22,11 +22,13 @@ describe('BaseRepository', () => { let createdId: string; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [DummyModule], - }).compile(); - dummyModel = module.get>(getModelToken(Dummy.name)); - dummyRepository = module.get(DummyRepository); + }); + [dummyRepository, dummyModel] = await getMocks([ + DummyRepository, + getModelToken(Dummy.name), + ]); }); afterEach(jest.clearAllMocks); afterAll(closeInMongodConnection); diff --git a/api/src/utils/generics/base-service.spec.ts b/api/src/utils/generics/base-service.spec.ts index 20ffc076..4b45d868 100644 --- a/api/src/utils/generics/base-service.spec.ts +++ b/api/src/utils/generics/base-service.spec.ts @@ -6,13 +6,12 @@ * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { Test, TestingModule } from '@nestjs/testing'; - import { DummyService } from '@/utils/test/dummy/services/dummy.service'; import { closeInMongodConnection } from '@/utils/test/test'; import { DummyModule } from '../test/dummy/dummy.module'; import { DummyRepository } from '../test/dummy/repositories/dummy.repository'; +import { buildTestingMocks } from '../test/utils'; describe('BaseService', () => { let dummyRepository: DummyRepository; @@ -30,11 +29,13 @@ describe('BaseService', () => { }; beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ imports: [DummyModule], - }).compile(); - dummyRepository = module.get(DummyRepository); - dummyService = module.get(DummyService); + }); + [dummyRepository, dummyService] = await getMocks([ + DummyRepository, + DummyService, + ]); }); afterEach(jest.clearAllMocks); afterAll(closeInMongodConnection); diff --git a/api/src/utils/test/utils.ts b/api/src/utils/test/utils.ts new file mode 100644 index 00000000..13da6e7d --- /dev/null +++ b/api/src/utils/test/utils.ts @@ -0,0 +1,53 @@ +/* + * Copyright © 2025 Hexastack. All rights reserved. + * + * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: + * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. + * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). + */ + +import { ModuleMetadata } from '@nestjs/common'; +import { EventEmitter2 } from '@nestjs/event-emitter'; +import { Test, TestingModule } from '@nestjs/testing'; + +import { LoggerService } from '@/logger/logger.service'; + +type TTypeOrToken = [ + new (...args: any[]) => any, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + ...(new (...args: any[]) => any[]), +]; +const findInstances = async ( + type: keyof TestingModule, + module: TestingModule, + typesOrTokens: T, +): Promise<{ [K in keyof T]: InstanceType }> => + Promise.all( + typesOrTokens.map((typeOrToken) => + module[type.toString()]>(typeOrToken), + ), + ); + +const extractInstances = + (type: keyof TestingModule, module: TestingModule) => + async (types: T) => + await findInstances(type, module, types); + +export const buildTestingMocks = async ({ + providers, + ...rest +}: ModuleMetadata) => { + const module = await Test.createTestingModule({ + ...rest, + ...(providers && { + providers: [LoggerService, EventEmitter2, ...providers], + }), + }).compile(); + + return { + module, + getMocks: extractInstances('get', module), + resolveMocks: extractInstances('resolve', module), + }; +}; diff --git a/api/src/websocket/websocket.gateway.spec.ts b/api/src/websocket/websocket.gateway.spec.ts index b47cedac..d64e3a3b 100644 --- a/api/src/websocket/websocket.gateway.spec.ts +++ b/api/src/websocket/websocket.gateway.spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -8,14 +8,13 @@ import { INestApplication } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; -import { Test } from '@nestjs/testing'; import { Socket, io } from 'socket.io-client'; -import { LoggerService } from '@/logger/logger.service'; import { closeInMongodConnection, rootMongooseTestModule, } from '@/utils/test/test'; +import { buildTestingMocks } from '@/utils/test/utils'; import { SocketEventDispatcherService } from './services/socket-event-dispatcher.service'; import { WebsocketGateway } from './websocket.gateway'; @@ -27,10 +26,9 @@ describe('WebsocketGateway', () => { beforeAll(async () => { // Instantiate the app - const testingModule = await Test.createTestingModule({ + const { module } = await buildTestingMocks({ providers: [ WebsocketGateway, - LoggerService, EventEmitter2, SocketEventDispatcherService, ], @@ -41,8 +39,8 @@ describe('WebsocketGateway', () => { return Promise.resolve(); }), ], - }).compile(); - app = testingModule.createNestApplication(); + }); + app = module.createNestApplication(); // Get the gateway instance from the app instance gateway = app.get(WebsocketGateway); // Create a new client that will interact with the gateway diff --git a/api/test/app.e2e-spec.ts b/api/test/app.e2e-spec.ts index 8aa73c07..f78c3fbc 100644 --- a/api/test/app.e2e-spec.ts +++ b/api/test/app.e2e-spec.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -7,20 +7,21 @@ */ import { INestApplication } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; import request from 'supertest'; +import { buildTestingMocks } from '@/utils/test/utils'; + import { HexabotModule } from './../src/app.module'; describe('AppController (e2e)', () => { let app: INestApplication; beforeEach(async () => { - const moduleFixture: TestingModule = await Test.createTestingModule({ + const { module } = await buildTestingMocks({ imports: [HexabotModule], - }).compile(); + }); - app = moduleFixture.createNestApplication(); + app = module.createNestApplication(); await app.init(); });