Skip to content

Commit

Permalink
fix: unit testing
Browse files Browse the repository at this point in the history
  • Loading branch information
incredible-phoenix246 committed Jul 22, 2024
1 parent 2670193 commit cdb5bee
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 131 deletions.
11 changes: 7 additions & 4 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ const config: Config = {
verbose: true,
preset: "ts-jest",
testEnvironment: "node",
globals: {
"ts-jest": {
tsconfig: "tsconfig.jest.json",
},
transform: {
"^.+\\.tsx?$": [
"ts-jest",
{
tsconfig: "tsconfig.jest.json",
},
],
},
};

Expand Down
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@
"prod": "node dist/index.js",
"migrate": "typeorm migration:run -d src/data-source.ts"
},
"keywords": [],
"repository": {
"type": "git",
"url": "https://github.com/hngprojects/hng_boilerplate_expressjs"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/hngprojects/hng_boilerplate_expressjs/issues"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/jest": "^29.5.12",
Expand Down
11 changes: 7 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import express, { Express, Request, Response } from "express";
import config from "./config";
import dotenv from "dotenv";
import cors from "cors";
import { userRouter, authRoute, testimonialRoute, notificationRouter } from "./routes";

import {
userRouter,
authRoute,
testimonialRoute,
notificationRouter,
} from "./routes";
import { routeNotFound, errorHandler } from "./middleware";
import { seed } from "./seeder";
import { orgRouter } from "./routes/organisation";
import swaggerUi from "swagger-ui-express";
import swaggerSpec from "./swaggerConfig";
Expand All @@ -29,7 +32,7 @@ server.use(
"Content-Type",
"Authorization",
],
}),
})
);
server.use(express.json());
server.use(express.urlencoded({ extended: true }));
Expand Down
3 changes: 0 additions & 3 deletions src/models/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,6 @@ export class User extends ExtendedBaseEntity {
@JoinTable()
organizations: Organization[];

@OneToMany(() => Sms, (sms) => sms.sender, { cascade: true })
sms: Sms[];

@CreateDateColumn()
createdAt: Date;

Expand Down
8 changes: 4 additions & 4 deletions src/services/OrgService.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Organization } from "../models/organization";
import { AppDataSource } from "../data-source";
import AppDataSource from "../data-source";
import { User } from "../models/user";
import { IOrgService, IUserService } from "../types";

