diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8bb26407..ced9c802 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,6 +30,34 @@ Theses are just some examples of the hidden costs that are not so apparent from * Do not open an issue on GitHub until you have collected positive feedback about the change. GitHub issues are primarily intended for bug reports and fixes. + +#### **How can i create my first contribution ?** + +- **Find an Issue:** + Start by finding an issue to work on. You can either create a new GitHub issue or pick one that has been assigned to you. + +- **Create a Branch:** + Create a new branch for your work. Use a descriptive name that reflects the issue or feature you're addressing (e.g., fix/login-bug or add/feature-x). + +- **Make Changes:** + Write or fix the code in your branch. Ensure your changes align with the project's coding standards and guidelines. + +- **Push Changes:** + Once your changes are ready, push your branch to GitHub. + +- **Open a Pull Request (PR):** + Create a pull request (PR) from your branch. Include a clear and concise description of your changes, explaining what the PR does and why it’s needed. Make sure to reference the related issue (e.g., "Fixes #123"). + Note: At least two reviewers are required to approve the PR before it can be merged. + +- **Review Process:** + Team members will review your code, provide feedback, and suggest improvements. Be open to constructive criticism and ready to iterate on your work. + +- **Address Feedback:** + Make any necessary changes based on the feedback. Once you’ve addressed the comments, tag the reviewers to let them know your updates are ready for another review. + +- **Merge:** + Once your PR is approved by at least two reviewers, it will be merged into the main project. Congratulations, your code is now part of the project! + #### **Do you have questions about the source code?** * Ask any question about how to use Hexabot in our [Discord Channel](https://discord.gg/rNb9t2MFkG). 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/repositories/bot-stats.repository.ts b/api/src/analytics/repositories/bot-stats.repository.ts index 4c6f7c86..d8ee3221 100644 --- a/api/src/analytics/repositories/bot-stats.repository.ts +++ b/api/src/analytics/repositories/bot-stats.repository.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 { Injectable } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; @@ -17,11 +16,8 @@ import { BotStats, BotStatsType } from '../schemas/bot-stats.schema'; @Injectable() export class BotStatsRepository extends BaseRepository { - constructor( - readonly eventEmitter: EventEmitter2, - @InjectModel(BotStats.name) readonly model: Model, - ) { - super(eventEmitter, model, BotStats); + constructor(@InjectModel(BotStats.name) readonly model: Model) { + super(model, BotStats); } /** 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/analytics/services/bot-stats.service.ts b/api/src/analytics/services/bot-stats.service.ts index 2b319a66..4d87f64b 100644 --- a/api/src/analytics/services/bot-stats.service.ts +++ b/api/src/analytics/services/bot-stats.service.ts @@ -7,11 +7,10 @@ */ import { Injectable } from '@nestjs/common'; -import { EventEmitter2, OnEvent } from '@nestjs/event-emitter'; +import { OnEvent } from '@nestjs/event-emitter'; import { Subscriber } from '@/chat/schemas/subscriber.schema'; import { config } from '@/config'; -import { LoggerService } from '@/logger/logger.service'; import { BaseService } from '@/utils/generics/base-service'; import { BotStatsRepository } from '../repositories/bot-stats.repository'; @@ -19,11 +18,7 @@ import { BotStats, BotStatsType } from '../schemas/bot-stats.schema'; @Injectable() export class BotStatsService extends BaseService { - constructor( - readonly repository: BotStatsRepository, - private readonly eventEmitter: EventEmitter2, - private readonly logger: LoggerService, - ) { + constructor(readonly repository: BotStatsRepository) { super(repository); } @@ -98,8 +93,9 @@ export class BotStatsService extends BaseService { ) { this.eventEmitter.emit( 'hook:stats:entry', - 'retention', + BotStatsType.retention, 'Retentioned users', + subscriber, ); } } @@ -111,7 +107,11 @@ export class BotStatsService extends BaseService { * @param name - The name or identifier of the statistics entry (e.g., a specific feature or component being tracked). */ @OnEvent('hook:stats:entry') - async handleStatEntry(type: BotStatsType, name: string): Promise { + async handleStatEntry( + type: BotStatsType, + name: string, + _subscriber: Subscriber, + ): Promise { const day = new Date(); day.setMilliseconds(0); day.setSeconds(0); diff --git a/api/src/app.controller.ts b/api/src/app.controller.ts index c8e9dd4f..305d9b1f 100644 --- a/api/src/app.controller.ts +++ b/api/src/app.controller.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. @@ -13,15 +13,11 @@ import { Request } from 'express'; import { Session as ExpressSession } from 'express-session'; import { AppService } from './app.service'; -import { LoggerService } from './logger/logger.service'; import { Roles } from './utils/decorators/roles.decorator'; @Controller() export class AppController { - constructor( - private readonly appService: AppService, - private readonly logger: LoggerService, - ) {} + constructor(private readonly appService: AppService) {} @Roles('public') @Get() diff --git a/api/src/app.module.ts b/api/src/app.module.ts index 86c35c44..72465eb3 100644 --- a/api/src/app.module.ts +++ b/api/src/app.module.ts @@ -35,6 +35,7 @@ import { ChannelModule } from './channel/channel.module'; import { ChatModule } from './chat/chat.module'; import { CmsModule } from './cms/cms.module'; import { config } from './config'; +import { ExtensionModule } from './extension/extension.module'; import extraModules from './extra'; import { HelperModule } from './helper/helper.module'; import { I18nModule } from './i18n/i18n.module'; @@ -152,6 +153,7 @@ const i18nOptions: I18nOptions = { max: config.cache.max, }), MigrationModule, + ExtensionModule, ...extraModules, ], controllers: [AppController], 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/controllers/attachment.controller.ts b/api/src/attachment/controllers/attachment.controller.ts index 8f794e03..44cbe661 100644 --- a/api/src/attachment/controllers/attachment.controller.ts +++ b/api/src/attachment/controllers/attachment.controller.ts @@ -30,7 +30,6 @@ import { diskStorage, memoryStorage } from 'multer'; import { config } from '@/config'; import { CsrfInterceptor } from '@/interceptors/csrf.interceptor'; -import { LoggerService } from '@/logger/logger.service'; import { Roles } from '@/utils/decorators/roles.decorator'; import { BaseController } from '@/utils/generics/base-controller'; import { DeleteResult } from '@/utils/generics/base-repository'; @@ -52,10 +51,7 @@ import { AttachmentAccess, AttachmentCreatedByRef } from '../types'; @Controller('attachment') @UseGuards(AttachmentGuard) export class AttachmentController extends BaseController { - constructor( - private readonly attachmentService: AttachmentService, - private readonly logger: LoggerService, - ) { + constructor(private readonly attachmentService: AttachmentService) { super(attachmentService); } 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/attachment/repositories/attachment.repository.ts b/api/src/attachment/repositories/attachment.repository.ts index a686cd43..005b9f24 100644 --- a/api/src/attachment/repositories/attachment.repository.ts +++ b/api/src/attachment/repositories/attachment.repository.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 { Injectable } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; @@ -17,10 +16,7 @@ import { Attachment } from '../schemas/attachment.schema'; @Injectable() export class AttachmentRepository extends BaseRepository { - constructor( - readonly eventEmitter: EventEmitter2, - @InjectModel(Attachment.name) readonly model: Model, - ) { - super(eventEmitter, model, Attachment); + constructor(@InjectModel(Attachment.name) readonly model: Model) { + super(model, Attachment); } } diff --git a/api/src/attachment/services/attachment.service.ts b/api/src/attachment/services/attachment.service.ts index bf0674f1..fc7cf231 100644 --- a/api/src/attachment/services/attachment.service.ts +++ b/api/src/attachment/services/attachment.service.ts @@ -12,7 +12,6 @@ import { Injectable, Optional, StreamableFile } from '@nestjs/common'; import { HelperService } from '@/helper/helper.service'; import { HelperType } from '@/helper/types'; -import { LoggerService } from '@/logger/logger.service'; import { BaseService } from '@/utils/generics/base-service'; import { AttachmentMetadataDto } from '../dto/attachment.dto'; @@ -23,7 +22,6 @@ import { Attachment } from '../schemas/attachment.schema'; export class AttachmentService extends BaseService { constructor( readonly repository: AttachmentRepository, - private readonly logger: LoggerService, @Optional() private readonly helperService: HelperService, ) { super(repository); diff --git a/api/src/chat/controllers/block.controller.spec.ts b/api/src/chat/controllers/block.controller.spec.ts index 74e73021..24945c3d 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'; @@ -53,6 +51,7 @@ import { CategoryRepository } from '../repositories/category.repository'; import { LabelRepository } from '../repositories/label.repository'; import { Block, BlockModel } from '../schemas/block.schema'; import { LabelModel } from '../schemas/label.schema'; +import { PayloadType } from '../schemas/types/button'; import { BlockService } from '../services/block.service'; import { CategoryService } from '../services/category.service'; import { LabelService } from '../services/label.service'; @@ -79,7 +78,7 @@ describe('BlockController', () => { ]; beforeAll(async () => { - const module = await Test.createTestingModule({ + const { getMocks } = await buildTestingMocks({ controllers: [BlockController], imports: [ rootMongooseTestModule(installBlockFixtures), @@ -117,7 +116,6 @@ describe('BlockController', () => { PermissionService, LanguageService, PluginService, - LoggerService, { provide: I18nService, useValue: { @@ -133,7 +131,6 @@ describe('BlockController', () => { getSettings: jest.fn(() => ({})), }, }, - EventEmitter2, { provide: CACHE_MANAGER, useValue: { @@ -143,10 +140,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' }))!; @@ -336,4 +335,56 @@ describe('BlockController', () => { ).rejects.toThrow(getUpdateOneError(Block.name, blockToDelete.id)); }); }); + + it('should update block trigger to postback menu', async () => { + jest.spyOn(blockService, 'updateOne'); + const updateBlock: BlockUpdateDto = { + patterns: [ + { + label: 'postback123', + value: 'postback123', + type: PayloadType.menu, + }, + ], + }; + const result = await blockController.updateOne(block.id, updateBlock); + expect(blockService.updateOne).toHaveBeenCalledWith(block.id, updateBlock); + + expect( + result.patterns.find( + (pattern) => + typeof pattern === 'object' && + 'type' in pattern && + pattern.type === PayloadType.menu && + pattern, + ), + ).toBeDefined(); + expect(result.patterns).toEqual(updateBlock.patterns); + }); + + it('should update the block trigger with a content payloadType payload', async () => { + jest.spyOn(blockService, 'updateOne'); + const updateBlock: BlockUpdateDto = { + patterns: [ + { + label: 'Content label', + value: 'Content value', + type: PayloadType.content, + }, + ], + }; + const result = await blockController.updateOne(block.id, updateBlock); + expect(blockService.updateOne).toHaveBeenCalledWith(block.id, updateBlock); + + expect( + result.patterns.find( + (pattern) => + typeof pattern === 'object' && + 'type' in pattern && + pattern.type === PayloadType.content && + pattern, + ), + ).toBeDefined(); + expect(result.patterns).toEqual(updateBlock.patterns); + }); }); diff --git a/api/src/chat/controllers/block.controller.ts b/api/src/chat/controllers/block.controller.ts index 92b48823..4428e141 100644 --- a/api/src/chat/controllers/block.controller.ts +++ b/api/src/chat/controllers/block.controller.ts @@ -23,7 +23,6 @@ import { import { CsrfCheck } from '@tekuconcept/nestjs-csrf'; import { CsrfInterceptor } from '@/interceptors/csrf.interceptor'; -import { LoggerService } from '@/logger/logger.service'; import { BaseBlockPlugin } from '@/plugins/base-block-plugin'; import { PluginService } from '@/plugins/plugins.service'; import { PluginName, PluginType } from '@/plugins/types'; @@ -57,7 +56,6 @@ export class BlockController extends BaseController< > { constructor( private readonly blockService: BlockService, - private readonly logger: LoggerService, private readonly categoryService: CategoryService, private readonly labelService: LabelService, private readonly userService: UserService, 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/category.controller.ts b/api/src/chat/controllers/category.controller.ts index 3f3a49b6..9cb27cc5 100644 --- a/api/src/chat/controllers/category.controller.ts +++ b/api/src/chat/controllers/category.controller.ts @@ -23,7 +23,6 @@ import { import { CsrfCheck } from '@tekuconcept/nestjs-csrf'; import { CsrfInterceptor } from '@/interceptors/csrf.interceptor'; -import { LoggerService } from '@/logger/logger.service'; import { BaseController } from '@/utils/generics/base-controller'; import { DeleteResult } from '@/utils/generics/base-repository'; import { PageQueryDto } from '@/utils/pagination/pagination-query.dto'; @@ -38,10 +37,7 @@ import { CategoryService } from '../services/category.service'; @UseInterceptors(CsrfInterceptor) @Controller('category') export class CategoryController extends BaseController { - constructor( - private readonly categoryService: CategoryService, - private readonly logger: LoggerService, - ) { + constructor(private readonly categoryService: CategoryService) { super(categoryService); } 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/context-var.controller.ts b/api/src/chat/controllers/context-var.controller.ts index 1d16f92c..52358b4e 100644 --- a/api/src/chat/controllers/context-var.controller.ts +++ b/api/src/chat/controllers/context-var.controller.ts @@ -23,7 +23,6 @@ import { import { CsrfCheck } from '@tekuconcept/nestjs-csrf'; import { CsrfInterceptor } from '@/interceptors/csrf.interceptor'; -import { LoggerService } from '@/logger/logger.service'; import { BaseController } from '@/utils/generics/base-controller'; import { DeleteResult } from '@/utils/generics/base-repository'; import { PageQueryDto } from '@/utils/pagination/pagination-query.dto'; @@ -41,10 +40,7 @@ import { ContextVarService } from '../services/context-var.service'; @UseInterceptors(CsrfInterceptor) @Controller('contextvar') export class ContextVarController extends BaseController { - constructor( - private readonly contextVarService: ContextVarService, - private readonly logger: LoggerService, - ) { + constructor(private readonly contextVarService: ContextVarService) { super(contextVarService); } 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/label.controller.ts b/api/src/chat/controllers/label.controller.ts index 976d9c0c..791599af 100644 --- a/api/src/chat/controllers/label.controller.ts +++ b/api/src/chat/controllers/label.controller.ts @@ -23,7 +23,6 @@ import { import { CsrfCheck } from '@tekuconcept/nestjs-csrf'; import { CsrfInterceptor } from '@/interceptors/csrf.interceptor'; -import { LoggerService } from '@/logger/logger.service'; import { BaseController } from '@/utils/generics/base-controller'; import { DeleteResult } from '@/utils/generics/base-repository'; import { PageQueryDto } from '@/utils/pagination/pagination-query.dto'; @@ -49,10 +48,7 @@ export class LabelController extends BaseController< LabelPopulate, LabelFull > { - constructor( - private readonly labelService: LabelService, - private readonly logger: LoggerService, - ) { + constructor(private readonly labelService: LabelService) { super(labelService); } 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/message.controller.ts b/api/src/chat/controllers/message.controller.ts index dda5430d..b75e6f84 100644 --- a/api/src/chat/controllers/message.controller.ts +++ b/api/src/chat/controllers/message.controller.ts @@ -18,14 +18,12 @@ import { Req, UseInterceptors, } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { CsrfCheck } from '@tekuconcept/nestjs-csrf'; import { Request } from 'express'; // Import the Express request and response types import { ChannelService } from '@/channel/channel.service'; import { GenericEventWrapper } from '@/channel/lib/EventWrapper'; import { CsrfInterceptor } from '@/interceptors/csrf.interceptor'; -import { LoggerService } from '@/logger/logger.service'; import { BaseController } from '@/utils/generics/base-controller'; import { BaseSchema } from '@/utils/generics/base-schema'; import { PageQueryDto } from '@/utils/pagination/pagination-query.dto'; @@ -65,8 +63,6 @@ export class MessageController extends BaseController< private readonly messageService: MessageService, private readonly subscriberService: SubscriberService, private readonly channelService: ChannelService, - private readonly logger: LoggerService, - private readonly eventEmitter: EventEmitter2, ) { super(messageService); } @@ -168,7 +164,7 @@ export class MessageController extends BaseController< read: false, delivery: false, }; - this.eventEmitter.emit('hook:chatbot:sent', sentMessage); + this.eventEmitter.emit('hook:chatbot:sent', sentMessage, event); return { success: true, }; 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/controllers/subscriber.controller.ts b/api/src/chat/controllers/subscriber.controller.ts index 69205952..e2c8ad46 100644 --- a/api/src/chat/controllers/subscriber.controller.ts +++ b/api/src/chat/controllers/subscriber.controller.ts @@ -21,7 +21,6 @@ import { CsrfCheck } from '@tekuconcept/nestjs-csrf'; import { AttachmentService } from '@/attachment/services/attachment.service'; import { CsrfInterceptor } from '@/interceptors/csrf.interceptor'; -import { LoggerService } from '@/logger/logger.service'; import { BaseController } from '@/utils/generics/base-controller'; import { generateInitialsAvatar } from '@/utils/helpers/avatar'; import { PageQueryDto } from '@/utils/pagination/pagination-query.dto'; @@ -50,7 +49,6 @@ export class SubscriberController extends BaseController< constructor( private readonly subscriberService: SubscriberService, private readonly attachmentService: AttachmentService, - private readonly logger: LoggerService, ) { super(subscriberService); } 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/block.repository.ts b/api/src/chat/repositories/block.repository.ts index c10f11c6..cb6c2616 100644 --- a/api/src/chat/repositories/block.repository.ts +++ b/api/src/chat/repositories/block.repository.ts @@ -6,8 +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 { Injectable, Optional } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; +import { Injectable } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Document, @@ -18,7 +17,6 @@ import { UpdateWithAggregationPipeline, } from 'mongoose'; -import { LoggerService } from '@/logger/logger.service'; import { BaseRepository, DeleteResult } from '@/utils/generics/base-repository'; import { TFilterQuery } from '@/utils/types/filter.types'; @@ -37,12 +35,8 @@ export class BlockRepository extends BaseRepository< BlockFull, BlockDto > { - constructor( - readonly eventEmitter: EventEmitter2, - @InjectModel(Block.name) readonly model: Model, - @Optional() private readonly logger?: LoggerService, - ) { - super(eventEmitter, model, Block, BLOCK_POPULATE, BlockFull); + constructor(@InjectModel(Block.name) readonly model: Model) { + super(model, Block, BLOCK_POPULATE, BlockFull); } /** diff --git a/api/src/chat/repositories/category.repository.ts b/api/src/chat/repositories/category.repository.ts index d3e6a213..69a9974c 100644 --- a/api/src/chat/repositories/category.repository.ts +++ b/api/src/chat/repositories/category.repository.ts @@ -7,7 +7,6 @@ */ import { ForbiddenException, Injectable, Optional } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { InjectModel } from '@nestjs/mongoose'; import { Document, Model, Query } from 'mongoose'; @@ -28,11 +27,10 @@ export class CategoryRepository extends BaseRepository< private readonly blockService: BlockService; constructor( - readonly eventEmitter: EventEmitter2, @InjectModel(Category.name) readonly model: Model, @Optional() blockService?: BlockService, ) { - super(eventEmitter, model, Category); + super(model, Category); this.blockService = blockService!; } diff --git a/api/src/chat/repositories/context-var.repository.ts b/api/src/chat/repositories/context-var.repository.ts index 3432351e..fe3f7e35 100644 --- a/api/src/chat/repositories/context-var.repository.ts +++ b/api/src/chat/repositories/context-var.repository.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,7 +12,6 @@ import { NotFoundException, Optional, } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { InjectModel } from '@nestjs/mongoose'; import { Document, Model, Query } from 'mongoose'; @@ -33,11 +32,10 @@ export class ContextVarRepository extends BaseRepository< private readonly blockService: BlockService; constructor( - readonly eventEmitter: EventEmitter2, @InjectModel(ContextVar.name) readonly model: Model, @Optional() blockService?: BlockService, ) { - super(eventEmitter, model, ContextVar); + super(model, ContextVar); if (blockService) this.blockService = blockService; } diff --git a/api/src/chat/repositories/conversation.repository.ts b/api/src/chat/repositories/conversation.repository.ts index c17c9c62..62cfbf59 100644 --- a/api/src/chat/repositories/conversation.repository.ts +++ b/api/src/chat/repositories/conversation.repository.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 { Injectable } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; @@ -29,16 +28,9 @@ export class ConversationRepository extends BaseRepository< ConversationDto > { constructor( - readonly eventEmitter: EventEmitter2, @InjectModel(Conversation.name) readonly model: Model, ) { - super( - eventEmitter, - model, - Conversation, - CONVERSATION_POPULATE, - ConversationFull, - ); + super(model, Conversation, CONVERSATION_POPULATE, ConversationFull); } /** 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/label.repository.ts b/api/src/chat/repositories/label.repository.ts index af7af401..bf5bcdd7 100644 --- a/api/src/chat/repositories/label.repository.ts +++ b/api/src/chat/repositories/label.repository.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 { Injectable } from '@nestjs/common'; -import { EventEmitter2 } from '@nestjs/event-emitter'; import { InjectModel } from '@nestjs/mongoose'; import { Document, Model, Query } from 'mongoose'; @@ -30,11 +29,8 @@ export class LabelRepository extends BaseRepository< LabelFull, LabelDto > { - constructor( - readonly eventEmitter: EventEmitter2, - @InjectModel(Label.name) readonly model: Model