161 lines
6.5 KiB
JavaScript
161 lines
6.5 KiB
JavaScript
jest.mock("nodemailer", () => ({
|
|
__esModule: true,
|
|
default: {
|
|
createTransport: jest.fn(() => ({
|
|
sendMail: jest.fn().mockResolvedValue({}),
|
|
})),
|
|
},
|
|
}));
|
|
|
|
// Default: no env SMTP so system-settings path is used unless overridden per-test
|
|
jest.mock("@/config/index.js", () => ({
|
|
config: {
|
|
SMTP_HOST: "not_set",
|
|
SMTP_PORT: -1,
|
|
SMTP_USER: "not_set",
|
|
SMTP_PASS: "not_set",
|
|
},
|
|
}));
|
|
|
|
import EmailService from "@/services/infrastructure/NotificationServices/Email.js";
|
|
|
|
// Mock user service to avoid calling getAllUsers
|
|
const userServiceMock = { getAllUsers: jest.fn().mockResolvedValue([{ email: "a@example.com" }]) };
|
|
// Settings service mock (unused path in test)
|
|
const settingsServiceMock = {
|
|
get: jest.fn().mockResolvedValue({
|
|
systemEmailHost: "smtp.example.com",
|
|
systemEmailPort: 587,
|
|
systemEmailAddress: "noreply@example.com",
|
|
systemEmailUser: "smtp-user",
|
|
systemEmailPassword: "smtp-pass",
|
|
systemEmailConnectionHost: "example.com",
|
|
systemEmailTLSServername: "example.com",
|
|
systemEmailSecure: false,
|
|
systemEmailPool: false,
|
|
systemEmailIgnoreTLS: false,
|
|
systemEmailRequireTLS: false,
|
|
systemEmailRejectUnauthorized: true,
|
|
}),
|
|
};
|
|
|
|
const getMailer = () => jest.requireMock("nodemailer").default;
|
|
|
|
const buildChannel = (overrides = {}) => ({
|
|
_id: "c1",
|
|
name: "Email",
|
|
type: "email",
|
|
config: { emailAddress: "alerts@example.com" },
|
|
...overrides,
|
|
});
|
|
|
|
const buildMonitor = (overrides = {}) => ({ name: "m", status: "up", url: "u", ...overrides });
|
|
const buildIncident = (overrides = {}) => ({ resolved: false, ...overrides });
|
|
|
|
describe("EmailService", () => {
|
|
it("sends test message", async () => {
|
|
const service = new EmailService(userServiceMock , settingsServiceMock);
|
|
// Force transporter build
|
|
getMailer().createTransport.mockReturnValue({ sendMail: jest.fn().mockResolvedValue({}) });
|
|
// ensure we bypass env SMTP path
|
|
const ok = await service.testMessage(buildChannel());
|
|
expect(ok).toBe(true);
|
|
});
|
|
|
|
it("uses system settings transport (no env) and sendGeneric succeeds", async () => {
|
|
const service = new EmailService(userServiceMock, settingsServiceMock);
|
|
const mailer = getMailer();
|
|
const sendMail = jest.fn().mockResolvedValue({});
|
|
mailer.createTransport.mockReturnValue({ sendMail });
|
|
|
|
const ok = await service.sendGeneric("to@example.com", "Subj", "Body");
|
|
expect(ok).toBe(true);
|
|
expect(mailer.createTransport).toHaveBeenCalled();
|
|
const arg = mailer.createTransport.mock.calls[0][0];
|
|
expect(arg.host || arg?.host === undefined).toBeDefined();
|
|
});
|
|
|
|
it("returns false when no user emails found in sendMessage", async () => {
|
|
const service = new EmailService({ getAllUsers: jest.fn().mockResolvedValue([]) }, settingsServiceMock);
|
|
const ok = await service.sendMessage({ name: "n", url: "u", status: "s", checkTime: new Date(), alertTime: new Date(), resolved: false }, buildChannel());
|
|
expect(ok).toBe(false);
|
|
});
|
|
|
|
it("rebuildTransport sets transporter and from and returns true", async () => {
|
|
const service = new EmailService(userServiceMock, settingsServiceMock);
|
|
const mailer = getMailer();
|
|
const sendMail = jest.fn().mockResolvedValue({});
|
|
mailer.createTransport.mockReturnValue({ sendMail });
|
|
const res = await service.rebuildTransport({
|
|
systemEmailHost: "smtp.example.com",
|
|
systemEmailPort: 465,
|
|
systemEmailAddress: "noreply@example.com",
|
|
systemEmailUser: "smtp-user",
|
|
systemEmailPassword: "smtp-pass",
|
|
systemEmailSecure: true,
|
|
systemEmailPool: true,
|
|
systemEmailIgnoreTLS: false,
|
|
systemEmailRequireTLS: false,
|
|
systemEmailRejectUnauthorized: true,
|
|
});
|
|
expect(res).toBe(true);
|
|
expect(mailer.createTransport).toHaveBeenCalled();
|
|
});
|
|
|
|
it("testTransport throws when env SMTP configured", async () => {
|
|
jest.resetModules();
|
|
jest.doMock("@/config/index.js", () => ({
|
|
config: { SMTP_HOST: "smtp.env", SMTP_PORT: 465, SMTP_USER: "u", SMTP_PASS: "p" },
|
|
}));
|
|
const { default: EmailServiceEnv } = await import("@/services/infrastructure/NotificationServices/Email.js");
|
|
const service = new EmailServiceEnv(userServiceMock, settingsServiceMock);
|
|
await expect(
|
|
service.testTransport({ systemEmailAddress: "noreply@example.com", systemEmailSecure: false, systemEmailPool: false, systemEmailIgnoreTLS: false, systemEmailRequireTLS: false, systemEmailRejectUnauthorized: true })
|
|
).rejects.toMatchObject({ status: 400 });
|
|
});
|
|
|
|
it("builds env transport when env present and uses secure flag", async () => {
|
|
jest.resetModules();
|
|
jest.doMock("@/config/index.js", () => ({
|
|
config: { SMTP_HOST: "smtp.env", SMTP_PORT: 465, SMTP_USER: "u", SMTP_PASS: "p" },
|
|
}));
|
|
const { default: EmailServiceEnv } = await import("@/services/infrastructure/NotificationServices/Email.js");
|
|
const mailer = getMailer();
|
|
mailer.createTransport.mockReturnValue({ sendMail: jest.fn().mockResolvedValue({}) });
|
|
const service = new EmailServiceEnv(userServiceMock, settingsServiceMock);
|
|
await service.sendGeneric("t@example.com", "s", "b");
|
|
expect(mailer.createTransport).toHaveBeenCalledWith(
|
|
expect.objectContaining({ host: "smtp.env", port: 465, secure: true })
|
|
);
|
|
});
|
|
|
|
it("sendGeneric rejects when transporter sendMail fails", async () => {
|
|
const service = new EmailService(userServiceMock, settingsServiceMock);
|
|
// Bypass nodemailer mock by injecting a failing transporter directly
|
|
service.transporter = { sendMail: jest.fn().mockRejectedValue(new Error("fail")) };
|
|
await expect(service.sendGeneric("t@example.com", "s", "b")).rejects.toBeInstanceOf(Error);
|
|
});
|
|
|
|
it("testTransport throws ApiError when sendMail fails", async () => {
|
|
const service = new EmailService(userServiceMock, settingsServiceMock);
|
|
// Force buildSystemSettingsTransport to return a transporter whose sendMail fails
|
|
service.buildSystemSettingsTransport = jest
|
|
.fn()
|
|
.mockResolvedValue({ sendMail: jest.fn().mockRejectedValue(new Error("smtp-fail")) });
|
|
await expect(
|
|
service.testTransport({
|
|
systemEmailHost: "smtp.example.com",
|
|
systemEmailPort: 587,
|
|
systemEmailAddress: "noreply@example.com",
|
|
systemEmailUser: "smtp-user",
|
|
systemEmailPassword: "smtp-pass",
|
|
systemEmailSecure: false,
|
|
systemEmailPool: false,
|
|
systemEmailIgnoreTLS: false,
|
|
systemEmailRequireTLS: false,
|
|
systemEmailRejectUnauthorized: true,
|
|
})
|
|
).rejects.toMatchObject({ status: 400 });
|
|
});
|
|
});
|