Add FunctionalJavascript coverage for the place map and calendar JavaScript
What this adds
Ten browser tests for the place picker, in one class. Tests only: no production file is touched. The picker is the headline way to buy a seat and none of it is reachable from PHP, so until now the whole interaction layer was unguarded.
Scope is the place map, as the issue proposes; the calendar follows in its own MR.
The two bugs the issue was filed over
Both are guarded, and reading the code corrected my understanding of the first one:
- #3611882 was pointer capture on the viewport swallowing the place
button's click, so a plain click booked nothing. (The comment at
venue-map.js:1250-1252records why the pointer listeners moved to the window.) So the guard is two-sided:testSeatIsBookedOnClickproves a plain click still books, andtestDraggingTheMapBooksNothingproves a pan does not. - #3611904 was the panel controls disappearing once the selection list grew.
testSelectionControlsSurviveLongListtakes six seats and asserts Remove all, the total and the last row's tariff control are visible, not merely present. The elements existed throughout, which is exactly why no PHP test could have caught it.
The rest
testSeatIsReleasedOnSecondClick (and that focus returns to the seat, so the
keyboard does not lose its place), testSeatIsReleasedFromThePicksList,
testPoolUnitsAreTakenAndReturned (the counter and "N left" both move, and the
minus button is disabled at zero), testRemoveAllClearsSeatsAndPools (the only
operation that touches both at once, so the highest value per round trip),
testTotalSumsSeatsAndPoolUnits, testChangingTariffUpdatesTotal, and
testSeatTakenAfterLoadFlipsToTaken — that last one holds the seat from PHP
after the page is drawn, so the 409 path runs for real with no stubbing.
Two things worth a reviewer's attention
Every live-region assertion has to poll. announce()
(venue-map.js:572-577) blanks the region and refills it 30ms later on purpose,
so a screen reader re-announces a repeated message. Reading it straight after an
action finds the blank. Two tests failed on this first time and four others were
passing by luck; all six now go through one assertAnnounced() helper. Please do
not "simplify" them back to elementTextContains.
The drag test fakes the gesture rather than performing it. WebDriver's drag moves between element centres and does not reliably produce the click that the guard protects, so the test dispatches pointerdown / pointermove past the 4px threshold / pointerup and then clicks. It also books a different seat afterwards and waits for that, because otherwise "nothing happened" would assert true before a booking could have landed anyway.
Fixture
One private hall(), following house style (yoyaku has no shared test trait and
every existing fixture is a private method): a background SVG whose sprite is a
real shape, so seats cannot draw invisibly and let an assertion pass against an
empty hall; six drawn seats in a row; a pooled area declaring capacity ten and
naming no shape on the plan, because an untouched area that has a shape is
sold from the plan and keeps its panel block hidden; and two priced tariffs on one
grade so a pick has something to switch to.
The payment stack (yoyaku_order, kessai, yoyaku_payment) is installed for one
reason: a tariff's price comes from the payment policy resolver, and with no price
the total never renders, so the assertion that seats and pooled units are summed
would have nothing to read.
Runs
Ten tests, 87 assertions, two clean consecutive runs at 181s and 240s before pushing, because a browser test that passes once is not yet known to be stable. The whole FunctionalJavascript directory is 12 tests, 100 assertions, 230s alongside the two from [#3614076].
No production changes, so there is nothing for eslint or phpstan that was not
already there, no new translatable strings, and nothing to document: fr.po and
docs/ are deliberately untouched.
Follow-up filed
op: category failing is handled by nothing: the endpoint answers 409
{ok: false, error: 'Not held.'} and the select's handler checks r.ok and then
does nothing, so the dropdown keeps showing a tariff the server refused.
testChangingTariffUpdatesTotal covers the happy path only and says so.
Not in scope
The check-in scanner. It drives a camera through getUserMedia, which needs
fake-media Chrome flags and a fabricated QR frame; a flaky test that later gets
disabled is worse than none, so it belongs in its own issue with its own setup.