Skip to content

Commit c78f4b4

Browse files
authored
test(pagination): add coverage for body and query fallback logic
1 parent 827d9c8 commit c78f4b4

File tree

1 file changed

+187
-2
lines changed

1 file changed

+187
-2
lines changed

packages/openapi-ts/src/ir/__tests__/pagination.test.ts

Lines changed: 187 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import { describe, expect, it } from 'vitest';
1+
import { describe, expect, it, vi } from 'vitest';
22

33
import type { Config } from '../../types/config';
4+
import { operationPagination } from '../operation';
45
import { getPaginationKeywordsRegExp } from '../pagination';
6+
import type { IR } from '../types';
57

68
describe('paginationKeywordsRegExp', () => {
79
const defaultScenarios: Array<{
@@ -66,9 +68,192 @@ describe('paginationKeywordsRegExp', () => {
6668
const pagination: Config['input']['pagination'] = {
6769
keywords: ['customPagination', 'pageSize', 'perPage'],
6870
};
69-
7071
const paginationRegExp = getPaginationKeywordsRegExp(pagination);
7172
expect(paginationRegExp.test(value)).toEqual(result);
7273
},
7374
);
7475
});
76+
77+
describe('operationPagination', () => {
78+
const queryScenarios: Array<{
79+
hasPagination: boolean;
80+
operation: IR.OperationObject;
81+
}> = [
82+
{
83+
hasPagination: true,
84+
operation: {
85+
id: 'op1',
86+
method: 'get',
87+
parameters: {
88+
query: {
89+
page: {
90+
explode: true,
91+
location: 'query',
92+
name: 'page',
93+
schema: { type: 'integer' },
94+
style: 'form',
95+
},
96+
perPage: {
97+
explode: true,
98+
location: 'query',
99+
name: 'perPage',
100+
schema: { type: 'integer' },
101+
style: 'form',
102+
},
103+
},
104+
},
105+
path: '/test',
106+
},
107+
},
108+
{
109+
hasPagination: false,
110+
operation: {
111+
id: 'op2',
112+
method: 'get',
113+
parameters: {
114+
query: {
115+
sort: {
116+
explode: true,
117+
location: 'query',
118+
name: 'sort',
119+
schema: { type: 'string' },
120+
style: 'form',
121+
},
122+
},
123+
},
124+
path: '/test',
125+
},
126+
},
127+
];
128+
129+
it.each(queryScenarios)(
130+
'query params for $operation.id → $hasPagination',
131+
({ hasPagination, operation }) => {
132+
const result = operationPagination({ context: {} as any, operation });
133+
expect(Boolean(result)).toEqual(hasPagination);
134+
},
135+
);
136+
137+
it('body.pagination === true returns entire body', () => {
138+
const operation: IR.OperationObject = {
139+
body: {
140+
mediaType: 'application/json',
141+
pagination: true,
142+
schema: {
143+
properties: {
144+
page: { type: 'integer' },
145+
},
146+
type: 'object',
147+
},
148+
},
149+
id: 'bodyTrue',
150+
method: 'post',
151+
path: '/test',
152+
};
153+
154+
const result = operationPagination({ context: {} as any, operation });
155+
156+
expect(result?.in).toEqual('body');
157+
expect(result?.name).toEqual('body');
158+
expect(result?.schema?.type).toEqual('object');
159+
});
160+
161+
it('body.pagination = "pagination" returns the matching property', () => {
162+
const operation: IR.OperationObject = {
163+
body: {
164+
mediaType: 'application/json',
165+
pagination: 'pagination',
166+
schema: {
167+
properties: {
168+
pagination: {
169+
properties: {
170+
page: { type: 'integer' },
171+
},
172+
type: 'object',
173+
},
174+
},
175+
type: 'object',
176+
},
177+
},
178+
id: 'bodyField',
179+
method: 'post',
180+
path: '/test',
181+
};
182+
183+
const result = operationPagination({ context: {} as any, operation });
184+
185+
expect(result?.in).toEqual('body');
186+
expect(result?.name).toEqual('pagination');
187+
expect(result?.schema?.type).toEqual('object');
188+
});
189+
190+
it('resolves $ref and uses the resolved pagination property', () => {
191+
const context: IR.Context = {
192+
resolveIrRef: vi.fn().mockReturnValue({
193+
properties: {
194+
pagination: {
195+
properties: {
196+
page: { type: 'integer' },
197+
},
198+
type: 'object',
199+
},
200+
},
201+
type: 'object',
202+
}),
203+
} as unknown as IR.Context;
204+
205+
const operation: IR.OperationObject = {
206+
body: {
207+
mediaType: 'application/json',
208+
pagination: 'pagination',
209+
schema: { $ref: '#/components/schemas/PaginationBody' },
210+
},
211+
id: 'refPagination',
212+
method: 'post',
213+
path: '/test',
214+
};
215+
216+
const result = operationPagination({ context, operation });
217+
218+
expect(context.resolveIrRef).toHaveBeenCalledWith(
219+
'#/components/schemas/PaginationBody',
220+
);
221+
expect(result?.in).toEqual('body');
222+
expect(result?.name).toEqual('pagination');
223+
expect(result?.schema?.type).toEqual('object');
224+
});
225+
226+
it('falls back to query when pagination key not found in body', () => {
227+
const operation: IR.OperationObject = {
228+
body: {
229+
mediaType: 'application/json',
230+
pagination: 'pagination',
231+
schema: {
232+
properties: {
233+
notPagination: { type: 'string' },
234+
},
235+
type: 'object',
236+
},
237+
},
238+
id: 'fallback',
239+
method: 'post',
240+
parameters: {
241+
query: {
242+
cursor: {
243+
explode: true,
244+
location: 'query',
245+
name: 'cursor',
246+
schema: { type: 'string' },
247+
style: 'form',
248+
},
249+
},
250+
},
251+
path: '/test',
252+
};
253+
254+
const result = operationPagination({ context: {} as any, operation });
255+
256+
expect(result?.in).toEqual('query');
257+
expect(result?.schema?.properties?.cursor).toBeDefined();
258+
});
259+
});

0 commit comments

Comments
 (0)