feat: add seller saved views
Quality / test (push) Canceled after 0s

This commit is contained in:
2026-09-10 01:36:15 -04:00
parent ec322df25c
commit ffd239d27c
19 changed files with 364 additions and 0 deletions
@@ -0,0 +1,22 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { createSavedViewService } from '../../src/modules/search/services/saved-view-service.js';
test('creates and merges a seller saved view through the repository', async () => {
const calls = [];
const service = createSavedViewService({
savedViewRepository: {
async create(sellerId, view) { calls.push([sellerId, view]); return { id: 'view-1', sellerId, ...view }; },
},
});
const result = await service.create({ sellerId: 'seller-1', view: { name: 'Needs Attention', filters: { status: 'ACTIVE', missingImages: true } } });
assert.deepEqual(result, { id: 'view-1', sellerId: 'seller-1', name: 'Needs Attention', filters: { status: 'ACTIVE', missingImages: true } });
assert.deepEqual(calls, [['seller-1', { name: 'Needs Attention', filters: { status: 'ACTIVE', missingImages: true } }]]);
});
test('rejects an unknown saved-view filter value', async () => {
const service = createSavedViewService({ savedViewRepository: {} });
await assert.rejects(() => service.create({ sellerId: 'seller-1', view: { name: 'Bad', filters: { query: { nested: true } } } }));
});
@@ -0,0 +1,48 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { buildApp } from '../../src/app/build-app.js';
function createTestApp({ authorizeUnsafeRequest } = {}) {
const views = [];
return buildApp({
authenticateAdmin: async () => ({ sellerId: 'seller-1' }),
authorizeUnsafeRequest,
savedViewService: {
async list() { return views; },
async create({ view }) { const result = { id: 'view-1', ...view }; views.push(result); return result; },
async update({ view }) { return { id: 'view-1', ...view }; },
async delete() { return { id: 'view-1' }; },
},
});
}
test('creates, lists, updates, and deletes saved views', async (testContext) => {
const app = createTestApp();
testContext.after(() => app.close());
const createResponse = await app.inject({ method: 'POST', url: '/api/v1/admin/saved-views', payload: { name: 'Needs Attention', filters: { missingImages: true } } });
const listResponse = await app.inject({ method: 'GET', url: '/api/v1/admin/saved-views' });
const updateResponse = await app.inject({ method: 'PATCH', url: '/api/v1/admin/saved-views/view-1', payload: { name: 'Recent', filters: { sort: 'recent' } } });
const deleteResponse = await app.inject({ method: 'DELETE', url: '/api/v1/admin/saved-views/view-1' });
assert.equal(createResponse.statusCode, 201);
assert.equal(listResponse.statusCode, 200);
assert.equal(updateResponse.statusCode, 200);
assert.equal(deleteResponse.statusCode, 204);
});
test('protects saved-view mutations with CSRF validation', async (testContext) => {
const app = createTestApp({
authorizeUnsafeRequest: async () => {
const error = new Error('CSRF validation failed.');
error.code = 'FORBIDDEN';
error.statusCode = 403;
throw error;
},
});
testContext.after(() => app.close());
const response = await app.inject({ method: 'POST', url: '/api/v1/admin/saved-views', payload: { name: 'Recent', filters: {} } });
assert.equal(response.statusCode, 403);
});