// __tests__/unit/services/emailService.test.js const emailServiceModule = require("../../../src/services/emailService"); // Adjust path const { Resend } = require("resend"); const logger = require("../../../config/logger"); // Adjust path jest.mock("resend"); // Mock the Resend constructor and its methods jest.mock("../../../config/logger"); // Mock logger to spy on it describe("Email Service (Resend)", () => { const mockSend = jest.fn(); const originalResendApiKey = process.env.RESEND_API_KEY; const originalEmailFrom = process.env.EMAIL_FROM_ADDRESS; beforeEach(() => { mockSend.mockClear(); Resend.mockClear(); Resend.mockImplementation(() => ({ emails: { send: mockSend }, })); // Ensure env vars are set for these tests process.env.RESEND_API_KEY = "test-resend-api-key"; process.env.EMAIL_FROM_ADDRESS = "sender@example.com"; }); afterAll(() => { process.env.RESEND_API_KEY = originalResendApiKey; process.env.EMAIL_FROM_ADDRESS = originalEmailFrom; }); describe("sendSubmissionNotification", () => { const form = { name: "Test Form", email_notifications_enabled: true, notification_email_address: "custom@example.com", }; const submissionData = { name: "John Doe", message: "Hello" }; const userOwnerEmail = "owner@example.com"; it("should send email if notifications enabled and custom address provided", async () => { mockSend.mockResolvedValue({ data: { id: "email_id_123" }, error: null }); await emailServiceModule.sendSubmissionNotification( form, submissionData, userOwnerEmail ); expect(Resend).toHaveBeenCalledWith("test-resend-api-key"); expect(mockSend).toHaveBeenCalledWith({ from: "sender@example.com", to: "custom@example.com", subject: "New Submission for Form: Test Form", html: expect.stringContaining("Test Form"), }); expect(logger.info).toHaveBeenCalledWith( expect.stringContaining("Submission email sent successfully") ); }); it("should use owner email if custom address not provided", async () => { const formNoCustomEmail = { ...form, notification_email_address: null }; mockSend.mockResolvedValue({ data: { id: "email_id_123" }, error: null }); await emailServiceModule.sendSubmissionNotification( formNoCustomEmail, submissionData, userOwnerEmail ); expect(mockSend).toHaveBeenCalledWith( expect.objectContaining({ to: "owner@example.com", }) ); }); it("should not send email if notifications are disabled", async () => { const disabledForm = { ...form, email_notifications_enabled: false }; await emailServiceModule.sendSubmissionNotification( disabledForm, submissionData, userOwnerEmail ); expect(mockSend).not.toHaveBeenCalled(); expect(logger.info).toHaveBeenCalledWith( expect.stringContaining("Email notifications are disabled") ); }); it("should log error if Resend fails", async () => { const resendError = new Error("Resend API Error"); mockSend.mockResolvedValue({ data: null, error: resendError }); // Resend SDK might return error in object // OR mockSend.mockRejectedValue(resendError); if it throws await emailServiceModule.sendSubmissionNotification( form, submissionData, userOwnerEmail ); expect(logger.error).toHaveBeenCalledWith( "Error sending submission email via Resend:", resendError ); }); it("should not send if RESEND_API_KEY is missing", async () => { delete process.env.RESEND_API_KEY; // Temporarily remove // Re-require or re-instantiate the service if it checks env vars at import time // For this structure, the check is at the top of the file, so it might already be 'null' // A better approach would be for the service to have an isConfigured() method. // Forcing a re-import for the test is tricky without specific Jest features for module reloading. // Let's assume the check inside sendSubmissionNotification handles the 'resend' object being null. // To test this properly, we might need to re-import the module after changing env var jest.resetModules(); // Clears module cache process.env.RESEND_API_KEY = undefined; const freshEmailService = require("../../../src/services/emailService"); await freshEmailService.sendSubmissionNotification( form, submissionData, userOwnerEmail ); expect(mockSend).not.toHaveBeenCalled(); expect(logger.warn).toHaveBeenCalledWith( expect.stringContaining("Resend SDK not initialized") ); process.env.RESEND_API_KEY = "test-resend-api-key"; // Restore jest.resetModules(); // Clean up }); }); // You would add similar tests for sendVerificationEmail, etc. from the old Nodemailer-based service // if you intend to keep that functionality (currently it's commented out or separate) });