@longzai-intelligence/pagination 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -203
- package/dist/hono.cjs +1 -0
- package/dist/hono.d.cts +15 -0
- package/dist/hono.d.mts +15 -0
- package/dist/hono.mjs +1 -0
- package/dist/index-C4IwIpFc.d.mts +199 -0
- package/dist/index-DpbbjAwO.d.cts +199 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +79 -80
- package/dist/index.d.mts +79 -80
- package/dist/index.mjs +1 -1
- package/dist/typeorm.cjs +1 -0
- package/dist/typeorm.d.cts +26 -0
- package/dist/typeorm.d.mts +26 -0
- package/dist/typeorm.mjs +1 -0
- package/dist/utils-B200OLT-.cjs +1 -0
- package/dist/utils-DsM7-PZL.mjs +1 -0
- package/package.json +29 -5
- package/.turbo/turbo-build.log +0 -22
- package/.turbo/turbo-lint.log +0 -1
- package/.turbo/turbo-test$colon$coverage.log +0 -36
- package/.turbo/turbo-test.log +0 -14
- package/.turbo/turbo-typecheck.log +0 -4
- package/CHANGELOG.md +0 -11
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/coverage-final.json +0 -12
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -161
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/coverage/src/adapters/index.html +0 -131
- package/coverage/src/adapters/index.ts.html +0 -118
- package/coverage/src/adapters/typeorm.adapter.ts.html +0 -940
- package/coverage/src/index.html +0 -116
- package/coverage/src/index.ts.html +0 -253
- package/coverage/src/types/index.html +0 -176
- package/coverage/src/types/index.ts.html +0 -133
- package/coverage/src/types/pagination.types.ts.html +0 -292
- package/coverage/src/types/result.types.ts.html +0 -415
- package/coverage/src/types/sort.types.ts.html +0 -265
- package/coverage/src/types/typeorm.d.ts.html +0 -196
- package/coverage/src/utils/index.html +0 -146
- package/coverage/src/utils/index.ts.html +0 -178
- package/coverage/src/utils/pagination.util.ts.html +0 -703
- package/coverage/src/utils/validation.util.ts.html +0 -535
- package/eslint.config.ts +0 -3
- package/src/__tests__/index.test.ts +0 -66
- package/src/__tests__/pagination.util.test.ts +0 -253
- package/src/__tests__/typeorm.adapter.test.ts +0 -214
- package/src/__tests__/validation.util.test.ts +0 -122
- package/src/adapters/index.ts +0 -11
- package/src/adapters/typeorm.adapter.ts +0 -285
- package/src/index.ts +0 -56
- package/src/types/index.ts +0 -16
- package/src/types/pagination.types.ts +0 -69
- package/src/types/result.types.ts +0 -110
- package/src/types/sort.types.ts +0 -60
- package/src/types/typeorm.d.ts +0 -37
- package/src/utils/index.ts +0 -31
- package/src/utils/pagination.util.ts +0 -206
- package/src/utils/validation.util.ts +0 -150
- package/tsconfig/.cache/app.tsbuildinfo +0 -1
- package/tsconfig/.cache/build.tsbuildinfo +0 -1
- package/tsconfig/.cache/node.tsbuildinfo +0 -1
- package/tsconfig/.cache/test.tsbuildinfo +0 -1
- package/tsconfig/app.json +0 -12
- package/tsconfig/node.json +0 -11
- package/tsconfig/test.json +0 -14
- package/tsconfig.json +0 -9
- package/tsdown.config.ts +0 -6
- package/vitest.config.ts +0 -3
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file pagination.util.test.ts
|
|
3
|
-
* 分页计算工具函数测试
|
|
4
|
-
* @author Longzai Intelligence
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect } from 'vitest';
|
|
8
|
-
import {
|
|
9
|
-
normalizePagination,
|
|
10
|
-
normalizeOffsetPagination,
|
|
11
|
-
calculateOffset,
|
|
12
|
-
calculateTotalPages,
|
|
13
|
-
hasNextPage,
|
|
14
|
-
hasPreviousPage,
|
|
15
|
-
offsetToPage,
|
|
16
|
-
pageToOffset,
|
|
17
|
-
createPaginatedResult,
|
|
18
|
-
} from '@/utils/pagination.util';
|
|
19
|
-
import { PAGINATION_DEFAULTS } from '@/types';
|
|
20
|
-
|
|
21
|
-
describe('normalizePagination', () => {
|
|
22
|
-
it('应返回默认值当参数为空时', () => {
|
|
23
|
-
const result = normalizePagination();
|
|
24
|
-
expect(result).toEqual({
|
|
25
|
-
page: PAGINATION_DEFAULTS.page,
|
|
26
|
-
pageSize: PAGINATION_DEFAULTS.pageSize,
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('应返回默认值当参数为 undefined 时', () => {
|
|
31
|
-
const result = normalizePagination(undefined);
|
|
32
|
-
expect(result).toEqual({
|
|
33
|
-
page: PAGINATION_DEFAULTS.page,
|
|
34
|
-
pageSize: PAGINATION_DEFAULTS.pageSize,
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('应正确规范化有效的分页参数', () => {
|
|
39
|
-
const result = normalizePagination({ page: 2, pageSize: 50 });
|
|
40
|
-
expect(result).toEqual({ page: 2, pageSize: 50 });
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('应限制 pageSize 不超过最大值', () => {
|
|
44
|
-
const result = normalizePagination({ pageSize: 200 });
|
|
45
|
-
expect(result.pageSize).toBe(PAGINATION_DEFAULTS.maxPageSize);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('应限制 pageSize 不小于最小值', () => {
|
|
49
|
-
const result = normalizePagination({ pageSize: 0 });
|
|
50
|
-
expect(result.pageSize).toBe(PAGINATION_DEFAULTS.minPageSize);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('应限制 page 不小于 1', () => {
|
|
54
|
-
const result = normalizePagination({ page: -1 });
|
|
55
|
-
expect(result.page).toBe(1);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('应正确处理小数值', () => {
|
|
59
|
-
const result = normalizePagination({ page: 1.5, pageSize: 10.9 });
|
|
60
|
-
expect(result).toEqual({ page: 1, pageSize: 10 });
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('应正确处理部分参数', () => {
|
|
64
|
-
const result = normalizePagination({ page: 5 });
|
|
65
|
-
expect(result).toEqual({ page: 5, pageSize: PAGINATION_DEFAULTS.pageSize });
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
describe('normalizeOffsetPagination', () => {
|
|
70
|
-
it('应返回默认值当参数为空时', () => {
|
|
71
|
-
const result = normalizeOffsetPagination();
|
|
72
|
-
expect(result).toEqual({
|
|
73
|
-
limit: PAGINATION_DEFAULTS.pageSize,
|
|
74
|
-
offset: 0,
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('应正确规范化有效的 offset 分页参数', () => {
|
|
79
|
-
const result = normalizeOffsetPagination({ limit: 50, offset: 100 });
|
|
80
|
-
expect(result).toEqual({ limit: 50, offset: 100 });
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('应限制 limit 不超过最大值', () => {
|
|
84
|
-
const result = normalizeOffsetPagination({ limit: 200 });
|
|
85
|
-
expect(result.limit).toBe(PAGINATION_DEFAULTS.maxPageSize);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it('应限制 limit 不小于最小值', () => {
|
|
89
|
-
const result = normalizeOffsetPagination({ limit: 0 });
|
|
90
|
-
expect(result.limit).toBe(PAGINATION_DEFAULTS.minPageSize);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('应限制 offset 不小于 0', () => {
|
|
94
|
-
const result = normalizeOffsetPagination({ offset: -10 });
|
|
95
|
-
expect(result.offset).toBe(0);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('应正确处理小数值', () => {
|
|
99
|
-
const result = normalizeOffsetPagination({ limit: 10.9, offset: 50.5 });
|
|
100
|
-
expect(result).toEqual({ limit: 10, offset: 50 });
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
describe('calculateOffset', () => {
|
|
105
|
-
it('应正确计算第一页的偏移量', () => {
|
|
106
|
-
expect(calculateOffset(1, 20)).toBe(0);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('应正确计算第二页的偏移量', () => {
|
|
110
|
-
expect(calculateOffset(2, 20)).toBe(20);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('应正确计算任意页的偏移量', () => {
|
|
114
|
-
expect(calculateOffset(5, 10)).toBe(40);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('应正确处理不同的页面大小', () => {
|
|
118
|
-
expect(calculateOffset(3, 50)).toBe(100);
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
describe('calculateTotalPages', () => {
|
|
123
|
-
it('应正确计算总页数', () => {
|
|
124
|
-
expect(calculateTotalPages(100, 20)).toBe(5);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('应正确处理有余数的情况', () => {
|
|
128
|
-
expect(calculateTotalPages(95, 20)).toBe(5);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('应正确处理总数为 0 的情况', () => {
|
|
132
|
-
expect(calculateTotalPages(0, 20)).toBe(0);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('应正确处理总数小于页面大小的情况', () => {
|
|
136
|
-
expect(calculateTotalPages(15, 20)).toBe(1);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('应正确处理 pageSize 为 0 的情况', () => {
|
|
140
|
-
expect(calculateTotalPages(100, 0)).toBe(0);
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
describe('hasNextPage', () => {
|
|
145
|
-
it('应返回 true 当有下一页时', () => {
|
|
146
|
-
expect(hasNextPage(1, 5)).toBe(true);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('应返回 false 当在最后一页时', () => {
|
|
150
|
-
expect(hasNextPage(5, 5)).toBe(false);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('应返回 false 当总页数为 0 时', () => {
|
|
154
|
-
expect(hasNextPage(1, 0)).toBe(false);
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
describe('hasPreviousPage', () => {
|
|
159
|
-
it('应返回 false 当在第一页时', () => {
|
|
160
|
-
expect(hasPreviousPage(1)).toBe(false);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('应返回 true 当不在第一页时', () => {
|
|
164
|
-
expect(hasPreviousPage(2)).toBe(true);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it('应返回 true 当在大页码时', () => {
|
|
168
|
-
expect(hasPreviousPage(100)).toBe(true);
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
describe('offsetToPage', () => {
|
|
173
|
-
it('应正确转换 offset 0 到第一页', () => {
|
|
174
|
-
expect(offsetToPage(0, 20)).toEqual({ page: 1, pageSize: 20 });
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it('应正确转换 offset 到对应页', () => {
|
|
178
|
-
expect(offsetToPage(40, 20)).toEqual({ page: 3, pageSize: 20 });
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
it('应正确处理非整除情况', () => {
|
|
182
|
-
expect(offsetToPage(25, 20)).toEqual({ page: 2, pageSize: 20 });
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it('应正确处理 limit 为 0 的情况', () => {
|
|
186
|
-
expect(offsetToPage(0, 0)).toEqual({ page: 1, pageSize: 1 });
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
describe('pageToOffset', () => {
|
|
191
|
-
it('应正确转换第一页到 offset 0', () => {
|
|
192
|
-
expect(pageToOffset(1, 20)).toEqual({ offset: 0, limit: 20 });
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it('应正确转换页码到 offset', () => {
|
|
196
|
-
expect(pageToOffset(3, 20)).toEqual({ offset: 40, limit: 20 });
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
it('应正确处理 page 为 0 的情况', () => {
|
|
200
|
-
expect(pageToOffset(0, 20)).toEqual({ offset: 0, limit: 20 });
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('应正确处理 pageSize 为 0 的情况', () => {
|
|
204
|
-
expect(pageToOffset(1, 0)).toEqual({ offset: 0, limit: 1 });
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
describe('createPaginatedResult', () => {
|
|
209
|
-
it('应正确创建分页结果', () => {
|
|
210
|
-
const items = [1, 2, 3];
|
|
211
|
-
const result = createPaginatedResult(items, 100, 2, 20);
|
|
212
|
-
|
|
213
|
-
expect(result).toEqual({
|
|
214
|
-
items,
|
|
215
|
-
total: 100,
|
|
216
|
-
page: 2,
|
|
217
|
-
pageSize: 20,
|
|
218
|
-
totalPages: 5,
|
|
219
|
-
hasNextPage: true,
|
|
220
|
-
hasPreviousPage: true,
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it('应正确处理第一页', () => {
|
|
225
|
-
const items = [1, 2, 3];
|
|
226
|
-
const result = createPaginatedResult(items, 100, 1, 20);
|
|
227
|
-
|
|
228
|
-
expect(result.hasPreviousPage).toBe(false);
|
|
229
|
-
expect(result.hasNextPage).toBe(true);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it('应正确处理最后一页', () => {
|
|
233
|
-
const items = [1, 2, 3];
|
|
234
|
-
const result = createPaginatedResult(items, 100, 5, 20);
|
|
235
|
-
|
|
236
|
-
expect(result.hasPreviousPage).toBe(true);
|
|
237
|
-
expect(result.hasNextPage).toBe(false);
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
it('应正确处理空结果', () => {
|
|
241
|
-
const result = createPaginatedResult([], 0, 1, 20);
|
|
242
|
-
|
|
243
|
-
expect(result).toEqual({
|
|
244
|
-
items: [],
|
|
245
|
-
total: 0,
|
|
246
|
-
page: 1,
|
|
247
|
-
pageSize: 20,
|
|
248
|
-
totalPages: 0,
|
|
249
|
-
hasNextPage: false,
|
|
250
|
-
hasPreviousPage: false,
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
});
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file typeorm.adapter.test.ts
|
|
3
|
-
* TypeORM 适配器测试
|
|
4
|
-
* @author Longzai Intelligence
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
8
|
-
import {
|
|
9
|
-
paginateWithRepository,
|
|
10
|
-
paginateWithQueryBuilder,
|
|
11
|
-
createPaginationQueryBuilder,
|
|
12
|
-
} from '@/adapters/typeorm.adapter';
|
|
13
|
-
import type { Repository, SelectQueryBuilder, FindOptionsOrder } from 'typeorm';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 测试实体类型
|
|
17
|
-
*
|
|
18
|
-
* 用于测试的简单实体定义
|
|
19
|
-
*/
|
|
20
|
-
type TestEntity = {
|
|
21
|
-
id: number;
|
|
22
|
-
name?: string;
|
|
23
|
-
status?: string;
|
|
24
|
-
createdAt?: Date;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* 映射后的 DTO 类型
|
|
29
|
-
*/
|
|
30
|
-
type MappedDto = {
|
|
31
|
-
mapped: TestEntity;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* 创建模拟的 Repository
|
|
36
|
-
*
|
|
37
|
-
* @returns 模拟的 Repository 对象
|
|
38
|
-
*/
|
|
39
|
-
function createMockRepository(): Repository<TestEntity> {
|
|
40
|
-
return {
|
|
41
|
-
findAndCount: vi.fn(),
|
|
42
|
-
createQueryBuilder: vi.fn(),
|
|
43
|
-
metadata: {
|
|
44
|
-
name: 'TestEntity',
|
|
45
|
-
},
|
|
46
|
-
} as Repository<TestEntity>;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* 创建模拟的 QueryBuilder
|
|
51
|
-
*
|
|
52
|
-
* @returns 模拟的 QueryBuilder 对象
|
|
53
|
-
*/
|
|
54
|
-
function createMockQueryBuilder(): SelectQueryBuilder<TestEntity> {
|
|
55
|
-
return {
|
|
56
|
-
skip: vi.fn().mockReturnThis(),
|
|
57
|
-
take: vi.fn().mockReturnThis(),
|
|
58
|
-
getManyAndCount: vi.fn(),
|
|
59
|
-
} as SelectQueryBuilder<TestEntity>;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
describe('paginateWithRepository', () => {
|
|
63
|
-
it('应正确执行分页查询', async () => {
|
|
64
|
-
const mockRepository = createMockRepository();
|
|
65
|
-
|
|
66
|
-
const mockEntities: TestEntity[] = [{ id: 1 }, { id: 2 }];
|
|
67
|
-
vi.mocked(mockRepository.findAndCount).mockResolvedValue([mockEntities, 10]);
|
|
68
|
-
|
|
69
|
-
const result = await paginateWithRepository(mockRepository, { page: 1, pageSize: 10 });
|
|
70
|
-
|
|
71
|
-
expect(result).toEqual({
|
|
72
|
-
items: mockEntities,
|
|
73
|
-
total: 10,
|
|
74
|
-
page: 1,
|
|
75
|
-
pageSize: 10,
|
|
76
|
-
totalPages: 1,
|
|
77
|
-
hasNextPage: false,
|
|
78
|
-
hasPreviousPage: false,
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('应正确使用自定义映射函数', async () => {
|
|
83
|
-
const mockRepository = createMockRepository();
|
|
84
|
-
|
|
85
|
-
const mockEntities: TestEntity[] = [{ id: 1 }, { id: 2 }];
|
|
86
|
-
vi.mocked(mockRepository.findAndCount).mockResolvedValue([mockEntities, 10]);
|
|
87
|
-
|
|
88
|
-
const mapper = (entity: TestEntity): MappedDto => ({ mapped: entity });
|
|
89
|
-
const result = await paginateWithRepository(
|
|
90
|
-
mockRepository,
|
|
91
|
-
{ page: 1, pageSize: 10 },
|
|
92
|
-
{
|
|
93
|
-
mapper,
|
|
94
|
-
},
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
expect(result.items).toEqual([{ mapped: { id: 1 } }, { mapped: { id: 2 } }]);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('应正确处理分页参数', async () => {
|
|
101
|
-
const mockRepository = createMockRepository();
|
|
102
|
-
|
|
103
|
-
const mockEntities: TestEntity[] = [{ id: 1 }];
|
|
104
|
-
vi.mocked(mockRepository.findAndCount).mockResolvedValue([mockEntities, 100]);
|
|
105
|
-
|
|
106
|
-
const result = await paginateWithRepository(mockRepository, { page: 2, pageSize: 20 });
|
|
107
|
-
|
|
108
|
-
expect(result.page).toBe(2);
|
|
109
|
-
expect(result.pageSize).toBe(20);
|
|
110
|
-
expect(result.totalPages).toBe(5);
|
|
111
|
-
expect(result.hasNextPage).toBe(true);
|
|
112
|
-
expect(result.hasPreviousPage).toBe(true);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it('应正确使用查询选项', async () => {
|
|
116
|
-
const mockRepository = createMockRepository();
|
|
117
|
-
|
|
118
|
-
const mockEntities: TestEntity[] = [{ id: 1 }];
|
|
119
|
-
vi.mocked(mockRepository.findAndCount).mockResolvedValue([mockEntities, 10]);
|
|
120
|
-
|
|
121
|
-
const options = {
|
|
122
|
-
where: { status: 'active' },
|
|
123
|
-
order: { createdAt: 'DESC' } as FindOptionsOrder<TestEntity>,
|
|
124
|
-
relations: ['user'],
|
|
125
|
-
select: ['id', 'name'],
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
await paginateWithRepository(mockRepository, { page: 1, pageSize: 10 }, options);
|
|
129
|
-
|
|
130
|
-
expect(mockRepository.findAndCount).toHaveBeenCalledWith(
|
|
131
|
-
expect.objectContaining({
|
|
132
|
-
skip: 0,
|
|
133
|
-
take: 10,
|
|
134
|
-
where: options.where,
|
|
135
|
-
order: options.order,
|
|
136
|
-
relations: options.relations,
|
|
137
|
-
select: options.select,
|
|
138
|
-
}),
|
|
139
|
-
);
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
describe('paginateWithQueryBuilder', () => {
|
|
144
|
-
it('应正确执行分页查询', async () => {
|
|
145
|
-
const mockQueryBuilder = createMockQueryBuilder();
|
|
146
|
-
|
|
147
|
-
const mockEntities: TestEntity[] = [{ id: 1 }, { id: 2 }];
|
|
148
|
-
vi.mocked(mockQueryBuilder.getManyAndCount).mockResolvedValue([mockEntities, 10]);
|
|
149
|
-
|
|
150
|
-
const result = await paginateWithQueryBuilder(mockQueryBuilder, { page: 1, pageSize: 10 });
|
|
151
|
-
|
|
152
|
-
expect(result).toEqual({
|
|
153
|
-
items: mockEntities,
|
|
154
|
-
total: 10,
|
|
155
|
-
page: 1,
|
|
156
|
-
pageSize: 10,
|
|
157
|
-
totalPages: 1,
|
|
158
|
-
hasNextPage: false,
|
|
159
|
-
hasPreviousPage: false,
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('应正确使用自定义映射函数', async () => {
|
|
164
|
-
const mockQueryBuilder = createMockQueryBuilder();
|
|
165
|
-
|
|
166
|
-
const mockEntities: TestEntity[] = [{ id: 1 }, { id: 2 }];
|
|
167
|
-
vi.mocked(mockQueryBuilder.getManyAndCount).mockResolvedValue([mockEntities, 10]);
|
|
168
|
-
|
|
169
|
-
const mapper = (entity: TestEntity): MappedDto => ({ mapped: entity });
|
|
170
|
-
const result = await paginateWithQueryBuilder(
|
|
171
|
-
mockQueryBuilder,
|
|
172
|
-
{ page: 1, pageSize: 10 },
|
|
173
|
-
mapper,
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
expect(result.items).toEqual([{ mapped: { id: 1 } }, { mapped: { id: 2 } }]);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it('应正确设置 skip 和 take', async () => {
|
|
180
|
-
const mockQueryBuilder = createMockQueryBuilder();
|
|
181
|
-
|
|
182
|
-
vi.mocked(mockQueryBuilder.getManyAndCount).mockResolvedValue([[], 0]);
|
|
183
|
-
|
|
184
|
-
await paginateWithQueryBuilder(mockQueryBuilder, { page: 2, pageSize: 20 });
|
|
185
|
-
|
|
186
|
-
expect(mockQueryBuilder.skip).toHaveBeenCalledWith(20);
|
|
187
|
-
expect(mockQueryBuilder.take).toHaveBeenCalledWith(20);
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
describe('createPaginationQueryBuilder', () => {
|
|
192
|
-
it('应正确创建 QueryBuilder', () => {
|
|
193
|
-
const mockQueryBuilder = createMockQueryBuilder();
|
|
194
|
-
|
|
195
|
-
const mockRepository = createMockRepository();
|
|
196
|
-
vi.mocked(mockRepository.createQueryBuilder).mockReturnValue(mockQueryBuilder);
|
|
197
|
-
|
|
198
|
-
const result = createPaginationQueryBuilder(mockRepository);
|
|
199
|
-
|
|
200
|
-
expect(result).toBe(mockQueryBuilder);
|
|
201
|
-
expect(mockRepository.createQueryBuilder).toHaveBeenCalled();
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it('应使用自定义别名', () => {
|
|
205
|
-
const mockQueryBuilder = createMockQueryBuilder();
|
|
206
|
-
|
|
207
|
-
const mockRepository = createMockRepository();
|
|
208
|
-
vi.mocked(mockRepository.createQueryBuilder).mockReturnValue(mockQueryBuilder);
|
|
209
|
-
|
|
210
|
-
createPaginationQueryBuilder(mockRepository, 'custom_alias');
|
|
211
|
-
|
|
212
|
-
expect(mockRepository.createQueryBuilder).toHaveBeenCalledWith('custom_alias');
|
|
213
|
-
});
|
|
214
|
-
});
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file validation.util.test.ts
|
|
3
|
-
* 分页参数验证工具函数测试
|
|
4
|
-
* @author Longzai Intelligence
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect } from 'vitest';
|
|
8
|
-
import {
|
|
9
|
-
isValidPage,
|
|
10
|
-
isValidPageSize,
|
|
11
|
-
isValidOffset,
|
|
12
|
-
isValidLimit,
|
|
13
|
-
isValidPagination,
|
|
14
|
-
isValidOffsetPagination,
|
|
15
|
-
} from '@/utils/validation.util';
|
|
16
|
-
import { PAGINATION_DEFAULTS } from '@/types';
|
|
17
|
-
|
|
18
|
-
describe('isValidPage', () => {
|
|
19
|
-
it('应返回 true 对于有效的页码', () => {
|
|
20
|
-
expect(isValidPage(1)).toBe(true);
|
|
21
|
-
expect(isValidPage(10)).toBe(true);
|
|
22
|
-
expect(isValidPage(1000)).toBe(true);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('应返回 false 对于无效的页码', () => {
|
|
26
|
-
expect(isValidPage(0)).toBe(false);
|
|
27
|
-
expect(isValidPage(-1)).toBe(false);
|
|
28
|
-
expect(isValidPage(1.5)).toBe(false);
|
|
29
|
-
expect(isValidPage('1')).toBe(false);
|
|
30
|
-
expect(isValidPage(null)).toBe(false);
|
|
31
|
-
expect(isValidPage(undefined)).toBe(false);
|
|
32
|
-
expect(isValidPage(NaN)).toBe(false);
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
describe('isValidPageSize', () => {
|
|
37
|
-
it('应返回 true 对于有效的页面大小', () => {
|
|
38
|
-
expect(isValidPageSize(1)).toBe(true);
|
|
39
|
-
expect(isValidPageSize(20)).toBe(true);
|
|
40
|
-
expect(isValidPageSize(PAGINATION_DEFAULTS.maxPageSize)).toBe(true);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('应返回 false 对于无效的页面大小', () => {
|
|
44
|
-
expect(isValidPageSize(0)).toBe(false);
|
|
45
|
-
expect(isValidPageSize(-1)).toBe(false);
|
|
46
|
-
expect(isValidPageSize(PAGINATION_DEFAULTS.maxPageSize + 1)).toBe(false);
|
|
47
|
-
expect(isValidPageSize(1.5)).toBe(false);
|
|
48
|
-
expect(isValidPageSize('20')).toBe(false);
|
|
49
|
-
expect(isValidPageSize(null)).toBe(false);
|
|
50
|
-
expect(isValidPageSize(undefined)).toBe(false);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
describe('isValidOffset', () => {
|
|
55
|
-
it('应返回 true 对于有效的偏移量', () => {
|
|
56
|
-
expect(isValidOffset(0)).toBe(true);
|
|
57
|
-
expect(isValidOffset(10)).toBe(true);
|
|
58
|
-
expect(isValidOffset(1000)).toBe(true);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('应返回 false 对于无效的偏移量', () => {
|
|
62
|
-
expect(isValidOffset(-1)).toBe(false);
|
|
63
|
-
expect(isValidOffset(1.5)).toBe(false);
|
|
64
|
-
expect(isValidOffset('10')).toBe(false);
|
|
65
|
-
expect(isValidOffset(null)).toBe(false);
|
|
66
|
-
expect(isValidOffset(undefined)).toBe(false);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('isValidLimit', () => {
|
|
71
|
-
it('应返回 true 对于有效的限制数量', () => {
|
|
72
|
-
expect(isValidLimit(1)).toBe(true);
|
|
73
|
-
expect(isValidLimit(20)).toBe(true);
|
|
74
|
-
expect(isValidLimit(PAGINATION_DEFAULTS.maxPageSize)).toBe(true);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('应返回 false 对于无效的限制数量', () => {
|
|
78
|
-
expect(isValidLimit(0)).toBe(false);
|
|
79
|
-
expect(isValidLimit(-1)).toBe(false);
|
|
80
|
-
expect(isValidLimit(PAGINATION_DEFAULTS.maxPageSize + 1)).toBe(false);
|
|
81
|
-
expect(isValidLimit(1.5)).toBe(false);
|
|
82
|
-
expect(isValidLimit('20')).toBe(false);
|
|
83
|
-
expect(isValidLimit(null)).toBe(false);
|
|
84
|
-
expect(isValidLimit(undefined)).toBe(false);
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
describe('isValidPagination', () => {
|
|
89
|
-
it('应返回 true 对于有效的分页参数', () => {
|
|
90
|
-
expect(isValidPagination({ page: 1, pageSize: 20 })).toBe(true);
|
|
91
|
-
expect(isValidPagination({ page: 5 })).toBe(true);
|
|
92
|
-
expect(isValidPagination({ pageSize: 50 })).toBe(true);
|
|
93
|
-
expect(isValidPagination({})).toBe(true);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('应返回 false 对于无效的分页参数', () => {
|
|
97
|
-
expect(isValidPagination(null)).toBe(false);
|
|
98
|
-
expect(isValidPagination('string')).toBe(false);
|
|
99
|
-
expect(isValidPagination(123)).toBe(false);
|
|
100
|
-
expect(isValidPagination({ page: -1 })).toBe(false);
|
|
101
|
-
expect(isValidPagination({ pageSize: 0 })).toBe(false);
|
|
102
|
-
expect(isValidPagination({ page: 1.5 })).toBe(false);
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
describe('isValidOffsetPagination', () => {
|
|
107
|
-
it('应返回 true 对于有效的 offset 分页参数', () => {
|
|
108
|
-
expect(isValidOffsetPagination({ limit: 20, offset: 0 })).toBe(true);
|
|
109
|
-
expect(isValidOffsetPagination({ limit: 50 })).toBe(true);
|
|
110
|
-
expect(isValidOffsetPagination({ offset: 100 })).toBe(true);
|
|
111
|
-
expect(isValidOffsetPagination({})).toBe(true);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('应返回 false 对于无效的 offset 分页参数', () => {
|
|
115
|
-
expect(isValidOffsetPagination(null)).toBe(false);
|
|
116
|
-
expect(isValidOffsetPagination('string')).toBe(false);
|
|
117
|
-
expect(isValidOffsetPagination(123)).toBe(false);
|
|
118
|
-
expect(isValidOffsetPagination({ offset: -1 })).toBe(false);
|
|
119
|
-
expect(isValidOffsetPagination({ limit: 0 })).toBe(false);
|
|
120
|
-
expect(isValidOffsetPagination({ limit: 1.5 })).toBe(false);
|
|
121
|
-
});
|
|
122
|
-
});
|
package/src/adapters/index.ts
DELETED