From 5fb729985018fd20d7935d5ef9271e405b989dc3 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 8 Feb 2026 03:36:59 +0000 Subject: [PATCH] test: add unit tests for sanitizeProfileMediaUrl and fix bugs - Add `tests/utils/profileMedia.test.mjs` with comprehensive test cases. - Fix `sanitizeProfileMediaUrl` to correctly trim whitespace after removing quotes. - Fix `sanitizeProfileMediaUrl` to correctly detect and normalize `ipfs/` paths (without protocol). Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- js/utils/profileMedia.js | 4 +- tests/utils/profileMedia.test.mjs | 74 +++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 tests/utils/profileMedia.test.mjs diff --git a/js/utils/profileMedia.js b/js/utils/profileMedia.js index 4de331ed..a496f326 100644 --- a/js/utils/profileMedia.js +++ b/js/utils/profileMedia.js @@ -33,7 +33,7 @@ export function sanitizeProfileMediaUrl(value) { return ""; } - trimmed = trimmed.replace(/^['"]+|['"]+$/g, ""); + trimmed = trimmed.replace(/^['"]+|['"]+$/g, "").trim(); if (!trimmed) { return ""; } @@ -50,7 +50,7 @@ export function sanitizeProfileMediaUrl(value) { return ""; } - if (/^ipfs:\/\//i.test(trimmed)) { + if (/^ipfs(\/|:\/\/)/i.test(trimmed)) { return normalizeIpfsGatewayUrl(trimmed); } diff --git a/tests/utils/profileMedia.test.mjs b/tests/utils/profileMedia.test.mjs new file mode 100644 index 00000000..c85c3343 --- /dev/null +++ b/tests/utils/profileMedia.test.mjs @@ -0,0 +1,74 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { sanitizeProfileMediaUrl } from "../../js/utils/profileMedia.js"; + +test("sanitizeProfileMediaUrl handles non-string inputs", () => { + assert.equal(sanitizeProfileMediaUrl(null), ""); + assert.equal(sanitizeProfileMediaUrl(undefined), ""); + assert.equal(sanitizeProfileMediaUrl(123), ""); + assert.equal(sanitizeProfileMediaUrl({}), ""); +}); + +test("sanitizeProfileMediaUrl handles empty or whitespace-only strings", () => { + assert.equal(sanitizeProfileMediaUrl(""), ""); + assert.equal(sanitizeProfileMediaUrl(" "), ""); + assert.equal(sanitizeProfileMediaUrl("\t\n"), ""); +}); + +test("sanitizeProfileMediaUrl trims whitespace and removes quotes", () => { + assert.equal(sanitizeProfileMediaUrl(" http://example.com "), "https://example.com"); + assert.equal(sanitizeProfileMediaUrl("'http://example.com'"), "https://example.com"); + assert.equal(sanitizeProfileMediaUrl('"http://example.com"'), "https://example.com"); + assert.equal(sanitizeProfileMediaUrl(" ' http://example.com ' "), "https://example.com"); +}); + +test("sanitizeProfileMediaUrl allows data:image/ URLs", () => { + const dataUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="; + assert.equal(sanitizeProfileMediaUrl(dataUrl), dataUrl); +}); + +test("sanitizeProfileMediaUrl allows blob: URLs", () => { + const blobUrl = "blob:http://example.com/550e8400-e29b-41d4-a716-446655440000"; + assert.equal(sanitizeProfileMediaUrl(blobUrl), blobUrl); +}); + +test("sanitizeProfileMediaUrl rejects specific placeholder images", () => { + assert.equal(sanitizeProfileMediaUrl("images/robot.png"), ""); +}); + +test("sanitizeProfileMediaUrl normalizes IPFS URLs", () => { + assert.equal(sanitizeProfileMediaUrl("ipfs://CID"), "https://ipfs.io/ipfs/CID"); + assert.equal(sanitizeProfileMediaUrl("ipfs/CID"), "https://ipfs.io/ipfs/CID"); +}); + +test("sanitizeProfileMediaUrl handles protocol-relative URLs", () => { + assert.equal(sanitizeProfileMediaUrl("//example.com/image.jpg"), "https://example.com/image.jpg"); +}); + +test("sanitizeProfileMediaUrl allows relative paths", () => { + assert.equal(sanitizeProfileMediaUrl("/assets/image.jpg"), "/assets/image.jpg"); + assert.equal(sanitizeProfileMediaUrl("./image.jpg"), "./image.jpg"); + assert.equal(sanitizeProfileMediaUrl("../image.jpg"), "../image.jpg"); + assert.equal(sanitizeProfileMediaUrl("assets/image.jpg"), "assets/image.jpg"); +}); + +test("sanitizeProfileMediaUrl adds protocol to domains and localhost", () => { + assert.equal(sanitizeProfileMediaUrl("localhost:8080/image.jpg"), "http://localhost:8080/image.jpg"); + assert.equal(sanitizeProfileMediaUrl("example.com/image.jpg"), "https://example.com/image.jpg"); + assert.equal(sanitizeProfileMediaUrl("sub.example.com/image.jpg"), "https://sub.example.com/image.jpg"); + // IP address pattern in code: (?:\d{1,3}\.){3}\d{1,3} + assert.equal(sanitizeProfileMediaUrl("127.0.0.1:8080/image.jpg"), "http://127.0.0.1:8080/image.jpg"); +}); + +test("sanitizeProfileMediaUrl coerces http to https except for localhost", () => { + assert.equal(sanitizeProfileMediaUrl("http://example.com/image.jpg"), "https://example.com/image.jpg"); + assert.equal(sanitizeProfileMediaUrl("http://localhost:8080/image.jpg"), "http://localhost:8080/image.jpg"); + assert.equal(sanitizeProfileMediaUrl("http://127.0.0.1:8080/image.jpg"), "http://127.0.0.1:8080/image.jpg"); +}); + +test("sanitizeProfileMediaUrl rejects unsupported patterns", () => { + // The code logs a warning and returns "" for things that don't match localhost or domain patterns + // if they don't start with http/https + assert.equal(sanitizeProfileMediaUrl("javascript:alert(1)"), ""); + assert.equal(sanitizeProfileMediaUrl("ftp://example.com/file"), ""); // Starts with ftp, not http/https/ipfs +});