import { describe, expect, test } from "vitest"; import { buildAssetUrl, extractFlagName, rewriteAssetsForCdn, } from "../src/core/AssetUrls"; describe("AssetUrls", () => { test("returns hashed URLs for direct asset matches", () => { expect( buildAssetUrl("images/Favicon.svg", { "images/Favicon.svg": "/_assets/images/Favicon.hash.svg", }), ).toBe("/_assets/images/Favicon.hash.svg"); }); test("falls back to the unversioned path when manifest has no match", () => { expect(buildAssetUrl("images/unknown.svg", {})).toBe("/images/unknown.svg"); }); test("falls back to the unversioned path for directory-like paths", () => { const manifest = { "maps/britanniaclassic/manifest.json": "/_assets/maps/britanniaclassic/manifest.hash.json", "maps/britanniaclassic/map.bin": "/_assets/maps/britanniaclassic/map.hash.bin", }; expect(buildAssetUrl("maps", manifest)).toBe("/maps"); expect(buildAssetUrl("maps/britanniaclassic", manifest)).toBe( "/maps/britanniaclassic", ); }); test("rejects dot segments in asset paths", () => { expect(() => buildAssetUrl("../api/instance", {})).toThrow( "Invalid asset path segment: ..", ); expect(() => buildAssetUrl("images/%2e%2e/secret.svg", {})).toThrow( "Invalid asset path segment: %2e%2e", ); }); test("rejects empty asset paths", () => { expect(() => buildAssetUrl("", {})).toThrow("Asset path must not be empty"); expect(() => buildAssetUrl("///", {})).toThrow( "Asset path must not be empty", ); }); test("prefixes baseUrl onto hashed URLs when provided", () => { expect( buildAssetUrl( "images/Favicon.svg", { "images/Favicon.svg": "/_assets/images/Favicon.hash.svg" }, "https://cdn.example.com", ), ).toBe("https://cdn.example.com/_assets/images/Favicon.hash.svg"); }); test("preserves direct URL when baseUrl is empty string", () => { expect( buildAssetUrl( "images/Favicon.svg", { "images/Favicon.svg": "/_assets/images/Favicon.hash.svg" }, "", ), ).toBe("/_assets/images/Favicon.hash.svg"); }); test("returns absolute http(s) URLs unchanged and ignores baseUrl", () => { expect( buildAssetUrl( "https://example.com/foo.png", {}, "https://cdn.example.com", ), ).toBe("https://example.com/foo.png"); expect(buildAssetUrl("HTTP://example.com/foo.png", {})).toBe( "HTTP://example.com/foo.png", ); }); // Manifest miss → keep same-origin; the CDN only serves what was explicitly // hashed and uploaded, so unknown paths must not be prefixed. test("does not prefix baseUrl on manifest misses", () => { expect( buildAssetUrl("images/unknown.svg", {}, "https://cdn.example.com"), ).toBe("/images/unknown.svg"); }); test("strips trailing slashes on baseUrl to avoid double slash", () => { const manifest = { "images/Favicon.svg": "/_assets/images/Favicon.hash.svg", }; expect( buildAssetUrl("images/Favicon.svg", manifest, "https://cdn.example.com/"), ).toBe("https://cdn.example.com/_assets/images/Favicon.hash.svg"); expect( buildAssetUrl( "images/Favicon.svg", manifest, "https://cdn.example.com///", ), ).toBe("https://cdn.example.com/_assets/images/Favicon.hash.svg"); }); }); describe("extractFlagName", () => { test("extracts from flag: prefix", () => { expect(extractFlagName("flag:Abbasid Caliphate")).toBe("Abbasid Caliphate"); }); test("extracts and decodes from URL", () => { expect( extractFlagName( "https://cdn.ofedge.dev/game_assets/_assets/flags/Abbasid%20Caliphate.ed17b262829c.svg", ), ).toBe("Abbasid Caliphate"); expect(extractFlagName("/flags/Abbasid%20Caliphate.svg")).toBe( "Abbasid Caliphate", ); }); test("returns raw string if not matching flag: or /flags/ URL", () => { expect(extractFlagName("Some Random String")).toBe("Some Random String"); }); test("handles malformed percent-encodings without throwing", () => { expect(extractFlagName("/flags/Bad%C2Encoding.12345678.svg")).toBe( "Bad%C2Encoding", ); }); test("handles edge cases like names containing colons or URLs with hashes", () => { expect( extractFlagName( "/flags/Name%3AWith%3AColons.12345678.svg?query=1#anchor", ), ).toBe("Name:With:Colons"); }); }); describe("rewriteAssetsForCdn", () => { test("rewrites src=/assets/ to EJS placeholder", () => { const out = rewriteAssetsForCdn( ``, ); expect(out).toBe( ``, ); }); test("rewrites href=/assets/ for modulepreload and stylesheet links", () => { const out = rewriteAssetsForCdn( `\n`, ); expect(out).toBe( `/assets/vendor-XXX.js">\n/assets/index-XXX.css">`, ); }); test("supports single-quoted attribute values", () => { expect(rewriteAssetsForCdn(``)).toBe( ``, ); }); test("does not rewrite /_assets/ (underscore manifest paths)", () => { const html = ``; expect(rewriteAssetsForCdn(html)).toBe(html); }); test("does not rewrite already-absolute asset URLs", () => { const html = ``; expect(rewriteAssetsForCdn(html)).toBe(html); }); // Inline scripts containing the literal "/assets/..." string must survive // unrewrite — the regex requires whitespace before src=/href=, and inside a // JS string literal there's no preceding `src=`/`href=` token at all. test("does not mangle /assets/ inside inline script string literals", () => { const html = ``; expect(rewriteAssetsForCdn(html)).toBe(html); }); test("does not match data-src or other custom attributes", () => { const html = ``; expect(rewriteAssetsForCdn(html)).toBe(html); }); });