@brandlab-digital/conformance 3.14.0 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -3
- package/dist/current-release.js +5 -5
- package/dist/current-release.js.map +1 -1
- package/dist/engineering.d.ts.map +1 -1
- package/dist/engineering.js +18 -2
- package/dist/engineering.js.map +1 -1
- package/dist/estate-snapshot.d.ts +54 -0
- package/dist/estate-snapshot.d.ts.map +1 -0
- package/dist/estate-snapshot.js +164 -0
- package/dist/estate-snapshot.js.map +1 -0
- package/dist/estate.d.ts +10 -0
- package/dist/estate.d.ts.map +1 -1
- package/dist/estate.js +36 -16
- package/dist/estate.js.map +1 -1
- package/dist/media-snapshot.d.ts +53 -0
- package/dist/media-snapshot.d.ts.map +1 -0
- package/dist/media-snapshot.js +66 -0
- package/dist/media-snapshot.js.map +1 -0
- package/dist/site-system/checks.d.ts +2 -2
- package/dist/site-system/checks.js +2 -2
- package/dist/site-system/checks.js.map +1 -1
- package/dist/site-system/config.d.ts +13 -0
- package/dist/site-system/config.d.ts.map +1 -1
- package/dist/site-system/config.js +30 -1
- package/dist/site-system/config.js.map +1 -1
- package/dist/site-system/index.d.ts +1 -1
- package/dist/site-system/index.d.ts.map +1 -1
- package/dist/site-system/index.js +1 -1
- package/dist/site-system/index.js.map +1 -1
- package/dist/site-system/journeys/conversion.d.ts.map +1 -1
- package/dist/site-system/journeys/conversion.js +15 -2
- package/dist/site-system/journeys/conversion.js.map +1 -1
- package/dist/site-system/journeys/menu.d.ts.map +1 -1
- package/dist/site-system/journeys/menu.js +24 -1
- package/dist/site-system/journeys/menu.js.map +1 -1
- package/dist/site-system/journeys/page-helpers.d.ts.map +1 -1
- package/dist/site-system/journeys/page-helpers.js +1 -1
- package/dist/site-system/journeys/page-helpers.js.map +1 -1
- package/dist/site-system/journeys/plan.d.ts +13 -3
- package/dist/site-system/journeys/plan.d.ts.map +1 -1
- package/dist/site-system/journeys/plan.js +12 -2
- package/dist/site-system/journeys/plan.js.map +1 -1
- package/dist/site-system/journeys/shell.d.ts +1 -1
- package/dist/site-system/journeys/shell.js +2 -2
- package/dist/site-system/journeys/shell.js.map +1 -1
- package/dist/site-system/report.d.ts.map +1 -1
- package/dist/site-system/report.js +24 -4
- package/dist/site-system/report.js.map +1 -1
- package/dist/site-system/rules/form/c7-thank-you.d.ts +7 -1
- package/dist/site-system/rules/form/c7-thank-you.d.ts.map +1 -1
- package/dist/site-system/rules/form/c7-thank-you.js +26 -3
- package/dist/site-system/rules/form/c7-thank-you.js.map +1 -1
- package/dist/site-system/rules/form/index.d.ts.map +1 -1
- package/dist/site-system/rules/form/index.js +11 -1
- package/dist/site-system/rules/form/index.js.map +1 -1
- package/dist/site-system/rules/full/common.d.ts +2 -0
- package/dist/site-system/rules/full/common.d.ts.map +1 -1
- package/dist/site-system/rules/full/common.js.map +1 -1
- package/dist/site-system/rules/full/estate.d.ts +10 -2
- package/dist/site-system/rules/full/estate.d.ts.map +1 -1
- package/dist/site-system/rules/full/estate.js +35 -5
- package/dist/site-system/rules/full/estate.js.map +1 -1
- package/dist/site-system/rules/full/geography.d.ts +7 -0
- package/dist/site-system/rules/full/geography.d.ts.map +1 -1
- package/dist/site-system/rules/full/geography.js +9 -0
- package/dist/site-system/rules/full/geography.js.map +1 -1
- package/dist/site-system/rules/full/index.d.ts +2 -1
- package/dist/site-system/rules/full/index.d.ts.map +1 -1
- package/dist/site-system/rules/full/index.js +5 -1
- package/dist/site-system/rules/full/index.js.map +1 -1
- package/dist/site-system/rules/full/l10-location-copy.d.ts +1 -1
- package/dist/site-system/rules/full/l10-location-copy.d.ts.map +1 -1
- package/dist/site-system/rules/full/l10-location-copy.js +5 -2
- package/dist/site-system/rules/full/l10-location-copy.js.map +1 -1
- package/dist/site-system/rules/full/l3-neighbours.d.ts +3 -2
- package/dist/site-system/rules/full/l3-neighbours.d.ts.map +1 -1
- package/dist/site-system/rules/full/l3-neighbours.js +4 -1
- package/dist/site-system/rules/full/l3-neighbours.js.map +1 -1
- package/dist/site-system/rules/full/l4-local-copy.d.ts +2 -1
- package/dist/site-system/rules/full/l4-local-copy.d.ts.map +1 -1
- package/dist/site-system/rules/full/l4-local-copy.js +8 -3
- package/dist/site-system/rules/full/l4-local-copy.js.map +1 -1
- package/dist/site-system/rules/full/l9-data-contract.js +2 -2
- package/dist/site-system/rules/full/l9-data-contract.js.map +1 -1
- package/dist/site-system/rules/full/links.d.ts +3 -1
- package/dist/site-system/rules/full/links.d.ts.map +1 -1
- package/dist/site-system/rules/full/links.js +15 -5
- package/dist/site-system/rules/full/links.js.map +1 -1
- package/dist/site-system/rules/full/route-kinds.d.ts +15 -0
- package/dist/site-system/rules/full/route-kinds.d.ts.map +1 -0
- package/dist/site-system/rules/full/route-kinds.js +52 -0
- package/dist/site-system/rules/full/route-kinds.js.map +1 -0
- package/dist/site-system/rules/full/strategy.d.ts +2 -0
- package/dist/site-system/rules/full/strategy.d.ts.map +1 -1
- package/dist/site-system/rules/full/strategy.js +86 -14
- package/dist/site-system/rules/full/strategy.js.map +1 -1
- package/dist/site-system/rules/sections/k2-skin-coverage.d.ts +2 -2
- package/dist/site-system/rules/sections/k2-skin-coverage.d.ts.map +1 -1
- package/dist/site-system/rules/sections/k2-skin-coverage.js +9 -2
- package/dist/site-system/rules/sections/k2-skin-coverage.js.map +1 -1
- package/dist/site-system/rules/sections/t6-media-entries.d.ts.map +1 -1
- package/dist/site-system/rules/sections/t6-media-entries.js +69 -5
- package/dist/site-system/rules/sections/t6-media-entries.js.map +1 -1
- package/dist/site-system-e2e.d.ts +1 -1
- package/dist/site-system-e2e.d.ts.map +1 -1
- package/dist/site-system-e2e.js +17 -4
- package/dist/site-system-e2e.js.map +1 -1
- package/package.json +10 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-helpers.js","sourceRoot":"","sources":["../../../src/site-system/journeys/page-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Functions the site-system journeys run inside the page under test. Each one is self-contained: it uses DOM globals\n * and the other helpers in this file only, because `pageHelpersSource()` injects their source into every document\n * (as `window.__brandlabSiteSystem`, through Playwright's init script, which a Content Security Policy does not\n * block). The pure parts (colour, contrast, placement) are unit-tested in Node.\n */\n\n/**\n * The placements `phone_link_click` accepts: site-next's PHONE_CALL_PLACEMENTS (conformance cannot depend on\n * site-next; a test reads the site-next source and compares). Injected into the page with the helpers.\n */\nexport const SITE_SYSTEM_PHONE_PLACEMENTS: readonly string[] = Object.freeze(['header', 'footer', 'hero', 'cta', 'fab', 'contact', 'location', 'page']);\n\nexport type Rgba = [number, number, number, number];\n\n/** What `watchDisclosure` has seen, in `performance.now()` milliseconds. */\nexport interface DisclosureWatch {\n enter: number | null;\n leave: number | null;\n opened: number | null;\n closed: number | null;\n open: boolean;\n}\n\n/**\n * Whether an element is rendered: connected, with a box, not `visibility: hidden`, not fully transparent and not\n * inside a closed `<details>` (outside its summary). Chromium gives the content of a closed `<details>` a box, so\n * the box alone is not enough; `checkVisibility()` settles it where the browser has it.\n */\nexport function isRendered(element: Element | null | undefined): boolean {\n if (!element || !element.isConnected) return false;\n for (let details = element.closest('details:not([open])'); details; details = details.parentElement?.closest('details:not([open])') ?? null) {\n const summary = Array.from(details.children).find((child) => child.tagName === 'SUMMARY');\n if (!summary || !summary.contains(element)) return false;\n }\n if (typeof element.checkVisibility === 'function' && !element.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true })) return false;\n const rect = element.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) return false;\n if (getComputedStyle(element).visibility !== 'visible') return false;\n for (let node: Element | null = element; node; node = node.parentElement) {\n if (getComputedStyle(node).opacity === '0') return false;\n }\n return true;\n}\n\n/** A short, readable name for an element in a failure message. */\nexport function describeElement(element: Element): string {\n const tag = element.tagName.toLowerCase();\n const label = element.getAttribute('aria-label') ?? (element as HTMLElement).innerText ?? element.textContent ?? '';\n const text = label.replace(/\\s+/g, ' ').trim().slice(0, 40);\n const href = element.getAttribute('href');\n return `${tag}${text ? ` \"${text}\"` : ''}${href ? ` (${href})` : ''}`;\n}\n\n/** The accessible name, approximately: aria-label, aria-labelledby, the rendered text, then the title. */\nexport function accessibleName(element: Element): string {\n const label = element.getAttribute('aria-label');\n if (label && label.trim()) return label.trim();\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const text = labelledBy.split(/\\s+/).map((id) => document.getElementById(id)?.textContent ?? '').join(' ').trim();\n if (text) return text.replace(/\\s+/g, ' ');\n }\n const text = ((element as HTMLElement).innerText ?? element.textContent ?? '').replace(/\\s+/g, ' ').trim();\n return text || (element.getAttribute('title') ?? '').trim();\n}\n\n/**\n * Where a telephone link reports its tap, exactly as site-next's shared listener resolves it: its own valid\n * `data-phone-location`, then a `<header>` or `<footer>` ancestor, then the nearest ancestor with a valid value,\n * otherwise `page`. `invalid` is the nearest declared value when it is not an allowed placement (the listener then\n * reports the link somewhere else, silently).\n */\nexport function phonePlacement(link: Element): { placement: string; invalid: string | null } {\n const valid = (node: Element): string | undefined => {\n const value = node.getAttribute('data-phone-location')?.trim().toLowerCase();\n return value && SITE_SYSTEM_PHONE_PLACEMENTS.includes(value) ? value : undefined;\n };\n const nearest = link.closest('[data-phone-location]');\n const invalid = nearest && !valid(nearest) ? nearest.getAttribute('data-phone-location') : null;\n const own = valid(link);\n if (own) return { placement: own, invalid };\n if (link.closest('header')) return { placement: 'header', invalid };\n if (link.closest('footer')) return { placement: 'footer', invalid };\n for (let node = link.parentElement?.closest('[data-phone-location]') ?? null; node; node = node.parentElement?.closest('[data-phone-location]') ?? null) {\n const value = valid(node);\n if (value) return { placement: value, invalid };\n }\n return { placement: 'page', invalid };\n}\n\n/** Parse a computed colour. `rgb()`/`rgba()` directly; any other syntax (oklch, lab, color()) through a canvas pixel. */\nexport function parseColour(value: string): Rgba | null {\n const text = value.trim().toLowerCase();\n if (text === 'transparent') return [0, 0, 0, 0];\n const match = /^rgba?\\(([^)]+)\\)$/.exec(text);\n if (match) {\n const parts = match[1]!.split(/[\\s,/]+/).filter(Boolean);\n if (parts.length < 3) return null;\n const channel = (part: string) => (part.endsWith('%') ? (Number.parseFloat(part) / 100) * 255 : Number.parseFloat(part));\n const alphaPart = parts[3];\n const alpha = alphaPart === undefined ? 1 : alphaPart.endsWith('%') ? Number.parseFloat(alphaPart) / 100 : Number.parseFloat(alphaPart);\n const rgba: Rgba = [channel(parts[0]!), channel(parts[1]!), channel(parts[2]!), alpha];\n return rgba.every((part) => Number.isFinite(part)) ? rgba : null;\n }\n if (typeof document === 'undefined') return null;\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n const context = canvas.getContext('2d', { willReadFrequently: true });\n if (!context) return null;\n context.clearRect(0, 0, 1, 1);\n context.fillStyle = value;\n context.fillRect(0, 0, 1, 1);\n const [red = 0, green = 0, blue = 0, alpha = 0] = Array.from(context.getImageData(0, 0, 1, 1).data);\n return [red, green, blue, alpha / 255];\n}\n\n/** `top` painted over an opaque `bottom`. */\nexport function compositeColour(top: Rgba, bottom: Rgba): Rgba {\n const alpha = top[3];\n return [\n top[0] * alpha + bottom[0] * (1 - alpha),\n top[1] * alpha + bottom[1] * (1 - alpha),\n top[2] * alpha + bottom[2] * (1 - alpha),\n 1,\n ];\n}\n\n/** The WCAG contrast ratio of two opaque colours. */\nexport function contrastRatio(first: Rgba, second: Rgba): number {\n const luminance = (colour: Rgba) => {\n const [red, green, blue] = colour.slice(0, 3).map((channel) => {\n const value = channel / 255;\n return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;\n }) as [number, number, number];\n return 0.2126 * red + 0.7152 * green + 0.0722 * blue;\n };\n const [light, dark] = [luminance(first), luminance(second)].sort((left, right) => right - left) as [number, number];\n return (light + 0.05) / (dark + 0.05);\n}\n\n/**\n * The opaque colour behind an element, from its own and its ancestors' background colours over a white canvas.\n * `null` when a background image (a photo or gradient) is in the way: the contrast cannot be computed there.\n */\nexport function backgroundBehind(element: Element): Rgba | null {\n const layers: Rgba[] = [];\n for (let node: Element | null = element; node; node = node.parentElement) {\n const style = getComputedStyle(node);\n if (style.backgroundImage && style.backgroundImage !== 'none') return null;\n const colour = parseColour(style.backgroundColor);\n if (colour && colour[3] > 0) {\n layers.push(colour);\n if (colour[3] >= 1) break;\n }\n }\n return layers.reverse().reduce<Rgba>((bottom, top) => compositeColour(top, bottom), [255, 255, 255, 1]);\n}\n\n/**\n * Non-text contrast (WCAG 1.4.11) of icon-only controls inside `root`: a link or button with no visible text whose\n * icon is an SVG must reach 3:1 against what is behind it. Returns one line per failure; controls over a photo are\n * counted in `unmeasured`.\n */\nexport function iconContrastProblems(root: Element): { problems: string[]; checked: number; unmeasured: number } {\n const problems: string[] = [];\n let checked = 0;\n let unmeasured = 0;\n const paintOf = (svg: SVGElement): Rgba | null => {\n for (const shape of Array.from(svg.querySelectorAll('path, circle, rect, ellipse, line, polyline, polygon, text, use'))) {\n if (!isRendered(shape)) continue;\n const style = getComputedStyle(shape);\n for (const [paint, opacity] of [[style.fill, style.fillOpacity], [style.stroke, style.strokeOpacity]] as const) {\n if (!paint || paint === 'none' || paint.startsWith('url(')) continue;\n const colour = parseColour(paint);\n const alpha = colour ? colour[3] * Number(opacity || 1) * Number(style.opacity || 1) : 0;\n if (colour && alpha > 0) return [colour[0], colour[1], colour[2], alpha];\n }\n }\n return null;\n };\n for (const control of Array.from(root.querySelectorAll('a[href], button'))) {\n if (!isRendered(control)) continue;\n if (((control as HTMLElement).innerText ?? '').trim()) continue;\n const svg = control.querySelector('svg');\n if (!svg || !isRendered(svg)) continue;\n const paint = paintOf(svg);\n if (!paint) continue;\n const background = backgroundBehind(svg);\n if (!background) {\n unmeasured += 1;\n continue;\n }\n checked += 1;\n const ratio = contrastRatio(compositeColour(paint, background), background);\n if (ratio < 3) problems.push(`${describeElement(control)}: its icon is ${ratio.toFixed(2)}:1 against its background (needs 3:1)`);\n }\n return { problems, checked, unmeasured };\n}\n\n/**\n * The phone call bar: the shared `MobileCallBar`, or any fixed or sticky element along the bottom of the screen that\n * holds a visible telephone link (outside the header and dialogs). `null` when none is on screen.\n */\nexport function findCallBar(): Element | null {\n const tagged = Array.from(document.querySelectorAll('[data-bl=\"call-bar\"], [data-bl=\"callbar\"], [data-bl=\"mobile-call-bar\"]')).find(isRendered);\n if (tagged) return tagged;\n const height = window.innerHeight;\n for (const element of Array.from(document.body.querySelectorAll('*'))) {\n const position = getComputedStyle(element).position;\n if (position !== 'fixed' && position !== 'sticky') continue;\n if (element.closest('header, dialog, [role=\"dialog\"]')) continue;\n const rect = element.getBoundingClientRect();\n if (rect.height <= 0 || rect.bottom < height - 4 || rect.top < height / 2) continue;\n if (!isRendered(element)) continue;\n if (Array.from(element.querySelectorAll('a[href^=\"tel:\"]')).some(isRendered)) return element;\n }\n return null;\n}\n\n/** Visible quote actions in `root`: links or buttons named like the quote action, or the shared quote hooks. */\nexport function quoteActions(root: Element, name: { source: string; flags: string }): Element[] {\n const pattern = new RegExp(name.source, name.flags);\n return Array.from(root.querySelectorAll('a[href], button')).filter((element) => {\n if (!isRendered(element) || element.getAttribute('href')?.startsWith('tel:')) return false;\n if (element.matches('[data-bl=\"quote-button\"], [data-bl-cta^=\"quote\"], [data-lead-cta^=\"quote\"]')) return true;\n return pattern.test(accessibleName(element));\n });\n}\n\n/** The order of the first visible phone link and quote action in `root`. */\nexport function actionOrder(root: Element, name: { source: string; flags: string }): 'phone-first' | 'quote-first' | 'incomplete' {\n const phone = Array.from(root.querySelectorAll('a[href^=\"tel:\"]')).find(isRendered);\n const quote = quoteActions(root, name)[0];\n if (!phone || !quote) return 'incomplete';\n return phone.compareDocumentPosition(quote) & Node.DOCUMENT_POSITION_FOLLOWING ? 'phone-first' : 'quote-first';\n}\n\n/**\n * The hero: the shared hero section, else the smallest block around the page's visible H1 that holds a phone link\n * and a quote action, never above the H1's own section and never `<main>` (without a section, never a block holding\n * an H2). When none holds both, the H1's section (or its parent): its order then reads \"incomplete\".\n */\nexport function heroRegion(name: { source: string; flags: string }): Element | null {\n const heading = Array.from(document.querySelectorAll('h1')).find(isRendered);\n if (!heading) return null;\n const tagged = heading.closest('[data-bl-section=\"hero\"]');\n if (tagged) return tagged;\n const section = heading.closest('section');\n const fallback = section ?? heading.parentElement;\n for (let node = heading.parentElement; node && node !== document.body && node.tagName !== 'MAIN'; node = node.parentElement) {\n if (!section && node.querySelector('h2')) break;\n if (Array.from(node.querySelectorAll('a[href^=\"tel:\"]')).some(isRendered) && quoteActions(node, name).length > 0) return node;\n if (node === section) break;\n }\n return fallback && fallback.tagName !== 'MAIN' ? fallback : heading;\n}\n\n/** A point in the page that is not on an interactive element, a menu or anything in `avoid`. */\nexport function outsidePoint(avoid: Element[]): { x: number; y: number } | null {\n const interactive = 'a[href], button, input, select, textarea, label, summary, details, iframe, video, audio, [role=\"button\"], [role=\"link\"], [role=\"menuitem\"], [role=\"tab\"], [tabindex], [contenteditable=\"\"], [contenteditable=\"true\"]';\n for (let row = 9; row >= 3; row -= 1) {\n for (let column = 1; column <= 9; column += 1) {\n const x = Math.round((window.innerWidth * column) / 10);\n const y = Math.round((window.innerHeight * row) / 10);\n const element = document.elementFromPoint(x, y);\n if (!element || avoid.some((region) => region.contains(element))) continue;\n if (element.closest(interactive) || element.closest('header, nav, dialog, [role=\"dialog\"]')) continue;\n return { x, y };\n }\n }\n return null;\n}\n\n/** Tag an element so Playwright and axe can find it by `[data-brandlab-journey~=\"<name>\"]`. */\nexport function markElement(element: Element, name: string): void {\n const names = new Set((element.getAttribute('data-brandlab-journey') ?? '').split(/\\s+/).filter(Boolean));\n names.add(name);\n element.setAttribute('data-brandlab-journey', [...names].join(' '));\n}\n\n/**\n * Watch one disclosure: when the pointer enters and leaves its item (and panel), and when the panel it controls\n * becomes rendered or hidden, timed with `performance.now()`. Attribute and tree changes are sampled at once; style\n * changes without a DOM change (CSS `:hover`) every animation frame.\n */\nexport function watchDisclosure(trigger: Element, panelId: string): void {\n const item = trigger.closest('li') ?? trigger.parentElement ?? trigger;\n const panel = () => document.getElementById(panelId);\n const inside = (node: EventTarget | null) => node instanceof Node && (item.contains(node) || Boolean(panel()?.contains(node)));\n const state: DisclosureWatch = { enter: null, leave: null, opened: null, closed: null, open: isRendered(panel()) };\n const sample = () => {\n const open = isRendered(panel());\n if (open === state.open) return;\n state.open = open;\n if (open && state.opened === null) state.opened = performance.now();\n if (!open && state.closed === null) state.closed = performance.now();\n };\n const onOver = (event: Event) => {\n if (state.enter === null && inside(event.target)) state.enter = performance.now();\n };\n const onOut = (event: Event) => {\n if (state.leave === null && inside(event.target) && !inside((event as PointerEvent).relatedTarget)) state.leave = performance.now();\n };\n const observer = new MutationObserver(sample);\n observer.observe(document.documentElement, { attributes: true, childList: true, subtree: true });\n let frame = 0;\n const loop = () => {\n sample();\n frame = requestAnimationFrame(loop);\n };\n loop();\n document.addEventListener('pointerover', onOver, true);\n document.addEventListener('pointerout', onOut, true);\n const previous = (window as unknown as { __brandlabSiteSystemWatch?: { stop(): void } }).__brandlabSiteSystemWatch;\n previous?.stop();\n (window as unknown as { __brandlabSiteSystemWatch: unknown }).__brandlabSiteSystemWatch = {\n state,\n stop() {\n observer.disconnect();\n cancelAnimationFrame(frame);\n document.removeEventListener('pointerover', onOver, true);\n document.removeEventListener('pointerout', onOut, true);\n },\n };\n}\n\n/** The current state of `watchDisclosure`'s watch. */\nexport function watchState(): DisclosureWatch | null {\n const watch = (window as unknown as { __brandlabSiteSystemWatch?: { state: DisclosureWatch } }).__brandlabSiteSystemWatch;\n return watch ? { ...watch.state } : null;\n}\n\n/**\n * After a Tab press: is the focused element fully hidden under the sticky header or the call bar? Samples nine points\n * across the visible part of its box; it is hidden when the header or call bar is on top at every one. `repeat` is\n * true once focus comes back to an element it has already visited.\n */\nexport function focusStep(): { done: boolean; repeat: boolean; obscured: string | null; covered: 'header' | 'call bar' | null } {\n const element = document.activeElement;\n const store = window as unknown as { __brandlabSiteSystemFocus?: WeakSet<Element> };\n store.__brandlabSiteSystemFocus ??= new WeakSet<Element>();\n if (!element || element === document.body || element === document.documentElement) return { done: true, repeat: false, obscured: null, covered: null };\n const repeat = store.__brandlabSiteSystemFocus.has(element);\n store.__brandlabSiteSystemFocus.add(element);\n const header = document.querySelector('[data-brandlab-journey~=\"header\"]')\n ?? Array.from(document.querySelectorAll('[data-bl=\"header\"], header')).find((candidate) => isRendered(candidate) && !candidate.closest('main, article, section, aside, footer'))\n ?? null;\n const callBar = findCallBar();\n if (header?.contains(element) || callBar?.contains(element)) return { done: false, repeat, obscured: null, covered: null };\n const rect = element.getBoundingClientRect();\n const left = Math.max(rect.left, 0);\n const right = Math.min(rect.right, window.innerWidth);\n const top = Math.max(rect.top, 0);\n const bottom = Math.min(rect.bottom, window.innerHeight);\n if (right - left < 1 || bottom - top < 1) return { done: false, repeat, obscured: null, covered: null };\n let coveredBy: 'header' | 'call bar' | null = null;\n for (const fx of [0.15, 0.5, 0.85]) {\n for (const fy of [0.15, 0.5, 0.85]) {\n const hit = document.elementFromPoint(left + (right - left) * fx, top + (bottom - top) * fy);\n if (!hit || element.contains(hit)) return { done: false, repeat, obscured: null, covered: null };\n if (header?.contains(hit)) coveredBy ??= 'header';\n else if (callBar?.contains(hit)) coveredBy ??= 'call bar';\n else return { done: false, repeat, obscured: null, covered: null };\n }\n }\n return { done: false, repeat, obscured: describeElement(element), covered: coveredBy };\n}\n\n/**\n * `focusStep` one animation frame after the focus moved (capped at 50 ms, since a background page may not paint), so\n * a sticky bar that hides on its observer's next frame is measured after it moved, not mid-transition.\n */\nexport function focusStepAfterFrame(): Promise<ReturnType<typeof focusStep>> {\n return new Promise((resolve) => {\n let settled = false;\n const finish = () => {\n if (settled) return;\n settled = true;\n resolve(focusStep());\n };\n requestAnimationFrame(() => finish());\n setTimeout(finish, 50);\n });\n}\n\n/** Elements a Tab press can reach, roughly: enough to bound the K5 walk. */\nexport function tabbableCount(): number {\n const selector = 'a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), summary, iframe, [tabindex]:not([tabindex=\"-1\"])';\n return Array.from(document.querySelectorAll(selector)).filter(isRendered).length;\n}\n\nconst PAGE_HELPERS = {\n isRendered, describeElement, accessibleName, phonePlacement, parseColour, compositeColour, contrastRatio, backgroundBehind,\n iconContrastProblems, findCallBar, quoteActions, actionOrder, heroRegion, outsidePoint, markElement, watchDisclosure,\n watchState, focusStep, focusStepAfterFrame, tabbableCount,\n};\n\n/** `window.__brandlabSiteSystem` in a page the journeys opened. */\nexport type SiteSystemPageHelpers = typeof PAGE_HELPERS;\n\n/** The init script that defines `window.__brandlabSiteSystem` in every document of the page. */\nexport function pageHelpersSource(): string {\n const names = Object.keys(PAGE_HELPERS);\n return `(() => {\\nconst SITE_SYSTEM_PHONE_PLACEMENTS = ${JSON.stringify(SITE_SYSTEM_PHONE_PLACEMENTS)};\\n${Object.values(PAGE_HELPERS).map((helper) => helper.toString()).join('\\n')}\\nwindow.__brandlabSiteSystem = { ${names.join(', ')} };\\n})();`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"page-helpers.js","sourceRoot":"","sources":["../../../src/site-system/journeys/page-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Functions the site-system journeys run inside the page under test. Each one is self-contained: it uses DOM globals\n * and the other helpers in this file only, because `pageHelpersSource()` injects their source into every document\n * (as `window.__brandlabSiteSystem`, through Playwright's init script, which a Content Security Policy does not\n * block). The pure parts (colour, contrast, placement) are unit-tested in Node.\n */\n\n/**\n * The placements `phone_link_click` accepts: site-next's PHONE_CALL_PLACEMENTS (conformance cannot depend on\n * site-next; a test reads the site-next source and compares). Injected into the page with the helpers.\n */\nexport const SITE_SYSTEM_PHONE_PLACEMENTS: readonly string[] = Object.freeze(['header', 'footer', 'hero', 'cta', 'fab', 'contact', 'location', 'page', 'emergency']);\n\nexport type Rgba = [number, number, number, number];\n\n/** What `watchDisclosure` has seen, in `performance.now()` milliseconds. */\nexport interface DisclosureWatch {\n enter: number | null;\n leave: number | null;\n opened: number | null;\n closed: number | null;\n open: boolean;\n}\n\n/**\n * Whether an element is rendered: connected, with a box, not `visibility: hidden`, not fully transparent and not\n * inside a closed `<details>` (outside its summary). Chromium gives the content of a closed `<details>` a box, so\n * the box alone is not enough; `checkVisibility()` settles it where the browser has it.\n */\nexport function isRendered(element: Element | null | undefined): boolean {\n if (!element || !element.isConnected) return false;\n for (let details = element.closest('details:not([open])'); details; details = details.parentElement?.closest('details:not([open])') ?? null) {\n const summary = Array.from(details.children).find((child) => child.tagName === 'SUMMARY');\n if (!summary || !summary.contains(element)) return false;\n }\n if (typeof element.checkVisibility === 'function' && !element.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true })) return false;\n const rect = element.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) return false;\n if (getComputedStyle(element).visibility !== 'visible') return false;\n for (let node: Element | null = element; node; node = node.parentElement) {\n if (getComputedStyle(node).opacity === '0') return false;\n }\n return true;\n}\n\n/** A short, readable name for an element in a failure message. */\nexport function describeElement(element: Element): string {\n const tag = element.tagName.toLowerCase();\n const label = element.getAttribute('aria-label') ?? (element as HTMLElement).innerText ?? element.textContent ?? '';\n const text = label.replace(/\\s+/g, ' ').trim().slice(0, 40);\n const href = element.getAttribute('href');\n return `${tag}${text ? ` \"${text}\"` : ''}${href ? ` (${href})` : ''}`;\n}\n\n/** The accessible name, approximately: aria-label, aria-labelledby, the rendered text, then the title. */\nexport function accessibleName(element: Element): string {\n const label = element.getAttribute('aria-label');\n if (label && label.trim()) return label.trim();\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const text = labelledBy.split(/\\s+/).map((id) => document.getElementById(id)?.textContent ?? '').join(' ').trim();\n if (text) return text.replace(/\\s+/g, ' ');\n }\n const text = ((element as HTMLElement).innerText ?? element.textContent ?? '').replace(/\\s+/g, ' ').trim();\n return text || (element.getAttribute('title') ?? '').trim();\n}\n\n/**\n * Where a telephone link reports its tap, exactly as site-next's shared listener resolves it: its own valid\n * `data-phone-location`, then a `<header>` or `<footer>` ancestor, then the nearest ancestor with a valid value,\n * otherwise `page`. `invalid` is the nearest declared value when it is not an allowed placement (the listener then\n * reports the link somewhere else, silently).\n */\nexport function phonePlacement(link: Element): { placement: string; invalid: string | null } {\n const valid = (node: Element): string | undefined => {\n const value = node.getAttribute('data-phone-location')?.trim().toLowerCase();\n return value && SITE_SYSTEM_PHONE_PLACEMENTS.includes(value) ? value : undefined;\n };\n const nearest = link.closest('[data-phone-location]');\n const invalid = nearest && !valid(nearest) ? nearest.getAttribute('data-phone-location') : null;\n const own = valid(link);\n if (own) return { placement: own, invalid };\n if (link.closest('header')) return { placement: 'header', invalid };\n if (link.closest('footer')) return { placement: 'footer', invalid };\n for (let node = link.parentElement?.closest('[data-phone-location]') ?? null; node; node = node.parentElement?.closest('[data-phone-location]') ?? null) {\n const value = valid(node);\n if (value) return { placement: value, invalid };\n }\n return { placement: 'page', invalid };\n}\n\n/** Parse a computed colour. `rgb()`/`rgba()` directly; any other syntax (oklch, lab, color()) through a canvas pixel. */\nexport function parseColour(value: string): Rgba | null {\n const text = value.trim().toLowerCase();\n if (text === 'transparent') return [0, 0, 0, 0];\n const match = /^rgba?\\(([^)]+)\\)$/.exec(text);\n if (match) {\n const parts = match[1]!.split(/[\\s,/]+/).filter(Boolean);\n if (parts.length < 3) return null;\n const channel = (part: string) => (part.endsWith('%') ? (Number.parseFloat(part) / 100) * 255 : Number.parseFloat(part));\n const alphaPart = parts[3];\n const alpha = alphaPart === undefined ? 1 : alphaPart.endsWith('%') ? Number.parseFloat(alphaPart) / 100 : Number.parseFloat(alphaPart);\n const rgba: Rgba = [channel(parts[0]!), channel(parts[1]!), channel(parts[2]!), alpha];\n return rgba.every((part) => Number.isFinite(part)) ? rgba : null;\n }\n if (typeof document === 'undefined') return null;\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n const context = canvas.getContext('2d', { willReadFrequently: true });\n if (!context) return null;\n context.clearRect(0, 0, 1, 1);\n context.fillStyle = value;\n context.fillRect(0, 0, 1, 1);\n const [red = 0, green = 0, blue = 0, alpha = 0] = Array.from(context.getImageData(0, 0, 1, 1).data);\n return [red, green, blue, alpha / 255];\n}\n\n/** `top` painted over an opaque `bottom`. */\nexport function compositeColour(top: Rgba, bottom: Rgba): Rgba {\n const alpha = top[3];\n return [\n top[0] * alpha + bottom[0] * (1 - alpha),\n top[1] * alpha + bottom[1] * (1 - alpha),\n top[2] * alpha + bottom[2] * (1 - alpha),\n 1,\n ];\n}\n\n/** The WCAG contrast ratio of two opaque colours. */\nexport function contrastRatio(first: Rgba, second: Rgba): number {\n const luminance = (colour: Rgba) => {\n const [red, green, blue] = colour.slice(0, 3).map((channel) => {\n const value = channel / 255;\n return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;\n }) as [number, number, number];\n return 0.2126 * red + 0.7152 * green + 0.0722 * blue;\n };\n const [light, dark] = [luminance(first), luminance(second)].sort((left, right) => right - left) as [number, number];\n return (light + 0.05) / (dark + 0.05);\n}\n\n/**\n * The opaque colour behind an element, from its own and its ancestors' background colours over a white canvas.\n * `null` when a background image (a photo or gradient) is in the way: the contrast cannot be computed there.\n */\nexport function backgroundBehind(element: Element): Rgba | null {\n const layers: Rgba[] = [];\n for (let node: Element | null = element; node; node = node.parentElement) {\n const style = getComputedStyle(node);\n if (style.backgroundImage && style.backgroundImage !== 'none') return null;\n const colour = parseColour(style.backgroundColor);\n if (colour && colour[3] > 0) {\n layers.push(colour);\n if (colour[3] >= 1) break;\n }\n }\n return layers.reverse().reduce<Rgba>((bottom, top) => compositeColour(top, bottom), [255, 255, 255, 1]);\n}\n\n/**\n * Non-text contrast (WCAG 1.4.11) of icon-only controls inside `root`: a link or button with no visible text whose\n * icon is an SVG must reach 3:1 against what is behind it. Returns one line per failure; controls over a photo are\n * counted in `unmeasured`.\n */\nexport function iconContrastProblems(root: Element): { problems: string[]; checked: number; unmeasured: number } {\n const problems: string[] = [];\n let checked = 0;\n let unmeasured = 0;\n const paintOf = (svg: SVGElement): Rgba | null => {\n for (const shape of Array.from(svg.querySelectorAll('path, circle, rect, ellipse, line, polyline, polygon, text, use'))) {\n if (!isRendered(shape)) continue;\n const style = getComputedStyle(shape);\n for (const [paint, opacity] of [[style.fill, style.fillOpacity], [style.stroke, style.strokeOpacity]] as const) {\n if (!paint || paint === 'none' || paint.startsWith('url(')) continue;\n const colour = parseColour(paint);\n const alpha = colour ? colour[3] * Number(opacity || 1) * Number(style.opacity || 1) : 0;\n if (colour && alpha > 0) return [colour[0], colour[1], colour[2], alpha];\n }\n }\n return null;\n };\n for (const control of Array.from(root.querySelectorAll('a[href], button'))) {\n if (!isRendered(control)) continue;\n if (((control as HTMLElement).innerText ?? '').trim()) continue;\n const svg = control.querySelector('svg');\n if (!svg || !isRendered(svg)) continue;\n const paint = paintOf(svg);\n if (!paint) continue;\n const background = backgroundBehind(svg);\n if (!background) {\n unmeasured += 1;\n continue;\n }\n checked += 1;\n const ratio = contrastRatio(compositeColour(paint, background), background);\n if (ratio < 3) problems.push(`${describeElement(control)}: its icon is ${ratio.toFixed(2)}:1 against its background (needs 3:1)`);\n }\n return { problems, checked, unmeasured };\n}\n\n/**\n * The phone call bar: the shared `MobileCallBar`, or any fixed or sticky element along the bottom of the screen that\n * holds a visible telephone link (outside the header and dialogs). `null` when none is on screen.\n */\nexport function findCallBar(): Element | null {\n const tagged = Array.from(document.querySelectorAll('[data-bl=\"call-bar\"], [data-bl=\"callbar\"], [data-bl=\"mobile-call-bar\"]')).find(isRendered);\n if (tagged) return tagged;\n const height = window.innerHeight;\n for (const element of Array.from(document.body.querySelectorAll('*'))) {\n const position = getComputedStyle(element).position;\n if (position !== 'fixed' && position !== 'sticky') continue;\n if (element.closest('header, dialog, [role=\"dialog\"]')) continue;\n const rect = element.getBoundingClientRect();\n if (rect.height <= 0 || rect.bottom < height - 4 || rect.top < height / 2) continue;\n if (!isRendered(element)) continue;\n if (Array.from(element.querySelectorAll('a[href^=\"tel:\"]')).some(isRendered)) return element;\n }\n return null;\n}\n\n/** Visible quote actions in `root`: links or buttons named like the quote action, or the shared quote hooks. */\nexport function quoteActions(root: Element, name: { source: string; flags: string }): Element[] {\n const pattern = new RegExp(name.source, name.flags);\n return Array.from(root.querySelectorAll('a[href], button')).filter((element) => {\n if (!isRendered(element) || element.getAttribute('href')?.startsWith('tel:')) return false;\n if (element.matches('[data-bl=\"quote-button\"], [data-bl-cta^=\"quote\"], [data-lead-cta^=\"quote\"]')) return true;\n return pattern.test(accessibleName(element));\n });\n}\n\n/** The order of the first visible phone link and quote action in `root`. */\nexport function actionOrder(root: Element, name: { source: string; flags: string }): 'phone-first' | 'quote-first' | 'incomplete' {\n const phone = Array.from(root.querySelectorAll('a[href^=\"tel:\"]')).find(isRendered);\n const quote = quoteActions(root, name)[0];\n if (!phone || !quote) return 'incomplete';\n return phone.compareDocumentPosition(quote) & Node.DOCUMENT_POSITION_FOLLOWING ? 'phone-first' : 'quote-first';\n}\n\n/**\n * The hero: the shared hero section, else the smallest block around the page's visible H1 that holds a phone link\n * and a quote action, never above the H1's own section and never `<main>` (without a section, never a block holding\n * an H2). When none holds both, the H1's section (or its parent): its order then reads \"incomplete\".\n */\nexport function heroRegion(name: { source: string; flags: string }): Element | null {\n const heading = Array.from(document.querySelectorAll('h1')).find(isRendered);\n if (!heading) return null;\n const tagged = heading.closest('[data-bl-section=\"hero\"]');\n if (tagged) return tagged;\n const section = heading.closest('section');\n const fallback = section ?? heading.parentElement;\n for (let node = heading.parentElement; node && node !== document.body && node.tagName !== 'MAIN'; node = node.parentElement) {\n if (!section && node.querySelector('h2')) break;\n if (Array.from(node.querySelectorAll('a[href^=\"tel:\"]')).some(isRendered) && quoteActions(node, name).length > 0) return node;\n if (node === section) break;\n }\n return fallback && fallback.tagName !== 'MAIN' ? fallback : heading;\n}\n\n/** A point in the page that is not on an interactive element, a menu or anything in `avoid`. */\nexport function outsidePoint(avoid: Element[]): { x: number; y: number } | null {\n const interactive = 'a[href], button, input, select, textarea, label, summary, details, iframe, video, audio, [role=\"button\"], [role=\"link\"], [role=\"menuitem\"], [role=\"tab\"], [tabindex], [contenteditable=\"\"], [contenteditable=\"true\"]';\n for (let row = 9; row >= 3; row -= 1) {\n for (let column = 1; column <= 9; column += 1) {\n const x = Math.round((window.innerWidth * column) / 10);\n const y = Math.round((window.innerHeight * row) / 10);\n const element = document.elementFromPoint(x, y);\n if (!element || avoid.some((region) => region.contains(element))) continue;\n if (element.closest(interactive) || element.closest('header, nav, dialog, [role=\"dialog\"]')) continue;\n return { x, y };\n }\n }\n return null;\n}\n\n/** Tag an element so Playwright and axe can find it by `[data-brandlab-journey~=\"<name>\"]`. */\nexport function markElement(element: Element, name: string): void {\n const names = new Set((element.getAttribute('data-brandlab-journey') ?? '').split(/\\s+/).filter(Boolean));\n names.add(name);\n element.setAttribute('data-brandlab-journey', [...names].join(' '));\n}\n\n/**\n * Watch one disclosure: when the pointer enters and leaves its item (and panel), and when the panel it controls\n * becomes rendered or hidden, timed with `performance.now()`. Attribute and tree changes are sampled at once; style\n * changes without a DOM change (CSS `:hover`) every animation frame.\n */\nexport function watchDisclosure(trigger: Element, panelId: string): void {\n const item = trigger.closest('li') ?? trigger.parentElement ?? trigger;\n const panel = () => document.getElementById(panelId);\n const inside = (node: EventTarget | null) => node instanceof Node && (item.contains(node) || Boolean(panel()?.contains(node)));\n const state: DisclosureWatch = { enter: null, leave: null, opened: null, closed: null, open: isRendered(panel()) };\n const sample = () => {\n const open = isRendered(panel());\n if (open === state.open) return;\n state.open = open;\n if (open && state.opened === null) state.opened = performance.now();\n if (!open && state.closed === null) state.closed = performance.now();\n };\n const onOver = (event: Event) => {\n if (state.enter === null && inside(event.target)) state.enter = performance.now();\n };\n const onOut = (event: Event) => {\n if (state.leave === null && inside(event.target) && !inside((event as PointerEvent).relatedTarget)) state.leave = performance.now();\n };\n const observer = new MutationObserver(sample);\n observer.observe(document.documentElement, { attributes: true, childList: true, subtree: true });\n let frame = 0;\n const loop = () => {\n sample();\n frame = requestAnimationFrame(loop);\n };\n loop();\n document.addEventListener('pointerover', onOver, true);\n document.addEventListener('pointerout', onOut, true);\n const previous = (window as unknown as { __brandlabSiteSystemWatch?: { stop(): void } }).__brandlabSiteSystemWatch;\n previous?.stop();\n (window as unknown as { __brandlabSiteSystemWatch: unknown }).__brandlabSiteSystemWatch = {\n state,\n stop() {\n observer.disconnect();\n cancelAnimationFrame(frame);\n document.removeEventListener('pointerover', onOver, true);\n document.removeEventListener('pointerout', onOut, true);\n },\n };\n}\n\n/** The current state of `watchDisclosure`'s watch. */\nexport function watchState(): DisclosureWatch | null {\n const watch = (window as unknown as { __brandlabSiteSystemWatch?: { state: DisclosureWatch } }).__brandlabSiteSystemWatch;\n return watch ? { ...watch.state } : null;\n}\n\n/**\n * After a Tab press: is the focused element fully hidden under the sticky header or the call bar? Samples nine points\n * across the visible part of its box; it is hidden when the header or call bar is on top at every one. `repeat` is\n * true once focus comes back to an element it has already visited.\n */\nexport function focusStep(): { done: boolean; repeat: boolean; obscured: string | null; covered: 'header' | 'call bar' | null } {\n const element = document.activeElement;\n const store = window as unknown as { __brandlabSiteSystemFocus?: WeakSet<Element> };\n store.__brandlabSiteSystemFocus ??= new WeakSet<Element>();\n if (!element || element === document.body || element === document.documentElement) return { done: true, repeat: false, obscured: null, covered: null };\n const repeat = store.__brandlabSiteSystemFocus.has(element);\n store.__brandlabSiteSystemFocus.add(element);\n const header = document.querySelector('[data-brandlab-journey~=\"header\"]')\n ?? Array.from(document.querySelectorAll('[data-bl=\"header\"], header')).find((candidate) => isRendered(candidate) && !candidate.closest('main, article, section, aside, footer'))\n ?? null;\n const callBar = findCallBar();\n if (header?.contains(element) || callBar?.contains(element)) return { done: false, repeat, obscured: null, covered: null };\n const rect = element.getBoundingClientRect();\n const left = Math.max(rect.left, 0);\n const right = Math.min(rect.right, window.innerWidth);\n const top = Math.max(rect.top, 0);\n const bottom = Math.min(rect.bottom, window.innerHeight);\n if (right - left < 1 || bottom - top < 1) return { done: false, repeat, obscured: null, covered: null };\n let coveredBy: 'header' | 'call bar' | null = null;\n for (const fx of [0.15, 0.5, 0.85]) {\n for (const fy of [0.15, 0.5, 0.85]) {\n const hit = document.elementFromPoint(left + (right - left) * fx, top + (bottom - top) * fy);\n if (!hit || element.contains(hit)) return { done: false, repeat, obscured: null, covered: null };\n if (header?.contains(hit)) coveredBy ??= 'header';\n else if (callBar?.contains(hit)) coveredBy ??= 'call bar';\n else return { done: false, repeat, obscured: null, covered: null };\n }\n }\n return { done: false, repeat, obscured: describeElement(element), covered: coveredBy };\n}\n\n/**\n * `focusStep` one animation frame after the focus moved (capped at 50 ms, since a background page may not paint), so\n * a sticky bar that hides on its observer's next frame is measured after it moved, not mid-transition.\n */\nexport function focusStepAfterFrame(): Promise<ReturnType<typeof focusStep>> {\n return new Promise((resolve) => {\n let settled = false;\n const finish = () => {\n if (settled) return;\n settled = true;\n resolve(focusStep());\n };\n requestAnimationFrame(() => finish());\n setTimeout(finish, 50);\n });\n}\n\n/** Elements a Tab press can reach, roughly: enough to bound the K5 walk. */\nexport function tabbableCount(): number {\n const selector = 'a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), summary, iframe, [tabindex]:not([tabindex=\"-1\"])';\n return Array.from(document.querySelectorAll(selector)).filter(isRendered).length;\n}\n\nconst PAGE_HELPERS = {\n isRendered, describeElement, accessibleName, phonePlacement, parseColour, compositeColour, contrastRatio, backgroundBehind,\n iconContrastProblems, findCallBar, quoteActions, actionOrder, heroRegion, outsidePoint, markElement, watchDisclosure,\n watchState, focusStep, focusStepAfterFrame, tabbableCount,\n};\n\n/** `window.__brandlabSiteSystem` in a page the journeys opened. */\nexport type SiteSystemPageHelpers = typeof PAGE_HELPERS;\n\n/** The init script that defines `window.__brandlabSiteSystem` in every document of the page. */\nexport function pageHelpersSource(): string {\n const names = Object.keys(PAGE_HELPERS);\n return `(() => {\\nconst SITE_SYSTEM_PHONE_PLACEMENTS = ${JSON.stringify(SITE_SYSTEM_PHONE_PLACEMENTS)};\\n${Object.values(PAGE_HELPERS).map((helper) => helper.toString()).join('\\n')}\\nwindow.__brandlabSiteSystem = { ${names.join(', ')} };\\n})();`;\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { detectInstalledBrandlabRelease } from '../../project.js';
|
|
1
2
|
import { SITE_SYSTEM_CHECKS, type SiteSystemTier } from '../checks.js';
|
|
2
3
|
type JourneyCheck = Extract<(typeof SITE_SYSTEM_CHECKS)[number], {
|
|
3
4
|
kind: 'journey';
|
|
@@ -22,9 +23,11 @@ export interface BrandlabSiteSystemTestOptions {
|
|
|
22
23
|
/** The adoption tier from brandlab.config.ts (`siteSystem.tier`). C1 registers from `enquiry`. */
|
|
23
24
|
tier: SiteSystemTier;
|
|
24
25
|
/**
|
|
25
|
-
* The release whose journeys register
|
|
26
|
-
* release
|
|
27
|
-
*
|
|
26
|
+
* The release whose journeys register. `defineBrandlabSiteSystemTests` defaults it to the site's installed Brandlab
|
|
27
|
+
* release, read from its package.json as `brandlab-ready` reads it (one exact version, or one canary such as
|
|
28
|
+
* `3.15.0-canary.2`), else this conformance release. A journey registers only from the release that brings it, so a
|
|
29
|
+
* later journey never turns a site's e2e run red before the gate blocks on it, and a check that blocks has its
|
|
30
|
+
* journey. Name a later release to preview its journeys.
|
|
28
31
|
*/
|
|
29
32
|
release?: string;
|
|
30
33
|
/**
|
|
@@ -83,6 +86,13 @@ export declare function siteSystemJourneyTitle(id: SiteSystemJourneyId, text: st
|
|
|
83
86
|
* it (default: this conformance release).
|
|
84
87
|
*/
|
|
85
88
|
export declare function siteSystemJourneysFor(tier: SiteSystemTier, release?: string): SiteSystemJourneyId[];
|
|
89
|
+
/**
|
|
90
|
+
* The release the journeys register for on a site: its installed Brandlab release as `brandlab-ready` reads it (all
|
|
91
|
+
* four packages at one exact version, or one canary, from package.json), else this conformance release. A canary's
|
|
92
|
+
* own release manifest still names the last published release, so without this its new journeys (W2 and W9 on
|
|
93
|
+
* 3.15.0-canary.2) would not register while the gate blocks on them.
|
|
94
|
+
*/
|
|
95
|
+
export declare function siteSystemJourneyRelease(packageJson: Parameters<typeof detectInstalledBrandlabRelease>[0]): string;
|
|
86
96
|
/** Validate the options and fill the defaults. Malformed options throw, listing every problem. */
|
|
87
97
|
export declare function planBrandlabSiteSystemJourneys(options: BrandlabSiteSystemTestOptions): SiteSystemJourneyPlan;
|
|
88
98
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/site-system/journeys/plan.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,EAA4C,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAEjH,KAAK,YAAY,GAAG,OAAO,CAAC,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC;AACtF,MAAM,MAAM,mBAAmB,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;AAErD,+DAA+D;AAC/D,eAAO,MAAM,uBAAuB,yFAAkJ,CAAC;AAEvL,wHAAwH;AACxH,eAAO,MAAM,0BAA0B,mBAAgD,CAAC;AACxF,eAAO,MAAM,0BAA0B;;;EAA6C,CAAC;AACrF,eAAO,MAAM,4BAA4B;;;EAA8C,CAAC;AAExF,4EAA4E;AAC5E,eAAO,MAAM,sBAAsB,QAAe,CAAC;AAEnD,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG,aAAa,CAAC;AAElE,MAAM,WAAW,6BAA6B;IAC5C,kGAAkG;IAClG,IAAI,EAAE,cAAc,CAAC;IACrB
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/site-system/journeys/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* defaults. Pure, so it is unit-tested without a browser.
|
|
4
4
|
*/
|
|
5
5
|
import { BRANDLAB_CURRENT_RUNTIME_RELEASE } from '../../current-release.js';
|
|
6
|
+
import { detectBrandlabCanaryRelease, detectInstalledBrandlabRelease } from '../../project.js';
|
|
6
7
|
import { SITE_SYSTEM_CHECKS, SITE_SYSTEM_TIERS, siteSystemReleaseRank } from '../checks.js';
|
|
7
8
|
/** Every journey check, in the order the journeys register. */
|
|
8
9
|
export const SITE_SYSTEM_JOURNEY_IDS = Object.freeze(['N3', 'N4', 'N5', 'N6', 'N8', 'K3', 'K4', 'K5', 'K6', 'C4', 'W2', 'C1', 'W9']);
|
|
@@ -30,6 +31,15 @@ export function siteSystemJourneysFor(tier, release = BRANDLAB_CURRENT_RUNTIME_R
|
|
|
30
31
|
&& siteSystemReleaseRank(check.from) <= releaseRank;
|
|
31
32
|
});
|
|
32
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The release the journeys register for on a site: its installed Brandlab release as `brandlab-ready` reads it (all
|
|
36
|
+
* four packages at one exact version, or one canary, from package.json), else this conformance release. A canary's
|
|
37
|
+
* own release manifest still names the last published release, so without this its new journeys (W2 and W9 on
|
|
38
|
+
* 3.15.0-canary.2) would not register while the gate blocks on them.
|
|
39
|
+
*/
|
|
40
|
+
export function siteSystemJourneyRelease(packageJson) {
|
|
41
|
+
return detectInstalledBrandlabRelease(packageJson) ?? detectBrandlabCanaryRelease(packageJson)?.version ?? BRANDLAB_CURRENT_RUNTIME_RELEASE.releaseVersion;
|
|
42
|
+
}
|
|
33
43
|
function pathProblem(label, path) {
|
|
34
44
|
if (typeof path !== 'string' || !path.startsWith('/') || path.startsWith('//') || /\s/.test(path)) {
|
|
35
45
|
return `${label} must be a site path starting with "/" (got ${JSON.stringify(path)})`;
|
|
@@ -77,8 +87,8 @@ export function planBrandlabSiteSystemJourneys(options) {
|
|
|
77
87
|
if (value !== undefined && (!Number.isInteger(value) || value <= 0))
|
|
78
88
|
errors.push(`${key} must be a positive whole number (got ${value})`);
|
|
79
89
|
}
|
|
80
|
-
if (input.release !== undefined && (typeof input.release !== 'string' || !/^\d+\.\d+\.\d
|
|
81
|
-
errors.push(`release must be a version such as 3.9.0 (got ${JSON.stringify(input.release)})`);
|
|
90
|
+
if (input.release !== undefined && (typeof input.release !== 'string' || !/^\d+\.\d+\.\d+(?:-canary\.\d+)?$/.test(input.release))) {
|
|
91
|
+
errors.push(`release must be a version such as 3.9.0 or 3.15.0-canary.2 (got ${JSON.stringify(input.release)})`);
|
|
82
92
|
}
|
|
83
93
|
if (input.navName !== undefined && (typeof input.navName !== 'string' || !input.navName.trim()))
|
|
84
94
|
errors.push('navName must be a non-empty string');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/site-system/journeys/plan.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,gCAAgC,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,qBAAqB,EAAuB,MAAM,cAAc,CAAC;AAKjH,+DAA+D;AAC/D,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAmD,CAAC,CAAC;AAEvL,wHAAwH;AACxH,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AACxF,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AACrF,MAAM,CAAC,MAAM,4BAA4B,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AAExF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,sBAAsB,GAAG,YAAY,CAAC;AA4DnD,MAAM,UAAU,sBAAsB,CAAC,EAAuB,EAAE,IAAY;IAC1E,OAAO,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAoB,EAAE,UAAkB,gCAAgC,CAAC,cAAc;IAC3H,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAyC,kBAAkB,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACnK,OAAO,uBAAuB,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;QAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/B,OAAO,KAAK,KAAK,SAAS;eACrB,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,IAAsB,CAAC,IAAI,IAAI;eAC/D,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,KAAa,EAAE,IAAa;IAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAClG,OAAO,GAAG,KAAK,+CAA+C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;IACxF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,8BAA8B,CAAC,OAAsC;IACnF,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,CAAC,OAAO,IAAI,EAAE,CAA2C,CAAC;IACxE,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAsB,CAAC,EAAE,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,uBAAuB,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzG,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAK,EAA6C,CAAC;IAC5E,MAAM,WAAW,GAAG,WAAW,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,WAAW;QAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAClH,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,OAAO,GAAG,WAAW,CAAC,eAAe,KAAK,GAAG,EAAE,IAAI,CAAC,CAAC;QAC3D,IAAI,OAAO;YAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,WAAW,CAAC,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5D,IAAI,OAAO;YAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IACjI,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC/B,MAAM,OAAO,GAAG,WAAW,CAAC,kBAAkB,KAAK,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,kBAAkB,KAAK,uDAAuD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpN,IAAI,OAAO;YAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,0BAA0B,CAAC,CAAC;IAC/G,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI;YAAE,MAAM,CAAC,IAAI,CAAC,mEAAmE,KAAK,GAAG,CAAC,CAAC;IACzJ,CAAC;IACD,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,KAAK,aAAa,IAAI,KAAK,CAAC,WAAW,KAAK,aAAa,EAAE,CAAC;QAClH,MAAM,CAAC,IAAI,CAAC,uDAAuD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC3G,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,CAAC,qBAAqB,EAAE,iBAAiB,EAAE,aAAa,CAAU,EAAE,CAAC;QACrF,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,yCAAyC,KAAK,GAAG,CAAC,CAAC;IAC5I,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACjH,MAAM,CAAC,IAAI,CAAC,gDAAgD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChG,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;IACnJ,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,kCAAkC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAElG,MAAM,IAAI,GAAG,KAAK,CAAC,IAAsB,CAAC;IAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,gCAAgC,CAAC,cAAc,CAAC;IACjF,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAsC,EAAE,CAAC;IACvD,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,QAAQ,CAAC,EAAE,GAAG,wGAAwG,CAAC;IACzH,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,QAAQ,CAAC,EAAE,GAAG,qGAAqG,CAAC;IACtH,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,KAAK,SAAS;QAC7C,CAAC,CAAC,sBAAsB;QACxB,CAAC,CAAC,KAAK,CAAC,SAAS,YAAY,MAAM;YACjC,CAAC,CAAC,KAAK,CAAC,SAAS;YACjB,CAAC,CAAC,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7F,OAAO;QACL,IAAI;QACJ,OAAO;QACP,QAAQ;QACR,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK;QACL,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChC,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxF,aAAa;QACb,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,aAAa;QAC/C,SAAS;QACT,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,MAAM;QAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,MAAM;QAClC,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,IAAI,MAAM;QACxD,eAAe,EAAE,KAAK,CAAC,eAAe,IAAI,MAAM;QAChD,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,GAAG;QACrC,QAAQ;KACT,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Options and planning for the site-system journeys: which journeys a tier registers, the sampled pages and the\n * defaults. Pure, so it is unit-tested without a browser.\n */\nimport { BRANDLAB_CURRENT_RUNTIME_RELEASE } from '../../current-release.js';\nimport { SITE_SYSTEM_CHECKS, SITE_SYSTEM_TIERS, siteSystemReleaseRank, type SiteSystemTier } from '../checks.js';\n\ntype JourneyCheck = Extract<(typeof SITE_SYSTEM_CHECKS)[number], { kind: 'journey' }>;\nexport type SiteSystemJourneyId = JourneyCheck['id'];\n\n/** Every journey check, in the order the journeys register. */\nexport const SITE_SYSTEM_JOURNEY_IDS = Object.freeze(['N3', 'N4', 'N5', 'N6', 'N8', 'K3', 'K4', 'K5', 'K6', 'C4', 'W2', 'C1', 'W9'] as const satisfies readonly SiteSystemJourneyId[]);\n\n/** Desktop widths for N6: both ends and the middle of the compact band, the desktop breakpoint and two wide screens. */\nexport const SITE_SYSTEM_DESKTOP_WIDTHS = Object.freeze([1024, 1100, 1280, 1440, 1920]);\nexport const SITE_SYSTEM_PHONE_VIEWPORT = Object.freeze({ width: 390, height: 844 });\nexport const SITE_SYSTEM_DESKTOP_VIEWPORT = Object.freeze({ width: 1440, height: 900 });\n\n/** The quote action's accessible name when the site does not record one. */\nexport const SITE_SYSTEM_QUOTE_NAME = /\\bquote\\b/i;\n\nexport type SiteSystemActionOrder = 'phone-first' | 'quote-first';\n\nexport interface BrandlabSiteSystemTestOptions {\n /** The adoption tier from brandlab.config.ts (`siteSystem.tier`). C1 registers from `enquiry`. */\n tier: SiteSystemTier;\n /**\n * The release whose journeys register (default: this conformance release). A journey registers only from the\n * release that brings it, so a later journey never turns a site's e2e run red before the gate blocks on it. Name a\n * later release to preview its journeys.\n */\n release?: string;\n /**\n * The sampled pages: home, the money pages (service pages with the enquiry form) and the contact page. `families`\n * (W9, full tier from 3.13.0) names one built page per dynamic route family, such as `/services/blocked-drains` and\n * `/locations/ryde`: its URL variants are checked.\n */\n pages: { home: string; money?: string | readonly string[]; contact?: string; families?: string | readonly string[] };\n /** Desktop widths for N6, each 1024 px or more (default 1024, 1100, 1280, 1440 and 1920). */\n desktopWidths?: readonly number[];\n /** The recorded order of the phone and quote actions (K6), default `phone-first`. */\n actionOrder?: SiteSystemActionOrder;\n /** The quote action's accessible name (default /\\bquote\\b/i), for a recorded label such as \"Book an inspection\". */\n quoteName?: string | RegExp;\n /** The main menu's accessible name (default \"Main\"). */\n navName?: string;\n /** The phone menu button's accessible name (default \"Menu\"). */\n menuName?: string | RegExp;\n /** How long a document may take to load, default 45 seconds; a timeout is retried once. */\n navigationTimeoutMs?: number;\n /** How long to wait for the network to settle after a load, default 10 seconds; a busy network is not a failure. */\n settleTimeoutMs?: number;\n /** The most Tab presses K5 makes on one page (default 400); a longer page is reported, not failed. */\n maxTabStops?: number;\n}\n\nexport interface SiteSystemJourneyPlan {\n tier: SiteSystemTier;\n release: string;\n journeys: readonly SiteSystemJourneyId[];\n home: string;\n money: readonly string[];\n contact: string | undefined;\n /** One page per dynamic route family, for W9's URL variants. */\n families: readonly string[];\n /** Home, the money pages and the contact page, without repeats: K5, K6 and C4 run on each. */\n sampled: readonly string[];\n desktopWidths: readonly number[];\n actionOrder: SiteSystemActionOrder;\n quoteName: RegExp;\n navName: string;\n menuName: string | RegExp;\n navigationTimeoutMs: number;\n settleTimeoutMs: number;\n maxTabStops: number;\n /** Gaps that fail a journey when it runs (fail closed), rather than stopping the whole spec file. */\n problems: Partial<Record<SiteSystemJourneyId, string>>;\n}\n\nexport function siteSystemJourneyTitle(id: SiteSystemJourneyId, text: string): string {\n return `[${id}] ${text}`;\n}\n\n/**\n * The journey checks a tier registers on a release: its own and the tiers below it, each from the release that brings\n * it (default: this conformance release).\n */\nexport function siteSystemJourneysFor(tier: SiteSystemTier, release: string = BRANDLAB_CURRENT_RUNTIME_RELEASE.releaseVersion): SiteSystemJourneyId[] {\n const rank = SITE_SYSTEM_TIERS.indexOf(tier);\n const releaseRank = siteSystemReleaseRank(release);\n const journeys = new Map<string, { tier: string; from: string }>(SITE_SYSTEM_CHECKS.filter((check) => check.kind === 'journey').map((check) => [check.id, check]));\n return SITE_SYSTEM_JOURNEY_IDS.filter((id) => {\n const check = journeys.get(id);\n return check !== undefined\n && SITE_SYSTEM_TIERS.indexOf(check.tier as SiteSystemTier) <= rank\n && siteSystemReleaseRank(check.from) <= releaseRank;\n });\n}\n\nfunction pathProblem(label: string, path: unknown): string | null {\n if (typeof path !== 'string' || !path.startsWith('/') || path.startsWith('//') || /\\s/.test(path)) {\n return `${label} must be a site path starting with \"/\" (got ${JSON.stringify(path)})`;\n }\n return null;\n}\n\n/** Validate the options and fill the defaults. Malformed options throw, listing every problem. */\nexport function planBrandlabSiteSystemJourneys(options: BrandlabSiteSystemTestOptions): SiteSystemJourneyPlan {\n const errors: string[] = [];\n const input = (options ?? {}) as Partial<BrandlabSiteSystemTestOptions>;\n if (!SITE_SYSTEM_TIERS.includes(input.tier as SiteSystemTier)) {\n errors.push(`tier must be one of ${SITE_SYSTEM_TIERS.join(', ')} (got ${JSON.stringify(input.tier)})`);\n }\n const pages = input.pages ?? ({} as BrandlabSiteSystemTestOptions['pages']);\n const homeProblem = pathProblem('pages.home', pages.home);\n if (homeProblem) errors.push(homeProblem);\n const money = pages.money === undefined ? [] : typeof pages.money === 'string' ? [pages.money] : [...pages.money];\n money.forEach((path, index) => {\n const problem = pathProblem(`pages.money[${index}]`, path);\n if (problem) errors.push(problem);\n });\n if (pages.contact !== undefined) {\n const problem = pathProblem('pages.contact', pages.contact);\n if (problem) errors.push(problem);\n }\n const families = pages.families === undefined ? [] : typeof pages.families === 'string' ? [pages.families] : [...pages.families];\n families.forEach((path, index) => {\n const problem = pathProblem(`pages.families[${index}]`, path) ?? (/[?#]/.test(path) || path === '/' ? `pages.families[${index}] must be a page path below home with no query (got ${JSON.stringify(path)})` : null);\n if (problem) errors.push(problem);\n });\n const desktopWidths = input.desktopWidths?.length ? [...input.desktopWidths] : [...SITE_SYSTEM_DESKTOP_WIDTHS];\n for (const width of desktopWidths) {\n if (!Number.isInteger(width) || width < 1024 || width > 3840) errors.push(`desktopWidths must be whole pixel widths from 1024 to 3840 (got ${width})`);\n }\n if (input.actionOrder !== undefined && input.actionOrder !== 'phone-first' && input.actionOrder !== 'quote-first') {\n errors.push(`actionOrder must be phone-first or quote-first (got ${JSON.stringify(input.actionOrder)})`);\n }\n for (const key of ['navigationTimeoutMs', 'settleTimeoutMs', 'maxTabStops'] as const) {\n const value = input[key];\n if (value !== undefined && (!Number.isInteger(value) || value <= 0)) errors.push(`${key} must be a positive whole number (got ${value})`);\n }\n if (input.release !== undefined && (typeof input.release !== 'string' || !/^\\d+\\.\\d+\\.\\d+$/.test(input.release))) {\n errors.push(`release must be a version such as 3.9.0 (got ${JSON.stringify(input.release)})`);\n }\n if (input.navName !== undefined && (typeof input.navName !== 'string' || !input.navName.trim())) errors.push('navName must be a non-empty string');\n if (errors.length > 0) throw new TypeError(`defineBrandlabSiteSystemTests: ${errors.join('; ')}`);\n\n const tier = input.tier as SiteSystemTier;\n const release = input.release ?? BRANDLAB_CURRENT_RUNTIME_RELEASE.releaseVersion;\n const journeys = siteSystemJourneysFor(tier, release);\n const problems: SiteSystemJourneyPlan['problems'] = {};\n if (journeys.includes('C1') && money.length === 0) {\n problems.C1 = 'pages.money names no money page: C1 checks the first screen of each service page with the enquiry form';\n }\n if (journeys.includes('W9') && families.length === 0) {\n problems.W9 = 'pages.families names no page: W9 checks the URL variants of one built page per dynamic route family';\n }\n const quoteName = input.quoteName === undefined\n ? SITE_SYSTEM_QUOTE_NAME\n : input.quoteName instanceof RegExp\n ? input.quoteName\n : new RegExp(`^\\\\s*${input.quoteName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\s*$`, 'i');\n return {\n tier,\n release,\n journeys,\n home: pages.home,\n money,\n contact: pages.contact,\n families: [...new Set(families)],\n sampled: [...new Set([pages.home, ...money, ...(pages.contact ? [pages.contact] : [])])],\n desktopWidths,\n actionOrder: input.actionOrder ?? 'phone-first',\n quoteName,\n navName: input.navName ?? 'Main',\n menuName: input.menuName ?? 'Menu',\n navigationTimeoutMs: input.navigationTimeoutMs ?? 45_000,\n settleTimeoutMs: input.settleTimeoutMs ?? 10_000,\n maxTabStops: input.maxTabStops ?? 400,\n problems,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/site-system/journeys/plan.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,gCAAgC,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,2BAA2B,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,qBAAqB,EAAuB,MAAM,cAAc,CAAC;AAKjH,+DAA+D;AAC/D,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAmD,CAAC,CAAC;AAEvL,wHAAwH;AACxH,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AACxF,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AACrF,MAAM,CAAC,MAAM,4BAA4B,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AAExF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,sBAAsB,GAAG,YAAY,CAAC;AA8DnD,MAAM,UAAU,sBAAsB,CAAC,EAAuB,EAAE,IAAY;IAC1E,OAAO,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAoB,EAAE,UAAkB,gCAAgC,CAAC,cAAc;IAC3H,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAyC,kBAAkB,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACnK,OAAO,uBAAuB,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;QAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/B,OAAO,KAAK,KAAK,SAAS;eACrB,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,IAAsB,CAAC,IAAI,IAAI;eAC/D,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,WAAiE;IACxG,OAAO,8BAA8B,CAAC,WAAW,CAAC,IAAI,2BAA2B,CAAC,WAAW,CAAC,EAAE,OAAO,IAAI,gCAAgC,CAAC,cAAc,CAAC;AAC7J,CAAC;AAED,SAAS,WAAW,CAAC,KAAa,EAAE,IAAa;IAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAClG,OAAO,GAAG,KAAK,+CAA+C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;IACxF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,8BAA8B,CAAC,OAAsC;IACnF,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,CAAC,OAAO,IAAI,EAAE,CAA2C,CAAC;IACxE,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAsB,CAAC,EAAE,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,uBAAuB,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzG,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAK,EAA6C,CAAC;IAC5E,MAAM,WAAW,GAAG,WAAW,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,WAAW;QAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAClH,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,OAAO,GAAG,WAAW,CAAC,eAAe,KAAK,GAAG,EAAE,IAAI,CAAC,CAAC;QAC3D,IAAI,OAAO;YAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,WAAW,CAAC,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5D,IAAI,OAAO;YAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IACjI,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC/B,MAAM,OAAO,GAAG,WAAW,CAAC,kBAAkB,KAAK,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,kBAAkB,KAAK,uDAAuD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpN,IAAI,OAAO;YAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,0BAA0B,CAAC,CAAC;IAC/G,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI;YAAE,MAAM,CAAC,IAAI,CAAC,mEAAmE,KAAK,GAAG,CAAC,CAAC;IACzJ,CAAC;IACD,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,KAAK,aAAa,IAAI,KAAK,CAAC,WAAW,KAAK,aAAa,EAAE,CAAC;QAClH,MAAM,CAAC,IAAI,CAAC,uDAAuD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC3G,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,CAAC,qBAAqB,EAAE,iBAAiB,EAAE,aAAa,CAAU,EAAE,CAAC;QACrF,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,yCAAyC,KAAK,GAAG,CAAC,CAAC;IAC5I,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,kCAAkC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QAClI,MAAM,CAAC,IAAI,CAAC,mEAAmE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnH,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;IACnJ,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,kCAAkC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAElG,MAAM,IAAI,GAAG,KAAK,CAAC,IAAsB,CAAC;IAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,gCAAgC,CAAC,cAAc,CAAC;IACjF,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAsC,EAAE,CAAC;IACvD,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,QAAQ,CAAC,EAAE,GAAG,wGAAwG,CAAC;IACzH,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,QAAQ,CAAC,EAAE,GAAG,qGAAqG,CAAC;IACtH,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,KAAK,SAAS;QAC7C,CAAC,CAAC,sBAAsB;QACxB,CAAC,CAAC,KAAK,CAAC,SAAS,YAAY,MAAM;YACjC,CAAC,CAAC,KAAK,CAAC,SAAS;YACjB,CAAC,CAAC,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7F,OAAO;QACL,IAAI;QACJ,OAAO;QACP,QAAQ;QACR,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK;QACL,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChC,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxF,aAAa;QACb,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,aAAa;QAC/C,SAAS;QACT,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,MAAM;QAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,MAAM;QAClC,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,IAAI,MAAM;QACxD,eAAe,EAAE,KAAK,CAAC,eAAe,IAAI,MAAM;QAChD,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,GAAG;QACrC,QAAQ;KACT,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Options and planning for the site-system journeys: which journeys a tier registers, the sampled pages and the\n * defaults. Pure, so it is unit-tested without a browser.\n */\nimport { BRANDLAB_CURRENT_RUNTIME_RELEASE } from '../../current-release.js';\nimport { detectBrandlabCanaryRelease, detectInstalledBrandlabRelease } from '../../project.js';\nimport { SITE_SYSTEM_CHECKS, SITE_SYSTEM_TIERS, siteSystemReleaseRank, type SiteSystemTier } from '../checks.js';\n\ntype JourneyCheck = Extract<(typeof SITE_SYSTEM_CHECKS)[number], { kind: 'journey' }>;\nexport type SiteSystemJourneyId = JourneyCheck['id'];\n\n/** Every journey check, in the order the journeys register. */\nexport const SITE_SYSTEM_JOURNEY_IDS = Object.freeze(['N3', 'N4', 'N5', 'N6', 'N8', 'K3', 'K4', 'K5', 'K6', 'C4', 'W2', 'C1', 'W9'] as const satisfies readonly SiteSystemJourneyId[]);\n\n/** Desktop widths for N6: both ends and the middle of the compact band, the desktop breakpoint and two wide screens. */\nexport const SITE_SYSTEM_DESKTOP_WIDTHS = Object.freeze([1024, 1100, 1280, 1440, 1920]);\nexport const SITE_SYSTEM_PHONE_VIEWPORT = Object.freeze({ width: 390, height: 844 });\nexport const SITE_SYSTEM_DESKTOP_VIEWPORT = Object.freeze({ width: 1440, height: 900 });\n\n/** The quote action's accessible name when the site does not record one. */\nexport const SITE_SYSTEM_QUOTE_NAME = /\\bquote\\b/i;\n\nexport type SiteSystemActionOrder = 'phone-first' | 'quote-first';\n\nexport interface BrandlabSiteSystemTestOptions {\n /** The adoption tier from brandlab.config.ts (`siteSystem.tier`). C1 registers from `enquiry`. */\n tier: SiteSystemTier;\n /**\n * The release whose journeys register. `defineBrandlabSiteSystemTests` defaults it to the site's installed Brandlab\n * release, read from its package.json as `brandlab-ready` reads it (one exact version, or one canary such as\n * `3.15.0-canary.2`), else this conformance release. A journey registers only from the release that brings it, so a\n * later journey never turns a site's e2e run red before the gate blocks on it, and a check that blocks has its\n * journey. Name a later release to preview its journeys.\n */\n release?: string;\n /**\n * The sampled pages: home, the money pages (service pages with the enquiry form) and the contact page. `families`\n * (W9, full tier from 3.13.0) names one built page per dynamic route family, such as `/services/blocked-drains` and\n * `/locations/ryde`: its URL variants are checked.\n */\n pages: { home: string; money?: string | readonly string[]; contact?: string; families?: string | readonly string[] };\n /** Desktop widths for N6, each 1024 px or more (default 1024, 1100, 1280, 1440 and 1920). */\n desktopWidths?: readonly number[];\n /** The recorded order of the phone and quote actions (K6), default `phone-first`. */\n actionOrder?: SiteSystemActionOrder;\n /** The quote action's accessible name (default /\\bquote\\b/i), for a recorded label such as \"Book an inspection\". */\n quoteName?: string | RegExp;\n /** The main menu's accessible name (default \"Main\"). */\n navName?: string;\n /** The phone menu button's accessible name (default \"Menu\"). */\n menuName?: string | RegExp;\n /** How long a document may take to load, default 45 seconds; a timeout is retried once. */\n navigationTimeoutMs?: number;\n /** How long to wait for the network to settle after a load, default 10 seconds; a busy network is not a failure. */\n settleTimeoutMs?: number;\n /** The most Tab presses K5 makes on one page (default 400); a longer page is reported, not failed. */\n maxTabStops?: number;\n}\n\nexport interface SiteSystemJourneyPlan {\n tier: SiteSystemTier;\n release: string;\n journeys: readonly SiteSystemJourneyId[];\n home: string;\n money: readonly string[];\n contact: string | undefined;\n /** One page per dynamic route family, for W9's URL variants. */\n families: readonly string[];\n /** Home, the money pages and the contact page, without repeats: K5, K6 and C4 run on each. */\n sampled: readonly string[];\n desktopWidths: readonly number[];\n actionOrder: SiteSystemActionOrder;\n quoteName: RegExp;\n navName: string;\n menuName: string | RegExp;\n navigationTimeoutMs: number;\n settleTimeoutMs: number;\n maxTabStops: number;\n /** Gaps that fail a journey when it runs (fail closed), rather than stopping the whole spec file. */\n problems: Partial<Record<SiteSystemJourneyId, string>>;\n}\n\nexport function siteSystemJourneyTitle(id: SiteSystemJourneyId, text: string): string {\n return `[${id}] ${text}`;\n}\n\n/**\n * The journey checks a tier registers on a release: its own and the tiers below it, each from the release that brings\n * it (default: this conformance release).\n */\nexport function siteSystemJourneysFor(tier: SiteSystemTier, release: string = BRANDLAB_CURRENT_RUNTIME_RELEASE.releaseVersion): SiteSystemJourneyId[] {\n const rank = SITE_SYSTEM_TIERS.indexOf(tier);\n const releaseRank = siteSystemReleaseRank(release);\n const journeys = new Map<string, { tier: string; from: string }>(SITE_SYSTEM_CHECKS.filter((check) => check.kind === 'journey').map((check) => [check.id, check]));\n return SITE_SYSTEM_JOURNEY_IDS.filter((id) => {\n const check = journeys.get(id);\n return check !== undefined\n && SITE_SYSTEM_TIERS.indexOf(check.tier as SiteSystemTier) <= rank\n && siteSystemReleaseRank(check.from) <= releaseRank;\n });\n}\n\n/**\n * The release the journeys register for on a site: its installed Brandlab release as `brandlab-ready` reads it (all\n * four packages at one exact version, or one canary, from package.json), else this conformance release. A canary's\n * own release manifest still names the last published release, so without this its new journeys (W2 and W9 on\n * 3.15.0-canary.2) would not register while the gate blocks on them.\n */\nexport function siteSystemJourneyRelease(packageJson: Parameters<typeof detectInstalledBrandlabRelease>[0]): string {\n return detectInstalledBrandlabRelease(packageJson) ?? detectBrandlabCanaryRelease(packageJson)?.version ?? BRANDLAB_CURRENT_RUNTIME_RELEASE.releaseVersion;\n}\n\nfunction pathProblem(label: string, path: unknown): string | null {\n if (typeof path !== 'string' || !path.startsWith('/') || path.startsWith('//') || /\\s/.test(path)) {\n return `${label} must be a site path starting with \"/\" (got ${JSON.stringify(path)})`;\n }\n return null;\n}\n\n/** Validate the options and fill the defaults. Malformed options throw, listing every problem. */\nexport function planBrandlabSiteSystemJourneys(options: BrandlabSiteSystemTestOptions): SiteSystemJourneyPlan {\n const errors: string[] = [];\n const input = (options ?? {}) as Partial<BrandlabSiteSystemTestOptions>;\n if (!SITE_SYSTEM_TIERS.includes(input.tier as SiteSystemTier)) {\n errors.push(`tier must be one of ${SITE_SYSTEM_TIERS.join(', ')} (got ${JSON.stringify(input.tier)})`);\n }\n const pages = input.pages ?? ({} as BrandlabSiteSystemTestOptions['pages']);\n const homeProblem = pathProblem('pages.home', pages.home);\n if (homeProblem) errors.push(homeProblem);\n const money = pages.money === undefined ? [] : typeof pages.money === 'string' ? [pages.money] : [...pages.money];\n money.forEach((path, index) => {\n const problem = pathProblem(`pages.money[${index}]`, path);\n if (problem) errors.push(problem);\n });\n if (pages.contact !== undefined) {\n const problem = pathProblem('pages.contact', pages.contact);\n if (problem) errors.push(problem);\n }\n const families = pages.families === undefined ? [] : typeof pages.families === 'string' ? [pages.families] : [...pages.families];\n families.forEach((path, index) => {\n const problem = pathProblem(`pages.families[${index}]`, path) ?? (/[?#]/.test(path) || path === '/' ? `pages.families[${index}] must be a page path below home with no query (got ${JSON.stringify(path)})` : null);\n if (problem) errors.push(problem);\n });\n const desktopWidths = input.desktopWidths?.length ? [...input.desktopWidths] : [...SITE_SYSTEM_DESKTOP_WIDTHS];\n for (const width of desktopWidths) {\n if (!Number.isInteger(width) || width < 1024 || width > 3840) errors.push(`desktopWidths must be whole pixel widths from 1024 to 3840 (got ${width})`);\n }\n if (input.actionOrder !== undefined && input.actionOrder !== 'phone-first' && input.actionOrder !== 'quote-first') {\n errors.push(`actionOrder must be phone-first or quote-first (got ${JSON.stringify(input.actionOrder)})`);\n }\n for (const key of ['navigationTimeoutMs', 'settleTimeoutMs', 'maxTabStops'] as const) {\n const value = input[key];\n if (value !== undefined && (!Number.isInteger(value) || value <= 0)) errors.push(`${key} must be a positive whole number (got ${value})`);\n }\n if (input.release !== undefined && (typeof input.release !== 'string' || !/^\\d+\\.\\d+\\.\\d+(?:-canary\\.\\d+)?$/.test(input.release))) {\n errors.push(`release must be a version such as 3.9.0 or 3.15.0-canary.2 (got ${JSON.stringify(input.release)})`);\n }\n if (input.navName !== undefined && (typeof input.navName !== 'string' || !input.navName.trim())) errors.push('navName must be a non-empty string');\n if (errors.length > 0) throw new TypeError(`defineBrandlabSiteSystemTests: ${errors.join('; ')}`);\n\n const tier = input.tier as SiteSystemTier;\n const release = input.release ?? BRANDLAB_CURRENT_RUNTIME_RELEASE.releaseVersion;\n const journeys = siteSystemJourneysFor(tier, release);\n const problems: SiteSystemJourneyPlan['problems'] = {};\n if (journeys.includes('C1') && money.length === 0) {\n problems.C1 = 'pages.money names no money page: C1 checks the first screen of each service page with the enquiry form';\n }\n if (journeys.includes('W9') && families.length === 0) {\n problems.W9 = 'pages.families names no page: W9 checks the URL variants of one built page per dynamic route family';\n }\n const quoteName = input.quoteName === undefined\n ? SITE_SYSTEM_QUOTE_NAME\n : input.quoteName instanceof RegExp\n ? input.quoteName\n : new RegExp(`^\\\\s*${input.quoteName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\s*$`, 'i');\n return {\n tier,\n release,\n journeys,\n home: pages.home,\n money,\n contact: pages.contact,\n families: [...new Set(families)],\n sampled: [...new Set([pages.home, ...money, ...(pages.contact ? [pages.contact] : [])])],\n desktopWidths,\n actionOrder: input.actionOrder ?? 'phone-first',\n quoteName,\n navName: input.navName ?? 'Main',\n menuName: input.menuName ?? 'Menu',\n navigationTimeoutMs: input.navigationTimeoutMs ?? 45_000,\n settleTimeoutMs: input.settleTimeoutMs ?? 10_000,\n maxTabStops: input.maxTabStops ?? 400,\n problems,\n };\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* N6 and N8: the header at every desktop width, and the phone drawer and call bar. The header stays at the top with a
|
|
3
3
|
* readable phone and the quote action from 1024 px up; the drawer is a modal dialog that starts on its close button,
|
|
4
|
-
* keeps focus, closes on Escape, a link tap and a widening past
|
|
4
|
+
* keeps focus, closes on Escape, a link tap and a widening past the 1200 px desktop breakpoint; the call bar's phone reports `fab`.
|
|
5
5
|
*/
|
|
6
6
|
import { type Locator, type Page } from '@playwright/test';
|
|
7
7
|
import { type SiteSystemJourneyPlan } from './plan.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* N6 and N8: the header at every desktop width, and the phone drawer and call bar. The header stays at the top with a
|
|
3
3
|
* readable phone and the quote action from 1024 px up; the drawer is a modal dialog that starts on its close button,
|
|
4
|
-
* keeps focus, closes on Escape, a link tap and a widening past
|
|
4
|
+
* keeps focus, closes on Escape, a link tap and a widening past the 1200 px desktop breakpoint; the call bar's phone reports `fab`.
|
|
5
5
|
*/
|
|
6
6
|
import { expect, test } from '@playwright/test';
|
|
7
7
|
import { SITE_SYSTEM_AXE_TAGS, describeAxe, mainNavigation, note, openSitePage, raiseTimeout, runAxe, seriousOrCritical, settle, siteHeader, waitUntil, } from './browser.js';
|
|
@@ -244,7 +244,7 @@ export function defineShellJourneys(plan, runs) {
|
|
|
244
244
|
await page.waitForTimeout(300);
|
|
245
245
|
button = menuButton(await siteHeader(page), plan);
|
|
246
246
|
}
|
|
247
|
-
expect(await button.count(), `no visible "${String(plan.menuName)}" button below
|
|
247
|
+
expect(await button.count(), `no visible "${String(plan.menuName)}" button below 1200 px`).toBe(1);
|
|
248
248
|
expect(await openDrawer(page, button, 'click'), 'the Menu button showed no dialog').not.toBeNull();
|
|
249
249
|
await page.setViewportSize({ width: 1440, height: 800 });
|
|
250
250
|
await page.waitForTimeout(400);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../../src/site-system/journeys/shell.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * N6 and N8: the header at every desktop width, and the phone drawer and call bar. The header stays at the top with a\n * readable phone and the quote action from 1024 px up; the drawer is a modal dialog that starts on its close button,\n * keeps focus, closes on Escape, a link tap and a widening past 1280 px; the call bar's phone reports `fab`.\n */\nimport { expect, test, type Locator, type Page } from '@playwright/test';\nimport {\n SITE_SYSTEM_AXE_TAGS,\n describeAxe,\n mainNavigation,\n note,\n openSitePage,\n raiseTimeout,\n runAxe,\n seriousOrCritical,\n settle,\n siteHeader,\n waitUntil,\n} from './browser.js';\nimport { SITE_SYSTEM_PHONE_VIEWPORT, siteSystemJourneyTitle as title, type SiteSystemJourneyPlan } from './plan.js';\n\n/** The visible phone menu button in the header. */\nexport function menuButton(header: Locator, plan: Pick<SiteSystemJourneyPlan, 'menuName'>): Locator {\n const name = plan.menuName;\n return header.getByRole('button', typeof name === 'string' ? { name, exact: true } : { name }).filter({ visible: true }).first();\n}\n\n/** The drawer the menu button opens: the element its aria-controls names, else the visible dialog. Marked `drawer`. */\nexport async function openDrawer(page: Page, button: Locator, how: 'tap' | 'click'): Promise<Locator | null> {\n await (how === 'tap' ? button.tap() : button.click());\n const controls = (await button.getAttribute('aria-controls'))?.trim();\n const named = controls ? page.locator(`[id=\"${controls.replace(/[\"\\\\]/g, '\\\\$&')}\"]`) : null;\n const drawer = named && (await named.count()) === 1 ? named : page.getByRole('dialog').filter({ visible: true }).first();\n if (!(await waitUntil(async () => (await drawer.count()) > 0 && (await drawer.isVisible()), 1_000))) return null;\n await page.waitForTimeout(250);\n await drawer.evaluate((element) => window.__brandlabSiteSystem.markElement(element, 'drawer'));\n return drawer;\n}\n\n/** Whether any dialog is still open or shown. */\nexport async function anyDialogOpen(page: Page): Promise<boolean> {\n return page.evaluate(() => Array.from(document.querySelectorAll('dialog')).some((dialog) => dialog.open)\n || Array.from(document.querySelectorAll('[role=\"dialog\"]')).some((dialog) => window.__brandlabSiteSystem.isRendered(dialog)));\n}\n\n/**\n * Scroll a phone page down past its hero, half a screen at a time, until a call bar shows; return its phone links,\n * or null when none shows before the end of the page.\n */\nexport async function callBarLinks(page: Page): Promise<{ description: string; placement: string; invalid: string | null }[] | null> {\n let previous = -1;\n for (let screens = 1; screens <= 8; screens += 0.5) {\n const scrolled = await page.evaluate((factor) => {\n window.scrollTo({ top: window.innerHeight * factor, behavior: 'instant' });\n return window.scrollY;\n }, screens);\n if (scrolled === previous) return null;\n previous = scrolled;\n await page.waitForTimeout(250);\n const links = await page.evaluate(() => {\n const helpers = window.__brandlabSiteSystem;\n const bar = helpers.findCallBar();\n if (!bar) return null;\n helpers.markElement(bar, 'call-bar');\n return Array.from(bar.querySelectorAll('a[href^=\"tel:\"]')).filter(helpers.isRendered)\n .map((link) => ({ description: helpers.describeElement(link), ...helpers.phonePlacement(link) }));\n });\n if (links) return links;\n }\n return null;\n}\n\nexport function defineShellJourneys(plan: SiteSystemJourneyPlan, runs: ReadonlySet<string>): void {\n const quote = { source: plan.quoteName.source, flags: plan.quoteName.flags };\n\n if (runs.has('N6')) {\n test.describe('header at desktop widths', () => {\n for (const width of plan.desktopWidths) {\n test(title('N6', `the header stays at the top with the phone and quote visible at ${width} px`), async ({ page }, testInfo) => {\n await page.setViewportSize({ width, height: 900 });\n await openSitePage(page, plan.home, plan);\n const header = await siteHeader(page);\n expect(await header.count(), `${plan.home} has no header (a <header> banner landmark)`).toBe(1);\n const problems: string[] = [];\n const inspect = async (moment: string) => {\n const seen = await header.evaluate((element, name) => {\n const helpers = window.__brandlabSiteSystem;\n const inView = (node: Element) => {\n const rect = node.getBoundingClientRect();\n return rect.top >= -1 && rect.bottom <= window.innerHeight + 1;\n };\n const phones = Array.from(element.querySelectorAll('a[href^=\"tel:\"]')).filter(helpers.isRendered);\n const readable = phones.filter((link) => ((link as HTMLElement).innerText.match(/\\d/g) ?? []).length >= 6 && inView(link));\n return { phones: phones.length, readable: readable.length, quotes: helpers.quoteActions(element, name).filter(inView).length };\n }, quote);\n if (seen.readable === 0) problems.push(`${moment}: no phone number is readable in the header (${seen.phones} phone link(s) without the number)`);\n if (seen.quotes === 0) problems.push(`${moment}: no quote action is visible in the header`);\n };\n await inspect('at the top');\n const nav = await mainNavigation(page, plan);\n if (!nav && !(await menuButton(header, plan).count())) problems.push(`neither the menu named \"${plan.navName}\" nor a Menu button is visible`);\n const scrolled = await page.evaluate(() => {\n window.scrollTo({ top: 2_000, behavior: 'instant' });\n return window.scrollY;\n });\n await page.waitForTimeout(300);\n if (scrolled < 400) note(testInfo, `${plan.home} at ${width} px scrolls only ${scrolled} px, too little to show whether the header stays at the top`);\n const top = await header.evaluate((element) => Math.round(element.getBoundingClientRect().top));\n if (scrolled > 0 && Math.abs(top) > 1) problems.push(`after scrolling ${scrolled} px the header's top is at ${top} px (expected 0: keep it sticky)`);\n if (scrolled > 0) await inspect(`after scrolling ${scrolled} px`);\n const overflow = await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth);\n if (overflow > 0) problems.push(`the page scrolls sideways by ${overflow} px`);\n expect(problems).toEqual([]);\n });\n }\n });\n }\n\n if (!runs.has('N8')) return;\n\n test.describe('phone drawer and call bar at 390 px', () => {\n test.use({ viewport: { ...SITE_SYSTEM_PHONE_VIEWPORT }, isMobile: true, hasTouch: true });\n\n test(title('N8', 'the Menu button opens a modal drawer that starts on its close button, keeps focus inside and closes on Escape'), async ({ page }, testInfo) => {\n await openSitePage(page, plan.home, plan);\n const header = await siteHeader(page);\n const button = menuButton(header, plan);\n expect(await button.count(), `no visible \"${String(plan.menuName)}\" button in the header at 390 px`).toBe(1);\n const drawer = await openDrawer(page, button, 'tap');\n expect(drawer, 'tapping the Menu button showed no dialog').not.toBeNull();\n const problems: string[] = [];\n const facts = await drawer!.evaluate((element) => ({\n modal: (element instanceof HTMLDialogElement && element.matches(':modal')) || element.getAttribute('aria-modal') === 'true',\n focus: element.contains(document.activeElement) ? window.__brandlabSiteSystem.accessibleName(document.activeElement!) : null,\n }));\n if (!facts.modal) problems.push('the drawer is not a modal dialog (showModal() or aria-modal=\"true\")');\n if (facts.focus === null) problems.push('focus did not move into the drawer');\n else if (!/close/i.test(facts.focus)) problems.push(`focus starts on \"${facts.focus}\", not the close button`);\n\n const groups = drawer!.locator('button[aria-expanded], summary').filter({ visible: true });\n const groupCount = await groups.count();\n if (groupCount > 0) {\n await groups.nth(0).tap();\n if (groupCount > 1) await groups.nth(1).tap();\n await page.waitForTimeout(150);\n const expanded = await drawer!.evaluate((element) => element.querySelectorAll('button[aria-expanded=\"true\"]').length + element.querySelectorAll('details[open]').length);\n if (expanded !== 1) problems.push(`opening drawer groups left ${expanded} open (one at a time)`);\n } else note(testInfo, 'The drawer has no groups.');\n\n const escaped: string[] = [];\n for (let press = 0; press < 40; press += 1) {\n await page.keyboard.press('Tab');\n const outside = await drawer!.evaluate((element) => {\n const active = document.activeElement;\n if (!active || active === document.body || element.contains(active)) return null;\n return window.__brandlabSiteSystem.describeElement(active);\n });\n if (outside) escaped.push(outside);\n }\n if (escaped.length) problems.push(`Tab moved focus out of the drawer to ${[...new Set(escaped)].slice(0, 3).join(', ')}`);\n await page.keyboard.press('Escape');\n await page.waitForTimeout(300);\n if (await anyDialogOpen(page)) problems.push('Escape did not close the drawer');\n expect(problems).toEqual([]);\n });\n\n test(title('N8', 'axe finds no serious or critical issue with the drawer open'), async ({ page }) => {\n await openSitePage(page, plan.home, plan);\n const drawer = await openDrawer(page, menuButton(await siteHeader(page), plan), 'tap');\n expect(drawer, 'tapping the Menu button showed no dialog').not.toBeNull();\n const outcome = await runAxe(page, ['[data-brandlab-journey~=\"drawer\"]'], { tags: SITE_SYSTEM_AXE_TAGS });\n expect(describeAxe(seriousOrCritical(outcome.violations))).toEqual([]);\n });\n\n test(title('N8', 'a link tap in the drawer closes it and loads the page'), async ({ page }) => {\n await openSitePage(page, plan.home, plan);\n const drawer = await openDrawer(page, menuButton(await siteHeader(page), plan), 'tap');\n expect(drawer, 'tapping the Menu button showed no dialog').not.toBeNull();\n const href = await drawer!.evaluate((element) => {\n const link = Array.from(element.querySelectorAll<HTMLAnchorElement>('a[href]')).find((anchor) => window.__brandlabSiteSystem.isRendered(anchor)\n && anchor.origin === location.origin && anchor.pathname !== location.pathname);\n if (!link) return null;\n window.__brandlabSiteSystem.markElement(link, 'drawer-link');\n return link.pathname;\n });\n expect(href, 'the open drawer shows no link to another page').not.toBeNull();\n await page.locator('[data-brandlab-journey~=\"drawer-link\"]').tap();\n await page.waitForURL((url) => url.pathname === href, { timeout: plan.navigationTimeoutMs });\n await settle(page, plan.settleTimeoutMs);\n expect(await anyDialogOpen(page), `the drawer is still open on ${href}`).toBe(false);\n });\n\n test(title('N8', 'the phone header shows a call control named with the number, and no page scrolls sideways at 390 px'), async ({ page }, testInfo) => {\n raiseTimeout(testInfo, 180_000);\n const problems: string[] = [];\n for (const path of plan.sampled) {\n await openSitePage(page, path, plan);\n await siteHeader(page);\n // Against the device width: a phone browser widens its layout viewport (and innerWidth) to overflowing content.\n const seen = await page.evaluate((width) => {\n const helpers = window.__brandlabSiteSystem;\n const header = document.querySelector('[data-brandlab-journey~=\"header\"]');\n const calls = Array.from(header?.querySelectorAll('a[href^=\"tel:\"]') ?? []).filter(helpers.isRendered)\n .map((link) => ({ description: helpers.describeElement(link), digits: (helpers.accessibleName(link).match(/\\d/g) ?? []).length }));\n return { calls, overflow: document.documentElement.scrollWidth - width };\n }, SITE_SYSTEM_PHONE_VIEWPORT.width);\n if (seen.calls.length === 0) problems.push(`${path}: the phone header shows no call control`);\n for (const call of seen.calls) {\n if (call.digits < 6) problems.push(`${path}: the header's ${call.description} is not named with the phone number`);\n }\n if (seen.overflow > 0) problems.push(`${path}: the page scrolls sideways by ${seen.overflow} px at 390 px`);\n }\n note(testInfo, `Checked ${plan.sampled.join(', ')}`);\n expect(problems).toEqual([]);\n });\n\n test(title('N8', 'the call bar\\'s phone reports placement fab'), async ({ page }, testInfo) => {\n raiseTimeout(testInfo, 180_000);\n const problems: string[] = [];\n for (const path of [plan.home, ...plan.money]) {\n await openSitePage(page, path, plan);\n const links = await callBarLinks(page);\n if (!links) {\n note(testInfo, `${path}: no call bar showed after scrolling.`);\n continue;\n }\n if (links.length === 0) problems.push(`${path}: the call bar shows no phone link`);\n for (const link of links) {\n if (link.placement !== 'fab' || link.invalid) problems.push(`${path}: ${link.description} reports placement ${link.placement}${link.invalid ? ` (it declares \"${link.invalid}\")` : ''}, not fab`);\n }\n }\n expect(problems).toEqual([]);\n });\n });\n\n test.describe('drawer across the desktop breakpoint', () => {\n test(title('N8', 'widening past 1280 px closes the drawer and leaves the page usable'), async ({ page }) => {\n await page.setViewportSize({ width: 1100, height: 800 });\n await openSitePage(page, plan.home, plan);\n let button = menuButton(await siteHeader(page), plan);\n if (!(await button.count())) {\n await page.setViewportSize({ ...SITE_SYSTEM_PHONE_VIEWPORT });\n await page.waitForTimeout(300);\n button = menuButton(await siteHeader(page), plan);\n }\n expect(await button.count(), `no visible \"${String(plan.menuName)}\" button below 1280 px`).toBe(1);\n expect(await openDrawer(page, button, 'click'), 'the Menu button showed no dialog').not.toBeNull();\n await page.setViewportSize({ width: 1440, height: 800 });\n await page.waitForTimeout(400);\n const problems: string[] = [];\n if (await anyDialogOpen(page)) problems.push('the drawer stayed open at 1440 px');\n const usable = await page.evaluate(() => {\n const hit = document.elementFromPoint(window.innerWidth / 2, window.innerHeight * 0.75);\n const locked = [document.documentElement, document.body].some((element) => getComputedStyle(element).overflowY === 'hidden');\n return { covered: Boolean(hit?.closest('dialog, [role=\"dialog\"]')), inert: document.body.inert || Boolean(document.querySelector('main')?.closest('[inert]')), locked };\n });\n if (usable.covered) problems.push('a dialog still covers the page at 1440 px');\n if (usable.inert) problems.push('the page is still inert at 1440 px');\n if (usable.locked) problems.push('page scrolling is still locked at 1440 px');\n expect(problems).toEqual([]);\n });\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../../src/site-system/journeys/shell.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * N6 and N8: the header at every desktop width, and the phone drawer and call bar. The header stays at the top with a\n * readable phone and the quote action from 1024 px up; the drawer is a modal dialog that starts on its close button,\n * keeps focus, closes on Escape, a link tap and a widening past the 1200 px desktop breakpoint; the call bar's phone reports `fab`.\n */\nimport { expect, test, type Locator, type Page } from '@playwright/test';\nimport {\n SITE_SYSTEM_AXE_TAGS,\n describeAxe,\n mainNavigation,\n note,\n openSitePage,\n raiseTimeout,\n runAxe,\n seriousOrCritical,\n settle,\n siteHeader,\n waitUntil,\n} from './browser.js';\nimport { SITE_SYSTEM_PHONE_VIEWPORT, siteSystemJourneyTitle as title, type SiteSystemJourneyPlan } from './plan.js';\n\n/** The visible phone menu button in the header. */\nexport function menuButton(header: Locator, plan: Pick<SiteSystemJourneyPlan, 'menuName'>): Locator {\n const name = plan.menuName;\n return header.getByRole('button', typeof name === 'string' ? { name, exact: true } : { name }).filter({ visible: true }).first();\n}\n\n/** The drawer the menu button opens: the element its aria-controls names, else the visible dialog. Marked `drawer`. */\nexport async function openDrawer(page: Page, button: Locator, how: 'tap' | 'click'): Promise<Locator | null> {\n await (how === 'tap' ? button.tap() : button.click());\n const controls = (await button.getAttribute('aria-controls'))?.trim();\n const named = controls ? page.locator(`[id=\"${controls.replace(/[\"\\\\]/g, '\\\\$&')}\"]`) : null;\n const drawer = named && (await named.count()) === 1 ? named : page.getByRole('dialog').filter({ visible: true }).first();\n if (!(await waitUntil(async () => (await drawer.count()) > 0 && (await drawer.isVisible()), 1_000))) return null;\n await page.waitForTimeout(250);\n await drawer.evaluate((element) => window.__brandlabSiteSystem.markElement(element, 'drawer'));\n return drawer;\n}\n\n/** Whether any dialog is still open or shown. */\nexport async function anyDialogOpen(page: Page): Promise<boolean> {\n return page.evaluate(() => Array.from(document.querySelectorAll('dialog')).some((dialog) => dialog.open)\n || Array.from(document.querySelectorAll('[role=\"dialog\"]')).some((dialog) => window.__brandlabSiteSystem.isRendered(dialog)));\n}\n\n/**\n * Scroll a phone page down past its hero, half a screen at a time, until a call bar shows; return its phone links,\n * or null when none shows before the end of the page.\n */\nexport async function callBarLinks(page: Page): Promise<{ description: string; placement: string; invalid: string | null }[] | null> {\n let previous = -1;\n for (let screens = 1; screens <= 8; screens += 0.5) {\n const scrolled = await page.evaluate((factor) => {\n window.scrollTo({ top: window.innerHeight * factor, behavior: 'instant' });\n return window.scrollY;\n }, screens);\n if (scrolled === previous) return null;\n previous = scrolled;\n await page.waitForTimeout(250);\n const links = await page.evaluate(() => {\n const helpers = window.__brandlabSiteSystem;\n const bar = helpers.findCallBar();\n if (!bar) return null;\n helpers.markElement(bar, 'call-bar');\n return Array.from(bar.querySelectorAll('a[href^=\"tel:\"]')).filter(helpers.isRendered)\n .map((link) => ({ description: helpers.describeElement(link), ...helpers.phonePlacement(link) }));\n });\n if (links) return links;\n }\n return null;\n}\n\nexport function defineShellJourneys(plan: SiteSystemJourneyPlan, runs: ReadonlySet<string>): void {\n const quote = { source: plan.quoteName.source, flags: plan.quoteName.flags };\n\n if (runs.has('N6')) {\n test.describe('header at desktop widths', () => {\n for (const width of plan.desktopWidths) {\n test(title('N6', `the header stays at the top with the phone and quote visible at ${width} px`), async ({ page }, testInfo) => {\n await page.setViewportSize({ width, height: 900 });\n await openSitePage(page, plan.home, plan);\n const header = await siteHeader(page);\n expect(await header.count(), `${plan.home} has no header (a <header> banner landmark)`).toBe(1);\n const problems: string[] = [];\n const inspect = async (moment: string) => {\n const seen = await header.evaluate((element, name) => {\n const helpers = window.__brandlabSiteSystem;\n const inView = (node: Element) => {\n const rect = node.getBoundingClientRect();\n return rect.top >= -1 && rect.bottom <= window.innerHeight + 1;\n };\n const phones = Array.from(element.querySelectorAll('a[href^=\"tel:\"]')).filter(helpers.isRendered);\n const readable = phones.filter((link) => ((link as HTMLElement).innerText.match(/\\d/g) ?? []).length >= 6 && inView(link));\n return { phones: phones.length, readable: readable.length, quotes: helpers.quoteActions(element, name).filter(inView).length };\n }, quote);\n if (seen.readable === 0) problems.push(`${moment}: no phone number is readable in the header (${seen.phones} phone link(s) without the number)`);\n if (seen.quotes === 0) problems.push(`${moment}: no quote action is visible in the header`);\n };\n await inspect('at the top');\n const nav = await mainNavigation(page, plan);\n if (!nav && !(await menuButton(header, plan).count())) problems.push(`neither the menu named \"${plan.navName}\" nor a Menu button is visible`);\n const scrolled = await page.evaluate(() => {\n window.scrollTo({ top: 2_000, behavior: 'instant' });\n return window.scrollY;\n });\n await page.waitForTimeout(300);\n if (scrolled < 400) note(testInfo, `${plan.home} at ${width} px scrolls only ${scrolled} px, too little to show whether the header stays at the top`);\n const top = await header.evaluate((element) => Math.round(element.getBoundingClientRect().top));\n if (scrolled > 0 && Math.abs(top) > 1) problems.push(`after scrolling ${scrolled} px the header's top is at ${top} px (expected 0: keep it sticky)`);\n if (scrolled > 0) await inspect(`after scrolling ${scrolled} px`);\n const overflow = await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth);\n if (overflow > 0) problems.push(`the page scrolls sideways by ${overflow} px`);\n expect(problems).toEqual([]);\n });\n }\n });\n }\n\n if (!runs.has('N8')) return;\n\n test.describe('phone drawer and call bar at 390 px', () => {\n test.use({ viewport: { ...SITE_SYSTEM_PHONE_VIEWPORT }, isMobile: true, hasTouch: true });\n\n test(title('N8', 'the Menu button opens a modal drawer that starts on its close button, keeps focus inside and closes on Escape'), async ({ page }, testInfo) => {\n await openSitePage(page, plan.home, plan);\n const header = await siteHeader(page);\n const button = menuButton(header, plan);\n expect(await button.count(), `no visible \"${String(plan.menuName)}\" button in the header at 390 px`).toBe(1);\n const drawer = await openDrawer(page, button, 'tap');\n expect(drawer, 'tapping the Menu button showed no dialog').not.toBeNull();\n const problems: string[] = [];\n const facts = await drawer!.evaluate((element) => ({\n modal: (element instanceof HTMLDialogElement && element.matches(':modal')) || element.getAttribute('aria-modal') === 'true',\n focus: element.contains(document.activeElement) ? window.__brandlabSiteSystem.accessibleName(document.activeElement!) : null,\n }));\n if (!facts.modal) problems.push('the drawer is not a modal dialog (showModal() or aria-modal=\"true\")');\n if (facts.focus === null) problems.push('focus did not move into the drawer');\n else if (!/close/i.test(facts.focus)) problems.push(`focus starts on \"${facts.focus}\", not the close button`);\n\n const groups = drawer!.locator('button[aria-expanded], summary').filter({ visible: true });\n const groupCount = await groups.count();\n if (groupCount > 0) {\n await groups.nth(0).tap();\n if (groupCount > 1) await groups.nth(1).tap();\n await page.waitForTimeout(150);\n const expanded = await drawer!.evaluate((element) => element.querySelectorAll('button[aria-expanded=\"true\"]').length + element.querySelectorAll('details[open]').length);\n if (expanded !== 1) problems.push(`opening drawer groups left ${expanded} open (one at a time)`);\n } else note(testInfo, 'The drawer has no groups.');\n\n const escaped: string[] = [];\n for (let press = 0; press < 40; press += 1) {\n await page.keyboard.press('Tab');\n const outside = await drawer!.evaluate((element) => {\n const active = document.activeElement;\n if (!active || active === document.body || element.contains(active)) return null;\n return window.__brandlabSiteSystem.describeElement(active);\n });\n if (outside) escaped.push(outside);\n }\n if (escaped.length) problems.push(`Tab moved focus out of the drawer to ${[...new Set(escaped)].slice(0, 3).join(', ')}`);\n await page.keyboard.press('Escape');\n await page.waitForTimeout(300);\n if (await anyDialogOpen(page)) problems.push('Escape did not close the drawer');\n expect(problems).toEqual([]);\n });\n\n test(title('N8', 'axe finds no serious or critical issue with the drawer open'), async ({ page }) => {\n await openSitePage(page, plan.home, plan);\n const drawer = await openDrawer(page, menuButton(await siteHeader(page), plan), 'tap');\n expect(drawer, 'tapping the Menu button showed no dialog').not.toBeNull();\n const outcome = await runAxe(page, ['[data-brandlab-journey~=\"drawer\"]'], { tags: SITE_SYSTEM_AXE_TAGS });\n expect(describeAxe(seriousOrCritical(outcome.violations))).toEqual([]);\n });\n\n test(title('N8', 'a link tap in the drawer closes it and loads the page'), async ({ page }) => {\n await openSitePage(page, plan.home, plan);\n const drawer = await openDrawer(page, menuButton(await siteHeader(page), plan), 'tap');\n expect(drawer, 'tapping the Menu button showed no dialog').not.toBeNull();\n const href = await drawer!.evaluate((element) => {\n const link = Array.from(element.querySelectorAll<HTMLAnchorElement>('a[href]')).find((anchor) => window.__brandlabSiteSystem.isRendered(anchor)\n && anchor.origin === location.origin && anchor.pathname !== location.pathname);\n if (!link) return null;\n window.__brandlabSiteSystem.markElement(link, 'drawer-link');\n return link.pathname;\n });\n expect(href, 'the open drawer shows no link to another page').not.toBeNull();\n await page.locator('[data-brandlab-journey~=\"drawer-link\"]').tap();\n await page.waitForURL((url) => url.pathname === href, { timeout: plan.navigationTimeoutMs });\n await settle(page, plan.settleTimeoutMs);\n expect(await anyDialogOpen(page), `the drawer is still open on ${href}`).toBe(false);\n });\n\n test(title('N8', 'the phone header shows a call control named with the number, and no page scrolls sideways at 390 px'), async ({ page }, testInfo) => {\n raiseTimeout(testInfo, 180_000);\n const problems: string[] = [];\n for (const path of plan.sampled) {\n await openSitePage(page, path, plan);\n await siteHeader(page);\n // Against the device width: a phone browser widens its layout viewport (and innerWidth) to overflowing content.\n const seen = await page.evaluate((width) => {\n const helpers = window.__brandlabSiteSystem;\n const header = document.querySelector('[data-brandlab-journey~=\"header\"]');\n const calls = Array.from(header?.querySelectorAll('a[href^=\"tel:\"]') ?? []).filter(helpers.isRendered)\n .map((link) => ({ description: helpers.describeElement(link), digits: (helpers.accessibleName(link).match(/\\d/g) ?? []).length }));\n return { calls, overflow: document.documentElement.scrollWidth - width };\n }, SITE_SYSTEM_PHONE_VIEWPORT.width);\n if (seen.calls.length === 0) problems.push(`${path}: the phone header shows no call control`);\n for (const call of seen.calls) {\n if (call.digits < 6) problems.push(`${path}: the header's ${call.description} is not named with the phone number`);\n }\n if (seen.overflow > 0) problems.push(`${path}: the page scrolls sideways by ${seen.overflow} px at 390 px`);\n }\n note(testInfo, `Checked ${plan.sampled.join(', ')}`);\n expect(problems).toEqual([]);\n });\n\n test(title('N8', 'the call bar\\'s phone reports placement fab'), async ({ page }, testInfo) => {\n raiseTimeout(testInfo, 180_000);\n const problems: string[] = [];\n for (const path of [plan.home, ...plan.money]) {\n await openSitePage(page, path, plan);\n const links = await callBarLinks(page);\n if (!links) {\n note(testInfo, `${path}: no call bar showed after scrolling.`);\n continue;\n }\n if (links.length === 0) problems.push(`${path}: the call bar shows no phone link`);\n for (const link of links) {\n if (link.placement !== 'fab' || link.invalid) problems.push(`${path}: ${link.description} reports placement ${link.placement}${link.invalid ? ` (it declares \"${link.invalid}\")` : ''}, not fab`);\n }\n }\n expect(problems).toEqual([]);\n });\n });\n\n test.describe('drawer across the desktop breakpoint', () => {\n test(title('N8', 'widening past 1280 px closes the drawer and leaves the page usable'), async ({ page }) => {\n await page.setViewportSize({ width: 1100, height: 800 });\n await openSitePage(page, plan.home, plan);\n let button = menuButton(await siteHeader(page), plan);\n if (!(await button.count())) {\n await page.setViewportSize({ ...SITE_SYSTEM_PHONE_VIEWPORT });\n await page.waitForTimeout(300);\n button = menuButton(await siteHeader(page), plan);\n }\n expect(await button.count(), `no visible \"${String(plan.menuName)}\" button below 1200 px`).toBe(1);\n expect(await openDrawer(page, button, 'click'), 'the Menu button showed no dialog').not.toBeNull();\n await page.setViewportSize({ width: 1440, height: 800 });\n await page.waitForTimeout(400);\n const problems: string[] = [];\n if (await anyDialogOpen(page)) problems.push('the drawer stayed open at 1440 px');\n const usable = await page.evaluate(() => {\n const hit = document.elementFromPoint(window.innerWidth / 2, window.innerHeight * 0.75);\n const locked = [document.documentElement, document.body].some((element) => getComputedStyle(element).overflowY === 'hidden');\n return { covered: Boolean(hit?.closest('dialog, [role=\"dialog\"]')), inert: document.body.inert || Boolean(document.querySelector('main')?.closest('[inert]')), locked };\n });\n if (usable.covered) problems.push('a dialog still covers the page at 1440 px');\n if (usable.inert) problems.push('the page is still inert at 1440 px');\n if (usable.locked) problems.push('page scrolling is still locked at 1440 px');\n expect(problems).toEqual([]);\n });\n });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/site-system/report.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/site-system/report.ts"],"names":[],"mappings":"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"}
|