feat: First-Start Create Admin Modal 1.03

This commit is contained in:
OpenVelo Agent
2026-07-21 16:25:36 +00:00
parent 6210cdb6de
commit bf95610226
3 changed files with 270 additions and 191 deletions
+53
View File
@@ -13,6 +13,29 @@ function makeGroup(password: string | null | undefined, confirm: string | null |
};
}
const USERNAME_PATTERN = /^[a-zA-Z0-9_.-]+$/;
const USERNAME_MIN = 3;
const USERNAME_MAX = 32;
function usernameErrors(value: string): string | null {
if (!value) return 'required';
if (value.length < USERNAME_MIN) return 'minlength';
if (value.length > USERNAME_MAX) return 'maxlength';
if (!USERNAME_PATTERN.test(value)) return 'pattern';
return null;
}
function isFormReadyForSubmit(username: string, password: string, confirm: string): boolean {
if (usernameErrors(username) !== null) return false;
if (!password) return false;
if (!confirm) return false;
const groupLike: PasswordMatchGroupLike = {
get: (name) => (name === 'password' ? { value: password } : { value: confirm }),
};
if (passwordMatchValidator(groupLike)?.passwordMismatch) return false;
return true;
}
describe('passwordMatchValidator', () => {
it('returns null when either field is empty (let other validators handle required)', () => {
expect(passwordMatchValidator(makeGroup('', 'x'))).toBeNull();
@@ -58,3 +81,33 @@ describe('Username field rules (mirroring component validators)', () => {
expect(isValidUsername('a'.repeat(33))).toBe(false);
});
});
describe('Composed submit gate (mirrors SetupCreateAdminComponent.submit)', () => {
it('rejects an all-empty form (no required field passes)', () => {
expect(isFormReadyForSubmit('', '', '')).toBe(false);
});
it('rejects a partial form (username only)', () => {
expect(isFormReadyForSubmit('first.admin', '', '')).toBe(false);
});
it('rejects when password and confirm are empty even with a valid username', () => {
expect(isFormReadyForSubmit('first.admin', '', '')).toBe(false);
});
it('rejects when passwordConfirm is empty', () => {
expect(isFormReadyForSubmit('first.admin', 'Sup3rSecret!Pass', '')).toBe(false);
});
it('rejects when password and confirm differ', () => {
expect(isFormReadyForSubmit('first.admin', 'Sup3rSecret!Pass', 'Different!Pass1')).toBe(false);
});
it('rejects when username violates the pattern', () => {
expect(isFormReadyForSubmit('bad name!', 'Sup3rSecret!Pass', 'Sup3rSecret!Pass')).toBe(false);
});
it('accepts a fully valid, matching form', () => {
expect(isFormReadyForSubmit('first.admin', 'Sup3rSecret!Pass', 'Sup3rSecret!Pass')).toBe(true);
});
});