Skip to content

Commit 20c34ca

Browse files
New prompt for auto-test generation framework
1 parent 8ba68e1 commit 20c34ca

1 file changed

Lines changed: 189 additions & 0 deletions

File tree

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
---
2+
agent: 'agent'
3+
description: 'Add a new automated test type to the test-tokenizer generation framework'
4+
---
5+
6+
Your goal is to add a new automated test type to the test-tokenizer generation framework in this codebase. The framework auto-generates Jest spec files from declarative test definitions so developers can quickly observe how behavior changes for complex cases.
7+
8+
## Getting Started
9+
10+
1. Get the name of the new test type (e.g. "ENVI Modeler", "Assembler", "Hover Help")
11+
2. Understand what function(s) the tests will exercise and what inputs/outputs they need
12+
3. Determine the output lib directory under `libs/tests/<name>/src/lib`
13+
14+
---
15+
16+
## Step 1 — Add interfaces to `tests.interface.ts`
17+
18+
File: `apps/test-tokenizer/src/test-maker/tests.interface.ts`
19+
20+
Add two interfaces at the bottom of the file, following the `IAssemblerTest` / `IAutoAssemblerTest` pattern:
21+
22+
- **Individual test interface** (`IXxxTest`) — fields: `name: string` plus whatever inputs the function under test requires
23+
- **Suite wrapper interface** (`IAutoXxxTest extends IBaseAutoTest`) — field: `tests: IXxxTest[]`
24+
25+
Add any required type imports at the top of the file.
26+
27+
Example (for ENVI Modeler):
28+
```typescript
29+
export interface IENVIModelerTest {
30+
name: string;
31+
nodes: ENVIModelerNode[];
32+
edges: ENVIModelerEdge[];
33+
}
34+
35+
export interface IAutoENVIModelerTest extends IBaseAutoTest {
36+
tests: IENVIModelerTest[];
37+
}
38+
```
39+
40+
---
41+
42+
## Step 2 — Create the auto-tests interface file
43+
44+
Create: `apps/test-tokenizer/src/test-maker/tests/auto-<name>-tests.interface.ts`
45+
46+
Export an empty array constant of the suite wrapper type. The developer will populate this with test suites.
47+
48+
Example:
49+
```typescript
50+
import { IAutoENVIModelerTest } from '../tests.interface';
51+
52+
export const AUTO_ENVI_MODELER_TESTS: IAutoENVIModelerTest[] = [];
53+
```
54+
55+
---
56+
57+
## Step 3 — Create the maker function
58+
59+
Create: `apps/test-tokenizer/src/test-maker/makers/tests-for-<name>.ts`
60+
61+
Export an async function `TestsForXxx(name: string, tests: IXxxTest[], uri = join(process.cwd(), 'tokens.ts'))`.
62+
63+
The maker does two things:
64+
1. **At generation time**: runs the actual logic against each test's inputs to capture expected outputs as inline snapshots
65+
2. **Emits a spec file**: writes TypeScript source code to `uri` that reproduces the same setup and asserts against those snapshots
66+
67+
### Key patterns
68+
69+
- Build up a `strings: string[]` array and call `writeFileSync(uri, strings.join('\n'))` at the end
70+
- The generated spec file must be self-contained (all imports, all setup, all assertions inline)
71+
- For each test, serialize inputs as JSON literals using `JSON.stringify(value, null, 2)`
72+
- Close with `strings.push('});')` and `strings.push('')`
73+
74+
### Registry setup (required for ENVI Modeler tests)
75+
76+
When the function under test requires an `MCPTaskRegistry`, bootstrap it fully — both at generation time **and** in the emitted spec (once per file, outside the `describe` block):
77+
78+
```typescript
79+
// generation-time bootstrap
80+
const logManager = new LogManager({ alert: () => {} });
81+
const index = new IDLIndex(logManager, 1, false);
82+
index.loadGlobalTokens(DEFAULT_IDL_EXTENSION_CONFIG);
83+
const registry = new MCPTaskRegistry(logManager);
84+
registry.registerTasksFromGlobalTokens(
85+
index.globalIndex.globalTokensByTypeByName[GLOBAL_TOKEN_TYPES.FUNCTION],
86+
index.globalIndex.globalTokensByTypeByName[GLOBAL_TOKEN_TYPES.STRUCTURE],
87+
);
88+
```
89+
90+
Emit the equivalent code into the generated spec using `strings.push(...)`.
91+
92+
Required imports for registry-based tests (in both maker and generated spec):
93+
- `LogManager` from `@idl/logger`
94+
- `MCPTaskRegistry` from `@idl/mcp/tasks`
95+
- `IDL_INDEX_OPTIONS, IDLIndex` from `@idl/parsing/index`
96+
- `GLOBAL_TOKEN_TYPES` from `@idl/types/idl-data-types`
97+
- `DEFAULT_IDL_EXTENSION_CONFIG` from `@idl/vscode/extension-config`
98+
99+
### Structure of one generated test
100+
101+
```typescript
102+
it(`[auto generated] ${testName}`, () => {
103+
// inputs serialized as JSON literals
104+
const nodes: ENVIModelerNode[] = <JSON>;
105+
const edges: ENVIModelerEdge[] = <JSON>;
106+
107+
// call function under test
108+
const errors = ValidateENVIModelerNodes(nodes, edges, registry);
109+
110+
// inline snapshot of expected output (captured at generation time)
111+
const expectedErrors: string[] = <captured>;
112+
expect(errors).toEqual(expectedErrors);
113+
114+
// conditional: only emit workflow assertion when there are no errors
115+
if (workflow !== undefined) {
116+
const expectedWorkflow = <captured>;
117+
expect(CreateENVIModelerWorkflow(nodes, edges, registry)).toEqual(expectedWorkflow);
118+
}
119+
});
120+
```
121+
122+
Look at `apps/test-tokenizer/src/test-maker/makers/tests-for-envi-modeler.ts` for a complete reference implementation.
123+
124+
---
125+
126+
## Step 4 — Wire into the generator
127+
128+
File: `apps/test-tokenizer/src/test-maker/generate-automated-tests.ts`
129+
130+
Add two imports near the other maker/test imports:
131+
```typescript
132+
import { TestsForXxx } from './makers/tests-for-xxx';
133+
import { AUTO_XXX_TESTS } from './tests/auto-xxx-tests.interface';
134+
```
135+
136+
Add a generation block at the end of `GenerateAutomatedTests()`, following the exact same pattern as every other block:
137+
```typescript
138+
const outDirXxx = join(process.cwd(), 'libs/tests/<name>/src/lib');
139+
CleanTestDir(outDirXxx);
140+
console.log('Generating tests for <name>');
141+
for (let i = 0; i < AUTO_XXX_TESTS.length; i++) {
142+
console.log(` Suite (${i}): ${AUTO_XXX_TESTS[i].suiteName}`);
143+
await TestsForXxx(
144+
AUTO_XXX_TESTS[i].suiteName,
145+
AUTO_XXX_TESTS[i].tests,
146+
join(outDirXxx, AUTO_XXX_TESTS[i].fileName),
147+
);
148+
}
149+
console.log();
150+
```
151+
152+
---
153+
154+
## Step 5 — Set up the test lib
155+
156+
If `libs/tests/<name>/` does not yet exist, scaffold it to match the pattern of an existing test lib such as `libs/tests/assembler/`. Required files:
157+
- `project.json` — name: `"tests-<name>"`, executor: `@nx/jest:jest`
158+
- `jest.config.ts`
159+
- `tsconfig.json`, `tsconfig.lib.json`, `tsconfig.spec.json`
160+
- `.eslintrc.json`
161+
- `src/index.ts` — leave empty (no exports)
162+
- `src/lib/` — directory for generated spec files
163+
164+
If the lib already exists, make sure `src/index.ts` is empty (no broken exports).
165+
166+
Also check `tsconfig.base.json` to confirm the path alias follows the `"@idl/tests/<name>"` pattern used by all other test libs.
167+
168+
---
169+
170+
## Step 6 — Create a placeholder spec
171+
172+
Create: `libs/tests/<name>/src/lib/auto-<name>-basic.spec.ts`
173+
174+
```typescript
175+
describe(`[auto generated] <Name> placeholder`, () => {
176+
/* stub — run the test-tokenizer generator to populate this directory */
177+
});
178+
```
179+
180+
This ensures Jest recognizes the suite and the directory is non-empty before the generator runs.
181+
182+
---
183+
184+
## Verification
185+
186+
1. Check for TypeScript errors in the edited files
187+
2. Populate `AUTO_XXX_TESTS` in the interface file with at least one test suite entry
188+
3. Run the test-tokenizer NX generator target — should log `Generating tests for <name>` without errors
189+
4. Run `nx test tests-<name>` — stub spec (or generated specs) should pass

0 commit comments

Comments
 (0)