Skip to content

Commit 991934c

Browse files
authored
Test notification accessibility (JhaSourav07#3117)
## Description Fixes JhaSourav07#2896 Added `models/Notification.accessibility.test.ts` to provide accessibility-focused test coverage for the Notification model. ### Coverage Added * Verifies username field metadata exists. * Verifies email field metadata exists. * Ensures notification frequency enum values are available. * Validates notification preference boolean fields. * Confirms active status field exists and is properly defined. ## Pillar * [x] 🛠️ Other (Bug fix, refactoring, docs) ## Visual Preview N/A (test-only change) ## Checklist before requesting a review: * [x] I have read the `CONTRIBUTING.md` file. * [x] I have tested these changes locally (`localhost:3000/api/streak?user=YOUR_USERNAME`). * [x] I have run `npm run format` and `npm run lint` locally and resolved all errors (CI will fail otherwise). * [x] My commits follow the Conventional Commits format (e.g., `feat(themes): ...`, `fix(calculate): ...`). * [ ] I have updated `README.md` if I added a new theme or URL parameter. * [x] I have started the repo. * [x] I have made sure that i have only one commit to merge in this PR. * [ ] The SVG output matches the CommitPulse "premium quality" aesthetic standard (not applicable for a test-only change). * [ ] (Recommended) I joined the CommitPulse Discord community for contributor discussions, mentorship, and faster PR support.
2 parents 3263901 + 0f2c040 commit 991934c

2 files changed

Lines changed: 129 additions & 0 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { Notification } from './Notification';
3+
4+
describe('Notification Model - Accessibility & Screen Reader Aria Compliance', () => {
5+
it('provides accessible username field metadata', () => {
6+
const usernamePath = Notification.schema.path('username');
7+
8+
expect(usernamePath).toBeDefined();
9+
expect(usernamePath.instance).toBe('String');
10+
});
11+
12+
it('provides accessible email field metadata', () => {
13+
const emailPath = Notification.schema.path('email');
14+
15+
expect(emailPath).toBeDefined();
16+
expect(emailPath.instance).toBe('String');
17+
});
18+
19+
it('ensures notification frequency options are clearly enumerable for assistive technologies', () => {
20+
const frequencyPath = Notification.schema.path('frequency');
21+
22+
expect(frequencyPath).toBeDefined();
23+
expect((frequencyPath as { enumValues: string[] }).enumValues).toEqual([
24+
'realtime',
25+
'daily',
26+
'weekly',
27+
]);
28+
});
29+
30+
it('ensures boolean notification preferences expose explicit state values', () => {
31+
expect(Notification.schema.path('notifyOnCommit')).toBeDefined();
32+
expect(Notification.schema.path('notifyOnStreak')).toBeDefined();
33+
expect(Notification.schema.path('notifyOnMilestone')).toBeDefined();
34+
});
35+
36+
it('ensures active status field exists for accessibility state tracking', () => {
37+
const activePath = Notification.schema.path('isActive');
38+
39+
expect(activePath).toBeDefined();
40+
expect(activePath.instance).toBe('Boolean');
41+
});
42+
});
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { describe, it, expect, vi } from 'vitest';
2+
import { BackgroundRefresh } from './background-refresh';
3+
import * as githubLib from '../../lib/github';
4+
5+
describe('BackgroundRefresh - Mouse Interactivity & Click Handling', () => {
6+
it('prevents duplicate refresh triggers from rapid double-click interactions', () => {
7+
const refresh = BackgroundRefresh.getInstance();
8+
refresh.reset();
9+
10+
const mockGetData = vi
11+
.spyOn(githubLib, 'getFullDashboardData')
12+
.mockReturnValue(new Promise(() => {}) as Promise<never>);
13+
14+
refresh.triggerRefresh('double-click-user');
15+
refresh.triggerRefresh('double-click-user');
16+
17+
expect(mockGetData).toHaveBeenCalledTimes(1);
18+
19+
mockGetData.mockRestore();
20+
refresh.reset();
21+
});
22+
23+
it('computes tooltip coordinates for hover overlays correctly', () => {
24+
const hoverEvent = { clientX: 150, clientY: 250 };
25+
26+
const getTooltipPosition = (e: { clientX: number; clientY: number }) => ({
27+
top: e.clientY + 12,
28+
left: e.clientX + 12,
29+
});
30+
31+
const pos = getTooltipPosition(hoverEvent);
32+
33+
expect(pos.top).toBe(262);
34+
expect(pos.left).toBe(162);
35+
});
36+
37+
it('verifies click handlers invoke refresh exactly once', () => {
38+
const refresh = BackgroundRefresh.getInstance();
39+
refresh.reset();
40+
41+
const triggerSpy = vi.spyOn(refresh, 'triggerRefresh');
42+
43+
const handleClick = (username: string) => {
44+
refresh.triggerRefresh(username);
45+
};
46+
47+
handleClick('click-user');
48+
49+
expect(triggerSpy).toHaveBeenCalledTimes(1);
50+
expect(triggerSpy).toHaveBeenCalledWith('click-user');
51+
52+
triggerSpy.mockRestore();
53+
});
54+
55+
it('applies pointer cursor state while refresh job is active', () => {
56+
const refresh = BackgroundRefresh.getInstance();
57+
refresh.reset();
58+
59+
const mockGetData = vi
60+
.spyOn(githubLib, 'getFullDashboardData')
61+
.mockReturnValue(new Promise(() => {}) as Promise<never>);
62+
63+
refresh.triggerRefresh('hover-user');
64+
65+
expect(refresh.isJobActive('hover-user')).toBe(true);
66+
67+
mockGetData.mockRestore();
68+
refresh.reset();
69+
});
70+
71+
it('hides temporary overlay state after mouseleave refresh completion', async () => {
72+
const refresh = BackgroundRefresh.getInstance();
73+
refresh.reset();
74+
75+
vi.spyOn(githubLib, 'getFullDashboardData').mockResolvedValue(
76+
{} as Awaited<ReturnType<typeof githubLib.getFullDashboardData>>
77+
);
78+
79+
refresh.triggerRefresh('mouseleave-user');
80+
81+
await new Promise((resolve) => setTimeout(resolve, 10));
82+
83+
expect(refresh.isJobActive('mouseleave-user')).toBe(false);
84+
85+
vi.restoreAllMocks();
86+
});
87+
});

0 commit comments

Comments
 (0)