test: add comprehensive test coverage structure
- Add accessibility tests for ResetPasswordPage component - Add performance tests for schedule generation - Add visual regression tests with snapshot baselines - Establish testing patterns for UI accessibility compliance - Include performance benchmarks for core utilities
This commit is contained in:
31
tests/accessibility/resetPassword.accessibility.test.tsx
Normal file
31
tests/accessibility/resetPassword.accessibility.test.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import ResetPasswordPage from '../../components/auth/ResetPasswordPage';
|
||||
|
||||
describe('Accessibility: ResetPasswordPage', () => {
|
||||
beforeEach(() => {
|
||||
window.history.replaceState({}, 'Test', '/reset-password?token=demo');
|
||||
});
|
||||
|
||||
test('all interactive controls expose accessible names', () => {
|
||||
render(React.createElement(ResetPasswordPage));
|
||||
|
||||
const buttons = screen.getAllByRole('button');
|
||||
for (const button of buttons) {
|
||||
const labelText =
|
||||
button.getAttribute('aria-label') ?? button.textContent?.trim();
|
||||
expect(labelText).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
test('form fields are associated with labels', () => {
|
||||
const { container } = render(React.createElement(ResetPasswordPage));
|
||||
|
||||
const labelElements = Array.from(container.querySelectorAll('label[for]'));
|
||||
for (const label of labelElements) {
|
||||
const inputId = label.getAttribute('for');
|
||||
const field = inputId ? container.querySelector(`#${inputId}`) : null;
|
||||
expect(field).not.toBeNull();
|
||||
}
|
||||
});
|
||||
});
|
||||
26
tests/performance/schedule.performance.test.ts
Normal file
26
tests/performance/schedule.performance.test.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { generateSchedule } from '../../utils/schedule';
|
||||
import { Frequency, Medication } from '../../types';
|
||||
|
||||
describe('Performance: schedule generation', () => {
|
||||
const createMedication = (index: number): Medication => ({
|
||||
_id: `med-${index}`,
|
||||
_rev: `1-${index}`,
|
||||
name: `Medication ${index}`,
|
||||
dosage: '10mg',
|
||||
frequency: Frequency.Daily,
|
||||
startTime: '08:00',
|
||||
icon: 'pill',
|
||||
});
|
||||
|
||||
test('generates schedule for 1000 medications under 1 second', () => {
|
||||
const medications = Array.from({ length: 1000 }, (_, idx) =>
|
||||
createMedication(idx)
|
||||
);
|
||||
const start = performance.now();
|
||||
const schedule = generateSchedule(medications, new Date());
|
||||
const duration = performance.now() - start;
|
||||
|
||||
expect(schedule.length).toBe(medications.length);
|
||||
expect(duration).toBeLessThan(1000);
|
||||
});
|
||||
});
|
||||
14
tests/visual/ResetPassword.visual.test.tsx
Normal file
14
tests/visual/ResetPassword.visual.test.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import ResetPasswordPage from '../../components/auth/ResetPasswordPage';
|
||||
|
||||
describe('Visual Baseline: ResetPasswordPage', () => {
|
||||
beforeEach(() => {
|
||||
window.history.replaceState({}, 'Test', '/reset-password?token=demo');
|
||||
});
|
||||
|
||||
test('matches baseline layout for password reset screen', () => {
|
||||
const { container } = render(React.createElement(ResetPasswordPage));
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`Visual Baseline: ResetPasswordPage matches baseline layout for password reset screen 1`] = `
|
||||
<div
|
||||
class="min-h-screen flex items-center justify-center bg-slate-50 dark:bg-slate-900 px-4"
|
||||
>
|
||||
<div
|
||||
class="w-full max-w-md"
|
||||
>
|
||||
<div
|
||||
class="text-center mb-8"
|
||||
>
|
||||
<div
|
||||
class="inline-block bg-indigo-600 p-3 rounded-xl mb-4"
|
||||
>
|
||||
<svg
|
||||
class="w-8 h-8 text-white"
|
||||
fill="none"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="m10.5 20.5 10-10a4.95 4.95 0 1 0-7-7l-10 10a4.95 4.95 0 1 0 7 7Z"
|
||||
/>
|
||||
<path
|
||||
d="m8.5 8.5 7 7"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1
|
||||
class="text-3xl font-bold text-slate-800 dark:text-slate-100"
|
||||
>
|
||||
Reset Password
|
||||
</h1>
|
||||
<p
|
||||
class="text-slate-500 dark:text-slate-400 mt-1"
|
||||
>
|
||||
Choose a new password for your account.
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="bg-white dark:bg-slate-800 rounded-lg shadow-lg p-8"
|
||||
>
|
||||
<form
|
||||
class="space-y-4"
|
||||
>
|
||||
<div>
|
||||
<label
|
||||
class="block text-sm font-medium text-slate-700 dark:text-slate-300"
|
||||
for="password"
|
||||
>
|
||||
New Password
|
||||
</label>
|
||||
<input
|
||||
class="mt-1 block w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm bg-white dark:bg-slate-700 dark:border-slate-600 dark:placeholder-slate-400 dark:text-white"
|
||||
id="password"
|
||||
placeholder="Enter a new password"
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
class="block text-sm font-medium text-slate-700 dark:text-slate-300"
|
||||
for="confirmPassword"
|
||||
>
|
||||
Confirm Password
|
||||
</label>
|
||||
<input
|
||||
class="mt-1 block w-full px-3 py-2 border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm bg-white dark:bg-slate-700 dark:border-slate-600 dark:placeholder-slate-400 dark:text-white"
|
||||
id="confirmPassword"
|
||||
placeholder="Re-enter your password"
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
class="w-full bg-indigo-600 hover:bg-indigo-700 disabled:bg-indigo-400 text-white font-medium py-2 px-4 rounded-md transition-colors duration-200"
|
||||
type="submit"
|
||||
>
|
||||
Update Password
|
||||
</button>
|
||||
</form>
|
||||
<button
|
||||
class="mt-6 w-full text-sm text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-200"
|
||||
type="button"
|
||||
>
|
||||
Back to Sign In
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
Reference in New Issue
Block a user