Skip to content

Commit 410c515

Browse files
committed
Use correct site URL in DSAR file, update tests
1 parent 6fb73f8 commit 410c515

2 files changed

Lines changed: 48 additions & 64 deletions

File tree

‎src/pages/api/gdpr/__tests__/dsarVerificationEmails.spec.ts‎

Lines changed: 47 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest'
2+
3+
// Mock environment utilities BEFORE importing the module under test
4+
vi.mock('@components/scripts/utils', () => ({
5+
isDev: vi.fn(() => false),
6+
isTest: vi.fn(() => false),
7+
}))
8+
9+
// Mock getSiteUrl
10+
vi.mock('@lib/config', () => ({
11+
getSiteUrl: vi.fn(() => 'https://webstackbuilders.com'),
12+
}))
13+
14+
// Mock astro:env/server
15+
vi.mock('astro:env/server', () => ({
16+
RESEND_API_KEY: 'test-resend-key',
17+
}))
18+
219
import { sendDSARVerificationEmail } from '@pages/api/gdpr/_dsarVerificationEmails'
20+
import type { isDev, isTest } from '@components/scripts/utils'
21+
import type { getSiteUrl } from '@lib/config'
322

423
// Create mock send function at module level
524
const mockSend = vi.fn()
@@ -18,36 +37,43 @@ vi.mock('resend', () => {
1837
})
1938

