view design_system/test/catalog_test.js @ 264:04fee26ecce0

add authenticated JRPG conversation platform Add reusable auth/session storage, owned conversation recovery, guest quotas, admin workflows, URL-routed conversation UI, mobile frame support, and parallel browser acceptance. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Fri, 07 Aug 2026 07:34:12 -0700
parents 667156fcd3e3
children
line wrap: on
line source

const assert = require('node:assert/strict');
const http = require('node:http');
const net = require('node:net');
const path = require('node:path');
const { spawn } = require('node:child_process');

const RUNFILES = process.env.JS_BINARY__RUNFILES;
const WORKSPACE = process.env.JS_BINARY__WORKSPACE;
const runfilesWorkspace = path.join(RUNFILES, WORKSPACE);
const playwrightPath = path.join(
  runfilesWorkspace,
  'hg-web/e2e/node_modules/playwright-core',
);
const { chromium } = require(playwrightPath);

function findFreePort() {
  return new Promise((resolve, reject) => {
    const server = net.createServer();
    server.once('error', reject);
    server.listen(0, '127.0.0.1', () => {
      const address = server.address();
      server.close(error => {
        if (error) reject(error);
        else resolve(String(address.port));
      });
    });
  });
}

async function stopProcess(child) {
  if (!child || child.exitCode !== null) return;
  child.kill('SIGTERM');
  await new Promise(resolve => {
    const timer = setTimeout(() => {
      if (child.exitCode === null) child.kill('SIGKILL');
    }, 3000);
    child.once('exit', () => {
      clearTimeout(timer);
      resolve();
    });
  });
}

