feat(pagination): add generic typed pagination with ordering to all list endpoints

- add PaginationQueryDto<TOrderBy> generic with orderBy and orderDir fields
- add SessionOrderBy, EnvironmentOrderBy, ScenarioOrderBy type aliases
- update session, environment, scenario services and controllers to use typed pagination
- update MCP list_sessions, list_environments, list_scenarios tools to expose orderBy/orderDir
- update tests for all list endpoints to cover page, limit, ordering, and invalid param rejection
This commit is contained in:
2026-04-07 17:54:23 +03:00
parent d9cdb64ee2
commit 36f8b8c0ca
16 changed files with 337 additions and 81 deletions
+30 -2
View File
@@ -68,16 +68,44 @@ describe('ScenarioController', () => {
});
it('respects page and limit params', async () => {
await createScenario('paged-sc-a');
await createScenario('paged-sc-b');
const res = await request(app.getHttpServer())
.get('/scenarios?page=1&limit=2')
.get('/scenarios?page=1&limit=1')
.expect(200);
expect(res.body.limit).toBe(2);
expect(res.body.data).toHaveLength(1);
expect(res.body.limit).toBe(1);
expect(res.body.page).toBe(1);
});
it('returns empty data for out-of-range page', async () => {
const res = await request(app.getHttpServer()).get('/scenarios?page=9999&limit=20').expect(200);
expect(res.body.data).toHaveLength(0);
});
it('returns 400 for invalid pagination params', async () => {
await request(app.getHttpServer()).get('/scenarios?page=0').expect(400);
});
it('orders by name ASC', async () => {
await createScenario('zzz-order-sc');
await createScenario('aaa-order-sc');
const res = await request(app.getHttpServer()).get('/scenarios?orderBy=name&orderDir=ASC').expect(200);
const names: string[] = res.body.data.map((s: any) => s.name);
expect(names).toEqual([...names].sort());
});
it('orders by name DESC', async () => {
const res = await request(app.getHttpServer()).get('/scenarios?orderBy=name&orderDir=DESC').expect(200);
const names: string[] = res.body.data.map((s: any) => s.name);
expect(names).toEqual([...names].sort().reverse());
});
it('returns 400 for invalid orderDir', async () => {
await request(app.getHttpServer()).get('/scenarios?orderDir=SIDEWAYS').expect(400);
});
});
// ── GET /scenarios/:id ─────────────────────────────────────────────────────