Skip to content

test(plantext): exercise the PlanText grammar through the UI - #1725

Open
renemadsen wants to merge 2 commits into
stablefrom
test/plantext-playwright-shard-t
Open

renemadsen wants to merge 2 commits into
stablefrom
test/plantext-playwright-shard-t

Conversation

@renemadsen

Copy link
Copy Markdown
Member

Follows #1724. The shared parser has ~130 unit tests, but nothing crossed the browser boundary: PlanText is typed in the UI and parsed server-side, and no test proved that wiring.

The seven cases

Each one answered differently through this exact UI path before the migration.

Typed Asserted Before
8-16/1.5 break 01:30, hours 6.5 8.0 — break paid as worked time
6.3-16/1 start 06:30 06:03
7,5-16 start 07:30 07:05
8-16/2 helligdag break 02:00 0
8-16 hjemme 08:00–16:00 threw, aborting the import
5 segments with breaks hours 6.25 7.75 — the 1.5 on shift 4 zeroed
Ferie hours 7.4 survive guards the regression review caught

planHours is the load-bearing assertion: computed from all five shifts less their breaks, so a wrong start, a dropped break or a lost segment all surface in it — no fragile selectors for shifts 3–5 needed.

The Ferie case is the one that would also have passed before. It is deliberate: it guards the data-loss regression introduced while fixing the others, where non-shift text briefly zeroed PlanHours and seeded the flex chain from it.

Where the parse actually happens

Not the save. The seed holds no planning two weeks out, so the working-hours PUT takes the CreatePlanning branch, which stores PlanText verbatim and never parses. The derivation happens on the next dashboard load, in UpdatePlanRegistrationsInPeriod, and is persisted there. The fill → save → open-dashboard → read flow is not three conveniences in a row; the dashboard load is the step under test. This is documented in the spec because it is not obvious and I had it wrong initially.

It also respects both server gates: a future week so the day is past the day of payment, and the day dialog only ever read and cancelled — saving it sets PlanChangedByAdmin, after which the server stops deriving columns from PlanText and every later case would read stale values.

Why a new shard

Shard b holds the existing PlanText spec but its specs share one worker and week with no DB reset between them, which is why the config pins retries: 0. t is isolated, falls back to a's seed automatically, and carries its own activate-plugin.spec.ts (byte-identical to the other 18, deliberately — divergence would break a future consolidation).

Registered in both workflow matrices. Playwright shards are a directory glob with no equivalent of ShardCoverageTests, so an unlisted directory silently never runs.

Review

Dual gate found six real problems, all fixed:

  • Two waitForResponse calls armed after the click that fires them — one would deadlock to the 180s timeout, the other could let a stale site-filter response satisfy the date-range wait and read the wrong week while passing green.
  • The grid save doesn't parse on this path at all — my comment claimed it did.
  • The five-segment rationale was factually wrong: the old parser read all five segments and gave 7.75, it didn't drop shifts 3–5.
  • #cell0_{day} is positional and the dashboard wasn't filtered to the worker, so row 0 could have been someone else.
  • exactly() was dead weight — toHaveValue with a string is already exact equality, never substring.
  • The row-count assertion overclaimed what it checked.

Not verified locally

A hook blocks local Playwright runs and this needs the full stack, so CI is this spec's first execution — and a brand-new shard directory is exactly where a silent mistake hides. I'll watch it to a verdict rather than assume.

🤖 Generated with Claude Code

The shared parser is covered exhaustively by unit tests, but nothing
proved it was wired up: PlanText is typed in the browser and parsed
server-side, and no test crossed that boundary.

Shard t types seven strings into the working-hours grid and reads back
what the server derived. Each one answered differently through this exact
path before the migration: a break over an hour was paid as worked time,
"6.3" started at 06:03 and "7,5" at 07:05, a break with a word after it
fell through to zero, a note after the shift threw and aborted the import
for every later worker, and five segments with breaks lost the 1.5 on
shift four. The seventh, an absence marker, guards the regression
introduced while fixing the others, where non-shift text briefly zeroed
PlanHours and seeded the flex chain from it.

Planned hours is the load-bearing assertion: it is computed from all five
shifts less their breaks, so a wrong start, a dropped break or a lost
segment all surface in it without needing selectors for shifts three to
five.

Where the parse happens is documented, because it is not the save. The
seed holds no planning two weeks out, so the PUT takes the CreatePlanning
branch and stores the text verbatim; the dashboard load is what parses
and persists. The fixture also respects the two server gates -- a future
week so the day is past the day of payment, and the day dialog only ever
read and cancelled, because saving it sets PlanChangedByAdmin and stops
the server deriving columns from PlanText at all.

A new shard rather than an addition to b, whose specs share one worker
and week with no reset between them. t carries its own copy of
activate-plugin, and is registered in both workflow matrices: Playwright
shards are a directory glob with no coverage guard, so an unlisted
directory silently never runs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XekmxLJTEhzv7aJQYjzmyp
Copilot AI lite review requested due to automatic review settings September 24, 2026 05:49

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The new isolated Playwright shard has not been executed locally and requires CI verification.

Review effort: Lite
Findings: None

What changed in this PR

Adds Playwright coverage for PlanText parsing through the UI and registers isolated shard t in CI.

Changes:

  • Adds seven grammar and persistence test cases.
  • Adds shard t plugin activation setup.
  • Registers shard t in PR and master workflows.
File Summary
eform-client/​playwright/​e2e/​plugins/​time-planning-pn/​t/​plan-text-grammar.spec.ts End-to-end PlanText parsing and dashboard persistence coverage; description should distinguish regression cases from the deliberate guard case.
eform-client/​playwright/​e2e/​plugins/​time-planning-pn/​t/​activate-plugin.spec.ts Enables the plugin for shard t.
.github/​workflows/​dotnet-core-pr.yml Registers shard t for pull-request CI.
.github/​workflows/​dotnet-core-master.yml Registers shard t for master CI.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

The first CI run timed out clicking the Timeregistrering tree node after
saving. The tree is already expanded at that point, and with the filter
toolbar still open it overlays the menu, so the node never settled enough
to be clicked -- 324 stability retries before the test timeout.

The working spec in shard b collapses the toolbar after saving and clicks
the Dashboard node directly rather than re-clicking its parent. Doing the
same here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XekmxLJTEhzv7aJQYjzmyp
Copilot AI review requested due to automatic review settings September 24, 2026 06:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The new shard has not been verified locally and CI is its first execution.

Review effort: Lite
Findings: None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants