import { describe, it, expect, vi, beforeEach } from 'vitest'; import { isHttpError } from '@sveltejs/kit'; import { _clearRateLimits } from '$lib/server/v2-rate-limit'; vi.mock('$lib/db', () => ({ prisma: { licenseKey: { findFirst: vi.fn() }, user: { findUnique: vi.fn() }, subscriptionLevel: { findFirst: vi.fn() } } })); import { prisma } from '$lib/db'; import { POST } from './+server'; type POSTEvent = Parameters[0]; const mockKeyFindFirst = prisma.licenseKey.findFirst as ReturnType; const mockUserFindUnique = prisma.user.findUnique as ReturnType; const mockLevelFindFirst = prisma.subscriptionLevel.findFirst as ReturnType; function licenseRequest(body: unknown): Request { return new Request('http://localhost/api/v2/license', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) }); } async function expectHttpError(promise: unknown, status: number, message: string) { try { await promise; } catch (e) { expect(isHttpError(e)).toBe(true); const err = e as { status: number; body: { message: string } }; expect(err.status).toBe(status); expect(err.body.message).toBe(message); return; } throw new Error('expected handler to throw an HttpError'); } const storedKey = { id: 'key-1', key: 'ABCD-EFGH-IJKL-MNOP', active: true, level: 'Advanced', userId: 'user-1' }; describe('POST /api/v2/license', () => { beforeEach(() => { vi.clearAllMocks(); _clearRateLimits(); }); it('returns the subscription_level object for a valid key', async () => { mockKeyFindFirst.mockResolvedValue(storedKey); mockUserFindUnique.mockResolvedValue({ id: 'user-1', email: 'user@example.com' }); mockLevelFindFirst.mockResolvedValue({ id: 2, name: 'Advanced', description: 'General + Specific' }); const res = await POST({ request: licenseRequest({ license_key: storedKey.key, email_address: 'user@example.com' }) } as POSTEvent); expect(res.status).toBe(200); expect(await res.json()).toEqual({ key: storedKey.key, email_address: 'user@example.com', subscription_level: { id: 2, name: 'Advanced', description: 'General + Specific' } }); }); it('falls back to a structurally consistent subscription_level for an unknown level name', async () => { mockKeyFindFirst.mockResolvedValue({ ...storedKey, level: 'SomeCustomLevel' }); mockUserFindUnique.mockResolvedValue({ id: 'user-1', email: 'user@example.com' }); mockLevelFindFirst.mockResolvedValue(null); const res = await POST({ request: licenseRequest({ license_key: storedKey.key, email_address: 'user@example.com' }) } as POSTEvent); expect(res.status).toBe(200); expect(await res.json()).toEqual({ key: storedKey.key, email_address: 'user@example.com', subscription_level: { id: null, name: 'SomeCustomLevel', description: null } }); }); it('rejects a missing license_key', async () => { await expectHttpError( POST({ request: licenseRequest({ email_address: 'user@example.com' }) } as POSTEvent), 400, 'license_key is required' ); }); it('rejects a missing email_address', async () => { await expectHttpError( POST({ request: licenseRequest({ license_key: storedKey.key }) } as POSTEvent), 400, 'email_address is required' ); }); it('rejects an unknown key', async () => { mockKeyFindFirst.mockResolvedValue(null); await expectHttpError( POST({ request: licenseRequest({ license_key: storedKey.key, email_address: 'user@example.com' }) } as POSTEvent), 400, 'license key not found' ); }); it('rejects an inactive key', async () => { mockKeyFindFirst.mockResolvedValue({ ...storedKey, active: false }); await expectHttpError( POST({ request: licenseRequest({ license_key: storedKey.key, email_address: 'user@example.com' }) } as POSTEvent), 400, 'license key is not active' ); }); it('rejects a nonexistent user', async () => { mockKeyFindFirst.mockResolvedValue(storedKey); mockUserFindUnique.mockResolvedValue(null); await expectHttpError( POST({ request: licenseRequest({ license_key: storedKey.key, email_address: 'nobody@example.com' }) } as POSTEvent), 400, 'user does not exist' ); }); it('rejects a key owned by a different user', async () => { mockKeyFindFirst.mockResolvedValue(storedKey); mockUserFindUnique.mockResolvedValue({ id: 'user-2', email: 'other@example.com' }); await expectHttpError( POST({ request: licenseRequest({ license_key: storedKey.key, email_address: 'other@example.com' }) } as POSTEvent), 400, 'key does not belong to specified user' ); }); it('rejects a malformed license key format', async () => { await expectHttpError( POST({ request: licenseRequest({ license_key: 'not-a-key', email_address: 'user@example.com' }) } as POSTEvent), 400, 'license key not found' ); expect(mockKeyFindFirst).not.toHaveBeenCalled(); }); });