@midscene/test 1.13.2-beta-20260923035443.0 → 1.13.2
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~214.mjs +15 -15
- package/dist/es/1~214.mjs.map +1 -1
- package/dist/es/cli/index.mjs +6 -25
- package/dist/es/cli/index.mjs.map +1 -1
- package/dist/es/test-cli.mjs +53 -49
- package/dist/es/test-cli.mjs.map +1 -1
- package/dist/lib/0~160.js +15 -15
- package/dist/lib/0~160.js.map +1 -1
- package/dist/lib/cli/index.js +5 -24
- package/dist/lib/cli/index.js.map +1 -1
- package/dist/lib/test-cli.js +52 -48
- package/dist/lib/test-cli.js.map +1 -1
- package/dist/types/cli/index.d.ts +0 -3
- package/package.json +13 -13
package/dist/es/test-cli.mjs
CHANGED
|
@@ -10,7 +10,7 @@ import { JSON_SCHEMA, load } from "js-yaml";
|
|
|
10
10
|
import { createHash, randomUUID } from "node:crypto";
|
|
11
11
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
12
12
|
import { setMaxListeners } from "node:events";
|
|
13
|
-
import { TestRunReportAssembler
|
|
13
|
+
import { TestRunReportAssembler } from "@midscene/core/report";
|
|
14
14
|
import { getDebug } from "@midscene/shared/logger";
|
|
15
15
|
var __webpack_modules__ = {
|
|
16
16
|
"node:fs" (module) {
|
|
@@ -20,7 +20,9 @@ var __webpack_modules__ = {
|
|
|
20
20
|
module.exports = __rspack_external_node_path_c5b9b54f;
|
|
21
21
|
},
|
|
22
22
|
"./package.json" (module) {
|
|
23
|
-
module.exports =
|
|
23
|
+
module.exports = {
|
|
24
|
+
rE: "1.13.2"
|
|
25
|
+
};
|
|
24
26
|
}
|
|
25
27
|
};
|
|
26
28
|
var __webpack_module_cache__ = {};
|
|
@@ -96,7 +98,7 @@ var external_node_fs_ = __webpack_require__("node:fs");
|
|
|
96
98
|
var external_node_path_ = __webpack_require__("node:path");
|
|
97
99
|
var package_0 = __webpack_require__("./package.json");
|
|
98
100
|
const GENERATED_COMMENT = '<!-- Generated by `midscene-test nodes`. Do not edit directly. -->';
|
|
99
|
-
const
|
|
101
|
+
const sortNodesForSpec = (nodes)=>{
|
|
100
102
|
const priority = (name)=>'aiAct' === name ? 0 : 'aiAssert' === name ? 1 : 2;
|
|
101
103
|
return [
|
|
102
104
|
...nodes
|
|
@@ -116,7 +118,7 @@ const renderNodeOverview = (nodes)=>{
|
|
|
116
118
|
const renderWorkflowLocations = (location)=>{
|
|
117
119
|
const sections = [
|
|
118
120
|
'## Where to use these Nodes',
|
|
119
|
-
'Use these Nodes in Workflow Documents (`.yaml` or `.yml` files) selected by an Execution Project. Case file patterns and the config file path below are relative to this
|
|
121
|
+
'Use these Nodes in Workflow Documents (`.yaml` or `.yml` files) selected by an Execution Project. Case file patterns and the config file path below are relative to this spec file. Case file patterns use glob syntax. A custom `--config` path does not change where case files are selected.',
|
|
120
122
|
'Projects created by `midscene-test create` select `cases/**/*.{yaml,yml}` by default, so you can write test cases in `cases/example.yaml` or subdirectories of `cases/`. If an Execution Project has no `files` configuration, Midscene Test searches `**/*.{yaml,yml}` recursively instead. Check `projects[].files` in your configuration before choosing a file location.'
|
|
121
123
|
];
|
|
122
124
|
if (location) {
|
|
@@ -206,13 +208,14 @@ const renderNode = (node, warnings)=>{
|
|
|
206
208
|
}
|
|
207
209
|
return sections.join('\n\n');
|
|
208
210
|
};
|
|
209
|
-
const
|
|
211
|
+
const renderNodeSpec = (nodes, location)=>{
|
|
210
212
|
const warnings = [];
|
|
211
|
-
const sortedNodes =
|
|
213
|
+
const sortedNodes = sortNodesForSpec(nodes);
|
|
212
214
|
const sections = [
|
|
213
215
|
GENERATED_COMMENT,
|
|
214
|
-
'# Midscene Test Node
|
|
215
|
-
'This document describes the
|
|
216
|
+
'# Midscene Test Node Spec',
|
|
217
|
+
'This document describes the Nodes available in YAML test files (`.yaml` or `.yml`) for the Midscene Test framework (`@midscene/test`). It lists the Nodes registered by the current Test Project, their inputs, and how to call them in test steps and lifecycle hooks.',
|
|
218
|
+
"Learn about the framework and YAML test authoring:\n\n- [Midscene Test overview](https://midscenejs.com/midscene-test/overview): framework concepts and the role of Nodes.\n- [Create and use test projects](https://midscenejs.com/midscene-test/use): write YAML cases, run tests, and inspect results.\n- [Configure test projects](https://midscenejs.com/midscene-test/configuration): register Nodes, select case files, and manage runtime resources.",
|
|
216
219
|
renderNodeOverview(sortedNodes),
|
|
217
220
|
renderWorkflowLocations(location),
|
|
218
221
|
WORKFLOW_STEP_CONTRACT
|
|
@@ -1218,32 +1221,13 @@ const asNotRun = (documentId, collectedCase, projectName, reason)=>({
|
|
|
1218
1221
|
notRunReason: reason
|
|
1219
1222
|
});
|
|
1220
1223
|
const summarize = (projects)=>{
|
|
1221
|
-
const
|
|
1222
|
-
const documentAttemptByRunId = new Map(project.documents.map((document)=>[
|
|
1223
|
-
document.documentRunId,
|
|
1224
|
-
document.attemptIndex ?? 0
|
|
1225
|
-
]));
|
|
1226
|
-
return latestById(project.cases, (item)=>item.caseId).map((item)=>({
|
|
1227
|
-
status: item.status,
|
|
1228
|
-
...item.run ? {
|
|
1229
|
-
run: item.run
|
|
1230
|
-
} : {},
|
|
1231
|
-
...item.attempts ? {
|
|
1232
|
-
attempts: item.attempts
|
|
1233
|
-
} : {},
|
|
1234
|
-
retryCount: item.documentRunId ? documentAttemptByRunId.get(item.documentRunId) ?? 0 : 0
|
|
1235
|
-
}));
|
|
1236
|
-
});
|
|
1224
|
+
const cases = projects.flatMap((project)=>latestById(project.cases, (item)=>item.caseId));
|
|
1237
1225
|
const documents = projects.flatMap((project)=>latestById(project.documents, (item)=>item.documentId));
|
|
1238
|
-
const health = calculateTestRunHealth(healthCases);
|
|
1239
1226
|
return {
|
|
1240
|
-
total:
|
|
1241
|
-
passed:
|
|
1242
|
-
failed:
|
|
1243
|
-
notRun:
|
|
1244
|
-
passedAfterRetry: health.passedAfterRetry,
|
|
1245
|
-
finalPassRate: health.finalPassRate,
|
|
1246
|
-
firstPassRate: health.firstPassRate,
|
|
1227
|
+
total: cases.length,
|
|
1228
|
+
passed: cases.filter((item)=>'success' === item.status).length,
|
|
1229
|
+
failed: cases.filter((item)=>'failed' === item.status).length,
|
|
1230
|
+
notRun: cases.filter((item)=>'not-run' === item.status).length,
|
|
1247
1231
|
filtered: projects.reduce((total, project)=>total + project.filteredCaseCount, 0),
|
|
1248
1232
|
collectionErrors: projects.reduce((total, project)=>total + project.collectionErrors.length, 0),
|
|
1249
1233
|
documentFailures: documents.filter((document)=>'failed' === document.status).length,
|
|
@@ -1603,24 +1587,44 @@ const runNodesCommand = async (options, io)=>{
|
|
|
1603
1587
|
const projectName = options.projectNames?.[0];
|
|
1604
1588
|
const selectedProjects = projectName ? project.projects.filter((candidate)=>candidate.name === projectName) : project.projects;
|
|
1605
1589
|
if (0 === selectedProjects.length) throw new Error(`Unknown Midscene project: ${projectName}`);
|
|
1606
|
-
const
|
|
1607
|
-
|
|
1608
|
-
const
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1590
|
+
const filenames = new Map();
|
|
1591
|
+
const owners = new Map();
|
|
1592
|
+
for (const executionProject of project.projects){
|
|
1593
|
+
const safeName = executionProject.name.normalize('NFC').replace(/[<>:"/\\|?*\u0000-\u001f]/g, '-').replace(/[. ]+$/g, '-');
|
|
1594
|
+
const filename = project.hasExplicitProjects ? `midscene-node-spec.${safeName}.md` : 'midscene-node-spec.md';
|
|
1595
|
+
const key = filename.toLowerCase();
|
|
1596
|
+
const owner = owners.get(key);
|
|
1597
|
+
if (void 0 !== owner) throw new Error(`Projects "${owner}" and "${executionProject.name}" generate the same Node Spec filename: ${filename}`);
|
|
1598
|
+
owners.set(key, executionProject.name);
|
|
1599
|
+
filenames.set(executionProject.name, filename);
|
|
1600
|
+
}
|
|
1601
|
+
const specs = selectedProjects.map((executionProject)=>{
|
|
1602
|
+
const nodes = sortNodesForSpec(executionProject.nodes.definitions());
|
|
1603
|
+
const document = renderNodeSpec(nodes, {
|
|
1604
|
+
configPath: configPath ? (0, external_node_path_.relative)(configSearchRoot, configPath).split(external_node_path_.sep).join('/') : void 0,
|
|
1605
|
+
projects: [
|
|
1606
|
+
{
|
|
1607
|
+
name: executionProject.name,
|
|
1608
|
+
files: executionProject.files ?? DEFAULT_TEST_FILE_SELECTION
|
|
1609
|
+
}
|
|
1610
|
+
]
|
|
1611
|
+
});
|
|
1612
|
+
return {
|
|
1613
|
+
executionProject,
|
|
1614
|
+
nodes,
|
|
1615
|
+
document
|
|
1616
|
+
};
|
|
1615
1617
|
});
|
|
1616
|
-
for (const
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1618
|
+
for (const { executionProject, nodes, document } of specs){
|
|
1619
|
+
for (const warning of document.warnings)io.error(`midscene-test nodes: ${warning}`);
|
|
1620
|
+
const specPath = (0, external_node_path_.resolve)(configSearchRoot, filenames.get(executionProject.name));
|
|
1621
|
+
(0, external_node_fs_.writeFileSync)(specPath, document.markdown);
|
|
1622
|
+
if (project.hasExplicitProjects || projectName) io.log(`Execution Project: ${executionProject.name}`);
|
|
1623
|
+
io.log(`Registered Nodes (${nodes.length}):`);
|
|
1624
|
+
if (0 === nodes.length) io.log('No nodes are registered by the current Test Project.');
|
|
1625
|
+
for (const node of nodes)io.log(`- ${node.name}: ${node.description?.trim() || "Description not declared."}`);
|
|
1626
|
+
io.log(`\nNode Spec generated: ${specPath}`);
|
|
1627
|
+
}
|
|
1624
1628
|
};
|
|
1625
1629
|
async function runTestCli(args, io = defaultCliIO) {
|
|
1626
1630
|
try {
|