import { beforeEach, describe, expect, it, vi } from 'vitest'; import { POST as updateViewingPreference } from './route'; import { POST as updateAccountPreference } from '../account-nsfw/route'; import { requireSignedAction, SignedActionError } from '@/lib/auth/verify-signature'; import { db } from '@/db'; vi.mock('@/lib/auth', () => ({ requireAuth: vi.fn() })); vi.mock('@/lib/auth/verify-signature', () => { class MockSignedActionError extends Error {} return { requireSignedAction: vi.fn(), SignedActionError: MockSignedActionError, }; }); vi.mock('drizzle-orm', () => ({ eq: vi.fn(() => ({})) })); vi.mock('@/db', () => { const where = vi.fn().mockResolvedValue(undefined); const set = vi.fn(() => ({ where })); const update = vi.fn(() => ({ set })); return { db: { update }, users: { id: 'id' }, }; }); const signedAction = (action: string, data: Record) => ({ action, data, did: 'did:synapsis:test', handle: 'tester', ts: Date.now(), nonce: 'nonce', sig: 'signature', }); const request = (body: unknown) => new Request('http://localhost/api/settings/nsfw', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); describe('NSFW settings mutations', () => { beforeEach(() => { vi.clearAllMocks(); vi.mocked(requireSignedAction).mockResolvedValue({ id: 'user-id', ageVerifiedAt: new Date('2026-01-01T00:00:00.000Z'), } as never); }); it('accepts a signed viewing-preference update', async () => { const payload = signedAction('update_nsfw_settings', { nsfwEnabled: true }); const response = await updateViewingPreference(request(payload) as never); expect(response.status).toBe(200); expect(requireSignedAction).toHaveBeenCalledWith(payload); expect(db?.update).toHaveBeenCalled(); }); it('accepts a signed account-level update', async () => { const payload = signedAction('update_account_nsfw', { isNsfw: true }); const response = await updateAccountPreference(request(payload) as never); expect(response.status).toBe(200); expect(requireSignedAction).toHaveBeenCalledWith(payload); expect(await response.json()).toMatchObject({ success: true, isNsfw: true }); }); it('rejects the old unsigned request shape', async () => { const response = await updateViewingPreference(request({ nsfwEnabled: true }) as never); expect(response.status).toBe(400); expect(requireSignedAction).not.toHaveBeenCalled(); }); it('returns a useful identity error when verification fails', async () => { vi.mocked(requireSignedAction).mockRejectedValue(new SignedActionError('INVALID_SIGNATURE')); const payload = signedAction('update_nsfw_settings', { nsfwEnabled: true }); const response = await updateViewingPreference(request(payload) as never); expect(response.status).toBe(403); expect(await response.json()).toEqual({ error: 'Your identity could not be verified. Please unlock it and try again.', }); }); });