Skip to content

Commit

Permalink
⚡️ Prefix with [TEST] in email subject if not in prod. mode
Browse files Browse the repository at this point in the history
  • Loading branch information
anthonypillot committed Mar 11, 2023
1 parent 6b899e9 commit a92d248
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 7 deletions.
14 changes: 13 additions & 1 deletion src/outputs/emailer/emailer.output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ export class EmailerOutput {
});
}

public sendEmail(mailOptions: EmailOptionsInterface) {
public async sendEmail(mailOptions: EmailOptionsInterface) {
mailOptions = await this.checkEnvironment(mailOptions);

return new Promise<EmailResponseInterface>((resolve, reject) => {
this.transporter.sendMail(mailOptions, (error, data) => {
return resolve({
Expand All @@ -37,4 +39,14 @@ export class EmailerOutput {
});
});
}

/**
* Verify if the application is running in production mode or not, if not, prefix the @param mailOptions.subject with "[TEST]".
*/
private async checkEnvironment(mailOptions: EmailOptionsInterface): Promise<EmailOptionsInterface> {
if (process.env.NODE_ENV !== "production") {
mailOptions.subject = `(TEST) ${mailOptions.subject}`;
}
return mailOptions;
}
}
8 changes: 4 additions & 4 deletions src/outputs/google/drive.output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class DriveOutput {
* @returns The content of the file.
*/
public async getDocument(fileName: string): Promise<Object | null> {
fileName = this.verify(fileName);
fileName = this.checkEnvironment(fileName);
const id = await this.getFileId(fileName);

if (id) {
Expand All @@ -36,7 +36,7 @@ export class DriveOutput {
}

public async updateDocument(fileName: string, content: string): Promise<void> {
fileName = this.verify(fileName);
fileName = this.checkEnvironment(fileName);
const id = await this.getFileId(fileName);

if (id) {
Expand Down Expand Up @@ -77,11 +77,11 @@ export class DriveOutput {
}

/**
* Verify if the application is running in production mode or not, if not, prefix the @param fileName with "prep-filename.json".
* Check if the application is running in production mode or not, if not, prefix the @param fileName with "prep-filename.json".
* Because Google Drive API not permit to search file by folder, all prep. files are prefixed by "prep-filename.json" in the Google Drive.
* @param fileName The name of the file to retrieve.
*/
private verify(fileName: string): string {
private checkEnvironment(fileName: string): string {
if (process.env.NODE_ENV !== "production") {
fileName = `prep-${fileName}`;
return fileName;
Expand Down
4 changes: 2 additions & 2 deletions src/services/email.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ export class EmailService {
const $emailsToSend = emailList.map((element) => {
// Create email template
datasToCompile.uuid = receivers?.find((el) => (el.email = element))?.uuid;
const emailOptions: EmailOptionsInterface = this.prepareTemplate(subject, datasToCompile);
return this.emailer.sendEmail({ ...emailOptions, to: [element] });
const mailOptions: EmailOptionsInterface = this.prepareTemplate(subject, datasToCompile);
return this.emailer.sendEmail({ ...mailOptions, to: [element] });
});

// Send all emails
Expand Down
91 changes: 91 additions & 0 deletions test/outputs/emailer.output.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { EmailerOutput } from "../../src/outputs/emailer/emailer.output";

import nodemailer from "nodemailer";

describe("EmailerOutput", () => {
jest.mock("nodemailer");
nodemailer.createTransport = jest.fn().mockReturnValue({
sendMail: jest.fn().mockImplementation((mailOptions, callback) => {
callback(null, "any");
}),
});

let emailer: EmailerOutput;

beforeEach(() => {
emailer = new EmailerOutput({
host: "smtp.example.com",
port: 587,
secure: false,
auth: {
user: "[email protected]",
pass: "password",
},
tls: {
rejectUnauthorized: false,
},
});
});

test(`given NODE_ENV is set to "production" and standard mail options,
when sendEmail is called,
then should send an email with the given options`, async () => {
// given
const mailOptions = {
// eslint-disable-next-line @typescript-eslint/quotes
from: '"Test" <[email protected]>',
to: ["[email protected]"],
subject: "Hello",
text: "Hello world!",
html: "<b>Hello world!</b>",
sender: "Tester",
};

const mailOptionsCloned = JSON.parse(JSON.stringify(mailOptions));

// when
process.env.NODE_ENV = "production";

const spyParameter = jest.spyOn(emailer, "sendEmail");
await emailer.sendEmail(mailOptions);

// then
expect(spyParameter.mock.calls.length).toEqual(1);
const firstCallParameter = spyParameter.mock.calls[0][0];

expect(firstCallParameter).toBeDefined();
expect(firstCallParameter).toEqual(mailOptionsCloned);
});

test(`given NODE_ENV is set to "development" and standard mail options,
when sendEmail is called,
then should send an email with the given options and subject prefixed by (TEST)`, async () => {
// given
const mailOptions = {
// eslint-disable-next-line @typescript-eslint/quotes
from: '"Test" <[email protected]>',
to: ["[email protected]"],
subject: "Hello",
text: "Hello world!",
html: "<b>Hello world!</b>",
sender: "Tester",
};

const mailOptionsCloned = JSON.parse(JSON.stringify(mailOptions));

// when
process.env.NODE_ENV = "development";

const spyParameter = jest.spyOn(emailer, "sendEmail");
await emailer.sendEmail(mailOptions);

// then
expect(spyParameter.mock.calls.length).toEqual(1);

const firstCallParameter = spyParameter.mock.calls[0][0];

expect(firstCallParameter).toBeDefined();
expect(firstCallParameter).not.toEqual(mailOptionsCloned);
expect(firstCallParameter.subject).toEqual(`(TEST) ${mailOptionsCloned.subject}`);
});
});

0 comments on commit a92d248

Please sign in to comment.