-
Notifications
You must be signed in to change notification settings - Fork 71
Feat: remove container #190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,85 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { AuthModuleFactory } from "../../factories/auth.factory"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { PrismaUserRepository } from "../../../user/repositories/PrismaUserRepository"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { SendVerificationEmailUseCase } from "../../use-cases/send-verification-email.usecase"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ResendVerificationEmailUseCase } from "../../use-cases/resend-verification-email.usecase"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { VerifyEmailUseCase } from "../../use-cases/verify-email.usecase"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ValidateWalletFormatUseCase } from "../../use-cases/wallet-format-validation.usecase"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { VerifyWalletUseCase } from "../../use-cases/verify-wallet.usecase"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Mock the dependencies | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jest.mock("../../../user/repositories/PrismaUserRepository"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jest.mock("../../use-cases/send-verification-email.usecase"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jest.mock("../../use-cases/resend-verification-email.usecase"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jest.mock("../../use-cases/verify-email.usecase"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jest.mock("../../use-cases/wallet-format-validation.usecase"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jest.mock("../../use-cases/verify-wallet.usecase"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| describe("AuthModuleFactory", () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mockUserRepository: jest.Mocked<PrismaUserRepository>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mockSendVerificationEmailUseCase: jest.Mocked<SendVerificationEmailUseCase>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mockResendVerificationEmailUseCase: jest.Mocked<ResendVerificationEmailUseCase>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mockVerifyEmailUseCase: jest.Mocked<VerifyEmailUseCase>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mockValidateWalletFormatUseCase: jest.Mocked<ValidateWalletFormatUseCase>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mockVerifyWalletUseCase: jest.Mocked<VerifyWalletUseCase>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| beforeEach(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jest.clearAllMocks(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Create mock instances | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mockUserRepository = new PrismaUserRepository() as jest.Mocked<PrismaUserRepository>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mockSendVerificationEmailUseCase = new SendVerificationEmailUseCase(mockUserRepository) as jest.Mocked<SendVerificationEmailUseCase>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mockResendVerificationEmailUseCase = new ResendVerificationEmailUseCase(mockUserRepository) as jest.Mocked<ResendVerificationEmailUseCase>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mockVerifyEmailUseCase = new VerifyEmailUseCase(mockUserRepository) as jest.Mocked<VerifyEmailUseCase>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mockValidateWalletFormatUseCase = new ValidateWalletFormatUseCase() as jest.Mocked<ValidateWalletFormatUseCase>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mockVerifyWalletUseCase = new VerifyWalletUseCase() as jest.Mocked<VerifyWalletUseCase>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Mock the constructors | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (PrismaUserRepository as jest.Mock).mockImplementation(() => mockUserRepository); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (SendVerificationEmailUseCase as jest.Mock).mockImplementation(() => mockSendVerificationEmailUseCase); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (ResendVerificationEmailUseCase as jest.Mock).mockImplementation(() => mockResendVerificationEmailUseCase); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (VerifyEmailUseCase as jest.Mock).mockImplementation(() => mockVerifyEmailUseCase); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (ValidateWalletFormatUseCase as jest.Mock).mockImplementation(() => mockValidateWalletFormatUseCase); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (VerifyWalletUseCase as jest.Mock).mockImplementation(() => mockVerifyWalletUseCase); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+25
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not instantiate mocked classes in setup; it corrupts constructor call counts. Creating mocks via beforeEach(() => {
jest.clearAllMocks();
- // Create mock instances
- mockUserRepository = new PrismaUserRepository() as jest.Mocked<PrismaUserRepository>;
- mockSendVerificationEmailUseCase = new SendVerificationEmailUseCase(mockUserRepository) as jest.Mocked<SendVerificationEmailUseCase>;
- mockResendVerificationEmailUseCase = new ResendVerificationEmailUseCase(mockUserRepository) as jest.Mocked<ResendVerificationEmailUseCase>;
- mockVerifyEmailUseCase = new VerifyEmailUseCase(mockUserRepository) as jest.Mocked<VerifyEmailUseCase>;
- mockValidateWalletFormatUseCase = new ValidateWalletFormatUseCase() as jest.Mocked<ValidateWalletFormatUseCase>;
- mockVerifyWalletUseCase = new VerifyWalletUseCase() as jest.Mocked<VerifyWalletUseCase>;
+ // Create stub instances (no constructor calls)
+ mockUserRepository = {} as unknown as jest.Mocked<PrismaUserRepository>;
+ mockSendVerificationEmailUseCase = {} as unknown as jest.Mocked<SendVerificationEmailUseCase>;
+ mockResendVerificationEmailUseCase = {} as unknown as jest.Mocked<ResendVerificationEmailUseCase>;
+ mockVerifyEmailUseCase = {} as unknown as jest.Mocked<VerifyEmailUseCase>;
+ mockValidateWalletFormatUseCase = {} as unknown as jest.Mocked<ValidateWalletFormatUseCase>;
+ mockVerifyWalletUseCase = {} as unknown as jest.Mocked<VerifyWalletUseCase>;
// Mock the constructors
- (PrismaUserRepository as jest.Mock).mockImplementation(() => mockUserRepository);
- (SendVerificationEmailUseCase as jest.Mock).mockImplementation(() => mockSendVerificationEmailUseCase);
- (ResendVerificationEmailUseCase as jest.Mock).mockImplementation(() => mockResendVerificationEmailUseCase);
- (VerifyEmailUseCase as jest.Mock).mockImplementation(() => mockVerifyEmailUseCase);
- (ValidateWalletFormatUseCase as jest.Mock).mockImplementation(() => mockValidateWalletFormatUseCase);
- (VerifyWalletUseCase as jest.Mock).mockImplementation(() => mockVerifyWalletUseCase);
+ (PrismaUserRepository as jest.Mock).mockReturnValue(mockUserRepository);
+ (SendVerificationEmailUseCase as jest.Mock).mockReturnValue(mockSendVerificationEmailUseCase);
+ (ResendVerificationEmailUseCase as jest.Mock).mockReturnValue(mockResendVerificationEmailUseCase);
+ (VerifyEmailUseCase as jest.Mock).mockReturnValue(mockVerifyEmailUseCase);
+ (ValidateWalletFormatUseCase as jest.Mock).mockReturnValue(mockValidateWalletFormatUseCase);
+ (VerifyWalletUseCase as jest.Mock).mockReturnValue(mockVerifyWalletUseCase);
});π Committable suggestion
Suggested change
π€ Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| describe("createAuthController", () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it("should create all required use cases with proper dependencies", () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const authUseCases = AuthModuleFactory.createAuthController(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Verify all use cases are created | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(authUseCases.sendVerificationEmailUseCase).toBeDefined(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(authUseCases.resendVerificationEmailUseCase).toBeDefined(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(authUseCases.verifyEmailUseCase).toBeDefined(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(authUseCases.validateWalletFormatUseCase).toBeDefined(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(authUseCases.verifyWalletUseCase).toBeDefined(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Verify constructors were called with correct dependencies | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(PrismaUserRepository).toHaveBeenCalledTimes(1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(SendVerificationEmailUseCase).toHaveBeenCalledWith(mockUserRepository); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(ResendVerificationEmailUseCase).toHaveBeenCalledWith(mockUserRepository); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(VerifyEmailUseCase).toHaveBeenCalledWith(mockUserRepository); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(ValidateWalletFormatUseCase).toHaveBeenCalledTimes(1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(VerifyWalletUseCase).toHaveBeenCalledTimes(1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it("should return different instances on each call", () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const firstInstance = AuthModuleFactory.createAuthController(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const secondInstance = AuthModuleFactory.createAuthController(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(firstInstance).not.toBe(secondInstance); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(firstInstance.sendVerificationEmailUseCase).not.toBe(secondInstance.sendVerificationEmailUseCase); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it("should create use cases with the same user repository instance", () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const authUseCases = AuthModuleFactory.createAuthController(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // All use cases that depend on user repository should use the same instance | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(authUseCases.sendVerificationEmailUseCase).toBeDefined(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(authUseCases.resendVerificationEmailUseCase).toBeDefined(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(authUseCases.verifyEmailUseCase).toBeDefined(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Verify the user repository was created only once | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(PrismaUserRepository).toHaveBeenCalledTimes(1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import { PrismaUserRepository } from "../../user/repositories/PrismaUserRepository"; | ||
| import { SendVerificationEmailUseCase } from "../use-cases/send-verification-email.usecase"; | ||
| import { ResendVerificationEmailUseCase } from "../use-cases/resend-verification-email.usecase"; | ||
| import { VerifyEmailUseCase } from "../use-cases/verify-email.usecase"; | ||
| import { ValidateWalletFormatUseCase } from "../use-cases/wallet-format-validation.usecase"; | ||
| import { VerifyWalletUseCase } from "../use-cases/verify-wallet.usecase"; | ||
|
|
||
| export class AuthModuleFactory { | ||
| static createAuthController() { | ||
| const userRepository = new PrismaUserRepository(); | ||
| const sendVerificationEmailUseCase = new SendVerificationEmailUseCase(userRepository); | ||
| const resendVerificationEmailUseCase = new ResendVerificationEmailUseCase(userRepository); | ||
| const verifyEmailUseCase = new VerifyEmailUseCase(userRepository); | ||
| const validateWalletFormatUseCase = new ValidateWalletFormatUseCase(); | ||
| const verifyWalletUseCase = new VerifyWalletUseCase(); | ||
|
|
||
| return { | ||
| sendVerificationEmailUseCase, | ||
| resendVerificationEmailUseCase, | ||
| verifyEmailUseCase, | ||
| validateWalletFormatUseCase, | ||
| verifyWalletUseCase, | ||
| }; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,43 @@ | ||||||||||||||||||||||||||||||||||||
| import { CertificateModuleFactory } from "../../factories/certificate.factory"; | ||||||||||||||||||||||||||||||||||||
| import { CertificateService } from "../../application/services/CertificateService"; | ||||||||||||||||||||||||||||||||||||
| import { ICertificateService } from "../../domain/interfaces/ICertificateService"; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // Mock the CertificateService | ||||||||||||||||||||||||||||||||||||
| jest.mock("../../application/services/CertificateService"); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| describe("CertificateModuleFactory", () => { | ||||||||||||||||||||||||||||||||||||
| let mockCertificateService: jest.Mocked<CertificateService>; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| beforeEach(() => { | ||||||||||||||||||||||||||||||||||||
| jest.clearAllMocks(); | ||||||||||||||||||||||||||||||||||||
| mockCertificateService = new CertificateService() as jest.Mocked<CertificateService>; | ||||||||||||||||||||||||||||||||||||
| (CertificateService as jest.Mock).mockImplementation(() => mockCertificateService); | ||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+11
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test mutates constructor call counts before assertions Instantiating Apply this diff to avoid pre-instantiation and still control the returned mock: beforeEach(() => {
- jest.clearAllMocks();
- mockCertificateService = new CertificateService() as jest.Mocked<CertificateService>;
- (CertificateService as jest.Mock).mockImplementation(() => mockCertificateService);
+ jest.clearAllMocks();
+ // Return a fresh mock on each factory call without invoking the constructor early
+ (CertificateService as unknown as jest.Mock).mockImplementation(() => {
+ return Object.assign(Object.create(CertificateService.prototype), {
+ createCertificate: jest.fn(),
+ getCertificateUrl: jest.fn(),
+ getCertificateBuffer: jest.fn(),
+ logDownload: jest.fn(),
+ }) as CertificateService;
+ });
});π Committable suggestion
Suggested change
π€ Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| describe("createCertificateService", () => { | ||||||||||||||||||||||||||||||||||||
| it("should create a certificate service instance", () => { | ||||||||||||||||||||||||||||||||||||
| const certificateService = CertificateModuleFactory.createCertificateService(); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| expect(certificateService).toBeDefined(); | ||||||||||||||||||||||||||||||||||||
| expect(CertificateService).toHaveBeenCalledTimes(1); | ||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| it("should return an instance that implements ICertificateService", () => { | ||||||||||||||||||||||||||||||||||||
| const certificateService = CertificateModuleFactory.createCertificateService(); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| expect(certificateService).toBeInstanceOf(CertificateService); | ||||||||||||||||||||||||||||||||||||
| expect(typeof certificateService.createCertificate).toBe("function"); | ||||||||||||||||||||||||||||||||||||
| expect(typeof certificateService.getCertificateUrl).toBe("function"); | ||||||||||||||||||||||||||||||||||||
| expect(typeof certificateService.getCertificateBuffer).toBe("function"); | ||||||||||||||||||||||||||||||||||||
| expect(typeof certificateService.logDownload).toBe("function"); | ||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| it("should return different instances on each call", () => { | ||||||||||||||||||||||||||||||||||||
| const firstInstance = CertificateModuleFactory.createCertificateService(); | ||||||||||||||||||||||||||||||||||||
| const secondInstance = CertificateModuleFactory.createCertificateService(); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| expect(firstInstance).not.toBe(secondInstance); | ||||||||||||||||||||||||||||||||||||
| expect(CertificateService).toHaveBeenCalledTimes(2); | ||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import { CertificateService } from "../application/services/CertificateService"; | ||
| import { ICertificateService } from "../domain/interfaces/ICertificateService"; | ||
|
|
||
| export class CertificateModuleFactory { | ||
| static createCertificateService(): ICertificateService { | ||
| return new CertificateService(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,66 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { MessagingModuleFactory } from "../../factories/messaging.factory"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { MessagingService } from "../../application/services/MessagingService"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { MessagingController } from "../../controllers/MessagingController"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { MessagePrismaRepository } from "../../repositories/implementations/message-prisma.repository"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { PrismaClient } from "@prisma/client"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Mock the dependencies | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jest.mock("../../application/services/MessagingService"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jest.mock("../../controllers/MessagingController"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jest.mock("../../repositories/implementations/message-prisma.repository"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jest.mock("@prisma/client"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| describe("MessagingModuleFactory", () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mockPrisma: jest.Mocked<PrismaClient>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mockMessageRepository: jest.Mocked<MessagePrismaRepository>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mockMessagingService: jest.Mocked<MessagingService>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mockMessagingController: jest.Mocked<MessagingController>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| beforeEach(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jest.clearAllMocks(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Create mock instances | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mockPrisma = new PrismaClient() as jest.Mocked<PrismaClient>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mockMessageRepository = new MessagePrismaRepository(mockPrisma) as jest.Mocked<MessagePrismaRepository>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mockMessagingService = new MessagingService(mockMessageRepository, mockPrisma) as jest.Mocked<MessagingService>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mockMessagingController = new MessagingController(mockMessagingService) as jest.Mocked<MessagingController>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Mock the constructors | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (PrismaClient as jest.Mock).mockImplementation(() => mockPrisma); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (MessagePrismaRepository as jest.Mock).mockImplementation(() => mockMessageRepository); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (MessagingService as jest.Mock).mockImplementation(() => mockMessagingService); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (MessagingController as jest.Mock).mockImplementation(() => mockMessagingController); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+22
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pre-instantiating mocks inflates constructor call counts Creating instances with Apply this diff to return stubs without early constructor calls and preserve - // Create mock instances
- mockPrisma = new PrismaClient() as jest.Mocked<PrismaClient>;
- mockMessageRepository = new MessagePrismaRepository(mockPrisma) as jest.Mocked<MessagePrismaRepository>;
- mockMessagingService = new MessagingService(mockMessageRepository, mockPrisma) as jest.Mocked<MessagingService>;
- mockMessagingController = new MessagingController(mockMessagingService) as jest.Mocked<MessagingController>;
-
- // Mock the constructors
- (PrismaClient as jest.Mock).mockImplementation(() => mockPrisma);
- (MessagePrismaRepository as jest.Mock).mockImplementation(() => mockMessageRepository);
- (MessagingService as jest.Mock).mockImplementation(() => mockMessagingService);
- (MessagingController as jest.Mock).mockImplementation(() => mockMessagingController);
+ // Provide stub instances without calling constructors
+ mockPrisma = {} as unknown as PrismaClient;
+ mockMessageRepository = {} as unknown as MessagePrismaRepository;
+ mockMessagingService = {
+ sendMessage: jest.fn(),
+ getConversation: jest.fn(),
+ markMessageAsRead: jest.fn(),
+ } as unknown as MessagingService;
+ const makeController = () => {
+ const ctrl = Object.create(MessagingController.prototype) as MessagingController;
+ (ctrl as any).sendMessage = jest.fn();
+ (ctrl as any).getConversation = jest.fn();
+ (ctrl as any).markAsRead = jest.fn();
+ return ctrl as jest.Mocked<MessagingController>;
+ };
+
+ // Mock the constructors to return the stubs
+ (PrismaClient as unknown as jest.Mock).mockImplementation(() => mockPrisma);
+ (MessagePrismaRepository as unknown as jest.Mock).mockImplementation(() => mockMessageRepository);
+ (MessagingService as unknown as jest.Mock).mockImplementation(() => mockMessagingService);
+ (MessagingController as unknown as jest.Mock).mockImplementation(() => makeController());π Committable suggestion
Suggested change
π€ Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| describe("createMessagingController", () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it("should create a messaging controller with all required dependencies", () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const messagingController = MessagingModuleFactory.createMessagingController(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(messagingController).toBeDefined(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(messagingController).toBeInstanceOf(MessagingController); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Verify constructors were called with correct dependencies | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(PrismaClient).toHaveBeenCalledTimes(1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(MessagePrismaRepository).toHaveBeenCalledWith(mockPrisma); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(MessagingService).toHaveBeenCalledWith(mockMessageRepository, mockPrisma); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(MessagingController).toHaveBeenCalledWith(mockMessagingService); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it("should return different instances on each call", () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const firstInstance = MessagingModuleFactory.createMessagingController(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const secondInstance = MessagingModuleFactory.createMessagingController(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(firstInstance).not.toBe(secondInstance); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(MessagingController).toHaveBeenCalledTimes(2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it("should create dependencies with proper wiring", () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const messagingController = MessagingModuleFactory.createMessagingController(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Verify the controller has the expected methods | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(typeof messagingController.sendMessage).toBe("function"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(typeof messagingController.getConversation).toBe("function"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(typeof messagingController.markAsRead).toBe("function"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import { MessagingService } from "../application/services/MessagingService"; | ||
| import { MessagingController } from "../controllers/MessagingController"; | ||
| import { MessagePrismaRepository } from "../repositories/implementations/message-prisma.repository"; | ||
| import { PrismaClient } from "@prisma/client"; | ||
|
|
||
| export class MessagingModuleFactory { | ||
| static createMessagingController(): MessagingController { | ||
| const prisma = new PrismaClient(); | ||
| const messageRepository = new MessagePrismaRepository(prisma); | ||
| const messagingService = new MessagingService(messageRepository, prisma); | ||
| return new MessagingController(messagingService); | ||
| } | ||
|
Comment on lines
+8
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Accept PrismaClient from caller; donβt instantiate here. Creating Prisma inside the factory impedes lifecycle control and can leak connections. Accept an injected instance instead. -export class MessagingModuleFactory {
- static createMessagingController(): MessagingController {
- const prisma = new PrismaClient();
- const messageRepository = new MessagePrismaRepository(prisma);
- const messagingService = new MessagingService(messageRepository, prisma);
- return new MessagingController(messagingService);
- }
-}
+export class MessagingModuleFactory {
+ static createMessagingController(prisma: PrismaClient): MessagingController {
+ const messageRepository = new MessagePrismaRepository(prisma);
+ const messagingService = new MessagingService(messageRepository, prisma);
+ return new MessagingController(messagingService);
+ }
+}Add graceful shutdown (app-level): // e.g., index.ts
process.on("SIGINT", async () => { await prisma.$disconnect(); process.exit(0); });
process.on("SIGTERM", async () => { await prisma.$disconnect(); process.exit(0); });π€ Prompt for AI Agents |
||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,16 +1,10 @@ | ||||||||||||||||||||||||||||||||||||||
| import { Router } from "express"; | ||||||||||||||||||||||||||||||||||||||
| import { MessagingController } from "../controllers/MessagingController"; | ||||||||||||||||||||||||||||||||||||||
| import { MessagingService } from "../application/services/MessagingService"; | ||||||||||||||||||||||||||||||||||||||
| import { MessagePrismaRepository } from "../repositories/implementations/message-prisma.repository"; | ||||||||||||||||||||||||||||||||||||||
| import { MessagingModuleFactory } from "../factories/messaging.factory"; | ||||||||||||||||||||||||||||||||||||||
| import { authMiddleware } from "../../../middleware/authMiddleware"; | ||||||||||||||||||||||||||||||||||||||
| import { PrismaClient } from "@prisma/client"; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const router = Router(); | ||||||||||||||||||||||||||||||||||||||
| const prisma = new PrismaClient(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const messageRepository = new MessagePrismaRepository(prisma); | ||||||||||||||||||||||||||||||||||||||
| const messagingService = new MessagingService(messageRepository, prisma); | ||||||||||||||||||||||||||||||||||||||
| const messagingController = new MessagingController(messagingService); | ||||||||||||||||||||||||||||||||||||||
| const messagingController = MessagingModuleFactory.createMessagingController(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+2
to
8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Avoid new PrismaClient per factory; inject app-scoped Prisma. Factory currently creates its own Prisma client, risking excess connections and no shutdown disposal. Import the shared prisma and pass it to the factory. -import { MessagingModuleFactory } from "../factories/messaging.factory";
+import { MessagingModuleFactory } from "../factories/messaging.factory";
+import { prisma } from "../../../config/prisma";
-const messagingController = MessagingModuleFactory.createMessagingController();
+const messagingController = MessagingModuleFactory.createMessagingController(prisma);And adjust the factory (see factory file comment) to accept a PrismaClient. π Committable suggestion
Suggested change
π€ Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| router.use(authMiddleware); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import { WalletService } from "../application/services/WalletService"; | ||
| import { HorizonWalletRepository } from "../repositories/HorizonWalletRepository"; | ||
| import { VerifyWalletUseCase } from "../use-cases/VerifyWalletUseCase"; | ||
| import { ValidateWalletFormatUseCase } from "../use-cases/ValidateWalletFormatUseCase"; | ||
|
|
||
| export class WalletModuleFactory { | ||
| static createWalletService(): WalletService { | ||
| const walletRepository = new HorizonWalletRepository(); | ||
| const verifyWalletUseCase = new VerifyWalletUseCase(walletRepository); | ||
| const validateWalletFormatUseCase = new ValidateWalletFormatUseCase(); | ||
|
|
||
| const walletService = new WalletService(); | ||
| (walletService as any).walletRepository = walletRepository; | ||
| (walletService as any).verifyWalletUseCase = verifyWalletUseCase; | ||
| (walletService as any).validateWalletFormatUseCase = validateWalletFormatUseCase; | ||
|
Comment on lines
+12
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Remove any-cast field injection; use typed constructor injection. Assigning private deps via - const walletService = new WalletService();
- (walletService as any).walletRepository = walletRepository;
- (walletService as any).verifyWalletUseCase = verifyWalletUseCase;
- (walletService as any).validateWalletFormatUseCase = validateWalletFormatUseCase;
+ const walletService = new WalletService({
+ walletRepository,
+ verifyWalletUseCase,
+ validateWalletFormatUseCase,
+ });Outside this file, update WalletService to accept deps: // WalletService.ts
export interface WalletServiceDeps {
walletRepository: HorizonWalletRepository; // or interface type
verifyWalletUseCase: VerifyWalletUseCase;
validateWalletFormatUseCase: ValidateWalletFormatUseCase;
}
export class WalletService {
constructor(private readonly deps: WalletServiceDeps) {}
// use: this.deps.verifyWalletUseCase, etc.
}π€ Prompt for AI Agents |
||
|
|
||
| return walletService; | ||
| } | ||
| } | ||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π‘ Verification agent
π§© Analysis chain
Supabase env vars: add service role key note and align .env.example.
Document the server-only SUPABASE_SERVICE_ROLE_KEY and warn against committing secrets. Also ensure .env.example includes these vars.
Apply:
Length of output: 400
Add SUPABASE_SERVICE_ROLE_KEY to README and .env.example
SUPABASE_SERVICE_ROLE_KEY=β¦ # Server-only key for admin operations (never expose publicly)to the env snippet.
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key.π§° Tools
πͺ LanguageTool
[grammar] ~239-~239: There might be a mistake here.
Context: ...eed ``` --- ## π Supabase Integration This project uses Supabase for external ...
(QB_NEW_EN)
π€ Prompt for AI Agents