Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions frontend/src/components/LeftoverMapPlot.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1275,8 +1275,8 @@ describe("LeftoverMapPlot", () => {
);
expect(screen.queryByLabelText(/leftover map comparison graphic reconstruction/)).not.toBeInTheDocument();
expect(screen.queryByLabelText(/leftover-map reconstruction/)).not.toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent(
"Leftover map used 2 of 3 scored posts (complete-case)",
);
Expand Down Expand Up @@ -1391,8 +1391,8 @@ describe("LeftoverMapPlot", () => {
expect(
screen.getByLabelText("leftover map comparison graphic reconstruction R̂ +0.25"),
).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent(
"Leftover map used 2 of 3 scored posts (complete-case)",
);
Expand Down Expand Up @@ -1517,8 +1517,8 @@ describe("LeftoverMapPlot", () => {
expect(
screen.getByLabelText("leftover map comparison graphic reconstruction R̂ +0.25"),
).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent(
"Leftover map used 2 of 3 scored posts (complete-case)",
);
Expand Down Expand Up @@ -1653,8 +1653,8 @@ describe("LeftoverMapPlot", () => {
expect(
screen.getByLabelText("leftover map comparison graphic reconstruction R̂ +0.25"),
).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent(
"Leftover map used 2 of 3 scored posts (complete-case)",
);
Expand Down Expand Up @@ -1799,8 +1799,8 @@ describe("LeftoverMapPlot", () => {
expect(
screen.getByLabelText("leftover map comparison graphic reconstruction R̂ +0.25"),
).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent(
"Leftover map used 2 of 3 scored posts (complete-case)",
);
Expand Down Expand Up @@ -1955,8 +1955,8 @@ describe("LeftoverMapPlot", () => {
expect(
screen.getByLabelText("leftover map comparison graphic reconstruction R̂ +0.25"),
).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent(
"Leftover map used 2 of 3 scored posts (complete-case)",
);
Expand Down Expand Up @@ -2120,8 +2120,8 @@ describe("LeftoverMapPlot", () => {
expect(
screen.getByLabelText("leftover map comparison graphic reconstruction R̂ +0.25"),
).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent(
"Leftover map used 2 of 3 scored posts (complete-case)",
);
Expand Down Expand Up @@ -2291,8 +2291,8 @@ describe("LeftoverMapPlot", () => {
expect(
screen.getByLabelText("leftover map comparison graphic reconstruction R̂ +0.25"),
).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 0.12")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic: leftover-map distance d 1.84")).toBeInTheDocument();
expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent(
"Leftover map used 2 of 3 scored posts (complete-case)",
);
Expand Down
13 changes: 10 additions & 3 deletions frontend/src/components/LeftoverMapPlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ function leftoverMapPlotAxisText(
* labels. ADR 0318 captions leftover-map rank on that comparison graphic
* from already-named leftover-map rank while composing existing localized
* comparison-graphic and rank labels rather than adding SPA translation debt.
* ADR 0319 captions leftover-map distance on that comparison graphic using
* the same localized composition boundary rather than adding another static
* comparison-only translation key.
* Never invent a leftover score.
*/
export function LeftoverMapPlot({
Expand Down Expand Up @@ -327,9 +330,13 @@ export function LeftoverMapPlot({
x={segment.labelX}
y={segment.labelY}
textAnchor="middle"
aria-label={tf(LEFTOVER_MAP_PLOT_SEGMENT_DISTANCE, {
label: segment.distanceLabel,
})}
aria-label={
variant === "comparison"
? `${t(LEFTOVER_MAP_COMPARE_PLOT_LABEL)}: ${tf(LEFTOVER_MAP_PLOT_SEGMENT_DISTANCE, {
label: segment.distanceLabel,
})}`
: tf(LEFTOVER_MAP_PLOT_SEGMENT_DISTANCE, { label: segment.distanceLabel })
}
>
{segment.distanceLabel}
</text>
Expand Down
29 changes: 29 additions & 0 deletions frontend/src/leftoverMapDistanceLocalization.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { afterEach, describe, expect, it } from "vitest";
import { setLocale, t, tf, type Locale } from "./i18n";
import {
LEFTOVER_MAP_COMPARE_PLOT_LABEL,
LEFTOVER_MAP_PLOT_SEGMENT_DISTANCE,
} from "./leftoverMapPlotLayout";

const PRODUCT_LOCALES = ["ko", "zh", "ja", "vi"] as const satisfies readonly Exclude<Locale, "en">[];

function comparisonDistanceAccessibleName(label: string): string {
return `${t(LEFTOVER_MAP_COMPARE_PLOT_LABEL)}: ${tf(LEFTOVER_MAP_PLOT_SEGMENT_DISTANCE, { label })}`;
}

afterEach(() => {
setLocale("en");
});

describe("grouping-comparison leftover-map distance localization", () => {
it.each(PRODUCT_LOCALES)("keeps comparison distance accessible naming localized in %s", (locale) => {
setLocale(locale);
const comparisonLabel = t(LEFTOVER_MAP_COMPARE_PLOT_LABEL);
const distanceLabel = tf(LEFTOVER_MAP_PLOT_SEGMENT_DISTANCE, { label: "d 1.25" });

expect(comparisonLabel).not.toBe(LEFTOVER_MAP_COMPARE_PLOT_LABEL);
expect(distanceLabel).not.toBe("leftover-map distance d 1.25");
expect(distanceLabel).toContain("d 1.25");
expect(comparisonDistanceAccessibleName("d 1.25")).toBe(`${comparisonLabel}: ${distanceLabel}`);
});
});
40 changes: 40 additions & 0 deletions tests/test_grouping_comparison_graphic_distance_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""Executable contract for persisted distance on the grouping-comparison graphic."""

from pathlib import Path
import re


ROOT = Path(__file__).resolve().parents[1]
PLOT_SOURCE = ROOT / "frontend" / "src" / "components" / "LeftoverMapPlot.tsx"
LAYOUT_SOURCE = ROOT / "frontend" / "src" / "leftoverMapPlotLayout.ts"


def test_comparison_graphic_names_persisted_distance_with_distinct_localized_copy() -> None:
"""Comparison distance composes localized graphic and distance vocabulary."""
plot_source = PLOT_SOURCE.read_text(encoding="utf-8")
layout_source = LAYOUT_SOURCE.read_text(encoding="utf-8")

assert "LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_DISTANCE" not in layout_source
assert "LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_DISTANCE" not in plot_source
assert 'variant === "comparison"' in plot_source
assert (
'`${t(LEFTOVER_MAP_COMPARE_PLOT_LABEL)}: ${tf(LEFTOVER_MAP_PLOT_SEGMENT_DISTANCE, {'
in plot_source
)
assert "label: segment.distanceLabel" in plot_source
assert ': tf(LEFTOVER_MAP_PLOT_SEGMENT_DISTANCE, { label: segment.distanceLabel })' in plot_source


def test_distance_projection_consumes_persisted_fail_closed_evidence() -> None:
"""Missing/non-finite distance omits while finite zero and signed values remain data-driven."""
layout_source = LAYOUT_SOURCE.read_text(encoding="utf-8")

assert re.search(
r"formatLeftoverMapDistance\(\s*pair\.leftover_distance\s*\)",
layout_source,
)
assert "value == null || !Number.isFinite(value)" in layout_source
assert "return `d ${value.toFixed(2)}`;" in layout_source
assert "Math.max(value" not in layout_source
assert "Math.min(value" not in layout_source
assert "Math.abs(value" not in layout_source
Loading