// Mock dependencies jest.mock("../../../../../services/email/core/EmailClient", () => { return jest.fn().mockImplementation(() => ({ initialize: jest.fn().mockResolvedValue(), sendEmail: jest .fn() .mockResolvedValue({ success: true, messageId: "msg-123" }), })); }); jest.mock("../../../../../services/email/core/TemplateManager", () => { return jest.fn().mockImplementation(() => ({ initialize: jest.fn().mockResolvedValue(), renderTemplate: jest.fn().mockResolvedValue("Test"), })); }); const FeedbackEmailService = require("../../../../../services/email/domain/FeedbackEmailService"); describe("FeedbackEmailService", () => { let service; const originalEnv = process.env; beforeEach(() => { jest.clearAllMocks(); process.env = { ...originalEnv, CUSTOMER_SUPPORT_EMAIL: "feedback@example.com", }; service = new FeedbackEmailService(); }); afterEach(() => { process.env = originalEnv; }); describe("initialize", () => { it("should initialize only once", async () => { await service.initialize(); await service.initialize(); expect(service.emailClient.initialize).toHaveBeenCalledTimes(1); expect(service.templateManager.initialize).toHaveBeenCalledTimes(1); }); }); describe("sendFeedbackConfirmation", () => { it("should send feedback confirmation to user", async () => { const user = { firstName: "John", email: "john@example.com" }; const feedback = { feedbackText: "Great app!", createdAt: new Date(), }; const result = await service.sendFeedbackConfirmation(user, feedback); expect(result.success).toBe(true); expect(service.templateManager.renderTemplate).toHaveBeenCalledWith( "feedbackConfirmationToUser", expect.objectContaining({ userName: "John", userEmail: "john@example.com", feedbackText: "Great app!", }), ); expect(service.emailClient.sendEmail).toHaveBeenCalledWith( "john@example.com", "Thank You for Your Feedback - Village Share", expect.any(String), ); }); it("should use default name when firstName is missing", async () => { const user = { email: "john@example.com" }; const feedback = { feedbackText: "Great app!", createdAt: new Date(), }; await service.sendFeedbackConfirmation(user, feedback); expect(service.templateManager.renderTemplate).toHaveBeenCalledWith( "feedbackConfirmationToUser", expect.objectContaining({ userName: "there" }), ); }); }); describe("sendFeedbackNotificationToAdmin", () => { it("should send feedback notification to admin", async () => { const user = { id: "user-123", firstName: "John", lastName: "Doe", email: "john@example.com", }; const feedback = { id: "feedback-123", feedbackText: "Great app!", url: "https://example.com/page", userAgent: "Mozilla/5.0", createdAt: new Date(), }; const result = await service.sendFeedbackNotificationToAdmin( user, feedback, ); expect(result.success).toBe(true); expect(service.templateManager.renderTemplate).toHaveBeenCalledWith( "feedbackNotificationToAdmin", expect.objectContaining({ userName: "John Doe", userEmail: "john@example.com", userId: "user-123", feedbackText: "Great app!", feedbackId: "feedback-123", url: "https://example.com/page", userAgent: "Mozilla/5.0", }), ); expect(service.emailClient.sendEmail).toHaveBeenCalledWith( "feedback@example.com", "New Feedback from John Doe", expect.any(String), ); }); it("should return error when no admin email configured", async () => { delete process.env.CUSTOMER_SUPPORT_EMAIL; const user = { id: "user-123", firstName: "John", lastName: "Doe", email: "john@example.com", }; const feedback = { id: "feedback-123", feedbackText: "Test", createdAt: new Date(), }; const result = await service.sendFeedbackNotificationToAdmin( user, feedback, ); expect(result.success).toBe(false); expect(result.error).toContain("No admin email configured"); }); it("should use default values for optional fields", async () => { const user = { id: "user-123", firstName: "John", lastName: "Doe", email: "john@example.com", }; const feedback = { id: "feedback-123", feedbackText: "Test", createdAt: new Date(), }; await service.sendFeedbackNotificationToAdmin(user, feedback); expect(service.templateManager.renderTemplate).toHaveBeenCalledWith( "feedbackNotificationToAdmin", expect.objectContaining({ url: "Not provided", userAgent: "Not provided", }), ); }); }); });