@veloxts/cli 0.3.6 → 0.4.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/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/generate.d.ts +17 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +219 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/migrate.d.ts +8 -3
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +17 -123
- package/dist/commands/migrate.js.map +1 -1
- package/dist/generators/base.d.ts +76 -0
- package/dist/generators/base.d.ts.map +1 -0
- package/dist/generators/base.js +271 -0
- package/dist/generators/base.js.map +1 -0
- package/dist/generators/generators/index.d.ts +17 -0
- package/dist/generators/generators/index.d.ts.map +1 -0
- package/dist/generators/generators/index.js +43 -0
- package/dist/generators/generators/index.js.map +1 -0
- package/dist/generators/generators/migration.d.ts +43 -0
- package/dist/generators/generators/migration.d.ts.map +1 -0
- package/dist/generators/generators/migration.js +121 -0
- package/dist/generators/generators/migration.js.map +1 -0
- package/dist/generators/generators/model.d.ts +38 -0
- package/dist/generators/generators/model.d.ts.map +1 -0
- package/dist/generators/generators/model.js +108 -0
- package/dist/generators/generators/model.js.map +1 -0
- package/dist/generators/generators/procedure.d.ts +37 -0
- package/dist/generators/generators/procedure.d.ts.map +1 -0
- package/dist/generators/generators/procedure.js +99 -0
- package/dist/generators/generators/procedure.js.map +1 -0
- package/dist/generators/generators/resource.d.ts +29 -0
- package/dist/generators/generators/resource.d.ts.map +1 -0
- package/dist/generators/generators/resource.js +124 -0
- package/dist/generators/generators/resource.js.map +1 -0
- package/dist/generators/generators/schema.d.ts +28 -0
- package/dist/generators/generators/schema.d.ts.map +1 -0
- package/dist/generators/generators/schema.js +83 -0
- package/dist/generators/generators/schema.js.map +1 -0
- package/dist/generators/generators/test.d.ts +28 -0
- package/dist/generators/generators/test.d.ts.map +1 -0
- package/dist/generators/generators/test.js +96 -0
- package/dist/generators/generators/test.js.map +1 -0
- package/dist/generators/index.d.ts +16 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +16 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/generators/registry.d.ts +97 -0
- package/dist/generators/registry.d.ts.map +1 -0
- package/dist/generators/registry.js +253 -0
- package/dist/generators/registry.js.map +1 -0
- package/dist/generators/templates/migration.d.ts +23 -0
- package/dist/generators/templates/migration.d.ts.map +1 -0
- package/dist/generators/templates/migration.js +389 -0
- package/dist/generators/templates/migration.js.map +1 -0
- package/dist/generators/templates/model.d.ts +37 -0
- package/dist/generators/templates/model.d.ts.map +1 -0
- package/dist/generators/templates/model.js +374 -0
- package/dist/generators/templates/model.js.map +1 -0
- package/dist/generators/templates/procedure.d.ts +25 -0
- package/dist/generators/templates/procedure.d.ts.map +1 -0
- package/dist/generators/templates/procedure.js +274 -0
- package/dist/generators/templates/procedure.js.map +1 -0
- package/dist/generators/templates/resource.d.ts +34 -0
- package/dist/generators/templates/resource.d.ts.map +1 -0
- package/dist/generators/templates/resource.js +550 -0
- package/dist/generators/templates/resource.js.map +1 -0
- package/dist/generators/templates/schema.d.ts +33 -0
- package/dist/generators/templates/schema.d.ts.map +1 -0
- package/dist/generators/templates/schema.js +248 -0
- package/dist/generators/templates/schema.js.map +1 -0
- package/dist/generators/templates/test.d.ts +31 -0
- package/dist/generators/templates/test.d.ts.map +1 -0
- package/dist/generators/templates/test.js +882 -0
- package/dist/generators/templates/test.js.map +1 -0
- package/dist/generators/types.d.ts +211 -0
- package/dist/generators/types.d.ts.map +1 -0
- package/dist/generators/types.js +54 -0
- package/dist/generators/types.js.map +1 -0
- package/dist/generators/utils/filesystem.d.ts +68 -0
- package/dist/generators/utils/filesystem.d.ts.map +1 -0
- package/dist/generators/utils/filesystem.js +217 -0
- package/dist/generators/utils/filesystem.js.map +1 -0
- package/dist/generators/utils/naming.d.ts +122 -0
- package/dist/generators/utils/naming.d.ts.map +1 -0
- package/dist/generators/utils/naming.js +198 -0
- package/dist/generators/utils/naming.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/migrations/commands/fresh.d.ts +11 -0
- package/dist/migrations/commands/fresh.d.ts.map +1 -0
- package/dist/migrations/commands/fresh.js +164 -0
- package/dist/migrations/commands/fresh.js.map +1 -0
- package/dist/migrations/commands/index.d.ts +11 -0
- package/dist/migrations/commands/index.d.ts.map +1 -0
- package/dist/migrations/commands/index.js +11 -0
- package/dist/migrations/commands/index.js.map +1 -0
- package/dist/migrations/commands/reset.d.ts +11 -0
- package/dist/migrations/commands/reset.d.ts.map +1 -0
- package/dist/migrations/commands/reset.js +258 -0
- package/dist/migrations/commands/reset.js.map +1 -0
- package/dist/migrations/commands/rollback.d.ts +11 -0
- package/dist/migrations/commands/rollback.d.ts.map +1 -0
- package/dist/migrations/commands/rollback.js +241 -0
- package/dist/migrations/commands/rollback.js.map +1 -0
- package/dist/migrations/commands/run.d.ts +11 -0
- package/dist/migrations/commands/run.d.ts.map +1 -0
- package/dist/migrations/commands/run.js +183 -0
- package/dist/migrations/commands/run.js.map +1 -0
- package/dist/migrations/commands/status.d.ts +11 -0
- package/dist/migrations/commands/status.d.ts.map +1 -0
- package/dist/migrations/commands/status.js +154 -0
- package/dist/migrations/commands/status.js.map +1 -0
- package/dist/migrations/errors.d.ts +74 -0
- package/dist/migrations/errors.d.ts.map +1 -0
- package/dist/migrations/errors.js +155 -0
- package/dist/migrations/errors.js.map +1 -0
- package/dist/migrations/index.d.ts +13 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +17 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/loader.d.ts +44 -0
- package/dist/migrations/loader.d.ts.map +1 -0
- package/dist/migrations/loader.js +181 -0
- package/dist/migrations/loader.js.map +1 -0
- package/dist/migrations/prisma-wrapper.d.ts +60 -0
- package/dist/migrations/prisma-wrapper.d.ts.map +1 -0
- package/dist/migrations/prisma-wrapper.js +184 -0
- package/dist/migrations/prisma-wrapper.js.map +1 -0
- package/dist/migrations/rollback-runner.d.ts +40 -0
- package/dist/migrations/rollback-runner.d.ts.map +1 -0
- package/dist/migrations/rollback-runner.js +191 -0
- package/dist/migrations/rollback-runner.js.map +1 -0
- package/dist/migrations/types.d.ts +214 -0
- package/dist/migrations/types.d.ts.map +1 -0
- package/dist/migrations/types.js +19 -0
- package/dist/migrations/types.js.map +1 -0
- package/package.json +29 -8
|
@@ -0,0 +1,882 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Template
|
|
3
|
+
*
|
|
4
|
+
* Generates Vitest test files for VeloxTS applications.
|
|
5
|
+
*/
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Template Functions
|
|
8
|
+
// ============================================================================
|
|
9
|
+
/**
|
|
10
|
+
* Generate unit test for procedures
|
|
11
|
+
*/
|
|
12
|
+
function generateProcedureUnitTest(entity) {
|
|
13
|
+
const { pascal, camel, kebab } = entity;
|
|
14
|
+
return `/**
|
|
15
|
+
* ${pascal} Procedures - Unit Tests
|
|
16
|
+
*
|
|
17
|
+
* Tests for ${pascal} procedure handlers.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
21
|
+
// import { ${camel}Procedures } from '../procedures/${kebab}.js';
|
|
22
|
+
|
|
23
|
+
describe('${pascal} Procedures', () => {
|
|
24
|
+
// Mock context
|
|
25
|
+
const mockCtx = {
|
|
26
|
+
db: {
|
|
27
|
+
${camel}: {
|
|
28
|
+
findUnique: vi.fn(),
|
|
29
|
+
findMany: vi.fn(),
|
|
30
|
+
create: vi.fn(),
|
|
31
|
+
update: vi.fn(),
|
|
32
|
+
delete: vi.fn(),
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
vi.clearAllMocks();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('get${pascal}', () => {
|
|
42
|
+
it('should return a ${camel} by id', async () => {
|
|
43
|
+
const mock${pascal} = {
|
|
44
|
+
id: 'test-uuid-1234',
|
|
45
|
+
// TODO: Add expected fields
|
|
46
|
+
createdAt: new Date(),
|
|
47
|
+
updatedAt: new Date(),
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
mockCtx.db.${camel}.findUnique.mockResolvedValue(mock${pascal});
|
|
51
|
+
|
|
52
|
+
// TODO: Call the procedure
|
|
53
|
+
// const result = await ${camel}Procedures.get${pascal}({
|
|
54
|
+
// input: { id: 'test-uuid-1234' },
|
|
55
|
+
// ctx: mockCtx,
|
|
56
|
+
// });
|
|
57
|
+
|
|
58
|
+
// expect(result).toEqual(mock${pascal});
|
|
59
|
+
// expect(mockCtx.db.${camel}.findUnique).toHaveBeenCalledWith({
|
|
60
|
+
// where: { id: 'test-uuid-1234' },
|
|
61
|
+
// });
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should return null for non-existent ${camel}', async () => {
|
|
65
|
+
mockCtx.db.${camel}.findUnique.mockResolvedValue(null);
|
|
66
|
+
|
|
67
|
+
// TODO: Test not found case
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('list${pascal}s', () => {
|
|
72
|
+
it('should return paginated ${camel}s', async () => {
|
|
73
|
+
const mock${pascal}s = [
|
|
74
|
+
{ id: 'uuid-1', createdAt: new Date(), updatedAt: new Date() },
|
|
75
|
+
{ id: 'uuid-2', createdAt: new Date(), updatedAt: new Date() },
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
mockCtx.db.${camel}.findMany.mockResolvedValue(mock${pascal}s);
|
|
79
|
+
|
|
80
|
+
// TODO: Test list procedure
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('create${pascal}', () => {
|
|
85
|
+
it('should create a new ${camel}', async () => {
|
|
86
|
+
const input = {
|
|
87
|
+
// TODO: Add create input fields
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const created${pascal} = {
|
|
91
|
+
id: 'new-uuid',
|
|
92
|
+
...input,
|
|
93
|
+
createdAt: new Date(),
|
|
94
|
+
updatedAt: new Date(),
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
mockCtx.db.${camel}.create.mockResolvedValue(created${pascal});
|
|
98
|
+
|
|
99
|
+
// TODO: Test create procedure
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should validate required fields', async () => {
|
|
103
|
+
// TODO: Test validation errors
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('update${pascal}', () => {
|
|
108
|
+
it('should update an existing ${camel}', async () => {
|
|
109
|
+
const existing${pascal} = {
|
|
110
|
+
id: 'test-uuid',
|
|
111
|
+
createdAt: new Date(),
|
|
112
|
+
updatedAt: new Date(),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
mockCtx.db.${camel}.findUnique.mockResolvedValue(existing${pascal});
|
|
116
|
+
mockCtx.db.${camel}.update.mockResolvedValue({
|
|
117
|
+
...existing${pascal},
|
|
118
|
+
// updated fields
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// TODO: Test update procedure
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
describe('delete${pascal}', () => {
|
|
126
|
+
it('should delete a ${camel}', async () => {
|
|
127
|
+
mockCtx.db.${camel}.delete.mockResolvedValue({ id: 'test-uuid' });
|
|
128
|
+
|
|
129
|
+
// TODO: Test delete procedure
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
`;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Generate unit test for schemas
|
|
137
|
+
*/
|
|
138
|
+
function generateSchemaUnitTest(entity) {
|
|
139
|
+
const { pascal, camel, kebab } = entity;
|
|
140
|
+
return `/**
|
|
141
|
+
* ${pascal} Schema - Unit Tests
|
|
142
|
+
*
|
|
143
|
+
* Tests for ${pascal} Zod validation schemas.
|
|
144
|
+
*/
|
|
145
|
+
|
|
146
|
+
import { describe, it, expect } from 'vitest';
|
|
147
|
+
// import {
|
|
148
|
+
// ${camel}Schema,
|
|
149
|
+
// create${pascal}InputSchema,
|
|
150
|
+
// update${pascal}InputSchema,
|
|
151
|
+
// ${camel}IdParamSchema,
|
|
152
|
+
// } from '../schemas/${kebab}.schema.js';
|
|
153
|
+
|
|
154
|
+
describe('${pascal} Schema', () => {
|
|
155
|
+
describe('${camel}Schema', () => {
|
|
156
|
+
it('should validate a valid ${camel}', () => {
|
|
157
|
+
const valid${pascal} = {
|
|
158
|
+
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
159
|
+
// TODO: Add required fields
|
|
160
|
+
createdAt: new Date(),
|
|
161
|
+
updatedAt: new Date(),
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// const result = ${camel}Schema.safeParse(valid${pascal});
|
|
165
|
+
// expect(result.success).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should reject invalid id format', () => {
|
|
169
|
+
const invalid${pascal} = {
|
|
170
|
+
id: 'not-a-uuid',
|
|
171
|
+
createdAt: new Date(),
|
|
172
|
+
updatedAt: new Date(),
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// const result = ${camel}Schema.safeParse(invalid${pascal});
|
|
176
|
+
// expect(result.success).toBe(false);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should require mandatory fields', () => {
|
|
180
|
+
const incomplete${pascal} = {
|
|
181
|
+
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
182
|
+
// Missing required fields
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// const result = ${camel}Schema.safeParse(incomplete${pascal});
|
|
186
|
+
// expect(result.success).toBe(false);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
describe('create${pascal}InputSchema', () => {
|
|
191
|
+
it('should validate create input', () => {
|
|
192
|
+
const validInput = {
|
|
193
|
+
// TODO: Add create input fields
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// const result = create${pascal}InputSchema.safeParse(validInput);
|
|
197
|
+
// expect(result.success).toBe(true);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('should omit auto-generated fields', () => {
|
|
201
|
+
const inputWithId = {
|
|
202
|
+
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
203
|
+
createdAt: new Date(),
|
|
204
|
+
// other fields
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// The schema should strip id and timestamps
|
|
208
|
+
// const result = create${pascal}InputSchema.safeParse(inputWithId);
|
|
209
|
+
// expect(result.success).toBe(true);
|
|
210
|
+
// expect(result.data).not.toHaveProperty('id');
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
describe('update${pascal}InputSchema', () => {
|
|
215
|
+
it('should validate full update input', () => {
|
|
216
|
+
const validInput = {
|
|
217
|
+
// TODO: Add all updatable fields
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// const result = update${pascal}InputSchema.safeParse(validInput);
|
|
221
|
+
// expect(result.success).toBe(true);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
describe('${camel}IdParamSchema', () => {
|
|
226
|
+
it('should validate valid UUID', () => {
|
|
227
|
+
const validParam = { id: '550e8400-e29b-41d4-a716-446655440000' };
|
|
228
|
+
|
|
229
|
+
// const result = ${camel}IdParamSchema.safeParse(validParam);
|
|
230
|
+
// expect(result.success).toBe(true);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('should reject invalid UUID', () => {
|
|
234
|
+
const invalidParam = { id: 'invalid' };
|
|
235
|
+
|
|
236
|
+
// const result = ${camel}IdParamSchema.safeParse(invalidParam);
|
|
237
|
+
// expect(result.success).toBe(false);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
`;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Generate integration test
|
|
245
|
+
*/
|
|
246
|
+
function generateIntegrationTest(entity) {
|
|
247
|
+
const { pascal, camel } = entity;
|
|
248
|
+
return `/**
|
|
249
|
+
* ${pascal} - Integration Tests
|
|
250
|
+
*
|
|
251
|
+
* Tests ${pascal} procedures with actual database interactions.
|
|
252
|
+
*/
|
|
253
|
+
|
|
254
|
+
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
|
255
|
+
// import { createTestApp, cleanupTestApp } from '../test/setup.js';
|
|
256
|
+
// import type { TestApp } from '../test/setup.js';
|
|
257
|
+
|
|
258
|
+
describe('${pascal} Integration', () => {
|
|
259
|
+
// let app: TestApp;
|
|
260
|
+
|
|
261
|
+
beforeAll(async () => {
|
|
262
|
+
// app = await createTestApp();
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
afterAll(async () => {
|
|
266
|
+
// await cleanupTestApp(app);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
beforeEach(async () => {
|
|
270
|
+
// Clean up test data before each test
|
|
271
|
+
// await app.db.${camel}.deleteMany();
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
describe('CRUD Operations', () => {
|
|
275
|
+
it('should create and retrieve a ${camel}', async () => {
|
|
276
|
+
// const created = await app.procedures.${camel}.create${pascal}({
|
|
277
|
+
// // input fields
|
|
278
|
+
// });
|
|
279
|
+
|
|
280
|
+
// expect(created.id).toBeDefined();
|
|
281
|
+
|
|
282
|
+
// const retrieved = await app.procedures.${camel}.get${pascal}({
|
|
283
|
+
// id: created.id,
|
|
284
|
+
// });
|
|
285
|
+
|
|
286
|
+
// expect(retrieved).toEqual(created);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('should update a ${camel}', async () => {
|
|
290
|
+
// const created = await app.procedures.${camel}.create${pascal}({
|
|
291
|
+
// // input fields
|
|
292
|
+
// });
|
|
293
|
+
|
|
294
|
+
// const updated = await app.procedures.${camel}.update${pascal}({
|
|
295
|
+
// id: created.id,
|
|
296
|
+
// // updated fields
|
|
297
|
+
// });
|
|
298
|
+
|
|
299
|
+
// expect(updated.id).toBe(created.id);
|
|
300
|
+
// expect(updated.updatedAt).not.toBe(created.updatedAt);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('should delete a ${camel}', async () => {
|
|
304
|
+
// const created = await app.procedures.${camel}.create${pascal}({
|
|
305
|
+
// // input fields
|
|
306
|
+
// });
|
|
307
|
+
|
|
308
|
+
// await app.procedures.${camel}.delete${pascal}({
|
|
309
|
+
// id: created.id,
|
|
310
|
+
// });
|
|
311
|
+
|
|
312
|
+
// const deleted = await app.procedures.${camel}.get${pascal}({
|
|
313
|
+
// id: created.id,
|
|
314
|
+
// });
|
|
315
|
+
|
|
316
|
+
// expect(deleted).toBeNull();
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('should list ${camel}s with pagination', async () => {
|
|
320
|
+
// Create multiple ${camel}s
|
|
321
|
+
// for (let i = 0; i < 5; i++) {
|
|
322
|
+
// await app.procedures.${camel}.create${pascal}({
|
|
323
|
+
// // input fields
|
|
324
|
+
// });
|
|
325
|
+
// }
|
|
326
|
+
|
|
327
|
+
// const page1 = await app.procedures.${camel}.list${pascal}s({
|
|
328
|
+
// page: 1,
|
|
329
|
+
// limit: 2,
|
|
330
|
+
// });
|
|
331
|
+
|
|
332
|
+
// expect(page1.data).toHaveLength(2);
|
|
333
|
+
// expect(page1.meta.total).toBe(5);
|
|
334
|
+
// expect(page1.meta.totalPages).toBe(3);
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
describe('Error Handling', () => {
|
|
339
|
+
it('should handle not found errors', async () => {
|
|
340
|
+
// const result = await app.procedures.${camel}.get${pascal}({
|
|
341
|
+
// id: 'non-existent-uuid',
|
|
342
|
+
// });
|
|
343
|
+
|
|
344
|
+
// expect(result).toBeNull();
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('should handle validation errors', async () => {
|
|
348
|
+
// await expect(
|
|
349
|
+
// app.procedures.${camel}.create${pascal}({
|
|
350
|
+
// // invalid input
|
|
351
|
+
// })
|
|
352
|
+
// ).rejects.toThrow();
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
`;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Generate E2E test
|
|
360
|
+
*/
|
|
361
|
+
function generateE2ETest(entity) {
|
|
362
|
+
const { pascal, camel, kebab } = entity;
|
|
363
|
+
return `/**
|
|
364
|
+
* ${pascal} - E2E Tests
|
|
365
|
+
*
|
|
366
|
+
* End-to-end tests for ${pascal} REST API endpoints.
|
|
367
|
+
*/
|
|
368
|
+
|
|
369
|
+
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
|
370
|
+
// import { createTestServer, cleanupTestServer } from '../test/e2e-setup.js';
|
|
371
|
+
// import type { TestServer } from '../test/e2e-setup.js';
|
|
372
|
+
|
|
373
|
+
describe('${pascal} API E2E', () => {
|
|
374
|
+
// let server: TestServer;
|
|
375
|
+
const baseUrl = 'http://localhost:3000/api';
|
|
376
|
+
|
|
377
|
+
beforeAll(async () => {
|
|
378
|
+
// server = await createTestServer();
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
afterAll(async () => {
|
|
382
|
+
// await cleanupTestServer(server);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
beforeEach(async () => {
|
|
386
|
+
// Clean up test data
|
|
387
|
+
// await server.db.${camel}.deleteMany();
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
describe('GET /api/${kebab}s', () => {
|
|
391
|
+
it('should return a list of ${camel}s', async () => {
|
|
392
|
+
// const response = await fetch(\`\${baseUrl}/${kebab}s\`);
|
|
393
|
+
// const data = await response.json();
|
|
394
|
+
|
|
395
|
+
// expect(response.status).toBe(200);
|
|
396
|
+
// expect(data).toHaveProperty('data');
|
|
397
|
+
// expect(data).toHaveProperty('meta');
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it('should support pagination', async () => {
|
|
401
|
+
// const response = await fetch(\`\${baseUrl}/${kebab}s?page=1&limit=10\`);
|
|
402
|
+
// const data = await response.json();
|
|
403
|
+
|
|
404
|
+
// expect(response.status).toBe(200);
|
|
405
|
+
// expect(data.meta.page).toBe(1);
|
|
406
|
+
// expect(data.meta.limit).toBe(10);
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
describe('GET /api/${kebab}s/:id', () => {
|
|
411
|
+
it('should return a single ${camel}', async () => {
|
|
412
|
+
// First create a ${camel}
|
|
413
|
+
// const createResponse = await fetch(\`\${baseUrl}/${kebab}s\`, {
|
|
414
|
+
// method: 'POST',
|
|
415
|
+
// headers: { 'Content-Type': 'application/json' },
|
|
416
|
+
// body: JSON.stringify({ /* fields */ }),
|
|
417
|
+
// });
|
|
418
|
+
// const created = await createResponse.json();
|
|
419
|
+
|
|
420
|
+
// const response = await fetch(\`\${baseUrl}/${kebab}s/\${created.id}\`);
|
|
421
|
+
// const data = await response.json();
|
|
422
|
+
|
|
423
|
+
// expect(response.status).toBe(200);
|
|
424
|
+
// expect(data.id).toBe(created.id);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it('should return 404 for non-existent ${camel}', async () => {
|
|
428
|
+
// const response = await fetch(\`\${baseUrl}/${kebab}s/non-existent-id\`);
|
|
429
|
+
|
|
430
|
+
// expect(response.status).toBe(404);
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
describe('POST /api/${kebab}s', () => {
|
|
435
|
+
it('should create a new ${camel}', async () => {
|
|
436
|
+
// const payload = {
|
|
437
|
+
// // TODO: Add required fields
|
|
438
|
+
// };
|
|
439
|
+
|
|
440
|
+
// const response = await fetch(\`\${baseUrl}/${kebab}s\`, {
|
|
441
|
+
// method: 'POST',
|
|
442
|
+
// headers: { 'Content-Type': 'application/json' },
|
|
443
|
+
// body: JSON.stringify(payload),
|
|
444
|
+
// });
|
|
445
|
+
// const data = await response.json();
|
|
446
|
+
|
|
447
|
+
// expect(response.status).toBe(201);
|
|
448
|
+
// expect(data.id).toBeDefined();
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('should return 400 for invalid input', async () => {
|
|
452
|
+
// const response = await fetch(\`\${baseUrl}/${kebab}s\`, {
|
|
453
|
+
// method: 'POST',
|
|
454
|
+
// headers: { 'Content-Type': 'application/json' },
|
|
455
|
+
// body: JSON.stringify({}),
|
|
456
|
+
// });
|
|
457
|
+
|
|
458
|
+
// expect(response.status).toBe(400);
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
describe('PUT /api/${kebab}s/:id', () => {
|
|
463
|
+
it('should update a ${camel}', async () => {
|
|
464
|
+
// Create first
|
|
465
|
+
// const createResponse = await fetch(\`\${baseUrl}/${kebab}s\`, {
|
|
466
|
+
// method: 'POST',
|
|
467
|
+
// headers: { 'Content-Type': 'application/json' },
|
|
468
|
+
// body: JSON.stringify({ /* fields */ }),
|
|
469
|
+
// });
|
|
470
|
+
// const created = await createResponse.json();
|
|
471
|
+
|
|
472
|
+
// Update
|
|
473
|
+
// const response = await fetch(\`\${baseUrl}/${kebab}s/\${created.id}\`, {
|
|
474
|
+
// method: 'PUT',
|
|
475
|
+
// headers: { 'Content-Type': 'application/json' },
|
|
476
|
+
// body: JSON.stringify({ /* updated fields */ }),
|
|
477
|
+
// });
|
|
478
|
+
// const data = await response.json();
|
|
479
|
+
|
|
480
|
+
// expect(response.status).toBe(200);
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
describe('DELETE /api/${kebab}s/:id', () => {
|
|
485
|
+
it('should delete a ${camel}', async () => {
|
|
486
|
+
// Create first
|
|
487
|
+
// const createResponse = await fetch(\`\${baseUrl}/${kebab}s\`, {
|
|
488
|
+
// method: 'POST',
|
|
489
|
+
// headers: { 'Content-Type': 'application/json' },
|
|
490
|
+
// body: JSON.stringify({ /* fields */ }),
|
|
491
|
+
// });
|
|
492
|
+
// const created = await createResponse.json();
|
|
493
|
+
|
|
494
|
+
// Delete
|
|
495
|
+
// const response = await fetch(\`\${baseUrl}/${kebab}s/\${created.id}\`, {
|
|
496
|
+
// method: 'DELETE',
|
|
497
|
+
// });
|
|
498
|
+
|
|
499
|
+
// expect(response.status).toBe(200);
|
|
500
|
+
|
|
501
|
+
// Verify deleted
|
|
502
|
+
// const getResponse = await fetch(\`\${baseUrl}/${kebab}s/\${created.id}\`);
|
|
503
|
+
// expect(getResponse.status).toBe(404);
|
|
504
|
+
});
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
`;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Generate generic unit test
|
|
511
|
+
*/
|
|
512
|
+
function generateGenericUnitTest(entity) {
|
|
513
|
+
const { pascal, camel, kebab } = entity;
|
|
514
|
+
return `/**
|
|
515
|
+
* ${pascal} - Unit Tests
|
|
516
|
+
*
|
|
517
|
+
* Tests for ${pascal} module.
|
|
518
|
+
*/
|
|
519
|
+
|
|
520
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
521
|
+
// import { ${camel} } from '../${kebab}.js';
|
|
522
|
+
|
|
523
|
+
describe('${pascal}', () => {
|
|
524
|
+
beforeEach(() => {
|
|
525
|
+
vi.clearAllMocks();
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
describe('initialization', () => {
|
|
529
|
+
it('should initialize correctly', () => {
|
|
530
|
+
// TODO: Test initialization
|
|
531
|
+
expect(true).toBe(true);
|
|
532
|
+
});
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
describe('core functionality', () => {
|
|
536
|
+
it('should perform main operation', () => {
|
|
537
|
+
// TODO: Test main functionality
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
it('should handle edge cases', () => {
|
|
541
|
+
// TODO: Test edge cases
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
describe('error handling', () => {
|
|
546
|
+
it('should handle invalid input', () => {
|
|
547
|
+
// TODO: Test error scenarios
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
it('should throw on failure', () => {
|
|
551
|
+
// TODO: Test error throwing
|
|
552
|
+
});
|
|
553
|
+
});
|
|
554
|
+
});
|
|
555
|
+
`;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Generate service unit test
|
|
559
|
+
*/
|
|
560
|
+
function generateServiceUnitTest(entity) {
|
|
561
|
+
const { pascal, camel, kebab } = entity;
|
|
562
|
+
return `/**
|
|
563
|
+
* ${pascal}Service - Unit Tests
|
|
564
|
+
*
|
|
565
|
+
* Tests for ${pascal}Service business logic.
|
|
566
|
+
*/
|
|
567
|
+
|
|
568
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
569
|
+
// import { ${pascal}Service } from '../services/${kebab}.service.js';
|
|
570
|
+
|
|
571
|
+
describe('${pascal}Service', () => {
|
|
572
|
+
// let service: ${pascal}Service;
|
|
573
|
+
// let mockDb: any;
|
|
574
|
+
|
|
575
|
+
beforeEach(() => {
|
|
576
|
+
vi.clearAllMocks();
|
|
577
|
+
|
|
578
|
+
// mockDb = {
|
|
579
|
+
// ${camel}: {
|
|
580
|
+
// findUnique: vi.fn(),
|
|
581
|
+
// findMany: vi.fn(),
|
|
582
|
+
// create: vi.fn(),
|
|
583
|
+
// update: vi.fn(),
|
|
584
|
+
// delete: vi.fn(),
|
|
585
|
+
// },
|
|
586
|
+
// };
|
|
587
|
+
|
|
588
|
+
// service = new ${pascal}Service(mockDb);
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
describe('findById', () => {
|
|
592
|
+
it('should find ${camel} by id', async () => {
|
|
593
|
+
// const mock${pascal} = { id: 'test-id', name: 'Test' };
|
|
594
|
+
// mockDb.${camel}.findUnique.mockResolvedValue(mock${pascal});
|
|
595
|
+
|
|
596
|
+
// const result = await service.findById('test-id');
|
|
597
|
+
|
|
598
|
+
// expect(result).toEqual(mock${pascal});
|
|
599
|
+
// expect(mockDb.${camel}.findUnique).toHaveBeenCalledWith({
|
|
600
|
+
// where: { id: 'test-id' },
|
|
601
|
+
// });
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
it('should return null when not found', async () => {
|
|
605
|
+
// mockDb.${camel}.findUnique.mockResolvedValue(null);
|
|
606
|
+
|
|
607
|
+
// const result = await service.findById('non-existent');
|
|
608
|
+
|
|
609
|
+
// expect(result).toBeNull();
|
|
610
|
+
});
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
describe('create', () => {
|
|
614
|
+
it('should create a new ${camel}', async () => {
|
|
615
|
+
// const input = { name: 'New ${pascal}' };
|
|
616
|
+
// const created = { id: 'new-id', ...input };
|
|
617
|
+
// mockDb.${camel}.create.mockResolvedValue(created);
|
|
618
|
+
|
|
619
|
+
// const result = await service.create(input);
|
|
620
|
+
|
|
621
|
+
// expect(result).toEqual(created);
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it('should validate input before creation', async () => {
|
|
625
|
+
// TODO: Test validation
|
|
626
|
+
});
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
describe('update', () => {
|
|
630
|
+
it('should update an existing ${camel}', async () => {
|
|
631
|
+
// const existing = { id: 'test-id', name: 'Old' };
|
|
632
|
+
// const updated = { ...existing, name: 'New' };
|
|
633
|
+
// mockDb.${camel}.findUnique.mockResolvedValue(existing);
|
|
634
|
+
// mockDb.${camel}.update.mockResolvedValue(updated);
|
|
635
|
+
|
|
636
|
+
// const result = await service.update('test-id', { name: 'New' });
|
|
637
|
+
|
|
638
|
+
// expect(result.name).toBe('New');
|
|
639
|
+
});
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
describe('delete', () => {
|
|
643
|
+
it('should delete a ${camel}', async () => {
|
|
644
|
+
// mockDb.${camel}.delete.mockResolvedValue({ id: 'test-id' });
|
|
645
|
+
|
|
646
|
+
// await service.delete('test-id');
|
|
647
|
+
|
|
648
|
+
// expect(mockDb.${camel}.delete).toHaveBeenCalledWith({
|
|
649
|
+
// where: { id: 'test-id' },
|
|
650
|
+
// });
|
|
651
|
+
});
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
describe('business logic', () => {
|
|
655
|
+
it('should apply business rules', async () => {
|
|
656
|
+
// TODO: Test specific business logic
|
|
657
|
+
});
|
|
658
|
+
});
|
|
659
|
+
});
|
|
660
|
+
`;
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Generate model unit test
|
|
664
|
+
*/
|
|
665
|
+
function generateModelUnitTest(entity) {
|
|
666
|
+
const { pascal, camel, kebab } = entity;
|
|
667
|
+
return `/**
|
|
668
|
+
* ${pascal} Model - Unit Tests
|
|
669
|
+
*
|
|
670
|
+
* Tests for ${pascal} Prisma model operations.
|
|
671
|
+
*/
|
|
672
|
+
|
|
673
|
+
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
|
674
|
+
// import { PrismaClient } from '@prisma/client';
|
|
675
|
+
// import { mockDeep, mockReset, DeepMockProxy } from 'vitest-mock-extended';
|
|
676
|
+
|
|
677
|
+
describe('${pascal} Model', () => {
|
|
678
|
+
// let prisma: DeepMockProxy<PrismaClient>;
|
|
679
|
+
|
|
680
|
+
beforeEach(() => {
|
|
681
|
+
// mockReset(prisma);
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
describe('findUnique', () => {
|
|
685
|
+
it('should find ${camel} by id', async () => {
|
|
686
|
+
// const mock${pascal} = {
|
|
687
|
+
// id: 'test-${kebab}-uuid',
|
|
688
|
+
// createdAt: new Date(),
|
|
689
|
+
// updatedAt: new Date(),
|
|
690
|
+
// };
|
|
691
|
+
|
|
692
|
+
// prisma.${camel}.findUnique.mockResolvedValue(mock${pascal});
|
|
693
|
+
|
|
694
|
+
// const result = await prisma.${camel}.findUnique({
|
|
695
|
+
// where: { id: 'test-uuid' },
|
|
696
|
+
// });
|
|
697
|
+
|
|
698
|
+
// expect(result).toEqual(mock${pascal});
|
|
699
|
+
});
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
describe('findMany', () => {
|
|
703
|
+
it('should find all ${camel}s', async () => {
|
|
704
|
+
// const mock${pascal}s = [
|
|
705
|
+
// { id: 'uuid-1', createdAt: new Date(), updatedAt: new Date() },
|
|
706
|
+
// { id: 'uuid-2', createdAt: new Date(), updatedAt: new Date() },
|
|
707
|
+
// ];
|
|
708
|
+
|
|
709
|
+
// prisma.${camel}.findMany.mockResolvedValue(mock${pascal}s);
|
|
710
|
+
|
|
711
|
+
// const result = await prisma.${camel}.findMany();
|
|
712
|
+
|
|
713
|
+
// expect(result).toHaveLength(2);
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
it('should filter ${camel}s', async () => {
|
|
717
|
+
// prisma.${camel}.findMany.mockResolvedValue([]);
|
|
718
|
+
|
|
719
|
+
// const result = await prisma.${camel}.findMany({
|
|
720
|
+
// where: { /* filter */ },
|
|
721
|
+
// });
|
|
722
|
+
|
|
723
|
+
// expect(result).toEqual([]);
|
|
724
|
+
});
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
describe('create', () => {
|
|
728
|
+
it('should create a ${camel}', async () => {
|
|
729
|
+
// const input = {
|
|
730
|
+
// // TODO: Add fields
|
|
731
|
+
// };
|
|
732
|
+
|
|
733
|
+
// const created = {
|
|
734
|
+
// id: 'new-uuid',
|
|
735
|
+
// ...input,
|
|
736
|
+
// createdAt: new Date(),
|
|
737
|
+
// updatedAt: new Date(),
|
|
738
|
+
// };
|
|
739
|
+
|
|
740
|
+
// prisma.${camel}.create.mockResolvedValue(created);
|
|
741
|
+
|
|
742
|
+
// const result = await prisma.${camel}.create({ data: input });
|
|
743
|
+
|
|
744
|
+
// expect(result.id).toBeDefined();
|
|
745
|
+
});
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
describe('update', () => {
|
|
749
|
+
it('should update a ${camel}', async () => {
|
|
750
|
+
// const updated = {
|
|
751
|
+
// id: 'test-uuid',
|
|
752
|
+
// // updated fields
|
|
753
|
+
// createdAt: new Date(),
|
|
754
|
+
// updatedAt: new Date(),
|
|
755
|
+
// };
|
|
756
|
+
|
|
757
|
+
// prisma.${camel}.update.mockResolvedValue(updated);
|
|
758
|
+
|
|
759
|
+
// const result = await prisma.${camel}.update({
|
|
760
|
+
// where: { id: 'test-uuid' },
|
|
761
|
+
// data: { /* updates */ },
|
|
762
|
+
// });
|
|
763
|
+
|
|
764
|
+
// expect(result).toEqual(updated);
|
|
765
|
+
});
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
describe('delete', () => {
|
|
769
|
+
it('should delete a ${camel}', async () => {
|
|
770
|
+
// const deleted = { id: 'test-uuid' };
|
|
771
|
+
|
|
772
|
+
// prisma.${camel}.delete.mockResolvedValue(deleted);
|
|
773
|
+
|
|
774
|
+
// const result = await prisma.${camel}.delete({
|
|
775
|
+
// where: { id: 'test-uuid' },
|
|
776
|
+
// });
|
|
777
|
+
|
|
778
|
+
// expect(result.id).toBe('test-uuid');
|
|
779
|
+
});
|
|
780
|
+
});
|
|
781
|
+
});
|
|
782
|
+
`;
|
|
783
|
+
}
|
|
784
|
+
// ============================================================================
|
|
785
|
+
// Template Export
|
|
786
|
+
// ============================================================================
|
|
787
|
+
/**
|
|
788
|
+
* Test template function
|
|
789
|
+
*/
|
|
790
|
+
export const testTemplate = (ctx) => {
|
|
791
|
+
const { type, target } = ctx.options;
|
|
792
|
+
// E2E tests
|
|
793
|
+
if (type === 'e2e') {
|
|
794
|
+
return generateE2ETest(ctx.entity);
|
|
795
|
+
}
|
|
796
|
+
// Integration tests
|
|
797
|
+
if (type === 'integration') {
|
|
798
|
+
return generateIntegrationTest(ctx.entity);
|
|
799
|
+
}
|
|
800
|
+
// Unit tests by target
|
|
801
|
+
switch (target) {
|
|
802
|
+
case 'procedure':
|
|
803
|
+
return generateProcedureUnitTest(ctx.entity);
|
|
804
|
+
case 'schema':
|
|
805
|
+
return generateSchemaUnitTest(ctx.entity);
|
|
806
|
+
case 'model':
|
|
807
|
+
return generateModelUnitTest(ctx.entity);
|
|
808
|
+
case 'service':
|
|
809
|
+
return generateServiceUnitTest(ctx.entity);
|
|
810
|
+
default:
|
|
811
|
+
return generateGenericUnitTest(ctx.entity);
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
/**
|
|
815
|
+
* Get an output path for a test file
|
|
816
|
+
*/
|
|
817
|
+
export function getTestPath(entity, options) {
|
|
818
|
+
const { type, target } = options;
|
|
819
|
+
const suffix = type === 'e2e' ? 'e2e' : type === 'integration' ? 'integration' : 'test';
|
|
820
|
+
// Determine directory based on test type
|
|
821
|
+
if (type === 'e2e') {
|
|
822
|
+
return `tests/e2e/${entity.kebab}.${suffix}.ts`;
|
|
823
|
+
}
|
|
824
|
+
if (type === 'integration') {
|
|
825
|
+
return `tests/integration/${entity.kebab}.${suffix}.ts`;
|
|
826
|
+
}
|
|
827
|
+
// Unit tests go alongside the source or in __tests__
|
|
828
|
+
switch (target) {
|
|
829
|
+
case 'procedure':
|
|
830
|
+
return `src/procedures/__tests__/${entity.kebab}.${suffix}.ts`;
|
|
831
|
+
case 'schema':
|
|
832
|
+
return `src/schemas/__tests__/${entity.kebab}.${suffix}.ts`;
|
|
833
|
+
case 'model':
|
|
834
|
+
return `src/models/__tests__/${entity.kebab}.${suffix}.ts`;
|
|
835
|
+
case 'service':
|
|
836
|
+
return `src/services/__tests__/${entity.kebab}.${suffix}.ts`;
|
|
837
|
+
default:
|
|
838
|
+
return `src/__tests__/${entity.kebab}.${suffix}.ts`;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Generate all files for a test
|
|
843
|
+
*/
|
|
844
|
+
export function generateTestFiles(ctx) {
|
|
845
|
+
const content = testTemplate(ctx);
|
|
846
|
+
return [
|
|
847
|
+
{
|
|
848
|
+
path: getTestPath(ctx.entity, ctx.options),
|
|
849
|
+
content,
|
|
850
|
+
},
|
|
851
|
+
];
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Generate post-generation instructions
|
|
855
|
+
*/
|
|
856
|
+
export function getTestInstructions(entityName, options) {
|
|
857
|
+
const { type } = options;
|
|
858
|
+
const runCommand = type === 'e2e'
|
|
859
|
+
? 'pnpm test:e2e'
|
|
860
|
+
: type === 'integration'
|
|
861
|
+
? 'pnpm test:integration'
|
|
862
|
+
: 'pnpm test';
|
|
863
|
+
return `
|
|
864
|
+
1. Uncomment and customize the test cases in the generated file.
|
|
865
|
+
|
|
866
|
+
2. Run the tests:
|
|
867
|
+
|
|
868
|
+
${runCommand}
|
|
869
|
+
|
|
870
|
+
Or run specific test file:
|
|
871
|
+
pnpm vitest ${getTestPath({ kebab: entityName.toLowerCase() }, options)}
|
|
872
|
+
|
|
873
|
+
3. Test types:
|
|
874
|
+
- Unit tests: Fast, isolated, mock dependencies
|
|
875
|
+
- Integration tests: Test with real database
|
|
876
|
+
- E2E tests: Full HTTP request/response cycle
|
|
877
|
+
|
|
878
|
+
Tip: Start with unit tests, add integration tests for critical paths,
|
|
879
|
+
and E2E tests for user-facing workflows.
|
|
880
|
+
`;
|
|
881
|
+
}
|
|
882
|
+
//# sourceMappingURL=test.js.map
|