async function waitForServer(server, baseUrl, logs) {
  const deadline = Date.now() + 15000;
  while (Date.now() < deadline) {
    if (server.exitCode !== null) {
      throw new Error(`Server exited with ${server.exitCode}\n${logs.join('')}`);
    }
    try {
      const response = await fetch(baseUrl);
      if (response.ok) return;
    } catch {
      // Keep waiting.
    }
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  throw new Error(`Server startup timed out\n${logs.join('')}`);
}

function requestRawPath(port, requestPath) {
  return new Promise((resolve, reject) => {
    const request = http.request({
      host: '127.0.0.1',
      port,
      method: 'GET',
      path: requestPath,
      agent: false,
    }, response => {
      response.resume();
      response.on('end', () => resolve(response.statusCode));
    });
    request.on('error', reject);
    request.end();
  });
}

(async () => {
  assert.ok(RUNFILES);
  assert.ok(WORKSPACE);
  const serverBinary = path.join(
    runfilesWorkspace,
    'design_system/design_system_server',
  );
  const chromiumPath = path.resolve(process.env.CHROMIUM_PATH);
  const port = await findFreePort();
  const baseUrl = `http://127.0.0.1:${port}`;
  const logs = [];
  let server;
  let browser;

  try {
    const invalidServer = spawn(serverBinary, [], {
      cwd: runfilesWorkspace,
      env: {
        ...process.env,
        DESIGN_SYSTEM_PORT: 'not-a-port',
      },
      stdio: ['ignore', 'pipe', 'pipe'],
    });
    const invalidExit = await new Promise(resolve => {
      invalidServer.once('exit', (code, signal) => resolve({ code, signal }));
    });
    assert.equal(invalidExit.code, 1);
    assert.equal(invalidExit.signal, null);

    server = spawn(serverBinary, [], {
      cwd: runfilesWorkspace,
      env: {
        ...process.env,
        DESIGN_SYSTEM_PORT: port,
      },
      stdio: ['ignore', 'pipe', 'pipe'],
    });
    server.stdout.on('data', chunk => logs.push(chunk.toString()));
    server.stderr.on('data', chunk => logs.push(chunk.toString()));
    await waitForServer(server, baseUrl, logs);
    assert.equal(await requestRawPath(port, '/../../MODULE.bazel'), 400);

    for (const route of [
      '/',
      '/tokens',
      '/icons',
      '/components',
      '/components/button',
      '/components/card',
      '/components/alert',
      '/components/field',
      '/components/notifications',
      '/components/stack',
    ]) {
      const response = await fetch(`${baseUrl}${route}`);
      assert.equal(response.status, 200, route);
      assert.match(
        response.headers.get('content-type') || '',
        /^text\/html/,
      );
    }
    for (const asset of [
      '/styles/tokens.css',
      '/styles/reference.css',
      '/styles/semantic.css',
      '/styles/density.css',
      '/styles/themes.css',
      '/styles/components.css',
      '/styles/elements.css',
      '/components/index.js',
      '/components/icon.js',
      '/catalog.js',
      '/catalog.js',
    ]) {
      const response = await fetch(`${baseUrl}${asset}`);
      assert.equal(response.status, 200, asset);
      assert.ok((await response.text()).length > 100, asset);
    }

    browser = await chromium.launch({
      executablePath: chromiumPath,
      headless: true,
      args: ['--no-sandbox'],
    });
    const context = await browser.newContext({ colorScheme: 'light' });
    const page = await context.newPage();
    const errors = [];
    const devtools = await context.newCDPSession(page);
    await devtools.send('Runtime.enable');
    devtools.on('Runtime.exceptionThrown', event => {
      const exception = event.exceptionDetails;
      errors.push(
        `${exception.text}: ${exception.exception?.description || ''} ` +
        `${exception.url || ''}:${exception.lineNumber + 1}`,
      );
    });
    page.on('pageerror', error => errors.push(error.stack || error.message));
    page.on('console', message => {
      if (message.type() === 'error') {
        const location = message.location();
        errors.push(
          `${message.text()} ${location.url || ''}:${location.lineNumber + 1}`,
        );
      }
    });
    page.on('response', response => {
      if (response.status() >= 400) {
        errors.push(`${response.status()} ${response.url()}`);
      }
    });

    await page.goto(`${baseUrl}/components/button`, {
      waitUntil: 'networkidle',
    });
    try {
      await page.waitForFunction(
        () => customElements.get('zen-button') &&
          customElements.get('zen-story'),
        undefined,
        { timeout: 5000 },
      );
    } catch (error) {
      throw new Error(`${error.message}\n${errors.join('\n')}`);
    }
    const catalogState = await page.evaluate(async () => {
      const links = [
        ...document.querySelectorAll(
          '.catalog-nav[aria-label="Components"] a',
        ),
      ];
      const elements = [...new Set(
        links.map(link => link.dataset.zenElement).filter(Boolean),
      )];
      const statuses = await Promise.all(
        links.map(async link => (await fetch(link.href)).status),
      );
      return {
        cards: document.querySelectorAll('.component-grid > a').length,
        elements,
        links: links.length,
        missing: elements.filter(name => !customElements.get(name)),
        routes: links.map(link => new URL(link.href).pathname),
        statuses,
      };
    });
    assert.equal(catalogState.cards, 70);
    assert.equal(catalogState.links, 70);
    assert.equal(catalogState.elements.length, 69);
    assert.deepEqual(catalogState.missing, []);
    assert.deepEqual(
      [...new Set(catalogState.statuses)],
      [200],
    );
    const primitiveOwnership = await page.evaluate(() => {
      const buttonOwners = [
        'zen-alert',
        'zen-attachment',
        'zen-button',
        'zen-button-group',
        'zen-calendar',
        'zen-carousel',
        'zen-combobox',
        'zen-command',
        'zen-context-menu',
        'zen-data-table',
        'zen-date-picker',
        'zen-dropdown-menu',
        'zen-input-group',
        'zen-menubar',
        'zen-message-scroller',
        'zen-navigation-menu',
        'zen-notifications',
        'zen-sidebar',
        'zen-tabs',
        'zen-toggle',
        'zen-toggle-group',
      ].join(',');
      const controlOwners = [
        'zen-calendar',
        'zen-checkbox',
        'zen-combobox',
        'zen-command',
        'zen-date-picker',
        'zen-field',
        'zen-form',
        'zen-input',
        'zen-input-group',
        'zen-input-otp',
        'zen-native-select',
        'zen-radio-group',
        'zen-select',
        'zen-slider',
        'zen-switch',
        'zen-textarea',
      ].join(',');
      return {
        buttons: [...document.querySelectorAll('button')].filter(button =>
          !button.closest(buttonOwners) &&
          !button.matches('zen-story > header > button')
        ).map(button => button.outerHTML),
        controls: [
          ...document.querySelectorAll('input, select, textarea'),
        ].filter(control => !control.closest(controlOwners))
          .map(control => control.outerHTML),
      };
    });
    assert.deepEqual(primitiveOwnership, {
      buttons: [],
      controls: [],
    });
    const brokenCatalogPages = await page.evaluate(routes => {
      const failures = [];
      const buttonOwners = [
        'zen-alert',
        'zen-attachment',
        'zen-button',
        'zen-button-group',
        'zen-calendar',
        'zen-carousel',
        'zen-combobox',
        'zen-command',
        'zen-context-menu',
        'zen-data-table',
        'zen-date-picker',
        'zen-dropdown-menu',
        'zen-input-group',
        'zen-menubar',
        'zen-message-scroller',
        'zen-navigation-menu',
        'zen-notifications',
        'zen-sidebar',
        'zen-tabs',
        'zen-toggle',
        'zen-toggle-group',
      ].join(',');
      for (const route of ['/', '/tokens', '/icons', '/components', ...routes]) {
        history.replaceState({}, '', route);
        window.dispatchEvent(new PopStateEvent('popstate'));
        const visible = [
          ...document.querySelectorAll('[data-catalog-page]:not([hidden])'),
        ];
        const expected = route === '/' || route === '/components'
          ? 'overview'
          : route.slice(route.lastIndexOf('/') + 1);
        if (visible.length !== 1 ||
            visible[0].dataset.catalogPage !== expected ||
            !visible[0].querySelector('h1')?.textContent.trim()) {
          failures.push(route);
          continue;
        }
        if (route.startsWith('/components/')) {
          const story = visible[0].querySelector('zen-story');
          const canvas = story?.querySelector('.story-canvas');
          const source = story?.querySelector('pre code');
          if (!story || !canvas?.children.length ||
              !source?.textContent.trim()) {
            failures.push(`${route}:empty-story`);
          }
          const unownedButtons = [...canvas?.querySelectorAll('button') || []]
            .filter(button => !button.closest(buttonOwners));
          if (unownedButtons.length) {
            failures.push(`${route}:unowned-button`);
          }
        }
      }
      history.replaceState({}, '', '/components/button');
      window.dispatchEvent(new PopStateEvent('popstate'));
      return failures;
    }, catalogState.routes);
    assert.deepEqual(brokenCatalogPages, []);
    await page.keyboard.press('/');
    assert.equal(
      await page.locator('#componentSearch').evaluate(
        input => document.activeElement === input,
      ),
      true,
    );
    await page.locator('#componentSearch').fill('date');
    assert.equal(
      await page.locator(
        '.catalog-nav[aria-label="Components"] a:not([hidden])',
      ).count(),
      2,
    );
    assert.equal(
      await page.locator('.component-grid > a:not([hidden])').count(),
      2,
    );
    assert.match(
      await page.locator('#componentSearchStatus').textContent(),
      /^2 components found$/,
    );
    await page.locator('#componentSearch').press('Escape');
    assert.equal(await page.locator('#componentSearch').inputValue(), '');
    assert.equal(
      await page.locator(
        '.catalog-nav[aria-label="Components"] a:not([hidden])',
      ).count(),
      70,
    );
    await page.locator('#componentSearch').fill('stack');
    assert.equal(
      await page.locator(
        '.catalog-nav[aria-label="Components"] a[href="/components/stack"]',
      ).getAttribute('hidden'),
      null,
    );
    assert.equal(
      await page.locator(
        '.component-grid > a[href="/components/stack"]',
      ).getAttribute('hidden'),
      null,
    );
    await page.locator('#componentSearch').press('Escape');
    assert.equal(
      await page.locator('[data-catalog-page="button"]').isVisible(),
      true,
    );
    assert.equal(
      await page.locator('.catalog-sidebar a[href="/components/button"]').getAttribute('aria-current'),
      'page',
    );
    assert.match(
      await page.locator('zen-story pre').first().textContent(),
      /<zen-button>/,
    );
    const plainPresentation = await page.evaluate(() => {
      const style = document.createElement('style');
      style.textContent = `
        .application-button {
          padding: 7px;
          border: 3px solid currentColor;
          box-shadow: none;
          background: transparent;
        }
        .application-input {
          appearance: auto;
          padding: 9px;
          border: 4px solid currentColor;
          background: transparent;
        }
      `;
      document.head.append(style);
      const buttonHost = document.createElement('zen-button');
      buttonHost.setAttribute('appearance', 'plain');
      buttonHost.setAttribute('loading', '');
      const button = document.createElement('button');
      button.className = 'application-button';
      button.textContent = 'Plain';
      buttonHost.append(button);

      const card = document.createElement('zen-card');
      card.setAttribute('appearance', 'plain');
      const article = document.createElement('article');
      card.append(article);

      const field = document.createElement('zen-field');
      field.setAttribute('appearance', 'plain');
      const label = document.createElement('label');
      label.textContent = 'Plain field';
      const input = document.createElement('input');
      field.append(label, input);
      const inputHost = document.createElement('zen-input');
      inputHost.setAttribute('appearance', 'plain');
      inputHost.setAttribute('size', 'lg');
      const applicationInput = document.createElement('input');
      applicationInput.className = 'application-input';
      inputHost.append(applicationInput);
      document.body.append(buttonHost, card, field, inputHost);

      const buttonStyle = getComputedStyle(button);
      const cardStyle = getComputedStyle(article);
      return {
        buttonBackground: buttonStyle.backgroundColor,
        buttonBorder: buttonStyle.borderTopWidth,
        buttonPadding: buttonStyle.paddingTop,
        buttonShadow: buttonStyle.boxShadow,
        buttonOpacity: buttonStyle.opacity,
        buttonSpinner: getComputedStyle(button, '::before').content,
        cardBackground: cardStyle.backgroundColor,
        cardBorder: cardStyle.borderTopWidth,
        cardShadow: cardStyle.boxShadow,
        fieldDisplay: getComputedStyle(field).display,
        inputAppearance: getComputedStyle(input).appearance,
        plainInputAppearance: getComputedStyle(applicationInput).appearance,
        plainInputBorder: getComputedStyle(applicationInput).borderTopWidth,
        plainInputPadding: getComputedStyle(applicationInput).paddingTop,
        labelFor: label.htmlFor,
        inputId: input.id,
      };
    });
    assert.deepEqual(plainPresentation, {
      buttonBackground: 'rgba(0, 0, 0, 0)',
      buttonBorder: '3px',
      buttonPadding: '7px',
      buttonShadow: 'none',
      buttonOpacity: '1',
      buttonSpinner: 'none',
      cardBackground: 'rgba(0, 0, 0, 0)',
      cardBorder: '0px',
      cardShadow: 'none',
      fieldDisplay: 'contents',
      inputAppearance: 'auto',
      plainInputAppearance: 'auto',
      plainInputBorder: '4px',
      plainInputPadding: '9px',
      labelFor: plainPresentation.inputId,
      inputId: plainPresentation.inputId,
    });
    const buttonScale = await page.locator(
      '[data-catalog-page="button"] zen-button[size] > button',
    ).evaluateAll(buttons => buttons.map(button => {
      const host = button.parentElement;
      const style = getComputedStyle(button);
      const hostStyle = getComputedStyle(host);
      return {
        fontSize: Number.parseFloat(style.fontSize),
        height: button.getBoundingClientRect().height,
        paddingInline: Number.parseFloat(style.paddingInlineStart),
        size: host.getAttribute('size'),
        variableHeight: Number.parseFloat(
          hostStyle.getPropertyValue('--zenbu-control-height'),
        ) * Number.parseFloat(getComputedStyle(document.documentElement).fontSize),
      };
    }));
    assert.deepEqual(
      buttonScale.map(item => item.size),
      ['xs', 'sm', 'md', 'lg', 'xl'],
    );
    for (let index = 1; index < buttonScale.length; index++) {
      assert.ok(buttonScale[index].height > buttonScale[index - 1].height);
      assert.ok(
        buttonScale[index].paddingInline >
          buttonScale[index - 1].paddingInline,
      );
      assert.ok(
        buttonScale[index].fontSize > buttonScale[index - 1].fontSize,
      );
    }
    for (const item of buttonScale) {
      assert.ok(
        Math.abs(item.height - item.variableHeight) < 1,
        JSON.stringify(buttonScale),
      );
    }
    const compactScale = await page.evaluate(() => {
      document.documentElement.dataset.zenDensity = 'compact';
      return [...document.querySelectorAll(
        '[data-catalog-page="button"] zen-button[size] > button',
      )]
        .map(button => button.getBoundingClientRect().height);
    });
    assert.equal(compactScale.length, buttonScale.length);
    for (let index = 0; index < compactScale.length; index++) {
      assert.ok(compactScale[index] < buttonScale[index].height);
    }
    await page.evaluate(() => {
      delete document.documentElement.dataset.zenDensity;
    });

    await page.emulateMedia({ reducedMotion: 'reduce' });
    assert.equal(
      await page.evaluate(() =>
        getComputedStyle(document.documentElement)
          .getPropertyValue('--zenbu-sys-motion-duration-state')
          .trim()
      ),
      '1ms',
    );
    await page.emulateMedia({ reducedMotion: 'no-preference' });

    assert.equal(
      await page.locator('zen-button[loading]:not([appearance="plain"])').getAttribute('inert'),
      null,
    );
    assert.equal(
      await page.locator('zen-button[loading]:not([appearance="plain"]) button').getAttribute('aria-disabled'),
      'true',
    );
    assert.equal(
      await page.locator('zen-button[loading]:not([appearance="plain"]) button').getAttribute('aria-busy'),
      'true',
    );
    await page.evaluate(() => {
      window.__loadingClicks = 0;
      document.querySelector('zen-button[loading]:not([appearance="plain"]) button')
        .addEventListener('click', () => window.__loadingClicks++);
    });
    await page.locator('zen-button[loading]:not([appearance="plain"]) button').evaluate(
      button => button.click(),
    );
    assert.equal(await page.evaluate(() => window.__loadingClicks), 0);
    await page.locator('zen-button[loading]:not([appearance="plain"]) button').focus();
    assert.equal(
      await page.locator('zen-button[loading]:not([appearance="plain"]) button').evaluate(
        button => document.activeElement === button,
      ),
      true,
    );
    await page.keyboard.press('Tab');
    assert.equal(
      await page.locator('zen-button[loading]:not([appearance="plain"]) button').evaluate(
        button => document.activeElement === button,
      ),
      false,
    );
    const nativeDisabledPreserved = await page.evaluate(async () => {
      const wrapper = document.createElement('zen-button');
      const button = document.createElement('button');
      button.disabled = true;
      button.textContent = 'Native disabled';
      wrapper.append(button);
      document.body.append(wrapper);
      await customElements.whenDefined('zen-button');
      wrapper.setAttribute('disabled', '');
      wrapper.removeAttribute('disabled');
      return button.disabled;
    });
    assert.equal(nativeDisabledPreserved, true);
    const replacementButtonState = await page.evaluate(async () => {
      const wrapper = document.createElement('zen-button');
      wrapper.setAttribute('disabled', '');
      const first = document.createElement('button');
      first.textContent = 'First';
      wrapper.append(first);
      document.body.append(wrapper);
      await new Promise(resolve => setTimeout(resolve));
      const second = document.createElement('button');
      second.textContent = 'Second';
      wrapper.replaceChildren(second);
      await new Promise(resolve => setTimeout(resolve));
      return {
        firstDisabled: first.disabled,
        secondAriaDisabled: second.getAttribute('aria-disabled'),
        wrapperInert: wrapper.hasAttribute('inert'),
      };
    });
    assert.equal(replacementButtonState.firstDisabled, false);
    assert.equal(replacementButtonState.secondAriaDisabled, 'true');
    assert.equal(replacementButtonState.wrapperInert, false);
    const modifiedClickAllowed = await page.evaluate(() => {
      const link = document.querySelector(
        '.catalog-sidebar a[href="/components/card"]',
      );
      return link.dispatchEvent(new MouseEvent('click', {
        bubbles: true,
        cancelable: true,
        button: 0,
        ctrlKey: true,
      }));
    });
    assert.equal(modifiedClickAllowed, true);

    await page.goto(`${baseUrl}/icons`, { waitUntil: 'networkidle' });
    const iconCount = await page.locator('#iconGrid figure').count();
    assert.ok(iconCount >= 30);
    assert.equal(
      await page.locator('#iconGrid figure zen-icon > svg').count(),
      iconCount,
    );
    const iconFallback = await page.evaluate(() => {
      const icon = document.createElement('zen-icon');
      icon.setAttribute('name', 'not-a-real-icon');
      icon.setAttribute('label', 'Missing icon fallback');
      document.body.append(icon);
      return {
        fallback: icon.dataset.zenIcon,
        hidden: icon.getAttribute('aria-hidden'),
        label: icon.getAttribute('aria-label'),
        role: icon.getAttribute('role'),
      };
    });
    assert.deepEqual(iconFallback, {
      fallback: 'alert',
      hidden: null,
      label: 'Missing icon fallback',
      role: 'img',
    });

    await page.goto(`${baseUrl}/components/link`, {
      waitUntil: 'networkidle',
    });
    const linkPrimitive = page.locator('zen-link[effect="paw"]').first();
    assert.equal(
      await linkPrimitive.locator(
        ':scope > a > zen-icon[name="paw"][data-zen-link-decoration]',
      ).count(),
      1,
    );
    const pawMotion = await linkPrimitive.locator('zen-icon').evaluate(icon => {
      const style = getComputedStyle(icon);
      const keyframes = icon.getAnimations().some(animation =>
        animation.animationName === 'zen-paw-step'
      );
      return {
        animationDuration: style.animationDuration,
        color: style.color,
        keyframes,
      };
    });
    assert.notEqual(pawMotion.animationDuration, '0s');
    assert.notEqual(pawMotion.color, 'rgba(0, 0, 0, 0)');
    assert.equal(pawMotion.keyframes, true);
    await page.emulateMedia({ reducedMotion: 'reduce' });
    assert.equal(
      await linkPrimitive.locator('zen-icon').evaluate(
        icon => getComputedStyle(icon).animationName,
      ),
      'none',
    );
    await page.emulateMedia({ reducedMotion: 'no-preference' });

    await page.goto(`${baseUrl}/components/text`, {
      waitUntil: 'networkidle',
    });
    const textScale = await page.locator('zen-text[size] > p').evaluateAll(
      texts => texts.map(text => Number.parseFloat(
        getComputedStyle(text).fontSize,
      )),
    );
    assert.equal(textScale.length, 5);
    for (let index = 1; index < textScale.length; index++) {
      assert.ok(textScale[index] > textScale[index - 1]);
    }

    await page.goto(`${baseUrl}/components/heading`, {
      waitUntil: 'networkidle',
    });
    const headingScale = await page.locator(
      'zen-heading[size] > h3',
    ).evaluateAll(headings => headings.map(heading => ({
      fontSize: Number.parseFloat(getComputedStyle(heading).fontSize),
      weight: Number(getComputedStyle(heading).fontWeight),
    })));
    assert.equal(headingScale.length, 5);
    assert.ok(headingScale.every(heading => heading.weight >= 700));
    for (let index = 1; index < headingScale.length; index++) {
      assert.ok(
        headingScale[index].fontSize > headingScale[index - 1].fontSize,
      );
    }

    await page.goto(`${baseUrl}/components/box`, {
      waitUntil: 'networkidle',
    });
    const boxScale = await page.locator('zen-box[padding]').evaluateAll(
      boxes => boxes.map(box => Number.parseFloat(
        getComputedStyle(box).paddingTop,
      )),
    );
    assert.equal(boxScale.length, 5);
    for (let index = 1; index < boxScale.length; index++) {
      assert.ok(boxScale[index] > boxScale[index - 1]);
    }

    await page.goto(`${baseUrl}/components/skeleton`, {
      waitUntil: 'networkidle',
    });
    assert.equal(
      await page.locator('zen-skeleton[width="60%"]').evaluate(
        skeleton => skeleton.style.getPropertyValue(
          '--zenbu-skeleton-width',
        ),
      ),
      '60%',
    );

    await page.goto(`${baseUrl}/tokens`, { waitUntil: 'networkidle' });
    const colorTokenState = await page.evaluate(() => {
      const root = document.documentElement;
      const value = name => getComputedStyle(root)
        .getPropertyValue(`--zen-color-${name}`)
        .trim();
      const systemValue = name => getComputedStyle(root)
        .getPropertyValue(`--zenbu-sys-${name}`)
        .trim();
      const families = [
        'neutral',
        'red',
        'orange',
        'amber',
        'green',
        'teal',
        'blue',
        'violet',
        'rose',
        'brown',
      ];
      const steps = [
        '50',
        '100',
        '200',
        '300',
        '400',
        '500',
        '600',
        '700',
        '800',
        '900',
        '950',
      ];
      const rampsComplete = families.every(family =>
        steps.every(step => value(`${family}-${step}`))
      );
      const data = Array.from(
        { length: 10 },
        (_, index) => value(`data-${index + 1}`),
      );
      const materials = [
        'paper',
        'washi',
        'linen',
        'sumi',
        'brick',
        'persimmon',
        'ochre',
        'moss',
        'patina',
        'indigo',
        'plum',
        'clay',
        'wood',
      ].map(value);
      const lightMuted = systemValue('color-surface-subtle');
      root.dataset.zenTheme = 'dark';
      const darkMuted = systemValue('color-surface-subtle');
      const darkData = Array.from(
        { length: 10 },
        (_, index) => value(`data-${index + 1}`),
      );
      const themes = ['paper', 'ink', 'playful', 'cyberpunk'].map(theme => {
        root.dataset.zenTheme = theme;
        const channels = value => value.match(/\d+(?:\.\d+)?/g)
          .slice(0, 3)
          .map(Number);
        const luminance = value => {
          const converted = channels(value).map(channel => {
            const normalized = channel / 255;
            return normalized <= 0.04045
              ? normalized / 12.92
              : ((normalized + 0.055) / 1.055) ** 2.4;
          });
          return converted[0] * 0.2126 +
            converted[1] * 0.7152 +
            converted[2] * 0.0722;
        };
        const contrasts = [
          'info',
          'success',
          'warning',
          'danger',
        ].map(tone => {
          const probe = document.createElement('span');
          probe.style.background =
            `var(--zenbu-sys-color-${tone}-background)`;
          probe.style.color =
            `var(--zenbu-sys-color-${tone}-foreground)`;
          document.body.append(probe);
          const probeStyle = getComputedStyle(probe);
          const foreground = luminance(probeStyle.color);
          const background = luminance(probeStyle.backgroundColor);
          const contrast = (Math.max(foreground, background) + 0.05) /
            (Math.min(foreground, background) + 0.05);
          probe.remove();
          return contrast;
        });
        return {
          canvas: systemValue('color-surface-page'),
          contrast: Math.min(...contrasts),
          font: getComputedStyle(root)
            .getPropertyValue('--zenbu-sys-font-family-ui')
            .trim(),
          name: theme,
          radius: getComputedStyle(root)
            .getPropertyValue('--zenbu-sys-radius-container')
            .trim(),
        };
      });
      delete root.dataset.zenTheme;
      return {
        darkData,
        darkMuted,
        data,
        lightMuted,
        materials,
        rampsComplete,
        themes,
      };
    });
    assert.equal(colorTokenState.rampsComplete, true);
    assert.equal(new Set(colorTokenState.materials).size, 13);
    assert.equal(new Set(colorTokenState.data).size, 10);
    assert.equal(new Set(colorTokenState.darkData).size, 10);
    assert.notDeepEqual(colorTokenState.data, colorTokenState.darkData);
    assert.equal(
      new Set(colorTokenState.themes.map(theme => theme.canvas)).size,
      4,
    );
    assert.notEqual(
      colorTokenState.themes.find(theme => theme.name === 'paper').radius,
      colorTokenState.themes.find(theme => theme.name === 'playful').radius,
    );
    assert.ok(
      colorTokenState.themes.every(theme => theme.contrast >= 4.5),
      JSON.stringify(colorTokenState.themes),
    );
    assert.notEqual(
      colorTokenState.lightMuted,
      colorTokenState.darkMuted,
    );
    assert.equal(await page.locator('.palette-grid > div').count(), 13);
    assert.equal(await page.locator('.data-palette > span').count(), 10);
    await page.evaluate(() => {
      document.documentElement.dataset.zenTheme = 'playful';
    });
    await page.emulateMedia({ forcedColors: 'active' });
    assert.equal(
      await page.evaluate(() =>
        getComputedStyle(document.documentElement)
          .getPropertyValue('--zenbu-sys-color-surface-page')
          .trim()
          .toLowerCase()
      ),
      'canvas',
    );
    await page.emulateMedia({ forcedColors: 'none' });
    await page.evaluate(() => {
      delete document.documentElement.dataset.zenTheme;
    });

    await page.goto(`${baseUrl}/components/field`, {
      waitUntil: 'networkidle',
    });
    const fieldWiring = await page.locator('zen-field').first().evaluate(field => {
      const label = field.querySelector('label');
      const input = field.querySelector('input');
      const help = field.querySelector('small');
      input.checkValidity();
      return {
        describedBy: input.getAttribute('aria-describedby'),
        helpId: help.id,
        inputId: input.id,
        invalid: field.hasAttribute('data-invalid'),
        labelFor: label.htmlFor,
      };
    });
    assert.ok(fieldWiring.inputId);
    assert.equal(fieldWiring.labelFor, fieldWiring.inputId);
    assert.equal(fieldWiring.describedBy, fieldWiring.helpId);
    assert.equal(fieldWiring.invalid, true);
    await page.locator('zen-field input').first().focus();
    assert.equal(
      await page.locator('zen-field input').first().evaluate(
        input => getComputedStyle(input).outlineStyle,
      ),
      'none',
    );
    const replacementField = await page.locator('zen-field').first().evaluate(
      async field => {
        const label = field.querySelector('label');
        const oldInput = field.querySelector('input');
        const blocker = document.createElement('div');
        blocker.id = 'zen-field-3';
        document.body.append(blocker);
        const nextInput = document.createElement('input');
        nextInput.required = true;
        oldInput.replaceWith(nextInput);
        await new Promise(resolve => setTimeout(resolve));
        oldInput.dispatchEvent(new Event('invalid'));
        const help = field.querySelector('small');
        nextInput.id = 'replacement-email';
        help.id = 'replacement-help';
        await new Promise(resolve => setTimeout(resolve));
        return {
          describedBy: nextInput.getAttribute('aria-describedby'),
          helpId: help.id,
          labelFor: label.htmlFor,
          nextId: nextInput.id,
          blockerId: blocker.id,
        };
      },
    );
    assert.ok(replacementField.nextId);
    assert.notEqual(replacementField.nextId, replacementField.blockerId);
    assert.equal(replacementField.labelFor, replacementField.nextId);
    assert.equal(replacementField.describedBy, replacementField.helpId);

    await page.goto(`${baseUrl}/components/alert`, {
      waitUntil: 'networkidle',
    });
    await page.evaluate(() => {
      window.__dismissed = 0;
      document.addEventListener('zen-dismiss', () => {
        window.__dismissed++;
      });
    });
    const dismissible = page.locator('zen-alert[dismissible]');
    assert.equal(await dismissible.getAttribute('role'), 'alert');
    await dismissible.locator('[data-zen-dismiss]').click();
    assert.equal(await dismissible.count(), 0);
    assert.equal(await page.evaluate(() => window.__dismissed), 1);
    const authoredDismissState = await page.evaluate(async () => {
      const alert = document.createElement('zen-alert');
      alert.setAttribute('dismissible', '');
      const message = document.createElement('p');
      message.textContent = 'Authored dismiss control';
      const dismiss = document.createElement('button');
      dismiss.dataset.zenDismiss = '';
      alert.append(message, dismiss);
      document.body.append(alert);
      await new Promise(resolve => setTimeout(resolve));
      let events = 0;
      alert.addEventListener('zen-dismiss', () => events++);
      alert.removeAttribute('dismissible');
      dismiss.click();
      return {
        connected: alert.isConnected,
        events,
      };
    });
    assert.equal(authoredDismissState.connected, true);
    assert.equal(authoredDismissState.events, 0);

    await page.goto(`${baseUrl}/components/accordion`, {
      waitUntil: 'networkidle',
    });
    const accordion = page.locator('zen-accordion').first();
    const disclosureIcon = accordion.locator(
      'summary > zen-icon[data-zen-disclosure-icon]',
    ).nth(1);
    const collapsedDisclosure = await disclosureIcon.evaluate(icon => {
      const style = getComputedStyle(icon);
      return {
        duration: style.transitionDuration,
        transform: style.transform,
      };
    });
    assert.notEqual(collapsedDisclosure.duration, '0s');
    await accordion.locator('summary').nth(1).click();
    await page.waitForTimeout(250);
    assert.notEqual(
      await disclosureIcon.evaluate(icon => getComputedStyle(icon).transform),
      collapsedDisclosure.transform,
    );
    assert.equal(
      await accordion.locator('details').first().getAttribute('open'),
      null,
    );
    assert.equal(
      await accordion.locator('details').nth(1).getAttribute('open'),
      '',
    );
    await accordion.locator('summary').nth(1).press('ArrowUp');
    assert.equal(
      await accordion.locator('summary').first().evaluate(
        summary => document.activeElement === summary,
      ),
      true,
    );

    await page.goto(`${baseUrl}/components/aspect-ratio`, {
      waitUntil: 'networkidle',
    });
    const aspectColors = await page.locator('.demo-media').evaluate(media => {
      const style = getComputedStyle(media);
      const probe = document.createElement('span');
      probe.style.background = 'var(--zenbu-sys-color-surface-subtle)';
      document.body.append(probe);
      const token = getComputedStyle(probe).backgroundColor;
      probe.remove();
      return {
        background: style.backgroundColor,
        image: style.backgroundImage,
        token,
      };
    });
    assert.equal(aspectColors.image, 'none');
    assert.equal(aspectColors.background, aspectColors.token);

    await page.goto(`${baseUrl}/components/tabs`, {
      waitUntil: 'networkidle',
    });
    await page.evaluate(() => {
      window.__tabValue = null;
      document.querySelector('zen-tabs').addEventListener(
        'zen-change',
        event => {
          window.__tabValue = event.detail.value;
        },
      );
    });
    await page.locator('zen-tabs [role="tab"]').nth(1).click();
    assert.equal(
      await page.locator('zen-tabs [role="tab"]').nth(1)
        .getAttribute('aria-selected'),
      'true',
    );
    assert.equal(
      await page.locator('zen-tabs [role="tabpanel"]').nth(1)
        .getAttribute('hidden'),
      null,
    );
    assert.equal(await page.evaluate(() => window.__tabValue), 'history');

    await page.goto(`${baseUrl}/components/dialog`, {
      waitUntil: 'networkidle',
    });
    await page.locator('zen-dialog [data-zen-trigger]').click();
    assert.equal(await page.locator('zen-dialog dialog').getAttribute('open'), '');
    await page.locator('zen-dialog [data-zen-close]').click();
    assert.equal(await page.locator('zen-dialog dialog').getAttribute('open'), null);
    const dynamicOverlays = await page.evaluate(async () => {
      const ownAction = button => {
        const owner = document.createElement('zen-button');
        owner.setAttribute('size', 'md');
        owner.append(button);
        return owner;
      };
      const dialogHost = document.createElement('zen-dialog');
      const popoverHost = document.createElement('zen-popover');
      const tooltipHost = document.createElement('zen-tooltip');
      const menuHost = document.createElement('zen-dropdown-menu');
      document.body.append(dialogHost, popoverHost, tooltipHost, menuHost);

      const dialogTrigger = document.createElement('button');
      dialogTrigger.type = 'button';
      dialogTrigger.dataset.zenTrigger = '';
      const dialog = document.createElement('dialog');
      dialogHost.append(ownAction(dialogTrigger), dialog);

      const popoverTrigger = document.createElement('button');
      popoverTrigger.type = 'button';
      popoverTrigger.dataset.zenTrigger = '';
      const popover = document.createElement('div');
      popover.dataset.zenContent = '';
      popoverHost.append(ownAction(popoverTrigger), popover);

      const tooltipTrigger = document.createElement('button');
      tooltipTrigger.type = 'button';
      tooltipTrigger.dataset.zenTrigger = '';
      const tooltip = document.createElement('span');
      tooltip.dataset.zenContent = '';
      tooltipHost.append(ownAction(tooltipTrigger), tooltip);

      const menuTrigger = document.createElement('button');
      menuTrigger.type = 'button';
      menuTrigger.dataset.zenTrigger = '';
      const menu = document.createElement('div');
      menu.setAttribute('role', 'menu');
      const item = document.createElement('button');
      item.type = 'button';
      item.setAttribute('role', 'menuitem');
      menu.append(item);
      menuHost.append(menuTrigger, menu);

      await new Promise(resolve => setTimeout(resolve));
      dialogTrigger.click();
      const dialogOpen = dialog.open;
      dialog.close();
      popoverTrigger.click();
      menuTrigger.click();
      tooltipTrigger.focus();
      await new Promise(resolve => setTimeout(resolve, 375));
      return {
        dialogControlled: Boolean(dialogTrigger.getAttribute('aria-controls')),
        dialogOpen,
        menuOpen: !menu.hidden,
        popoverExpanded: popoverTrigger.getAttribute('aria-expanded'),
        tooltipOpen: !tooltip.hidden,
      };
    });
    assert.deepEqual(dynamicOverlays, {
      dialogControlled: true,
      dialogOpen: true,
      menuOpen: true,
      popoverExpanded: 'true',
      tooltipOpen: true,
    });

    await page.goto(`${baseUrl}/components/dropdown-menu`, {
      waitUntil: 'networkidle',
    });
    const dropdownTrigger = page.locator(
      'zen-dropdown-menu [data-zen-trigger]',
    );
    await dropdownTrigger.click();
    assert.equal(
      await page.locator('zen-dropdown-menu [role="menu"]')
        .getAttribute('hidden'),
      null,
    );
    await page.keyboard.press('Escape');
    assert.equal(
      await page.locator('zen-dropdown-menu [role="menu"]')
        .getAttribute('hidden'),
      '',
    );
    assert.equal(
      await dropdownTrigger.evaluate(
        trigger => document.activeElement === trigger,
      ),
      true,
    );
    await dropdownTrigger.click();
    await page.locator('zen-dropdown-menu [role="menuitem"]').first().click();
    assert.equal(
      await dropdownTrigger.evaluate(
        trigger => document.activeElement === trigger,
      ),
      true,
    );

    await page.goto(`${baseUrl}/components/combobox`, {
      waitUntil: 'networkidle',
    });
    const comboboxInput = page.locator('zen-combobox input');
    await comboboxInput.fill('seo');
    assert.equal(
      await page.locator('zen-combobox [role="option"]:not([hidden])').count(),
      1,
    );
    await comboboxInput.press('ArrowDown');
    await comboboxInput.press('Enter');
    assert.equal(await comboboxInput.inputValue(), 'seobeo');
    assert.equal(
      await page.locator('zen-combobox [role="listbox"]')
        .getAttribute('hidden'),
      '',
    );

    await page.goto(`${baseUrl}/components/date-picker`, {
      waitUntil: 'networkidle',
    });
    const dateInput = page.locator('zen-date-picker input[type="date"]');
    assert.equal(await dateInput.getAttribute('aria-hidden'), 'true');
    assert.equal(
      await dateInput.evaluate(input => getComputedStyle(input).position),
      'absolute',
    );
    await page.evaluate(() => {
      window.__dateValue = null;
      document.querySelector('zen-date-picker').addEventListener(
        'zen-change',
        event => {
          window.__dateValue = event.detail.value;
        },
      );
    });
    const dateTrigger = page.locator(
      'zen-date-picker [data-zen-date-trigger]',
    );
    await dateTrigger.click();
    assert.equal(
      await page.locator('zen-date-picker [data-zen-calendar-panel]')
        .getAttribute('hidden'),
      null,
    );
    assert.equal(
      await page.locator(
        'zen-date-picker [data-zen-calendar-day]',
      ).count(),
      42,
    );
    const chosenDate = await page.locator(
      'zen-date-picker [data-zen-calendar-day]:not([data-outside]):not(:disabled)',
    ).nth(14).getAttribute('data-zen-calendar-day');
    await page.locator(
      `zen-date-picker [data-zen-calendar-day="${chosenDate}"]`,
    ).click();
    assert.equal(await dateInput.inputValue(), chosenDate);
    assert.equal(await page.evaluate(() => window.__dateValue), chosenDate);
    assert.equal(await dateTrigger.getAttribute('aria-expanded'), 'false');
    const triggerName = await dateTrigger.evaluate(trigger =>
      (trigger.getAttribute('aria-labelledby') || '')
        .split(/\s+/)
        .map(id => document.getElementById(id)?.textContent || '')
        .join(' ')
    );
    assert.match(triggerName, /Deploy on/);
    assert.equal(
      await page.locator('zen-date-picker > label').getAttribute('for'),
      await dateTrigger.getAttribute('id'),
    );
    const minimumDate = `${chosenDate.slice(0, 8)}10`;
    await dateInput.evaluate((input, minimum) => {
      input.min = minimum;
    }, minimumDate);
    await page.waitForTimeout(0);
    await dateTrigger.click();
    const focusedBoundary = page.locator(
      `zen-date-picker [data-zen-calendar-day="${chosenDate}"]`,
    );
    await focusedBoundary.press('PageUp');
    assert.equal(
      await page.evaluate(() =>
        document.activeElement?.dataset.zenCalendarDay
      ),
      minimumDate,
    );
    assert.equal(
      await page.locator(
        'zen-date-picker [data-zen-calendar-day][tabindex="0"]:not(:disabled)',
      ).count(),
      1,
    );
    await page.keyboard.press('Escape');
    await dateInput.evaluate(input => {
      input.disabled = true;
    });
    await page.waitForTimeout(0);
    assert.equal(await dateTrigger.isDisabled(), true);
    await dateInput.evaluate(input => {
      input.disabled = false;
      input.readOnly = true;
    });
    await page.waitForTimeout(0);
    assert.equal(await dateTrigger.isDisabled(), true);
    await dateInput.evaluate(input => {
      input.readOnly = false;
      input.required = true;
      input.value = '';
      input.dispatchEvent(new Event('input', { bubbles: true }));
      input.reportValidity();
    });
    await page.waitForTimeout(0);
    assert.equal(await dateTrigger.getAttribute('aria-invalid'), 'true');
    assert.equal(
      await dateTrigger.evaluate(
        trigger => document.activeElement === trigger,
      ),
      true,
    );
    assert.equal(
      await page.locator('zen-date-picker').getAttribute('data-invalid'),
      '',
    );
    await dateInput.evaluate((input, value) => {
      input.value = value;
      input.dispatchEvent(new Event('input', { bubbles: true }));
    }, chosenDate);
    assert.equal(await dateTrigger.getAttribute('aria-invalid'), 'false');
    const earlyYear = await page.evaluate(async () => {
      const calendar = document.createElement('zen-calendar');
      const input = document.createElement('input');
      input.type = 'date';
      input.value = '0001-01-01';
      input.setAttribute('aria-label', 'Early date');
      calendar.append(input);
      document.body.append(calendar);
      await new Promise(resolve => setTimeout(resolve));
      return {
        selected: calendar.querySelector(
          '[data-zen-calendar-day][aria-selected="true"]',
        )?.dataset.zenCalendarDay,
        value: input.value,
      };
    });
    assert.deepEqual(earlyYear, {
      selected: '0001-01-01',
      value: '0001-01-01',
    });
    const resetDateState = await page.evaluate(async () => {
      const label = document.createElement('span');
      label.id = 'reset-date-label';
      label.textContent = 'Reset date';
      const form = document.createElement('form');
      const picker = document.createElement('zen-date-picker');
      const input = document.createElement('input');
      input.type = 'date';
      input.defaultValue = '2026-08-04';
      input.setAttribute('aria-labelledby', label.id);
      picker.append(input);
      form.append(picker);
      document.body.append(label, form);
      await new Promise(resolve => setTimeout(resolve));
      input.value = '2026-08-12';
      input.dispatchEvent(new Event('input', { bubbles: true }));
      form.reset();
      await new Promise(resolve => setTimeout(resolve));
      const trigger = picker.querySelector('[data-zen-date-trigger]');
      return {
        labelledBy: trigger.getAttribute('aria-labelledby'),
        selected: picker.querySelector(
          '[data-zen-calendar-day][aria-selected="true"]',
        )?.dataset.zenCalendarDay,
        value: input.value,
      };
    });
    assert.match(resetDateState.labelledBy, /^reset-date-label /);
    assert.deepEqual(
      {
        selected: resetDateState.selected,
        value: resetDateState.value,
      },
      {
        selected: '2026-08-04',
        value: '2026-08-04',
      },
    );

    await page.goto(`${baseUrl}/components/input-otp`, {
      waitUntil: 'networkidle',
    });
    await page.evaluate(() => {
      window.__otpValue = null;
      document.querySelector('zen-input-otp').addEventListener(
        'zen-complete',
        event => {
          window.__otpValue = event.detail.value;
        },
      );
    });
    await page.locator('zen-input-otp input').evaluate(input => {
      input.value = '12a3456';
      input.dispatchEvent(new Event('input', { bubbles: true }));
    });
    assert.equal(await page.locator('zen-input-otp input').inputValue(), '123456');
    assert.equal(
      await page.locator('zen-input-otp [data-zen-otp-slots] > span').count(),
      6,
    );
    const otp = page.locator('zen-input-otp');
    await otp.evaluate(host => host.setAttribute('size', 'xs'));
    const compactOtpSize = await otp.locator(
      '[data-zen-otp-slots] > span',
    ).first().evaluate(slot => slot.getBoundingClientRect().width);
    await otp.evaluate(host => host.setAttribute('size', 'xl'));
    const largeOtpSize = await otp.locator(
      '[data-zen-otp-slots] > span',
    ).first().evaluate(slot => slot.getBoundingClientRect().width);
    assert.ok(largeOtpSize > compactOtpSize);
    assert.equal(await page.evaluate(() => window.__otpValue), '123456');

    await page.goto(`${baseUrl}/components/data-table`, {
      waitUntil: 'networkidle',
    });
    await page.locator('zen-data-table [data-zen-sort="commits"]').click();
    assert.equal(
      await page.locator('zen-data-table th').nth(1).getAttribute('aria-sort'),
      'ascending',
    );
    assert.equal(
      await page.locator('zen-data-table tbody tr').first().locator(
        '[data-key="commits"]',
      ).textContent(),
      '12',
    );

    await page.goto(`${baseUrl}/components/carousel`, {
      waitUntil: 'networkidle',
    });
    await page.evaluate(() => {
      window.__carouselIndex = null;
      document.querySelector('zen-carousel').addEventListener(
        'zen-change',
        event => {
          window.__carouselIndex = event.detail.index;
        },
      );
    });
    await page.locator('zen-carousel [data-zen-next]').click();
    assert.equal(await page.evaluate(() => window.__carouselIndex), 1);
    assert.equal(
      await page.locator('zen-carousel [data-zen-prev]').isDisabled(),
      false,
    );

    await page.goto(`${baseUrl}/components/resizable`, {
      waitUntil: 'networkidle',
    });
    const resizeHandle = page.locator('zen-resizable [data-zen-handle]');
    const initialPercent = Number(
      await resizeHandle.getAttribute('aria-valuenow'),
    );
    await resizeHandle.focus();
    await resizeHandle.press('ArrowRight');
    assert.ok(
      Number(await resizeHandle.getAttribute('aria-valuenow')) > initialPercent,
    );

    await page.goto(`${baseUrl}/components/switch`, {
      waitUntil: 'networkidle',
    });
    const switchInput = page.locator('zen-switch input');
    assert.equal(await switchInput.getAttribute('role'), 'switch');
    assert.equal(await switchInput.getAttribute('aria-checked'), 'true');
    await switchInput.uncheck();
    assert.equal(await switchInput.getAttribute('aria-checked'), 'false');

    await page.goto(`${baseUrl}/components/checkbox`, {
      waitUntil: 'networkidle',
    });
    assert.equal(
      await page.locator('zen-checkbox input').evaluate(
        input => getComputedStyle(input).appearance,
      ),
      'none',
    );
    await page.goto(`${baseUrl}/components/native-select`, {
      waitUntil: 'networkidle',
    });
    assert.equal(
      await page.locator('zen-native-select select').evaluate(
        select => getComputedStyle(select).appearance,
      ),
      'none',
    );
    assert.equal(
      await page.locator(
        'zen-native-select > zen-icon[data-zen-select-icon]',
      ).count(),
      1,
    );
    await page.goto(`${baseUrl}/components/slider`, {
      waitUntil: 'networkidle',
    });
    assert.equal(
      await page.locator('zen-slider input').evaluate(
        input => getComputedStyle(input).appearance,
      ),
      'none',
    );

    await page.goto(`${baseUrl}/components/toggle-group`, {
      waitUntil: 'networkidle',
    });
    await page.locator('zen-toggle-group button[value="right"]').click();
    assert.equal(
      await page.locator('zen-toggle-group button[value="right"]')
        .getAttribute('aria-pressed'),
      'true',
    );
    assert.equal(
      await page.locator('zen-toggle-group').getAttribute('value'),
      'right',
    );

    await page.goto(`${baseUrl}/components/sidebar`, {
      waitUntil: 'networkidle',
    });
    const sidebarTrigger = page.locator(
      'zen-sidebar [data-zen-sidebar-trigger]',
    );
    const sidebarPanel = page.locator(
      'zen-sidebar [data-zen-sidebar-panel]',
    );
    assert.equal(await sidebarTrigger.getAttribute('aria-expanded'), 'true');
    assert.equal(await sidebarPanel.getAttribute('hidden'), null);
    await sidebarTrigger.click();
    assert.equal(await sidebarTrigger.getAttribute('aria-expanded'), 'false');
    assert.equal(await sidebarPanel.getAttribute('hidden'), '');

    await page.goto(`${baseUrl}/components/notifications`, {
      waitUntil: 'networkidle',
    });
    const notificationScope = page.locator('zen-notifications').first();
    const notificationPosition = await notificationScope.locator(
      '[data-zen-notification-stack]',
    ).evaluate(stack => {
      const style = getComputedStyle(stack);
      return {
        bottom: style.bottom,
        position: style.position,
        right: style.right,
      };
    });
    assert.equal(notificationPosition.position, 'fixed');
    assert.notEqual(notificationPosition.bottom, 'auto');
    assert.notEqual(notificationPosition.right, 'auto');

    const dedupe = await notificationScope.evaluate(scope => {
      const source = scope.querySelector('[data-notification-demo]');
      const send = detail => source.dispatchEvent(
        new CustomEvent('zen-notify', {
          bubbles: true,
          composed: false,
          detail,
        }),
      );
      send({
        version: 1,
        id: 'dedupe',
        tone: 'info',
        message: 'First announcement',
        announcement: 'polite',
        persistent: true,
      });
      send({
        version: 1,
        id: 'dedupe',
        tone: 'success',
        message: 'Updated without duplication',
        announcement: 'polite',
        persistent: true,
      });
      send({ version: 99, id: 'invalid' });
      return {
        size: scope.size,
        visible: scope.visibleCount,
      };
    });
    assert.deepEqual(dedupe, { size: 1, visible: 1 });
    assert.equal(
      await notificationScope.locator('article').count(),
      1,
    );
    assert.match(
      await notificationScope.locator('article').textContent(),
      /Updated without duplication/,
    );
    await page.waitForFunction(() =>
      document.querySelector(
        'zen-notifications [data-zen-live="polite"]',
      )?.textContent === 'First announcement'
    );

    const bounded = await notificationScope.evaluate(scope => {
      let accepted = 0;
      for (let index = 0; index < 25; index++) {
        if (scope.notify({
          version: 1,
          id: `bounded-${index}`,
          tone: 'info',
          message: `Bounded ${index}`,
          announcement: 'none',
          durationMs: 120000,
        })) accepted++;
      }
      return {
        accepted,
        size: scope.size,
        visible: scope.visibleCount,
      };
    });
    assert.deepEqual(bounded, { accepted: 25, size: 23, visible: 3 });
    assert.equal(
      await notificationScope.locator('article').count(),
      3,
    );
    await page.waitForFunction(() =>
      [...document.querySelectorAll(
        'zen-notifications article',
      )].some(article => article.dataset.depth === '2')
    );
    const collapsedStack = await notificationScope.locator(
      '[data-zen-notification-stack]',
    ).evaluate(stack => {
      const articles = [...stack.querySelectorAll('article')];
      return {
        depths: articles.map(article => article.dataset.depth),
        height: stack.getBoundingClientRect().height,
        positions: articles.map(article =>
          getComputedStyle(article).position
        ),
        transforms: articles.map(article =>
          getComputedStyle(article).transform
        ),
      };
    });
    assert.deepEqual(collapsedStack.depths, ['2', '1', '0']);
    assert.deepEqual(
      collapsedStack.positions,
      ['absolute', 'absolute', 'absolute'],
    );
    await notificationScope.locator('article').last().hover();
    await page.waitForTimeout(300);
    const expandedStack = await notificationScope.locator(
      '[data-zen-notification-stack]',
    ).evaluate(stack => ({
      height: stack.getBoundingClientRect().height,
      rects: [...stack.querySelectorAll('article')].map(article => {
        const bounds = article.getBoundingClientRect();
        return {
          bottom: bounds.bottom,
          left: bounds.left,
          right: bounds.right,
          top: bounds.top,
        };
      }),
      tops: [...stack.querySelectorAll('article')].map(
        article => Math.round(article.getBoundingClientRect().top),
      ),
      transforms: [...stack.querySelectorAll('article')].map(
        article => getComputedStyle(article).transform,
      ),
    }));
    assert.ok(expandedStack.height > collapsedStack.height);
    assert.equal(new Set(expandedStack.tops).size, 3);
    const expandedGaps = [
      expandedStack.rects[1].top - expandedStack.rects[0].bottom,
      expandedStack.rects[2].top - expandedStack.rects[1].bottom,
    ];
    for (const gap of expandedGaps) {
      assert.ok(gap >= 10 && gap <= 14, JSON.stringify(expandedGaps));
    }
    assert.notDeepEqual(
      expandedStack.transforms,
      collapsedStack.transforms,
    );
    const gapX =
      (expandedStack.rects[0].left + expandedStack.rects[0].right) / 2;
    const gapY =
      (expandedStack.rects[0].bottom + expandedStack.rects[1].top) / 2;
    await page.mouse.move(gapX, gapY);
    await page.waitForTimeout(100);
    const gapState = await notificationScope.locator(
      '[data-zen-notification-stack]',
    ).evaluate(stack => ({
      height: stack.getBoundingClientRect().height,
      hovered: stack.matches(':hover'),
    }));
    assert.equal(gapState.hovered, true);
    assert.ok(gapState.height >= expandedStack.height - 1);
    await page.mouse.move(0, 0);

    const actionScope = await page.evaluate(() => {
      const scope = document.createElement('zen-notifications');
      scope.id = 'action-scope';
      const source = document.createElement('button');
      scope.append(source);
      document.body.append(scope);
      window.__notificationAction = null;
      scope.addEventListener('zen-notification-action', event => {
        window.__notificationAction = event.detail;
      });
      source.dispatchEvent(new CustomEvent('zen-notify', {
        bubbles: true,
        composed: false,
        detail: {
          version: 1,
          id: 'action',
          tone: 'error',
          message: 'Action required',
          announcement: 'assertive',
          persistent: true,
          action: {
            token: 'opaque-secret-token',
            label: 'Retry',
          },
        },
      }));
      return scope.id;
    });
    assert.equal(
      await page.locator(`#${actionScope}`).evaluate(
        scope => scope.records,
      ),
      undefined,
    );
    const actionArticle = page.locator(
      `#${actionScope} [data-zen-notification-id="action"]`,
    );
    assert.doesNotMatch(
      await actionArticle.evaluate(article => article.outerHTML),
      /opaque-secret-token/,
    );
    await actionArticle.locator('.zen-notification-action').focus();
    await page.locator(`#${actionScope}`).evaluate(scope => {
      const source = scope.querySelector('button');
      source.dispatchEvent(new CustomEvent('zen-notify', {
        bubbles: true,
        composed: false,
        detail: {
          version: 1,
          id: 'action-neighbor',
          tone: 'info',
          message: 'Neighbor',
          announcement: 'none',
          persistent: true,
        },
      }));
    });
    assert.equal(
      await actionArticle.locator('.zen-notification-action').evaluate(
        action => document.activeElement === action,
      ),
      true,
    );
    await actionArticle.locator('.zen-notification-action').click();
    assert.deepEqual(
      await page.evaluate(() => window.__notificationAction),
      {
        version: 1,
        id: 'action',
        token: 'opaque-secret-token',
      },
    );
    await page.locator(`#${actionScope}`).evaluate(scope => {
      const source = scope.querySelector('button');
      source.dispatchEvent(new CustomEvent(
        'zen-dismiss-notification',
        {
          bubbles: true,
          composed: false,
          detail: { version: 1, id: 'action' },
        },
      ));
    });
    await actionArticle.waitFor({ state: 'detached' });

    await page.evaluate(() => {
      const scope = document.createElement('zen-notifications');
      scope.id = 'announcement-scope';
      const source = document.createElement('button');
      scope.append(source);
      document.body.append(scope);
      window.__announcements = [];
      const region = scope.querySelector('[data-zen-live="polite"]');
      new MutationObserver(() => {
        if (region.textContent) {
          window.__announcements.push(region.textContent);
        }
      }).observe(region, { childList: true });
      for (let index = 0; index < 3; index++) {
        source.dispatchEvent(new CustomEvent('zen-notify', {
          bubbles: true,
          composed: false,
          detail: {
            version: 1,
            id: `announcement-${index}`,
            tone: 'info',
            message: `Announcement ${index}`,
            announcement: 'polite',
            persistent: true,
          },
        }));
      }
    });
    await page.waitForFunction(() =>
      window.__announcements?.length === 3
    );
    assert.deepEqual(
      await page.evaluate(() => window.__announcements),
      ['Announcement 0', 'Announcement 1', 'Announcement 2'],
    );

    const composedRejected = await page.evaluate(() => {
      const scope = document.createElement('zen-notifications');
      const source = document.createElement('button');
      scope.append(source);
      document.body.append(scope);
      source.dispatchEvent(new CustomEvent('zen-notify', {
        bubbles: true,
        composed: true,
        detail: {
          version: 1,
          id: 'composed',
          tone: 'info',
          message: 'Must be rejected',
          announcement: 'none',
          persistent: true,
        },
      }));
      return scope.size;
    });
    assert.equal(composedRejected, 0);

    await page.evaluate(() => {
      const scope = document.createElement('zen-notifications');
      scope.id = 'focus-timer-scope';
      const source = document.createElement('button');
      scope.append(source);
      document.body.append(scope);
      source.dispatchEvent(new CustomEvent('zen-notify', {
        bubbles: true,
        composed: false,
        detail: {
          version: 1,
          id: 'focus-timer',
          tone: 'warning',
          message: 'Focus timer',
          announcement: 'none',
          durationMs: 300,
          action: { token: 'focus-token', label: 'Keep focused' },
        },
      }));
    });
    const focusTimer = page.locator(
      '#focus-timer-scope [data-zen-notification-id="focus-timer"]',
    );
    await focusTimer.locator('.zen-notification-action').focus();
    await page.locator('#focus-timer-scope').evaluate(scope => {
      const source = scope.querySelector(':scope > button');
      source.dispatchEvent(new CustomEvent('zen-notify', {
        bubbles: true,
        composed: false,
        detail: {
          version: 1,
          id: 'focus-neighbor',
          tone: 'info',
          message: 'Focus neighbor',
          announcement: 'none',
          persistent: true,
        },
      }));
    });
    await page.waitForTimeout(500);
    assert.equal(await focusTimer.count(), 1);
    assert.equal(
      await focusTimer.locator('.zen-notification-action').evaluate(
        action => document.activeElement === action,
      ),
      true,
    );
    await page.mouse.move(0, 0);
    await page.locator('#catalogMain').focus();
    await page.waitForFunction(() =>
      !document.querySelector(
        '#focus-timer-scope [data-zen-notification-id="focus-timer"]',
      )
    );

    await page.evaluate(() => {
      const scope = document.createElement('zen-notifications');
      scope.id = 'timer-scope';
      const source = document.createElement('button');
      scope.append(source);
      document.body.append(scope);
      source.dispatchEvent(new CustomEvent('zen-notify', {
        bubbles: true,
        composed: false,
        detail: {
          version: 1,
          id: 'timer',
          tone: 'info',
          message: 'Paused timer',
          announcement: 'none',
          durationMs: 300,
        },
      }));
    });
    const timerArticle = page.locator('#timer-scope article');
    await timerArticle.hover();
    await page.waitForTimeout(500);
    assert.equal(await timerArticle.count(), 1);
    await page.mouse.move(0, 0);
    await page.waitForFunction(() =>
      !document.querySelector('#timer-scope article')
    );

    await page.evaluate(() => {
      const scope = document.createElement('zen-notifications');
      scope.id = 'hidden-timer-scope';
      const source = document.createElement('button');
      scope.append(source);
      document.body.append(scope);
      source.dispatchEvent(new CustomEvent('zen-notify', {
        bubbles: true,
        composed: false,
        detail: {
          version: 1,
          id: 'hidden-timer',
          tone: 'info',
          message: 'Hidden timer',
          announcement: 'none',
          durationMs: 300,
        },
      }));
      Object.defineProperty(document, 'hidden', {
        configurable: true,
        value: true,
      });
      document.dispatchEvent(new Event('visibilitychange'));
    });
    await page.waitForTimeout(500);
    assert.equal(
      await page.locator('#hidden-timer-scope article').count(),
      1,
    );
    await page.evaluate(() => {
      Object.defineProperty(document, 'hidden', {
        configurable: true,
        value: false,
      });
      document.dispatchEvent(new Event('visibilitychange'));
    });
    await page.waitForFunction(() =>
      !document.querySelector('#hidden-timer-scope article')
    );

    const isolated = await page.evaluate(() => {
      const makeScope = id => {
        const scope = document.createElement('zen-notifications');
        scope.id = id;
        const source = document.createElement('button');
        scope.append(source);
        document.body.append(scope);
        return { scope, source };
      };
      const first = makeScope('scope-one');
      const second = makeScope('scope-two');
      first.source.dispatchEvent(new CustomEvent('zen-notify', {
        bubbles: true,
        composed: false,
        detail: {
          version: 1,
          id: 'isolated',
          tone: 'success',
          message: 'Only first scope',
          announcement: 'none',
          persistent: true,
        },
      }));
      return [first.scope.size, second.scope.size];
    });
    assert.deepEqual(isolated, [1, 0]);

    const lightCanvas = await page.evaluate(() =>
      getComputedStyle(document.documentElement)
        .getPropertyValue('--zenbu-sys-color-surface-page')
        .trim()
    );
    await page.locator('#themeToggle').click();
    const darkCanvas = await page.evaluate(() =>
      getComputedStyle(document.documentElement)
        .getPropertyValue('--zenbu-sys-color-surface-page')
        .trim()
    );
    assert.notEqual(lightCanvas, darkCanvas);
    assert.equal(
      await page.evaluate(() => localStorage.getItem('zen-theme')),
      'dark',
    );

    assert.deepEqual(errors, []);
    await context.close();

    const darkContext = await browser.newContext({ colorScheme: 'dark' });
    const darkPage = await darkContext.newPage();
    await darkPage.goto(baseUrl, { waitUntil: 'networkidle' });
    assert.equal(
      await darkPage.locator('#themeToggle').getAttribute('aria-pressed'),
      'true',
    );
    const systemDarkCanvas = await darkPage.evaluate(() =>
      getComputedStyle(document.documentElement)
        .getPropertyValue('--zenbu-sys-color-surface-page')
        .trim()
    );
    await darkPage.locator('#themeToggle').click();
    const explicitLightCanvas = await darkPage.evaluate(() =>
      getComputedStyle(document.documentElement)
        .getPropertyValue('--zenbu-sys-color-surface-page')
        .trim()
    );
    assert.notEqual(systemDarkCanvas, explicitLightCanvas);
    await darkContext.close();

    const mobileContext = await browser.newContext({
      colorScheme: 'light',
      viewport: { width: 390, height: 844 },
    });
    const mobilePage = await mobileContext.newPage();
    const mobileErrors = [];
    mobilePage.on('pageerror', error => {
      mobileErrors.push(error.stack || error.message);
    });
    mobilePage.on('console', message => {
      if (message.type() === 'error') mobileErrors.push(message.text());
    });
    await mobilePage.goto(baseUrl, { waitUntil: 'networkidle' });
    await mobilePage.waitForFunction(() =>
      customElements.get('zen-date-picker') &&
      document.querySelectorAll(
        '.catalog-nav[aria-label="Components"] a',
      ).length === 70
    );
    const mobileFailures = await mobilePage.evaluate(() => {
      const routes = [
        '/',
        '/tokens',
        '/icons',
        ...[...document.querySelectorAll(
          '.catalog-nav[aria-label="Components"] a',
        )].map(link => new URL(link.href).pathname),
      ];
      const failures = [];
      for (const route of routes) {
        history.replaceState({}, '', route);
        window.dispatchEvent(new PopStateEvent('popstate'));
        const page = document.querySelector(
          '[data-catalog-page]:not([hidden])',
        );
        if (!page ||
            document.documentElement.scrollWidth > innerWidth + 1 ||
            page.getBoundingClientRect().right > innerWidth + 1) {
          failures.push(route);
        }
      }
      return failures;
    });
    assert.deepEqual(mobileFailures, []);
    await mobilePage.goto(`${baseUrl}/components/date-picker`, {
      waitUntil: 'networkidle',
    });
    await mobilePage.locator(
      'zen-date-picker [data-zen-date-trigger]',
    ).click();
    const mobileCalendarBounds = await mobilePage.locator(
      'zen-date-picker [data-zen-calendar-panel]',
    ).evaluate(panel => {
      const bounds = panel.getBoundingClientRect();
      return {
        bottom: bounds.bottom,
        left: bounds.left,
        right: bounds.right,
        top: bounds.top,
      };
    });
    assert.ok(mobileCalendarBounds.left >= 0);
    assert.ok(mobileCalendarBounds.right <= 390);
    assert.ok(mobileCalendarBounds.top >= 0);
    assert.ok(mobileCalendarBounds.bottom <= 844);
    assert.deepEqual(mobileErrors, []);
    await mobileContext.close();
  } finally {
    if (browser) await browser.close();
    await stopProcess(server);
  }
})().catch(error => {
  console.error(error.stack || error);
  process.exitCode = 1;
});