/**
* REST Router Tests
* Tests the routeUCPv1 dispatcher that routes /ucp/v1/* requests
* to the appropriate domain handlers.
*/
vi.mock('../../src/rest/catalog.js', () => ({ handleCatalog: vi.fn() }));
vi.mock('../../src/rest/cart.js', () => ({ handleCart: vi.fn() }));
vi.mock('../../src/rest/checkout.js', () => ({ handleCheckout: vi.fn() }));
vi.mock('../../src/rest/orders.js', () => ({ handleOrders: vi.fn() }));
vi.mock('../../src/rest/negotiate.js', () => ({ handleNegotiate: vi.fn() }));
import { routeUCPv1 } from '../../src/rest/router.js';
import { handleCatalog } from '../../src/rest/catalog.js';
import { handleCart } from '../../src/rest/cart.js';
import { handleCheckout } from '../../src/rest/checkout.js';
import { handleOrders } from '../../src/rest/orders.js';
import { handleNegotiate } from '../../src/rest/negotiate.js';
// ─── Helper ───
function makeEvent(method: string, path: string): any {
return {
httpMethod: method,
path,
headers: {},
body: null,
isBase64Encoded: false,
queryStringParameters: null,
};
}
// ─── Tests ───
describe('routeUCPv1', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('OPTIONS returns 204 with empty body', async () => {
const result = await routeUCPv1(makeEvent('OPTIONS', '/ucp/v1/catalog'));
expect(result.statusCode).toBe(204);
expect(result.body).toBe('');
// Should not call any handler
expect(handleCatalog).not.toHaveBeenCalled();
expect(handleCart).not.toHaveBeenCalled();
expect(handleCheckout).not.toHaveBeenCalled();
expect(handleOrders).not.toHaveBeenCalled();
expect(handleNegotiate).not.toHaveBeenCalled();
});
it('/ucp/v1/catalog routes to handleCatalog', async () => {
const mockResponse = { statusCode: 200, body: { products: [] } };
vi.mocked(handleCatalog).mockResolvedValue(mockResponse);
const result = await routeUCPv1(makeEvent('GET', '/ucp/v1/catalog'));
expect(handleCatalog).toHaveBeenCalledTimes(1);
expect(result).toEqual(mockResponse);
});
it('/ucp/v1/cart routes to handleCart', async () => {
const mockResponse = { statusCode: 201, body: { cart_id: 'c-1' } };
vi.mocked(handleCart).mockResolvedValue(mockResponse);
const result = await routeUCPv1(makeEvent('POST', '/ucp/v1/cart'));
expect(handleCart).toHaveBeenCalledTimes(1);
expect(result).toEqual(mockResponse);
});
it('/ucp/v1/checkout routes to handleCheckout', async () => {
const mockResponse = { statusCode: 201, body: { id: 'sess-1', status: 'incomplete' } };
vi.mocked(handleCheckout).mockResolvedValue(mockResponse);
const result = await routeUCPv1(makeEvent('POST', '/ucp/v1/checkout'));
expect(handleCheckout).toHaveBeenCalledTimes(1);
expect(result).toEqual(mockResponse);
});
it('/ucp/v1/orders routes to handleOrders', async () => {
const mockResponse = { statusCode: 200, body: { found: true, order: { id: 'o-1' } } };
vi.mocked(handleOrders).mockResolvedValue(mockResponse);
const result = await routeUCPv1(makeEvent('GET', '/ucp/v1/orders'));
expect(handleOrders).toHaveBeenCalledTimes(1);
expect(result).toEqual(mockResponse);
});
it('/ucp/v1/negotiate routes to handleNegotiate', async () => {
const mockResponse = { statusCode: 200, body: { negotiation: { active_capabilities: [] } } };
vi.mocked(handleNegotiate).mockResolvedValue(mockResponse);
const result = await routeUCPv1(makeEvent('POST', '/ucp/v1/negotiate'));
expect(handleNegotiate).toHaveBeenCalledTimes(1);
expect(result).toEqual(mockResponse);
});
it('unknown path returns 404 with notFound message', async () => {
const result = await routeUCPv1(makeEvent('GET', '/ucp/v1/unknown'));
expect(result.statusCode).toBe(404);
const body = result.body as { error: { code: string; message: string } };
expect(body.error.code).toBe('not_found');
expect(body.error.message).toContain('GET');
expect(body.error.message).toContain('/ucp/v1/unknown');
});
it('/ucp/v1/catalog/products routes to handleCatalog (nested path)', async () => {
const mockResponse = { statusCode: 200, body: { products: [{ id: 'p-1' }] } };
vi.mocked(handleCatalog).mockResolvedValue(mockResponse);
const result = await routeUCPv1(makeEvent('GET', '/ucp/v1/catalog/products'));
expect(handleCatalog).toHaveBeenCalledTimes(1);
expect(result).toEqual(mockResponse);
// Ensure no other handlers were called
expect(handleCart).not.toHaveBeenCalled();
expect(handleCheckout).not.toHaveBeenCalled();
expect(handleOrders).not.toHaveBeenCalled();
expect(handleNegotiate).not.toHaveBeenCalled();
});
});