From 7f5cf7a9e599f4cce24f6fabfa2e6a05500c49f5 Mon Sep 17 00:00:00 2001 From: William Valentin Date: Thu, 16 Oct 2025 13:16:12 -0700 Subject: [PATCH] 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 --- .../resetPassword.accessibility.test.tsx | 31 ++++++ .../performance/schedule.performance.test.ts | 26 +++++ tests/visual/ResetPassword.visual.test.tsx | 14 +++ .../ResetPassword.visual.test.tsx.snap | 99 +++++++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 tests/accessibility/resetPassword.accessibility.test.tsx create mode 100644 tests/performance/schedule.performance.test.ts create mode 100644 tests/visual/ResetPassword.visual.test.tsx create mode 100644 tests/visual/__snapshots__/ResetPassword.visual.test.tsx.snap diff --git a/tests/accessibility/resetPassword.accessibility.test.tsx b/tests/accessibility/resetPassword.accessibility.test.tsx new file mode 100644 index 0000000..f72c27a --- /dev/null +++ b/tests/accessibility/resetPassword.accessibility.test.tsx @@ -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(); + } + }); +}); diff --git a/tests/performance/schedule.performance.test.ts b/tests/performance/schedule.performance.test.ts new file mode 100644 index 0000000..6b252d2 --- /dev/null +++ b/tests/performance/schedule.performance.test.ts @@ -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); + }); +}); diff --git a/tests/visual/ResetPassword.visual.test.tsx b/tests/visual/ResetPassword.visual.test.tsx new file mode 100644 index 0000000..9b0d4da --- /dev/null +++ b/tests/visual/ResetPassword.visual.test.tsx @@ -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(); + }); +}); diff --git a/tests/visual/__snapshots__/ResetPassword.visual.test.tsx.snap b/tests/visual/__snapshots__/ResetPassword.visual.test.tsx.snap new file mode 100644 index 0000000..620f112 --- /dev/null +++ b/tests/visual/__snapshots__/ResetPassword.visual.test.tsx.snap @@ -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`] = ` +
+
+
+
+ + + + +
+

+ Reset Password +

+

+ Choose a new password for your account. +

+
+
+
+
+ + +
+
+ + +
+ +
+ +
+
+
+`;