|
| 1 | +import { |
| 2 | + CreateENVIModelerWorkflow, |
| 3 | + ValidateENVIModelerNodes, |
| 4 | +} from '@idl/envi/modeler'; |
| 5 | +import { LogManager } from '@idl/logger'; |
| 6 | +import { MCPTaskRegistry } from '@idl/mcp/tasks'; |
| 7 | +import { IDLIndex } from '@idl/parsing/index'; |
| 8 | +import { GLOBAL_TOKEN_TYPES } from '@idl/types/idl-data-types'; |
| 9 | +import { DEFAULT_IDL_EXTENSION_CONFIG } from '@idl/vscode/extension-config'; |
| 10 | +import { writeFileSync } from 'fs'; |
| 11 | +import { join } from 'path'; |
| 12 | + |
| 13 | +import { IENVIModelerTest } from '../tests.interface'; |
| 14 | + |
| 15 | +/** |
| 16 | + * Generates tests for ENVI Modeler validation and workflow creation. |
| 17 | + * |
| 18 | + * At generation time this bootstraps a real MCPTaskRegistry (same pattern as |
| 19 | + * the sandbox) to capture expected errors and workflow output as inline |
| 20 | + * snapshots. Each generated spec file re-creates the same setup so that |
| 21 | + * tests are self-contained and exercise real task registration. |
| 22 | + */ |
| 23 | +export async function TestsForENVIModeler( |
| 24 | + name: string, |
| 25 | + tests: IENVIModelerTest[], |
| 26 | + uri = join(process.cwd(), 'tokens.ts'), |
| 27 | +) { |
| 28 | + // track our strings |
| 29 | + const strings: string[] = []; |
| 30 | + |
| 31 | + // --- imports --- |
| 32 | + strings.push( |
| 33 | + `import { CreateENVIModelerWorkflow, ValidateENVIModelerNodes } from '@idl/envi/modeler';`, |
| 34 | + ); |
| 35 | + strings.push(`import { LogManager } from '@idl/logger';`); |
| 36 | + strings.push(`import { MCPTaskRegistry } from '@idl/mcp/tasks';`); |
| 37 | + strings.push( |
| 38 | + `import { IDL_INDEX_OPTIONS, IDLIndex } from '@idl/parsing/index';`, |
| 39 | + ); |
| 40 | + strings.push( |
| 41 | + `import { GLOBAL_TOKEN_TYPES } from '@idl/types/idl-data-types';`, |
| 42 | + ); |
| 43 | + strings.push( |
| 44 | + `import { ENVIModelerEdge, ENVIModelerNode } from '@idl/types/mcp';`, |
| 45 | + ); |
| 46 | + strings.push( |
| 47 | + `import { DEFAULT_IDL_EXTENSION_CONFIG } from '@idl/vscode/extension-config';`, |
| 48 | + ); |
| 49 | + strings.push(``); |
| 50 | + strings.push(`IDL_INDEX_OPTIONS.IS_TEST = true;`); |
| 51 | + strings.push(``); |
| 52 | + |
| 53 | + // --- module-level registry setup (once per spec file, outside describe) --- |
| 54 | + strings.push(`// create log manager`); |
| 55 | + strings.push(`const logManager = new LogManager({`); |
| 56 | + strings.push(` alert: () => {`); |
| 57 | + strings.push(` // do nothing`); |
| 58 | + strings.push(` },`); |
| 59 | + strings.push(`});`); |
| 60 | + strings.push(``); |
| 61 | + strings.push(`// create index`); |
| 62 | + strings.push(`const index = new IDLIndex(logManager, 1, false);`); |
| 63 | + strings.push(``); |
| 64 | + strings.push(`// load global tokens`); |
| 65 | + strings.push(`index.loadGlobalTokens(DEFAULT_IDL_EXTENSION_CONFIG);`); |
| 66 | + strings.push(``); |
| 67 | + strings.push(`// create registry`); |
| 68 | + strings.push(`const registry = new MCPTaskRegistry(logManager);`); |
| 69 | + strings.push(``); |
| 70 | + strings.push(`// populate registry`); |
| 71 | + strings.push(`registry.registerTasksFromGlobalTokens(`); |
| 72 | + strings.push( |
| 73 | + ` index.globalIndex.globalTokensByTypeByName[GLOBAL_TOKEN_TYPES.FUNCTION],`, |
| 74 | + ); |
| 75 | + strings.push( |
| 76 | + ` index.globalIndex.globalTokensByTypeByName[GLOBAL_TOKEN_TYPES.STRUCTURE],`, |
| 77 | + ); |
| 78 | + strings.push(`);`); |
| 79 | + strings.push(``); |
| 80 | + |
| 81 | + // --- bootstrap generation-time registry to capture expected outputs --- |
| 82 | + const genLogManager = new LogManager({ |
| 83 | + alert: () => { |
| 84 | + // do nothing |
| 85 | + }, |
| 86 | + }); |
| 87 | + const genIndex = new IDLIndex(genLogManager, 1, false); |
| 88 | + genIndex.loadGlobalTokens(DEFAULT_IDL_EXTENSION_CONFIG); |
| 89 | + const genRegistry = new MCPTaskRegistry(genLogManager); |
| 90 | + genRegistry.registerTasksFromGlobalTokens( |
| 91 | + genIndex.globalIndex.globalTokensByTypeByName[GLOBAL_TOKEN_TYPES.FUNCTION], |
| 92 | + genIndex.globalIndex.globalTokensByTypeByName[GLOBAL_TOKEN_TYPES.STRUCTURE], |
| 93 | + ); |
| 94 | + |
| 95 | + // --- describe block --- |
| 96 | + strings.push(`describe(\`[auto generated] ${name}\`, () => {`); |
| 97 | + |
| 98 | + for (let i = 0; i < tests.length; i++) { |
| 99 | + const test = tests[i]; |
| 100 | + const testName = test.name; |
| 101 | + |
| 102 | + // run validation at generation time to capture expected outputs |
| 103 | + const errors = ValidateENVIModelerNodes( |
| 104 | + test.nodes, |
| 105 | + test.edges, |
| 106 | + genRegistry, |
| 107 | + ); |
| 108 | + |
| 109 | + let workflow: Record<string, unknown> | undefined; |
| 110 | + if (errors.length === 0) { |
| 111 | + workflow = CreateENVIModelerWorkflow(test.nodes, test.edges, genRegistry); |
| 112 | + } |
| 113 | + |
| 114 | + // serialize nodes and edges as JSON literals |
| 115 | + const nodesStr = JSON.stringify(test.nodes, null, 2); |
| 116 | + const edgesStr = JSON.stringify(test.edges, null, 2); |
| 117 | + |
| 118 | + strings.push(` it(\`[auto generated] ${testName}\`, () => {`); |
| 119 | + strings.push(` // define nodes`); |
| 120 | + strings.push(` const nodes: ENVIModelerNode[] = ${nodesStr};`); |
| 121 | + strings.push(``); |
| 122 | + strings.push(` // define edges`); |
| 123 | + strings.push(` const edges: ENVIModelerEdge[] = ${edgesStr};`); |
| 124 | + strings.push(``); |
| 125 | + strings.push(` // validate nodes`); |
| 126 | + strings.push( |
| 127 | + ` const errors = ValidateENVIModelerNodes(nodes, edges, registry);`, |
| 128 | + ); |
| 129 | + strings.push(``); |
| 130 | + strings.push(` // define expected errors`); |
| 131 | + strings.push( |
| 132 | + ` const expectedErrors: string[] = ${JSON.stringify(errors)};`, |
| 133 | + ); |
| 134 | + strings.push(``); |
| 135 | + strings.push(` // verify errors`); |
| 136 | + strings.push(` expect(errors).toEqual(expectedErrors);`); |
| 137 | + |
| 138 | + if (workflow !== undefined) { |
| 139 | + strings.push(``); |
| 140 | + strings.push(` // define expected workflow`); |
| 141 | + strings.push( |
| 142 | + ` const expectedWorkflow = ${JSON.stringify(workflow, null, 2)} as Record<string, unknown>;`, |
| 143 | + ); |
| 144 | + strings.push(``); |
| 145 | + strings.push(` // verify workflow`); |
| 146 | + strings.push( |
| 147 | + ` expect(CreateENVIModelerWorkflow(nodes, edges, registry)).toEqual(expectedWorkflow);`, |
| 148 | + ); |
| 149 | + } |
| 150 | + |
| 151 | + strings.push(` });`); |
| 152 | + strings.push(``); |
| 153 | + } |
| 154 | + |
| 155 | + strings.push(`});`); |
| 156 | + strings.push(``); |
| 157 | + |
| 158 | + writeFileSync(uri, strings.join('\n')); |
| 159 | +} |
0 commit comments