test(routes): expand register coverage for password and form branches
Adds password show/hide toggle (independent for both fields), pwHint visible after typing, pwValid green hint for 8+ chars, pwMismatch red hint, pwMatch green hint, form.error rendering, notifyOnMention checkbox toggle. 7 new tests targeting ~25 branches in the register flow. Refs #496. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -118,4 +118,111 @@ describe('register page', () => {
|
|||||||
const codeInput = document.querySelector('input[name="code"]') as HTMLInputElement;
|
const codeInput = document.querySelector('input[name="code"]') as HTMLInputElement;
|
||||||
expect(codeInput.value).toBe('');
|
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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user