From 332f75b4105b7d0da86e6621fcb3af4a490184b3 Mon Sep 17 00:00:00 2001 From: Florian Sylvain Date: Mon, 6 Mar 2023 11:02:41 +0100 Subject: [PATCH] Added session tests and ran prettier --- src/__tests__/session.test.ts | 98 +++++++++++++++++++++++++++++++++++ src/app.ts | 7 ++- src/routers/session.ts | 10 ++-- src/utils/pagination.ts | 5 +- 4 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 src/__tests__/session.test.ts diff --git a/src/__tests__/session.test.ts b/src/__tests__/session.test.ts new file mode 100644 index 0000000..a2034ac --- /dev/null +++ b/src/__tests__/session.test.ts @@ -0,0 +1,98 @@ +import { initServer } from "../app.js" +import request from "supertest" +import { PrismaClient } from "@prisma/client" +import bcrypt from "bcrypt" + +const prisma = new PrismaClient() +const app = initServer() +let jwtCookie: string | undefined + +const testUsers = [ + { + email: "a@a.com", + password: "aaaaaaaaaa", + }, + { + email: "b@b.com", + password: "bbbbbbbbbb", + }, +] + +beforeAll(async () => { + await prisma.user.create({ + data: { + email: testUsers[0].email, + password: await bcrypt.hash(testUsers[0].password, 10), + name: "", + }, + }) +}) + +afterAll(async () => { + for (const user of testUsers) { + await prisma.user.delete({ where: { email: user.email } }) + } +}) + +describe("GET /v1", () => { + it("returns status code 200 and api version message", async () => { + const res = await request(app).get("/v1") + + expect(res.statusCode).toEqual(200) + expect(res.body).toHaveProperty("message") + }) +}) + +describe("POST /v1/session/register", () => { + it("returns status code 200 and a success message", async () => { + const res = await request(app) + .post("/v1/session/register") + .set("Content-Type", "application/json") + .send(JSON.stringify(testUsers[1])) + + expect(res.statusCode).toEqual(200) + expect(res.body).toHaveProperty("message") + }) + + it("returns status code 400 and an error message", async () => { + const res = await request(app) + .post("/v1/session/register") + .set("Content-Type", "application/json") + .send(JSON.stringify(testUsers[0])) + + expect(res.statusCode).toEqual(400) + expect(res.body).toHaveProperty("message") + }) +}) + +describe("POST /v1/session/login", () => { + it("returns status code 200 and set httpOnly jwt token cookie", async () => { + const res = await request(app) + .post("/v1/session/login") + .set("Content-Type", "application/json") + .send(JSON.stringify(testUsers[0])) + + const jwtRegEx = /^jwt=.*Path=\/.*HttpOnly.*Secure.*SameSite=Strict.*$/ + jwtCookie = res + .get("Set-Cookie") + ?.filter((cookie) => cookie.match(jwtRegEx))[0] + + expect(res.statusCode).toEqual(200) + expect(jwtCookie).not.toBe(undefined) + }) + + it("returns status code 400 and credentials error message", async () => { + const res = await request(app) + .post("/v1/session/login") + .set("Content-Type", "application/json") + .send( + JSON.stringify({ + email: "rip bozo", + password: "rip bozo", + }) + ) + + expect(res.statusCode).toEqual(400) + expect(res.body).toHaveProperty("message") + }) +}) diff --git a/src/app.ts b/src/app.ts index 1a126ac..f69ff38 100644 --- a/src/app.ts +++ b/src/app.ts @@ -4,6 +4,8 @@ import jwt from "jsonwebtoken" import cors from "cors" import cookieParser from "cookie-parser" +import sessionRouter from "./routers/session" + import { getJwtSecret } from "./utils/jwt.js" const authMiddleware: RequestHandler = (req, res, next) => { @@ -55,7 +57,6 @@ export function initServer(): express.Express { appRouter.get("/", appRouterGet) appRouter.use("/session/", sessionRouter) - appRouter.use("/user/", authMiddleware, userRouter) app.use("/v1/", appRouter) @@ -63,5 +64,7 @@ export function initServer(): express.Express { } export function startServer(app: express.Express): void { - app.listen(process.env.API_PORT, () => console.log(`Listening on port ${process.env.API_PORT}`)) + app.listen(process.env.API_PORT, () => + console.log(`Listening on port ${process.env.API_PORT}`) + ) } diff --git a/src/routers/session.ts b/src/routers/session.ts index 38b162b..d53e5db 100644 --- a/src/routers/session.ts +++ b/src/routers/session.ts @@ -29,7 +29,10 @@ export function parseJwtUserId(jwtoken: string): number | undefined { return payload.userId } -async function isUserValid(user: User | null, loginData: any): Promise { +async function isUserValid( + user: User | null, + loginData: any +): Promise { if (user == undefined) return false return await bcrypt.compare(loginData.password, user.password) } @@ -45,7 +48,6 @@ async function createUser(email: string, password: string) { email: email, password: password, name: "", - picture_path: "", created_at: new Date(), updated_at: new Date(), }, @@ -77,7 +79,9 @@ export const userRouterPostLogin: RequestHandler = async (req, res) => { return } - const jwtToken = jwt.sign({ userId: user?.id }, getJwtSecret(), { expiresIn: "1h" }) + const jwtToken = jwt.sign({ userId: user?.id }, getJwtSecret(), { + expiresIn: "1h", + }) res.cookie("jwt", jwtToken, { httpOnly: true, secure: true, diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts index 1d74015..256688e 100644 --- a/src/utils/pagination.ts +++ b/src/utils/pagination.ts @@ -10,7 +10,10 @@ export const queryPaginationParser = z.object({ take: z.coerce.number().optional().default(10), }) -export function getPaginationLinks(query: Pagination, routeName: string): object { +export function getPaginationLinks( + query: Pagination, + routeName: string +): object { const nextStart = query.skip + query.take const prevStart = Math.max(0, query.skip - query.take)