← Files DataARCHIVED FILE

tests/inline-chart-browser-sources.mjs

51.4 KB · Sep 30, 2026 · 23:19 UTC

↓ Download file

import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import { join } from "node:path";

import { renderInlineSources } from "../skills/visualize-data/scripts/render-inline-sources.mjs";

// Seek the real CSS transition instead of relying on CI rendering a frame
// inside its short wall-clock duration. Measurements still come from the DOM.
function armReceiptTransition(element, { targetSelector, attributeSelector, property, measure }) {
  const scope = element.shadowRoot ?? element;
  const target = scope.querySelector(targetSelector);
  const attributeTarget = attributeSelector ? scope.querySelector(attributeSelector) : element;
  const readValue = () => {
    if (measure === "height") return target.getBoundingClientRect().height;
    const transform = getComputedStyle(target).transform;
    const matrix = new DOMMatrixReadOnly(transform === "none" ? undefined : transform);
    return Math.abs(Math.atan2(matrix.b, matrix.a) * 180 / Math.PI);
  };
  element.receiptMotionElement ??= target;
  readValue();
  element.receiptMotion = new Promise((resolve, reject) => {
    const observer = new MutationObserver(() => {
      observer.disconnect();
      try {
        const transition = target.getAnimations().find((animation) => animation.transitionProperty === property);
        if (!transition) return resolve({ values: [readValue()], duration: 0 });
        const duration = Number(transition.effect.getComputedTiming().duration);
        transition.pause();
        // Reduced motion uses an effectively instant transition; check its endpoints.
        const checkpoints = duration <= 1 ? [0, 1] : [0, 0.25, 0.5, 0.75, 1];
        const values = checkpoints.map((progress) => {
          transition.currentTime = duration * progress;
          return readValue();
        });
        transition.finish();
        resolve({ values, duration });
      } catch (error) {
        reject(error);
      }
    });
    observer.observe(attributeTarget, { attributes: true, attributeFilter: ["data-open"] });
  });
}

