Skip to content

Commit 56a9e34

Browse files
committed
Add scripts/api GDPR client unit test
1 parent 2bacd1c commit 56a9e34

1 file changed

Lines changed: 139 additions & 0 deletions

File tree

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// @vitest-environment node
2+
import { beforeEach, describe, expect, it, vi } from 'vitest'
3+
import {
4+
recordConsent,
5+
recordConsentServerSide,
6+
submitDataRequest,
7+
} from '../gdpr.client'
8+
import type {
9+
ConsentRequest,
10+
ConsentResponse,
11+
DSARRequestInput,
12+
DSARResponse,
13+
ErrorResponse,
14+
} from '@pages/api/_contracts/gdpr.contracts'
15+
16+
const fetchSpy = vi.fn()
17+
18+
const mockFetchResponse = <T>(payload: T, ok = true) => ({
19+
ok,
20+
json: vi.fn().mockResolvedValue(payload),
21+
}) as unknown as Response
22+
23+
const consentRequest: ConsentRequest = {
24+
DataSubjectId: 'user-123',
25+
email: 'user@example.com',
26+
purposes: ['analytics'],
27+
source: 'cookies_modal',
28+
userAgent: 'jest',
29+
verified: false,
30+
}
31+
32+
const consentResponse: ConsentResponse = {
33+
success: true,
34+
record: {
35+
id: 'rec_1',
36+
DataSubjectId: 'user-123',
37+
email: 'user@example.com',
38+
purposes: ['analytics'],
39+
timestamp: '2024-01-01T00:00:00Z',
40+
source: 'cookies_modal',
41+
userAgent: 'jest',
42+
privacyPolicyVersion: '1.0.0',
43+
verified: false,
44+
consentText: 'text',
45+
},
46+
}
47+
48+
const dsarRequest: DSARRequestInput = {
49+
email: 'user@example.com',
50+
requestType: 'ACCESS',
51+
}
52+
53+
const dsarResponse: DSARResponse = {
54+
success: true,
55+
message: 'Request received',
56+
}
57+
58+
const errorResponse: ErrorResponse = {
59+
success: false,
60+
error: {
61+
code: 'INVALID_REQUEST',
62+
message: 'Bad request',
63+
},
64+
}
65+
66+
beforeEach(() => {
67+
fetchSpy.mockReset()
68+
globalThis.fetch = fetchSpy as unknown as typeof fetch
69+
})
70+
71+
describe('gdpr.client', () => {
72+
describe('recordConsent', () => {
73+
it('returns success payload when API call resolves', async () => {
74+
fetchSpy.mockResolvedValue(mockFetchResponse(consentResponse))
75+
76+
const result = await recordConsent(consentRequest)
77+
78+
expect(fetchSpy).toHaveBeenCalledWith('/api/gdpr/consent', expect.objectContaining({
79+
method: 'POST',
80+
headers: { 'Content-Type': 'application/json' },
81+
}))
82+
expect(JSON.parse((fetchSpy.mock.calls[0]?.[1] as RequestInit).body as string)).toEqual(consentRequest)
83+
expect(result).toEqual({ success: true, data: consentResponse })
84+
})
85+
86+
it('returns error payload when API responds with failure', async () => {
87+
fetchSpy.mockResolvedValue(mockFetchResponse(errorResponse, false))
88+
89+
const result = await recordConsent(consentRequest)
90+
91+
expect(result).toEqual({ success: false, error: errorResponse.error })
92+
})
93+
94+
it('returns fallback error when fetch throws', async () => {
95+
fetchSpy.mockRejectedValue(new Error('network down'))
96+
97+
const result = await recordConsent(consentRequest)
98+
99+
expect(result.success).toBe(false)
100+
expect(result).toEqual({
101+
success: false,
102+
error: {
103+
code: 'INVALID_REQUEST',
104+
message: 'network down',
105+
},
106+
})
107+
})
108+
})
109+
110+
describe('submitDataRequest', () => {
111+
it('hits the DSAR endpoint and returns success payload', async () => {
112+
fetchSpy.mockResolvedValue(mockFetchResponse(dsarResponse))
113+
114+
const result = await submitDataRequest(dsarRequest)
115+
116+
expect(fetchSpy).toHaveBeenCalledWith('/api/gdpr/request-data', expect.any(Object))
117+
expect(result).toEqual({ success: true, data: dsarResponse })
118+
})
119+
120+
it('mirrors error responses from the API', async () => {
121+
fetchSpy.mockResolvedValue(mockFetchResponse(errorResponse, false))
122+
123+
const result = await submitDataRequest(dsarRequest)
124+
125+
expect(result).toEqual({ success: false, error: errorResponse.error })
126+
})
127+
})
128+
129+
describe('recordConsentServerSide', () => {
130+
it('prefixes the base URL when invoking the consent endpoint', async () => {
131+
fetchSpy.mockResolvedValue(mockFetchResponse(consentResponse))
132+
133+
const result = await recordConsentServerSide('https://example.com', consentRequest)
134+
135+
expect(fetchSpy).toHaveBeenCalledWith('https://example.com/api/gdpr/consent', expect.any(Object))
136+
expect(result).toEqual({ success: true, data: consentResponse })
137+
})
138+
})
139+
})

0 commit comments

Comments
 (0)