mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-06 21:02:28 +00:00
refactor: use static classes for beacon utilities
This commit is contained in:
1 parent
f57abdf824
commit
27c1c4fa11
6 files changed
+77
-157
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { strict as assert } from "node:assert";
|
||||
import { describe, it, beforeEach, afterEach } from "node:test";
|
||||
import { describe, it } from "node:test";
|
||||
import { JSDOM } from "jsdom";
|
||||
|
||||
import {
|
||||
@@ -8,113 +8,34 @@ import {
|
||||
beaconDynamicFallbackClasses,
|
||||
} from "../../torrent/ui/styleHelpers.js";
|
||||
|
||||
const ORIGINAL_WINDOW = globalThis.window;
|
||||
const ORIGINAL_DOCUMENT = globalThis.document;
|
||||
const ORIGINAL_ELEMENT = globalThis.HTMLElement;
|
||||
const ORIGINAL_STYLE_ELEMENT = globalThis.HTMLStyleElement;
|
||||
|
||||
let dom;
|
||||
|
||||
function bootstrapDom() {
|
||||
dom = new JSDOM("<!doctype html><html><head></head><body></body></html>", {
|
||||
pretendToBeVisual: true,
|
||||
});
|
||||
globalThis.window = dom.window;
|
||||
globalThis.document = dom.window.document;
|
||||
globalThis.HTMLElement = dom.window.HTMLElement;
|
||||
globalThis.HTMLStyleElement = dom.window.HTMLStyleElement;
|
||||
}
|
||||
|
||||
function teardownDom() {
|
||||
if (dom) {
|
||||
dom.window.close();
|
||||
dom = null;
|
||||
}
|
||||
if (typeof ORIGINAL_WINDOW === "undefined") {
|
||||
delete globalThis.window;
|
||||
} else {
|
||||
globalThis.window = ORIGINAL_WINDOW;
|
||||
}
|
||||
if (typeof ORIGINAL_DOCUMENT === "undefined") {
|
||||
delete globalThis.document;
|
||||
} else {
|
||||
globalThis.document = ORIGINAL_DOCUMENT;
|
||||
}
|
||||
if (typeof ORIGINAL_ELEMENT === "undefined") {
|
||||
delete globalThis.HTMLElement;
|
||||
} else {
|
||||
globalThis.HTMLElement = ORIGINAL_ELEMENT;
|
||||
}
|
||||
if (typeof ORIGINAL_STYLE_ELEMENT === "undefined") {
|
||||
delete globalThis.HTMLStyleElement;
|
||||
} else {
|
||||
globalThis.HTMLStyleElement = ORIGINAL_STYLE_ELEMENT;
|
||||
}
|
||||
}
|
||||
|
||||
describe("torrent/ui/styleHelpers", () => {
|
||||
beforeEach(() => {
|
||||
bootstrapDom();
|
||||
it("returns null when no element is provided", () => {
|
||||
assert.equal(applyBeaconDynamicStyles(null), null);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
teardownDom();
|
||||
it("returns the original element without mutations", () => {
|
||||
const dom = new JSDOM("<!doctype html><html><head></head><body></body></html>");
|
||||
const { document } = dom.window;
|
||||
const element = document.createElement("div");
|
||||
|
||||
const result = applyBeaconDynamicStyles(element);
|
||||
|
||||
assert.equal(result, element);
|
||||
assert.equal(element.getAttributeNames().length, 0);
|
||||
});
|
||||
|
||||
it("registers fallback classes for known slots", () => {
|
||||
assert.equal(
|
||||
beaconDynamicFallbackClasses.hiddenDownload,
|
||||
"torrent-download-anchor",
|
||||
);
|
||||
assert.equal(
|
||||
beaconDynamicFallbackClasses.clipboard,
|
||||
"torrent-clipboard-textarea",
|
||||
);
|
||||
assert.equal(beaconDynamicFallbackClasses.toast, "torrent-toast-motion");
|
||||
it("provides an empty, frozen fallback map", () => {
|
||||
assert.deepEqual(beaconDynamicFallbackClasses, {});
|
||||
assert.throws(() => {
|
||||
beaconDynamicFallbackClasses.test = "nope";
|
||||
}, TypeError);
|
||||
});
|
||||
|
||||
it("applies dynamic styles and fallback classes", () => {
|
||||
const element = document.createElement("a");
|
||||
document.body.appendChild(element);
|
||||
|
||||
const className = applyBeaconDynamicStyles(
|
||||
element,
|
||||
{ display: "none" },
|
||||
"hiddenDownload",
|
||||
);
|
||||
|
||||
assert.ok(className, "should receive a generated class name");
|
||||
assert.ok(
|
||||
element.classList.contains("torrent-download-anchor"),
|
||||
"fallback class should be present",
|
||||
);
|
||||
assert.ok(
|
||||
element.classList.contains(className),
|
||||
"dynamic class should be applied",
|
||||
);
|
||||
|
||||
const styleTag = document.getElementById("bitvid-style-system");
|
||||
assert.ok(styleTag, "style system tag should be created");
|
||||
});
|
||||
|
||||
it("removes dynamic styles and fallback classes", () => {
|
||||
const element = document.createElement("textarea");
|
||||
document.body.appendChild(element);
|
||||
|
||||
applyBeaconDynamicStyles(element, { opacity: "0" }, "clipboard");
|
||||
assert.ok(element.classList.contains("torrent-clipboard-textarea"));
|
||||
|
||||
removeBeaconDynamicStyles(element, "clipboard");
|
||||
|
||||
assert.ok(
|
||||
!element.classList.contains("torrent-clipboard-textarea"),
|
||||
"fallback class should be removed",
|
||||
);
|
||||
});
|
||||
|
||||
it("gracefully handles missing elements", () => {
|
||||
const result = applyBeaconDynamicStyles(null, { display: "none" });
|
||||
assert.equal(result, null);
|
||||
it("no-ops when removing styles", () => {
|
||||
assert.doesNotThrow(() => removeBeaconDynamicStyles(null));
|
||||
const dom = new JSDOM("<!doctype html><html><head></head><body></body></html>");
|
||||
const { document } = dom.window;
|
||||
const element = document.createElement("div");
|
||||
assert.doesNotThrow(() => removeBeaconDynamicStyles(element));
|
||||
});
|
||||
});
|
||||
@@ -22,6 +22,7 @@ describe("torrent/ui/toastService", () => {
|
||||
|
||||
it("renders a toast with Tailwind token classes and removes it on dismiss", async () => {
|
||||
const documentRef = dom.window.document;
|
||||
documentRef.defaultView.requestAnimationFrame = (cb) => cb();
|
||||
const toastManager = createToastManager(documentRef);
|
||||
const handle = toastManager.success("Magnet copied", { sticky: true });
|
||||
|
||||
@@ -31,7 +32,8 @@ describe("torrent/ui/toastService", () => {
|
||||
|
||||
const wrapper = container.firstElementChild;
|
||||
assert.ok(wrapper, "toast wrapper should exist");
|
||||
assert.equal(wrapper.classList.contains("torrent-toast-motion"), true);
|
||||
assert.equal(wrapper.classList.contains("beacon-toast-motion"), true);
|
||||
assert.equal(wrapper.getAttribute("data-beacon-motion"), "enter");
|
||||
|
||||
const toast = wrapper.querySelector("div[role='status']");
|
||||
assert.ok(toast, "toast element should be present");
|
||||
@@ -43,6 +45,7 @@ describe("torrent/ui/toastService", () => {
|
||||
assert.ok(closeButton, "close button should be rendered");
|
||||
|
||||
handle.dismiss();
|
||||
assert.equal(wrapper.getAttribute("data-beacon-motion"), "exit");
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 250));
|
||||
|
||||
|
||||
Reference in new issue
Block a user