mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
Merge the final display polish into release/v1.42.0
This commit is contained in:
commit
dcfec1f35d
144 files changed
+4866
-2817
No files matched your search
@@ -336,8 +336,8 @@ describe("<DashboardLayoutSection> — native-only widget group (issue #581)", (
|
||||
const html = render(<DashboardLayoutSection id="dashboard-layout" />);
|
||||
|
||||
expect(html).toContain('data-widget-id="bmi"');
|
||||
expect(html).toContain('aria-label="BMI — Tile"');
|
||||
expect(html).toContain('aria-label="BMI — Chart"');
|
||||
expect(html).toContain('aria-label="BMI: Tile"');
|
||||
expect(html).toContain('aria-label="BMI: Chart"');
|
||||
// Reflects the stored flags rather than inventing a default.
|
||||
const row = html.match(
|
||||
/data-widget-id="bmi"[\s\S]*?(?=data-slot="native-widget-row"|$)/,
|
||||
@@ -448,7 +448,7 @@ describe("<DashboardLayoutSection> — iOS-pin-only ids hidden from web (v1.11.2
|
||||
html.indexOf('data-slot="native-only-widgets"'),
|
||||
);
|
||||
for (const id of IOS_PIN_ONLY_WIDGET_IDS) {
|
||||
expect(sortableList).not.toContain(`${pinOnlyLabels[id]} — `);
|
||||
expect(sortableList).not.toContain(`${pinOnlyLabels[id]}: `);
|
||||
// ...and each is reachable exactly once, in the native-only group.
|
||||
expect(html).toContain(`data-widget-id="${id}"`);
|
||||
}
|
||||
@@ -465,11 +465,11 @@ describe("<DashboardLayoutSection> — iOS-pin-only ids hidden from web (v1.11.2
|
||||
describe("<DashboardLayoutSection> — disabled-module widget toggles", () => {
|
||||
// The achievements widget label drives its switch aria-label; it is the
|
||||
// canonical disabled-module probe (label resolves to "Achievements").
|
||||
const ACHIEVEMENTS_ARIA = "Achievements — ";
|
||||
const ACHIEVEMENTS_ARIA = "Achievements: ";
|
||||
// Mood is a module-owned widget too; weight is a core widget with NO module
|
||||
// entry, so it must survive any module-off state.
|
||||
const MOOD_ARIA = "Mood — ";
|
||||
const WEIGHT_ARIA = "Weight — ";
|
||||
const MOOD_ARIA = "Mood: ";
|
||||
const WEIGHT_ARIA = "Weight: ";
|
||||
|
||||
it("hides a widget toggle whose owning module is disabled", () => {
|
||||
authState.modules = { achievements: false };
|
||||
|
||||
@@ -105,7 +105,7 @@ describe("IntegrationStatusPill", () => {
|
||||
<IntegrationStatusPill state="parked" lastSyncAt={null} />,
|
||||
);
|
||||
expect(html).toContain("Paused");
|
||||
expect(html).toContain("Paused — reconnect");
|
||||
expect(html).toContain("Paused: reconnect");
|
||||
expect(html).toContain('data-state="parked"');
|
||||
});
|
||||
|
||||
@@ -115,7 +115,7 @@ describe("IntegrationStatusPill", () => {
|
||||
"de",
|
||||
);
|
||||
expect(html).toContain("Pausiert");
|
||||
expect(html).toContain("Pausiert — neu verbinden");
|
||||
expect(html).toContain("Pausiert: neu verbinden");
|
||||
});
|
||||
|
||||
// The three states the server verdict added. `stale` and `stalled` both
|
||||
|
||||
@@ -233,7 +233,7 @@ describe("IntegrationsSection — single-status-display contract (A5)", () => {
|
||||
// The pill flips to `data-state="parked"` and the resume banner
|
||||
// renders with the reconnect CTA. The legacy `error` reconnect text
|
||||
// (red) must NOT appear because the user-facing copy is the lighter
|
||||
// "Paused — reconnect" string, not "Error — reconnect".
|
||||
// "Paused: reconnect" string, not "Error — reconnect".
|
||||
it("Withings parked state surfaces the parked pill + resume CTA", () => {
|
||||
setIntegrationStatus({
|
||||
threshold: 3,
|
||||
@@ -256,7 +256,7 @@ describe("IntegrationsSection — single-status-display contract (A5)", () => {
|
||||
const html = render();
|
||||
expect(html).toContain('data-state="parked"');
|
||||
expect(html).toContain("Paused");
|
||||
expect(html).toContain("Paused — reconnect");
|
||||
expect(html).toContain("Paused: reconnect");
|
||||
expect(html).toContain('data-testid="withings-parked-banner"');
|
||||
expect(html).toContain('data-testid="withings-resume-button"');
|
||||
// The lastError is surfaced under the pill so the operator sees
|
||||
|
||||
@@ -190,9 +190,9 @@ describe("<MoodSection> — SSR smoke", () => {
|
||||
const groupRows = html.match(/data-slot="mood-group-row"/g);
|
||||
expect(groupRows?.length ?? 0).toBe(2);
|
||||
// One kebab per CUSTOM group row; the seeded row carries none.
|
||||
const kebabs = html.match(/More options — Garten/g);
|
||||
const kebabs = html.match(/More options: Garten/g);
|
||||
expect(kebabs?.length ?? 0).toBeGreaterThanOrEqual(1);
|
||||
expect(html).not.toContain("More options — Feelings");
|
||||
expect(html).not.toContain("More options: Feelings");
|
||||
});
|
||||
|
||||
it("renders custom tags by decrypted label, never the raw key", () => {
|
||||
@@ -206,7 +206,7 @@ describe("<MoodSection> — SSR smoke", () => {
|
||||
expect(html).toMatch(
|
||||
/data-slot="mood-tag-manage-row"[^>]*data-hidden="true"/,
|
||||
);
|
||||
expect(html).toContain("Show tag — stressed");
|
||||
expect(html).toContain("Show tag: stressed");
|
||||
});
|
||||
|
||||
it("surfaces the usage count badge", () => {
|
||||
@@ -219,7 +219,7 @@ describe("<MoodSection> — SSR smoke", () => {
|
||||
expect(html).toContain('data-slot="mood-archived-row"');
|
||||
expect(html).toContain("Altes Tag");
|
||||
expect(html).toContain("Restore");
|
||||
expect(html).toContain("Delete permanently — Altes Tag");
|
||||
expect(html).toContain("Delete permanently: Altes Tag");
|
||||
// The active custom tag must NOT appear in the archived card.
|
||||
const archivedCard = html.slice(
|
||||
html.indexOf('data-slot="mood-archived-tags-card"'),
|
||||
|
||||
@@ -900,7 +900,7 @@ function SortableWidgetRow({
|
||||
type="button"
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
aria-label={`${labels.dragHandle} — ${labels.widgetLabel}`}
|
||||
aria-label={`${labels.dragHandle}: ${labels.widgetLabel}`}
|
||||
// v1.4.47 W4 — `aria-describedby` is set after `{...attributes}`
|
||||
// so our shared hint paragraph wins over dnd-kit's own announcer
|
||||
// hookup. The announcer still fires on drag-start / drag-over /
|
||||
@@ -930,7 +930,7 @@ function SortableWidgetRow({
|
||||
<Switch
|
||||
checked={tileChecked}
|
||||
onCheckedChange={(v) => onToggleTile(widget.id, v)}
|
||||
aria-label={`${labels.widgetLabel} — ${labels.tileColumn}`}
|
||||
aria-label={`${labels.widgetLabel}: ${labels.tileColumn}`}
|
||||
disabled={disabled}
|
||||
data-slot="widget-tile-switch"
|
||||
/>
|
||||
@@ -939,7 +939,7 @@ function SortableWidgetRow({
|
||||
<Switch
|
||||
checked={widget.visible}
|
||||
onCheckedChange={(v) => onToggleChart(widget.id, v)}
|
||||
aria-label={`${labels.widgetLabel} — ${labels.chartColumn}`}
|
||||
aria-label={`${labels.widgetLabel}: ${labels.chartColumn}`}
|
||||
disabled={disabled}
|
||||
data-slot="widget-chart-switch"
|
||||
/>
|
||||
@@ -1012,7 +1012,7 @@ function StaticWidgetRow({
|
||||
<Switch
|
||||
checked={tileChecked}
|
||||
onCheckedChange={(v) => onToggleTile(widget.id, v)}
|
||||
aria-label={`${labels.widgetLabel} — ${labels.tileColumn}`}
|
||||
aria-label={`${labels.widgetLabel}: ${labels.tileColumn}`}
|
||||
disabled={disabled}
|
||||
data-slot="widget-tile-switch"
|
||||
/>
|
||||
@@ -1021,7 +1021,7 @@ function StaticWidgetRow({
|
||||
<Switch
|
||||
checked={widget.visible}
|
||||
onCheckedChange={(v) => onToggleChart(widget.id, v)}
|
||||
aria-label={`${labels.widgetLabel} — ${labels.chartColumn}`}
|
||||
aria-label={`${labels.widgetLabel}: ${labels.chartColumn}`}
|
||||
disabled={disabled}
|
||||
data-slot="widget-chart-switch"
|
||||
/>
|
||||
|
||||
@@ -402,7 +402,7 @@ function EcgManagerRow({
|
||||
onClick={onToggle}
|
||||
disabled={disabled}
|
||||
aria-pressed={visible}
|
||||
aria-label={`${visible ? hideLabel : showLabel} — ${title}`}
|
||||
aria-label={`${visible ? hideLabel : showLabel}: ${title}`}
|
||||
title={visible ? hideLabel : showLabel}
|
||||
data-slot="insights-pill-order-eye"
|
||||
data-visible={visible ? "true" : "false"}
|
||||
@@ -463,7 +463,7 @@ function SortablePillRow({
|
||||
type="button"
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
aria-label={`${dragHandleLabel} — ${title}`}
|
||||
aria-label={`${dragHandleLabel}: ${title}`}
|
||||
title={dragHandleLabel}
|
||||
disabled={disabled}
|
||||
data-slot="insights-pill-order-handle"
|
||||
@@ -481,7 +481,7 @@ function SortablePillRow({
|
||||
onClick={() => onToggle(id, !visible)}
|
||||
disabled={disabled}
|
||||
aria-pressed={visible}
|
||||
aria-label={`${visible ? hideLabel : showLabel} — ${title}`}
|
||||
aria-label={`${visible ? hideLabel : showLabel}: ${title}`}
|
||||
title={visible ? hideLabel : showLabel}
|
||||
data-slot="insights-pill-order-eye"
|
||||
data-visible={visible ? "true" : "false"}
|
||||
|
||||
@@ -63,7 +63,7 @@ describe("OAuthProviderCard — parked + test + data-link parity", () => {
|
||||
expect(html).toContain('data-state="parked"');
|
||||
expect(html).toContain('data-testid="polar-parked-banner"');
|
||||
expect(html).toContain('data-testid="polar-resume-button"');
|
||||
expect(html).toContain("Paused — reconnect");
|
||||
expect(html).toContain("Paused: reconnect");
|
||||
// The parked banner uses the same warning treatment as the WHOOP card.
|
||||
expect(html).toContain("border-warning/30 bg-warning/10");
|
||||
});
|
||||
@@ -157,7 +157,7 @@ describe("OAuthProviderCard — per-user BYO credentials form (v1.17.1)", () =>
|
||||
syncHealth: { verdict: "pending_first_sync", since: null },
|
||||
},
|
||||
});
|
||||
expect(html).toContain("Saved — enter new to replace");
|
||||
expect(html).toContain("Saved. Enter new to replace");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user