import { describe, expect, it } from "vite-plus/test"; import { BROWSER_FAVICON_MAX_ENTRIES, type BrowserFaviconEntry, evictExcessFavicons, faviconKey, faviconStorageLocation, isStorableFaviconDataUrl, migratePersistedBrowserFaviconState,} from "./browserFaviconLogic"; const PNG = "data:image/png;base64,AAAA"; function entry(capturedAt = 0): BrowserFaviconEntry { return { dataUrl: PNG, capturedAt };} describe("browser favicon logic", () => { it("keys valid origins canonically while keeping distinct scopes separate", () => { expect(faviconKey("env:project", "http://myapp.test:3000/admin?x=1", null)).toBe( "env:project http://myapp.test:3000", ); expect(faviconKey("env:project", "http://192.168.64.2:3000/", "192.168.64.2")).toBe( faviconKey("env:project", "http://localhost:3000/", "192.168.64.2"), ); expect(faviconKey("env:project", "http://127.0.0.1:3000/", null)).toBe( faviconKey("env:project", "http://0.0.0.0:3000/", null), ); const keys = [ faviconKey("env:a", "http://localhost:3000/", null), faviconKey("env:b", "http://localhost:3000/", null), faviconKey("env:a", "http://localhost:5173/", null), faviconKey("env:a", "https://localhost:3000/", null), faviconKey("env:a", "http://192.168.1.50:3000/", "192.168.64.2"), ]; expect(new Set(keys).size).toBe(keys.length); expect(faviconKey("env:a", "not a url", null)).toBeNull(); expect(faviconKey("env:a", "ftp://example.com/", null)).toBeNull(); expect(faviconKey("", "http://localhost/", null)).toBeNull(); expect(faviconKey("env:a", "http://local:3000/", null)).not.toBe( faviconKey("env:a", "http://localhost:3000/", null), ); }); it("retains an exact environment-host alias for offline lookup", () => { const expected = { aliases: ["192.168.64.2"], key: "env:project http://localhost:3000", }; expect( faviconStorageLocation("env:project", "http://localhost:3000/app", "192.168.64.2"), ).toEqual(expected); expect( faviconStorageLocation("env:project", "http://192.168.64.2:3000/app", "192.168.64.2"), ).toEqual(expected); expect( faviconStorageLocation("env:project", "https://example.com/app", "192.168.64.2"), ).toEqual({ aliases: [], key: "env:project https://example.com:443" }); expect(faviconStorageLocation("env:project", "http://localhost:3000/app", "fd00::1")).toEqual({ aliases: ["fd00::1"], key: "env:project http://localhost:3000", }); expect(faviconKey("env:project", "http://[2001:4860:4860::8888]/", null)).toBe( "env:project http://[2001:4860:4860::8888]:80", ); }); it("accepts only bounded base64 PNG data", () => { expect(isStorableFaviconDataUrl(PNG)).toBe(true); expect(isStorableFaviconDataUrl("data:image/svg+xml;base64,AAAA")).toBe(false); expect(isStorableFaviconDataUrl("data:image/png;base64,")).toBe(false); expect(isStorableFaviconDataUrl("data:image/png;base64,%%%%")).toBe(false); expect(isStorableFaviconDataUrl(`data:image/png;base64,${"A".repeat(8192)}`)).toBe(false); }); it("evicts old entries and sanitizes hydrated state", () => { const byKey = Object.fromEntries( Array.from({ length: BROWSER_FAVICON_MAX_ENTRIES + 2 }, (_, index) => [ `key-${index}`, entry(index), ]), ); const result = evictExcessFavicons(byKey); expect(Object.keys(result)).toHaveLength(BROWSER_FAVICON_MAX_ENTRIES); expect(result["key-0"]).toBeUndefined(); expect(result["key-1"]).toBeUndefined(); expect( migratePersistedBrowserFaviconState({ byKey: { "env:project http://local:3000": entry(4), "env:project http://localhost:3000": entry(5), "env:project http://localhost:3003": { ...entry(6), aliases: [ "192.168.64.2", "192.168.64.2", "192.168.64.3", "192.168.64.4", "192.168.64.5", "192.168.64.6", "Not Normalized", "not a host/", "x".repeat(5_000), ], }, "env:project http://localhost:3001": { dataUrl: "https://example.com/icon.png", capturedAt: 6, }, "env:project http://localhost:3002": { dataUrl: PNG, capturedAt: Number.NaN }, }, }), ).toEqual({ byKey: { "env:project http://localhost:3000": entry(5), "env:project http://localhost:3003": { ...entry(6), aliases: ["192.168.64.2", "192.168.64.3", "192.168.64.4", "192.168.64.5"], }, }, }); });});
import { describe, expect, it } from "vite-plus/test";
import {
BROWSER_FAVICON_MAX_ENTRIES,
type BrowserFaviconEntry,
evictExcessFavicons,
faviconKey,
faviconStorageLocation,
isStorableFaviconDataUrl,
migratePersistedBrowserFaviconState,
} from "./browserFaviconLogic";
const PNG = "data:image/png;base64,AAAA";
function entry(capturedAt = 0): BrowserFaviconEntry {
return { dataUrl: PNG, capturedAt };
}
describe("browser favicon logic", () => {
it("keys valid origins canonically while keeping distinct scopes separate", () => {
expect(faviconKey("env:project", "http://myapp.test:3000/admin?x=1", null)).toBe(
"env:project http://myapp.test:3000",
);
expect(faviconKey("env:project", "http://192.168.64.2:3000/", "192.168.64.2")).toBe(
faviconKey("env:project", "http://localhost:3000/", "192.168.64.2"),
);
expect(faviconKey("env:project", "http://127.0.0.1:3000/", null)).toBe(
faviconKey("env:project", "http://0.0.0.0:3000/", null),
);
const keys = [
faviconKey("env:a", "http://localhost:3000/", null),
faviconKey("env:b", "http://localhost:3000/", null),
faviconKey("env:a", "http://localhost:5173/", null),
faviconKey("env:a", "https://localhost:3000/", null),
faviconKey("env:a", "http://192.168.1.50:3000/", "192.168.64.2"),
];
expect(new Set(keys).size).toBe(keys.length);
expect(faviconKey("env:a", "not a url", null)).toBeNull();
expect(faviconKey("env:a", "ftp://example.com/", null)).toBeNull();
expect(faviconKey("", "http://localhost/", null)).toBeNull();
expect(faviconKey("env:a", "http://local:3000/", null)).not.toBe(
faviconKey("env:a", "http://localhost:3000/", null),
);
});
it("retains an exact environment-host alias for offline lookup", () => {
const expected = {
aliases: ["192.168.64.2"],
key: "env:project http://localhost:3000",
};
expect(
faviconStorageLocation("env:project", "http://localhost:3000/app", "192.168.64.2"),
).toEqual(expected);
expect(
faviconStorageLocation("env:project", "http://192.168.64.2:3000/app", "192.168.64.2"),
).toEqual(expected);
expect(
faviconStorageLocation("env:project", "https://example.com/app", "192.168.64.2"),
).toEqual({ aliases: [], key: "env:project https://example.com:443" });
expect(faviconStorageLocation("env:project", "http://localhost:3000/app", "fd00::1")).toEqual({
aliases: ["fd00::1"],
key: "env:project http://localhost:3000",
});
expect(faviconKey("env:project", "http://[2001:4860:4860::8888]/", null)).toBe(
"env:project http://[2001:4860:4860::8888]:80",
);
});
it("accepts only bounded base64 PNG data", () => {
expect(isStorableFaviconDataUrl(PNG)).toBe(true);
expect(isStorableFaviconDataUrl("data:image/svg+xml;base64,AAAA")).toBe(false);
expect(isStorableFaviconDataUrl("data:image/png;base64,")).toBe(false);
expect(isStorableFaviconDataUrl("data:image/png;base64,%%%%")).toBe(false);
expect(isStorableFaviconDataUrl(`data:image/png;base64,${"A".repeat(8192)}`)).toBe(false);
});
it("evicts old entries and sanitizes hydrated state", () => {
const byKey = Object.fromEntries(
Array.from({ length: BROWSER_FAVICON_MAX_ENTRIES + 2 }, (_, index) => [
`key-${index}`,
entry(index),
]),
);
const result = evictExcessFavicons(byKey);
expect(Object.keys(result)).toHaveLength(BROWSER_FAVICON_MAX_ENTRIES);
expect(result["key-0"]).toBeUndefined();
expect(result["key-1"]).toBeUndefined();
expect(
migratePersistedBrowserFaviconState({
byKey: {
"env:project http://local:3000": entry(4),
"env:project http://localhost:3000": entry(5),
"env:project http://localhost:3003": {
...entry(6),
aliases: [
"192.168.64.2",
"192.168.64.2",
"192.168.64.3",
"192.168.64.4",
"192.168.64.5",
"192.168.64.6",
"Not Normalized",
"not a host/",
"x".repeat(5_000),
],
},
"env:project http://localhost:3001": {
dataUrl: "https://example.com/icon.png",
capturedAt: 6,
},
"env:project http://localhost:3002": { dataUrl: PNG, capturedAt: Number.NaN },
},
}),
).toEqual({
byKey: {
"env:project http://localhost:3000": entry(5),
"env:project http://localhost:3003": {
...entry(6),
aliases: ["192.168.64.2", "192.168.64.3", "192.168.64.4", "192.168.64.5"],
},
},
});
});
});