Some checks failed
CI / Lint (pull_request) Has been cancelled
CI / Schema map up to date (pull_request) Has been cancelled
CI / Forbidden patterns (9 checks) (pull_request) Has been cancelled
CI / Migrations apply (node-pg-migrate) (pull_request) Has been cancelled
Visual diff / Should run? (pull_request) Has been cancelled
CI / Unit tests (vitest) (pull_request) Has been cancelled
Convoy metrics gate / Require role-event telemetry on convoy PRs (pull_request) Has been cancelled
PR Health rollup / Aggregate gate status (pull_request) Has been cancelled
Preview smoke / Should run? (pull_request) Has been cancelled
Preview smoke / Playwright smoke (pull_request) Has been cancelled
Visual diff / Screenshot diff (pull_request) Has been cancelled
Add pricing schema, free API integrations (MTG bulk, TCGdex, Foolio), valuation and sort-by-price, card detail pricing UI, and nearby store discovery via home zip and OSM geo clients. Co-authored-by: Cursor <cursoragent@cursor.com>
96 lines
2.5 KiB
JavaScript
96 lines
2.5 KiB
JavaScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
vi.mock('../../lib/sql.js', () => ({
|
|
sql: vi.fn(),
|
|
}));
|
|
vi.mock('../../lib/permission-middleware.js', () => ({
|
|
getUserFromRequest: vi.fn(),
|
|
}));
|
|
|
|
import { sql } from '../../lib/sql.js';
|
|
import { getUserFromRequest } from '../../lib/permission-middleware.js';
|
|
import handler from '../../pages/api/user/settings.js';
|
|
|
|
function createRes() {
|
|
const res = {
|
|
statusCode: 200,
|
|
body: null,
|
|
status(code) {
|
|
res.statusCode = code;
|
|
return res;
|
|
},
|
|
json(data) {
|
|
res.body = data;
|
|
return res;
|
|
},
|
|
};
|
|
return res;
|
|
}
|
|
|
|
const baseUserRow = {
|
|
id: 1,
|
|
email: 'a@b.c',
|
|
role: 'user',
|
|
first_name: 'A',
|
|
last_name: 'B',
|
|
username: 'ab',
|
|
collection_visibility: 'private',
|
|
preferred_currency: 'USD',
|
|
cards_per_page: 50,
|
|
default_view: 'grid',
|
|
notifications_email: true,
|
|
notifications_marketing: false,
|
|
two_factor_enabled: false,
|
|
theme: 'system',
|
|
language: 'en',
|
|
home_zip: '10001',
|
|
created_at: '2026-01-01',
|
|
updated_at: '2026-01-01',
|
|
};
|
|
|
|
describe('/api/user/settings home_zip', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
getUserFromRequest.mockResolvedValue({ userId: 1, email: 'a@b.c', role: 'user' });
|
|
});
|
|
|
|
it('GET includes home_zip in settings', async () => {
|
|
sql.mockResolvedValue({ rows: [baseUserRow] });
|
|
const res = createRes();
|
|
await handler({ method: 'GET' }, res);
|
|
expect(res.statusCode).toBe(200);
|
|
expect(res.body.settings.home_zip).toBe('10001');
|
|
});
|
|
|
|
it('PUT persists valid 5-digit zip', async () => {
|
|
sql.query = vi.fn().mockResolvedValue({
|
|
rows: [{ ...baseUserRow, home_zip: '90210' }],
|
|
});
|
|
|
|
const res = createRes();
|
|
await handler({ method: 'PUT', body: { home_zip: '90210' } }, res);
|
|
expect(res.statusCode).toBe(200);
|
|
expect(res.body.settings.home_zip).toBe('90210');
|
|
expect(sql.query).toHaveBeenCalled();
|
|
const queryText = sql.query.mock.calls[0][0];
|
|
expect(queryText).toContain('home_zip');
|
|
});
|
|
|
|
it('PUT rejects invalid zip', async () => {
|
|
const res = createRes();
|
|
await handler({ method: 'PUT', body: { home_zip: '1234' } }, res);
|
|
expect(res.statusCode).toBe(400);
|
|
expect(res.body.error).toMatch(/zip/i);
|
|
});
|
|
|
|
it('PUT allows null to clear zip', async () => {
|
|
sql.query = vi.fn().mockResolvedValue({
|
|
rows: [{ ...baseUserRow, home_zip: null }],
|
|
});
|
|
|
|
const res = createRes();
|
|
await handler({ method: 'PUT', body: { home_zip: null } }, res);
|
|
expect(res.statusCode).toBe(200);
|
|
expect(res.body.settings.home_zip).toBeNull();
|
|
});
|
|
});
|