/** * RED test stubs for GET /api/events — Wave 0 state. * * These tests encode the contract for the evolved windowed /api/events route. * They reference the current events route which does not yet support windowed queries, * color joins, or the isShared flag — all tests are expected to fail (RED) until Plan 02. * * Contracts locked here: * 1. Missing/malformed start or end params → 400 (input validation guard) * 2. Valid window returns occurrences each with a color field and isShared flag */ import { describe, it, expect, vi } from 'vitest' // Mock DB to avoid real DB connections in unit tests vi.mock('../../src/db/client.js', () => ({ db: { select: vi.fn().mockReturnValue({ from: vi.fn().mockReturnValue({ innerJoin: vi.fn().mockReturnValue({ innerJoin: vi.fn().mockReturnValue({ where: vi.fn().mockResolvedValue([]), }), }), where: vi.fn().mockResolvedValue([]), }), }), }, })) describe('GET /api/events', () => { it('returns 400 when start param is missing', async () => { const { app } = await import('../../src/index.js') const res = await app.request('/api/events?end=2026-07-01') expect(res.status).toBe(400) }) it('returns 400 when end param is missing', async () => { const { app } = await import('../../src/index.js') const res = await app.request('/api/events?start=2026-06-01') expect(res.status).toBe(400) }) it('returns 400 when start param is malformed (not YYYY-MM-DD)', async () => { const { app } = await import('../../src/index.js') const res = await app.request('/api/events?start=not-a-date&end=2026-07-01') expect(res.status).toBe(400) }) it('returns occurrences with color and isShared fields for valid window', async () => { const { app } = await import('../../src/index.js') const res = await app.request('/api/events?start=2026-06-01&end=2026-07-01') // Route not yet evolved — currently returns raw events without windowing or color join. // This test will pass once Plan 02 implements the windowed query + expansion. expect(res.status).toBe(200) const body = await res.json() as { occurrences: Array<{ color: string; isShared: boolean }> } expect(body).toHaveProperty('occurrences') expect(Array.isArray(body.occurrences)).toBe(true) // Each occurrence must carry color + isShared (may be empty array if DB is mocked empty) for (const occ of body.occurrences) { expect(occ).toHaveProperty('color') expect(typeof occ.color).toBe('string') expect(occ).toHaveProperty('isShared') expect(typeof occ.isShared).toBe('boolean') } }) })