4ace4469eb
Task #139: cover Enter/Esc/Tab keyboard editing of time, title, and attendee inline editors with end-to-end tests that seed via DB and log in via UI as admin/admin123. What this adds - artifacts/tx-os/tests/executive-meetings-keyboard-editing.spec.mjs with 7 tests: * Tab into time cell + Enter opens edit + valid times save via Enter (asserts PATCH on /api/executive-meetings/:id and DB row updated) * Time cell Esc restores originals and sends no PATCH * Title cell Enter opens edit and Enter saves via PATCH * Title cell Esc restores original and sends no PATCH * Attendee cell Enter opens edit and Enter saves via PUT on /api/executive-meetings/:id/attendees * Attendee cell Esc restores original and sends no PUT * Tab from title cell reaches the time cell in the same row Implementation notes / deviations - Each test seeds its own future-dated meeting (and attendee where needed) directly through the pg pool with a unique date, then cleans those rows in afterAll — same pattern as the existing schedule-features spec. - After every save the page invalidates the day query and refetches; assertions wait for that GET to land before reading the DOM, which removed an early flaky-timing failure. - The title save test was originally written to do select-all + type. We discovered (via instrumented PATCH inspection) that the EditableCell writes to title_ar vs title_en based on the user's preferredLanguage, not the visible UI direction — admin's preferred language is ar, so saves go to title_ar even when the schedule is rendered LTR. The test now appends a unique suffix and asserts against whichever column actually received the saved HTML, mirroring the schedule-features formatting test. The underlying language-write mismatch is captured as a follow-up. - All 7 tests pass locally (~58s total). The pre-existing failures in the `test` workflow are unrelated PDF tests, not from this work. Code-review feedback applied - Removed two unrelated stray files (artifacts/tx-os/nohup.out and artifacts/tx-os/public/opengraph.jpg) that had no code references. - Scoped both attendee selectors under the seeded row's testid (em-row-:meetingId) so the locator stays unambiguous even if another test ever shares a date. Follow-ups proposed - #201 (test_gaps): Shift+Tab + cross-row + ghost-row keyboard tests - #202 (tech_debt): Save edits to the column matching the visible UI Replit-Task-Id: cbd9619c-1475-43c6-998e-163e8e6ec94a