export function createInlineSourcesBrowserCases({ pluginRoot, workspace, createPageScenario, tabLabels, generatedPayload }) {
  async function receiptFixture(name, { multiple = false, shortOverview = false } = {}) {
    const input = JSON.parse(await readFile(join(pluginRoot, "skills/visualize-data/assets/inline-sources-example.json"), "utf8"));
    input.items[0].queries[0].sourceRoles = [{ kind: "file", label: "sample-activation.csv",
      role: "Supplies the eligible and activated counts used in this calculation." }];
    input.items[0].queries[0].source.tables = [{ name: "analytics.product_adoption_summary", trust: {
      provider: "Snowflake", queryCount: 8967, uniqueUsers: 207, windowDays: 30,
      usageAsOf: "2026-09-04T12:00:00.000Z", lastQueriedAt: "2026-09-03T12:00:00.000Z",
      usageNote: "Successful queries, including reads through views.",
    } }];
    input.items[0].queries[0].source.filters.push("Eligibility: Active accounts in the same seven-day window, including all supported product experiences without summing overlapping source groups.");
    input.items[0].queries[0].source.metricDefinitions.push({ label: "Eligible accounts",
      definition: "Accounts that had access to setup during the reporting week." });
    if (multiple) {
      input.items[0].queries.push({ id: "python-export", source: { label: "CSV calculation", files: [{ label: "sample.csv" }], sql: "SELECT period, value FROM sample_csv;" },
        methods: [{ language: "python", code: "rate = activated / eligible\nchange = rate[-1] - rate[0]" }],
        columns: ["period", "value"], rows: Array.from({ length: 117 }, (_, index) => ({ period: `Week ${index + 1}`, value: index })),
        preview: { kind: "partial", note: "First 117 recorded rows.", totalRows: 130 } });
      input.items.push({ id: "release-context", title: "What changed in the release?", queries: [{ id: "release-note",
        summary: "The note records a setup change, not its effect on activation.",
        source: { label: "Synthetic release note", links: [{ label: "Release note", href: "https://example.com/releases" }] } }] });
    }
    if (shortOverview) {
      const finding = input.items[0];
      finding.assumptions = [];
      const query = finding.queries[0];
      query.summary = "A comparison of the two supplied weeks.";
      query.source.metricDefinitions = [];
      query.source.filters = [];
      query.source.caveats = [];
    }
    const metadata = await renderInlineSources({ input, output: join(workspace, `${name}.html`) });
    return { name, metadata, fragment: await readFile(metadata.path, "utf8"), root: `#${metadata.rootId}` };
  }

  async function inspectSourcesReceipt(browser, fixture, preview, { multiple, ...options }) {
    const scenario = await createPageScenario(browser, preview, { height: 700, ...options });
    try {
      const { page } = scenario;
      assert.equal(await page.locator("iframe").getAttribute("sandbox"), "allow-scripts");
      await page.locator("iframe").evaluate((el) => {
        const following = document.createElement("p");
        following.id = "following-conversation";
        following.textContent = "Conversation continues below Sources.";
        el.after(following);
      });
      const root = page.frameLocator("iframe").locator(fixture.root);
      const summary = multiple ? "Sources • 2" : "Sources";
      const toggle = root.getByRole("button", { name: summary, exact: true });
      await toggle.waitFor({ state: "visible" });
      assert.equal(await toggle.getAttribute("aria-expanded"), "false");
      const label = toggle.locator(":scope > span").first();
      assert.equal(await label.innerText(), summary, "The disclosure labels its finding cards as before");
      const labelStyle = await label.evaluate((el) => ({
        color: getComputedStyle(el).color, weight: getComputedStyle(el).fontWeight,
        background: getComputedStyle(el).backgroundColor,
      }));
      assert.deepEqual(labelStyle, {
        color: await toggle.evaluate((el) => getComputedStyle(el).color), weight: "400",
        background: "rgba(0, 0, 0, 0)",
      }, "The original disclosure text inherits the neutral button style");
      const resting = await toggle.evaluate((el) => ({
        background: getComputedStyle(el).backgroundColor,
        left: el.getBoundingClientRect().left,
        parentLeft: el.closest(".sources-receipt").getBoundingClientRect().left,
      }));
      assert.ok(Math.abs(resting.left - resting.parentLeft) <= 1, "Sources aligns with the receipt's left edge");
      await toggle.hover();
      const hovering = await toggle.evaluate(async (el) => {
        await Promise.all(el.getAnimations().map((animation) => animation.finished.catch(() => {})));
        return { background: getComputedStyle(el).backgroundColor, opacity: Number(getComputedStyle(el).opacity) };
      });
      assert.equal(hovering.background, resting.background, "Hover does not add a background highlight");
      assert.ok(hovering.opacity < 1 && hovering.opacity > .6, "Hover highlights Sources through opacity");
      await page.mouse.move(0, 0);
      await root.evaluate(armReceiptTransition, {
        targetSelector: ".receipt-expander", attributeSelector: ".receipt-expander",
        property: "grid-template-rows", measure: "height",
      });
      await toggle.click();
      const focusStyle = (element) => element.evaluate((el) => ({
        focused: el.matches(":focus"),
        outline: getComputedStyle(el).outlineStyle,
        cardOutline: getComputedStyle(el, "::after").outlineStyle,
      }));
      assert.equal((await focusStyle(toggle)).outline, "none", "Clicking Sources must not show a keyboard focus ring");
      const motion = await root.evaluate(async (el) => {
        const result = await el.receiptMotion;
        await Promise.all(el.shadowRoot.querySelector(".receipt-expander").getAnimations({ subtree: true })
          .map((animation) => animation.finished.catch(() => {})));
        return result;
      });
      const heights = motion.values;
      const finalHeight = heights.at(-1);
      if (options.reducedMotion !== "reduce") {
        assert.ok(motion.duration > 0, "Disclosure must create a real layout transition");
        assert.ok(heights.some((height) => height > 1 && height < finalHeight - 1), "Disclosure must interpolate its layout height");
      } else {
        assert.ok(motion.duration <= 1, "Reduced motion must settle within one millisecond");
        assert.ok(heights.every((height) => height < 1 || Math.abs(height - finalHeight) <= 1),
          `Reduced motion must settle without intermediate layouts: ${JSON.stringify(heights)}`);
      }
      // Model entering the sandboxed receipt after Tab began in its parent: the
      // receipt sees the new focus and keyup, but not the parent's keydown.
      await toggle.focus();
      await toggle.evaluate((el) => el.dispatchEvent(new KeyboardEvent("keyup", { key: "Tab", bubbles: true, composed: true })));
      assert.equal((await focusStyle(toggle)).outline, "solid", "Tab entry from the host restores keyboard focus styling");
      const card = root.getByRole("article", { name: "How did activation change?", exact: true });
      assert.equal(await card.evaluate((el) => getComputedStyle(el).boxShadow), "none",
        "The Sources card border must not rely on a shadow that clips in the expanding container");
      if (multiple) {
        assert.equal(await card.getAttribute("data-open"), "false");
        const sampleChevron = async () => card.evaluate(armReceiptTransition, {
          targetSelector: '.receipt-card-toggle [data-dashboard-icon="chevronDown"]',
          property: "transform", measure: "angle",
        });
        const verifyChevron = async (expanded) => {
          const result = await card.evaluate(async (el) => {
            const motion = await el.receiptMotion;
            await Promise.all(el.getAnimations({ subtree: true }).map((animation) => animation.finished.catch(() => {})));
            return { angles: motion.values, duration: motion.duration,
              sameNode: el.receiptMotionElement === el.querySelector('.receipt-card-toggle [data-dashboard-icon="chevronDown"]') };
          });
          assert.equal(result.sameNode, true, "Expand/collapse must rotate the existing chevron rather than replace it");
          assert.ok(Math.abs(result.angles.at(-1) - (expanded ? 180 : 0)) < 1);
          if (options.reducedMotion !== "reduce") {
            assert.ok(result.duration > 0, "The chevron must create a real transform transition");
            assert.ok(result.angles.some((angle) => angle > 1 && angle < 179), "The chevron must interpolate its rotation");
          } else {
            assert.ok(result.duration <= 1, "Reduced motion must settle within one millisecond");
            assert.ok(result.angles.every((angle) => angle < 1 || angle > 179));
          }
        };
        for (const edge of ["left", "right", "top", "bottom"]) {
          const bounds = await card.boundingBox();
          const position = { x: edge === "left" ? 2 : edge === "right" ? bounds.width - 2 : bounds.width / 2,
            y: edge === "top" ? 2 : edge === "bottom" ? bounds.height - 2 : bounds.height / 2 };
          await sampleChevron();
          await card.click({ position });
          assert.equal(await card.getAttribute("data-open"), "true", `Clicking the ${edge} card padding must expand it`);
          assert.equal(await card.evaluate((el) => getComputedStyle(el).boxShadow), "none",
            "Expanded Sources cards retain a clean border without a clipped shadow");
          await verifyChevron(true);
          await sampleChevron();
          await card.getByRole("button", { name: "Collapse How did activation change?", exact: true }).click();
          assert.equal(await card.getAttribute("data-open"), "false");
          await verifyChevron(false);
          const collapsedFocus = await focusStyle(card.getByRole("button", { name: "How did activation change?", exact: true }));
          assert.equal(collapsedFocus.outline, "none");
          assert.equal(collapsedFocus.cardOutline, "none", "Pointer collapse must not leave the full-card keyboard ring");
        }
        await card.getByRole("button", { name: "How did activation change?", exact: true }).press("Enter");
        assert.equal(await card.getAttribute("data-open"), "true");
        await card.getByRole("button", { name: "Collapse How did activation change?", exact: true }).press("Tab");
        assert.equal(await card.evaluate((el) => el.getRootNode().activeElement?.getAttribute("role")), "tab",
          "Tab from the expanded toggle must enter this card's content, not skip to the next card");
        await card.getByRole("tab", { name: "Overview", exact: true }).press("Shift+Tab");
        await card.getByRole("button", { name: "Collapse How did activation change?", exact: true }).press("Escape");
        assert.equal(await card.getAttribute("data-open"), "false");
        assert.equal(await toggle.getAttribute("aria-expanded"), "true", "Escape from the persistent toggle closes its card first");
        assert.equal((await focusStyle(card.getByRole("button", { name: "How did activation change?", exact: true }))).cardOutline,
          "solid", "Keyboard Escape restores visible focus to the collapsed card");
        await card.getByRole("button", { name: "How did activation change?", exact: true }).click();
      } else assert.equal(await card.getByRole("button", { name: /Collapse/ }).count(), 0);
      await card.evaluate(async (el) => {
        await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)));
        await Promise.all(el.getAnimations({ subtree: true }).map((animation) => animation.finished.catch(() => {})));
      });
      assert.equal(await card.locator(".receipt-details").count(), 0, "Overview has no secondary Details disclosure");
      const overviewLayout = await card.locator(".receipt-overview").first().evaluate((el) => {
        const definition = el.querySelector(".receipt-definitions");
        return { order: [...el.children].slice(0, 4).map((child) => child.className),
          background: getComputedStyle(definition).backgroundColor,
          overviewBackground: getComputedStyle(el).backgroundColor,
          padding: getComputedStyle(definition).paddingLeft,
          left: definition.getBoundingClientRect().left,
          overviewLeft: el.getBoundingClientRect().left,
          labelCount: definition.querySelectorAll(".source-label").length };
      });
      assert.deepEqual(overviewLayout.order, ["receipt-definitions", "source-group receipt-qualifications", "source-group"]);
      assert.equal(overviewLayout.background, overviewLayout.overviewBackground, "Definitions have no separate surface");
      assert.equal(overviewLayout.padding, "0px");
      assert.ok(Math.abs(overviewLayout.left - overviewLayout.overviewLeft) <= 1);
      assert.equal(overviewLayout.labelCount, 1, "Definitions use the same quiet heading as neighboring sections");
      assert.equal(await card.locator(".receipt-definitions .source-label").innerText(), "Definitions");
      assert.deepEqual(await card.locator(".receipt-definition-entry > p").allTextContents(), [
        "Activation rate is the share of eligible accounts that completed setup during the week.",
        "Eligible accounts: Accounts that had access to setup during the reporting week.",
      ], "Every definition names its term, including when the sentence does not repeat its label");
      assert.ok(await card.locator(".receipt-definition-list li").evaluateAll((entries) =>
        entries.length === 2 && entries.every((el) => getComputedStyle(el).display === "list-item"
          && getComputedStyle(el).listStyleType === "disc"
          && getComputedStyle(el).borderTopWidth === "0px"
          && getComputedStyle(el, "::marker").color === getComputedStyle(el).color)),
      "Definitions use text-colored bullets without per-entry dividers");
      assert.equal(await card.locator(".receipt-definition-entry .receipt-definition-metadata").count(), 0,
        "The example omits calculation detail that restates its definition");
      assert.equal(await card.locator(".receipt-definition-list").evaluate((el) => getComputedStyle(el).rowGap),
        "4px", "Definition bullets have the requested spacing");
      assert.equal(await card.locator(".receipt-definitions strong").first().evaluate((el) => getComputedStyle(el).fontWeight),
        "600", "Definition terms remain semibold");
      const qualifications = card.locator(".receipt-qualifications");
      assert.equal(await qualifications.locator(".source-label").innerText(), "Assumptions and caveats");
      assert.deepEqual(await qualifications.evaluate((el) => ({ border: getComputedStyle(el).borderTopWidth,
        padding: getComputedStyle(el).paddingTop })), { border: "0px", padding: "0px" },
      "Section boundaries remain free of an extra divider");
      assert.deepEqual(await qualifications.locator(".receipt-qualification-list li").allTextContents(),
        ["The two supplied weeks use the same activation definition.",
          "Synthetic example; no external source was queried."]);
      assert.equal(await qualifications.locator(".receipt-qualification-list").evaluate((el) => getComputedStyle(el).rowGap),
        "4px", "Assumption and caveat bullets have the requested spacing");
      assert.deepEqual(await qualifications.locator(".receipt-qualification-list li").first().evaluate((el) => ({
        display: getComputedStyle(el).display, marker: getComputedStyle(el).listStyleType,
      })), { display: "list-item", marker: "disc" }, "Each qualification keeps a visible list marker");
      assert.equal(await qualifications.locator(".receipt-qualification-list li").first().evaluate((el) => ({
        marker: getComputedStyle(el, "::marker").color, text: getComputedStyle(el).color,
      })).then(({ marker, text }) => marker === text), true, "The bullet and its text use the same color");
      const settlePanel = async () => {
        const panel = await card.evaluate(async (el) => {
          await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)));
          await Promise.all(el.getAnimations({ subtree: true }).map((animation) => animation.finished.catch(() => {})));
          const panels = el.querySelector(".receipt-panels");
          const active = panels.querySelector('[role="tabpanel"]:not([hidden])');
          return { container: panels.getBoundingClientRect().height, content: active.getBoundingClientRect().height,
            contentScrollHeight: active.scrollHeight, contentClientHeight: active.clientHeight,
            card: el.getBoundingClientRect().height, anchored: panels.hasAttribute("data-anchored"),
            lineHeight: parseFloat(getComputedStyle(panels).lineHeight) };
        });
        const host = await page.evaluate(async () => {
          await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)));
          const frame = document.querySelector("iframe").getBoundingClientRect();
          return { frame: frame.height, frameBottom: frame.bottom,
            following: document.getElementById("following-conversation").getBoundingClientRect().top,
            scroll: window.scrollY };
        });
        return { ...panel, ...host };
      };
      const overviewSize = await settlePanel();
      const assertVisiblePanel = async (action) => {
        const actual = await settlePanel();
        assert.ok(Math.abs(actual.container - actual.content) <= 1,
          `${action} must size the active panel to its container: ${JSON.stringify(actual)}`);
        assert.ok(actual.following >= actual.frameBottom - 1,
          `${action} must leave following conversation below the iframe: ${JSON.stringify(actual)}`);
        return actual;
      };
      assert.equal(overviewSize.anchored, false, "Overview retains its natural height without blank space");
      assert.ok(overviewSize.contentScrollHeight <= overviewSize.contentClientHeight + 1);
      const assertAnchoredPanel = async (action, baseline) => {
        const actual = await assertVisiblePanel(action);
        assert.equal(actual.anchored, true, `${action} must use the measured Overview anchor`);
        if (options.width <= 440) {
          assert.ok(actual.contentScrollHeight <= actual.contentClientHeight + 1,
            `${action} must grow naturally on mobile without trapping content`);
          return actual;
        }
        for (const key of ["container", "card", "frame"]) {
          assert.ok(Math.abs(actual[key] - baseline[key]) <= 1,
            `${action} must preserve ${key}: ${JSON.stringify({ baseline, actual })}`);
        }
        assert.ok(Math.abs(actual.following + actual.scroll - baseline.following - baseline.scroll) <= 1,
          `${action} must preserve the following conversation's document position`);
        return actual;
      };
      assert.equal(await card.locator(".receipt-overview .receipt-filters").count(), 0);
      const usageSource = card.locator('.receipt-overview .source-row[data-source-kind="table"]');
      assert.equal(await usageSource.locator(".source-trust").innerText(),
        "Table · Snowflake · 207 users · 8,967 queries over 30 days ending Sep 4, 2026 · Last queried Sep 3, 2026",
        "Warehouse usage must survive receipt generation and retain its observation window and last query date");
      assert.equal(await usageSource.locator(".source-usage-note").innerText(),
        "Successful queries, including reads through views.");
      const fileSource = card.locator('.receipt-overview .source-row[data-source-title="sample-activation.csv"]');
      assert.equal(await fileSource.locator(".source-trust").innerText(), "File",
        "A file must not inherit usage from the neighboring warehouse table");
      assert.equal(await fileSource.locator(".source-usage-note").count(), 0);
      const regularFont = await card.evaluate((el) => getComputedStyle(el).fontFamily);
      const sourceFonts = await card.locator(".receipt-overview .source-row-title").evaluateAll((elements) =>
        elements.map((el) => getComputedStyle(el).fontFamily));
      assert.ok(sourceFonts.length >= 2 && sourceFonts.every((font) => font === regularFont),
        "Table and file source names use the receipt's regular text font");
      assert.equal(await card.evaluate((el) => {
        const overview = el.querySelector(".receipt-overview");
        const box = overview.getBoundingClientRect();
        return [...overview.querySelectorAll("p, li, .source-row, .source-trust, .source-usage-note")].filter((entry) => entry.getClientRects().length).every((entry) => {
          const rect = entry.getBoundingClientRect();
          return rect.left >= box.left - 1 && rect.right <= box.right + 1 && entry.scrollWidth <= entry.clientWidth + 1;
        });
      }), true, "Long definitions, source labels, and warehouse usage wrap inside Overview");
      const sourceChip = fileSource;
      await sourceChip.scrollIntoViewIfNeeded();
      assert.equal(await sourceChip.evaluate((el) => getComputedStyle(el).cursor), "default",
        "Sources without a destination keep the default cursor");
      const restingSourceBackground = await sourceChip.evaluate((el) => getComputedStyle(el).backgroundColor);
      await sourceChip.hover();
      await sourceChip.evaluate(async (el) => Promise.all(el.getAnimations().map((animation) => animation.finished.catch(() => {}))));
      const sourceHoverBackground = await sourceChip.evaluate((el) => getComputedStyle(el).backgroundColor);
      assert.notEqual(sourceHoverBackground, restingSourceBackground,
        "A non-clickable source receives the same visible hover treatment as a link");
      await sourceChip.focus();
      const sourceTooltip = root.getByRole("tooltip");
      const iconParity = (chip) => chip.evaluate((el) => {
        const chipIcon = el.querySelector(".receipt-source-icon");
        const cardIcon = el.closest(".sources-receipt").querySelector(".receipt-tooltip .receipt-source-icon");
        const inspect = (icon) => {
          const style = getComputedStyle(icon);
          const rect = icon.getBoundingClientRect();
          return { kind: icon.dataset.sourceKind, variant: icon.dataset.sourceIcon,
            mask: style.maskImage, maskSize: style.maskSize,
            color: style.color, background: style.backgroundColor, width: rect.width, height: rect.height };
        };
        return { chip: inspect(chipIcon), card: inspect(cardIcon),
          wrapper: cardIcon.parentElement.getBoundingClientRect().toJSON() };
      });
      await sourceTooltip.waitFor({ state: "visible" });
      assert.equal(await sourceTooltip.locator(".source-preview-title").innerText(), await sourceChip.getAttribute("data-source-title"));
      assert.match(await sourceTooltip.locator(".source-preview-meta").innerText(), /File/u);
      assert.equal(await sourceTooltip.locator(".source-preview-summary").innerText(), await sourceChip.getAttribute("data-source-reason"));
      assert.deepEqual(await sourceTooltip.evaluate((el) => {
        const meta = el.querySelector(".source-preview-meta");
        const title = el.querySelector(".source-preview-title");
        const summary = el.querySelector(".source-preview-summary");
        return { padding: getComputedStyle(el).padding, iconGap: getComputedStyle(meta).gap,
          metaToTitle: Math.round(title.getBoundingClientRect().top - meta.getBoundingClientRect().bottom),
          titleToSummary: Math.round(summary.getBoundingClientRect().top - title.getBoundingClientRect().bottom) };
      }), { padding: "16px", iconGap: "6px", metaToTitle: 8, titleToSummary: 4 },
      "The receipt card uses the same tightened report spacing");
      const fileIcon = await iconParity(sourceChip);
      assert.deepEqual(fileIcon.card, fileIcon.chip, "The file card reuses the chip's exact icon mask and color");
      assert.equal(fileIcon.chip.variant, "file", "CSV inputs retain a generic file icon");
      assert.equal(fileIcon.card.maskSize, "contain", "The table/file icon keeps its native painted size");
      assert.deepEqual([fileIcon.card.width, fileIcon.card.height, fileIcon.wrapper.width, fileIcon.wrapper.height],
        [16, 16, 16, 16], "The card and chip icons occupy the same optical size");
      assert.deepEqual(await sourceTooltip.evaluate((el) => {
        const reference = el.ownerDocument.createElement("div");
        reference.className = "popover source-preview-card";
        el.parentElement.append(reference);
        const properties = ["display", "width", "padding", "borderWidth", "borderRadius", "backgroundColor",
          "boxShadow", "fontFamily", "fontSize", "lineHeight", "color"];
        const differences = properties.filter((property) =>
          getComputedStyle(el)[property] !== getComputedStyle(reference)[property]);
        reference.remove();
        return differences;
      }), [], "The receipt source card shares the report preview's computed styling");
      const tooltipBounds = await sourceTooltip.boundingBox();
      assert.ok(tooltipBounds.x >= 0 && tooltipBounds.width <= options.width,
        "Source inspection stays inside the narrow host");
      assert.equal(await sourceChip.evaluate((el) => {
        const next = el.closest(".receipt-overview").querySelector('.source-row[data-source-kind="table"]');
        el.dispatchEvent(new PointerEvent("pointerout", { bubbles: true, pointerType: "mouse", relatedTarget: next }));
        next.dispatchEvent(new PointerEvent("pointerover", { bubbles: true, pointerType: "mouse", relatedTarget: el }));
        const tooltip = el.closest(".sources-receipt").querySelector(".receipt-tooltip");
        return !tooltip.hidden && tooltip.querySelector(".source-preview-title")?.textContent === next.dataset.sourceTitle;
      }), true, "An adjacent source replaces an already-open tooltip without another delay");
      const tableIcon = await iconParity(usageSource);
      assert.deepEqual(tableIcon.card, tableIcon.chip, "The adjacent table card retains its matching chip icon");
      assert.equal(tableIcon.chip.variant, "table");
      assert.notEqual(fileIcon.chip.mask, tableIcon.chip.mask, "Tables and files use distinct glyphs");
      assert.notEqual(fileIcon.chip.color, tableIcon.chip.color, "Tables and files use distinct colors");
      await sourceChip.press("Escape");
      await sourceTooltip.waitFor({ state: "hidden" });
      assert.equal(await toggle.getAttribute("aria-expanded"), "true", "Escape dismisses the tooltip before collapsing the receipt");
      assert.equal(await sourceChip.evaluate((el) => {
        el.dispatchEvent(new PointerEvent("pointerover", { bubbles: true, pointerType: "mouse" }));
        return el.closest(".sources-receipt").querySelector(".receipt-tooltip").hidden;
      }), true, "A fresh hover starts with a delay when no tooltip is open");
      await sourceTooltip.waitFor({ state: "visible" });
      await sourceChip.press("Escape");
      await sourceTooltip.waitFor({ state: "hidden" });
      const overviewTab = card.getByRole("tab", { name: "Overview", exact: true });
      await overviewTab.focus();
      await page.mouse.move(0, 0);
      await sourceChip.hover();
      await overviewTab.press("Escape");
      await new Promise((resolve) => setTimeout(resolve, 350));
      assert.equal(await sourceTooltip.isVisible(), false, "Escape cancels the initial delayed hover");
      assert.equal(await toggle.getAttribute("aria-expanded"), "true");
      await card.getByRole("tab", { name: "SQL query", exact: true }).click();
      assert.equal((await focusStyle(card.getByRole("tab", { name: "SQL query", exact: true }))).outline, "none");
      const anchoredSize = await assertVisiblePanel("Switching to SQL query");
      assert.equal(anchoredSize.anchored, true);
      if (options.width <= 440) {
        assert.ok(anchoredSize.container < overviewSize.container,
          "Mobile SQL panels use their natural height without a blank Overview-sized gap");
      } else {
        assert.ok(anchoredSize.container >= overviewSize.container - 1);
        assert.ok(anchoredSize.container <= Math.max(overviewSize.container, 10 * overviewSize.lineHeight) + 2,
          "Only short Overviews receive a line-height-based reading floor");
      }
      const sqlPanel = card.getByRole("tabpanel", { name: "SQL query", exact: true });
      assert.equal(await sqlPanel.locator(".receipt-trace-chip").count(), 0,
        "Exact SQL is not preceded by a duplicate filter summary");
      const firstSql = multiple ? sqlPanel.getByRole("region", { name: "Illustrative activation export", exact: true }) : sqlPanel;
      assert.equal((await firstSql.locator("code").innerText()).replace(/^1\s*/u, ""),
        "SELECT week, activated, eligible FROM sample_activation ORDER BY week;");
      assert.deepEqual(await card.getByRole("tab").allTextContents(), tabLabels);
      assert.equal(await card.getByRole("button", { name: /^Source for /u }).count(), 0);
      assert.equal(await card.getByRole("button", { name: "Copy", exact: true }).count(), 0);
      await card.getByRole("tab", { name: "Data preview", exact: true }).click();
      await assertAnchoredPanel("Switching to Data preview", anchoredSize);
      await card.getByRole("tab", { name: "SQL query", exact: true }).click();
      await card.getByRole("tab", { name: "SQL query", exact: true }).press("ArrowRight");
      assert.equal(await card.getByRole("tab", { name: "Evidence flow", exact: true }).getAttribute("aria-selected"), "true");
      assert.deepEqual(await focusStyle(card.getByRole("tab", { name: "Evidence flow", exact: true })),
        { focused: true, outline: "solid", cardOutline: "none" }, "Arrow-key navigation must show keyboard focus");
      const evidencePanel = card.getByRole("tabpanel", { name: "Evidence flow", exact: true });
      await assertAnchoredPanel("Switching to Evidence flow with the keyboard", anchoredSize);
      assert.equal(await card.locator(".receipt-attribution").count(), 0, "Receipt prose does not append source-name annotations");
      await evidencePanel.locator('[data-checkpoint="filter"] summary').click();
      assert.equal(await evidencePanel.locator(".receipt-trace-chips").count(), 1,
        "Filters use one wrapping list without unexplained source sections");
      assert.equal(await evidencePanel.locator(":scope > :not(.source-trace)").count(), 0,
        "All supporting evidence belongs inside checkpoints");
      const filterTypography = await evidencePanel.locator(".receipt-trace-chip").evaluateAll((elements) => elements.map((el) => {
        const style = getComputedStyle(el);
        return { text: el.textContent, childCount: el.children.length,
          typography: [style.fontFamily, style.fontSize, style.fontWeight, style.lineHeight, style.color] };
      }));
      const periodQuery = generatedPayload(fixture).items[0].queries[0];
      const periodScope = multiple ? `${periodQuery.source.label}: ` : "";
      assert.deepEqual(filterTypography.filter(({ text }) => text.includes("Reporting period = ")).map(({ text }) => text),
        [`${periodScope}Reporting period = ${periodQuery.reportingPeriod}`],
        "The reporting period appears once and retains its owning source in a multi-source card");
      assert.ok(filterTypography.every(({ childCount, typography }) => childCount === 0
        && JSON.stringify(typography) === JSON.stringify(filterTypography[0].typography)),
        "Reporting period and filters share typography without nested source attribution");
      assert.match(await evidencePanel.locator(".receipt-trace-chips").innerText(), /including all supported product experiences/u);
      assert.equal(await evidencePanel.locator(".receipt-trace-chips").evaluate((el) => {
        const box = el.getBoundingClientRect();
        return [...el.querySelectorAll(".receipt-trace-chip")].every((entry) => {
          const rect = entry.getBoundingClientRect();
          return rect.left >= box.left - 1 && rect.right <= box.right + 1 && entry.scrollWidth <= entry.clientWidth + 1;
        });
      }), true, "The complete filter list wraps in Evidence flow");
      const detail = evidencePanel.locator('[data-checkpoint="source"] details');
      assert.equal(await detail.getAttribute("open"), null);
      await detail.locator("summary").click();
      assert.equal((await focusStyle(detail.locator("summary"))).outline, "none", "Pointer disclosure does not show a keyboard focus ring");
      assert.match(await detail.innerText(), /Supplies the eligible and activated counts/u);
      assert.doesNotMatch(await evidencePanel.innerText(), /Recorded inputs|Snapshot captured/u);
      const arithmetic = evidencePanel.locator("details").filter({ hasText: "240 / 400 × 100 = 60%" });
      await arithmetic.locator("summary").click();
      assert.equal(await arithmetic.locator(".receipt-calculation-text").last().innerText(), "240 / 400 × 100 = 60%\n280 / 400 × 100 = 70%\nChange: +10 percentage points");
      assert.equal(await arithmetic.locator(".receipt-trace-section-label").filter({ hasText: /^Calculation$/u }).count(), 0);
      const calculationTypography = await arithmetic.locator(".receipt-calculation-text").evaluateAll((elements) => elements.map((el) => {
        const style = getComputedStyle(el); return [style.fontFamily, style.fontSize, style.color, style.lineHeight];
      }));
      assert.ok(calculationTypography.every((value) => JSON.stringify(value) === JSON.stringify(calculationTypography[0])),
        "Supplemental formulas and worked arithmetic use the same body typography");
      await assertAnchoredPanel("Expanding evidence checkpoints", anchoredSize);
      if (multiple) {
        const python = evidencePanel.locator("details").filter({ hasText: "rate = activated / eligible" });
        assert.equal(await python.getAttribute("open"), "", "Python shares the already expanded Calculation checkpoint");
        assert.match(await python.locator(".receipt-method").last().innerText(), /rate = activated \/ eligible/u);
        await card.getByRole("tab", { name: "SQL query", exact: true }).click();
        assert.match(await sqlPanel.getByRole("region", { name: "CSV calculation", exact: true }).innerText(), /SELECT period, value FROM sample_csv/u);
        await card.getByRole("tab", { name: "Data preview", exact: true }).click();
        const dataPanel = card.getByRole("tabpanel", { name: "Data preview", exact: true });
        const csvData = dataPanel.getByRole("region", { name: "CSV calculation", exact: true });
        const longPreviewSize = await assertAnchoredPanel("Opening a long data preview", anchoredSize);
        if (options.width <= 440) {
          assert.ok(longPreviewSize.contentScrollHeight <= longPreviewSize.contentClientHeight + 1,
            "The long preview grows with the page on mobile");
        } else {
          assert.ok(longPreviewSize.contentScrollHeight > longPreviewSize.contentClientHeight + 100,
            "The long preview scrolls inside the Overview-sized tab area");
        }
        if (options.width === 736) {
          await page.setViewportSize({ width: 352, height: 700 });
          const resized = await assertVisiblePanel("Resizing with a long preview active");
          assert.equal(resized.anchored, true, "A width change must keep non-Overview tabs bounded");
          assert.ok(resized.contentScrollHeight <= resized.contentClientHeight + 1,
            "The long preview grows with the page after the receipt narrows");
          await card.getByRole("tab", { name: "Overview", exact: true }).click();
          const narrowOverview = await assertVisiblePanel("Measuring the narrow Overview");
          assert.equal(narrowOverview.anchored, false);
          assert.ok(narrowOverview.container > overviewSize.container,
            "The visible Overview remeasures its wrapped content at the new width");
          assert.ok(resized.container > narrowOverview.container,
            "The mobile data preview uses its own natural height");
          await card.getByRole("tab", { name: "Data preview", exact: true }).click();
          const narrowPreview = await assertVisiblePanel("Showing the narrow data preview");
          assert.equal(narrowPreview.anchored, true);
          assert.ok(Math.abs(narrowPreview.container - resized.container) <= 1);
          await page.setViewportSize({ width: 768, height: 700 });
          const restoredPreview = await assertVisiblePanel("Keeping the data preview bounded while widening");
          assert.equal(restoredPreview.anchored, true);
          await card.getByRole("tab", { name: "Overview", exact: true }).click();
          const restoredOverview = await assertVisiblePanel("Remeasuring Overview at its original width");
          assert.ok(Math.abs(restoredOverview.container - overviewSize.container) <= 1);
          assert.ok(Math.abs(restoredPreview.container - restoredOverview.container) <= 1,
            "Widening while Data preview is active immediately restores the Overview height");
          await card.getByRole("tab", { name: "Data preview", exact: true }).click();
          await assertAnchoredPanel("Restoring the width with a long preview active", anchoredSize);
        }
        if (options.width > 440) {
          await dataPanel.focus();
          await dataPanel.press("End");
          const keyboardScroll = await dataPanel.evaluate(async (el) => {
            const start = performance.now();
            while (el.scrollTop <= 0 && performance.now() - start < 1500)
              await new Promise(requestAnimationFrame);
            return { scrollTop: el.scrollTop, scrollHeight: el.scrollHeight, clientHeight: el.clientHeight,
              focused: el.getRootNode().activeElement === el, overflowY: getComputedStyle(el).overflowY };
          });
          assert.ok(keyboardScroll.scrollTop > 0,
            `A keyboard user can scroll the long preview inside its tab panel: ${JSON.stringify(keyboardScroll)}`);
        }
        await assertAnchoredPanel("Scrolling the preview", anchoredSize);
        assert.equal(await dataPanel.getByRole("table").count(), 2, "Separate result sets stay separate within one shared tab");
        assert.match(await csvData.innerText(), /117 of 130 recorded rows/u);
        await csvData.getByRole("button", { name: "Next page", exact: true }).click();
        await csvData.getByRole("button", { name: "Next page", exact: true }).click();
        const shortPageSize = await assertAnchoredPanel("Paging to the shorter last result page", anchoredSize);
        assert.ok(shortPageSize.contentScrollHeight < longPreviewSize.contentScrollHeight,
          "The final result page is shorter inside the stable panel");
        assert.match(await csvData.getByRole("table", { name: "Reviewed data", exact: true }).innerText(), /Week 117/u);
        assert.equal(await csvData.getByRole("button", { name: "Next page", exact: true }).isEnabled(), false);
        assert.match(await dataPanel.getByRole("region", { name: "Illustrative activation export", exact: true }).innerText(), /240/u);
        await card.getByRole("tab", { name: "Overview", exact: true }).click();
        const returnedOverview = await assertVisiblePanel("Returning to Overview");
        assert.equal(returnedOverview.anchored, false);
        assert.ok(Math.abs(returnedOverview.container - overviewSize.container) <= 1);
        const overview = card.getByRole("tabpanel", { name: "Overview", exact: true });
        assert.equal(await overview.getByRole("heading", { level: 3 }).count(), 0, "Overview is organized around the finding, not repeated source blocks");
        assert.equal(await overview.getByText("Sources", { exact: true }).count(), 1);
        assert.doesNotMatch(await overview.innerText(), /240 \/ 400|280 \/ 400/u, "Worked arithmetic belongs in Evidence flow");
        await card.getByRole("tab", { name: "Data preview", exact: true }).click();
        assert.match(await csvData.getByRole("table", { name: "Reviewed data", exact: true }).innerText(), /Week 117/u,
          "Each source's paging state survives shared tab changes");
        await card.getByRole("tab", { name: "Data preview", exact: true }).press("Escape");
        await card.getByRole("button", { name: "How did activation change?", exact: true }).waitFor({ state: "visible" });
        assert.equal(await card.evaluate((el) => el.getRootNode().activeElement?.getAttribute("aria-label")), "How did activation change?");
        const other = root.getByRole("article", { name: "What changed in the release?", exact: true });
        await other.getByRole("button", { name: "What changed in the release?", exact: true }).click();
        assert.equal(await other.getByRole("tab").count(), 0);
        assert.equal(await other.getByRole("tabpanel").count(), 0);
        assert.equal(await other.locator(".receipt-confidence-callout, .receipt-confidence").count(), 0,
          "No finding renders a confidence label");
        assert.equal(await other.getByRole("button", { name: "Collapse What changed in the release?", exact: true }).getAttribute("aria-description"), null);
        assert.match(await other.getByRole("region", { name: "Source details", exact: true }).innerText(), /The note records a setup change, not its effect on activation/u);
        assert.equal(await other.getByText("What this supports", { exact: true }).count(), 0);
        const linkedSource = other.getByRole("link", { name: "Release note", exact: true });
        assert.equal(await linkedSource.getAttribute("href"), "https://example.com/releases");
        assert.equal(await linkedSource.locator(".source-row-title").evaluate((el) => getComputedStyle(el).fontFamily),
          await other.evaluate((el) => getComputedStyle(el).fontFamily),
          "Linked document source names use the same regular text font");
        assert.equal(await linkedSource.evaluate((el) => getComputedStyle(el).cursor), "pointer");
        await linkedSource.hover();
        await linkedSource.evaluate(async (el) => Promise.all(el.getAnimations().map((animation) => animation.finished.catch(() => {}))));
        assert.equal(await linkedSource.evaluate((el) => getComputedStyle(el).backgroundColor), sourceHoverBackground,
          "Linked and non-linked source chips share the same hover surface");
        await linkedSource.focus();
        await sourceTooltip.waitFor({ state: "visible" });
        const documentIcon = await iconParity(linkedSource);
        assert.deepEqual(documentIcon.card, documentIcon.chip,
          "The linked document card retains the chip's exact icon mask, tone, and size");
        assert.equal(documentIcon.card.maskSize, "108%", "The linked source's inset SVG is optically balanced in both places");
        await linkedSource.press("Escape");
        await other.getByRole("button", { name: "Collapse What changed in the release?", exact: true }).click();
        assert.equal(await other.getAttribute("data-open"), "false");
        await other.getByRole("button", { name: "What changed in the release?", exact: true }).click();
        await other.locator(".receipt-card-title").click();
        assert.equal(await other.getAttribute("data-open"), "false", "The tab-free card header retains click-to-collapse");
      }
      if (!multiple && options.width === 736) {
        await card.getByRole("tab", { name: "Overview", exact: true }).click();
        const wide = await assertVisiblePanel("Returning to wide Overview");
        await page.setViewportSize({ width: 352, height: 700 });
        const narrow = await assertVisiblePanel("Reflowing the visible Overview");
        assert.ok(narrow.container > wide.container, "The Overview grows naturally as its content wraps at a narrow width");
        await card.getByRole("tab", { name: "SQL query", exact: true }).click();
        const narrowSql = await assertVisiblePanel("Showing a narrow SQL tab without unused space");
        assert.equal(narrowSql.anchored, true);
        assert.ok(narrowSql.container < narrow.container,
          "Mobile receipt tabs use their natural height instead of preserving the taller Overview");
        await page.setViewportSize({ width: 768, height: 700 });
        await card.getByRole("tab", { name: "Overview", exact: true }).click();
        const restored = await assertVisiblePanel("Recalculating Overview after resize");
        assert.ok(Math.abs(restored.container - wide.container) <= 1);
      }
      assert.equal(await root.evaluate((el) => {
        const receipt = el.shadowRoot.querySelector(".sources-receipt");
        return receipt.scrollWidth <= receipt.clientWidth + 1;
      }), true, "Receipt must not overflow its inline width");
      // Exercise live host tokens, not just the operating system's light/dark
      // preference. A bundled theme inside the shadow root must not mask them.
      if (await card.getAttribute("data-open") === "false")
        await card.getByRole("button", { name: "How did activation change?", exact: true }).click();
      await card.getByRole("tab", { name: "Overview", exact: true }).click();
      for (const palette of [
        { background: "rgb(248, 243, 230)", text: "rgb(48, 42, 32)", secondary: "rgb(105, 91, 70)", border: "rgb(191, 174, 146)", popover: "rgb(255, 250, 238)", accent: "rgb(128, 60, 20)" },
        { background: "rgb(24, 32, 43)", text: "rgb(230, 237, 247)", secondary: "rgb(168, 185, 207)", border: "rgb(67, 85, 108)", popover: "rgb(34, 45, 61)", accent: "rgb(155, 201, 255)" },
      ]) {
        await root.evaluate((el, palette) => {
          const style = el.ownerDocument.documentElement.style;
          style.colorScheme = palette.background === "rgb(248, 243, 230)" ? "light" : "dark";
          for (const [token, value] of Object.entries({ background: palette.background, foreground: palette.text,
            "muted-foreground": palette.secondary, border: palette.border, popover: palette.popover,
            "accent-foreground": palette.accent })) style.setProperty(`--${token}`, value);
        }, palette);
        const colors = await card.evaluate(async (el) => {
          await Promise.all(el.getAnimations({ subtree: true }).map((animation) => animation.finished.catch(() => {})));
          return { background: getComputedStyle(el).backgroundColor, text: getComputedStyle(el).color,
            border: getComputedStyle(el).borderTopColor,
            secondary: getComputedStyle(el.querySelector('.source-tabs [aria-selected="false"]')).color };
        });
        assert.deepEqual(colors, { background: palette.background, text: palette.text,
          border: palette.border, secondary: palette.secondary }, "Receipt follows live custom host colors");
        await sourceChip.focus();
        await sourceTooltip.waitFor({ state: "visible" });
        assert.equal(await sourceTooltip.evaluate((el) => getComputedStyle(el).backgroundColor), palette.popover,
          "Source hover card follows the local popover surface");
        await sourceChip.press("Escape");
        await card.getByRole("tab", { name: "SQL query", exact: true }).click();
        assert.equal(await card.locator('.sql-keyword').first().evaluate((el) => getComputedStyle(el).color), palette.accent,
          "SQL keywords follow the local text accent");
        await card.getByRole("tab", { name: "Overview", exact: true }).click();
        if (!multiple && options.width === 736)
          await page.screenshot({ path: join(workspace, `receipt-theme-${palette.background === "rgb(248, 243, 230)" ? "warm" : "slate"}.png`), fullPage: true });
      }
      await scenario.verifyClean();
      process.stdout.write(`${JSON.stringify({ test: "inline-sources-receipt", multiple, ...options, result: "pass" })}\n`);
    } finally { await scenario.context.close(); }
  }

  async function inspectShortOverview(browser, fixture, preview) {
    const scenario = await createPageScenario(browser, preview, { width: 736, height: 700 });
    try {
      const root = scenario.page.frameLocator("iframe").locator(fixture.root);
      await root.getByRole("button", { name: "Sources", exact: true }).click();
      const card = root.getByRole("article", { name: "How did activation change?", exact: true });
      const panels = card.locator(".receipt-panels");
      const overview = card.getByRole("tabpanel", { name: "Overview", exact: true });
      await overview.waitFor({ state: "visible" });
      const before = await panels.evaluate(async (el) => {
        await Promise.all(el.getAnimations({ subtree: true }).map((animation) => animation.finished.catch(() => {})));
        return { height: el.getBoundingClientRect().height,
          lineHeight: parseFloat(getComputedStyle(el).lineHeight), anchored: el.hasAttribute("data-anchored") };
      });
      assert.equal(before.anchored, false);
      assert.equal(await card.locator(".receipt-definitions").count(), 0,
        "A brief document-backed explanation must not invent a Definitions section");
      assert.ok(before.height < 10 * before.lineHeight,
        "The sparse Overview exercises the readable-height exception");
      await card.getByRole("tab", { name: "Data preview", exact: true }).click();
      const dataHeight = await panels.evaluate((el) => el.getBoundingClientRect().height);
      assert.ok(dataHeight >= 10 * before.lineHeight - 1 && dataHeight > before.height,
        "Other tabs show a usable reading area without padding the sparse Overview");
      await card.getByRole("tab", { name: "SQL query", exact: true }).click();
      assert.ok(Math.abs(await panels.evaluate((el) => el.getBoundingClientRect().height) - dataHeight) <= 1,
        "The short-Overview floor remains stable across non-Overview tabs");
      await card.getByRole("tab", { name: "Overview", exact: true }).click();
      assert.ok(Math.abs(await panels.evaluate((el) => el.getBoundingClientRect().height) - before.height) <= 1,
        "Returning to the sparse Overview removes the reading-height floor");
      await scenario.verifyClean();
      process.stdout.write(`${JSON.stringify({ test: "inline-sources-short-overview", result: "pass" })}\n`);
    } finally { await scenario.context.close(); }
  }

  return { receiptFixture, inspectSourcesReceipt, inspectShortOverview };
}

SHA-256: d65fbfde089d03f9af5e35687eeda4e2cafe4dacfb8ffd2b35c16afe9561e22e