diff --git a/apps/api/package.json b/apps/api/package.json index 25fa0e90e39..0a8f2abbd0d 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -5,7 +5,7 @@ "scripts": { "dev": "node src/server.js", "start": "node src/server.js", - "test": "node --test src/tests" + "test": "node --test src/tests/**/*.js" }, "dependencies": { "cors": "^2.8.5", diff --git a/apps/api/src/controllers/uploadController.js b/apps/api/src/controllers/uploadController.js index 6523adedc73..609856b5b30 100644 --- a/apps/api/src/controllers/uploadController.js +++ b/apps/api/src/controllers/uploadController.js @@ -1,8 +1,16 @@ -import { ok } from "../utils/response.js"; +import { fail, ok } from "../utils/response.js"; export async function uploadFile(req, res) { - return ok(res, { - filename: req.file?.originalname ?? null, - status: req.file ? "uploaded" : "no-file" - }, 201); + if (!req.file) { + return fail(res, "File is required", 400); + } + + return ok( + res, + { + filename: req.file.originalname, + status: "uploaded" + }, + 201 + ); } diff --git a/apps/api/src/tests/upload-empty.test.js b/apps/api/src/tests/upload-empty.test.js new file mode 100644 index 00000000000..8db663f095c --- /dev/null +++ b/apps/api/src/tests/upload-empty.test.js @@ -0,0 +1,50 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { createApp } from "../app.js"; + +async function withServer(run) { + const app = createApp(); + const server = app.listen(0); + await new Promise((resolve, reject) => { + server.once("listening", resolve); + server.once("error", reject); + }); + try { + const { port } = server.address(); + await run(port); + } finally { + await new Promise((resolve, reject) => { + server.close((error) => (error ? reject(error) : resolve())); + }); + } +} + +test("POST /api/uploads without file returns 400", async () => { + await withServer(async (port) => { + const response = await fetch(`http://127.0.0.1:${port}/api/uploads`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}" + }); + const payload = await response.json(); + assert.equal(response.status, 400); + assert.equal(payload.success, false); + assert.match(payload.message, /file/i); + }); +}); + +test("POST /api/uploads with multipart file returns 201", async () => { + await withServer(async (port) => { + const form = new FormData(); + form.append("file", new Blob(["hello"], { type: "text/plain" }), "hello.txt"); + const response = await fetch(`http://127.0.0.1:${port}/api/uploads`, { + method: "POST", + body: form + }); + const payload = await response.json(); + assert.equal(response.status, 201); + assert.equal(payload.success, true); + assert.equal(payload.data.status, "uploaded"); + assert.equal(payload.data.filename, "hello.txt"); + }); +});