From 2647c14c09dc97349d6ca93d96514ab789b2fe37 Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Wed, 29 Apr 2026 18:29:16 +0200 Subject: [PATCH] =?UTF-8?q?test(ST-1110.6):=20proxy=20demo-guard=20coverag?= =?UTF-8?q?e=20=E2=80=94=20403=20for=20demo+non-GET=20on=20/api/*?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __tests__/proxy/demo-guard.test.ts | 78 ++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 __tests__/proxy/demo-guard.test.ts diff --git a/__tests__/proxy/demo-guard.test.ts b/__tests__/proxy/demo-guard.test.ts new file mode 100644 index 0000000..f229a8f --- /dev/null +++ b/__tests__/proxy/demo-guard.test.ts @@ -0,0 +1,78 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' + +const { mockUnsealData } = vi.hoisted(() => ({ + mockUnsealData: vi.fn(), +})) + +vi.mock('iron-session', () => ({ + unsealData: mockUnsealData, +})) + +vi.mock('@/lib/session', () => ({ + sessionOptions: { cookieName: 'scrum4me-session', password: 'test-secret' }, +})) + +import { NextRequest } from 'next/server' +import { proxy } from '@/proxy' + +const COOKIE_NAME = 'scrum4me-session' +const RAW_COOKIE = 'sealed-cookie-value' + +function makeRequest(method: string, path: string, withCookie = false): NextRequest { + const url = `http://localhost:3000${path}` + const headers = new Headers() + if (withCookie) headers.set('Cookie', `${COOKIE_NAME}=${RAW_COOKIE}`) + return new NextRequest(url, { method, headers }) +} + +beforeEach(() => { + vi.clearAllMocks() +}) + +describe('proxy demo-guard', () => { + it('demo + POST /api/todos → 403', async () => { + mockUnsealData.mockResolvedValue({ userId: 'demo-user', isDemo: true }) + const req = makeRequest('POST', '/api/todos', true) + const res = await proxy(req) + expect(res?.status).toBe(403) + const body = await res?.json() + expect(body.error).toMatch(/demo-modus/i) + }) + + it('demo + GET /api/todos → passthrough (GET is veilig)', async () => { + const req = makeRequest('GET', '/api/todos', true) + const res = await proxy(req) + // NextResponse.next() heeft geen status 403 + expect(res?.status).not.toBe(403) + // unsealData nooit aangeroepen voor GET + expect(mockUnsealData).not.toHaveBeenCalled() + }) + + it('non-demo + POST /api/todos → passthrough', async () => { + mockUnsealData.mockResolvedValue({ userId: 'real-user', isDemo: false }) + const req = makeRequest('POST', '/api/todos', true) + const res = await proxy(req) + expect(res?.status).not.toBe(403) + }) + + it('geen cookie + POST /api/todos → passthrough (geen sessie = niet geblokkeerd)', async () => { + const req = makeRequest('POST', '/api/todos', false) + const res = await proxy(req) + expect(mockUnsealData).not.toHaveBeenCalled() + expect(res?.status).not.toBe(403) + }) + + it('demo + POST /api/cron/expire-questions → passthrough (cron in allowlist)', async () => { + const req = makeRequest('POST', '/api/cron/expire-questions', true) + const res = await proxy(req) + expect(mockUnsealData).not.toHaveBeenCalled() + expect(res?.status).not.toBe(403) + }) + + it('demo + POST /api/auth/pair/start → 403 (M11-keuze: blokken)', async () => { + mockUnsealData.mockResolvedValue({ userId: 'demo-user', isDemo: true }) + const req = makeRequest('POST', '/api/auth/pair/start', true) + const res = await proxy(req) + expect(res?.status).toBe(403) + }) +})