You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(captcha): scope the booking refresh to its form and make the ids unique (#1057)
* test: attribute the security-fields renderer to the class it exercises
Coveralls reported `SecurityService` at 25% patch coverage — 2 of the 8 changed
lines — with the whole body of `render_security_fields()` uncovered, even
though `test_render_security_fields_composes_honeypot_and_challenge` calls it
and asserts on its output.
The method was never untested; the report was filtered. `@covers` restricts
attribution to the classes it names, and this test class named only the two
captcha ones, so everything the composition tests executed inside
`SecurityService` was discarded. Adding it to `@covers` — with the
`class_exists()` preload CLAUDE.md prescribes for the pcov gotcha — takes the
file from 67/73 to 72/73; the one line left is the `exit` in the ABSPATH guard,
unreachable by construction.
No assertion changed. This makes the coverage report describe what the suite
actually does, so a later reader does not "add a test" for a covered method or
read it as dead.
Refs #1053
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012XWx9qJdjZdAq8crxM9GCU
* fix(captcha): scope the booking refresh to its form and make the ids unique
The plugin supports several forms on one page on purpose — DynamicFragments
has a branch that mints a distinct challenge per form — but the captcha did not
hold up under it.
`ffcCalendarFrontend.refreshCaptcha()` was page-global. It rewrote the question
in *every* `.ffc-captcha-row` on the page, then wrote the new token through
`$('#ffc_captcha_hash')`, which by definition matches only the first element.
With two forms up, a rejection in either one left the second displaying a
question its token did not answer: the visitor answered what was on screen and
was told the math answer is incorrect — true, and useless as a diagnosis.
It now scopes to the submitted form and matches by `name`, which is what
`ffc-frontend-helpers.js` already did on the certificate path. `$form` was
already in scope at the call site, so nothing had to be restructured.
That leaves the ids used only for the `<label for>` pair, and a census
confirmed it: every other consumer — ffc-dynamic-fragments, ffc-frontend,
ffc-frontend-helpers — matches by `name`, and no CSS references them. Duplicate
ids still broke the label association a screen reader needs to announce a
required field, so `MathCaptcha` now suffixes them per render. The `name`
attributes are the contract with the server and are untouched.
Three of the four new JS tests fail against the previous implementation and
pass against this one, so they pin the defect rather than describing the fix.
Also carries a test-attribution fix that missed the #1055 merge window: that
class `@covers` SecurityService, taking the file from 67/73 to 72/73 — the
method was always tested, the report was filtered.
On the timer sweep this issue also lists: the inventory is 16 timers of 1000ms
or more, several loaded by tests that do not fake timers. But three runs of the
full JS suite produced zero unhandled errors, so nothing beyond the instance
already fixed is observably leaking. Adding fake timers to five passing test
files on a static heuristic would be churn; the inventory is recorded on the
issue for whoever has a reproduction.
Refs #1056, #1053
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012XWx9qJdjZdAq8crxM9GCU
---------
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,6 +15,10 @@ The format follows [Keep a Changelog] (https://keepachangelog.com/en/1.1.0/).
15
15
16
16
- Internal (#1053) — o captcha passa a ter um contrato de estratégia (`CaptchaProviderInterface` + `CaptchaProvider::resolve()`), com o desafio matemático atrás dele. Os 6 sites de verificação e os 4 de retry não mudam: `validate_security_fields()` continua sendo o ponto único e agora delega a metade captcha. As duas cópias do bloco de segurança viraram uma, em `templates/`.
17
17
18
+
### Fixed
19
+
20
+
-**O captcha se atrapalhava com dois formulários na mesma página** (#1056): o refresh do agendamento reescrevia a pergunta em *todos* os formulários mas, casando por id, trocava o token só do primeiro — o segundo passava a exibir uma pergunta que seu token não respondia. Agora é escopado ao formulário e casa por `name`. Os ids do captcha passam a ser únicos por render, corrigindo também a associação `<label for>` para leitores de tela.
0 commit comments