1db2933758
Hop-State: A_06FP8RGGWKVFCFAHNJBQWT0 Hop-Proposal: R_06FP8RG166W8E071QG1PYWG Hop-Task: T_06FP8QVS84N3BR04V6F3GJG Hop-Attempt: AT_06FP8QVS87X77VCAYKNHKF0
93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
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<string, unknown>) => ({
|
|
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.',
|
|
});
|
|
});
|
|
});
|
|
|