Skip to content

Commit 74677da

Browse files
committed
test: add accessibility coverage for CompareClient
1 parent b283103 commit 74677da

2 files changed

Lines changed: 108 additions & 7 deletions

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { describe, it, expect, vi } from 'vitest';
2+
import React, { type ReactNode } from 'react';
3+
import { render, screen } from '@testing-library/react';
4+
import '@testing-library/jest-dom/vitest';
5+
6+
vi.mock('next/navigation', () => ({
7+
useRouter: () => ({
8+
push: vi.fn(),
9+
replace: vi.fn(),
10+
prefetch: vi.fn(),
11+
}),
12+
useSearchParams: () => ({
13+
get: vi.fn(() => null),
14+
}),
15+
usePathname: () => '',
16+
}));
17+
18+
vi.mock('framer-motion', () => ({
19+
motion: new Proxy(
20+
{},
21+
{
22+
get: (_, tag) => {
23+
return ({ children, ...props }: { children?: ReactNode; [key: string]: unknown }) =>
24+
React.createElement(tag as string, props, children);
25+
},
26+
}
27+
),
28+
AnimatePresence: ({ children }: { children?: ReactNode }) => <>{children}</>,
29+
}));
30+
31+
// This uses a dynamic import to completely bypass module hoisting safely without using require()
32+
const { default: CompareClient } = await import('./CompareClient');
33+
34+
describe('CompareClient Accessibility Standards', () => {
35+
it('ensures inputs and controls have accessible names', () => {
36+
render(<CompareClient />);
37+
38+
const input1 = screen.getByPlaceholderText(/github username #1/i);
39+
const input2 = screen.getByPlaceholderText(/github username #2/i);
40+
41+
expect(input1).toHaveAttribute('placeholder');
42+
expect(input2).toHaveAttribute('placeholder');
43+
});
44+
45+
it('keeps primary actions keyboard focusable with visible outline', () => {
46+
render(<CompareClient />);
47+
48+
const button = screen.getByRole('button', { name: /compare/i });
49+
50+
button.focus();
51+
52+
expect(document.activeElement).toBe(button);
53+
expect(button).toBeVisible();
54+
});
55+
56+
it('associates tooltip content using aria-describedby', () => {
57+
render(<CompareClient />);
58+
59+
const tooltipTrigger = screen.queryByRole('button', {
60+
name: /tooltip|info|help/i,
61+
});
62+
63+
if (tooltipTrigger) {
64+
const describedBy = tooltipTrigger.getAttribute('aria-describedby');
65+
expect(describedBy).toBeTruthy();
66+
67+
const tooltip = describedBy ? document.getElementById(describedBy) : null;
68+
69+
if (tooltip) {
70+
expect(tooltip.textContent?.length).toBeGreaterThan(0);
71+
}
72+
} else {
73+
expect(true).toBe(true);
74+
}
75+
});
76+
77+
it('maintains logical keyboard tab order for interactive elements', () => {
78+
render(<CompareClient />);
79+
80+
const focusables = document.querySelectorAll(
81+
'a[href], button:not([disabled]), input, select, textarea, [tabindex]:not([tabindex="-1"])'
82+
);
83+
84+
expect(focusables.length).toBeGreaterThan(0);
85+
86+
focusables.forEach((el) => {
87+
const tabIndex = el.getAttribute('tabindex');
88+
expect(tabIndex).not.toBe('-1');
89+
});
90+
});
91+
92+
it('renders proper heading hierarchy without skipping levels', () => {
93+
render(<CompareClient />);
94+
95+
const headings = screen.getAllByRole('heading');
96+
97+
expect(headings.length).toBeGreaterThan(0);
98+
99+
const levels = headings.map((h) => {
100+
const tag = h.tagName;
101+
return Number(tag.replace('H', ''));
102+
});
103+
104+
for (let i = 1; i < levels.length; i++) {
105+
expect(levels[i] - levels[i - 1]).toBeLessThanOrEqual(1);
106+
}
107+
});
108+
});

app/compare/CompareClient.test.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,6 @@ describe('CompareClient', () => {
109109
);
110110
});
111111

112-
it('renders username inputs', () => {
113-
render(<CompareClient />);
114-
115-
expect(screen.getByPlaceholderText(/github username #1/i)).toBeInTheDocument();
116-
expect(screen.getByPlaceholderText(/github username #2/i)).toBeInTheDocument();
117-
});
118-
119112
it('renders comparison page', () => {
120113
render(<CompareClient />);
121114

0 commit comments

Comments
 (0)