specforge-mcp 0.2.2 → 0.4.0
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/engine/skill-generator/sections-skills.d.ts +4 -0
- package/dist/engine/skill-generator/sections-skills.d.ts.map +1 -0
- package/dist/engine/skill-generator/sections-skills.js +51 -0
- package/dist/engine/skill-generator/sections-skills.js.map +1 -0
- package/dist/engine/skill-generator/sections.d.ts +1 -0
- package/dist/engine/skill-generator/sections.d.ts.map +1 -1
- package/dist/engine/skill-generator/sections.js +2 -1
- package/dist/engine/skill-generator/sections.js.map +1 -1
- package/dist/engine/skill-generator.d.ts +3 -1
- package/dist/engine/skill-generator.d.ts.map +1 -1
- package/dist/engine/skill-generator.js +11 -2
- package/dist/engine/skill-generator.js.map +1 -1
- package/dist/engine/test-plan-generator.d.ts +3 -0
- package/dist/engine/test-plan-generator.d.ts.map +1 -0
- package/dist/engine/test-plan-generator.js +166 -0
- package/dist/engine/test-plan-generator.js.map +1 -0
- package/dist/engine/test-spec-generator.d.ts +8 -0
- package/dist/engine/test-spec-generator.d.ts.map +1 -0
- package/dist/engine/test-spec-generator.js +348 -0
- package/dist/engine/test-spec-generator.js.map +1 -0
- package/dist/tools/generate-rules.d.ts.map +1 -1
- package/dist/tools/generate-rules.js +20 -0
- package/dist/tools/generate-rules.js.map +1 -1
- package/dist/tools/generate-tests/generators/database-test-generator.d.ts +11 -0
- package/dist/tools/generate-tests/generators/database-test-generator.d.ts.map +1 -0
- package/dist/tools/generate-tests/generators/database-test-generator.js +329 -0
- package/dist/tools/generate-tests/generators/database-test-generator.js.map +1 -0
- package/dist/tools/generate-tests/generators/graphql-test-generator.d.ts +17 -0
- package/dist/tools/generate-tests/generators/graphql-test-generator.d.ts.map +1 -0
- package/dist/tools/generate-tests/generators/graphql-test-generator.js +235 -0
- package/dist/tools/generate-tests/generators/graphql-test-generator.js.map +1 -0
- package/dist/tools/generate-tests/generators/grpc-test-generator.d.ts +17 -0
- package/dist/tools/generate-tests/generators/grpc-test-generator.d.ts.map +1 -0
- package/dist/tools/generate-tests/generators/grpc-test-generator.js +283 -0
- package/dist/tools/generate-tests/generators/grpc-test-generator.js.map +1 -0
- package/dist/tools/generate-tests/generators/microservices-test-generator.d.ts +10 -0
- package/dist/tools/generate-tests/generators/microservices-test-generator.d.ts.map +1 -0
- package/dist/tools/generate-tests/generators/microservices-test-generator.js +341 -0
- package/dist/tools/generate-tests/generators/microservices-test-generator.js.map +1 -0
- package/dist/tools/generate-tests/generators/security-test-generator.d.ts +11 -0
- package/dist/tools/generate-tests/generators/security-test-generator.d.ts.map +1 -0
- package/dist/tools/generate-tests/generators/security-test-generator.js +318 -0
- package/dist/tools/generate-tests/generators/security-test-generator.js.map +1 -0
- package/dist/tools/generate-tests/generators/visual-regression-generator.d.ts +19 -0
- package/dist/tools/generate-tests/generators/visual-regression-generator.d.ts.map +1 -0
- package/dist/tools/generate-tests/generators/visual-regression-generator.js +304 -0
- package/dist/tools/generate-tests/generators/visual-regression-generator.js.map +1 -0
- package/dist/tools/generate-tests/generators/websocket-test-generator.d.ts +17 -0
- package/dist/tools/generate-tests/generators/websocket-test-generator.d.ts.map +1 -0
- package/dist/tools/generate-tests/generators/websocket-test-generator.js +243 -0
- package/dist/tools/generate-tests/generators/websocket-test-generator.js.map +1 -0
- package/dist/tools/generate-tests/plan-mode-handler.d.ts +3 -0
- package/dist/tools/generate-tests/plan-mode-handler.d.ts.map +1 -0
- package/dist/tools/generate-tests/plan-mode-handler.js +54 -0
- package/dist/tools/generate-tests/plan-mode-handler.js.map +1 -0
- package/dist/tools/generate-tests/spec-dispatcher.d.ts.map +1 -1
- package/dist/tools/generate-tests/spec-dispatcher.js +46 -0
- package/dist/tools/generate-tests/spec-dispatcher.js.map +1 -1
- package/dist/tools/generate-tests/test-helpers.d.ts +8 -0
- package/dist/tools/generate-tests/test-helpers.d.ts.map +1 -0
- package/dist/tools/generate-tests/test-helpers.js +120 -0
- package/dist/tools/generate-tests/test-helpers.js.map +1 -0
- package/dist/tools/generate-tests.d.ts.map +1 -1
- package/dist/tools/generate-tests.js +6 -118
- package/dist/tools/generate-tests.js.map +1 -1
- package/dist/tools/init-project/handler.d.ts.map +1 -1
- package/dist/tools/init-project/handler.js +29 -0
- package/dist/tools/init-project/handler.js.map +1 -1
- package/dist/types/stack/recommend.d.ts +2 -0
- package/dist/types/stack/recommend.d.ts.map +1 -1
- package/dist/types/testing.d.ts +51 -0
- package/dist/types/testing.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/i18n/messages/en.json +333 -0
- package/src/i18n/messages/es.json +333 -0
- package/src/i18n/messages/pt.json +333 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
// tools/generate-tests/generators/database-test-generator.ts — SPEC-058b Section F
|
|
2
|
+
// Generates database & data layer test scaffolds:
|
|
3
|
+
// migrations, repository/DAO CRUD, caching, full-text search.
|
|
4
|
+
const CACHE_SIGNALS = ['redis', 'memcached', 'node-cache', 'caffeine', 'ehcache', 'valkey'];
|
|
5
|
+
const SEARCH_SIGNALS = [
|
|
6
|
+
'elasticsearch',
|
|
7
|
+
'meilisearch',
|
|
8
|
+
'algolia',
|
|
9
|
+
'opensearch',
|
|
10
|
+
'solr',
|
|
11
|
+
'typesense',
|
|
12
|
+
];
|
|
13
|
+
export function detectCaching(knowledge) {
|
|
14
|
+
const stackLower = knowledge.stack.map((s) => s.toLowerCase());
|
|
15
|
+
for (const sig of CACHE_SIGNALS) {
|
|
16
|
+
if (stackLower.some((s) => s.includes(sig))) {
|
|
17
|
+
return sig;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
export function detectSearchEngine(knowledge) {
|
|
23
|
+
const stackLower = knowledge.stack.map((s) => s.toLowerCase());
|
|
24
|
+
for (const sig of SEARCH_SIGNALS) {
|
|
25
|
+
if (stackLower.some((s) => s.includes(sig))) {
|
|
26
|
+
return sig;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
export function hasOrm(knowledge) {
|
|
32
|
+
return knowledge.orm !== null && knowledge.orm !== 'unknown';
|
|
33
|
+
}
|
|
34
|
+
export function isDatabaseTestProject(knowledge) {
|
|
35
|
+
return knowledge.database !== 'unknown';
|
|
36
|
+
}
|
|
37
|
+
export function generateDatabaseTestDefs(title, testDir, _testExt, knowledge) {
|
|
38
|
+
const defs = [
|
|
39
|
+
{
|
|
40
|
+
name: `${title} — migration: schema up/down and rollback safety`,
|
|
41
|
+
type: 'integration',
|
|
42
|
+
file: `${testDir}/database/`,
|
|
43
|
+
description: 'Verify schema migrations run up/down cleanly and preserve data integrity',
|
|
44
|
+
priority: 'critical',
|
|
45
|
+
automatable: true,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: `${title} — repository: CRUD operations on ${knowledge.database}`,
|
|
49
|
+
type: 'integration',
|
|
50
|
+
file: `${testDir}/database/`,
|
|
51
|
+
description: 'Verify create, read, update, delete operations on the data layer',
|
|
52
|
+
priority: 'high',
|
|
53
|
+
automatable: true,
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
if (hasOrm(knowledge)) {
|
|
57
|
+
defs.push({
|
|
58
|
+
name: `${title} — transactions and optimistic locking`,
|
|
59
|
+
type: 'integration',
|
|
60
|
+
file: `${testDir}/database/`,
|
|
61
|
+
description: 'Verify transaction commit/rollback and optimistic locking conflict detection',
|
|
62
|
+
priority: 'high',
|
|
63
|
+
automatable: true,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const cache = detectCaching(knowledge);
|
|
67
|
+
if (cache !== null) {
|
|
68
|
+
defs.push({
|
|
69
|
+
name: `${title} — caching (${cache}): hit/miss, TTL, invalidation`,
|
|
70
|
+
type: 'integration',
|
|
71
|
+
file: `${testDir}/database/`,
|
|
72
|
+
description: 'Verify cache hit/miss behavior, TTL expiration, and invalidation patterns',
|
|
73
|
+
priority: 'high',
|
|
74
|
+
automatable: true,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const search = detectSearchEngine(knowledge);
|
|
78
|
+
if (search !== null) {
|
|
79
|
+
defs.push({
|
|
80
|
+
name: `${title} — full-text search (${search}): indexing and query relevance`,
|
|
81
|
+
type: 'integration',
|
|
82
|
+
file: `${testDir}/database/`,
|
|
83
|
+
description: 'Verify document indexing, query relevance ranking, and fuzzy matching',
|
|
84
|
+
priority: 'medium',
|
|
85
|
+
automatable: true,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return defs;
|
|
89
|
+
}
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Scaffold builders
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
function buildTsDatabaseTest(title, db, orm, cache, search) {
|
|
94
|
+
const cacheSection = cache
|
|
95
|
+
? `
|
|
96
|
+
describe('Caching (${cache})', () => {
|
|
97
|
+
it('returns cached value on cache hit', async () => {
|
|
98
|
+
// await cache.set('user:1', { name: 'Test' }, { ttl: 60 });
|
|
99
|
+
// const result = await cache.get('user:1');
|
|
100
|
+
// expect(result).toMatchObject({ name: 'Test' });
|
|
101
|
+
expect(true).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('returns null on cache miss', async () => {
|
|
105
|
+
expect(true).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('expires entry after TTL', async () => {
|
|
109
|
+
expect(true).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('invalidates cache on data update', async () => {
|
|
113
|
+
expect(true).toBe(true);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
`
|
|
117
|
+
: '';
|
|
118
|
+
const searchSection = search
|
|
119
|
+
? `
|
|
120
|
+
describe('Full-text search (${search})', () => {
|
|
121
|
+
it('indexes document and makes it searchable', async () => {
|
|
122
|
+
// await searchClient.index('products').addDocuments([{ id: 1, name: 'Widget' }]);
|
|
123
|
+
// const results = await searchClient.index('products').search('Widget');
|
|
124
|
+
// expect(results.hits).toHaveLength(1);
|
|
125
|
+
expect(true).toBe(true);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('returns relevant results ranked by score', async () => {
|
|
129
|
+
expect(true).toBe(true);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('supports fuzzy matching for typos', async () => {
|
|
133
|
+
expect(true).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
`
|
|
137
|
+
: '';
|
|
138
|
+
const ormSection = orm
|
|
139
|
+
? `
|
|
140
|
+
describe('Transactions and locking', () => {
|
|
141
|
+
it('commits transaction on success', async () => {
|
|
142
|
+
expect(true).toBe(true);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('rolls back transaction on error', async () => {
|
|
146
|
+
expect(true).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('detects optimistic locking conflict', async () => {
|
|
150
|
+
// Concurrent update with stale version → should throw
|
|
151
|
+
expect(true).toBe(true);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
`
|
|
155
|
+
: '';
|
|
156
|
+
return `// Database & Data Layer tests for: ${title}
|
|
157
|
+
// Generated by SpecForge SDD MCP Server (SPEC-058b)
|
|
158
|
+
import { describe, it, expect } from 'vitest';
|
|
159
|
+
|
|
160
|
+
describe('${title} — Database Tests (${db})', () => {
|
|
161
|
+
describe('Migrations', () => {
|
|
162
|
+
it('schema migration up applies cleanly', async () => {
|
|
163
|
+
// await migrate.up();
|
|
164
|
+
// const tables = await db.query("SELECT name FROM sqlite_master WHERE type='table'");
|
|
165
|
+
// expect(tables).toContainEqual({ name: 'users' });
|
|
166
|
+
expect(true).toBe(true); // Replace with real migration assertion
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('schema migration down reverts cleanly', async () => {
|
|
170
|
+
expect(true).toBe(true);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('data integrity preserved after migration', async () => {
|
|
174
|
+
expect(true).toBe(true);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('rollback does not lose existing data', async () => {
|
|
178
|
+
expect(true).toBe(true);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe('Repository / DAO — CRUD', () => {
|
|
183
|
+
it('creates a record and returns its id', async () => {
|
|
184
|
+
// const user = await repo.create({ name: 'Test', email: 'test@example.com' });
|
|
185
|
+
// expect(user.id).toBeDefined();
|
|
186
|
+
expect(true).toBe(true);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('reads a record by id', async () => {
|
|
190
|
+
expect(true).toBe(true);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('updates a record', async () => {
|
|
194
|
+
expect(true).toBe(true);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('deletes a record', async () => {
|
|
198
|
+
expect(true).toBe(true);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('returns null for non-existent record', async () => {
|
|
202
|
+
expect(true).toBe(true);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
${ormSection}${cacheSection}${searchSection}});
|
|
206
|
+
`;
|
|
207
|
+
}
|
|
208
|
+
function buildPythonDatabaseTest(title, db, orm, cache, search) {
|
|
209
|
+
const cls = title.replace(/[^a-zA-Z0-9]/g, '');
|
|
210
|
+
const ormSection = orm
|
|
211
|
+
? `
|
|
212
|
+
def test_transaction_commits_on_success(self) -> None:
|
|
213
|
+
"""Transaction commits all changes on success."""
|
|
214
|
+
pass
|
|
215
|
+
|
|
216
|
+
def test_transaction_rolls_back_on_error(self) -> None:
|
|
217
|
+
"""Transaction rolls back on exception."""
|
|
218
|
+
pass
|
|
219
|
+
|
|
220
|
+
def test_optimistic_locking_conflict(self) -> None:
|
|
221
|
+
"""Concurrent update with stale version raises conflict."""
|
|
222
|
+
pass
|
|
223
|
+
`
|
|
224
|
+
: '';
|
|
225
|
+
const cacheSection = cache
|
|
226
|
+
? `
|
|
227
|
+
def test_cache_hit_returns_value(self) -> None:
|
|
228
|
+
"""Cache returns stored value on hit."""
|
|
229
|
+
pass
|
|
230
|
+
|
|
231
|
+
def test_cache_miss_returns_none(self) -> None:
|
|
232
|
+
"""Cache returns None on miss."""
|
|
233
|
+
pass
|
|
234
|
+
|
|
235
|
+
def test_cache_ttl_expiration(self) -> None:
|
|
236
|
+
"""Cache entry expires after TTL."""
|
|
237
|
+
pass
|
|
238
|
+
|
|
239
|
+
def test_cache_invalidation_on_update(self) -> None:
|
|
240
|
+
"""Cache is invalidated when underlying data changes."""
|
|
241
|
+
pass
|
|
242
|
+
`
|
|
243
|
+
: '';
|
|
244
|
+
const searchSection = search
|
|
245
|
+
? `
|
|
246
|
+
def test_index_document_searchable(self) -> None:
|
|
247
|
+
"""Indexed document is returned by search query."""
|
|
248
|
+
pass
|
|
249
|
+
|
|
250
|
+
def test_query_relevance_ranking(self) -> None:
|
|
251
|
+
"""Results are ranked by relevance score."""
|
|
252
|
+
pass
|
|
253
|
+
|
|
254
|
+
def test_fuzzy_matching_for_typos(self) -> None:
|
|
255
|
+
"""Fuzzy search finds results despite typos."""
|
|
256
|
+
pass
|
|
257
|
+
`
|
|
258
|
+
: '';
|
|
259
|
+
return `"""Database & Data Layer tests for: ${title}
|
|
260
|
+
Generated by SpecForge SDD MCP Server (SPEC-058b).
|
|
261
|
+
Database: ${db}
|
|
262
|
+
"""
|
|
263
|
+
import pytest
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class Test${cls}Database:
|
|
267
|
+
"""Database test suite for ${title} (${db})."""
|
|
268
|
+
|
|
269
|
+
def test_migration_up_applies_cleanly(self) -> None:
|
|
270
|
+
"""Schema migration up creates expected tables."""
|
|
271
|
+
# TODO: result = alembic.command.upgrade(config, 'head')
|
|
272
|
+
pass
|
|
273
|
+
|
|
274
|
+
def test_migration_down_reverts_cleanly(self) -> None:
|
|
275
|
+
"""Schema migration down removes tables cleanly."""
|
|
276
|
+
pass
|
|
277
|
+
|
|
278
|
+
def test_data_integrity_after_migration(self) -> None:
|
|
279
|
+
"""Existing data is preserved after migration."""
|
|
280
|
+
pass
|
|
281
|
+
|
|
282
|
+
def test_rollback_safety(self) -> None:
|
|
283
|
+
"""Rollback does not lose existing data."""
|
|
284
|
+
pass
|
|
285
|
+
|
|
286
|
+
def test_create_record(self) -> None:
|
|
287
|
+
"""Creates a record and returns its id."""
|
|
288
|
+
# TODO: user = repo.create(name='Test', email='test@example.com')
|
|
289
|
+
# assert user.id is not None
|
|
290
|
+
pass
|
|
291
|
+
|
|
292
|
+
def test_read_record_by_id(self) -> None:
|
|
293
|
+
"""Reads a record by primary key."""
|
|
294
|
+
pass
|
|
295
|
+
|
|
296
|
+
def test_update_record(self) -> None:
|
|
297
|
+
"""Updates a record field."""
|
|
298
|
+
pass
|
|
299
|
+
|
|
300
|
+
def test_delete_record(self) -> None:
|
|
301
|
+
"""Deletes a record."""
|
|
302
|
+
pass
|
|
303
|
+
|
|
304
|
+
def test_read_nonexistent_returns_none(self) -> None:
|
|
305
|
+
"""Reading a non-existent record returns None."""
|
|
306
|
+
pass
|
|
307
|
+
${ormSection}${cacheSection}${searchSection}`;
|
|
308
|
+
}
|
|
309
|
+
export function generateDatabaseTestFiles(spec, testDir, framework, language, testExt, autoGenerate, knowledge) {
|
|
310
|
+
const cache = detectCaching(knowledge);
|
|
311
|
+
const search = detectSearchEngine(knowledge);
|
|
312
|
+
const orm = hasOrm(knowledge);
|
|
313
|
+
const db = knowledge.database;
|
|
314
|
+
const isPython = language === 'python';
|
|
315
|
+
const ext = isPython ? 'py' : testExt;
|
|
316
|
+
const fw = isPython ? 'pytest' : framework;
|
|
317
|
+
const content = isPython
|
|
318
|
+
? buildPythonDatabaseTest(spec.title, db, orm, cache, search)
|
|
319
|
+
: buildTsDatabaseTest(spec.title, db, orm, cache, search);
|
|
320
|
+
return [
|
|
321
|
+
{
|
|
322
|
+
path: `${testDir}/database/${spec.slug}.database.test.${ext}`,
|
|
323
|
+
framework: fw,
|
|
324
|
+
content,
|
|
325
|
+
ready: autoGenerate,
|
|
326
|
+
},
|
|
327
|
+
];
|
|
328
|
+
}
|
|
329
|
+
//# sourceMappingURL=database-test-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-test-generator.js","sourceRoot":"","sources":["../../../../src/tools/generate-tests/generators/database-test-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { TestDefinition, TestFile, ProjectKnowledge } from '../../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Returns true when the project uses GraphQL (Apollo, Urql, Relay, Hasura, etc.).
|
|
4
|
+
*/
|
|
5
|
+
export declare function isGraphqlProject(knowledge: ProjectKnowledge): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Generate GraphQL test definitions covering schema, queries, mutations, and security.
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateGraphqlTestDefs(title: string, testDir: string, _testExt: string): TestDefinition[];
|
|
10
|
+
/**
|
|
11
|
+
* Generate GraphQL test file scaffolds.
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateGraphqlTestFiles(spec: {
|
|
14
|
+
title: string;
|
|
15
|
+
slug: string;
|
|
16
|
+
}, testDir: string, framework: string, language: string, testExt: string, autoGenerate: boolean): TestFile[];
|
|
17
|
+
//# sourceMappingURL=graphql-test-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql-test-generator.d.ts","sourceRoot":"","sources":["../../../../src/tools/generate-tests/generators/graphql-test-generator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAI1F;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAKrE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,cAAc,EAAE,CA2DlB;AAmJD;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACrC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,OAAO,GACpB,QAAQ,EAAE,CAcZ"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// tools/generate-tests/generators/graphql-test-generator.ts — SPEC-058a Section D
|
|
2
|
+
// Generates GraphQL API test scaffolds: schema validation, queries, mutations, security.
|
|
3
|
+
const GRAPHQL_SIGNALS = ['graphql', 'apollo', 'urql', 'relay', 'hasura', '@graphql-codegen'];
|
|
4
|
+
/**
|
|
5
|
+
* Returns true when the project uses GraphQL (Apollo, Urql, Relay, Hasura, etc.).
|
|
6
|
+
*/
|
|
7
|
+
export function isGraphqlProject(knowledge) {
|
|
8
|
+
const stackLower = knowledge.stack.map((s) => s.toLowerCase());
|
|
9
|
+
const hasSignal = GRAPHQL_SIGNALS.some((sig) => stackLower.some((s) => s.includes(sig)));
|
|
10
|
+
const hasContract = knowledge.apiContracts.some((c) => c.type.toLowerCase() === 'graphql');
|
|
11
|
+
return hasSignal || hasContract;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Generate GraphQL test definitions covering schema, queries, mutations, and security.
|
|
15
|
+
*/
|
|
16
|
+
export function generateGraphqlTestDefs(title, testDir, _testExt) {
|
|
17
|
+
return [
|
|
18
|
+
{
|
|
19
|
+
name: `${title} — GraphQL: schema validation passes introspection`,
|
|
20
|
+
type: 'integration',
|
|
21
|
+
file: `${testDir}/graphql/`,
|
|
22
|
+
description: 'Verify the GraphQL schema is valid and all types resolve correctly',
|
|
23
|
+
priority: 'critical',
|
|
24
|
+
automatable: true,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: `${title} — GraphQL: query with variables returns expected data shape`,
|
|
28
|
+
type: 'integration',
|
|
29
|
+
file: `${testDir}/graphql/`,
|
|
30
|
+
description: 'Execute a parameterized query and assert the response matches the schema',
|
|
31
|
+
priority: 'high',
|
|
32
|
+
automatable: true,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: `${title} — GraphQL: mutation creates resource and returns it`,
|
|
36
|
+
type: 'integration',
|
|
37
|
+
file: `${testDir}/graphql/`,
|
|
38
|
+
description: 'Execute a create mutation and verify the returned payload and side-effects',
|
|
39
|
+
priority: 'high',
|
|
40
|
+
automatable: true,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: `${title} — GraphQL: introspection disabled in production`,
|
|
44
|
+
type: 'integration',
|
|
45
|
+
file: `${testDir}/graphql/`,
|
|
46
|
+
description: 'Verify introspection query returns an error when NODE_ENV=production',
|
|
47
|
+
priority: 'critical',
|
|
48
|
+
automatable: true,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: `${title} — GraphQL: N+1 query detection on nested resolvers`,
|
|
52
|
+
type: 'integration',
|
|
53
|
+
file: `${testDir}/graphql/`,
|
|
54
|
+
description: 'Assert that nested list queries do not trigger N+1 database calls',
|
|
55
|
+
priority: 'high',
|
|
56
|
+
automatable: true,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: `${title} — GraphQL: query depth limiting rejects deep queries`,
|
|
60
|
+
type: 'integration',
|
|
61
|
+
file: `${testDir}/graphql/`,
|
|
62
|
+
description: 'Verify that queries exceeding the configured depth limit are rejected',
|
|
63
|
+
priority: 'medium',
|
|
64
|
+
automatable: true,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: `${title} — GraphQL: auth resolver rejects unauthenticated requests`,
|
|
68
|
+
type: 'integration',
|
|
69
|
+
file: `${testDir}/graphql/`,
|
|
70
|
+
description: 'Verify that protected resolvers return UNAUTHENTICATED error without a token',
|
|
71
|
+
priority: 'critical',
|
|
72
|
+
automatable: true,
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Content generators
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
function buildTsGraphqlTest(title) {
|
|
80
|
+
return `// GraphQL API tests for: ${title}
|
|
81
|
+
// Generated by SpecForge SDD MCP Server (SPEC-058a)
|
|
82
|
+
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
83
|
+
// Adjust import path to match your server setup
|
|
84
|
+
// import { createTestServer } from '../helpers/test-server';
|
|
85
|
+
// import { request } from 'graphql-request';
|
|
86
|
+
|
|
87
|
+
describe('${title} — GraphQL API Tests', () => {
|
|
88
|
+
// let server: ReturnType<typeof createTestServer>;
|
|
89
|
+
// let endpoint: string;
|
|
90
|
+
|
|
91
|
+
beforeAll(async () => {
|
|
92
|
+
// server = await createTestServer();
|
|
93
|
+
// endpoint = \`http://localhost:\${server.port}/graphql\`;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
afterAll(async () => {
|
|
97
|
+
// await server.close();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe('Schema validation', () => {
|
|
101
|
+
it('schema passes introspection query', async () => {
|
|
102
|
+
// const result = await request(endpoint, \`{ __schema { types { name } } }\`);
|
|
103
|
+
// expect(result.__schema.types.length).toBeGreaterThan(0);
|
|
104
|
+
expect(true).toBe(true); // Replace with real introspection assertion
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('Query with variables', () => {
|
|
109
|
+
it('returns expected data shape for parameterized query', async () => {
|
|
110
|
+
// const query = \`
|
|
111
|
+
// query GetItem($id: ID!) {
|
|
112
|
+
// item(id: $id) { id name createdAt }
|
|
113
|
+
// }
|
|
114
|
+
// \`;
|
|
115
|
+
// const result = await request(endpoint, query, { id: 'test-id' });
|
|
116
|
+
// expect(result.item).toMatchObject({ id: 'test-id' });
|
|
117
|
+
expect(true).toBe(true); // Replace with real query assertion
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe('Mutation', () => {
|
|
122
|
+
it('creates resource and returns it', async () => {
|
|
123
|
+
// const mutation = \`
|
|
124
|
+
// mutation CreateItem($input: CreateItemInput!) {
|
|
125
|
+
// createItem(input: $input) { id name }
|
|
126
|
+
// }
|
|
127
|
+
// \`;
|
|
128
|
+
// const result = await request(endpoint, mutation, { input: { name: 'Test' } });
|
|
129
|
+
// expect(result.createItem.name).toBe('Test');
|
|
130
|
+
expect(true).toBe(true); // Replace with real mutation assertion
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe('Security', () => {
|
|
135
|
+
it('rejects introspection in production mode', async () => {
|
|
136
|
+
// const originalEnv = process.env['NODE_ENV'];
|
|
137
|
+
// process.env['NODE_ENV'] = 'production';
|
|
138
|
+
// try {
|
|
139
|
+
// await expect(request(endpoint, \`{ __schema { types { name } } }\`)).rejects.toThrow();
|
|
140
|
+
// } finally {
|
|
141
|
+
// process.env['NODE_ENV'] = originalEnv;
|
|
142
|
+
// }
|
|
143
|
+
expect(true).toBe(true); // Replace with production introspection test
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('rejects queries exceeding depth limit', async () => {
|
|
147
|
+
// const deepQuery = \`{ a { b { c { d { e { f { name } } } } } } }\`;
|
|
148
|
+
// await expect(request(endpoint, deepQuery)).rejects.toThrow();
|
|
149
|
+
expect(true).toBe(true); // Replace with depth-limit assertion
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('returns UNAUTHENTICATED error for protected resolver without token', async () => {
|
|
153
|
+
// const result = await request(endpoint, \`{ protectedData { secret } }\`);
|
|
154
|
+
// expect(result.errors?.[0]?.extensions?.code).toBe('UNAUTHENTICATED');
|
|
155
|
+
expect(true).toBe(true); // Replace with auth assertion
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
`;
|
|
160
|
+
}
|
|
161
|
+
function buildPythonGraphqlTest(title) {
|
|
162
|
+
const cls = title.replace(/\s+/g, '');
|
|
163
|
+
return `"""GraphQL API tests for: ${title}
|
|
164
|
+
Generated by SpecForge SDD MCP Server (SPEC-058a).
|
|
165
|
+
Supports strawberry-graphql and graphene.
|
|
166
|
+
"""
|
|
167
|
+
import pytest
|
|
168
|
+
# from strawberry.test import Client # strawberry
|
|
169
|
+
# from graphene_django.utils.testing import GraphQLTestCase # graphene-django
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class Test${cls}GraphQL:
|
|
173
|
+
"""GraphQL API test suite for ${title}."""
|
|
174
|
+
|
|
175
|
+
def test_schema_passes_introspection(self) -> None:
|
|
176
|
+
"""Schema is valid and all types are resolvable via introspection."""
|
|
177
|
+
# TODO: client = Client(schema)
|
|
178
|
+
# result = client.execute("{ __schema { types { name } } }")
|
|
179
|
+
# assert "errors" not in result
|
|
180
|
+
pass
|
|
181
|
+
|
|
182
|
+
def test_query_with_variables_returns_expected_shape(self) -> None:
|
|
183
|
+
"""Parameterized query returns correct data shape."""
|
|
184
|
+
# TODO: result = client.execute(
|
|
185
|
+
# "query GetItem($id: ID!) { item(id: $id) { id name } }",
|
|
186
|
+
# variable_values={"id": "test-id"}
|
|
187
|
+
# )
|
|
188
|
+
# assert result["data"]["item"]["id"] == "test-id"
|
|
189
|
+
pass
|
|
190
|
+
|
|
191
|
+
def test_mutation_creates_resource(self) -> None:
|
|
192
|
+
"""Create mutation returns the newly created resource."""
|
|
193
|
+
# TODO: result = client.execute(
|
|
194
|
+
# 'mutation { createItem(name: "Test") { id name } }'
|
|
195
|
+
# )
|
|
196
|
+
# assert result["data"]["createItem"]["name"] == "Test"
|
|
197
|
+
pass
|
|
198
|
+
|
|
199
|
+
def test_introspection_disabled_in_production(self) -> None:
|
|
200
|
+
"""Introspection returns an error when running in production mode."""
|
|
201
|
+
# TODO: assert introspection_disabled_for_production()
|
|
202
|
+
pass
|
|
203
|
+
|
|
204
|
+
def test_deep_query_rejected_by_depth_limiter(self) -> None:
|
|
205
|
+
"""Queries exceeding the depth limit are rejected with an error."""
|
|
206
|
+
# TODO: deep_query = "{ a { b { c { d { e { f { name } } } } } } }"
|
|
207
|
+
# result = client.execute(deep_query)
|
|
208
|
+
# assert "errors" in result
|
|
209
|
+
pass
|
|
210
|
+
|
|
211
|
+
def test_protected_resolver_requires_auth(self) -> None:
|
|
212
|
+
"""Protected resolver returns UNAUTHENTICATED error without token."""
|
|
213
|
+
# TODO: result = unauthenticated_client.execute("{ protectedData { secret } }")
|
|
214
|
+
# assert result["errors"][0]["extensions"]["code"] == "UNAUTHENTICATED"
|
|
215
|
+
pass
|
|
216
|
+
`;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Generate GraphQL test file scaffolds.
|
|
220
|
+
*/
|
|
221
|
+
export function generateGraphqlTestFiles(spec, testDir, framework, language, testExt, autoGenerate) {
|
|
222
|
+
const isPython = language === 'python';
|
|
223
|
+
const resolvedExt = isPython ? 'py' : testExt;
|
|
224
|
+
const resolvedFramework = isPython ? 'pytest' : framework;
|
|
225
|
+
const content = isPython ? buildPythonGraphqlTest(spec.title) : buildTsGraphqlTest(spec.title);
|
|
226
|
+
return [
|
|
227
|
+
{
|
|
228
|
+
path: `${testDir}/graphql/${spec.slug}.graphql.test.${resolvedExt}`,
|
|
229
|
+
framework: resolvedFramework,
|
|
230
|
+
content,
|
|
231
|
+
ready: autoGenerate,
|
|
232
|
+
},
|
|
233
|
+
];
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=graphql-test-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql-test-generator.js","sourceRoot":"","sources":["../../../../src/tools/generate-tests/generators/graphql-test-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { TestDefinition, TestFile, ProjectKnowledge } from '../../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Returns true when the project uses gRPC / Protocol Buffers.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isGrpcProject(knowledge: ProjectKnowledge): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Generate gRPC test definitions: proto contracts, unary, streaming, deadlines.
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateGrpcTestDefs(title: string, testDir: string, _testExt: string): TestDefinition[];
|
|
10
|
+
/**
|
|
11
|
+
* Generate gRPC test file scaffolds for the target language.
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateGrpcTestFiles(spec: {
|
|
14
|
+
title: string;
|
|
15
|
+
slug: string;
|
|
16
|
+
}, testDir: string, framework: string, language: string, testExt: string, autoGenerate: boolean): TestFile[];
|
|
17
|
+
//# sourceMappingURL=grpc-test-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grpc-test-generator.d.ts","sourceRoot":"","sources":["../../../../src/tools/generate-tests/generators/grpc-test-generator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAI1F;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAMlE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,cAAc,EAAE,CAmDlB;AA6LD;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACrC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,OAAO,GACpB,QAAQ,EAAE,CA2BZ"}
|