Remove design system flag and update tests

This commit is contained in:
thePR0M3TH3AN committed 2025-10-14 20:16:38 -04:00
1 parent 68774f7e78
commit 39d8cee81a
14 files changed
+123 -295

No files matched your search

+4 -6
View File
@@ -1,9 +1,7 @@
# Deployment Notes
## FEATURE_DESIGN_SYSTEM rollout
## Design system rollout
- **Default:** `true` (design system styling). The flag lives in `js/constants.js` and is exposed through `window.__BITVID_RUNTIME_FLAGS__` at runtime.
- **Enable for canaries:** No action required—the new primitives ship enabled by default.
- **Disable / rollback:** Set the flag to `false` via the runtime object or redeploy with an override. All root containers revert to `data-ds="new"`, forcing controllers and templates to stay on the existing class list.
- **Template contract:** Every layout, view, and partial now includes `data-ds` on the root element. Keep this attribute intact when editing HTML so the runtime can swap modes without re-rendering.
- **Controllers:** UI controllers receive a `designSystem` context in their constructors. Call `context.isNew()` before attaching new components or classes, and lean on `context.getMode()` when logging or telemetry need to differentiate between legacy and new renders.
- **Status:** The design system styling is always active. The former `FEATURE_DESIGN_SYSTEM` runtime flag has been removed, so there is no rollback toggle during deployment.
- **Template contract:** Every layout, view, and partial must keep `data-ds` on its root element. The entrypoint stamps `data-ds="new"` during bootstrap so controllers inherit the correct primitives.
- **Controllers:** UI controllers still receive a `designSystem` context, but `context.isNew()` now always returns `true`. Use the context for consistency, but do not branch on legacy styling paths.
+9 -13
View File
@@ -4,13 +4,9 @@ bitvid's visual language is now powered by Tailwind utilities backed by our desi
All templates and embeds must load `css/tailwind.generated.css`; that compiled bundle is the only stylesheet shipped with the app. Remove any lingering references to legacy `tailwind.min.css` assets when porting surfaces into the design system.
## Feature Flag Rollout
## Runtime contract
The new design system ships behind the `FEATURE_DESIGN_SYSTEM` runtime flag defined in `js/constants.js`. Deployments can temporarily disable the flag (`false`) if they need to fall back to the legacy primitives during an incident.
- **Default state:** `FEATURE_DESIGN_SYSTEM` is `true`, so templates render with `data-ds="new"` on root containers.
- **Runtime toggle:** Set `window.__BITVID_RUNTIME_FLAGS__.FEATURE_DESIGN_SYSTEM = false` (or call `setFeatureDesignSystemEnabled(false)`) to temporarily fall back to the legacy primitives. The entrypoint automatically updates every `[data-ds]` container to `data-ds="new"` and notifies controllers.
- **DOM contract:** Templates and partials must include `data-ds` on their root elements. Controllers should rely on the `designSystem` context (see `js/designSystem.js`) before attaching classes or behaviors that only exist in the new system.
The design system is now the canonical styling path across bitvid—there is no runtime flag or rollback toggle. Every template renders with `data-ds="new"` on its root container, and controllers always receive the "new" mode from the `designSystem` context (see `js/designSystem.js`). When migrating surfaces, ensure their root nodes include `data-ds` so the entrypoint can stamp the attribute during bootstrap.
## Dynamic runtime styling
@@ -445,7 +441,7 @@ We continue to expose aliases such as `.profile-switcher` and nested variations
- [ ] Confirm no production templates emit `.profile-switcher*` selectors (owners: @ui-templates, @design-systems).
- [ ] Verify the torrent beacon renders `.card`, `.btn`, `.btn-ghost`, and `.input` primitives with no fallback selectors (owner: @torrent-beacon).
- [ ] Verify `FEATURE_DESIGN_SYSTEM` remains `true` in staging and run kitchen-sink visual snapshots to ensure no regressions.
- [ ] Verify staging renders with `data-ds="new"` across surfaces and run kitchen-sink visual snapshots to ensure no regressions.
- [ ] Delete residual `@apply` rules under "Legacy component compatibility" in `css/tailwind.source.css`.
- [ ] Announce the removal in release notes and update downstream embed documentation.
@@ -457,11 +453,11 @@ We continue to expose aliases such as `.profile-switcher` and nested variations
| Legacy selector | Replacement primitive(s) | Beacon / app notes | Feature-flag strategy |
| --- | --- | --- | --- |
| `.video-card`, `.video-card__meta`, `.video-card--loading` | `.card` with `data-state` + utility classes | Removed in web app; ensure beacon dashboards render `.card` with skeleton states instead of `.video-card--loading`. | Ship markup updates behind `FEATURE_DESIGN_SYSTEM`, defaulting to legacy HTML until verified.
| `.profile-switcher`, `.profile-switcher__item` | `.card` rows + `.btn-ghost` toggles | Keep shim until profile modal Reactors deploy; beacon does not consume this selector. | Enable flag per environment after QA verifies profile modals in the kitchen sink.
| `.button`, `.button-danger` (Skeleton) | `.btn`, `.btn-ghost[data-variant="critical"]` | Critical for torrent beacon—replace the Angular templates before removing Skeleton CDN. | Roll out under `FEATURE_DESIGN_SYSTEM` in beacon build; leave fallback until beacon release 2025.03 ships.
| `.u-full-width`, `.input-text` | `.input`, `.select`, `.form-control` | Applies to upload forms and beacon filter controls; also update tests that target legacy classes. | Toggle per route: controllers read `designSystem.isEnabled()` before rendering new markup.
| `.modal-container`, `.modal-content` | `.bv-modal`, `.bv-modal-backdrop`, `.bv-modal__panel` | Already removed in core app; verify beacon modals use the primitives before deleting helper styles. | No flag required—templates should ship the primitives outright while flag protects unrelated surfaces.
| `.video-card`, `.video-card__meta`, `.video-card--loading` | `.card` with `data-state` + utility classes | Removed in web app; ensure beacon dashboards render `.card` with skeleton states instead of `.video-card--loading`. | Deploy directly and validate in staging before rolling to beacon.
| `.profile-switcher`, `.profile-switcher__item` | `.card` rows + `.btn-ghost` toggles | Keep shim until profile modal Reactors deploy; beacon does not consume this selector. | Roll out once QA signs off; no flag gating remains.
| `.button`, `.button-danger` (Skeleton) | `.btn`, `.btn-ghost[data-variant="critical"]` | Critical for torrent beacon—replace the Angular templates before removing Skeleton CDN. | Coordinate a staged deploy; the design system is always on so fallbacks must ship in a separate release if required.
| `.u-full-width`, `.input-text` | `.input`, `.select`, `.form-control` | Applies to upload forms and beacon filter controls; also update tests that target legacy classes. | Update markup globally; controllers now always run in the design system mode.
| `.modal-container`, `.modal-content` | `.bv-modal`, `.bv-modal-backdrop`, `.bv-modal__panel` | Already removed in core app; verify beacon modals use the primitives before deleting helper styles. | Ship the primitives outright; there is no fallback mode.
### Migration Notes (Q4 2024)
@@ -510,7 +506,7 @@ Avoid re-declaring token values manually. If a new pattern repeats, promote it i
Continuous integration captures Playwright-powered screenshots of `docs/kitchen-sink.html` (`tests/visual/kitchen-sink.spec.ts`) on every pull request. When a snapshot job fails:
1. Read the diff produced by Playwright (attached as an artifact) and compare it with your local preview. The harness highlights per-pixel changes so reviewers can distinguish deliberate theme updates from regressions.
2. Reproduce locally with `npm run test:visual -- --update-snapshots` to refresh the expected images after verifying the change in the kitchen sink. Always run the command with the same feature flag configuration used in CI (`FEATURE_DESIGN_SYSTEM=true`).
2. Reproduce locally with `npm run test:visual -- --update-snapshots` to refresh the expected images after verifying the change in the kitchen sink.
3. Document the intent in the PR description (include before/after screenshots or reference the kitchen-sink toggle state) so reviewers and QA know the snapshot change is expected.
The design system doc is the single source of truth for reviewing these failures—if a diff contradicts the guidance above, treat it as a regression, request updates, and block the merge until the visual snapshot stabilises.
+2 -2
View File
@@ -4,13 +4,13 @@ Run this checklist before publishing releases or merging changes that touch uplo
Before starting, open `docs/kitchen-sink.html` in a browser to review the modal surface reference. With that page as your visual baseline, perform this quick accessibility spot check in the running app:
Automated regression coverage now exercises these flows across both the legacy and design-system variants:
Automated regression coverage now exercises these flows on the unified design-system variant:
* `tests/video-modal-accessibility.test.mjs` validates sticky header transitions, scroll locking, zap popover accessibility, and now verifies the video shell drops sticky positioning on mobile breakpoints.
* `tests/modal-accessibility.test.mjs` mirrors upload/edit modal accessibility along with their form validation and mode toggles.
* `tests/profile-modal-controller.test.mjs` verifies profile modal focus restoration and navigation button state changes.
`tests/visual/kitchen-sink.spec.ts` captures design-system snapshots for the kitchen sink and the video modal. When modal styles change, run `npm run test:visual:update` to refresh both the desktop and mobile baselines with `FEATURE_DESIGN_SYSTEM` toggled on and off.
`tests/visual/kitchen-sink.spec.ts` captures design-system snapshots for the kitchen sink and the video modal. When modal styles change, run `npm run test:visual:update` to refresh both the desktop and mobile baselines.
* Launch the site, trigger any video card or thumbnail to open the playback modal, and keep track of the element you used to open it.
* Scroll the modal content down and back up; confirm the sticky navigation bar hides on downward scroll and reappears when you reverse direction.
+5 -31
View File
@@ -84,10 +84,7 @@ import {
applyRootTimestampToVideosMap,
syncActiveVideoRootTimestamp,
} from "./utils/videoTimestamps.js";
import {
getDesignSystemMode as readDesignSystemMode,
subscribeToDesignSystemChanges,
} from "./designSystem.js";
import { getDesignSystemMode as getCanonicalDesignSystemMode } from "./designSystem.js";
import {
getPubkey as getStoredPubkey,
setPubkey as setStoredPubkey,
@@ -186,21 +183,10 @@ class Application {
this.watchHistoryTelemetry = null;
this.authEventUnsubscribes = [];
this.unsubscribeFromNostrService = null;
this.unsubscribeFromDesignSystem = null;
this.designSystemMode = readDesignSystemMode();
this.designSystemContext = {
getMode: () => this.getDesignSystemMode(),
isNew: () => this.isDesignSystemNew(),
getMode: () => "new",
isNew: () => true,
};
this.unsubscribeFromDesignSystem = subscribeToDesignSystemChanges(
({ mode }) => {
if (typeof mode === "string" && mode) {
this.designSystemMode = mode;
} else {
this.designSystemMode = readDesignSystemMode();
}
}
);
this.videoModalReadyPromise = null;
this.boundUploadSubmitHandler = null;
this.boundEditModalSubmitHandler = null;
@@ -1326,11 +1312,11 @@ class Application {
}
getDesignSystemMode() {
return this.designSystemMode === "new" ? "new" : "legacy";
return getCanonicalDesignSystemMode();
}
isDesignSystemNew() {
return this.getDesignSystemMode() === "new";
return true;
}
/**
@@ -6636,18 +6622,6 @@ class Application {
this.teardownModalViewCountSubscription();
this.videoModalReadyPromise = null;
if (typeof this.unsubscribeFromDesignSystem === "function") {
try {
this.unsubscribeFromDesignSystem();
} catch (error) {
console.warn(
"[Application] Failed to unsubscribe design system listener:",
error
);
}
this.unsubscribeFromDesignSystem = null;
}
if (this.watchHistoryTelemetry) {
try {
this.watchHistoryTelemetry.destroy();
-77
View File
@@ -4,7 +4,6 @@ const DEFAULT_FLAGS = Object.freeze({
VIEW_FILTER_INCLUDE_LEGACY_VIDEO: false,
FEATURE_WATCH_HISTORY_V2: false,
FEATURE_PUBLISH_NIP71: false,
FEATURE_DESIGN_SYSTEM: true,
WSS_TRACKERS: Object.freeze([
"wss://tracker.openwebtorrent.com",
"wss://tracker.fastcast.nz",
@@ -13,48 +12,8 @@ const DEFAULT_FLAGS = Object.freeze({
]),
});
export const DESIGN_SYSTEM_EVENT_NAME = "bitvid:design-system-flag-change";
const globalScope = typeof globalThis === "object" && globalThis ? globalThis : undefined;
function dispatchDesignSystemFlagChange(enabled) {
if (
!globalScope ||
typeof globalScope.dispatchEvent !== "function" ||
(typeof globalScope.CustomEvent !== "function" &&
typeof globalScope.Event !== "function")
) {
return;
}
let event;
if (typeof globalScope.CustomEvent === "function") {
event = new globalScope.CustomEvent(DESIGN_SYSTEM_EVENT_NAME, {
detail: { enabled: enabled === true },
});
} else {
event = new globalScope.Event(DESIGN_SYSTEM_EVENT_NAME);
try {
Object.defineProperty(event, "detail", {
configurable: true,
enumerable: true,
writable: true,
value: { enabled: enabled === true },
});
} catch (error) {
// Older browsers may not allow redefining detail; ignore.
}
}
try {
globalScope.dispatchEvent(event);
} catch (error) {
if (typeof console !== "undefined" && console && console.warn) {
console.warn("[design-system] Failed to dispatch flag change event:", error);
}
}
}
const runtimeFlags = (() => {
if (globalScope && typeof globalScope.__BITVID_RUNTIME_FLAGS__ === "object") {
return globalScope.__BITVID_RUNTIME_FLAGS__;
@@ -66,7 +25,6 @@ const runtimeFlags = (() => {
DEFAULT_FLAGS.VIEW_FILTER_INCLUDE_LEGACY_VIDEO,
FEATURE_WATCH_HISTORY_V2: DEFAULT_FLAGS.FEATURE_WATCH_HISTORY_V2,
FEATURE_PUBLISH_NIP71: DEFAULT_FLAGS.FEATURE_PUBLISH_NIP71,
FEATURE_DESIGN_SYSTEM: DEFAULT_FLAGS.FEATURE_DESIGN_SYSTEM,
WSS_TRACKERS: [...DEFAULT_FLAGS.WSS_TRACKERS],
};
if (globalScope) {
@@ -157,11 +115,6 @@ export let FEATURE_PUBLISH_NIP71 = coerceBoolean(
DEFAULT_FLAGS.FEATURE_PUBLISH_NIP71
);
export let FEATURE_DESIGN_SYSTEM = coerceBoolean(
runtimeFlags.FEATURE_DESIGN_SYSTEM,
DEFAULT_FLAGS.FEATURE_DESIGN_SYSTEM
);
export let WSS_TRACKERS = freezeTrackers(
sanitizeTrackerList(runtimeFlags.WSS_TRACKERS)
);
@@ -230,25 +183,6 @@ Object.defineProperty(runtimeFlags, "FEATURE_PUBLISH_NIP71", {
},
});
Object.defineProperty(runtimeFlags, "FEATURE_DESIGN_SYSTEM", {
configurable: true,
enumerable: true,
get() {
return FEATURE_DESIGN_SYSTEM;
},
set(next) {
const previous = FEATURE_DESIGN_SYSTEM === true;
FEATURE_DESIGN_SYSTEM = coerceBoolean(
next,
DEFAULT_FLAGS.FEATURE_DESIGN_SYSTEM
);
const current = FEATURE_DESIGN_SYSTEM === true;
if (previous !== current) {
dispatchDesignSystemFlagChange(current);
}
},
});
Object.defineProperty(runtimeFlags, "WSS_TRACKERS", {
configurable: true,
enumerable: true,
@@ -266,7 +200,6 @@ runtimeFlags.ACCEPT_LEGACY_V1 = ACCEPT_LEGACY_V1;
runtimeFlags.VIEW_FILTER_INCLUDE_LEGACY_VIDEO = VIEW_FILTER_INCLUDE_LEGACY_VIDEO;
runtimeFlags.FEATURE_WATCH_HISTORY_V2 = FEATURE_WATCH_HISTORY_V2;
runtimeFlags.FEATURE_PUBLISH_NIP71 = FEATURE_PUBLISH_NIP71;
runtimeFlags.FEATURE_DESIGN_SYSTEM = FEATURE_DESIGN_SYSTEM;
runtimeFlags.WSS_TRACKERS = WSS_TRACKERS;
export function setUrlFirstEnabled(next) {
@@ -288,10 +221,6 @@ export function getWatchHistoryV2Enabled() {
return FEATURE_WATCH_HISTORY_V2 === true;
}
export function getFeatureDesignSystemEnabled() {
return FEATURE_DESIGN_SYSTEM === true;
}
export function setWssTrackers(next) {
runtimeFlags.WSS_TRACKERS = next;
return WSS_TRACKERS;
@@ -304,7 +233,6 @@ export function resetRuntimeFlags() {
DEFAULT_FLAGS.VIEW_FILTER_INCLUDE_LEGACY_VIDEO
);
setWatchHistoryV2Enabled(DEFAULT_FLAGS.FEATURE_WATCH_HISTORY_V2);
setFeatureDesignSystemEnabled(DEFAULT_FLAGS.FEATURE_DESIGN_SYSTEM);
setWssTrackers(DEFAULT_FLAGS.WSS_TRACKERS);
}
@@ -315,8 +243,3 @@ export function setWatchHistoryV2Enabled(next) {
return FEATURE_WATCH_HISTORY_V2;
}
export function setFeatureDesignSystemEnabled(next) {
runtimeFlags.FEATURE_DESIGN_SYSTEM = next;
return FEATURE_DESIGN_SYSTEM;
}
+14 -48
View File
@@ -1,26 +1,16 @@
import {
DESIGN_SYSTEM_EVENT_NAME,
getFeatureDesignSystemEnabled,
} from "./constants.js";
const LEGACY_MODE = "legacy";
const NEW_MODE = "new";
const FALLBACK_CONTEXT = Object.freeze({
getMode: () => LEGACY_MODE,
isNew: () => false,
getMode: () => NEW_MODE,
isNew: () => true,
});
function normalizeMode(mode) {
return mode === NEW_MODE ? NEW_MODE : LEGACY_MODE;
}
export function getDesignSystemMode() {
return normalizeMode(getFeatureDesignSystemEnabled() ? NEW_MODE : LEGACY_MODE);
return NEW_MODE;
}
export function isDesignSystemNew() {
return getFeatureDesignSystemEnabled() === true;
return true;
}
export function normalizeDesignSystemContext(candidate) {
@@ -28,19 +18,15 @@ export function normalizeDesignSystemContext(candidate) {
return FALLBACK_CONTEXT;
}
const resolvedGetMode =
typeof candidate.getMode === "function"
? candidate.getMode
: FALLBACK_CONTEXT.getMode;
const resolvedIsNew =
typeof candidate.isNew === "function"
? candidate.isNew
: () => normalizeMode(resolvedGetMode()) === NEW_MODE;
return {
getMode: resolvedGetMode,
isNew: resolvedIsNew,
getMode:
typeof candidate.getMode === "function"
? candidate.getMode
: FALLBACK_CONTEXT.getMode,
isNew:
typeof candidate.isNew === "function"
? candidate.isNew
: FALLBACK_CONTEXT.isNew,
};
}
@@ -111,26 +97,6 @@ export function applyDesignSystemAttributes(root = null) {
}
export function subscribeToDesignSystemChanges(listener) {
if (typeof window !== "object" || window === null) {
return () => {};
}
if (typeof listener !== "function") {
return () => {};
}
const handler = (event) => {
listener({
mode: getDesignSystemMode(),
event,
});
};
window.addEventListener(DESIGN_SYSTEM_EVENT_NAME, handler);
return () => {
window.removeEventListener(DESIGN_SYSTEM_EVENT_NAME, handler);
};
void listener;
return () => {};
}
export { DESIGN_SYSTEM_EVENT_NAME };
+1 -8
View File
@@ -8,10 +8,7 @@ import { setApplication, setApplicationReady } from "./applicationContext.js";
import nostrService from "./services/nostrService.js";
import r2Service from "./services/r2Service.js";
import { loadView, viewInitRegistry } from "./viewManager.js";
import {
applyDesignSystemAttributes,
subscribeToDesignSystemChanges,
} from "./designSystem.js";
import { applyDesignSystemAttributes } from "./designSystem.js";
import {
initThemeController,
refreshThemeControls,
@@ -26,10 +23,6 @@ validateInstanceConfig();
applyDesignSystemAttributes();
initThemeController();
subscribeToDesignSystemChanges(() => {
applyDesignSystemAttributes();
refreshThemeControls(document);
});
let application = null;
let applicationReadyPromise = Promise.resolve();
+9 -26
View File
@@ -11,10 +11,7 @@ import {
openStaticModal,
closeStaticModal,
} from "../js/ui/components/staticModalAccessibility.js";
import {
setFeatureDesignSystemEnabled,
resetRuntimeFlags,
} from "../js/constants.js";
import { resetRuntimeFlags } from "../js/constants.js";
import { applyDesignSystemAttributes } from "../js/designSystem.js";
const uploadMarkupPromise = readFile(
@@ -95,11 +92,10 @@ async function flushMicrotasks() {
await Promise.resolve();
}
for (const designSystemEnabled of [false, true]) {
const modeLabel = designSystemEnabled ? "design-system" : "legacy";
for (const _ of [0]) {
test(
`[${modeLabel}] UploadModal closes on Escape and restores trigger focus`,
"UploadModal closes on Escape and restores trigger focus",
async (t) => {
const markup = await uploadMarkupPromise;
const cleanups = [];
@@ -112,8 +108,6 @@ for (const designSystemEnabled of [false, true]) {
stubFetch(new Map([["components/upload-modal.html", markup]])),
);
setFeatureDesignSystemEnabled(designSystemEnabled);
const modal = new UploadModal({
removeTrackingScripts: () => {},
setGlobalModalState: () => {},
@@ -149,7 +143,7 @@ for (const designSystemEnabled of [false, true]) {
);
test(
`[${modeLabel}] UploadModal backdrop click closes and restores trigger focus`,
"UploadModal backdrop click closes and restores trigger focus",
async (t) => {
const markup = await uploadMarkupPromise;
const cleanups = [];
@@ -162,8 +156,6 @@ for (const designSystemEnabled of [false, true]) {
stubFetch(new Map([["components/upload-modal.html", markup]])),
);
setFeatureDesignSystemEnabled(designSystemEnabled);
const modal = new UploadModal({
removeTrackingScripts: () => {},
setGlobalModalState: () => {},
@@ -198,7 +190,7 @@ for (const designSystemEnabled of [false, true]) {
);
test(
`[${modeLabel}] UploadModal mode toggle updates button states`,
"UploadModal mode toggle updates button states",
async (t) => {
const markup = await uploadMarkupPromise;
const cleanups = [];
@@ -211,8 +203,6 @@ for (const designSystemEnabled of [false, true]) {
stubFetch(new Map([["components/upload-modal.html", markup]])),
);
setFeatureDesignSystemEnabled(designSystemEnabled);
const modal = new UploadModal({
removeTrackingScripts: () => {},
setGlobalModalState: () => {},
@@ -255,11 +245,10 @@ for (const designSystemEnabled of [false, true]) {
);
}
for (const designSystemEnabled of [false, true]) {
const modeLabel = designSystemEnabled ? "design-system" : "legacy";
for (const _ of [0]) {
test(
`[${modeLabel}] EditModal Escape closes and restores trigger focus`,
"EditModal Escape closes and restores trigger focus",
async (t) => {
const markup = await editMarkupPromise;
const cleanups = [];
@@ -274,8 +263,6 @@ for (const designSystemEnabled of [false, true]) {
),
);
setFeatureDesignSystemEnabled(designSystemEnabled);
const modal = new EditModal({
removeTrackingScripts: () => {},
setGlobalModalState: () => {},
@@ -329,7 +316,7 @@ for (const designSystemEnabled of [false, true]) {
);
test(
`[${modeLabel}] EditModal backdrop click closes and restores trigger focus`,
"EditModal backdrop click closes and restores trigger focus",
async (t) => {
const markup = await editMarkupPromise;
const cleanups = [];
@@ -344,8 +331,6 @@ for (const designSystemEnabled of [false, true]) {
),
);
setFeatureDesignSystemEnabled(designSystemEnabled);
const modal = new EditModal({
removeTrackingScripts: () => {},
setGlobalModalState: () => {},
@@ -398,7 +383,7 @@ for (const designSystemEnabled of [false, true]) {
);
test(
`[${modeLabel}] EditModal visibility toggle updates button state`,
"EditModal visibility toggle updates button state",
async (t) => {
const markup = await editMarkupPromise;
const cleanups = [];
@@ -413,8 +398,6 @@ for (const designSystemEnabled of [false, true]) {
),
);
setFeatureDesignSystemEnabled(designSystemEnabled);
const modal = new EditModal({
removeTrackingScripts: () => {},
setGlobalModalState: () => {},
+4 -10
View File
@@ -3,10 +3,7 @@ import { strict as assert } from 'node:assert';
import { readFile } from 'node:fs/promises';
import { JSDOM } from 'jsdom';
import ProfileModalController from '../js/ui/profileModalController.js';
import {
setFeatureDesignSystemEnabled,
resetRuntimeFlags,
} from '../js/constants.js';
import { resetRuntimeFlags } from '../js/constants.js';
import { applyDesignSystemAttributes } from '../js/designSystem.js';
const profileModalHtml = await readFile(
@@ -174,13 +171,11 @@ function createController(options = {}) {
});
}
for (const designSystemEnabled of [false, true]) {
const modeLabel = designSystemEnabled ? 'design-system' : 'legacy';
for (const _ of [0]) {
test(
`[${modeLabel}] Profile modal Escape closes and restores trigger focus`,
'Profile modal Escape closes and restores trigger focus',
async (t) => {
setFeatureDesignSystemEnabled(designSystemEnabled);
const controller = createController();
await controller.load();
applyDesignSystemAttributes(document);
@@ -241,9 +236,8 @@ for (const designSystemEnabled of [false, true]) {
);
test(
`[${modeLabel}] Profile modal navigation buttons toggle active state`,
'Profile modal navigation buttons toggle active state',
async (t) => {
setFeatureDesignSystemEnabled(designSystemEnabled);
const controller = createController();
await controller.load();
applyDesignSystemAttributes(document);
+20 -38
View File
@@ -4,10 +4,7 @@ import { readFile } from "node:fs/promises";
import { JSDOM } from "jsdom";
import { VideoModal } from "../js/ui/components/VideoModal.js";
import {
setFeatureDesignSystemEnabled,
resetRuntimeFlags,
} from "../js/constants.js";
import { resetRuntimeFlags } from "../js/constants.js";
import { applyDesignSystemAttributes } from "../js/designSystem.js";
const modalMarkupPromise = readFile(
@@ -15,7 +12,7 @@ const modalMarkupPromise = readFile(
"utf8"
);
async function setupModal({ designSystemEnabled = false, lazyLoad = false } = {}) {
async function setupModal({ lazyLoad = false } = {}) {
const markup = await modalMarkupPromise;
const modalMarkup = lazyLoad ? "" : markup;
const dom = new JSDOM(
@@ -40,7 +37,6 @@ async function setupModal({ designSystemEnabled = false, lazyLoad = false } = {}
globalThis.KeyboardEvent = window.KeyboardEvent;
globalThis.MouseEvent = window.MouseEvent;
setFeatureDesignSystemEnabled(designSystemEnabled);
applyDesignSystemAttributes(document);
let restoreFetch = null;
@@ -176,14 +172,13 @@ test("Escape key closes the modal and returns focus to the trigger", async (t) =
assert.strictEqual(document.activeElement, trigger);
});
for (const designSystemEnabled of [false, true]) {
const modeLabel = designSystemEnabled ? "design-system" : "legacy";
for (const _ of [0]) {
test(
`[${modeLabel}] video modal sticky navigation responds to scroll direction`,
"video modal sticky navigation responds to scroll direction",
async (t) => {
const { window, modal, playerModal, trigger, cleanup } =
await setupModal({ designSystemEnabled });
await setupModal();
t.after(cleanup);
modal.open(null, { triggerElement: trigger });
@@ -226,10 +221,10 @@ for (const designSystemEnabled of [false, true]) {
);
test(
`[${modeLabel}] video modal video shell is not sticky at mobile breakpoints`,
"video modal video shell is not sticky at mobile breakpoints",
async (t) => {
const { window, modal, playerModal, trigger, cleanup } =
await setupModal({ designSystemEnabled });
await setupModal();
t.after(cleanup);
const originalInnerWidth = window.innerWidth;
@@ -261,11 +256,9 @@ for (const designSystemEnabled of [false, true]) {
);
test(
`[${modeLabel}] video modal toggles document scroll locking on open/close`,
"video modal toggles document scroll locking on open/close",
async (t) => {
const { document, modal, trigger, cleanup } = await setupModal({
designSystemEnabled,
});
const { document, modal, trigger, cleanup } = await setupModal();
t.after(cleanup);
modal.open(null, { triggerElement: trigger });
@@ -290,16 +283,10 @@ for (const designSystemEnabled of [false, true]) {
);
test(
`[${modeLabel}] video modal zap dialog updates aria state while toggling`,
"video modal zap dialog updates aria state while toggling",
async (t) => {
const {
window,
document,
modal,
playerModal,
trigger,
cleanup,
} = await setupModal({ designSystemEnabled });
const { window, document, modal, playerModal, trigger, cleanup } =
await setupModal();
t.after(cleanup);
modal.open(null, { triggerElement: trigger });
@@ -344,18 +331,13 @@ for (const designSystemEnabled of [false, true]) {
}
);
if (designSystemEnabled) {
test(
`[${modeLabel}] video modal inherits design system mode when loaded dynamically`,
async (t) => {
const { playerModal, cleanup } = await setupModal({
designSystemEnabled,
lazyLoad: true,
});
t.after(cleanup);
test(
"video modal inherits design system mode when loaded dynamically",
async (t) => {
const { playerModal, cleanup } = await setupModal({ lazyLoad: true });
t.after(cleanup);
assert.strictEqual(playerModal.getAttribute("data-ds"), "new");
}
);
}
assert.strictEqual(playerModal.getAttribute("data-ds"), "new");
}
);
}
+1 -4
View File
@@ -7,10 +7,7 @@ const __dirname = dirname(__filename);
export type KitchenSinkTheme = "default" | "light" | "contrast";
export type BaselineKey =
| KitchenSinkTheme
| "video-modal-mobile-legacy"
| "video-modal-mobile-design-system";
export type BaselineKey = KitchenSinkTheme | "video-modal-mobile";
type BaselineMap = Record<string, string>;
+4 -5
View File
@@ -1,7 +1,6 @@
{
"contrast": "iVBORw0KGgoAAAANSUhEUgAABQAAAAXgCAIAAACBwnMiAAAQAElEQVR4nOzdCUATV8IH8JdzEiAJgQAKBuQU5bCoaEWsij1E22p1W1u3d7u159dje3d77m6P3W7vy25P29pqW6ttrW6tV0U8AFEERW6IoEA4kgDJJJnkm0k4wingUUj+v2VtmMydPGb+8968ESqCJhEAAAAAAAAAdyckAAAAAAAAAB4AARgAAAAAAAA8AgIwAAAAAAAAeAQEYAAAAAAAAPAICMAAAAAAAADgERCAAQAAAAAAwCMgAAMAAAAAAIBHQAAGAAAAAAAAj4AADAAAAAAAAB4BARgAAAAAAAA8AgIwAAAAAAAAeAQEYAAAAAA4PZH/FJH/BXyJSkD58SX+7I+A8id/HIZusJm4H4ZutJm0loZc9ocAAAyIpwiaRAAAAAAAeuEJZaKAaVRgChV0IV8sJyObzayna/fStZmW+gN2po0AAPSCAAwAAAAAvQi8vaKv9xq/lC+UkNHGZjW1lX/fVrKGMC0EAMAFAjAAAAAAdLHzJWzu9YpaIRDLyGjGmPVsBmaTMM9uJgAADgjAAAAAAMCx2+0CWYTvtH8IfcYRd2FtOdGc/TfGUMbj8QgAeDyBxCeAAAAAAIAHY6Mv+69kXLpv8j8FEj/iRvhiuWTcAptJa9UXs78iBgN4OARgAAAAAI/GpV+eSD75UZ/YW3l8N3xECLtRkrGzBdIgum4/sTPIwACeDAEYAAAAwEM5K375kiDlhf+ixqQQtyZSRFMByXRdlt3K9YyFGAzgmRCAAQAAADyRM/0SPqWc+R+RbyzxAAJpgEiVZNL8j60HJsjAAB4JARgAAADA4zjTr53wFFP+RgVMIx5DIPEXeI+jT+50/ooMDOBpEIABAAAAPEt73S8hPrErvccvJh5GJA9n/7U0HHL+igwM4FEQgAEAAP4AnQkE4GwZZJDr/O5RY+fKE+4nHkmsSrK2VDKGcuevyMAAnsMNO/oDAAAY4dgEMn/e7IXp86Miw/38lATgDDQ2NhWXlP/8y9adu/acNsh1pl+e0Fs2+VFyzojHSD5+0meGl3XVv3X/OT4SL/fIEh821+23W1uJY7cgAwN4CARgAACA84o91f7rA3cSHln37Q+lpeVNzc0E4AwofX2josLnzE5NTJj41jsfDTLIeUVdLxD5kCERCq69V/FCPL/jd3t9lWXTb61vZzKG3iNbbGUaq0rIVLeN0MYO7OazO6G1cBUBAE/CUwRNIgAAAHBesOn3oQfu1DU3f7Z6DQE4q2675Xqpl/ebb/+3vwzcVf1L+anS1vKFFBmSzgBssZ3Q2uUqgVzEDmW+fqf52UOjskm/zUprty23mxudv6ISGMAToAYYAADgPHG0fE5lz7GRfuFc+PjTLx968N45F6Xs+j2zd5Zzve3cJ+aWIadfF/r81htW0dVeopefVCxVCWbHC/1PCd7gGjwzvx9gQiaIxlnoRz6y/vn/2ptAv62jPn7WZ4bI8W68OFJkO7Sn5dUy0cPLJBco7Mf2tD32janQSGLnyN67lhoncixCa91/oO0/P5rLrESVLNu4kgrQWTaV8abHC3nVZma8OEhHP/Ci4ZcGIpvgve4RaaSOfuxFww8NQ9oOwu4E7+g/txS83bmLkIEB3B6fAIDnoCbctyWrVpPn/Ml4dpr89NPIUl7c3DlJ5cZb44Z/ynQaAVe+cqRjQbX57y2PFJ92EmrSrb8Ud0yi2fyvOf7ELVCRV6/P79yu7R9cek626/ws5Y91NrdxOMWnDwvTL87I2EsAzg3223X5wosHHofvNVYaejk5YzKVMMSLe0FbOocJLpouIqesh07Z6T6mYN8Vc/lWxL9grvzLW6UXcJPzJ87yejhJwP7Fp7z4VJt1fy69Nd9Kq4SXLPR5cpag60igEC2K51WXWUpPWbZpHL9OYN/lTYwTRRJSf5w+oCPDIA29UuAVTADAY6AGGACGixq/4LZr0sY5T04M+d9+uTp3iNfe/wDiqKvf+OW1VEX7r9ofbrv6zl9dVpsNOeu+/NuUjpRf8mX64n8d1Dtey6f9feMnd0S1v2M6+MbCaz4poM9ocdS4WX979407OhdH6PyPHr355R11/c8xIOnqO66e4JwhfWLP5x/vKDnNOrgd+YQld996x2WJ6gBVoILbdSaTXl/fUHeiurgke8eP2zfvq9CTkSsqMry0tJwAnBslJaXR0ZG9h7tW/4p8J/L4AnIG5EmyHR/I2n9ps3yTZTWQ9hke26q/fq3F4OgE69Zea3Hoe91te3hPcfXGbDVyyzWrLJNXKl6J50dMEMgzmWM79Qs22x23E/MuvsX3vVmCiRMEAXuYjj9yzPpVumcO2cyExKaLl6lFM6aLxuVbZ09gF23bfcBSbSXDwFYCC31jmbaa9lVEJTCAu0MABoDhkoekX3/9tWrnL/Se0i1rcxs8LYudif7Sr4Ym/deyiwOnLLjjhmSJ8zcNtf3bHSX1xHNQ4+b9/aN/3dS9HYJEIpeo5YHq8PiZqVfdsPjDq69/ep+BjFR+fkr0egU7t/08d/5ZqIPtrbGp2f90/YpTYy4iZ4i7B9hmaLOVlZnX76J3n7KLxzjfsB7Kt/Zf/JhDZYzBItRzNcb2Y/mWExZbhKPalnI0e5ZHSJ5aSE1WC8d5dayqgs+W9vYji876u4ZLv6yyXPpQumhGBDV7Am9GKI9o6d/Khn8TMrtD6JrtBAA8AwIwAAyM1uz89kMS7Awc9NG8OnKu0CU7vvnC0F5Zqs8rrjcT99VH+v2iPf1yv9QXrv1yXUl7E9uazFJ33hVDIJ9wx2s90+/AsCcBSI+HTvNE4sAZ5My03wPcV42rfsBqWMdfuI6VsXR/Ty667wbvRSpyIrftmQOMfJb3w/Hd79Sz2M0dk5i15vXHbTOShDddzA8QkRP59KEzaPghDpzO7hZib587KoEB3BsCMAAMzKz59ZOnfyXngf7oln8+uYV4gL7T7/Pt6ZejP7L25SNrCXQTcOH1N87sSr86TWF+aU1dnYEo/AMDVIHjwqMDe2Vj7EmA7sSqKQKRNxmJeI4CbDe02akI8VUTBuynxmrbvcd8IkkyLlLA/rI716olwycQ+bC7xVy/nwCAB0AABvBoVEDCjXffdu3cxLgoFdFVF+Rmb/7i489/db2FUpby4rofbghx/uK88bUk4MpVW/6Rrug2p1nPfVv1XPsvpr2vXP157LsfLA51/q7LeGTxA6tdK98Cpv1r3Sc3td9PS+957vrrPj4uv/KV7e+mB3ZM8n+LH1jrMgkbGm+8++qrZjpWta684GjWD+9+snYk3+vZj9OnX0fXTV9vfHpW+x523jlsnvL4x5vvie02L/Xibw4u7vil+vPrr390V8cNxpQsbs6V116WHBcXHj0uPFBBTDqt5kRh/t49G778cUtp300U5ZHzbrr76iUzE6PUcolJX3V0z4cv/eu/+3rf2i1WX7jgxqvTprbPnNZpyvNLj+f8uHH1j9muG8LdU73xy7911NkWf3TrwtcNaXffeuPcxPi4EAWh60ryNr/3r398e3wQn6QsemZiaMcvpoKPr73mzYP67muVlLbkygl1enrAPdlwtldMrL700a/fvSa6vWE6qdv5xk33fHJwFH45wS11q/4lRKQcqc+/1Js/20xPv4GayNb9njT/XmaLHDADa8vo3Scl140l5KRlU9mZPoRJKI9yDcCoBAZwYwjAAJ6LUqf9fd3VV0V1JDFFyNS57M+8eS89cPN72Wd49t54aMsOzeKbnHcIKxLTZwavLa3ozCUBkxbM6+hNiujyNuwsH/jmYSryylXr/tERjgkJDJ/K/sydNeuj7HPWKfW5ETjrb/c87Zp+i3ul3zMnn7Tgb6/97aa4br0USxSqaEVqdFxyaH32jveO916gYuZdn712zazO6xoSeeiU9H98pCI3PPDfXJfATI1f8uy/3rwhVuIySKGOncX+zF18x92bn37oH6tz+w7YVMCsv6+7/tquNsxUYFTyTa+9H0huXfltxWn3AUV1dQdL62v0PScwa3K3vJ07nEYEZ7JiARfeteq1rvSr23tm6ZeacO/az/46zqBhN4+iyInDX7z++up9NX2vAxW++NnH771Qpd/17v0vbz9x+m+RbO6Lnz2sf37Fy4WBly6fSW9bt6vXnANmPf+f5SUvP7yOTv907bNT6Oo6mkgoUnd0+zsvv7tlEG3IqUk3rPlP4uq/PLXxRPvI1Lj0V/6TuuPJ5zeiCfoIwKf8yLBZmW/eaPymr3fMp0w3/J+p/yGmG+7qfG198Wntix2//PZpY8yn7a+1uwxpu/r665FlmJXVa7je+ttx5rqxgmO59DEjOUN8yRnsFgAYVfAYJADPFXrZ9V3pt4t81oNPP3LmzxPS5m34X2dXt/KplyWruxYli78subMqT5e7MfPEgKfF8oQ7Xnq0K/12CUm/fXG8hIweqvRn/9Et/a57+rqznX6pcQv+/u6/eqTfwaxb2u0u6beTIvmRhxZ0fU0o/3mP90i/3Uii0v/97qMLxvX9CKvQxbdd28cdvKr0B++aN+60T72i6040dJ5BK2Y++tlHf7txzvjhPYvobK2YPOnPb71729SO/cam35vPvO6XNux9feUlaVdclHbdYztV9/731b9eKOt76ZPSbkzS/mf5smXPDyb9upJFXbZk+UxVr20Wx126fGr95h3OpKovfOfeZRelXTE9/eG1JP2Ndx6fG0CGgT5xYMPR8Buvjj0rH5aHi5k4tPrbHtW/5AwD8Ighi6D+er3PfUkC0mZZn2U9817vBNIxPYb03nUA4B4QgAE8m67wh3df+b8n3vh8Z3XXQEn48nsWRPVftUrX7/n3Pfff9NDH2116xCpe9/eVt91/k+Pn5pfYUGfI/9/2/I53FUnzUjqDRABbIRze8Y4289vsAROgWD33+jtmupw51+V98+7f2XX+Zu+Z3PP1x5C4BEc2/d785JZBp19Dybf/Line truncated
"default": "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 truncated
"light": "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 truncated
"video-modal-mobile-legacy": "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 truncated
"video-modal-mobile-design-system": "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 truncated
"contrast": "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 truncated
"default": "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 truncated
"light": "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 truncated
"video-modal-mobile": "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 truncated
}
+10 -27
View File
@@ -15,18 +15,7 @@ const THEMES: { name: KitchenSinkTheme; value?: string }[] = [
{ name: "contrast", value: "contrast" }
];
const VIDEO_MODAL_VARIANTS = [
{
label: "legacy",
baselineKey: "video-modal-mobile-legacy" as BaselineKey,
designSystemEnabled: false
},
{
label: "design-system",
baselineKey: "video-modal-mobile-design-system" as BaselineKey,
designSystemEnabled: true
}
] as const;
const VIDEO_MODAL_BASELINE_KEY = "video-modal-mobile" as BaselineKey;
const MAX_DIFF_RATIO = 0.001;
const UPDATE_BASELINES = process.env.UPDATE_VISUAL_BASELINES === "1";
@@ -135,11 +124,7 @@ test.describe("video modal mobile regression", () => {
await page.emulateMedia({ reducedMotion: "reduce" });
});
for (const variant of VIDEO_MODAL_VARIANTS) {
test(`renders ${variant.label} video modal without regressions`, async (
{ page },
testInfo
) => {
test("renders video modal without regressions", async ({ page }, testInfo) => {
await page.goto("/components/video-modal.html", {
waitUntil: "networkidle"
});
@@ -149,7 +134,7 @@ test.describe("video modal mobile regression", () => {
"*, *::before, *::after { transition-duration: 0s !important; animation-duration: 0s !important; animation-delay: 0s !important; caret-color: transparent !important; }"
});
await page.evaluate(({ designSystemEnabled }) => {
await page.evaluate(() => {
const modal = document.getElementById("playerModal");
if (!modal) {
throw new Error("Missing player modal root element");
@@ -158,19 +143,18 @@ test.describe("video modal mobile regression", () => {
modal.classList.remove("hidden");
modal.removeAttribute("hidden");
const mode = designSystemEnabled ? "new" : "legacy";
modal.setAttribute("data-ds", mode);
modal.setAttribute("data-ds", "new");
const html = document.documentElement;
if (html) {
html.setAttribute("data-ds", mode);
html.setAttribute("data-ds", "new");
}
if (document.body) {
document.body.setAttribute("data-ds", mode);
document.body.setAttribute("data-ds", "new");
}
window.scrollTo(0, 0);
}, variant);
});
await page.waitForTimeout(100);
@@ -181,15 +165,15 @@ test.describe("video modal mobile regression", () => {
});
if (UPDATE_BASELINES) {
setBaseline(variant.baselineKey, screenshotBuffer);
await testInfo.attach(`${variant.baselineKey}-actual.png`, {
setBaseline(VIDEO_MODAL_BASELINE_KEY, screenshotBuffer);
await testInfo.attach(`${VIDEO_MODAL_BASELINE_KEY}-actual.png`, {
body: screenshotBuffer,
contentType: "image/png"
});
return;
}
const baselineBuffer = getBaseline(variant.baselineKey);
const baselineBuffer = getBaseline(VIDEO_MODAL_BASELINE_KEY);
const actual = PNG.sync.read(screenshotBuffer);
const expected = PNG.sync.read(baselineBuffer);
@@ -225,5 +209,4 @@ test.describe("video modal mobile regression", () => {
expect(diffRatio).toBeLessThanOrEqual(MAX_DIFF_RATIO);
});
}
});
+40
View File
@@ -1,4 +1,5 @@
import { expect, test } from "@playwright/test";
import type { Page } from "@playwright/test";
declare global {
interface Window {
@@ -9,12 +10,51 @@ declare global {
}
test.describe("overlay layering tokens", () => {
async function dismissDisclaimerModal(page: Page) {
const modal = page.locator("#disclaimerModal");
if ((await modal.count()) === 0) {
return;
}
await page.evaluate(() => {
try {
window.localStorage?.setItem("hasSeenDisclaimer", "true");
} catch (error) {
console.warn("Failed to persist disclaimer state", error);
}
document
.querySelectorAll<HTMLElement>("#disclaimerModal")
.forEach((node) => {
node.classList.add("hidden");
node.setAttribute("data-open", "false");
});
document.documentElement?.classList.remove("modal-open");
document.body?.classList.remove("modal-open");
});
await page.waitForFunction(() =>
Array.from(
document.querySelectorAll("#disclaimerModal")
).every((modalElement) => modalElement.classList.contains("hidden"))
);
}
test("mobile nav overlay uses nav layer", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 844 });
await page.goto("/index.html", { waitUntil: "networkidle" });
await dismissDisclaimerModal(page);
await page.waitForSelector("#mobileMenuBtn");
await page.click("#mobileMenuBtn");
await page.waitForFunction(() => {
const overlay = document.getElementById("sidebarOverlay");
if (!overlay) {
return false;
}
const styles = window.getComputedStyle(overlay);
return styles.opacity === "1" && styles.pointerEvents === "auto";
});
await page.waitForFunction(() =>
document.body.classList.contains("sidebar-open")
);