From 3b08d84b26cb06e2ed4b0cc5260f00facb4a0202 Mon Sep 17 00:00:00 2001 From: Maxime Cannoodt Date: Sun, 11 Sep 2022 17:47:01 +0200 Subject: [PATCH] test get embed controller --- server/src/app.integration.test.ts | 46 +++++++++- .../note/embeds/embeds.get.controller.ts | 2 +- .../embeds/embeds.get.controller.unit.test.ts | 87 +++++++++++++++++++ .../controllers/note/embeds/embeds.router.ts | 4 +- server/src/controllers/note/note.router.ts | 6 +- 5 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 server/src/controllers/note/embeds/embeds.get.controller.unit.test.ts diff --git a/server/src/app.integration.test.ts b/server/src/app.integration.test.ts index 9fb4c9d..465fda8 100644 --- a/server/src/app.integration.test.ts +++ b/server/src/app.integration.test.ts @@ -197,6 +197,47 @@ describe("POST /api/note", () => { }); }); +describe("Use case: POST note with embeds, then GET embeds", () => { + it("returns a view_url on correct POST body with embeds", async () => { + const payload = { + ciphertext: Buffer.from("sample_ciphertext").toString("base64"), + hmac: Buffer.from("sample_hmac").toString("base64"), + user_id: "f06536e7df6857fc", + embeds: [ + { + embed_id: "EMBED_ID", + ciphertext: Buffer.from("sample_ciphertext").toString("base64"), + hmac: Buffer.from("sample_hmac").toString("base64"), + }, + ], + }; + + // make post request + const res = await supertest(app).post("/api/note").send(payload); + + // check response and extract note id + expectCodeOrThrowResponse(res, 200); + expect(res.body).toHaveProperty("view_url"); + const match = (res.body.view_url as string).match(/note\/(.+)$/); + expect(match).not.toBeNull(); + const note_id = (match as RegExpMatchArray)[1]; + + // make get request for note + const noteRes = await supertest(app).get(`/api/note/${note_id}`); + expectCodeOrThrowResponse(noteRes, 200); + expect(noteRes.body?.ciphertext).toEqual(payload.ciphertext); + expect(noteRes.body?.hmac).toEqual(payload.hmac); + + // make get request for embed + const embedRes = await supertest(app).get( + `/api/note/${note_id}/embeds/EMBED_ID` + ); + expectCodeOrThrowResponse(embedRes, 200); + expect(embedRes.body?.ciphertext).toEqual(payload.embeds[0].ciphertext); + expect(embedRes.body?.hmac).toEqual(payload.embeds[0].hmac); + }); +}); + describe("Clean expired notes", () => { it("removes expired notes", async () => { // insert a note with expiry date in the past using prisma @@ -238,9 +279,10 @@ function expectCodeOrThrowResponse(res: supertest.Response, expected: number) { try { expect(res.status).toBe(expected); } catch (e) { - throw new Error(` + (e as Error).message = ` Unexpected status ${res.status} (expected ${expected}): - Response body: ${res.text}`); + Response body: ${res.text}`; + throw e; } } diff --git a/server/src/controllers/note/embeds/embeds.get.controller.ts b/server/src/controllers/note/embeds/embeds.get.controller.ts index d1b3abf..66b4ec5 100644 --- a/server/src/controllers/note/embeds/embeds.get.controller.ts +++ b/server/src/controllers/note/embeds/embeds.get.controller.ts @@ -1,7 +1,7 @@ import type { NextFunction, Request, Response } from "express"; import { getEmbed } from "../../../db/embed.dao"; -export async function getNoteController( +export async function getEmbedController( req: Request, res: Response, next: NextFunction diff --git a/server/src/controllers/note/embeds/embeds.get.controller.unit.test.ts b/server/src/controllers/note/embeds/embeds.get.controller.unit.test.ts new file mode 100644 index 0000000..bead2b7 --- /dev/null +++ b/server/src/controllers/note/embeds/embeds.get.controller.unit.test.ts @@ -0,0 +1,87 @@ +import express from "express"; +import supertest from "supertest"; +import { vi, it, expect, describe, beforeEach, afterEach } from "vitest"; +import { getEmbedController } from "./embeds.get.controller"; +import * as embedDao from "../../../db/embed.dao"; + +vi.mock("../../../db/embed.dao"); + +const MOCK_EMBED_DTO: embedDao.EncryptedEmbedDTO = { + note_id: "valid_note_id", + embed_id: "valid_embed_id", + ciphertext: Buffer.from("sample_ciphertext").toString("base64"), + hmac: Buffer.from("sample_hmac").toString("base64"), +}; + +describe("Test GET embeds", () => { + let app: express.Express; + let mockEmbedDao = vi.mocked(embedDao); + + beforeEach(() => { + app = express() + .use(express.json()) + .get("/:id/embeds/:embed_id", getEmbedController); + }); + + afterEach(() => { + vi.resetAllMocks(); + }); + + it("Should return 200 for a valid note_id+embed_id pair", async () => { + // mock db response + mockEmbedDao.getEmbed.mockImplementation(async (noteId, embedId) => { + if ( + noteId === MOCK_EMBED_DTO.note_id && + embedId === MOCK_EMBED_DTO.embed_id + ) { + return MOCK_EMBED_DTO; + } + return null; + }); + + // make request + const res = await supertest(app).get( + "/valid_note_id/embeds/valid_embed_id" + ); + + // check response + expect(res.statusCode).toBe(200); + expect(res.body).toMatchObject(MOCK_EMBED_DTO); + }); + + it("Should return 404 for an invalid note_id+embed_id pair", async () => { + // mock db response + mockEmbedDao.getEmbed.mockImplementation(async (noteId, embedId) => { + if ( + noteId === MOCK_EMBED_DTO.note_id && + embedId === MOCK_EMBED_DTO.embed_id + ) { + return MOCK_EMBED_DTO; + } + return null; + }); + + // make request + const res = await supertest(app).get( + "/invalid_note_id/embeds/invalid_embed_id" + ); + + // check response + expect(res.statusCode).toBe(404); + }); + + it("Should return 500 on database failure", async () => { + // mock db response + mockEmbedDao.getEmbed.mockImplementation(async (noteId, embedId) => { + throw new Error("Database failure"); + }); + + // make request + const res = await supertest(app).get( + "/valid_note_id/embeds/valid_embed_id" + ); + + // check response + expect(res.statusCode).toBe(500); + }); +}); diff --git a/server/src/controllers/note/embeds/embeds.router.ts b/server/src/controllers/note/embeds/embeds.router.ts index 5fd5704..5ad666b 100644 --- a/server/src/controllers/note/embeds/embeds.router.ts +++ b/server/src/controllers/note/embeds/embeds.router.ts @@ -1,6 +1,6 @@ import express from "express"; -import { getNoteController } from "../note.get.controller"; +import { getEmbedController } from "./embeds.get.controller"; export const embedsRoute = express.Router({ mergeParams: true }); -embedsRoute.get("/:embed_id", getNoteController); +embedsRoute.get("/:embed_id", getEmbedController); diff --git a/server/src/controllers/note/note.router.ts b/server/src/controllers/note/note.router.ts index cd62c1c..b57778a 100644 --- a/server/src/controllers/note/note.router.ts +++ b/server/src/controllers/note/note.router.ts @@ -25,8 +25,8 @@ const getRateLimit = rateLimit({ }); // notesRoute.use(jsonParser, uploadLimit); +notesRoute.use("/:id/embeds", embedsRoute); notesRoute.use(uploadLimit); notesRoute.use(jsonParser); -notesRoute.post("", postRateLimit, postNoteController); -notesRoute.get("/:id", getRateLimit, getNoteController); -notesRoute.use("/:id/embeds/", embedsRoute); +notesRoute.route("/").post(postRateLimit, postNoteController); +notesRoute.route("/:id").get(getRateLimit, getNoteController);