import { beforeEach, describe, expect, it, vi } from 'vitest'; import { listUnitPriceExpr } from '../../lib/pricing/collection-valuation.js'; vi.mock('../../lib/sql.js', () => ({ sql: { query: 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/cards/owned.js'; const UNIT_PRICE_SQL = listUnitPriceExpr({ cardAlias: 'c' }); function createRes() { const res = { statusCode: 200, body: null, status(code) { res.statusCode = code; return res; }, json(data) { res.body = data; return res; }, }; return res; } describe('GET /api/cards/owned sort', () => { beforeEach(() => { vi.clearAllMocks(); getUserFromRequest.mockResolvedValue({ userId: 1, email: 'a@b.c', role: 'user' }); sql.query.mockImplementation(async (queryText) => { if (queryText.includes('COUNT(*)')) { return { rows: [{ total: '0' }] }; } if (queryText.includes('DISTINCT')) { return { rows: [] }; } return { rows: [] }; }); }); it('orders by effective price when sort=price&order=desc', async () => { const req = { method: 'GET', query: { sort: 'price', order: 'desc' }, }; const res = createRes(); await handler(req, res); expect(res.statusCode).toBe(200); const cardsQueryCall = sql.query.mock.calls.find(([queryText]) => queryText.includes('INNER JOIN user_cards') ); expect(cardsQueryCall).toBeDefined(); const queryText = cardsQueryCall[0]; expect(queryText).toContain(UNIT_PRICE_SQL); expect(queryText).toContain('ORDER BY'); expect(queryText).toContain('DESC'); expect(queryText).toContain('NULLS LAST'); }); it('defaults to name sort when sort param is invalid', async () => { const req = { method: 'GET', query: { sort: 'invalid', order: 'asc' }, }; const res = createRes(); await handler(req, res); const cardsQueryCall = sql.query.mock.calls.find(([queryText]) => queryText.includes('INNER JOIN user_cards') ); expect(cardsQueryCall[0]).toContain('ORDER BY c.name ASC'); }); });