mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-06 04:42:57 +00:00
Remove dynamic style system and tighten inline style checks
This commit is contained in:
1 parent
861a9036d3
commit
dfa4a98f0a
6 files changed
+40
-295
No files matched your search
@@ -3,11 +3,16 @@ import { beforeEach, afterEach, describe, test } from 'node:test';
|
||||
|
||||
import { advanceSlide, createCarousel, destroyCarousel } from '../js/blog/carousel.js';
|
||||
import { mountProgressBar } from '../js/blog/progressBar.js';
|
||||
import {
|
||||
createBlogDomEnvironment,
|
||||
createSpy,
|
||||
readDynamicStyleRules,
|
||||
} from './test-helpers/blog-dom.mjs';
|
||||
import { createBlogDomEnvironment, createSpy } from './test-helpers/blog-dom.mjs';
|
||||
|
||||
function assertHasClasses(element, classes, messagePrefix = 'element') {
|
||||
classes.forEach((className) => {
|
||||
assert.ok(
|
||||
element.classList.contains(className),
|
||||
`${messagePrefix} should include the “${className}” class`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function assertNoInlineStyleAttributes(elements, messagePrefix = 'element') {
|
||||
elements.forEach((element, index) => {
|
||||
@@ -208,8 +213,12 @@ describe('progress bar', () => {
|
||||
|
||||
const wrapper = container.querySelector('.blog-carousel__progress');
|
||||
assert.ok(wrapper, 'wrapper element should be appended');
|
||||
assertHasClasses(wrapper, ['blog-carousel__progress', 'blog-progress', 'mt-2'], 'progress wrapper');
|
||||
assert.strictEqual(wrapper.dataset.carouselProgress, 'true');
|
||||
assert.strictEqual(wrapper.getAttribute('data-carousel-progress'), 'true');
|
||||
const meter = wrapper.querySelector('progress.progress--blog');
|
||||
assert.ok(meter, 'progress meter should be created');
|
||||
assertHasClasses(meter, ['progress', 'progress--blog'], 'progress meter');
|
||||
assert.strictEqual(meter.max, 100, 'progress meter should expose a 0-100 range');
|
||||
assert.strictEqual(meter.value, 0, 'progress meter should start at zero');
|
||||
assert.strictEqual(meter.dataset.state, 'idle');
|
||||
@@ -220,12 +229,12 @@ describe('progress bar', () => {
|
||||
'Carousel progress 0% complete',
|
||||
'progress meter should emit accessible status text',
|
||||
);
|
||||
assert.strictEqual(meter.getAttribute('data-progress-meter'), 'true');
|
||||
assert.strictEqual(meter.dataset.progressMeter, 'true');
|
||||
assert.strictEqual(meter.getAttribute('data-variant'), 'blog');
|
||||
|
||||
progress.reset();
|
||||
|
||||
assert.strictEqual(readDynamicStyleRules(env.document), '', 'no dynamic style rules should be injected');
|
||||
assert.strictEqual(env.document.getElementById('bitvid-style-system'), null);
|
||||
|
||||
assertNoInlineStyleAttributes([container, wrapper, meter], 'progress element');
|
||||
});
|
||||
|
||||
@@ -249,9 +258,6 @@ describe('progress bar', () => {
|
||||
assert.strictEqual(meter.value, 100);
|
||||
assert.strictEqual(meter.dataset.state, 'complete');
|
||||
assert.strictEqual(meter.dataset.progress, '100');
|
||||
|
||||
assert.strictEqual(readDynamicStyleRules(env.document), '', 'no dynamic style rules should be injected');
|
||||
assert.strictEqual(env.document.getElementById('bitvid-style-system'), null);
|
||||
});
|
||||
|
||||
test('manual controls support stop, restart, and cleanup', () => {
|
||||
@@ -281,9 +287,11 @@ describe('progress bar', () => {
|
||||
|
||||
progress.destroy();
|
||||
assert.strictEqual(container.children.length, 0, 'destroy should remove wrapper from DOM');
|
||||
|
||||
assert.strictEqual(readDynamicStyleRules(env.document), '', 'no dynamic style rules should be injected');
|
||||
assert.strictEqual(env.document.getElementById('bitvid-style-system'), null);
|
||||
assert.strictEqual(
|
||||
container.querySelector('[data-carousel-progress]'),
|
||||
null,
|
||||
'destroy should remove declarative progress markup',
|
||||
);
|
||||
assertNoInlineStyleAttributes([container], 'progress container');
|
||||
});
|
||||
});
|
||||
@@ -188,8 +188,8 @@ test("MediaLoader clears unsupported lazy targets without inline styles", async
|
||||
]);
|
||||
|
||||
assert.equal(
|
||||
div.style.backgroundImage,
|
||||
"",
|
||||
div.hasAttribute("style"),
|
||||
false,
|
||||
"background image styles should not be injected at runtime",
|
||||
);
|
||||
assert.ok(!observer.observed.has(div));
|
||||
|
||||
@@ -3,6 +3,14 @@ import assert from "node:assert/strict";
|
||||
import { JSDOM } from "jsdom";
|
||||
import positionFloatingPanel from "../js/ui/utils/positionFloatingPanel.js";
|
||||
|
||||
function getInlineStyleValue(element, property) {
|
||||
const styleAttr = element.getAttribute("style") || "";
|
||||
const escapedProperty = property.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
const pattern = new RegExp(`(?:^|;)\\s*${escapedProperty}\\s*:\\s*([^;]+)`, "i");
|
||||
const match = styleAttr.match(pattern);
|
||||
return match ? match[1].trim() : "";
|
||||
}
|
||||
|
||||
test("flips to top when bottom placement collides with viewport", () => {
|
||||
const dom = new JSDOM(
|
||||
`
|
||||
@@ -54,9 +62,9 @@ test("flips to top when bottom placement collides with viewport", () => {
|
||||
positioner.update();
|
||||
|
||||
assert.equal(panel.dataset.floatingPlacement, "top");
|
||||
assert.equal(panel.style.position, "fixed");
|
||||
assert.equal(panel.style.getPropertyValue("--floating-fallback-top"), "132px");
|
||||
assert.equal(panel.style.getPropertyValue("--floating-fallback-left"), "100px");
|
||||
assert.equal(getInlineStyleValue(panel, "position"), "fixed");
|
||||
assert.equal(getInlineStyleValue(panel, "--floating-fallback-top"), "132px");
|
||||
assert.equal(getInlineStyleValue(panel, "--floating-fallback-left"), "100px");
|
||||
|
||||
positioner.destroy();
|
||||
assert.equal(panel.dataset.floatingPanel, undefined);
|
||||
@@ -118,7 +126,7 @@ test("respects RTL alignment and clamps within the viewport", () => {
|
||||
// In RTL mode, start alignment hugs the right edge of the trigger.
|
||||
assert.equal(panel.dataset.floatingPlacement, "bottom");
|
||||
assert.equal(panel.dataset.floatingDir, "rtl");
|
||||
assert.equal(panel.style.getPropertyValue("--floating-fallback-left"), "140px");
|
||||
assert.equal(getInlineStyleValue(panel, "--floating-fallback-left"), "140px");
|
||||
|
||||
positioner.destroy();
|
||||
});
|
||||
@@ -182,12 +190,12 @@ test("updates when scroll containers move the trigger", async () => {
|
||||
panel.dataset.state = "open";
|
||||
positioner.update();
|
||||
|
||||
assert.equal(panel.style.getPropertyValue("--floating-fallback-top"), "152px");
|
||||
assert.equal(getInlineStyleValue(panel, "--floating-fallback-top"), "152px");
|
||||
assert.ok(scrollHandler, "scroll listener should be registered");
|
||||
|
||||
anchorTop = 60;
|
||||
scrollHandler?.({ type: "scroll" });
|
||||
assert.equal(panel.style.getPropertyValue("--floating-fallback-top"), "112px");
|
||||
assert.equal(getInlineStyleValue(panel, "--floating-fallback-top"), "112px");
|
||||
|
||||
positioner.destroy();
|
||||
window.addEventListener = originalAddEventListener;
|
||||
|
||||
@@ -157,22 +157,6 @@ export function installInlineStyleGuard(document) {
|
||||
};
|
||||
}
|
||||
|
||||
export function readDynamicStyleRules(document) {
|
||||
const styleElement = document.getElementById('bitvid-style-system');
|
||||
const sheet = styleElement?.sheet;
|
||||
if (!sheet) {
|
||||
return '';
|
||||
}
|
||||
|
||||
try {
|
||||
return Array.from(sheet.cssRules)
|
||||
.map((rule) => rule.cssText)
|
||||
.join('\n');
|
||||
} catch (error) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export function createBlogDomEnvironment(html) {
|
||||
const dom = new JSDOM(html, { url: 'https://example.com' });
|
||||
const { window } = dom;
|
||||
|
||||
Reference in new issue
Block a user