feat(password): add reset and change password pages

/reset-password page for the email request and the new password,
ChangePasswordCard in settings, password reset button on the admin
users page, 'Forgot password?' link on the login page, de/en texts.
This commit is contained in:
lobo committed 2026-10-02 10:35:08 +02:00
1 parent f71e8f7aff
commit 6627a8db66
19 files changed
+565 -25

No files matched your search

+20 -1
View File
@@ -1,5 +1,5 @@
import {describe, expect, it} from 'vitest';
import {confirmEmailSchema, registrationSchema, settingsSchema} from './validation.js';
import {changePasswordSchema, confirmEmailSchema, registrationSchema, settingsSchema} from './validation.js';
const settings = () => ({useDarkTheme: true, language: 'de'});
@@ -46,6 +46,25 @@ describe('confirm page password', () => {
});
});
describe('changePasswordSchema', () => {
const valid = {currentPassword: 'old', password: 'password1', passwordConfirmation: 'password1'};
it('takes a current password and a good new one', () => {
expect(changePasswordSchema.safeParse(valid).success).toBe(true);
});
it('requires the current password', () => {
expect(changePasswordSchema.safeParse({...valid, currentPassword: ''}).success).toBe(false);
});
it('applies the rules of the new password and the repeat', () => {
expect(changePasswordSchema.safeParse({...valid, password: 'short', passwordConfirmation: 'short'}).success).toBe(false);
expect(changePasswordSchema.safeParse({...valid, passwordConfirmation: 'password2'}).success).toBe(false);
const long = 'é'.repeat(37);
expect(changePasswordSchema.safeParse({...valid, password: long, passwordConfirmation: long}).success).toBe(false);
});
});
describe('registration', () => {
it('has no password field', () => {
expect(registrationSchema.parse({email: 'a@b.de', password: 'password1'})).not.toHaveProperty('password');