@mandujs/core 0.17.0 → 0.18.1
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/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/paths.ts +16 -0
- package/src/resource/__tests__/backward-compat.test.ts +302 -0
- package/src/resource/__tests__/edge-cases.test.ts +514 -0
- package/src/resource/__tests__/fixtures.ts +203 -0
- package/src/resource/__tests__/generator.test.ts +324 -0
- package/src/resource/__tests__/performance.test.ts +311 -0
- package/src/resource/__tests__/schema.test.ts +184 -0
- package/src/resource/generator.ts +277 -0
- package/src/resource/generators/client.ts +199 -0
- package/src/resource/generators/contract.ts +264 -0
- package/src/resource/generators/slot.ts +193 -0
- package/src/resource/generators/types.ts +83 -0
- package/src/resource/index.ts +42 -0
- package/src/resource/parser.ts +139 -0
- package/src/resource/schema.ts +252 -0
- package/src/router/fs-scanner.ts +21 -6
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource Edge Cases & Robustness Tests
|
|
3
|
+
*
|
|
4
|
+
* QA Engineer: Additional edge case coverage for resource architecture
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, test, expect } from "bun:test";
|
|
8
|
+
import {
|
|
9
|
+
defineResource,
|
|
10
|
+
validateResourceDefinition,
|
|
11
|
+
FieldTypes,
|
|
12
|
+
type ResourceDefinition,
|
|
13
|
+
} from "../schema";
|
|
14
|
+
|
|
15
|
+
describe("Edge Cases - Resource Names", () => {
|
|
16
|
+
test("should handle single character names", () => {
|
|
17
|
+
const definition: ResourceDefinition = {
|
|
18
|
+
name: "a",
|
|
19
|
+
fields: {
|
|
20
|
+
id: { type: "uuid", required: true },
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("should reject empty string name", () => {
|
|
28
|
+
const definition = {
|
|
29
|
+
name: "",
|
|
30
|
+
fields: {
|
|
31
|
+
id: { type: "uuid", required: true },
|
|
32
|
+
},
|
|
33
|
+
} as any;
|
|
34
|
+
|
|
35
|
+
expect(() => validateResourceDefinition(definition)).toThrow(/Resource name is required/);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("should reject names with spaces", () => {
|
|
39
|
+
const definition = {
|
|
40
|
+
name: "user profile",
|
|
41
|
+
fields: {
|
|
42
|
+
id: { type: "uuid", required: true },
|
|
43
|
+
},
|
|
44
|
+
} as any;
|
|
45
|
+
|
|
46
|
+
expect(() => validateResourceDefinition(definition)).toThrow(/Invalid resource name/);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("should reject names with special characters", () => {
|
|
50
|
+
const definition = {
|
|
51
|
+
name: "user@profile",
|
|
52
|
+
fields: {
|
|
53
|
+
id: { type: "uuid", required: true },
|
|
54
|
+
},
|
|
55
|
+
} as any;
|
|
56
|
+
|
|
57
|
+
expect(() => validateResourceDefinition(definition)).toThrow(/Invalid resource name/);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("should reject names starting with numbers", () => {
|
|
61
|
+
const definition = {
|
|
62
|
+
name: "1user",
|
|
63
|
+
fields: {
|
|
64
|
+
id: { type: "uuid", required: true },
|
|
65
|
+
},
|
|
66
|
+
} as any;
|
|
67
|
+
|
|
68
|
+
expect(() => validateResourceDefinition(definition)).toThrow(/Invalid resource name/);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("should accept names with underscores", () => {
|
|
72
|
+
const definition: ResourceDefinition = {
|
|
73
|
+
name: "user_profile",
|
|
74
|
+
fields: {
|
|
75
|
+
id: { type: "uuid", required: true },
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("should accept names with numbers (not starting)", () => {
|
|
83
|
+
const definition: ResourceDefinition = {
|
|
84
|
+
name: "user2",
|
|
85
|
+
fields: {
|
|
86
|
+
id: { type: "uuid", required: true },
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("should accept camelCase names", () => {
|
|
94
|
+
const definition: ResourceDefinition = {
|
|
95
|
+
name: "userProfile",
|
|
96
|
+
fields: {
|
|
97
|
+
id: { type: "uuid", required: true },
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe("Edge Cases - Field Names", () => {
|
|
106
|
+
test("should handle very long field names", () => {
|
|
107
|
+
const longName = "a".repeat(100);
|
|
108
|
+
const definition: ResourceDefinition = {
|
|
109
|
+
name: "test",
|
|
110
|
+
fields: {
|
|
111
|
+
[longName]: { type: "string", required: true },
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("should reject field names starting with underscore", () => {
|
|
119
|
+
const definition = {
|
|
120
|
+
name: "test",
|
|
121
|
+
fields: {
|
|
122
|
+
_privateField: { type: "string", required: true },
|
|
123
|
+
},
|
|
124
|
+
} as any;
|
|
125
|
+
|
|
126
|
+
// Field names must start with a letter (not underscore)
|
|
127
|
+
expect(() => validateResourceDefinition(definition)).toThrow(/Invalid field name/);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("should reject field names starting with numbers", () => {
|
|
131
|
+
const definition = {
|
|
132
|
+
name: "test",
|
|
133
|
+
fields: {
|
|
134
|
+
"1field": { type: "string", required: true },
|
|
135
|
+
},
|
|
136
|
+
} as any;
|
|
137
|
+
|
|
138
|
+
expect(() => validateResourceDefinition(definition)).toThrow(/Invalid field name/);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test("should handle field names with underscores (not starting)", () => {
|
|
142
|
+
const definition: ResourceDefinition = {
|
|
143
|
+
name: "test",
|
|
144
|
+
fields: {
|
|
145
|
+
field_name_1: { type: "string", required: true },
|
|
146
|
+
field123: { type: "boolean", required: false },
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test("should handle camelCase field names", () => {
|
|
154
|
+
const definition: ResourceDefinition = {
|
|
155
|
+
name: "test",
|
|
156
|
+
fields: {
|
|
157
|
+
firstName: { type: "string", required: true },
|
|
158
|
+
lastName: { type: "string", required: true },
|
|
159
|
+
emailAddress: { type: "email", required: true },
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe("Edge Cases - Field Types", () => {
|
|
168
|
+
test("should handle all supported field types", () => {
|
|
169
|
+
const allTypesDefinition: ResourceDefinition = {
|
|
170
|
+
name: "alltypes",
|
|
171
|
+
fields: {
|
|
172
|
+
stringField: { type: "string", required: true },
|
|
173
|
+
numberField: { type: "number", required: true },
|
|
174
|
+
booleanField: { type: "boolean", required: true },
|
|
175
|
+
dateField: { type: "date", required: true },
|
|
176
|
+
uuidField: { type: "uuid", required: true },
|
|
177
|
+
emailField: { type: "email", required: true },
|
|
178
|
+
urlField: { type: "url", required: true },
|
|
179
|
+
jsonField: { type: "json", required: true },
|
|
180
|
+
arrayField: { type: "array", items: "string", required: true },
|
|
181
|
+
objectField: { type: "object", required: true },
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
expect(() => validateResourceDefinition(allTypesDefinition)).not.toThrow();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test("should verify FieldTypes constant completeness", () => {
|
|
189
|
+
// Ensure FieldTypes constant matches expected types
|
|
190
|
+
expect(FieldTypes).toContain("string");
|
|
191
|
+
expect(FieldTypes).toContain("number");
|
|
192
|
+
expect(FieldTypes).toContain("boolean");
|
|
193
|
+
expect(FieldTypes).toContain("date");
|
|
194
|
+
expect(FieldTypes).toContain("uuid");
|
|
195
|
+
expect(FieldTypes).toContain("email");
|
|
196
|
+
expect(FieldTypes).toContain("url");
|
|
197
|
+
expect(FieldTypes).toContain("json");
|
|
198
|
+
expect(FieldTypes).toContain("array");
|
|
199
|
+
expect(FieldTypes).toContain("object");
|
|
200
|
+
expect(FieldTypes.length).toBe(10);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test("should reject unsupported field type", () => {
|
|
204
|
+
const definition = {
|
|
205
|
+
name: "test",
|
|
206
|
+
fields: {
|
|
207
|
+
id: { type: "unsupported_type", required: true },
|
|
208
|
+
},
|
|
209
|
+
} as any;
|
|
210
|
+
|
|
211
|
+
expect(() => validateResourceDefinition(definition)).toThrow(/Invalid field type/);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test("should handle nested arrays", () => {
|
|
215
|
+
const definition: ResourceDefinition = {
|
|
216
|
+
name: "test",
|
|
217
|
+
fields: {
|
|
218
|
+
tags: { type: "array", items: "string", required: true },
|
|
219
|
+
numbers: { type: "array", items: "number", required: false },
|
|
220
|
+
objects: { type: "array", items: "object", required: false },
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test("should reject array without items specification", () => {
|
|
228
|
+
const definition = {
|
|
229
|
+
name: "test",
|
|
230
|
+
fields: {
|
|
231
|
+
tags: { type: "array", required: true },
|
|
232
|
+
},
|
|
233
|
+
} as any;
|
|
234
|
+
|
|
235
|
+
expect(() => validateResourceDefinition(definition)).toThrow(/missing "items" property/);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
describe("Edge Cases - Field Defaults", () => {
|
|
240
|
+
test("should handle string defaults", () => {
|
|
241
|
+
const definition: ResourceDefinition = {
|
|
242
|
+
name: "test",
|
|
243
|
+
fields: {
|
|
244
|
+
status: { type: "string", default: "active", required: false },
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
test("should handle number defaults", () => {
|
|
252
|
+
const definition: ResourceDefinition = {
|
|
253
|
+
name: "test",
|
|
254
|
+
fields: {
|
|
255
|
+
count: { type: "number", default: 0, required: false },
|
|
256
|
+
score: { type: "number", default: 100, required: false },
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("should handle boolean defaults", () => {
|
|
264
|
+
const definition: ResourceDefinition = {
|
|
265
|
+
name: "test",
|
|
266
|
+
fields: {
|
|
267
|
+
isActive: { type: "boolean", default: true, required: false },
|
|
268
|
+
isDeleted: { type: "boolean", default: false, required: false },
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
test("should handle array defaults", () => {
|
|
276
|
+
const definition: ResourceDefinition = {
|
|
277
|
+
name: "test",
|
|
278
|
+
fields: {
|
|
279
|
+
tags: { type: "array", items: "string", default: [], required: false },
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
test("should handle object defaults", () => {
|
|
287
|
+
const definition: ResourceDefinition = {
|
|
288
|
+
name: "test",
|
|
289
|
+
fields: {
|
|
290
|
+
metadata: { type: "object", default: {}, required: false },
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
describe("Edge Cases - Resource Options", () => {
|
|
299
|
+
test("should handle empty options", () => {
|
|
300
|
+
const definition: ResourceDefinition = {
|
|
301
|
+
name: "test",
|
|
302
|
+
fields: {
|
|
303
|
+
id: { type: "uuid", required: true },
|
|
304
|
+
},
|
|
305
|
+
options: {},
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test("should handle no options", () => {
|
|
312
|
+
const definition: ResourceDefinition = {
|
|
313
|
+
name: "test",
|
|
314
|
+
fields: {
|
|
315
|
+
id: { type: "uuid", required: true },
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
test("should handle all endpoints disabled", () => {
|
|
323
|
+
const definition: ResourceDefinition = {
|
|
324
|
+
name: "test",
|
|
325
|
+
fields: {
|
|
326
|
+
id: { type: "uuid", required: true },
|
|
327
|
+
},
|
|
328
|
+
options: {
|
|
329
|
+
endpoints: {
|
|
330
|
+
list: false,
|
|
331
|
+
get: false,
|
|
332
|
+
create: false,
|
|
333
|
+
update: false,
|
|
334
|
+
delete: false,
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
test("should handle partial endpoint configuration", () => {
|
|
343
|
+
const definition: ResourceDefinition = {
|
|
344
|
+
name: "test",
|
|
345
|
+
fields: {
|
|
346
|
+
id: { type: "uuid", required: true },
|
|
347
|
+
},
|
|
348
|
+
options: {
|
|
349
|
+
endpoints: {
|
|
350
|
+
list: true,
|
|
351
|
+
get: true,
|
|
352
|
+
// create, update, delete will use defaults
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
test("should handle custom pagination limits", () => {
|
|
361
|
+
const definition: ResourceDefinition = {
|
|
362
|
+
name: "test",
|
|
363
|
+
fields: {
|
|
364
|
+
id: { type: "uuid", required: true },
|
|
365
|
+
},
|
|
366
|
+
options: {
|
|
367
|
+
pagination: {
|
|
368
|
+
defaultLimit: 50,
|
|
369
|
+
maxLimit: 500,
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
test("should handle very long description", () => {
|
|
378
|
+
const definition: ResourceDefinition = {
|
|
379
|
+
name: "test",
|
|
380
|
+
fields: {
|
|
381
|
+
id: { type: "uuid", required: true },
|
|
382
|
+
},
|
|
383
|
+
options: {
|
|
384
|
+
description: "A".repeat(1000),
|
|
385
|
+
},
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test("should handle many tags", () => {
|
|
392
|
+
const definition: ResourceDefinition = {
|
|
393
|
+
name: "test",
|
|
394
|
+
fields: {
|
|
395
|
+
id: { type: "uuid", required: true },
|
|
396
|
+
},
|
|
397
|
+
options: {
|
|
398
|
+
tags: Array.from({ length: 50 }, (_, i) => `tag${i}`),
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
test("should handle auth option", () => {
|
|
406
|
+
const definition: ResourceDefinition = {
|
|
407
|
+
name: "test",
|
|
408
|
+
fields: {
|
|
409
|
+
id: { type: "uuid", required: true },
|
|
410
|
+
},
|
|
411
|
+
options: {
|
|
412
|
+
auth: true,
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
test("should handle custom plural name", () => {
|
|
420
|
+
const definition: ResourceDefinition = {
|
|
421
|
+
name: "person",
|
|
422
|
+
fields: {
|
|
423
|
+
id: { type: "uuid", required: true },
|
|
424
|
+
},
|
|
425
|
+
options: {
|
|
426
|
+
pluralName: "people",
|
|
427
|
+
},
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
describe("Edge Cases - Large Schemas", () => {
|
|
435
|
+
test("should handle resource with many fields (50 fields)", () => {
|
|
436
|
+
const fields: Record<string, any> = {};
|
|
437
|
+
for (let i = 0; i < 50; i++) {
|
|
438
|
+
fields[`field${i}`] = { type: "string", required: i % 2 === 0 };
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const definition: ResourceDefinition = {
|
|
442
|
+
name: "largescale",
|
|
443
|
+
fields,
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
test("should handle resource with minimal fields (1 field)", () => {
|
|
450
|
+
const definition: ResourceDefinition = {
|
|
451
|
+
name: "minimal",
|
|
452
|
+
fields: {
|
|
453
|
+
id: { type: "uuid", required: true },
|
|
454
|
+
},
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
test("should handle resource with mixed field types", () => {
|
|
461
|
+
const definition: ResourceDefinition = {
|
|
462
|
+
name: "mixed",
|
|
463
|
+
fields: {
|
|
464
|
+
id: { type: "uuid", required: true },
|
|
465
|
+
name: { type: "string", required: true },
|
|
466
|
+
age: { type: "number", required: false },
|
|
467
|
+
isActive: { type: "boolean", default: true },
|
|
468
|
+
createdAt: { type: "date", required: true },
|
|
469
|
+
email: { type: "email", required: true },
|
|
470
|
+
website: { type: "url", required: false },
|
|
471
|
+
config: { type: "json", required: false },
|
|
472
|
+
tags: { type: "array", items: "string", default: [] },
|
|
473
|
+
metadata: { type: "object", default: {} },
|
|
474
|
+
},
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
expect(() => validateResourceDefinition(definition)).not.toThrow();
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
describe("Edge Cases - Boundary Conditions", () => {
|
|
482
|
+
test("should reject resource without fields", () => {
|
|
483
|
+
const definition = {
|
|
484
|
+
name: "test",
|
|
485
|
+
fields: {},
|
|
486
|
+
} as any;
|
|
487
|
+
|
|
488
|
+
expect(() => validateResourceDefinition(definition)).toThrow(
|
|
489
|
+
/must have at least one field/
|
|
490
|
+
);
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
test("should reject resource with null fields", () => {
|
|
494
|
+
const definition = {
|
|
495
|
+
name: "test",
|
|
496
|
+
fields: null,
|
|
497
|
+
} as any;
|
|
498
|
+
|
|
499
|
+
expect(() => validateResourceDefinition(definition)).toThrow(
|
|
500
|
+
/must have at least one field/
|
|
501
|
+
);
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
test("should reject resource with undefined fields", () => {
|
|
505
|
+
const definition = {
|
|
506
|
+
name: "test",
|
|
507
|
+
fields: undefined,
|
|
508
|
+
} as any;
|
|
509
|
+
|
|
510
|
+
expect(() => validateResourceDefinition(definition)).toThrow(
|
|
511
|
+
/must have at least one field/
|
|
512
|
+
);
|
|
513
|
+
});
|
|
514
|
+
});
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Fixtures for Resource Tests
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ResourceDefinition } from "../schema";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Simple user resource fixture
|
|
9
|
+
*/
|
|
10
|
+
export const userResourceFixture: ResourceDefinition = {
|
|
11
|
+
name: "user",
|
|
12
|
+
fields: {
|
|
13
|
+
id: {
|
|
14
|
+
type: "uuid",
|
|
15
|
+
required: true,
|
|
16
|
+
description: "User ID",
|
|
17
|
+
},
|
|
18
|
+
email: {
|
|
19
|
+
type: "email",
|
|
20
|
+
required: true,
|
|
21
|
+
description: "User email address",
|
|
22
|
+
},
|
|
23
|
+
name: {
|
|
24
|
+
type: "string",
|
|
25
|
+
required: true,
|
|
26
|
+
description: "User full name",
|
|
27
|
+
},
|
|
28
|
+
age: {
|
|
29
|
+
type: "number",
|
|
30
|
+
required: false,
|
|
31
|
+
description: "User age",
|
|
32
|
+
},
|
|
33
|
+
isActive: {
|
|
34
|
+
type: "boolean",
|
|
35
|
+
required: false,
|
|
36
|
+
default: true,
|
|
37
|
+
description: "Account status",
|
|
38
|
+
},
|
|
39
|
+
createdAt: {
|
|
40
|
+
type: "date",
|
|
41
|
+
required: true,
|
|
42
|
+
description: "Account creation timestamp",
|
|
43
|
+
},
|
|
44
|
+
updatedAt: {
|
|
45
|
+
type: "date",
|
|
46
|
+
required: true,
|
|
47
|
+
description: "Last update timestamp",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
options: {
|
|
51
|
+
description: "User management API",
|
|
52
|
+
tags: ["users", "auth"],
|
|
53
|
+
endpoints: {
|
|
54
|
+
list: true,
|
|
55
|
+
get: true,
|
|
56
|
+
create: true,
|
|
57
|
+
update: true,
|
|
58
|
+
delete: true,
|
|
59
|
+
},
|
|
60
|
+
pagination: {
|
|
61
|
+
defaultLimit: 20,
|
|
62
|
+
maxLimit: 100,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Post resource with array field
|
|
69
|
+
*/
|
|
70
|
+
export const postResourceFixture: ResourceDefinition = {
|
|
71
|
+
name: "post",
|
|
72
|
+
fields: {
|
|
73
|
+
id: {
|
|
74
|
+
type: "uuid",
|
|
75
|
+
required: true,
|
|
76
|
+
},
|
|
77
|
+
title: {
|
|
78
|
+
type: "string",
|
|
79
|
+
required: true,
|
|
80
|
+
},
|
|
81
|
+
content: {
|
|
82
|
+
type: "string",
|
|
83
|
+
required: true,
|
|
84
|
+
},
|
|
85
|
+
tags: {
|
|
86
|
+
type: "array",
|
|
87
|
+
items: "string",
|
|
88
|
+
required: false,
|
|
89
|
+
default: [],
|
|
90
|
+
},
|
|
91
|
+
metadata: {
|
|
92
|
+
type: "json",
|
|
93
|
+
required: false,
|
|
94
|
+
},
|
|
95
|
+
publishedAt: {
|
|
96
|
+
type: "date",
|
|
97
|
+
required: false,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
options: {
|
|
101
|
+
description: "Blog posts API",
|
|
102
|
+
tags: ["posts"],
|
|
103
|
+
autoPlural: true,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Product resource with custom plural
|
|
109
|
+
*/
|
|
110
|
+
export const productResourceFixture: ResourceDefinition = {
|
|
111
|
+
name: "product",
|
|
112
|
+
fields: {
|
|
113
|
+
id: {
|
|
114
|
+
type: "uuid",
|
|
115
|
+
required: true,
|
|
116
|
+
},
|
|
117
|
+
name: {
|
|
118
|
+
type: "string",
|
|
119
|
+
required: true,
|
|
120
|
+
},
|
|
121
|
+
price: {
|
|
122
|
+
type: "number",
|
|
123
|
+
required: true,
|
|
124
|
+
},
|
|
125
|
+
inStock: {
|
|
126
|
+
type: "boolean",
|
|
127
|
+
required: true,
|
|
128
|
+
default: true,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
options: {
|
|
132
|
+
description: "Product catalog API",
|
|
133
|
+
pluralName: "inventory",
|
|
134
|
+
endpoints: {
|
|
135
|
+
list: true,
|
|
136
|
+
get: true,
|
|
137
|
+
create: true,
|
|
138
|
+
update: false,
|
|
139
|
+
delete: false,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Minimal resource fixture
|
|
146
|
+
*/
|
|
147
|
+
export const minimalResourceFixture: ResourceDefinition = {
|
|
148
|
+
name: "item",
|
|
149
|
+
fields: {
|
|
150
|
+
id: {
|
|
151
|
+
type: "uuid",
|
|
152
|
+
required: true,
|
|
153
|
+
},
|
|
154
|
+
name: {
|
|
155
|
+
type: "string",
|
|
156
|
+
required: true,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Invalid resource fixtures for error testing
|
|
163
|
+
*/
|
|
164
|
+
export const invalidResourceFixtures = {
|
|
165
|
+
noName: {
|
|
166
|
+
fields: {
|
|
167
|
+
id: { type: "uuid", required: true },
|
|
168
|
+
},
|
|
169
|
+
} as any,
|
|
170
|
+
|
|
171
|
+
invalidName: {
|
|
172
|
+
name: "123-invalid",
|
|
173
|
+
fields: {
|
|
174
|
+
id: { type: "uuid", required: true },
|
|
175
|
+
},
|
|
176
|
+
} as ResourceDefinition,
|
|
177
|
+
|
|
178
|
+
noFields: {
|
|
179
|
+
name: "valid",
|
|
180
|
+
fields: {},
|
|
181
|
+
} as ResourceDefinition,
|
|
182
|
+
|
|
183
|
+
invalidFieldName: {
|
|
184
|
+
name: "valid",
|
|
185
|
+
fields: {
|
|
186
|
+
"invalid-field": { type: "string", required: true },
|
|
187
|
+
},
|
|
188
|
+
} as ResourceDefinition,
|
|
189
|
+
|
|
190
|
+
invalidFieldType: {
|
|
191
|
+
name: "valid",
|
|
192
|
+
fields: {
|
|
193
|
+
field: { type: "invalid" as any, required: true },
|
|
194
|
+
},
|
|
195
|
+
} as ResourceDefinition,
|
|
196
|
+
|
|
197
|
+
arrayWithoutItems: {
|
|
198
|
+
name: "valid",
|
|
199
|
+
fields: {
|
|
200
|
+
tags: { type: "array", required: true },
|
|
201
|
+
},
|
|
202
|
+
} as ResourceDefinition,
|
|
203
|
+
};
|