Skip to content

Commit

Permalink
Merge branch 'dev' into bugfix/server-crash-token-not-in-db
Browse files Browse the repository at this point in the history
  • Loading branch information
andram11 committed Dec 28, 2024
2 parents ef500ac + 775d0dd commit f456f46
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 42 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
## [Unreleased]
- Updated readme for installation part ([#225])(https://github.com/chingu-x/chingu-dashboard-be/pull/225)
- Updated nestjs packages to latest version ([#233])(https://github.com/chingu-x/chingu-dashboard-be/pull/233)
- Refactoring of email service + unit tests ([#232](https://github.com/chingu-x/chingu-dashboard-be/pull/232))
- Bug when user attempts to access a non-public endpoint after database reseed ([#230])(https://github.com/chingu-x/chingu-dashboard-be/pull/230)
### Added

Expand All @@ -26,6 +27,7 @@
### Removed

## [v1.1.0-alpha]
- Refactoring of email service + unit tests ([#232](https://github.com/chingu-x/chingu-dashboard-be/pull/232))


### Added
Expand Down
117 changes: 117 additions & 0 deletions src/utils/emails/email.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { Test, TestingModule } from "@nestjs/testing";
import { EmailService } from "./email.service";
import { MailConfigService } from "@/config/mail/mailConfig.service";
import { AppConfigService } from "@/config/app/appConfig.service";
import { templateIds } from "./templateIds";

jest.mock("node-mailjet", () => ({
Client: jest.fn().mockImplementation(() => ({
post: jest.fn(() => ({
request: jest.fn(),
})),
})),
}));

describe("EmailService", () => {
let emailService: EmailService;
let sendEmailSpy: jest.SpyInstance;
const mockMailConfigService = {
MailjetApiPublic: "some-public-key",
MailjetApiPrivate: "some-private-key",
};
const mockAppConfigService = {
nodeEnv: "development",
FrontendUrl: "https://dashboard-example.com",
};

const createTestData = () => ({
email: "[email protected]",
token: "test-token",
templateId: 56789,
});

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
EmailService,
{ provide: MailConfigService, useValue: mockMailConfigService },
{ provide: AppConfigService, useValue: mockAppConfigService },
],
}).compile();

emailService = module.get<EmailService>(EmailService);
sendEmailSpy = jest.spyOn(emailService as any, "sendEmail");
});

it("should be defined", () => {
expect(emailService).toBeDefined();
});

afterEach(() => {
jest.clearAllMocks();
});

describe("sendSignupVerificationEmail", () => {
it("should call sendEmail with the correct parameters", async () => {
const { email, token } = createTestData();

const verificationLink = `${mockAppConfigService.FrontendUrl}/users/verify?token=${token}`;

await emailService.sendSignupVerificationEmail(email, token);

expect(sendEmailSpy).toHaveBeenCalledWith(
email,
templateIds.verificationEmail,
{ verificationLink },
);
});
});

describe("sendAttemptedRegistrationEmail", () => {
it("should call sendEmail with the correct parameters", async () => {
const { email } = createTestData();
const passwordResetPage = `${mockAppConfigService.FrontendUrl}/users/reset-password`;

await emailService.sendAttemptedRegistrationEmail(email);

expect(sendEmailSpy).toHaveBeenCalledWith(
email,
templateIds.attemptRegistrationEmail,
{ userEmail: email, passwordResetPage },
);
});
});

describe("sendPasswordResetEmail", () => {
it("should call sendEmail with the correct parameters", async () => {
const { email, token } = createTestData();
const passwordResetLink = `${mockAppConfigService.FrontendUrl}/users/reset-password?token=${token}`;

await emailService.sendPasswordResetEmail(email, token);

expect(sendEmailSpy).toHaveBeenCalledWith(
email,
templateIds.passwordResetEmail,
{ passwordResetLink },
);
});
});

describe("sendEmail", () => {
it("should not send email in test environment", async () => {
const { email, templateId } = createTestData();
const verificationLink = `${mockAppConfigService.FrontendUrl}/emails`;

mockAppConfigService.nodeEnv = "test";
const mockMailjetPost = jest.spyOn(emailService["mailjet"], "post");

await (emailService as any).sendEmail(
email,
templateId,
verificationLink,
);

expect(mockMailjetPost).not.toHaveBeenCalled();
});
});
});
64 changes: 22 additions & 42 deletions src/utils/emails/email.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,63 +16,43 @@ export class EmailService {
apiSecret: this.mailConfigService.MailjetApiPrivate,
});
}
async sendSignupVerificationEmail(email: string, token: string) {

private async sendEmail(
email: string,
templateId: number,
variables: Record<string, any>,
) {
if (this.appConfigService.nodeEnv === "test") return;
await this.mailjet.post("send", { version: "v3.1" }).request({
Messages: [
{
To: [
{
Email: email,
},
],
TemplateID: templateIds.verificationEmail,
To: [{ Email: email }],
TemplateID: templateId,
TemplateLanguage: true,
Variables: {
verificationLink: `${this.appConfigService.FrontendUrl}/users/verify?token=${token}`,
},
Variables: variables,
},
],
});
}
async sendSignupVerificationEmail(email: string, token: string) {
const verificationLink = `${this.appConfigService.FrontendUrl}/users/verify?token=${token}`;
await this.sendEmail(email, templateIds.verificationEmail, {
verificationLink,
});
}

async sendAttemptedRegistrationEmail(email: string) {
if (this.appConfigService.nodeEnv === "test") return;
await this.mailjet.post("send", { version: "v3.1" }).request({
Messages: [
{
To: [
{
Email: email,
},
],
TemplateID: templateIds.attemptRegistrationEmail,
TemplateLanguage: true,
Variables: {
userEmail: email,
passwordResetPage: `${this.appConfigService.FrontendUrl}/users/reset-password`,
},
},
],
const passwordResetPage = `${this.appConfigService.FrontendUrl}/users/reset-password`;
await this.sendEmail(email, templateIds.attemptRegistrationEmail, {
userEmail: email,
passwordResetPage,
});
}

async sendPasswordResetEmail(email: string, token: string) {
await this.mailjet.post("send", { version: "v3.1" }).request({
Messages: [
{
To: [
{
Email: email,
},
],
TemplateID: templateIds.passwordResetEmail,
TemplateLanguage: true,
Variables: {
passwordResetLink: `${this.appConfigService.FrontendUrl}/users/reset-password?token=${token}`,
},
},
],
const passwordResetLink = `${this.appConfigService.FrontendUrl}/users/reset-password?token=${token}`;
await this.sendEmail(email, templateIds.passwordResetEmail, {
passwordResetLink,
});
}
}

0 comments on commit f456f46

Please sign in to comment.