Files
gridpilot.gg/apps/website/tests/view-data/auth.test.ts
Marc Mintel fb1221701d
Some checks failed
Contract Testing / contract-tests (push) Failing after 6m7s
Contract Testing / contract-snapshot (push) Failing after 4m46s
add tests
2026-01-22 11:52:42 +01:00

1021 lines
40 KiB
TypeScript

/**
* View Data Layer Tests - Auth Functionality
*
* This test file covers the view data layer for auth functionality.
*
* The view data layer is responsible for:
* - DTO → UI model mapping
* - Formatting, sorting, and grouping
* - Derived fields and defaults
* - UI-specific semantics
*
* This layer isolates the UI from API churn by providing a stable interface
* between the API layer and the presentation layer.
*
* Test coverage includes:
* - Login form data transformation and validation
* - Signup form view models and field formatting
* - Forgot password flow data handling
* - Reset password token validation and UI state
* - Auth error message formatting and display
* - User session data mapping for UI components
* - Derived auth state fields (isAuthenticated, authStatus, etc.)
* - Default values and fallbacks for auth views
* - Auth-specific formatting (password strength, email validation, etc.)
*/
import { LoginViewDataBuilder } from '@/lib/builders/view-data/LoginViewDataBuilder';
import { SignupViewDataBuilder } from '@/lib/builders/view-data/SignupViewDataBuilder';
import { ForgotPasswordViewDataBuilder } from '@/lib/builders/view-data/ForgotPasswordViewDataBuilder';
import { ResetPasswordViewDataBuilder } from '@/lib/builders/view-data/ResetPasswordViewDataBuilder';
import type { LoginPageDTO } from '@/lib/services/auth/types/LoginPageDTO';
import type { SignupPageDTO } from '@/lib/services/auth/types/SignupPageDTO';
import type { ForgotPasswordPageDTO } from '@/lib/services/auth/types/ForgotPasswordPageDTO';
import type { ResetPasswordPageDTO } from '@/lib/services/auth/types/ResetPasswordPageDTO';
describe('LoginViewDataBuilder', () => {
describe('happy paths', () => {
it('should transform LoginPageDTO to LoginViewData correctly', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '/dashboard',
hasInsufficientPermissions: false,
};
const result = LoginViewDataBuilder.build(loginPageDTO);
expect(result).toEqual({
returnTo: '/dashboard',
hasInsufficientPermissions: false,
showPassword: false,
showErrorDetails: false,
formState: {
fields: {
email: { value: '', error: undefined, touched: false, validating: false },
password: { value: '', error: undefined, touched: false, validating: false },
rememberMe: { value: false, error: undefined, touched: false, validating: false },
},
isValid: true,
isSubmitting: false,
submitError: undefined,
submitCount: 0,
},
isSubmitting: false,
submitError: undefined,
});
});
it('should handle insufficient permissions flag correctly', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '/admin',
hasInsufficientPermissions: true,
};
const result = LoginViewDataBuilder.build(loginPageDTO);
expect(result.hasInsufficientPermissions).toBe(true);
expect(result.returnTo).toBe('/admin');
});
it('should handle empty returnTo path', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '',
hasInsufficientPermissions: false,
};
const result = LoginViewDataBuilder.build(loginPageDTO);
expect(result.returnTo).toBe('');
expect(result.hasInsufficientPermissions).toBe(false);
});
});
describe('data transformation', () => {
it('should preserve all DTO fields in the output', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '/dashboard',
hasInsufficientPermissions: false,
};
const result = LoginViewDataBuilder.build(loginPageDTO);
expect(result.returnTo).toBe(loginPageDTO.returnTo);
expect(result.hasInsufficientPermissions).toBe(loginPageDTO.hasInsufficientPermissions);
});
it('should not modify the input DTO', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '/dashboard',
hasInsufficientPermissions: false,
};
const originalDTO = { ...loginPageDTO };
LoginViewDataBuilder.build(loginPageDTO);
expect(loginPageDTO).toEqual(originalDTO);
});
it('should initialize form fields with default values', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '/dashboard',
hasInsufficientPermissions: false,
};
const result = LoginViewDataBuilder.build(loginPageDTO);
expect(result.formState.fields.email.value).toBe('');
expect(result.formState.fields.email.error).toBeUndefined();
expect(result.formState.fields.email.touched).toBe(false);
expect(result.formState.fields.email.validating).toBe(false);
expect(result.formState.fields.password.value).toBe('');
expect(result.formState.fields.password.error).toBeUndefined();
expect(result.formState.fields.password.touched).toBe(false);
expect(result.formState.fields.password.validating).toBe(false);
expect(result.formState.fields.rememberMe.value).toBe(false);
expect(result.formState.fields.rememberMe.error).toBeUndefined();
expect(result.formState.fields.rememberMe.touched).toBe(false);
expect(result.formState.fields.rememberMe.validating).toBe(false);
});
it('should initialize form state with default values', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '/dashboard',
hasInsufficientPermissions: false,
};
const result = LoginViewDataBuilder.build(loginPageDTO);
expect(result.formState.isValid).toBe(true);
expect(result.formState.isSubmitting).toBe(false);
expect(result.formState.submitError).toBeUndefined();
expect(result.formState.submitCount).toBe(0);
});
it('should initialize UI state flags correctly', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '/dashboard',
hasInsufficientPermissions: false,
};
const result = LoginViewDataBuilder.build(loginPageDTO);
expect(result.showPassword).toBe(false);
expect(result.showErrorDetails).toBe(false);
expect(result.isSubmitting).toBe(false);
expect(result.submitError).toBeUndefined();
});
});
describe('edge cases', () => {
it('should handle special characters in returnTo path', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '/dashboard?param=value&other=test',
hasInsufficientPermissions: false,
};
const result = LoginViewDataBuilder.build(loginPageDTO);
expect(result.returnTo).toBe('/dashboard?param=value&other=test');
});
it('should handle returnTo with hash fragment', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '/dashboard#section',
hasInsufficientPermissions: false,
};
const result = LoginViewDataBuilder.build(loginPageDTO);
expect(result.returnTo).toBe('/dashboard#section');
});
it('should handle returnTo with encoded characters', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '/dashboard?redirect=%2Fadmin',
hasInsufficientPermissions: false,
};
const result = LoginViewDataBuilder.build(loginPageDTO);
expect(result.returnTo).toBe('/dashboard?redirect=%2Fadmin');
});
});
describe('form state structure', () => {
it('should have all required form fields', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '/dashboard',
hasInsufficientPermissions: false,
};
const result = LoginViewDataBuilder.build(loginPageDTO);
expect(result.formState.fields).toHaveProperty('email');
expect(result.formState.fields).toHaveProperty('password');
expect(result.formState.fields).toHaveProperty('rememberMe');
});
it('should have consistent field state structure', () => {
const loginPageDTO: LoginPageDTO = {
returnTo: '/dashboard',
hasInsufficientPermissions: false,
};
const result = LoginViewDataBuilder.build(loginPageDTO);
const fields = result.formState.fields;
Object.values(fields).forEach((field) => {
expect(field).toHaveProperty('value');
expect(field).toHaveProperty('error');
expect(field).toHaveProperty('touched');
expect(field).toHaveProperty('validating');
});
});
});
});
describe('SignupViewDataBuilder', () => {
describe('happy paths', () => {
it('should transform SignupPageDTO to SignupViewData correctly', () => {
const signupPageDTO: SignupPageDTO = {
returnTo: '/dashboard',
};
const result = SignupViewDataBuilder.build(signupPageDTO);
expect(result).toEqual({
returnTo: '/dashboard',
formState: {
fields: {
firstName: { value: '', error: undefined, touched: false, validating: false },
lastName: { value: '', error: undefined, touched: false, validating: false },
email: { value: '', error: undefined, touched: false, validating: false },
password: { value: '', error: undefined, touched: false, validating: false },
confirmPassword: { value: '', error: undefined, touched: false, validating: false },
},
isValid: true,
isSubmitting: false,
submitError: undefined,
submitCount: 0,
},
isSubmitting: false,
submitError: undefined,
});
});
it('should handle empty returnTo path', () => {
const signupPageDTO: SignupPageDTO = {
returnTo: '',
};
const result = SignupViewDataBuilder.build(signupPageDTO);
expect(result.returnTo).toBe('');
});
it('should handle returnTo with query parameters', () => {
const signupPageDTO: SignupPageDTO = {
returnTo: '/dashboard?welcome=true',
};
const result = SignupViewDataBuilder.build(signupPageDTO);
expect(result.returnTo).toBe('/dashboard?welcome=true');
});
});
describe('data transformation', () => {
it('should preserve all DTO fields in the output', () => {
const signupPageDTO: SignupPageDTO = {
returnTo: '/dashboard',
};
const result = SignupViewDataBuilder.build(signupPageDTO);
expect(result.returnTo).toBe(signupPageDTO.returnTo);
});
it('should not modify the input DTO', () => {
const signupPageDTO: SignupPageDTO = {
returnTo: '/dashboard',
};
const originalDTO = { ...signupPageDTO };
SignupViewDataBuilder.build(signupPageDTO);
expect(signupPageDTO).toEqual(originalDTO);
});
it('should initialize all signup form fields with default values', () => {
const signupPageDTO: SignupPageDTO = {
returnTo: '/dashboard',
};
const result = SignupViewDataBuilder.build(signupPageDTO);
expect(result.formState.fields.firstName.value).toBe('');
expect(result.formState.fields.firstName.error).toBeUndefined();
expect(result.formState.fields.firstName.touched).toBe(false);
expect(result.formState.fields.firstName.validating).toBe(false);
expect(result.formState.fields.lastName.value).toBe('');
expect(result.formState.fields.lastName.error).toBeUndefined();
expect(result.formState.fields.lastName.touched).toBe(false);
expect(result.formState.fields.lastName.validating).toBe(false);
expect(result.formState.fields.email.value).toBe('');
expect(result.formState.fields.email.error).toBeUndefined();
expect(result.formState.fields.email.touched).toBe(false);
expect(result.formState.fields.email.validating).toBe(false);
expect(result.formState.fields.password.value).toBe('');
expect(result.formState.fields.password.error).toBeUndefined();
expect(result.formState.fields.password.touched).toBe(false);
expect(result.formState.fields.password.validating).toBe(false);
expect(result.formState.fields.confirmPassword.value).toBe('');
expect(result.formState.fields.confirmPassword.error).toBeUndefined();
expect(result.formState.fields.confirmPassword.touched).toBe(false);
expect(result.formState.fields.confirmPassword.validating).toBe(false);
});
it('should initialize form state with default values', () => {
const signupPageDTO: SignupPageDTO = {
returnTo: '/dashboard',
};
const result = SignupViewDataBuilder.build(signupPageDTO);
expect(result.formState.isValid).toBe(true);
expect(result.formState.isSubmitting).toBe(false);
expect(result.formState.submitError).toBeUndefined();
expect(result.formState.submitCount).toBe(0);
});
it('should initialize UI state flags correctly', () => {
const signupPageDTO: SignupPageDTO = {
returnTo: '/dashboard',
};
const result = SignupViewDataBuilder.build(signupPageDTO);
expect(result.isSubmitting).toBe(false);
expect(result.submitError).toBeUndefined();
});
});
describe('edge cases', () => {
it('should handle returnTo with encoded characters', () => {
const signupPageDTO: SignupPageDTO = {
returnTo: '/dashboard?redirect=%2Fadmin',
};
const result = SignupViewDataBuilder.build(signupPageDTO);
expect(result.returnTo).toBe('/dashboard?redirect=%2Fadmin');
});
it('should handle returnTo with hash fragment', () => {
const signupPageDTO: SignupPageDTO = {
returnTo: '/dashboard#section',
};
const result = SignupViewDataBuilder.build(signupPageDTO);
expect(result.returnTo).toBe('/dashboard#section');
});
});
describe('form state structure', () => {
it('should have all required form fields', () => {
const signupPageDTO: SignupPageDTO = {
returnTo: '/dashboard',
};
const result = SignupViewDataBuilder.build(signupPageDTO);
expect(result.formState.fields).toHaveProperty('firstName');
expect(result.formState.fields).toHaveProperty('lastName');
expect(result.formState.fields).toHaveProperty('email');
expect(result.formState.fields).toHaveProperty('password');
expect(result.formState.fields).toHaveProperty('confirmPassword');
});
it('should have consistent field state structure', () => {
const signupPageDTO: SignupPageDTO = {
returnTo: '/dashboard',
};
const result = SignupViewDataBuilder.build(signupPageDTO);
const fields = result.formState.fields;
Object.values(fields).forEach((field) => {
expect(field).toHaveProperty('value');
expect(field).toHaveProperty('error');
expect(field).toHaveProperty('touched');
expect(field).toHaveProperty('validating');
});
});
});
});
describe('ForgotPasswordViewDataBuilder', () => {
describe('happy paths', () => {
it('should transform ForgotPasswordPageDTO to ForgotPasswordViewData correctly', () => {
const forgotPasswordPageDTO: ForgotPasswordPageDTO = {
returnTo: '/login',
};
const result = ForgotPasswordViewDataBuilder.build(forgotPasswordPageDTO);
expect(result).toEqual({
returnTo: '/login',
showSuccess: false,
formState: {
fields: {
email: { value: '', error: undefined, touched: false, validating: false },
},
isValid: true,
isSubmitting: false,
submitError: undefined,
submitCount: 0,
},
isSubmitting: false,
submitError: undefined,
});
});
it('should handle empty returnTo path', () => {
const forgotPasswordPageDTO: ForgotPasswordPageDTO = {
returnTo: '',
};
const result = ForgotPasswordViewDataBuilder.build(forgotPasswordPageDTO);
expect(result.returnTo).toBe('');
});
it('should handle returnTo with query parameters', () => {
const forgotPasswordPageDTO: ForgotPasswordPageDTO = {
returnTo: '/login?error=expired',
};
const result = ForgotPasswordViewDataBuilder.build(forgotPasswordPageDTO);
expect(result.returnTo).toBe('/login?error=expired');
});
});
describe('data transformation', () => {
it('should preserve all DTO fields in the output', () => {
const forgotPasswordPageDTO: ForgotPasswordPageDTO = {
returnTo: '/login',
};
const result = ForgotPasswordViewDataBuilder.build(forgotPasswordPageDTO);
expect(result.returnTo).toBe(forgotPasswordPageDTO.returnTo);
});
it('should not modify the input DTO', () => {
const forgotPasswordPageDTO: ForgotPasswordPageDTO = {
returnTo: '/login',
};
const originalDTO = { ...forgotPasswordPageDTO };
ForgotPasswordViewDataBuilder.build(forgotPasswordPageDTO);
expect(forgotPasswordPageDTO).toEqual(originalDTO);
});
it('should initialize form field with default values', () => {
const forgotPasswordPageDTO: ForgotPasswordPageDTO = {
returnTo: '/login',
};
const result = ForgotPasswordViewDataBuilder.build(forgotPasswordPageDTO);
expect(result.formState.fields.email.value).toBe('');
expect(result.formState.fields.email.error).toBeUndefined();
expect(result.formState.fields.email.touched).toBe(false);
expect(result.formState.fields.email.validating).toBe(false);
});
it('should initialize form state with default values', () => {
const forgotPasswordPageDTO: ForgotPasswordPageDTO = {
returnTo: '/login',
};
const result = ForgotPasswordViewDataBuilder.build(forgotPasswordPageDTO);
expect(result.formState.isValid).toBe(true);
expect(result.formState.isSubmitting).toBe(false);
expect(result.formState.submitError).toBeUndefined();
expect(result.formState.submitCount).toBe(0);
});
it('should initialize UI state flags correctly', () => {
const forgotPasswordPageDTO: ForgotPasswordPageDTO = {
returnTo: '/login',
};
const result = ForgotPasswordViewDataBuilder.build(forgotPasswordPageDTO);
expect(result.showSuccess).toBe(false);
expect(result.isSubmitting).toBe(false);
expect(result.submitError).toBeUndefined();
});
});
describe('edge cases', () => {
it('should handle returnTo with encoded characters', () => {
const forgotPasswordPageDTO: ForgotPasswordPageDTO = {
returnTo: '/login?redirect=%2Fdashboard',
};
const result = ForgotPasswordViewDataBuilder.build(forgotPasswordPageDTO);
expect(result.returnTo).toBe('/login?redirect=%2Fdashboard');
});
it('should handle returnTo with hash fragment', () => {
const forgotPasswordPageDTO: ForgotPasswordPageDTO = {
returnTo: '/login#section',
};
const result = ForgotPasswordViewDataBuilder.build(forgotPasswordPageDTO);
expect(result.returnTo).toBe('/login#section');
});
});
describe('form state structure', () => {
it('should have email field', () => {
const forgotPasswordPageDTO: ForgotPasswordPageDTO = {
returnTo: '/login',
};
const result = ForgotPasswordViewDataBuilder.build(forgotPasswordPageDTO);
expect(result.formState.fields).toHaveProperty('email');
});
it('should have consistent field state structure', () => {
const forgotPasswordPageDTO: ForgotPasswordPageDTO = {
returnTo: '/login',
};
const result = ForgotPasswordViewDataBuilder.build(forgotPasswordPageDTO);
const field = result.formState.fields.email;
expect(field).toHaveProperty('value');
expect(field).toHaveProperty('error');
expect(field).toHaveProperty('touched');
expect(field).toHaveProperty('validating');
});
});
});
describe('ResetPasswordViewDataBuilder', () => {
describe('happy paths', () => {
it('should transform ResetPasswordPageDTO to ResetPasswordViewData correctly', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc123def456',
returnTo: '/login',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(result).toEqual({
token: 'abc123def456',
returnTo: '/login',
showSuccess: false,
formState: {
fields: {
newPassword: { value: '', error: undefined, touched: false, validating: false },
confirmPassword: { value: '', error: undefined, touched: false, validating: false },
},
isValid: true,
isSubmitting: false,
submitError: undefined,
submitCount: 0,
},
isSubmitting: false,
submitError: undefined,
});
});
it('should handle empty returnTo path', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc123def456',
returnTo: '',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(result.returnTo).toBe('');
});
it('should handle returnTo with query parameters', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc123def456',
returnTo: '/login?success=true',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(result.returnTo).toBe('/login?success=true');
});
});
describe('data transformation', () => {
it('should preserve all DTO fields in the output', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc123def456',
returnTo: '/login',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(result.token).toBe(resetPasswordPageDTO.token);
expect(result.returnTo).toBe(resetPasswordPageDTO.returnTo);
});
it('should not modify the input DTO', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc123def456',
returnTo: '/login',
};
const originalDTO = { ...resetPasswordPageDTO };
ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(resetPasswordPageDTO).toEqual(originalDTO);
});
it('should initialize form fields with default values', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc123def456',
returnTo: '/login',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(result.formState.fields.newPassword.value).toBe('');
expect(result.formState.fields.newPassword.error).toBeUndefined();
expect(result.formState.fields.newPassword.touched).toBe(false);
expect(result.formState.fields.newPassword.validating).toBe(false);
expect(result.formState.fields.confirmPassword.value).toBe('');
expect(result.formState.fields.confirmPassword.error).toBeUndefined();
expect(result.formState.fields.confirmPassword.touched).toBe(false);
expect(result.formState.fields.confirmPassword.validating).toBe(false);
});
it('should initialize form state with default values', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc123def456',
returnTo: '/login',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(result.formState.isValid).toBe(true);
expect(result.formState.isSubmitting).toBe(false);
expect(result.formState.submitError).toBeUndefined();
expect(result.formState.submitCount).toBe(0);
});
it('should initialize UI state flags correctly', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc123def456',
returnTo: '/login',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(result.showSuccess).toBe(false);
expect(result.isSubmitting).toBe(false);
expect(result.submitError).toBeUndefined();
});
});
describe('edge cases', () => {
it('should handle token with special characters', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc-123_def.456',
returnTo: '/login',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(result.token).toBe('abc-123_def.456');
});
it('should handle token with URL-encoded characters', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc%20123%40def',
returnTo: '/login',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(result.token).toBe('abc%20123%40def');
});
it('should handle returnTo with encoded characters', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc123def456',
returnTo: '/login?redirect=%2Fdashboard',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(result.returnTo).toBe('/login?redirect=%2Fdashboard');
});
it('should handle returnTo with hash fragment', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc123def456',
returnTo: '/login#section',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(result.returnTo).toBe('/login#section');
});
});
describe('form state structure', () => {
it('should have all required form fields', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc123def456',
returnTo: '/login',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
expect(result.formState.fields).toHaveProperty('newPassword');
expect(result.formState.fields).toHaveProperty('confirmPassword');
});
it('should have consistent field state structure', () => {
const resetPasswordPageDTO: ResetPasswordPageDTO = {
token: 'abc123def456',
returnTo: '/login',
};
const result = ResetPasswordViewDataBuilder.build(resetPasswordPageDTO);
const fields = result.formState.fields;
Object.values(fields).forEach((field) => {
expect(field).toHaveProperty('value');
expect(field).toHaveProperty('error');
expect(field).toHaveProperty('touched');
expect(field).toHaveProperty('validating');
});
});
});
});
describe('Auth View Data - Cross-Builder Consistency', () => {
describe('common patterns', () => {
it('should all initialize with isSubmitting false', () => {
const loginDTO: LoginPageDTO = { returnTo: '/dashboard', hasInsufficientPermissions: false };
const signupDTO: SignupPageDTO = { returnTo: '/dashboard' };
const forgotPasswordDTO: ForgotPasswordPageDTO = { returnTo: '/dashboard' };
const resetPasswordDTO: ResetPasswordPageDTO = { token: 'abc123', returnTo: '/dashboard' };
const loginResult = LoginViewDataBuilder.build(loginDTO);
const signupResult = SignupViewDataBuilder.build(signupDTO);
const forgotPasswordResult = ForgotPasswordViewDataBuilder.build(forgotPasswordDTO);
const resetPasswordResult = ResetPasswordViewDataBuilder.build(resetPasswordDTO);
expect(loginResult.isSubmitting).toBe(false);
expect(signupResult.isSubmitting).toBe(false);
expect(forgotPasswordResult.isSubmitting).toBe(false);
expect(resetPasswordResult.isSubmitting).toBe(false);
});
it('should all initialize with submitError undefined', () => {
const loginDTO: LoginPageDTO = { returnTo: '/dashboard', hasInsufficientPermissions: false };
const signupDTO: SignupPageDTO = { returnTo: '/dashboard' };
const forgotPasswordDTO: ForgotPasswordPageDTO = { returnTo: '/dashboard' };
const resetPasswordDTO: ResetPasswordPageDTO = { token: 'abc123', returnTo: '/dashboard' };
const loginResult = LoginViewDataBuilder.build(loginDTO);
const signupResult = SignupViewDataBuilder.build(signupDTO);
const forgotPasswordResult = ForgotPasswordViewDataBuilder.build(forgotPasswordDTO);
const resetPasswordResult = ResetPasswordViewDataBuilder.build(resetPasswordDTO);
expect(loginResult.submitError).toBeUndefined();
expect(signupResult.submitError).toBeUndefined();
expect(forgotPasswordResult.submitError).toBeUndefined();
expect(resetPasswordResult.submitError).toBeUndefined();
});
it('should all initialize formState.isValid as true', () => {
const loginDTO: LoginPageDTO = { returnTo: '/dashboard', hasInsufficientPermissions: false };
const signupDTO: SignupPageDTO = { returnTo: '/dashboard' };
const forgotPasswordDTO: ForgotPasswordPageDTO = { returnTo: '/dashboard' };
const resetPasswordDTO: ResetPasswordPageDTO = { token: 'abc123', returnTo: '/dashboard' };
const loginResult = LoginViewDataBuilder.build(loginDTO);
const signupResult = SignupViewDataBuilder.build(signupDTO);
const forgotPasswordResult = ForgotPasswordViewDataBuilder.build(forgotPasswordDTO);
const resetPasswordResult = ResetPasswordViewDataBuilder.build(resetPasswordDTO);
expect(loginResult.formState.isValid).toBe(true);
expect(signupResult.formState.isValid).toBe(true);
expect(forgotPasswordResult.formState.isValid).toBe(true);
expect(resetPasswordResult.formState.isValid).toBe(true);
});
it('should all initialize formState.isSubmitting as false', () => {
const loginDTO: LoginPageDTO = { returnTo: '/dashboard', hasInsufficientPermissions: false };
const signupDTO: SignupPageDTO = { returnTo: '/dashboard' };
const forgotPasswordDTO: ForgotPasswordPageDTO = { returnTo: '/dashboard' };
const resetPasswordDTO: ResetPasswordPageDTO = { token: 'abc123', returnTo: '/dashboard' };
const loginResult = LoginViewDataBuilder.build(loginDTO);
const signupResult = SignupViewDataBuilder.build(signupDTO);
const forgotPasswordResult = ForgotPasswordViewDataBuilder.build(forgotPasswordDTO);
const resetPasswordResult = ResetPasswordViewDataBuilder.build(resetPasswordDTO);
expect(loginResult.formState.isSubmitting).toBe(false);
expect(signupResult.formState.isSubmitting).toBe(false);
expect(forgotPasswordResult.formState.isSubmitting).toBe(false);
expect(resetPasswordResult.formState.isSubmitting).toBe(false);
});
it('should all initialize formState.submitError as undefined', () => {
const loginDTO: LoginPageDTO = { returnTo: '/dashboard', hasInsufficientPermissions: false };
const signupDTO: SignupPageDTO = { returnTo: '/dashboard' };
const forgotPasswordDTO: ForgotPasswordPageDTO = { returnTo: '/dashboard' };
const resetPasswordDTO: ResetPasswordPageDTO = { token: 'abc123', returnTo: '/dashboard' };
const loginResult = LoginViewDataBuilder.build(loginDTO);
const signupResult = SignupViewDataBuilder.build(signupDTO);
const forgotPasswordResult = ForgotPasswordViewDataBuilder.build(forgotPasswordDTO);
const resetPasswordResult = ResetPasswordViewDataBuilder.build(resetPasswordDTO);
expect(loginResult.formState.submitError).toBeUndefined();
expect(signupResult.formState.submitError).toBeUndefined();
expect(forgotPasswordResult.formState.submitError).toBeUndefined();
expect(resetPasswordResult.formState.submitError).toBeUndefined();
});
it('should all initialize formState.submitCount as 0', () => {
const loginDTO: LoginPageDTO = { returnTo: '/dashboard', hasInsufficientPermissions: false };
const signupDTO: SignupPageDTO = { returnTo: '/dashboard' };
const forgotPasswordDTO: ForgotPasswordPageDTO = { returnTo: '/dashboard' };
const resetPasswordDTO: ResetPasswordPageDTO = { token: 'abc123', returnTo: '/dashboard' };
const loginResult = LoginViewDataBuilder.build(loginDTO);
const signupResult = SignupViewDataBuilder.build(signupDTO);
const forgotPasswordResult = ForgotPasswordViewDataBuilder.build(forgotPasswordDTO);
const resetPasswordResult = ResetPasswordViewDataBuilder.build(resetPasswordDTO);
expect(loginResult.formState.submitCount).toBe(0);
expect(signupResult.formState.submitCount).toBe(0);
expect(forgotPasswordResult.formState.submitCount).toBe(0);
expect(resetPasswordResult.formState.submitCount).toBe(0);
});
it('should all initialize form fields with touched false', () => {
const loginDTO: LoginPageDTO = { returnTo: '/dashboard', hasInsufficientPermissions: false };
const signupDTO: SignupPageDTO = { returnTo: '/dashboard' };
const forgotPasswordDTO: ForgotPasswordPageDTO = { returnTo: '/dashboard' };
const resetPasswordDTO: ResetPasswordPageDTO = { token: 'abc123', returnTo: '/dashboard' };
const loginResult = LoginViewDataBuilder.build(loginDTO);
const signupResult = SignupViewDataBuilder.build(signupDTO);
const forgotPasswordResult = ForgotPasswordViewDataBuilder.build(forgotPasswordDTO);
const resetPasswordResult = ResetPasswordViewDataBuilder.build(resetPasswordDTO);
expect(loginResult.formState.fields.email.touched).toBe(false);
expect(loginResult.formState.fields.password.touched).toBe(false);
expect(loginResult.formState.fields.rememberMe.touched).toBe(false);
expect(signupResult.formState.fields.firstName.touched).toBe(false);
expect(signupResult.formState.fields.lastName.touched).toBe(false);
expect(signupResult.formState.fields.email.touched).toBe(false);
expect(signupResult.formState.fields.password.touched).toBe(false);
expect(signupResult.formState.fields.confirmPassword.touched).toBe(false);
expect(forgotPasswordResult.formState.fields.email.touched).toBe(false);
expect(resetPasswordResult.formState.fields.newPassword.touched).toBe(false);
expect(resetPasswordResult.formState.fields.confirmPassword.touched).toBe(false);
});
it('should all initialize form fields with validating false', () => {
const loginDTO: LoginPageDTO = { returnTo: '/dashboard', hasInsufficientPermissions: false };
const signupDTO: SignupPageDTO = { returnTo: '/dashboard' };
const forgotPasswordDTO: ForgotPasswordPageDTO = { returnTo: '/dashboard' };
const resetPasswordDTO: ResetPasswordPageDTO = { token: 'abc123', returnTo: '/dashboard' };
const loginResult = LoginViewDataBuilder.build(loginDTO);
const signupResult = SignupViewDataBuilder.build(signupDTO);
const forgotPasswordResult = ForgotPasswordViewDataBuilder.build(forgotPasswordDTO);
const resetPasswordResult = ResetPasswordViewDataBuilder.build(resetPasswordDTO);
expect(loginResult.formState.fields.email.validating).toBe(false);
expect(loginResult.formState.fields.password.validating).toBe(false);
expect(loginResult.formState.fields.rememberMe.validating).toBe(false);
expect(signupResult.formState.fields.firstName.validating).toBe(false);
expect(signupResult.formState.fields.lastName.validating).toBe(false);
expect(signupResult.formState.fields.email.validating).toBe(false);
expect(signupResult.formState.fields.password.validating).toBe(false);
expect(signupResult.formState.fields.confirmPassword.validating).toBe(false);
expect(forgotPasswordResult.formState.fields.email.validating).toBe(false);
expect(resetPasswordResult.formState.fields.newPassword.validating).toBe(false);
expect(resetPasswordResult.formState.fields.confirmPassword.validating).toBe(false);
});
it('should all initialize form fields with error undefined', () => {
const loginDTO: LoginPageDTO = { returnTo: '/dashboard', hasInsufficientPermissions: false };
const signupDTO: SignupPageDTO = { returnTo: '/dashboard' };
const forgotPasswordDTO: ForgotPasswordPageDTO = { returnTo: '/dashboard' };
const resetPasswordDTO: ResetPasswordPageDTO = { token: 'abc123', returnTo: '/dashboard' };
const loginResult = LoginViewDataBuilder.build(loginDTO);
const signupResult = SignupViewDataBuilder.build(signupDTO);
const forgotPasswordResult = ForgotPasswordViewDataBuilder.build(forgotPasswordDTO);
const resetPasswordResult = ResetPasswordViewDataBuilder.build(resetPasswordDTO);
expect(loginResult.formState.fields.email.error).toBeUndefined();
expect(loginResult.formState.fields.password.error).toBeUndefined();
expect(loginResult.formState.fields.rememberMe.error).toBeUndefined();
expect(signupResult.formState.fields.firstName.error).toBeUndefined();
expect(signupResult.formState.fields.lastName.error).toBeUndefined();
expect(signupResult.formState.fields.email.error).toBeUndefined();
expect(signupResult.formState.fields.password.error).toBeUndefined();
expect(signupResult.formState.fields.confirmPassword.error).toBeUndefined();
expect(forgotPasswordResult.formState.fields.email.error).toBeUndefined();
expect(resetPasswordResult.formState.fields.newPassword.error).toBeUndefined();
expect(resetPasswordResult.formState.fields.confirmPassword.error).toBeUndefined();
});
});
describe('common returnTo handling', () => {
it('should all handle returnTo with query parameters', () => {
const loginDTO: LoginPageDTO = { returnTo: '/dashboard?welcome=true', hasInsufficientPermissions: false };
const signupDTO: SignupPageDTO = { returnTo: '/dashboard?welcome=true' };
const forgotPasswordDTO: ForgotPasswordPageDTO = { returnTo: '/dashboard?welcome=true' };
const resetPasswordDTO: ResetPasswordPageDTO = { token: 'abc123', returnTo: '/dashboard?welcome=true' };
const loginResult = LoginViewDataBuilder.build(loginDTO);
const signupResult = SignupViewDataBuilder.build(signupDTO);
const forgotPasswordResult = ForgotPasswordViewDataBuilder.build(forgotPasswordDTO);
const resetPasswordResult = ResetPasswordViewDataBuilder.build(resetPasswordDTO);
expect(loginResult.returnTo).toBe('/dashboard?welcome=true');
expect(signupResult.returnTo).toBe('/dashboard?welcome=true');
expect(forgotPasswordResult.returnTo).toBe('/dashboard?welcome=true');
expect(resetPasswordResult.returnTo).toBe('/dashboard?welcome=true');
});
it('should all handle returnTo with hash fragments', () => {
const loginDTO: LoginPageDTO = { returnTo: '/dashboard#section', hasInsufficientPermissions: false };
const signupDTO: SignupPageDTO = { returnTo: '/dashboard#section' };
const forgotPasswordDTO: ForgotPasswordPageDTO = { returnTo: '/dashboard#section' };
const resetPasswordDTO: ResetPasswordPageDTO = { token: 'abc123', returnTo: '/dashboard#section' };
const loginResult = LoginViewDataBuilder.build(loginDTO);
const signupResult = SignupViewDataBuilder.build(signupDTO);
const forgotPasswordResult = ForgotPasswordViewDataBuilder.build(forgotPasswordDTO);
const resetPasswordResult = ResetPasswordViewDataBuilder.build(resetPasswordDTO);
expect(loginResult.returnTo).toBe('/dashboard#section');
expect(signupResult.returnTo).toBe('/dashboard#section');
expect(forgotPasswordResult.returnTo).toBe('/dashboard#section');
expect(resetPasswordResult.returnTo).toBe('/dashboard#section');
});
it('should all handle returnTo with encoded characters', () => {
const loginDTO: LoginPageDTO = { returnTo: '/dashboard?redirect=%2Fadmin', hasInsufficientPermissions: false };
const signupDTO: SignupPageDTO = { returnTo: '/dashboard?redirect=%2Fadmin' };
const forgotPasswordDTO: ForgotPasswordPageDTO = { returnTo: '/dashboard?redirect=%2Fadmin' };
const resetPasswordDTO: ResetPasswordPageDTO = { token: 'abc123', returnTo: '/dashboard?redirect=%2Fadmin' };
const loginResult = LoginViewDataBuilder.build(loginDTO);
const signupResult = SignupViewDataBuilder.build(signupDTO);
const forgotPasswordResult = ForgotPasswordViewDataBuilder.build(forgotPasswordDTO);
const resetPasswordResult = ResetPasswordViewDataBuilder.build(resetPasswordDTO);
expect(loginResult.returnTo).toBe('/dashboard?redirect=%2Fadmin');
expect(signupResult.returnTo).toBe('/dashboard?redirect=%2Fadmin');
expect(forgotPasswordResult.returnTo).toBe('/dashboard?redirect=%2Fadmin');
expect(resetPasswordResult.returnTo).toBe('/dashboard?redirect=%2Fadmin');
});
});
});