@midscene/test 1.17.5 → 1.17.7
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/cli/index.mjs +73 -39
- package/dist/es/cli/index.mjs.map +1 -1
- package/dist/es/index.mjs +5 -0
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/test-cli.mjs +76 -40
- package/dist/es/test-cli.mjs.map +1 -1
- package/dist/lib/cli/index.js +73 -39
- package/dist/lib/cli/index.js.map +1 -1
- package/dist/lib/index.js +5 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/test-cli.js +76 -40
- package/dist/lib/test-cli.js.map +1 -1
- package/dist/templates/test/android/README.md +1 -1
- package/dist/templates/test/android/README.zh.md +1 -1
- package/dist/templates/test/android/gitignore +0 -1
- package/dist/templates/test/computer/README.md +1 -1
- package/dist/templates/test/computer/README.zh.md +1 -1
- package/dist/templates/test/computer/gitignore +0 -1
- package/dist/templates/test/harmony/README.md +1 -1
- package/dist/templates/test/harmony/README.zh.md +1 -1
- package/dist/templates/test/harmony/gitignore +0 -1
- package/dist/templates/test/ios/README.md +1 -1
- package/dist/templates/test/ios/README.zh.md +1 -1
- package/dist/templates/test/ios/gitignore +0 -1
- package/dist/templates/test/web/README.md +1 -1
- package/dist/templates/test/web/README.zh.md +1 -1
- package/dist/templates/test/web/gitignore +0 -1
- package/dist/types/cli/index.d.ts +2 -1
- package/package.json +13 -13
package/dist/lib/cli/index.js
CHANGED
|
@@ -276,8 +276,7 @@ const validateTestOptions = (value, hasExplicitProjects)=>{
|
|
|
276
276
|
testTimeout: validatePositiveInteger(candidate.testTimeout, 120000, 'test.testTimeout')
|
|
277
277
|
});
|
|
278
278
|
};
|
|
279
|
-
const validateOutputPath = (value,
|
|
280
|
-
if (void 0 === value) return fallback;
|
|
279
|
+
const validateOutputPath = (value, label)=>{
|
|
281
280
|
if ('string' != typeof value || 0 === value.trim().length) throw new TypeError(`Midscene config ${label} must be non-empty.`);
|
|
282
281
|
return value;
|
|
283
282
|
};
|
|
@@ -291,7 +290,9 @@ const validateOutput = (value)=>{
|
|
|
291
290
|
if (void 0 !== candidate.reportFormat && 'single-html' !== candidate.reportFormat && 'html-and-external-assets' !== candidate.reportFormat) throw new TypeError('Midscene config output.reportFormat must be single-html or html-and-external-assets.');
|
|
292
291
|
return Object.freeze({
|
|
293
292
|
reportFormat: candidate.reportFormat ?? 'single-html',
|
|
294
|
-
|
|
293
|
+
...void 0 === candidate.reportDir ? {} : {
|
|
294
|
+
reportDir: validateOutputPath(candidate.reportDir, 'output.reportDir')
|
|
295
|
+
}
|
|
295
296
|
});
|
|
296
297
|
};
|
|
297
298
|
const validateTestProjectDefinition = (definition)=>{
|
|
@@ -884,8 +885,16 @@ const DEFAULT_TEST_FILE_SELECTION = {
|
|
|
884
885
|
]
|
|
885
886
|
};
|
|
886
887
|
const project_preparation_toPosix = (value)=>value.split(external_node_path_namespaceObject.sep).join('/');
|
|
887
|
-
const discoverResolvedTestFiles = (projectRoot, selection)=>{
|
|
888
|
+
const discoverResolvedTestFiles = (projectRoot, selection, excludedDirectories = [])=>{
|
|
888
889
|
const root = (0, external_node_path_namespaceObject.resolve)(projectRoot);
|
|
890
|
+
const outputPatterns = excludedDirectories.flatMap((directory)=>{
|
|
891
|
+
const withinRoot = (0, external_node_path_namespaceObject.relative)(root, directory);
|
|
892
|
+
if (!withinRoot || (0, external_node_path_namespaceObject.isAbsolute)(withinRoot) || '..' === withinRoot || withinRoot.startsWith(`..${external_node_path_namespaceObject.sep}`)) return [];
|
|
893
|
+
const literal = project_preparation_toPosix(withinRoot).replace(/([*?{}[\]()!])/g, '\\$1');
|
|
894
|
+
return [
|
|
895
|
+
`${literal}/**`
|
|
896
|
+
];
|
|
897
|
+
});
|
|
889
898
|
const match = (patterns)=>(0, external_tinyglobby_namespaceObject.globSync)(patterns, {
|
|
890
899
|
absolute: true,
|
|
891
900
|
caseSensitiveMatch: false,
|
|
@@ -895,6 +904,7 @@ const discoverResolvedTestFiles = (projectRoot, selection)=>{
|
|
|
895
904
|
followSymbolicLinks: false,
|
|
896
905
|
ignore: [
|
|
897
906
|
...ALWAYS_IGNORED_PATTERNS,
|
|
907
|
+
...outputPatterns,
|
|
898
908
|
...selection.exclude ?? []
|
|
899
909
|
],
|
|
900
910
|
onlyFiles: true
|
|
@@ -969,7 +979,7 @@ async function prepareProject(project, projectRoot, runDir, defaultTimeoutMs, op
|
|
|
969
979
|
const platform = options.platform?.trim();
|
|
970
980
|
const fileSelection = project.files ?? DEFAULT_TEST_FILE_SELECTION;
|
|
971
981
|
const prerequisiteFile = options.prerequisiteFile ? (0, external_node_path_namespaceObject.resolve)(options.prerequisiteFile) : void 0;
|
|
972
|
-
const mainFiles = options.files ?? discoverResolvedTestFiles(projectRoot, fileSelection);
|
|
982
|
+
const mainFiles = options.files ?? discoverResolvedTestFiles(projectRoot, fileSelection, options.excludedDirectories);
|
|
973
983
|
const files = [
|
|
974
984
|
...prerequisiteFile ? [
|
|
975
985
|
prerequisiteFile
|
|
@@ -1093,6 +1103,7 @@ async function prepareProject(project, projectRoot, runDir, defaultTimeoutMs, op
|
|
|
1093
1103
|
filteredCaseCount
|
|
1094
1104
|
};
|
|
1095
1105
|
}
|
|
1106
|
+
const common_namespaceObject = require("@midscene/shared/common");
|
|
1096
1107
|
const padDatePart = (value)=>String(value).padStart(2, '0');
|
|
1097
1108
|
const createTestRunId = (date = new Date(), uuid = (0, external_node_crypto_namespaceObject.randomUUID)())=>{
|
|
1098
1109
|
const timestamp = [
|
|
@@ -1134,44 +1145,65 @@ async function prepareTestRun(options) {
|
|
|
1134
1145
|
if (options.configPath && /\.ya?ml$/i.test(configPath)) throw new Error(`midscene-test --config only accepts a native TypeScript or JavaScript project config: ${configPath}. Run legacy batch YAML with \`midscene --config ${options.configPath}\`.`);
|
|
1135
1146
|
if (options.configPath && !(0, external_node_fs_namespaceObject.existsSync)(configPath)) throw new Error(`Midscene config does not exist: ${configPath}`);
|
|
1136
1147
|
const definition = await loadTestProject(configPath);
|
|
1137
|
-
const
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1148
|
+
const artifactDir = (0, common_namespaceObject.resolveMidsceneRunDir)(input.projectRoot);
|
|
1149
|
+
return (0, common_namespaceObject.runWithMidsceneRunDir)(artifactDir, async ()=>{
|
|
1150
|
+
const resultDir = options.resultDir ? (0, external_node_path_namespaceObject.resolve)(input.cwd, options.resultDir) : (0, external_node_path_namespaceObject.join)(artifactDir, 'test-results');
|
|
1151
|
+
const runDir = (0, external_node_path_namespaceObject.join)(resultDir, runId);
|
|
1152
|
+
const summaryPath = (0, external_node_path_namespaceObject.join)(runDir, 'summary.json');
|
|
1153
|
+
const reportDir = definition.output.reportDir ? (0, external_node_path_namespaceObject.resolve)(input.projectRoot, definition.output.reportDir) : (0, external_node_path_namespaceObject.join)(artifactDir, 'report');
|
|
1154
|
+
(0, external_node_fs_namespaceObject.mkdirSync)(resultDir, {
|
|
1155
|
+
recursive: true
|
|
1156
|
+
});
|
|
1157
|
+
(0, external_node_fs_namespaceObject.mkdirSync)(runDir);
|
|
1158
|
+
const projects = [];
|
|
1159
|
+
for (const project of selectProjects(definition.projects, options.projectNames))projects.push(await prepareProject(project, input.projectRoot, runDir, definition.test.testTimeout, {
|
|
1160
|
+
...input.singleFile ? {
|
|
1161
|
+
files: [
|
|
1162
|
+
input.singleFile
|
|
1163
|
+
]
|
|
1164
|
+
} : {},
|
|
1165
|
+
excludedDirectories: [
|
|
1166
|
+
artifactDir,
|
|
1167
|
+
resultDir,
|
|
1168
|
+
reportDir,
|
|
1169
|
+
...[
|
|
1170
|
+
'cache',
|
|
1171
|
+
'log',
|
|
1172
|
+
'output',
|
|
1173
|
+
'tmp',
|
|
1174
|
+
'dump'
|
|
1175
|
+
].map((name)=>(0, external_node_path_namespaceObject.join)(artifactDir, name))
|
|
1176
|
+
]
|
|
1177
|
+
}));
|
|
1178
|
+
const hasFormatMismatch = projects.some((project)=>project.collectionErrors.some(({ error })=>error instanceof NativeWorkflowFormatError));
|
|
1179
|
+
return {
|
|
1180
|
+
startedAt,
|
|
1181
|
+
runId,
|
|
1182
|
+
projectRoot: input.projectRoot,
|
|
1183
|
+
artifactDir,
|
|
1184
|
+
...configPath ? {
|
|
1185
|
+
configPath
|
|
1186
|
+
} : {},
|
|
1187
|
+
resultDir,
|
|
1188
|
+
runDir,
|
|
1189
|
+
summaryPath,
|
|
1190
|
+
reportDir,
|
|
1191
|
+
definition,
|
|
1192
|
+
projects,
|
|
1193
|
+
preflightScope: hasFormatMismatch ? 'run' : 'project',
|
|
1194
|
+
reportEnabled: true,
|
|
1195
|
+
publications: [],
|
|
1196
|
+
onProgress: options.onProgress ?? (()=>{}),
|
|
1197
|
+
onEvent: options.onEvent
|
|
1198
|
+
};
|
|
1143
1199
|
});
|
|
1144
|
-
(0, external_node_fs_namespaceObject.mkdirSync)(runDir);
|
|
1145
|
-
const projects = [];
|
|
1146
|
-
for (const project of selectProjects(definition.projects, options.projectNames))projects.push(await prepareProject(project, input.projectRoot, runDir, definition.test.testTimeout, input.singleFile ? {
|
|
1147
|
-
files: [
|
|
1148
|
-
input.singleFile
|
|
1149
|
-
]
|
|
1150
|
-
} : void 0));
|
|
1151
|
-
const hasFormatMismatch = projects.some((project)=>project.collectionErrors.some(({ error })=>error instanceof NativeWorkflowFormatError));
|
|
1152
|
-
return {
|
|
1153
|
-
startedAt,
|
|
1154
|
-
runId,
|
|
1155
|
-
projectRoot: input.projectRoot,
|
|
1156
|
-
...configPath ? {
|
|
1157
|
-
configPath
|
|
1158
|
-
} : {},
|
|
1159
|
-
resultDir,
|
|
1160
|
-
runDir,
|
|
1161
|
-
summaryPath,
|
|
1162
|
-
reportDir,
|
|
1163
|
-
definition,
|
|
1164
|
-
projects,
|
|
1165
|
-
preflightScope: hasFormatMismatch ? 'run' : 'project',
|
|
1166
|
-
reportEnabled: true,
|
|
1167
|
-
publications: [],
|
|
1168
|
-
onProgress: options.onProgress ?? (()=>{}),
|
|
1169
|
-
onEvent: options.onEvent
|
|
1170
|
-
};
|
|
1171
1200
|
}
|
|
1172
1201
|
const external_node_events_namespaceObject = require("node:events");
|
|
1173
1202
|
const report_namespaceObject = require("@midscene/core/report");
|
|
1174
1203
|
const logger_namespaceObject = require("@midscene/shared/logger");
|
|
1204
|
+
function renderTestBadge(summary) {
|
|
1205
|
+
return ``;
|
|
1206
|
+
}
|
|
1175
1207
|
const result_markdown_text = (value)=>value.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"').replaceAll('|', '|').replaceAll('[', '[').replaceAll(']', ']').replaceAll('*', '*').replaceAll('_', '_').replaceAll('`', '`').replaceAll('\\', '\').replace(/[\r\n]+/g, ' ');
|
|
1176
1208
|
const duration = (ms)=>{
|
|
1177
1209
|
const seconds = Math.round(ms / 1000);
|
|
@@ -1184,6 +1216,8 @@ function renderTestResultMarkdown(dump, options = {}) {
|
|
|
1184
1216
|
const lines = [
|
|
1185
1217
|
'## Midscene Test',
|
|
1186
1218
|
'',
|
|
1219
|
+
renderTestBadge(summary),
|
|
1220
|
+
'',
|
|
1187
1221
|
`${outcome} · ${duration(dump.durationMs)}`,
|
|
1188
1222
|
''
|
|
1189
1223
|
];
|
|
@@ -1918,7 +1952,7 @@ const latestById = (items, id)=>[
|
|
|
1918
1952
|
const notRunSuite = (prepared, reason)=>prepared.documents.flatMap((document)=>document.cases.map((item)=>asNotRun(document.documentId, item, prepared.project.name, reason)));
|
|
1919
1953
|
async function runPreparedTestProject(plan) {
|
|
1920
1954
|
const reports = new report_namespaceObject.ReportSession((0, external_node_path_namespaceObject.join)(plan.runDir, 'records'));
|
|
1921
|
-
return reports.run(()=>runWithReportSession(plan, reports));
|
|
1955
|
+
return (0, common_namespaceObject.runWithMidsceneRunDir)(plan.artifactDir, ()=>reports.run(()=>runWithReportSession(plan, reports)));
|
|
1922
1956
|
}
|
|
1923
1957
|
async function runWithReportSession(plan, reports) {
|
|
1924
1958
|
const { startedAt, runId, projectRoot, configPath, resultDir, runDir, summaryPath, reportDir, definition, projects: preparedProjects } = plan;
|