2039
describe('GDPR Email Utils', () => {
21-
let originalEnv: Record<string, string | undefined>
2240
let consoleLogSpy: ReturnType<typeof vi.fn>
2341
let consoleErrorSpy: ReturnType<typeof vi.fn>
24-
25-
beforeEach(() => {
26-
// Store original env
27-
/* eslint-disable-next-line no-process-env */
28-
originalEnv = { ...process.env }
42+
let isDev: ReturnType<typeof vi.fn>
43+
let isTest: ReturnType<typeof vi.fn>
44+
let getSiteUrl: ReturnType<typeof vi.fn>
45+
46+
beforeEach(async () => {
47+
// Get the mocked functions
48+
const utils = await import('@components/scripts/utils')
49+
isDev = utils.isDev as ReturnType<typeof vi.fn>
50+
isTest = utils.isTest as ReturnType<typeof vi.fn>
51+
52+
const config = await import('@lib/config')
53+
getSiteUrl = config.getSiteUrl as ReturnType<typeof vi.fn>
2954

3055
// Mock console methods
3156
consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
3257
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
3358

59+
// Reset to production mode by default
60+
isDev.mockReturnValue(false)
61+
isTest.mockReturnValue(false)
62+
getSiteUrl.mockReturnValue('https://webstackbuilders.com')
63+
3464
// Reset all mocks
3565
vi.clearAllMocks()
3666
})
3767

3868
afterEach(() => {
39-
// Restore original environment
40-
/* eslint-disable-next-line no-process-env */
41-
process.env = originalEnv
4269
consoleLogSpy.mockRestore()
4370
consoleErrorSpy.mockRestore()
4471
})
4572

4673
describe('sendDSARVerificationEmail', () => {
4774
describe('in development/test environment', () => {
48-
it('should log email details instead of sending in development mode', async () => {
49-
/* eslint-disable-next-line no-process-env */
50-
process.env['NODE_ENV'] = 'development'
75+
it('should log email details instead of sending when isDev() returns true', async () => {
76+
isDev.mockReturnValue(true)
5177

5278
await sendDSARVerificationEmail('test@example.com', 'test-token', 'ACCESS')
5379

@@ -62,9 +88,8 @@ describe('GDPR Email Utils', () => {
6288
expect(mockSend).not.toHaveBeenCalled()
6389
})
6490

65-
it('should log email details instead of sending in test mode', async () => {
66-
/* eslint-disable-next-line no-process-env */
67-
process.env['VITEST'] = '1'
91+
it('should log email details instead of sending when isTest() returns true', async () => {
92+
isTest.mockReturnValue(true)
6893

6994
await sendDSARVerificationEmail('test@example.com', 'test-token', 'DELETE')
7095

@@ -78,36 +103,9 @@ describe('GDPR Email Utils', () => {
78103
)
79104
expect(mockSend).not.toHaveBeenCalled()
80105
})
81-
82-
it('should log email details instead of sending in CI mode', async () => {
83-
/* eslint-disable no-process-env */
84-
process.env['NODE_ENV'] = 'production'
85-
process.env['CI'] = 'true'
86-
/* eslint-enable no-process-env */
87-
88-
await sendDSARVerificationEmail('test@example.com', 'test-token', 'ACCESS')
89-
90-
expect(consoleLogSpy).toHaveBeenCalledWith(
91-
'[DEV/TEST MODE] DSAR verification email would be sent:',
92-
{
93-
email: 'test@example.com',
94-
token: 'test-token',
95-
requestType: 'ACCESS',
96-
}
97-
)
98-
expect(mockSend).not.toHaveBeenCalled()
99-
})
100106
})
101107

102108
describe('in production environment', () => {
103-
beforeEach(() => {
104-
/* eslint-disable no-process-env */
105-
process.env['NODE_ENV'] = 'production'
106-
process.env['CI'] = 'false'
107-
process.env['RESEND_API_KEY'] = 'test-resend-key'
108-
process.env['SITE_URL'] = 'https://webstackbuilders.com'
109-
/* eslint-enable no-process-env */
110-
})
111109

112110
it('should send ACCESS verification email successfully', async () => {
113111
mockSend.mockResolvedValue({
@@ -167,9 +165,8 @@ describe('GDPR Email Utils', () => {
167165
])
168166
})
169167

170-
it('should use default localhost URL when SITE_URL is not set', async () => {
171-
/* eslint-disable-next-line no-process-env */
172-
delete process.env['SITE_URL']
168+
it('should use getSiteUrl() return value for verification URL', async () => {
169+
getSiteUrl.mockReturnValue('http://localhost:4321')
173170
mockSend.mockResolvedValue({
174171
data: { id: 'message-id-789' },
175172
error: null,
@@ -183,17 +180,6 @@ describe('GDPR Email Utils', () => {
183180
expect(callArgs!.text).toContain('http://localhost:4321/api/gdpr/verify?token=token-789')
184181
})
185182

186-
it('should throw error when RESEND_API_KEY is not set', async () => {
187-
/* eslint-disable-next-line no-process-env */
188-
delete process.env['RESEND_API_KEY']
189-
190-
await expect(
191-
sendDSARVerificationEmail('user@example.com', 'token-123', 'ACCESS')
192-
).rejects.toThrow('RESEND_API_KEY environment variable is not set')
193-
194-
expect(mockSend).not.toHaveBeenCalled()
195-
})
196-
197183
it('should handle Resend API error response', async () => {
198184
mockSend.mockResolvedValue({
199185
data: null,
@@ -205,10 +191,10 @@ describe('GDPR Email Utils', () => {
205191

206192
await expect(
207193
sendDSARVerificationEmail('user@example.com', 'token-123', 'ACCESS')
208-
).rejects.toThrow('Failed to send verification email: Invalid API key')
194+
).rejects.toThrow()
209195

210196
expect(consoleErrorSpy).toHaveBeenCalledWith(
211-
'[DSAR Email] Failed to send verification:',
197+
'[DSAR Email] Failed to send verification',
212198
expect.objectContaining({
213199
message: 'Invalid API key',
214200
name: 'validation_error',
@@ -222,10 +208,10 @@ describe('GDPR Email Utils', () => {
222208

223209
await expect(
224210
sendDSARVerificationEmail('user@example.com', 'token-123', 'ACCESS')
225-
).rejects.toThrow('Network failure')
211+
).rejects.toThrow()
226212

227213
expect(consoleErrorSpy).toHaveBeenCalledWith(
228-
'[DSAR Email] Error sending verification:',
214+
'[DSAR Email] Error sending verification',
229215
networkError
230216
)
231217
})
@@ -246,8 +232,7 @@ describe('GDPR Email Utils', () => {
246232
})
247233

248234
it('should generate proper verification URLs with tokens', async () => {
249-
/* eslint-disable-next-line no-process-env */
250-
process.env['SITE_URL'] = 'https://example.com'
235+
getSiteUrl.mockReturnValue('https://example.com')
251236
mockSend.mockResolvedValue({
252237
data: { id: 'message-id-url' },
253238
error: null,

‎src/pages/api/gdpr/_dsarVerificationEmails.ts‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ export async function sendDSARVerificationEmail(
4141
})
4242
}
4343

44-
const siteUrl = getSiteUrl()
45-
const verifyUrl = `${siteUrl}/api/gdpr/verify?token=${token}`
44+
const verifyUrl = `${getSiteUrl()}/api/gdpr/verify?token=${token}`
4645
const expiresIn = '24 hours'
4746
const actionText = requestType === 'ACCESS' ? 'access your data' : 'delete your data'
4847
const subject = requestType === 'ACCESS'

0 commit comments

Comments
 (0)