@midscene/test 1.12.5-beta-20260908034641.0 → 1.12.5
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/es/1~891.mjs +3 -1
- package/dist/es/1~891.mjs.map +1 -1
- package/dist/es/cli/index.mjs +8 -18
- package/dist/es/cli/index.mjs.map +1 -1
- package/dist/es/test-cli.mjs +13 -29
- package/dist/es/test-cli.mjs.map +1 -1
- package/dist/lib/0~458.js +3 -1
- package/dist/lib/0~458.js.map +1 -1
- package/dist/lib/cli/index.js +8 -18
- package/dist/lib/cli/index.js.map +1 -1
- package/dist/lib/test-cli.js +13 -29
- package/dist/lib/test-cli.js.map +1 -1
- package/dist/types/cli/index.d.ts +2 -9
- package/package.json +10 -10
package/dist/es/test-cli.mjs
CHANGED
|
@@ -115,12 +115,12 @@ const renderWorkflowLocations = (location)=>{
|
|
|
115
115
|
sections.push(`**Config file:** ${location.configPath ? `\`${location.configPath}\`` : 'No config file loaded.'}`);
|
|
116
116
|
for (const project of location.projects){
|
|
117
117
|
const patterns = project.files.include.map((pattern)=>`\`${pattern}\``).join(', ');
|
|
118
|
-
const projectLabel = location.projects.length > 1
|
|
118
|
+
const projectLabel = location.projects.length > 1 ? ` (Execution Project: ${project.name})` : '';
|
|
119
119
|
const excludes = project.files.exclude?.length ? `; excludes: ${project.files.exclude.map((pattern)=>`\`${pattern}\``).join(', ')}` : '';
|
|
120
120
|
sections.push(`**Case files:** ${patterns}${projectLabel}${excludes}`);
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
|
-
sections.push('Files matching `files.exclude` are not selected. Midscene Test always ignores `.git/`, `.midscene/`, `midscene_run/`, and `node_modules/` directories, including nested ones.', 'Call a Node in `cases[].steps`, or in the Workflow Document lifecycle steps `beforeAll`, `beforeEach`, `afterEach`, and `afterAll`.
|
|
123
|
+
sections.push('Files matching `files.exclude` are not selected. Midscene Test always ignores `.git/`, `.midscene/`, `midscene_run/`, and `node_modules/` directories, including nested ones.', 'Call a Node in `cases[].steps`, or in the Workflow Document lifecycle steps `beforeAll`, `beforeEach`, `afterEach`, and `afterAll`. Node registrations are shared across the Test Project; each Execution Project supplies its own runtime environment.');
|
|
124
124
|
return sections.join('\n\n');
|
|
125
125
|
};
|
|
126
126
|
const WORKFLOW_STEP_CONTRACT = `## Workflow Step Contract
|
|
@@ -609,7 +609,7 @@ const validateNonNegativeInteger = (value, fallback, label)=>{
|
|
|
609
609
|
if (!Number.isInteger(value) || value < 0) throw new TypeError(`Midscene config ${label} must be a non-negative integer.`);
|
|
610
610
|
return value;
|
|
611
611
|
};
|
|
612
|
-
const validateExecutionProjects = (value, defaultSetup
|
|
612
|
+
const validateExecutionProjects = (value, defaultSetup)=>{
|
|
613
613
|
if (void 0 === value) {
|
|
614
614
|
let platform = 'web';
|
|
615
615
|
if (void 0 !== defaultSetup) {
|
|
@@ -635,8 +635,7 @@ const validateExecutionProjects = (value, defaultSetup, globalNodes)=>{
|
|
|
635
635
|
exclude: []
|
|
636
636
|
}),
|
|
637
637
|
retry: 0,
|
|
638
|
-
variables: Object.freeze({})
|
|
639
|
-
nodes: new NodeRegistry(globalNodes.definitions())
|
|
638
|
+
variables: Object.freeze({})
|
|
640
639
|
})
|
|
641
640
|
])
|
|
642
641
|
};
|
|
@@ -651,7 +650,6 @@ const validateExecutionProjects = (value, defaultSetup, globalNodes)=>{
|
|
|
651
650
|
'name',
|
|
652
651
|
'platform',
|
|
653
652
|
'setup',
|
|
654
|
-
'nodes',
|
|
655
653
|
'files',
|
|
656
654
|
'tags',
|
|
657
655
|
'retry',
|
|
@@ -662,17 +660,10 @@ const validateExecutionProjects = (value, defaultSetup, globalNodes)=>{
|
|
|
662
660
|
names.add(candidate.name);
|
|
663
661
|
const platform = validatePlatform(candidate.platform, `${label}.platform`);
|
|
664
662
|
const files = validateTestFileSelection(candidate.files, `${label}.files`);
|
|
665
|
-
if (void 0 !== candidate.nodes && !Array.isArray(candidate.nodes)) throw new TypeError(`Midscene config ${label}.nodes must be an array.`);
|
|
666
|
-
const localNodes = new NodeRegistry(candidate.nodes);
|
|
667
|
-
const nodes = new NodeRegistry([
|
|
668
|
-
...globalNodes.definitions().filter((node)=>!localNodes.has(node.name)),
|
|
669
|
-
...localNodes.definitions()
|
|
670
|
-
]);
|
|
671
663
|
return Object.freeze({
|
|
672
664
|
projectId: projectIdFromIndex(index),
|
|
673
665
|
name: candidate.name,
|
|
674
666
|
platform,
|
|
675
|
-
nodes,
|
|
676
667
|
...files ? {
|
|
677
668
|
files
|
|
678
669
|
} : {},
|
|
@@ -714,8 +705,7 @@ const validateOutput = (value)=>{
|
|
|
714
705
|
});
|
|
715
706
|
};
|
|
716
707
|
const validateTestProjectDefinition = (definition)=>{
|
|
717
|
-
if (!isRecord(definition)) throw new TypeError('Midscene config must default export an object.');
|
|
718
|
-
if (void 0 !== definition.nodes && !Array.isArray(definition.nodes)) throw new TypeError('Midscene config nodes must be an array.');
|
|
708
|
+
if (!isRecord(definition) || !('nodes' in definition) || !Array.isArray(definition.nodes)) throw new TypeError('Midscene config must default export an object with a nodes array.');
|
|
719
709
|
if ('setupWorkflow' in definition) throw new TypeError('Midscene config setupWorkflow is no longer supported. Use setup or projects[].setup instead.');
|
|
720
710
|
if ('setupDocument' in definition) throw new TypeError('Midscene config setupDocument is not supported. Use setup or projects[].setup for resources, and beforeAll/afterAll for document lifecycle steps.');
|
|
721
711
|
if ('root' in definition) throw new TypeError('Midscene config root is not supported. Pass the Test Project directory to midscene-test instead.');
|
|
@@ -728,8 +718,8 @@ const validateTestProjectDefinition = (definition)=>{
|
|
|
728
718
|
'output',
|
|
729
719
|
'nodes'
|
|
730
720
|
], 'root');
|
|
721
|
+
const resolvedProjects = validateExecutionProjects(definition.projects, definition.setup);
|
|
731
722
|
const nodes = new NodeRegistry(definition.nodes);
|
|
732
|
-
const resolvedProjects = validateExecutionProjects(definition.projects, definition.setup, nodes);
|
|
733
723
|
return {
|
|
734
724
|
...resolvedProjects,
|
|
735
725
|
test: validateTestOptions(definition.test),
|
|
@@ -1934,7 +1924,7 @@ const selectProjects = (projects, names)=>{
|
|
|
1934
1924
|
if (unknown) throw new Error(`Unknown Midscene project: ${unknown}`);
|
|
1935
1925
|
return projects.filter((project)=>requested.has(project.name));
|
|
1936
1926
|
};
|
|
1937
|
-
const prepareProject = (project, projectRoot, runDir)=>{
|
|
1927
|
+
const prepareProject = (project, projectRoot, resolveNode, runDir)=>{
|
|
1938
1928
|
const fileSelection = project.files ?? DEFAULT_TEST_FILE_SELECTION;
|
|
1939
1929
|
const files = discoverTestFiles(projectRoot, fileSelection);
|
|
1940
1930
|
const sources = files.map((absolutePath)=>({
|
|
@@ -1956,7 +1946,7 @@ const prepareProject = (project, projectRoot, runDir)=>{
|
|
|
1956
1946
|
}
|
|
1957
1947
|
for (const source of sources)try {
|
|
1958
1948
|
const collected = collectWorkflowDocument(source, {
|
|
1959
|
-
resolveNode
|
|
1949
|
+
resolveNode,
|
|
1960
1950
|
variables: project.variables,
|
|
1961
1951
|
env: process.env
|
|
1962
1952
|
});
|
|
@@ -2000,7 +1990,7 @@ async function runTestProject(options = {}) {
|
|
|
2000
1990
|
});
|
|
2001
1991
|
(0, external_node_fs_.mkdirSync)(runDir);
|
|
2002
1992
|
const selectedProjects = selectProjects(definition.projects, options.projectNames);
|
|
2003
|
-
const preparedProjects = selectedProjects.map((project)=>prepareProject(project, projectRoot, runDir));
|
|
1993
|
+
const preparedProjects = selectedProjects.map((project)=>prepareProject(project, projectRoot, definition.resolveNode, runDir));
|
|
2004
1994
|
const progress = options.onProgress ?? (()=>{});
|
|
2005
1995
|
const totalDocuments = preparedProjects.reduce((total, prepared)=>total + prepared.documents.length, 0);
|
|
2006
1996
|
const totalCases = preparedProjects.reduce((total, prepared)=>total + prepared.selectedCaseCount, 0);
|
|
@@ -2093,7 +2083,7 @@ async function runTestProject(options = {}) {
|
|
|
2093
2083
|
}
|
|
2094
2084
|
projectProgress(` [document ${documentIndex + 1}/${prepared.documents.length}] ${document.sourcePath}`);
|
|
2095
2085
|
const execution = await runWorkflowDocument(document, {
|
|
2096
|
-
resolveNode:
|
|
2086
|
+
resolveNode: definition.nodes.require.bind(definition.nodes),
|
|
2097
2087
|
project,
|
|
2098
2088
|
projectContext: runtime.context,
|
|
2099
2089
|
retry: project.retry,
|
|
@@ -2232,7 +2222,7 @@ const parseTestCliArgs = (args, cwd = process.cwd())=>{
|
|
|
2232
2222
|
} else throw new Error(`Unknown option: ${arg}`);
|
|
2233
2223
|
}
|
|
2234
2224
|
if ('nodes' === command && resultDir) throw new Error('--result-dir is not supported by nodes.');
|
|
2235
|
-
if ('nodes' === command && projectNames.length >
|
|
2225
|
+
if ('nodes' === command && projectNames.length > 0) throw new Error('--project is not supported by nodes.');
|
|
2236
2226
|
return {
|
|
2237
2227
|
...command ? {
|
|
2238
2228
|
command
|
|
@@ -2263,15 +2253,10 @@ const runNodesCommand = async (options, io)=>{
|
|
|
2263
2253
|
const configPath = options.configPath ? (0, external_node_path_.resolve)(configSearchRoot, options.configPath) : discoverTestConfig(configSearchRoot);
|
|
2264
2254
|
if (options.configPath && (!configPath || !(0, external_node_fs_.existsSync)(configPath))) throw new Error(`Midscene config does not exist: ${configPath}`);
|
|
2265
2255
|
const project = await loadTestProject(configPath);
|
|
2266
|
-
const
|
|
2267
|
-
const selectedProjects = projectName ? project.projects.filter((candidate)=>candidate.name === projectName) : project.projects;
|
|
2268
|
-
if (0 === selectedProjects.length) throw new Error(`Unknown Midscene project: ${projectName}`);
|
|
2269
|
-
const registry = selectedProjects[0].nodes;
|
|
2270
|
-
if (selectedProjects.some((candidate)=>candidate.nodes.names().length !== registry.names().length || candidate.nodes.definitions().some((node)=>registry.get(node.name) !== node))) throw new Error('Projects have different Nodes. Use nodes --project <name> to select one.');
|
|
2271
|
-
const nodes = sortNodesForReference(registry.definitions());
|
|
2256
|
+
const nodes = sortNodesForReference(project.nodes.definitions());
|
|
2272
2257
|
const document = renderNodeReference(nodes, {
|
|
2273
2258
|
configPath: configPath ? (0, external_node_path_.relative)(configSearchRoot, configPath).split(external_node_path_.sep).join('/') : void 0,
|
|
2274
|
-
projects:
|
|
2259
|
+
projects: project.projects.map((executionProject)=>({
|
|
2275
2260
|
name: executionProject.name,
|
|
2276
2261
|
files: executionProject.files ?? DEFAULT_TEST_FILE_SELECTION
|
|
2277
2262
|
}))
|
|
@@ -2279,7 +2264,6 @@ const runNodesCommand = async (options, io)=>{
|
|
|
2279
2264
|
for (const warning of document.warnings)io.error(`midscene-test nodes: ${warning}`);
|
|
2280
2265
|
const referencePath = (0, external_node_path_.resolve)(configSearchRoot, 'midscene-node-reference.md');
|
|
2281
2266
|
(0, external_node_fs_.writeFileSync)(referencePath, document.markdown);
|
|
2282
|
-
if (projectName) io.log(`Execution Project: ${projectName}`);
|
|
2283
2267
|
io.log(`Registered Nodes (${nodes.length}):`);
|
|
2284
2268
|
if (0 === nodes.length) io.log('No nodes are registered by the current Test Project.');
|
|
2285
2269
|
for (const node of nodes)io.log(`- ${node.name}: ${node.description?.trim() || "Description not declared."}`);
|