From 3fc0ec95efc0f6f130f706676a234e08e7b7ed24 Mon Sep 17 00:00:00 2001 From: Marcel Date: Thu, 14 May 2026 15:59:37 +0200 Subject: [PATCH] =?UTF-8?q?fix(invites):=20make=20group=20checkboxes=20wri?= =?UTF-8?q?table=20=E2=80=94=20$derived=20=E2=86=92=20$state?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bind:group requires a writable $state variable; $derived is read-only in Svelte 5, so every click was silently reset to unchecked, making the group picker non-functional. Also wraps checkboxes in
/ for WCAG 1.3.1 compliance. Co-Authored-By: Claude Sonnet 4.6 --- .../src/lib/user/UserGroupsSection.svelte | 7 ++-- .../routes/admin/invites/page.svelte.test.ts | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/frontend/src/lib/user/UserGroupsSection.svelte b/frontend/src/lib/user/UserGroupsSection.svelte index 590c3295..e9b2cd5c 100644 --- a/frontend/src/lib/user/UserGroupsSection.svelte +++ b/frontend/src/lib/user/UserGroupsSection.svelte @@ -7,10 +7,11 @@ let { selectedGroupIds?: string[]; } = $props(); -let selected = $derived([...selectedGroupIds]); +let selected = $state([...selectedGroupIds]); -
+
+ Gruppen {#each groups as group (group.id)}
+
diff --git a/frontend/src/routes/admin/invites/page.svelte.test.ts b/frontend/src/routes/admin/invites/page.svelte.test.ts index 61ec8801..84304006 100644 --- a/frontend/src/routes/admin/invites/page.svelte.test.ts +++ b/frontend/src/routes/admin/invites/page.svelte.test.ts @@ -299,4 +299,39 @@ describe('admin/invites page', () => { await expect.element(page.getByRole('checkbox', { name: 'Administratoren' })).toBeVisible(); await expect.element(page.getByRole('checkbox', { name: 'Familie' })).toBeVisible(); }); + + it('group checkbox stays checked after being clicked', async () => { + render(AdminInvitesPage, { + props: { + data: { + ...baseData(), + groups: [{ id: 'g-1', name: 'Familie', permissions: ['READ_ALL'] }], + groupsLoadError: null + } + } + }); + + await page + .getByRole('button', { name: /neue einladung/i }) + .first() + .click(); + + const checkbox = page.getByRole('checkbox', { name: 'Familie' }); + await checkbox.click(); + await expect.element(checkbox).toBeChecked(); + }); + + it('amber warning banner has role="alert"', async () => { + render(AdminInvitesPage, { + props: { data: { ...baseData(), groups: [], groupsLoadError: 'INTERNAL_ERROR' } } + }); + + await page + .getByRole('button', { name: /neue einladung/i }) + .first() + .click(); + + const alert = document.querySelector('[role="alert"]'); + expect(alert).not.toBeNull(); + }); });