Something went wrong. Try again.
Mirror of https://github.com/improsocial/improAn extensible Bluesky client for web
Something went wrong. Try again.
5.9 kB · 192 lines
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193import { describe, it, beforeEach, mock } from "node:test";import assert from "node:assert/strict";import { MockFetch } from "../../testHelpers.js";import "/js/components/plugin-icon.js";
describe("plugin-icon", () => { const SAMPLE_SVG = '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/></svg>';
function flush() { return new Promise((resolve) => setTimeout(resolve, 0)); }
function okResponse(body) { return { ok: true, status: 200, statusText: "OK", text: async () => body, }; }
function notFoundResponse() { return { ok: false, status: 404, statusText: "Not Found", text: async () => "", }; }
beforeEach(() => { document.body.innerHTML = ""; customElements.get("plugin-icon").cache = new Map(); });
describe("PluginIcon - iconset resolution", () => { it("resolves an icon from the majesticons set", async () => { const fetch = new MockFetch(); fetch.__intercept("/img/icons/", async () => okResponse(SAMPLE_SVG)); globalThis.fetch = fetch;
const element = document.createElement("plugin-icon"); element.setAttribute("icon", "bell"); document.body.appendChild(element); await flush();
assert.deepEqual(fetch.calls[0].url, "/img/icons/majesticons/bell.svg"); });
it("resolves an icon from the custom set", async () => { const fetch = new MockFetch(); fetch.__intercept("/img/icons/", async () => okResponse(SAMPLE_SVG)); globalThis.fetch = fetch;
const element = document.createElement("plugin-icon"); element.setAttribute("icon", "verified-check"); document.body.appendChild(element); await flush();
assert.deepEqual( fetch.calls[0].url, "/img/icons/custom/verified-check.svg", ); });
it("warns and renders nothing for an unknown icon", async () => { const fetch = new MockFetch(); globalThis.fetch = fetch;
const originalWarn = console.warn; const warnMock = mock.fn(); console.warn = warnMock;
try { const element = document.createElement("plugin-icon"); element.setAttribute("icon", "not-a-real-icon"); document.body.appendChild(element); await flush();
assert.deepEqual(fetch.calls.length, 0); assert.deepEqual(element.innerHTML, ""); assert.deepEqual(warnMock.mock.callCount(), 1); } finally { console.warn = originalWarn; } }); });
describe("PluginIcon - rendering", () => { it("injects the fetched SVG markup", async () => { const fetch = new MockFetch(); fetch.__intercept("/img/icons/", async () => okResponse(SAMPLE_SVG)); globalThis.fetch = fetch;
const element = document.createElement("plugin-icon"); element.setAttribute("icon", "cake"); document.body.appendChild(element); await flush();
const svg = element.querySelector("svg"); assert(svg !== null); assert.deepEqual(svg.getAttribute("viewBox"), "0 0 24 24"); });
it("renders nothing when icon is empty", async () => { const fetch = new MockFetch(); globalThis.fetch = fetch;
const element = document.createElement("plugin-icon"); document.body.appendChild(element); await flush();
assert.deepEqual(fetch.calls.length, 0); assert.deepEqual(element.innerHTML, ""); });
it("swaps the icon when icon changes", async () => { const fetch = new MockFetch(); fetch.__intercept("/img/icons/majesticons/bus.svg", async () => okResponse('<svg id="first"></svg>'), ); fetch.__intercept("/img/icons/majesticons/car.svg", async () => okResponse('<svg id="second"></svg>'), ); globalThis.fetch = fetch;
const element = document.createElement("plugin-icon"); element.setAttribute("icon", "bus"); document.body.appendChild(element); await flush(); assert.deepEqual(element.querySelector("svg").id, "first");
element.setAttribute("icon", "car"); await flush(); assert.deepEqual(element.querySelector("svg").id, "second"); }); });
describe("PluginIcon - caching", () => { it("only fetches once when the same icon is rendered twice", async () => { const fetch = new MockFetch(); fetch.__intercept("/img/icons/", async () => okResponse(SAMPLE_SVG)); globalThis.fetch = fetch;
const first = document.createElement("plugin-icon"); first.setAttribute("icon", "chat"); document.body.appendChild(first);
const second = document.createElement("plugin-icon"); second.setAttribute("icon", "chat"); document.body.appendChild(second);
await flush();
assert.deepEqual(fetch.calls.length, 1); assert(first.querySelector("svg") !== null); assert(second.querySelector("svg") !== null); }); });
describe("PluginIcon - error handling", () => { it("warns and renders nothing when the fetch 404s; does not retry", async () => { const fetch = new MockFetch(); fetch.__intercept("/img/icons/", async () => notFoundResponse()); globalThis.fetch = fetch;
const originalWarn = console.warn; const warnMock = mock.fn(); console.warn = warnMock;
try { const element = document.createElement("plugin-icon"); element.setAttribute("icon", "moon"); document.body.appendChild(element); await flush();
assert.deepEqual(element.innerHTML, ""); assert.deepEqual(warnMock.mock.callCount(), 1);
const retry = document.createElement("plugin-icon"); retry.setAttribute("icon", "moon"); document.body.appendChild(retry); await flush();
assert.deepEqual(fetch.calls.length, 1); } finally { console.warn = originalWarn; } }); });});