export class OrgService implements IOrgService {
public async removeUser(
org_id: string,
user_id: string,
user_id: string
): Promise<User | null> {
const userRepository = AppDataSource.getRepository(User);
const organizationRepository = AppDataSource.getRepository(Organization);
Expand All @@ -29,15 +29,15 @@ export class OrgService implements IOrgService {

// Check if the user is part of the organization
const userInOrganization = organization.users.some(
(user) => user.id === user_id,
(user) => user.id === user_id
);
if (!userInOrganization) {
return null;
}

// Remove the user from the organization
organization.users = organization.users.filter(
(user) => user.id !== user_id,
(user) => user.id !== user_id
);
await organizationRepository.save(organization);

Expand Down
244 changes: 129 additions & 115 deletions src/test/auth.spec.ts
Original file line number Diff line number Diff line change
@@ -1,139 +1,153 @@
// @ts-nocheck

import { AppDataSource } from "../data-source";
import AppDataSource from "../data-source";
import { User } from "../models";
import { hashPassword, generateNumericOTP, comparePassword } from "../utils";
import { Sendmail } from "../utils/mail";
import jwt from "jsonwebtoken";
import config from "../config";
import { Conflict, HttpError } from "../middleware";
import { AuthService } from "../services";

jest.mock("../data-source");
jest.mock("../data-source", () => {
return {
AppDataSource: {
manager: {},
initialize: jest.fn().mockResolvedValue(true),
},
};
});
jest.mock("../models");
jest.mock("../utils");
jest.mock("../utils/mail");
jest.mock("jsonwebtoken");

describe("AuthService", () => {
let authService: AuthService;
let mockManager;

beforeEach(() => {
authService = new AuthService();

mockManager = {
save: jest.fn(),
};

// Assign the mock manager to the AppDataSource.manager
AppDataSource.manager = mockManager;
});

// describe("signUp", () => {
// it("should sign up a new user", async () => {
// const payload = {
// firstName: "John",
// lastName: "Doe",
// email: "[email protected]",
// password: "password123",
// phone: "1234567890",
// };

// const hashedPassword = "hashedPassword";
// const otp = "123456";
// const mailSent = "mailSent";
// const createdUser = {
// id: 1,
// name: "John Doe",
// email: "[email protected]",
// password: hashedPassword,
// profile: {
// phone: "1234567890",
// first_name: "John",
// last_name: "Doe",
// avatarUrl: "",
// },
// otp: parseInt(otp),
// otp_expires_at: new Date(Date.now() + 10 * 60 * 1000),
// };
// const token = "access_token";

// (User.findOne as jest.Mock).mockResolvedValue(null);
// (hashPassword as jest.Mock).mockResolvedValue(hashedPassword);
// (generateNumericOTP as jest.Mock).mockReturnValue(otp);
// (AppDataSource.manager.save as jest.Mock).mockResolvedValue(createdUser);
// (jwt.sign as jest.Mock).mockReturnValue(token);
// (Sendmail as jest.Mock).mockResolvedValue(mailSent);

// const result = await authService.signUp(payload);

// expect(result).toEqual({
// mailSent,
// newUser: {
// id: 1,
// name: "John Doe",
// email: "[email protected]",
// profile: {
// phone: "1234567890",
// first_name: "John",
// last_name: "Doe",
// avatarUrl: "",
// },
// otp: parseInt(otp),
// otp_expires_at: expect.any(Date),
// },
// access_token: token,
// });
// });

// it("should throw a Conflict error if the user already exists", async () => {
// const payload = {
// firstName: "John",
// lastName: "Doe",
// email: "[email protected]",
// password: "password123",
// phone: "1234567890",
// };

// (User.findOne as jest.Mock).mockResolvedValue({});

// await expect(authService.signUp(payload)).rejects.toThrow(Conflict);
// });
// });

// describe("verifyEmail", () => {
// it("should verify email with correct OTP", async () => {
// const token = "validToken";
// const otp = 123456;
// const user = {
// id: 1,
// email: "[email protected]",
// otp,
// otp_expires_at: new Date(Date.now() + 10 * 60 * 1000),
// isverified: false,
// };

// (jwt.verify as jest.Mock).mockReturnValue({ userId: 1 });
// (User.findOne as jest.Mock).mockResolvedValue(user);
// (AppDataSource.manager.save as jest.Mock).mockResolvedValue(user);

// const result = await authService.verifyEmail(token, otp);

// expect(result).toEqual({ message: "Email successfully verified" });
// });

// it("should throw an error for invalid OTP", async () => {
// const token = "validToken";
// const otp = 123456;
// const user = {
// id: 1,
// email: "[email protected]",
// otp: 654321,
// otp_expires_at: new Date(Date.now() + 10 * 60 * 1000),
// isverified: false,
// };

// (jwt.verify as jest.Mock).mockReturnValue({ userId: 1 });
// (User.findOne as jest.Mock).mockResolvedValue(user);

// await expect(authService.verifyEmail(token, otp)).rejects.toThrow(
// HttpError
// );
// });
// });
describe("signUp", () => {
it("should sign up a new user", async () => {
const payload = {
firstName: "John",
lastName: "Doe",
email: "[email protected]",
password: "password123",
phone: "1234567890",
};

const hashedPassword = "hashedPassword";
const otp = "123456";
const mailSent = "mailSent";
const createdUser = {
id: 1,
name: "John Doe",
email: "[email protected]",
password: hashedPassword,
profile: {
phone: "1234567890",
first_name: "John",
last_name: "Doe",
avatarUrl: "",
},
otp: parseInt(otp),
otp_expires_at: new Date(Date.now() + 10 * 60 * 1000),
};
const token = "access_token";

(User.findOne as jest.Mock).mockResolvedValue(null);
(hashPassword as jest.Mock).mockResolvedValue(hashedPassword);
(generateNumericOTP as jest.Mock).mockReturnValue(otp);
mockManager.save.mockResolvedValue(createdUser);
(jwt.sign as jest.Mock).mockReturnValue(token);
(Sendmail as jest.Mock).mockResolvedValue(mailSent);

const result = await authService.signUp(payload);

expect(result).toEqual({
mailSent,
newUser: {
id: 1,
name: "John Doe",
email: "[email protected]",
profile: {
phone: "1234567890",
first_name: "John",
last_name: "Doe",
avatarUrl: "",
},
otp: parseInt(otp),
otp_expires_at: expect.any(Date),
},
access_token: token,
});
});

it("should throw a Conflict error if the user already exists", async () => {
const payload = {
firstName: "John",
lastName: "Doe",
email: "[email protected]",
password: "password123",
phone: "1234567890",
};

(User.findOne as jest.Mock).mockResolvedValue({});

await expect(authService.signUp(payload)).rejects.toThrow(Conflict);
});
});

describe("verifyEmail", () => {
it("should verify email with correct OTP", async () => {
const token = "validToken";
const otp = 123456;
const user = {
id: 1,
email: "[email protected]",
otp,
otp_expires_at: new Date(Date.now() + 10 * 60 * 1000),
isverified: false,
};

(jwt.verify as jest.Mock).mockReturnValue({ userId: 1 });
(User.findOne as jest.Mock).mockResolvedValue(user);
mockManager.save.mockResolvedValue(user);

const result = await authService.verifyEmail(token, otp);

expect(result).toEqual({ message: "Email successfully verified" });
});

it("should throw an error for invalid OTP", async () => {
const token = "validToken";
const otp = 123456;
const user = {
id: 1,
email: "[email protected]",
otp: 654321,
otp_expires_at: new Date(Date.now() + 10 * 60 * 1000),
isverified: false,
};

(jwt.verify as jest.Mock).mockReturnValue({ userId: 1 });
(User.findOne as jest.Mock).mockResolvedValue(user);

await expect(authService.verifyEmail(token, otp)).rejects.toThrow(
HttpError
);
});
});

describe("login", () => {
it("should login user with correct credentials", async () => {
Expand Down

0 comments on commit cdb5bee

Please sign in to comment.