/**
* REST Handler — Orders (isolated unit tests with mocks)
* Targets 95%+ coverage of src/rest/orders.ts
*/
vi.mock('../../src/tools/track-order.js', () => ({
trackOrder: vi.fn(),
}));
import { handleOrders } from '../../src/rest/orders.js';
import type { RESTRequest } from '../../src/rest/types.js';
import { trackOrder } from '../../src/tools/track-order.js';
// ─── Helpers ───
function makeReq(overrides: Partial<RESTRequest> = {}): RESTRequest {
return {
method: 'GET',
path: '/ucp/v1/orders',
segments: [],
query: {},
body: null,
headers: {},
...overrides,
};
}
// ─── Setup ───
beforeEach(() => {
vi.clearAllMocks();
});
// ─── Tests ───
describe('handleOrders', () => {
// 1. GET with orderId — found — returns 200
it('GET /{orderId} returns 200 when order is found', async () => {
const mockResult = {
found: true,
order: { id: 'order-123', status: 'shipped' },
};
vi.mocked(trackOrder).mockResolvedValue(mockResult as any);
const res = await handleOrders(makeReq({ segments: ['order-123'] }));
expect(res.statusCode).toBe(200);
expect(res.body).toEqual(mockResult);
expect(trackOrder).toHaveBeenCalledWith({ order_id: 'order-123' });
});
// 2. GET with orderId — not found — returns 404
it('GET /{orderId} returns 404 when order is not found', async () => {
const mockResult = { found: false };
vi.mocked(trackOrder).mockResolvedValue(mockResult as any);
const res = await handleOrders(makeReq({ segments: ['order-999'] }));
expect(res.statusCode).toBe(404);
const body = res.body as { error: { code: string; message: string } };
expect(body.error.code).toBe('not_found');
expect(body.error.message).toContain('order-999');
});
// 3. GET without orderId — returns 400
it('GET without orderId returns 400 bad request', async () => {
const res = await handleOrders(makeReq());
expect(res.statusCode).toBe(400);
const body = res.body as { error: { code: string; message: string } };
expect(body.error.code).toBe('bad_request');
expect(body.error.message).toContain('order_id is required');
expect(trackOrder).not.toHaveBeenCalled();
});
// 4. POST — returns 405
it('POST returns 405 method not allowed', async () => {
const res = await handleOrders(makeReq({ method: 'POST' }));
expect(res.statusCode).toBe(405);
const body = res.body as { error: { code: string; message: string } };
expect(body.error.code).toBe('method_not_allowed');
expect(body.error.message).toContain('GET');
});
// 5. trackOrder throws — returns 500
it('returns 500 when trackOrder throws an Error', async () => {
vi.mocked(trackOrder).mockRejectedValue(new Error('Shopify API unreachable'));
const res = await handleOrders(makeReq({ segments: ['order-123'] }));
expect(res.statusCode).toBe(500);
const body = res.body as { error: { code: string; message: string } };
expect(body.error.code).toBe('internal_error');
expect(body.error.message).toContain('Shopify API unreachable');
});
// Additional edge cases
it('PUT returns 405 method not allowed', async () => {
const res = await handleOrders(makeReq({ method: 'PUT' }));
expect(res.statusCode).toBe(405);
});
it('DELETE returns 405 method not allowed', async () => {
const res = await handleOrders(makeReq({ method: 'DELETE' }));
expect(res.statusCode).toBe(405);
});
it('returns 500 when trackOrder throws a non-Error value', async () => {
vi.mocked(trackOrder).mockRejectedValue('raw string error');
const res = await handleOrders(makeReq({ segments: ['order-123'] }));
expect(res.statusCode).toBe(500);
const body = res.body as { error: { code: string; message: string } };
expect(body.error.code).toBe('internal_error');
expect(body.error.message).toBe('raw string error');
});
it('GET with multiple segments still uses first as orderId', async () => {
const mockResult = { found: true, order: { id: 'order-123', status: 'delivered' } };
vi.mocked(trackOrder).mockResolvedValue(mockResult as any);
const res = await handleOrders(makeReq({ segments: ['order-123', 'details'] }));
expect(res.statusCode).toBe(200);
expect(trackOrder).toHaveBeenCalledWith({ order_id: 'order-123' });
});
it('POST with segments still returns 405 (method check first)', async () => {
const res = await handleOrders(makeReq({ method: 'POST', segments: ['order-123'] }));
expect(res.statusCode).toBe(405);
expect(trackOrder).not.toHaveBeenCalled();
});
});