Add DOM-safe blog carousel regression tests

This commit is contained in:
thePR0M3TH3AN committed 2025-10-13 17:28:57 -04:00
1 parent 3fba911f9a
commit 64beeaa8e5
2 files changed
+64

No files matched your search

+21
View File
@@ -9,6 +9,17 @@ import {
readDynamicStyleRules,
} from './test-helpers/blog-dom.mjs';
function assertNoInlineStyleAttributes(elements, messagePrefix = 'element') {
elements.forEach((element, index) => {
assert.ok(element, `${messagePrefix} at index ${index} should exist`);
assert.strictEqual(
element.hasAttribute('style'),
false,
`${messagePrefix} at index ${index} should not set inline style attributes`,
);
});
}
const CAROUSEL_HTML = `
<div data-carousel>
<div data-carousel-track>
@@ -68,6 +79,8 @@ describe('blog carousel', () => {
const trackDynamicClasses = Array.from(track.classList).filter((className) => className.startsWith('bvds-'));
assert.ok(trackDynamicClasses.length >= 1, 'track should receive dynamic style classes');
assertNoInlineStyleAttributes([container, track, ...slides], 'carousel element');
for (const slide of slides) {
assert.ok(slide.classList.contains('splide__slide'));
const dynamicClasses = Array.from(slide.classList).filter((className) => className.startsWith('bvds-'));
@@ -151,6 +164,8 @@ describe('blog carousel', () => {
assert.ok(!container.classList.contains('is-active'));
assert.strictEqual(state.cleanup.length, 0);
assertNoInlineStyleAttributes([container, track, ...slides], 'carousel element');
const previousIndex = state.index;
nextButton.dispatchEvent(new env.window.MouseEvent('click', { bubbles: true }));
assert.strictEqual(state.index, previousIndex, 'clicks after destroy should not change the index');
@@ -195,6 +210,8 @@ describe('progress bar', () => {
progress.reset();
const cssRules = readDynamicStyleRules(env.document);
assert.match(cssRules, /width:\s*0%/);
assertNoInlineStyleAttributes([container, wrapper, fill], 'progress element');
});
test('autoStart runs animation and triggers completion callback', () => {
@@ -204,6 +221,8 @@ describe('progress bar', () => {
const fill = wrapper.querySelector('.splide__progress__bar');
assert.ok(Array.from(fill.classList).some((className) => className.startsWith('bvds-')));
assertNoInlineStyleAttributes([container, wrapper, fill], 'progress element');
env.raf.step(0);
env.raf.step(300);
assert.strictEqual(onComplete.callCount, 0);
@@ -232,5 +251,7 @@ describe('progress bar', () => {
progress.destroy();
assert.strictEqual(container.children.length, 0, 'destroy should remove wrapper from DOM');
assertNoInlineStyleAttributes([container], 'progress container');
});
});
+43
View File
@@ -66,7 +66,43 @@ export function createAnimationFrameStub() {
export function installInlineStyleGuard(document) {
const originalCreateElement = document.createElement.bind(document);
const ElementConstructor = document.defaultView?.Element;
const guardedElements = new WeakSet();
const attributePatches = [];
if (ElementConstructor?.prototype) {
const prototype = ElementConstructor.prototype;
if (typeof prototype.setAttribute === 'function') {
const original = prototype.setAttribute;
prototype.setAttribute = function inlineStyleSafeSetAttribute(name, value) {
if (typeof name === 'string' && name.toLowerCase() === 'style') {
throw new Error(
'Inline style attributes are disabled in blog widget tests. Use applyDynamicStyles or CSS class toggles instead.',
);
}
return original.call(this, name, value);
};
attributePatches.push(() => {
prototype.setAttribute = original;
});
}
if (typeof prototype.setAttributeNS === 'function') {
const original = prototype.setAttributeNS;
prototype.setAttributeNS = function inlineStyleSafeSetAttributeNS(namespace, name, value) {
if (typeof name === 'string' && name.toLowerCase() === 'style') {
throw new Error(
'Inline style attributes are disabled in blog widget tests. Use applyDynamicStyles or CSS class toggles instead.',
);
}
return original.call(this, namespace, name, value);
};
attributePatches.push(() => {
prototype.setAttributeNS = original;
});
}
}
function guard(element) {
if (!element || typeof element !== 'object') {
@@ -110,6 +146,13 @@ export function installInlineStyleGuard(document) {
guard,
restore() {
document.createElement = originalCreateElement;
attributePatches.forEach((restorePatch) => {
try {
restorePatch();
} catch (error) {
// ignore failures to restore in tests
}
});
},
};
}