diff --git a/frontend/src/routes/register/page.svelte.test.ts b/frontend/src/routes/register/page.svelte.test.ts index db81aa1d..cb9f9e79 100644 --- a/frontend/src/routes/register/page.svelte.test.ts +++ b/frontend/src/routes/register/page.svelte.test.ts @@ -118,4 +118,111 @@ describe('register page', () => { const codeInput = document.querySelector('input[name="code"]') as HTMLInputElement; expect(codeInput.value).toBe(''); }); + + it('toggles password visibility when the show/hide button is clicked', async () => { + render(RegisterPage, { props: { data: baseData(), form: undefined } }); + + const pw = document.querySelector('input[name="password"]') as HTMLInputElement; + expect(pw.type).toBe('password'); + + const toggle = pw.parentElement?.querySelector('button[type="button"]') as HTMLButtonElement; + toggle.click(); + + await new Promise((r) => setTimeout(r, 30)); + expect(pw.type).toBe('text'); + + toggle.click(); + await new Promise((r) => setTimeout(r, 30)); + expect(pw.type).toBe('password'); + }); + + it('toggles passwordConfirm visibility independently from password', async () => { + render(RegisterPage, { props: { data: baseData(), form: undefined } }); + + const confirm = document.querySelector('#passwordConfirm') as HTMLInputElement; + expect(confirm.type).toBe('password'); + + const toggle = confirm.parentElement?.querySelector( + 'button[type="button"]' + ) as HTMLButtonElement; + toggle.click(); + + await new Promise((r) => setTimeout(r, 30)); + expect(confirm.type).toBe('text'); + }); + + it('shows the password length hint after typing a short password', async () => { + render(RegisterPage, { props: { data: baseData(), form: undefined } }); + + const pw = document.querySelector('input[name="password"]') as HTMLInputElement; + pw.value = 'abc'; + pw.dispatchEvent(new Event('input', { bubbles: true })); + + await new Promise((r) => setTimeout(r, 30)); + await expect.element(page.getByText(/mindestens 8 zeichen/i)).toBeVisible(); + }); + + it('shows the password OK hint when password is at least 8 chars', async () => { + render(RegisterPage, { props: { data: baseData(), form: undefined } }); + + const pw = document.querySelector('input[name="password"]') as HTMLInputElement; + pw.value = 'longenoughpw'; + pw.dispatchEvent(new Event('input', { bubbles: true })); + + await new Promise((r) => setTimeout(r, 30)); + // password OK hint shows up — find a green-700 text near password + const greens = document.querySelectorAll('.text-green-700'); + expect(greens.length).toBeGreaterThan(0); + }); + + it('shows the password mismatch error when confirm differs from password', async () => { + render(RegisterPage, { props: { data: baseData(), form: undefined } }); + + const pw = document.querySelector('input[name="password"]') as HTMLInputElement; + const confirm = document.querySelector('#passwordConfirm') as HTMLInputElement; + pw.value = 'longenoughpw'; + pw.dispatchEvent(new Event('input', { bubbles: true })); + confirm.value = 'differentpw'; + confirm.dispatchEvent(new Event('input', { bubbles: true })); + + await new Promise((r) => setTimeout(r, 30)); + const reds = document.querySelectorAll('.text-red-600'); + expect(reds.length).toBeGreaterThan(0); + }); + + it('shows the password match success when confirm equals password', async () => { + render(RegisterPage, { props: { data: baseData(), form: undefined } }); + + const pw = document.querySelector('input[name="password"]') as HTMLInputElement; + const confirm = document.querySelector('#passwordConfirm') as HTMLInputElement; + pw.value = 'longenoughpw'; + pw.dispatchEvent(new Event('input', { bubbles: true })); + confirm.value = 'longenoughpw'; + confirm.dispatchEvent(new Event('input', { bubbles: true })); + + await new Promise((r) => setTimeout(r, 30)); + // At least 2 green-700 elements (pw OK + match OK) + const greens = document.querySelectorAll('.text-green-700'); + expect(greens.length).toBeGreaterThanOrEqual(2); + }); + + it('renders the form error from the form prop', async () => { + render(RegisterPage, { + props: { data: baseData(), form: { error: 'EMAIL_TAKEN' } } + }); + + const errorBox = document.querySelector('.text-red-600.font-medium'); + expect(errorBox).not.toBeNull(); + }); + + it('toggles the notifyOnMention checkbox', async () => { + render(RegisterPage, { props: { data: baseData(), form: undefined } }); + + const cb = document.querySelector('input[name="notifyOnMention"]') as HTMLInputElement; + expect(cb.checked).toBe(true); + + cb.click(); + await new Promise((r) => setTimeout(r, 30)); + expect(cb.checked).toBe(false); + }); });