Safety Histogram: test evidence

Requirement-traced qualification evidence for the safety.viz histogram module.

Scope
35 coverage rows54 distinct requirement IDs
Tests executed
142 automated checks33 browser · 109 unit
Result
pass all passing16 evidence screenshots
Generated
2026-07-12 05:50 UTC
Environment
linux 6.17.0-1018-azure · node v22.23.1 · playwright 1.61.1 · chromium 149.0.7827.55

Scope & approach

Traceability for the histogram module (extracted from the safety-histogram pilot, dev @ a3ff9f7, under #2), per the convention in CONTRIBUTING.md. Two requirement-ID schemes appear:

Each table row traces one requirement to the automated test(s) that evidence it: the requirement ID and its source-matrix rows link back to the reviewed specification, the issue column links the implementing work, and the result column shows the recorded outcome of every matching test from the committed evidence.json with its captured screenshots. Browser evidence is captured at fixed conditions (1280×800, device scale 1) on the canonical Linux CI environment.

Browser evidence (Playwright — tests/e2e/histogram.spec.js)

24 requirement rows · 24 tests

RequirementSource matrix rowsIssueTests & evidence
SH-CTRL-001/SH-CTRL-002/SH-CTRL-006SH-FUNC-001, SH-FUNC-002#2
  • pass SH-CTRL-001/SH-CTRL-002/SH-CTRL-006: renders measure, filter, axis, bin, and group controls (#2)
Evidence screenshot SH-CTRL-001-control-panel.pngEvidence screenshot SH-CTRL-006-shared-bin-multiples.png
SH-CTRL-003SH-FUNC-003#2
  • pass SH-CTRL-003: participant note updates when a filter is applied (#2)
SH-DATA-002SH-CFG-005#2
  • pass SH-DATA-002: missing and non-numeric results are dropped with a reported count and visible note (#2)
Evidence screenshot SH-DATA-002-invalid-data-note.png
SH-CHART-003SH-FUNC-008, SH-FUNC-010, SH-FUNC-012#2
  • pass SH-CHART-003/SH-FUNC-010/SH-FUNC-012: selecting a canvas bar opens a linked listing with record details and count (#2)
Evidence screenshot SH-FUNC-010-linked-listing.png
SH-FUNC-011#2
  • pass SH-FUNC-011: selecting a bar de-emphasizes the bars outside the linked listing (#2)
Evidence screenshot SH-FUNC-011-bar-de-emphasis.png
SH-LIST-001/002/003/004SH-FUNC-008#2
  • pass SH-LIST-001/SH-LIST-002/SH-LIST-003/SH-LIST-004: listing supports pagination, search, sorting, and CSV export (#2)
Evidence screenshot SH-LIST-004-search-sort-paginate.png
SH-CTRL-004SH-FUNC-004A, SH-FUNC-004B#2
  • pass SH-CTRL-004/SH-FUNC-004A/SH-FUNC-004B: normal range checkbox toggles a stable overlay region (#2)
Evidence screenshot SH-CTRL-004-normal-range-overlay.png
SH-FUNC-004C#2
  • pass SH-FUNC-004C: normal range control is hidden when the measure has no normal range data (#2)
Evidence screenshot SH-FUNC-004C-control-hidden-for-pulse.png
SH-CTRL-005SH-FUNC-005A, SH-FUNC-005B, SH-FUNC-005D#2
  • pass SH-CTRL-005/SH-FUNC-005A/SH-FUNC-005B/SH-FUNC-005D: x-axis limit inputs redraw and normalize invalid ranges (#2)
Evidence screenshot SH-CTRL-005-axis-limits.png
SH-FUNC-005C#2
  • pass SH-FUNC-005C: x-axis limit inputs support stepper increments of 1 (#2)
SH-CTRL-007#2
  • pass SH-CTRL-007: x-axis tick mode switches labels between centers and bin boundaries (#2)
Evidence screenshot SH-CTRL-007-boundary-ticks.png
SH-CHART-005— (see SH-REG-078 note)#2
  • pass SH-CHART-005: p-value annotations display the approximation and validation disclaimer (#2)
Evidence screenshot SH-CHART-005-pvalue-disclaimer.png
SH-CHART-004#2
  • pass SH-CHART-004: group-by renders grouped histograms (#2)
Evidence screenshot SH-CHART-004-grouped-multiples.png
SH-CHART-004/SH-CTRL-006#19
  • pass SH-CHART-004/SH-CTRL-006: grouped small multiples share the main chart's bin boundaries (#19)
Evidence screenshot SH-CHART-004-grouped-multiples.pngEvidence screenshot SH-CTRL-006-shared-bin-multiples.png
SH-CTRL-006#19
  • pass SH-CTRL-006: bin boundaries anchor to the measure results, not the filtered subset (#19)
Evidence screenshot SH-CTRL-006-shared-bin-multiples.png
SH-CTRL-008SH-REG-024, SH-REG-025, SH-REG-026#19
  • pass SH-CTRL-008/SH-REG-024/SH-REG-025/SH-REG-026: bin quantity and width inputs reflect the resolved binning (#19)
Evidence screenshot SH-CTRL-008-bins-inputs-populated.png
SH-CTRL-008SH-REG-020#19
  • pass SH-CTRL-008/SH-REG-020: editing Quantity switches the algorithm to Custom and recomputes the width (#19)
Evidence screenshot SH-CTRL-008-bins-inputs-populated.png
SH-API-001 (module scheme)— (see legacy-API note)#2
  • pass SH-API-001: lifecycle API supports init, setData, setSettings, render, resize, and destroy (#2)
SH-OVW-001#39
  • pass SH-OVW-001: the overview is the default view when start_value is not set (#39)
SH-OVW-001#39
  • pass SH-OVW-001: an unknown start_value warns and falls back to the overview (#39)
SH-OVW-002#39
  • pass SH-OVW-002: the overview renders one independently binned panel per measure (#39)
Evidence screenshot SH-OVW-002-overview-panels.png
SH-OVW-003#39
  • pass SH-OVW-003: clicking a small multiple opens that measure in the single-measure view (#39)
Evidence screenshot SH-OVW-003-click-through-to-pulse.png
SH-OVW-004#39
  • pass SH-OVW-004: selecting All Measures returns from a single-measure view to the overview (#39)
SH-OVW-005#39
  • pass SH-OVW-005: filters stay active in the overview and measure controls hide (#39)
Evidence screenshot SH-OVW-005-overview-filtered.png

Unit evidence (Vitest — tests/unit/histogram/)

11 requirement rows · 31 tests

RequirementSource matrix rowsIssueTests & evidence
SH-CFG-004..009 (defaults)SH-CFG-004..009#2

configure.test.js

  • pass histogram configure SH-CFG-004..009: default settings map the standard measure, result, id, unit, and normal-range columns (#2)
SH-CFG-010/011, SH-CHART-004SH-CFG-010, SH-CFG-011#2

configure.test.js

  • pass histogram configure SH-CFG-010: filter specs normalize strings and objects to value_col/label pairs (#2)
  • pass histogram configure SH-CFG-011: details default to id, filters, result, normal limits, and unit when unset (#2)
  • pass histogram configure SH-CHART-004: the group list always offers None and adopts an unknown group_by column (#2)
Evidence screenshot SH-CHART-004-grouped-multiples.png
SH-CFG-013/014SH-CFG-013, SH-CFG-014#2

configure.test.js

  • pass histogram configure SH-CFG-013/SH-CFG-014: normal-range control and initial display flags are configurable (#2)
SH-DATA-001/002SH-CFG-005#2

structureData.test.js

  • pass histogram checkInputs SH-DATA-001: missing required variables throw the pilot's error message (#2)
  • pass histogram checkInputs SH-DATA-001: the JSON schema publishes the data contract with required column mappings (#2)
  • pass histogram checkInputs SH-DATA-001/SH-DATA-003: valid long-format data with optional columns passes (#2)
  • pass histogram structureData SH-DATA-001: measure labels combine the measure with its unit when present (#2)
  • pass histogram structureData SH-DATA-002: missing and non-numeric results are removed with a reported count (#2)
Evidence screenshot SH-DATA-002-invalid-data-note.png
SH-CTRL-002/005/006SH-FUNC-004C (detection)#2

structureData.test.js

  • pass histogram binning matches the original renderer (#19) SH-CTRL-006: ADBDS Albumin reproduces the original renderer's bin parameters (#19)
  • pass histogram binning matches the original renderer (#19) SH-CTRL-006: bin quantity is clamped to the count of unique results (#19)
  • pass histogram binning matches the original renderer (#19) SH-CTRL-006: Scott's rule and Freedman-Diaconis enforce the original's 5-bin floor (#19)
  • pass histogram binning matches the original renderer (#19) SH-CTRL-006: Shimazaki-Shinomoto minimizes the original's cost function (#19)
  • pass histogram binning matches the original renderer (#19) SH-CTRL-006: zero-spread results collapse to a single bin (#19)
  • pass histogram getScales SH-CTRL-005: normalizeDomain swaps inverted lower/upper limits (#2)
  • pass histogram getScales SH-CTRL-005/SH-FUNC-005A/SH-FUNC-005B: resolveDomain applies user limits over the data extent (#2)
  • pass histogram structureData SH-CTRL-002: active filters subset rows by stringified equality (#2)
  • pass histogram structureData SH-CTRL-005: an explicit domain bounds the bins and clamps edge values (#2)
  • pass histogram structureData SH-CTRL-006: binning algorithms produce the original renderer's bin quantities (#2)
  • pass histogram structureData SH-CTRL-006: custom quantity and custom width drive the bin count (#2)
Evidence screenshot SH-CTRL-006-shared-bin-multiples.pngEvidence screenshot SH-CTRL-005-axis-limits.png
SH-CTRL-006 (original QC)#19

binning.test.js

  • pass histogram binning matches the original renderer (#19) SH-CTRL-006: ADBDS Albumin reproduces the original renderer's bin parameters (#19)
  • pass histogram binning matches the original renderer (#19) SH-CTRL-006: bin quantity is clamped to the count of unique results (#19)
  • pass histogram binning matches the original renderer (#19) SH-CTRL-006: Scott's rule and Freedman-Diaconis enforce the original's 5-bin floor (#19)
  • pass histogram binning matches the original renderer (#19) SH-CTRL-006: Shimazaki-Shinomoto minimizes the original's cost function (#19)
  • pass histogram binning matches the original renderer (#19) SH-CTRL-006: zero-spread results collapse to a single bin (#19)
  • pass histogram structureData SH-CTRL-006: binning algorithms produce the original renderer's bin quantities (#2)
  • pass histogram structureData SH-CTRL-006: custom quantity and custom width drive the bin count (#2)
Evidence screenshot SH-CTRL-006-shared-bin-multiples.png
SH-CTRL-005/007SH-FUNC-005A, SH-FUNC-005B#2

getScales.test.js

  • pass histogram getScales SH-CTRL-005: normalizeDomain swaps inverted lower/upper limits (#2)
  • pass histogram getScales SH-CTRL-005/SH-FUNC-005A/SH-FUNC-005B: resolveDomain applies user limits over the data extent (#2)
  • pass histogram getScales SH-CTRL-007: tick labels switch between bin centers and bin boundaries (#2)
  • pass histogram structureData SH-CTRL-005: an explicit domain bounds the bins and clamps edge values (#2)
Evidence screenshot SH-CTRL-005-axis-limits.pngEvidence screenshot SH-CTRL-007-boundary-ticks.png
SH-CHART-002/005SH-FUNC-011 (colors)#2

getPlugins.test.js

  • pass histogram getPlugins SH-CHART-002: bin descriptions report the count and value range in the pilot's wording (#2)
  • pass histogram getPlugins SH-CHART-005: p-values format with bounded precision (#2)
  • pass histogram getPlugins SH-CHART-005: the group-comparison screen needs 2+ groups and separates distinct groups (#2)
  • pass histogram getPlugins SH-CHART-005: the normality screen needs at least 3 values and stays within (0, 1) (#2)
Evidence screenshot SH-CHART-005-pvalue-disclaimer.png
SH-LIST-002/003/004#2

listing.test.js

  • pass histogram listing SH-LIST-002: pagination slices pages and clamps out-of-range page numbers (#2)
  • pass histogram listing SH-LIST-003: CSV export renders label headers and quoted, null-safe values (#2)
  • pass histogram listing SH-LIST-004: search filters rows case-insensitively across listing columns (#2)
  • pass histogram listing SH-LIST-004: sorting is numeric when both values are numeric, string otherwise, and null-safe (#2)
Evidence screenshot SH-LIST-004-search-sort-paginate.png
SH-DATA-001/003 (schema)SH-DATA-001#2

checkInputs.test.js

  • pass histogram checkInputs SH-DATA-001: missing required variables throw the pilot's error message (#2)
  • pass histogram checkInputs SH-DATA-001: the JSON schema publishes the data contract with required column mappings (#2)
  • pass histogram checkInputs SH-DATA-001/SH-DATA-003: valid long-format data with optional columns passes (#2)
  • pass histogram structureData SH-DATA-001: measure labels combine the measure with its unit when present (#2)
SH-API-001 (module export)#2

../main.test.js

  • pass safety.viz scaffold SH-API-001: the collection exposes the histogram module factory (#2)

Visual evidence

Every screenshot below is a committed baseline: the same PNG is the visual-regression baseline the browser suite asserts against and the evidence artifact shown here. Click any capture for the full-resolution image.

Source-matrix routing status (125 rows)

Legacy-API note: source-matrix SH-API-001 ("a factory to create a custom Webcharts chart object") describes the legacy Webcharts API, which the designs intentionally do not preserve (pilot SH-API-002). The module ships the pilot's lifecycle API instead — SH-API-001 in the module scheme.

SH-REG-024 note: the row's inputs-update behavior is evidenced by SH-CTRL-008; its info-icon clause (an ⓘ link to the algorithm's description) is not ported.

Reproducing this report

The evidence set is regenerated from a full test run and committed with the code it qualifies; CI fails when they drift. To verify or rebuild it:

npm ci
npm run evidence:check   # compare a fresh run against the committed evidence
npm run evidence         # regenerate docs/evidence/histogram/evidence.json

Screenshot baselines are canonical to the Linux CI runner; the repository's Update evidence baselines workflow is the authoritative way to refresh them. See CONTRIBUTING.md for the traceability convention.