Skip to content

Commit 5164da2

Browse files
Add mock integration tests for TrackUserProtection async layer and cache stubs (JhaSourav07#3008)
The TrackUserProtection class depended on the async gitHubUserValidator service and an internal cooldown cache, but neither was tested with isolated mocks and stubs. This meant service layer contract changes or cache bugs could go undetected. Add five tests using vi.mock to stub the async validator and exercise the local cache layer: mock resolution, cache-before-DB short circuit, error propagation, cache write state, and per-user cache isolation. Co-authored-by: atul-upadhyay-7 <atul-upadhyay-7@users.noreply.github.com>
1 parent ac3c973 commit 5164da2

1 file changed

Lines changed: 60 additions & 0 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { describe, it, expect, beforeEach, vi } from 'vitest';
2+
import { trackUserProtection } from './track-user-protection';
3+
import { gitHubUserValidator } from '../github/validate-user';
4+
5+
vi.mock('../github/validate-user', () => ({
6+
gitHubUserValidator: {
7+
validateUser: vi.fn(),
8+
},
9+
}));
10+
11+
describe('TrackUserProtection Async Service Mocking & Local Cache Stubs', () => {
12+
beforeEach(() => {
13+
trackUserProtection.reset();
14+
vi.clearAllMocks();
15+
});
16+
17+
it('mocks async service layer and resolves user verification correctly', async () => {
18+
vi.mocked(gitHubUserValidator.validateUser).mockResolvedValue(true);
19+
20+
const result = await trackUserProtection.verifyAndDeduplicate('octocat');
21+
22+
expect(gitHubUserValidator.validateUser).toHaveBeenCalledTimes(1);
23+
expect(gitHubUserValidator.validateUser).toHaveBeenCalledWith('octocat');
24+
expect(result).toEqual({ allowed: true });
25+
});
26+
27+
it('queries local cache stub before triggering async database retrieval', async () => {
28+
trackUserProtection.recordWrite('testuser');
29+
30+
const result = await trackUserProtection.verifyAndDeduplicate('testuser');
31+
32+
expect(result.allowed).toBe(false);
33+
expect(result.reason).toBe('COOLDOWN_ACTIVE');
34+
expect(gitHubUserValidator.validateUser).not.toHaveBeenCalled();
35+
});
36+
37+
it('propagates async service rejection as fallback on endpoint timeout', async () => {
38+
const networkError = new Error('GitHub API timeout');
39+
vi.mocked(gitHubUserValidator.validateUser).mockRejectedValue(networkError);
40+
41+
await expect(trackUserProtection.verifyAndDeduplicate('octocat')).rejects.toThrow(
42+
'GitHub API timeout'
43+
);
44+
});
45+
46+
it('writes cache sync state on successful record callback', async () => {
47+
expect(trackUserProtection.isWriteAllowed('testuser')).toBe(true);
48+
49+
trackUserProtection.recordWrite('testuser');
50+
51+
expect(trackUserProtection.isWriteAllowed('testuser')).toBe(false);
52+
});
53+
54+
it('isolates cache entries per user without cross-contamination', async () => {
55+
trackUserProtection.recordWrite('userA');
56+
57+
expect(trackUserProtection.isWriteAllowed('userA')).toBe(false);
58+
expect(trackUserProtection.isWriteAllowed('userB')).toBe(true);
59+
});
60+
});

0 commit comments

Comments
 (0)