feat: add public search controls
Quality / test (push) Canceled after 0s

Add public category lookup options, allowlisted sort ordering, URL-backed catalog controls, and strict search route validation with regression tests.
This commit is contained in:
2026-09-09 01:44:28 -04:00
parent 67ce29a93e
commit f4e4685ecc
10 changed files with 71 additions and 12 deletions
@@ -41,6 +41,11 @@ test('builds a public query filter set that hides sold items by default', () =>
assert.deepEqual(filters.sort, ['recently_added']);
});
test('accepts only the supported public search sort values', () => {
assert.equal(createSearchQuery({ sort: 'price_low' }).sort, 'price_low');
assert.throws(() => createSearchQuery({ sort: 'random' }), /sort must be recent/);
});
test('normalizes whitespace and punctuation in free-text search terms', () => {
assert.equal(normalizeSearchQuery(' Pikachu #199 / holo '), 'pikachu 199 holo');
});
@@ -10,6 +10,7 @@ test('returns public search results with pagination metadata', async (testContex
assert.equal(filters.page, 2);
assert.equal(filters.limit, 5);
assert.equal(filters.includeSold, true);
assert.equal(filters.sort, 'price_low');
return {
items: [{ id: 'listing-1', status: 'CLOSED' }],
pagination: { page: 2, limit: 5, total: 6, totalPages: 2 },
@@ -21,7 +22,7 @@ test('returns public search results with pagination metadata', async (testContex
const response = await app.inject({
method: 'GET',
url: '/api/v1/public/search?query=charizard&page=2&limit=5&includeSold=true',
url: '/api/v1/public/search?query=charizard&page=2&limit=5&includeSold=true&sort=price_low',
});
assert.equal(response.statusCode, 200);
@@ -45,4 +46,17 @@ test('rejects malformed numeric search filters', async (testContext) => {
assert.equal(response.statusCode, 400);
assert.equal(response.json().error.code, 'INVALID_SEARCH_FILTER');
});
test('returns active public category options', async (testContext) => {
const app = buildApp({
catalogLookupRepository: {
async listCategories() { return [{ id: 'category-1', name: 'Trading Cards' }]; },
},
});
testContext.after(() => app.close());
const response = await app.inject({ method: 'GET', url: '/api/v1/public/lookups/categories' });
assert.equal(response.statusCode, 200);
assert.deepEqual(response.json().data, [{ id: 'category-1', name: 'Trading Cards' }]);
});