main is currently red. PR #317 was merged while run 875 was still failing, so four failures landed: 1 integration, 3 end-to-end. All are consequences of #56. This clears them.
What broke
The schema mirror was never regenerated. The migration added three columns to customers and src/db-kysely/schema.ts still described the table without them. That is the drift guard from #305 doing exactly what it exists for. Hand-edited to match kysely-codegen output — alphabetical, Generated<> on the defaulted column — because regenerating properly needs a live database.
The other three are the same mistake three times: a control addressed by position, and the position moved.
Locator
Was
Broke because
AuthModal.marketingConsent
getByRole('checkbox')
Ambiguous in strict mode once the form had two consents
AccountModal.favoriteAlertsSwitch
getByRole('switch').last()
The analytics switch is now last
account-modal.spec.ts
toHaveCount(2)
Three switches now
The .last() one is worth dwelling on. It did not error — it silently retargeted. The test meaning to turn favourite alerts off toggled analytics consent on, then failed on the resulting message (getByText('Turned off') missing, because turning analytics on says something else). The reported failure named a text assertion in favorites.spec.ts — neither the file nor the control actually at fault.
Why position was used at all
antd's Switch renders a bare role="switch" with no accessible name — the adjacent Text is a sibling, not a label. There was nothing to address them by, so position was the only option.
So each switch now carries an explicit aria-label and is addressed by it. The fix and the accessibility improvement are the same change: that label is what a screen reader needed too.
The count assertion stays, but alongside naming each switch — a count on its own would pass if two were swapped for each other.
Two coverage gaps closed
Both are properties the #56 compliance work depends on, and neither was asserted anywhere a customer can see:
The analytics checkbox is unchecked on the register form.
The account toggle is off for a new customer.
Law 25 s.8.1 requires profiling to start off. The integration suite asserts the server half; nothing asserted the rendered half.
Not in scope
auth.spec.ts:96 the logged-out header survives a reload is reported flaky, not failed — it passed on retry. Unrelated to #56; #257 covers flakes in this suite.
Verification
Backend tsc clean · frontend tsc against the test config clean · production build green · both lint suites 0 errors · 478 unit tests passing.
The integration and e2e suites still cannot run on the dev machine — no Docker, and the active Node is too old for Playwright. Whether this actually clears run 875's failures is for CI to say, which is the same gap that produced them.
Please wait for CI on this one
Runs 878–883 are queued and one has been in progress for a while. That backlog is how #317 and #319 both came to be merged without a completed run — a green tick that never arrives is indistinguishable from one nobody waited for. This PR is specifically fixing the consequences of that, so it is worth letting its run finish.
**`main` is currently red.** PR #317 was merged while [run 875](https://gitea.bermudalamb.synology.me/bermudalamb/redefined-designs/actions/runs/875) was still failing, so four failures landed: 1 integration, 3 end-to-end. All are consequences of #56. This clears them.
## What broke
**The schema mirror was never regenerated.** The migration added three columns to `customers` and `src/db-kysely/schema.ts` still described the table without them. That is the drift guard from #305 doing exactly what it exists for. Hand-edited to match `kysely-codegen` output — alphabetical, `Generated<>` on the defaulted column — because regenerating properly needs a live database.
**The other three are the same mistake three times: a control addressed by position, and the position moved.**
| Locator | Was | Broke because |
| --- | --- | --- |
| `AuthModal.marketingConsent` | `getByRole('checkbox')` | Ambiguous in strict mode once the form had two consents |
| `AccountModal.favoriteAlertsSwitch` | `getByRole('switch').last()` | The analytics switch is now last |
| `account-modal.spec.ts` | `toHaveCount(2)` | Three switches now |
The `.last()` one is worth dwelling on. **It did not error — it silently retargeted.** The test meaning to turn favourite alerts *off* toggled analytics consent *on*, then failed on the resulting message (`getByText('Turned off')` missing, because turning analytics on says something else). The reported failure named a text assertion in `favorites.spec.ts` — neither the file nor the control actually at fault.
## Why position was used at all
antd's `Switch` renders a bare `role="switch"` with **no accessible name** — the adjacent `Text` is a sibling, not a label. There was nothing to address them by, so position was the only option.
So each switch now carries an explicit `aria-label` and is addressed by it. The fix and the accessibility improvement are the same change: that label is what a screen reader needed too.
The count assertion stays, but alongside naming each switch — a count on its own would pass if two were swapped for each other.
## Two coverage gaps closed
Both are properties the #56 compliance work depends on, and neither was asserted anywhere a customer can see:
- The analytics checkbox is unchecked on the register form.
- The account toggle is off for a new customer.
Law 25 s.8.1 requires profiling to start off. The integration suite asserts the server half; nothing asserted the rendered half.
## Not in scope
`auth.spec.ts:96 the logged-out header survives a reload` is reported **flaky**, not failed — it passed on retry. Unrelated to #56; #257 covers flakes in this suite.
## Verification
Backend `tsc` clean · frontend `tsc` against the test config clean · production build green · both lint suites 0 errors · **478 unit tests passing**.
**The integration and e2e suites still cannot run on the dev machine** — no Docker, and the active Node is too old for Playwright. Whether this actually clears run 875's failures is for CI to say, which is the same gap that produced them.
## Please wait for CI on this one
Runs 878–883 are queued and one has been in progress for a while. That backlog is how #317 and #319 both came to be merged without a completed run — **a green tick that never arrives is indistinguishable from one nobody waited for.** This PR is specifically fixing the consequences of that, so it is worth letting its run finish.
Closes #320
🤖 Generated with [Claude Code](https://claude.com/claude-code)
PR #317 was merged while its run was still failing, so four failures landed on main: one integration and three end-to-end. All of them are consequences of #56, and none could have been caught on the dev machine, which has no database and no browser to run those suites with.
The schema mirror was never regenerated. The migration added three columns to customers and src/db-kysely/schema.ts still described the table without them, which is the drift guard from #305 doing exactly what it exists for. Hand-edited to match what kysely-codegen emits — alphabetical, and Generated on the column that has a default — because regenerating properly needs a live database.
The other three are the same mistake three times: a control addressed by position, and the position moved. An unscoped getByRole('checkbox') became ambiguous once the register form had two consents. A toHaveCount(2) on the account modal's switches became three. And favoriteAlertsSwitch was getByRole('switch').last(), which did not error when a switch was appended below it — it silently retargeted, toggled analytics consent instead of favourite alerts, and then failed on a text assertion in favorites.spec.ts, naming neither the file nor the control actually at fault.
The reason position was ever used is that antd's Switch renders a bare role="switch" with no accessible name; the adjacent Text is a sibling, not a label. So each one now carries an explicit aria-label and is addressed by it. That is what makes them addressable from a test, and it is what a screen reader needed regardless — the fix and the accessibility improvement are the same change.
The count assertion stays, but alongside naming each switch, because a count on its own would pass if two of them were swapped for each other.
Two coverage gaps closed while here, both properties the compliance work in #56 depends on and neither previously asserted anywhere a customer could see: the analytics checkbox is unchecked on the register form, and the account toggle is off for a new customer. Quebec's Law 25 s.8.1 requires profiling to start off, the integration suite asserts the server half of that, and nothing asserted the half rendered on screen.
The fourth Playwright entry, the logged-out header surviving a reload, is reported flaky rather than failed and passed on retry. Left alone; it is unrelated to #56 and #257 covers flakes in this suite.
Verified: backend tsc clean, frontend tsc against the test config clean, production build green, both lint suites 0 errors, 478 unit tests passing. The integration and e2e suites still cannot run here, so whether this actually clears run 875's failures is for CI to say — which is the same gap that produced them.
Closes#320
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
mainis currently red. PR #317 was merged while run 875 was still failing, so four failures landed: 1 integration, 3 end-to-end. All are consequences of #56. This clears them.What broke
The schema mirror was never regenerated. The migration added three columns to
customersandsrc/db-kysely/schema.tsstill described the table without them. That is the drift guard from #305 doing exactly what it exists for. Hand-edited to matchkysely-codegenoutput — alphabetical,Generated<>on the defaulted column — because regenerating properly needs a live database.The other three are the same mistake three times: a control addressed by position, and the position moved.
AuthModal.marketingConsentgetByRole('checkbox')AccountModal.favoriteAlertsSwitchgetByRole('switch').last()account-modal.spec.tstoHaveCount(2)The
.last()one is worth dwelling on. It did not error — it silently retargeted. The test meaning to turn favourite alerts off toggled analytics consent on, then failed on the resulting message (getByText('Turned off')missing, because turning analytics on says something else). The reported failure named a text assertion infavorites.spec.ts— neither the file nor the control actually at fault.Why position was used at all
antd's
Switchrenders a barerole="switch"with no accessible name — the adjacentTextis a sibling, not a label. There was nothing to address them by, so position was the only option.So each switch now carries an explicit
aria-labeland is addressed by it. The fix and the accessibility improvement are the same change: that label is what a screen reader needed too.The count assertion stays, but alongside naming each switch — a count on its own would pass if two were swapped for each other.
Two coverage gaps closed
Both are properties the #56 compliance work depends on, and neither was asserted anywhere a customer can see:
Law 25 s.8.1 requires profiling to start off. The integration suite asserts the server half; nothing asserted the rendered half.
Not in scope
auth.spec.ts:96 the logged-out header survives a reloadis reported flaky, not failed — it passed on retry. Unrelated to #56; #257 covers flakes in this suite.Verification
Backend
tscclean · frontendtscagainst the test config clean · production build green · both lint suites 0 errors · 478 unit tests passing.The integration and e2e suites still cannot run on the dev machine — no Docker, and the active Node is too old for Playwright. Whether this actually clears run 875's failures is for CI to say, which is the same gap that produced them.
Please wait for CI on this one
Runs 878–883 are queued and one has been in progress for a while. That backlog is how #317 and #319 both came to be merged without a completed run — a green tick that never arrives is indistinguishable from one nobody waited for. This PR is specifically fixing the consequences of that, so it is worth letting its run finish.
Closes #320
🤖 Generated with Claude Code