Files
gridpilot.gg/apps/website/lib/builders/view-models/ForgotPasswordViewModelBuilder.test.ts
Marc Mintel 94b92a9314
Some checks failed
Contract Testing / contract-tests (pull_request) Failing after 5m45s
Contract Testing / contract-snapshot (pull_request) Has been skipped
view data tests
2026-01-22 18:35:35 +01:00

496 lines
17 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { ForgotPasswordViewModelBuilder } from './ForgotPasswordViewModelBuilder';
import type { ForgotPasswordViewData } from '@/lib/builders/view-data/types/ForgotPasswordViewData';
describe('ForgotPasswordViewModelBuilder', () => {
describe('happy paths', () => {
it('should transform ForgotPasswordViewData to ForgotPasswordViewModel correctly', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result).toBeDefined();
expect(result.returnTo).toBe('/dashboard');
expect(result.formState).toBeDefined();
expect(result.formState.fields).toBeDefined();
expect(result.formState.fields.email).toBeDefined();
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.isValid).toBe(true);
expect(result.formState.isSubmitting).toBe(false);
expect(result.formState.submitError).toBeUndefined();
expect(result.formState.submitCount).toBe(0);
expect(result.hasInsufficientPermissions).toBe(false);
expect(result.error).toBeNull();
expect(result.successMessage).toBeNull();
expect(result.isProcessing).toBe(false);
});
it('should handle different returnTo paths', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/login',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/login');
});
it('should handle empty returnTo', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('');
});
});
describe('data transformation', () => {
it('should preserve all viewData fields in the output', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe(forgotPasswordViewData.returnTo);
});
it('should not modify the input viewData', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard',
};
const originalViewData = { ...forgotPasswordViewData };
ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(forgotPasswordViewData).toEqual(originalViewData);
});
});
describe('edge cases', () => {
it('should handle null returnTo', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: null,
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBeNull();
});
it('should handle undefined returnTo', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: undefined,
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBeUndefined();
});
it('should handle complex returnTo paths', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard/leagues/league-123/settings',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard/leagues/league-123/settings');
});
it('should handle returnTo with query parameters', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?tab=settings',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?tab=settings');
});
it('should handle returnTo with hash', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard#section',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard#section');
});
it('should handle returnTo with special characters', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard/leagues/league-123/settings?tab=general#section',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard/leagues/league-123/settings?tab=general#section');
});
it('should handle very long returnTo path', () => {
const longPath = '/dashboard/leagues/league-123/settings/section/subsection/item/' + 'a'.repeat(100);
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: longPath,
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe(longPath);
});
it('should handle returnTo with encoded characters', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard/leagues/league-123/settings?name=John%20Doe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard/leagues/league-123/settings?name=John%20Doe');
});
it('should handle returnTo with multiple query parameters', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?tab=settings&filter=active&sort=name',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?tab=settings&filter=active&sort=name');
});
it('should handle returnTo with fragment identifier', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard#section-1',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard#section-1');
});
it('should handle returnTo with multiple fragments', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard#section-1#subsection-2',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard#section-1#subsection-2');
});
it('should handle returnTo with trailing slash', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard/',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard/');
});
it('should handle returnTo with leading slash', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: 'dashboard',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('dashboard');
});
it('should handle returnTo with dots', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard/../login',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard/../login');
});
it('should handle returnTo with double dots', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard/../../login',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard/../../login');
});
it('should handle returnTo with percent encoding', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard/leagues/league-123/settings?name=John%20Doe&email=test%40example.com',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard/leagues/league-123/settings?name=John%20Doe&email=test%40example.com');
});
it('should handle returnTo with plus signs', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?query=hello+world',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?query=hello+world');
});
it('should handle returnTo with ampersands', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?tab=settings&filter=active',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?tab=settings&filter=active');
});
it('should handle returnTo with equals signs', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?tab=settings=value',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?tab=settings=value');
});
it('should handle returnTo with multiple equals signs', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?tab=settings=value&filter=active=true',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?tab=settings=value&filter=active=true');
});
it('should handle returnTo with semicolons', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard;jsessionid=123',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard;jsessionid=123');
});
it('should handle returnTo with colons', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard:section',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard:section');
});
it('should handle returnTo with commas', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?filter=a,b,c',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?filter=a,b,c');
});
it('should handle returnTo with spaces', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John Doe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John Doe');
});
it('should handle returnTo with tabs', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John\tDoe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John\tDoe');
});
it('should handle returnTo with newlines', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John\nDoe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John\nDoe');
});
it('should handle returnTo with carriage returns', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John\rDoe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John\rDoe');
});
it('should handle returnTo with form feeds', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John\fDoe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John\fDoe');
});
it('should handle returnTo with vertical tabs', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John\vDoe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John\vDoe');
});
it('should handle returnTo with backspaces', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John\bDoe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John\bDoe');
});
it('should handle returnTo with null bytes', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John\0Doe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John\0Doe');
});
it('should handle returnTo with bell characters', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John\aDoe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John\aDoe');
});
it('should handle returnTo with escape characters', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John\eDoe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John\eDoe');
});
it('should handle returnTo with unicode characters', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John\u00D6Doe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John\u00D6Doe');
});
it('should handle returnTo with emoji', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John😀Doe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John😀Doe');
});
it('should handle returnTo with special symbols', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard?name=John!@#$%^&*()_+-=[]{}|;:,.<>?Doe',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard?name=John!@#$%^&*()_+-=[]{}|;:,.<>?Doe');
});
it('should handle returnTo with mixed special characters', () => {
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: '/dashboard/leagues/league-123/settings?name=John%20Doe&email=test%40example.com&filter=active=true&sort=name#section-1',
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe('/dashboard/leagues/league-123/settings?name=John%20Doe&email=test%40example.com&filter=active=true&sort=name#section-1');
});
it('should handle returnTo with very long path', () => {
const longPath = '/dashboard/leagues/league-123/settings/section/subsection/item/' + 'a'.repeat(1000);
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: longPath,
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe(longPath);
});
it('should handle returnTo with very long query string', () => {
const longQuery = '/dashboard?' + 'a'.repeat(1000) + '=value';
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: longQuery,
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe(longQuery);
});
it('should handle returnTo with very long fragment', () => {
const longFragment = '/dashboard#' + 'a'.repeat(1000);
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: longFragment,
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe(longFragment);
});
it('should handle returnTo with mixed very long components', () => {
const longPath = '/dashboard/leagues/league-123/settings/section/subsection/item/' + 'a'.repeat(500);
const longQuery = '?' + 'b'.repeat(500) + '=value';
const longFragment = '#' + 'c'.repeat(500);
const forgotPasswordViewData: ForgotPasswordViewData = {
returnTo: longPath + longQuery + longFragment,
};
const result = ForgotPasswordViewModelBuilder.build(forgotPasswordViewData);
expect(result.returnTo).toBe(longPath + longQuery + longFragment);
});
});
});