// Unit tests for the upload pipeline building blocks (dev-plan.md T2). // Run: node --test uploads.test.js const test = require("node:test"); const assert = require("node:assert/strict"); const fs = require("node:fs"); const path = require("node:path"); const { parseMultipart, boundaryFromContentType, sniffImageType, sniffVideoType, stripMetadataAndSave, saveVideoUpload, UPLOADS_DIR, } = require("./uploads.js"); test("sniffImageType recognizes real magic bytes and rejects a zip disguised as .jpg", () => { const jpeg = Buffer.from([0xff, 0xd8, 0xff, 0xe0, 0, 0, 0, 0]); const png = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0, 0]); const webp = Buffer.concat([Buffer.from("RIFF"), Buffer.from([0, 0, 0, 0]), Buffer.from("WEBP")]); const zipDisguisedAsJpg = Buffer.from([0x50, 0x4b, 0x03, 0x04, 0, 0, 0, 0]); // PK.. local file header assert.equal(sniffImageType(jpeg).type, "image/jpeg"); assert.equal(sniffImageType(png).type, "image/png"); assert.equal(sniffImageType(webp).type, "image/webp"); assert.equal(sniffImageType(zipDisguisedAsJpg), null); }); test("parseMultipart extracts a file part from a real multipart body (built via the platform's own FormData/Response)", async () => { const fd = new FormData(); fd.append("file", new Blob([Buffer.from([1, 2, 3, 4])], { type: "image/png" }), "photo.png"); const encoded = new Response(fd); const body = Buffer.from(await encoded.arrayBuffer()); const boundary = boundaryFromContentType(encoded.headers.get("content-type")); const parts = parseMultipart(body, boundary); assert.equal(parts.length, 1); assert.equal(parts[0].name, "file"); assert.equal(parts[0].filename, "photo.png"); assert.deepEqual([...parts[0].data], [1, 2, 3, 4]); }); test("sniffVideoType recognizes a real mp4 (reused from the S1-S4 spike) and rejects a zip disguised as .mp4", () => { const realMp4 = fs.readFileSync(path.join(__dirname, "spike", "s1-s2-s4-2026-09-02", "danceref.mp4")); assert.equal(sniffVideoType(realMp4).type, "video/mp4"); const zipDisguisedAsMp4 = Buffer.from([0x50, 0x4b, 0x03, 0x04, 0, 0, 0, 0, 0, 0, 0, 0, 0]); assert.equal(sniffVideoType(zipDisguisedAsMp4), null); }); test("saveVideoUpload stores the video byte-for-byte under uploads/", () => { const realMp4 = fs.readFileSync(path.join(__dirname, "spike", "s1-s2-s4-2026-09-02", "danceref.mp4")); const sniffed = sniffVideoType(realMp4); const { absPath, relPath, ext } = saveVideoUpload(realMp4, sniffed); try { assert.equal(ext, "mp4"); assert.match(relPath, /^\/uploads\/\d{6}\/[0-9a-f-]+\.mp4$/); assert.deepEqual(fs.readFileSync(absPath), realMp4); } finally { fs.rmSync(absPath); } }); // Walks a JPEG's APP1 "Exif\0\0" TIFF block (if any) and reports whether // IFD0 has a GPS IFD pointer (tag 0x8825) — i.e. whether the file carries // GPS EXIF data. Dependency-free stand-in for what the original acceptance // criteria describes as "exiftool sees no GPS" (no exiftool on this // machine, see uploads.js's module comment). function hasGpsExifTag(jpegBuffer) { let offset = 2; // skip SOI (0xFFD8) while (offset < jpegBuffer.length - 4) { if (jpegBuffer[offset] !== 0xff) break; const marker = jpegBuffer[offset + 1]; if (marker === 0xd8 || marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) { offset += 2; continue; } if (marker === 0xda) break; // start of scan — no more markers to read const segmentLength = jpegBuffer.readUInt16BE(offset + 2); if (marker === 0xe1 && jpegBuffer.toString("latin1", offset + 4, offset + 10) === "Exif\0\0") { const tiffStart = offset + 10; const littleEndian = jpegBuffer.toString("latin1", tiffStart, tiffStart + 2) === "II"; const readU16 = (p) => (littleEndian ? jpegBuffer.readUInt16LE(p) : jpegBuffer.readUInt16BE(p)); const readU32 = (p) => (littleEndian ? jpegBuffer.readUInt32LE(p) : jpegBuffer.readUInt32BE(p)); const ifd0Offset = tiffStart + readU32(tiffStart + 4); const entryCount = readU16(ifd0Offset); for (let i = 0; i < entryCount; i++) { const entryOffset = ifd0Offset + 2 + i * 12; if (readU16(entryOffset) === 0x8825) return true; // GPS IFD pointer tag } return false; } offset += 2 + segmentLength; } return false; } test("stripMetadataAndSave strips embedded GPS EXIF from a real photo and preserves pixel dimensions", () => { const fixture = fs.readFileSync(path.join(__dirname, "test-fixtures", "with-gps.jpg")); assert.equal(hasGpsExifTag(fixture), true, "test fixture should actually carry GPS EXIF"); const sniffed = sniffImageType(fixture); assert.equal(sniffed.type, "image/jpeg"); const { absPath, relPath, ext } = stripMetadataAndSave(fixture, sniffed); try { assert.equal(ext, "jpg"); assert.match(relPath, /^\/uploads\/\d{6}\/[0-9a-f-]+\.jpg$/); const out = fs.readFileSync(absPath); assert.equal(hasGpsExifTag(out), false, "expected GPS EXIF to be gone after stripMetadataAndSave"); } finally { fs.rmSync(absPath); } }); test.after(() => { // stripMetadataAndSave writes into the real uploads/ tree (mirrors // production layout); clean up the yyyymm dir if the test left it empty. const yyyymm = new Date().toISOString().slice(0, 7).replace("-", ""); const dir = path.join(UPLOADS_DIR, yyyymm); try { if (fs.readdirSync(dir).length === 0) fs.rmdirSync(dir); if (fs.readdirSync(UPLOADS_DIR).length === 0) fs.rmdirSync(UPLOADS_DIR); } catch { // already clean } });