From 2d1604492d9d00aac85a4bec92a24d53b93fd5ed Mon Sep 17 00:00:00 2001 From: Marcel Raddatz Date: Thu, 2 Apr 2026 19:31:13 +0200 Subject: [PATCH] feat(onboarding): add max-length validation for household name (100 chars) Fails fast before the API call with a clear German error message. Tests boundary: 100 chars accepted, 101 rejected. Co-Authored-By: Claude Sonnet 4.6 --- .../routes/household/setup/+page.server.ts | 4 ++++ .../household/setup/page.server.test.ts | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/frontend/src/routes/household/setup/+page.server.ts b/frontend/src/routes/household/setup/+page.server.ts index 9fb1224..6fe21b8 100644 --- a/frontend/src/routes/household/setup/+page.server.ts +++ b/frontend/src/routes/household/setup/+page.server.ts @@ -18,6 +18,10 @@ export const actions = { return fail(400, { errors: { name: 'Haushaltsname ist erforderlich' }, name: '' }); } + if (name.length > 100) { + return fail(400, { errors: { name: 'Haushaltsname darf maximal 100 Zeichen lang sein' }, name }); + } + const api = apiClient(fetch); const { data, error } = await api.POST('/v1/households', { body: { name } diff --git a/frontend/src/routes/household/setup/page.server.test.ts b/frontend/src/routes/household/setup/page.server.test.ts index dd339f4..0971b2a 100644 --- a/frontend/src/routes/household/setup/page.server.test.ts +++ b/frontend/src/routes/household/setup/page.server.test.ts @@ -123,6 +123,28 @@ describe('household setup — form action', () => { expect(result.data.name).toBe(''); }); + it('returns fail(400) when name exceeds 100 characters', async () => { + const longName = 'a'.repeat(101); + const result = await actions.default(createRequest({ name: longName })); + + expect(result.status).toBe(400); + expect(result.data.errors.name).toBeTruthy(); + expect(mockPost).not.toHaveBeenCalled(); + }); + + it('accepts name at exactly 100 characters', async () => { + mockPost.mockResolvedValue(mockSuccess()); + const maxName = 'a'.repeat(100); + + try { + await actions.default(createRequest({ name: maxName })); + } catch { + // redirect throws + } + + expect(mockPost).toHaveBeenCalled(); + }); + it('returns fail with form error on API failure', async () => { mockPost.mockResolvedValue({ data: undefined,