Task #204: Make attendee group headers more prominent
Original ask: in the executive-meetings schedule's attendee cell, the
"Virtual / Internal / External Attendance" group labels (rendered above
each attendee group) read like stray attendee names — text-xs with em-dash
decoration. The user wanted them to stand out visually as section labels.
Changes
- artifacts/tx-os/src/pages/executive-meetings.tsx (AttendeeGroup):
* Header now renders text-sm font-bold, navy color (#0B1E3F), centered.
* Hairline underline (border-b border-[#0B1E3F]/15) with explicit
print:border-b print:border-gray-400 fallback so the underline is
preserved on print stylesheets that strip translucent borders.
* Em-dash decoration removed from the label.
* pointer-events-none + select-none so clicks/selection target the
attendee names, not the label.
* Added stable data-testid="em-attendee-group-header" for tests.
Tests
- New spec artifacts/tx-os/tests/executive-meetings-attendee-group-headers.spec.mjs:
* Seeds its OWN multi-group meeting (2 virtual + 3 internal) on a unique
far-future date per locale (offsets 1/2) — never collides with real
schedule data.
* Asserts BOTH expected localised headers appear (virtual + internal),
and that the external header is absent.
* Adds a regression guard: a single-group (all-internal) meeting on a
different unique future date renders ZERO group headers.
* Temporarily flips admin's preferred_language per-test (with try/finally
+ afterAll restore) so AuthContext does not override the locale via
i18n.changeLanguage on auth restore.
- Existing executive-meetings-edit-toggle.spec.mjs still passes (6/6).
- All 4 new tests pass.
Drift / deviations
- The original draft test lived inline in the toggle spec and skipped
because today's seed data has no multi-group meetings. Moved it to its
own spec with self-seeded data per code-review feedback so coverage is
deterministic, header assertions are tightened (require both expected
labels, reject the external one, not "any two of three"), and a
single-group regression guard is added.
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
@@ -1,5 +1,27 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
import pg from "pg";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, join } from "node:path";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
// Load expected header strings from the SAME locale bundles the app
|
||||
// renders from, so the assertions stay in sync if the copy ever
|
||||
// changes.
|
||||
function loadLocale(lang) {
|
||||
const p = join(__dirname, "..", "src", "locales", `${lang}.json`);
|
||||
return JSON.parse(readFileSync(p, "utf8"));
|
||||
}
|
||||
const localeBundles = { en: loadLocale("en"), ar: loadLocale("ar") };
|
||||
function attendanceLabel(lang, kind) {
|
||||
const em = localeBundles[lang]?.executiveMeetings;
|
||||
if (!em) throw new Error(`Missing executiveMeetings namespace in ${lang}.json`);
|
||||
const key = `${kind}Attendance`; // virtualAttendance | internalAttendance | externalAttendance
|
||||
const val = em[key];
|
||||
if (!val) throw new Error(`Missing locale key executiveMeetings.${key} in ${lang}.json`);
|
||||
return val;
|
||||
}
|
||||
|
||||
// E2E coverage for Task #204: the per-group attendee headers
|
||||
// ("Virtual Attendance / Internal Attendance / External Attendance")
|
||||
@@ -201,13 +223,11 @@ for (const lang of ["en", "ar"]) {
|
||||
// match because the virtual header may be suffixed with the
|
||||
// platform name, e.g. " — Zoom"). This rejects any regression
|
||||
// that drops a header, mislabels a group, or renders the same
|
||||
// label twice.
|
||||
const virtualLabel =
|
||||
lang === "ar" ? "الحضور عبر الاتصال المرئي" : "Virtual Attendance";
|
||||
const internalLabel =
|
||||
lang === "ar" ? "الحضور الداخلي" : "Internal Attendance";
|
||||
const externalLabel =
|
||||
lang === "ar" ? "حضور خارجي" : "External Attendance";
|
||||
// label twice. Labels are read from the SAME locale bundle the
|
||||
// app renders from so copy edits won't silently break the spec.
|
||||
const virtualLabel = attendanceLabel(lang, "virtual");
|
||||
const internalLabel = attendanceLabel(lang, "internal");
|
||||
const externalLabel = attendanceLabel(lang, "external");
|
||||
|
||||
const seenTexts = [];
|
||||
for (let idx = 0; idx < 2; idx++) {
|
||||
|
||||
Reference in New Issue
Block a user