
- Updated `.env` and `.env.test` files to include PostgreSQL connection settings and Redis configuration. - Migrated database from SQLite to PostgreSQL, updating relevant queries and connection logic. - Enhanced error handling and logging throughout the application. - Added new test utilities for PostgreSQL integration and updated user model methods. - Introduced new routes for user authentication and form management, ensuring compatibility with the new database structure. - Created login and registration views in EJS for user interaction.
134 lines
4.7 KiB
JavaScript
134 lines
4.7 KiB
JavaScript
// __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("<strong>Test Form</strong>"),
|
|
});
|
|
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)
|
|
});
|