@sync-in/server
Version:
The secure, open-source platform for file storage, sharing, collaboration, and sync
176 lines (175 loc) • 6.34 kB
JavaScript
/*
* Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>
* This file is part of Sync-in | The open source file sync and share solution
* See the LICENSE file for licensing details
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const _testing = require("@nestjs/testing");
const _config = require("@nestjs/config");
const _nestjspino = require("nestjs-pino");
const _nodemailer = /*#__PURE__*/ _interop_require_default(require("nodemailer"));
const _mailerservice = require("./mailer.service");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
// Mocks
jest.mock('nodemailer');
const createTransportMock = {
verify: jest.fn().mockResolvedValue(true),
sendMail: jest.fn().mockResolvedValue(true)
};
_nodemailer.default.createTransport.mockReturnValue(createTransportMock);
describe(_mailerservice.Mailer.name, ()=>{
let module;
let mailer;
let configService;
let logger;
const mailerConfig = {
host: 'smtp.example.com',
port: 587,
auth: {
user: 'user',
pass: 'pass'
},
secure: false,
sender: 'noreply@example.com',
debug: false,
logger: false
};
const initModule = async (config)=>{
module = await _testing.Test.createTestingModule({
providers: [
_mailerservice.Mailer,
{
provide: _config.ConfigService,
useValue: {
get: jest.fn().mockReturnValue(config)
}
},
{
provide: _nestjspino.PinoLogger,
useValue: {
setContext: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
info: jest.fn(),
assign: jest.fn(),
logger: {
level: 'info'
}
}
}
]
}).compile();
mailer = module.get(_mailerservice.Mailer);
configService = module.get(_config.ConfigService);
logger = module.get(_nestjspino.PinoLogger);
};
beforeAll(async ()=>{
await initModule(undefined);
});
it('should be defined', ()=>{
expect(module).toBeDefined();
expect(mailer).toBeDefined();
expect(configService).toBeDefined();
expect(logger).toBeDefined();
});
it('should not initialize transporter if config is absent', ()=>{
expect(mailer['transport']).toBeUndefined();
expect(_nodemailer.default.createTransport).not.toHaveBeenCalled();
});
it('should initialize secure transport with no secure port', async ()=>{
await initModule({
...mailerConfig,
secure: true
});
expect(mailer['configuration'].secure).toBe(false);
await initModule({
...mailerConfig,
port: 25,
secure: true,
logger: true,
debug: true
});
expect(mailer['configuration'].secure).toBe(false);
const loggerWarnSpy = jest.spyOn(logger, 'warn');
expect(loggerWarnSpy).toHaveBeenCalledWith(expect.stringMatching(/has been disabled/i));
loggerWarnSpy.mockClear();
});
it('should set mailer availability to false if transport failed', async ()=>{
createTransportMock.verify.mockRejectedValueOnce(new Error('Mail Server down'));
await initModule(mailerConfig);
expect(mailer.available).toBe(false);
const loggerErrorSpy = jest.spyOn(logger, 'error');
expect(loggerErrorSpy).toHaveBeenCalledWith(expect.stringMatching(/mail server down/i));
loggerErrorSpy.mockClear();
});
it('should initialize transporter if config exists', async ()=>{
// Reinstantiate the module and the services
await initModule(mailerConfig);
expect(_nodemailer.default.createTransport).toHaveBeenCalledWith(expect.objectContaining({
host: mailerConfig.host,
port: mailerConfig.port,
auth: mailerConfig.auth,
secure: mailerConfig.secure
}), expect.objectContaining({
from: mailerConfig.sender
}));
});
it('should send mails when available', async ()=>{
mailer.available = true;
await mailer.sendMails([
{
to: 'test@example.com',
subject: 'Hello',
html: 'world'
}
]);
expect(createTransportMock.sendMail).toHaveBeenCalledWith(expect.objectContaining({
to: 'test@example.com'
}));
createTransportMock.sendMail.mockClear();
});
it('should not send mails when not available', async ()=>{
mailer.available = false;
await mailer.sendMails([
{
to: 'test@example.com',
subject: 'Hello',
html: 'world'
}
]);
expect(createTransportMock.sendMail).not.toHaveBeenCalled();
createTransportMock.sendMail.mockClear();
});
it('should continue sending remaining mails if one send fails and log error', async ()=>{
mailer.available = true;
// first call rejects, second resolves
createTransportMock.sendMail.mockRejectedValueOnce(new Error('SMTP down')).mockResolvedValueOnce(true);
await mailer.sendMails([
{
to: 'fail@example.com',
subject: 'One',
html: '1'
},
{
to: 'ok@example.com',
subject: 'Two',
html: '2'
}
]);
expect(createTransportMock.sendMail).toHaveBeenCalledTimes(2);
expect(createTransportMock.sendMail).toHaveBeenNthCalledWith(1, expect.objectContaining({
to: 'fail@example.com'
}));
expect(createTransportMock.sendMail).toHaveBeenNthCalledWith(2, expect.objectContaining({
to: 'ok@example.com'
}));
createTransportMock.sendMail.mockClear();
});
});
//# sourceMappingURL=mailer.service.spec.js.map