@alwaysmeticulous/cli 2.16.1 → 2.18.0
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/api/test-run.api.d.ts +2 -1
- package/dist/commands/bootstrap/bootstrap.command.d.ts +1 -1
- package/dist/commands/bootstrap/bootstrap.command.js +2 -2
- package/dist/commands/create-test/create-test.command.d.ts +1 -1
- package/dist/commands/create-test/create-test.command.js +2 -2
- package/dist/commands/debug-replay/debug-replay.command.d.ts +1 -1
- package/dist/commands/debug-replay/debug-replay.command.js +2 -2
- package/dist/commands/download-replay/download-replay.command.d.ts +1 -1
- package/dist/commands/download-replay/download-replay.command.js +2 -2
- package/dist/commands/download-session/download-session.command.d.ts +1 -1
- package/dist/commands/download-session/download-session.command.js +2 -2
- package/dist/commands/record/record.command.d.ts +1 -1
- package/dist/commands/record/record.command.js +2 -2
- package/dist/commands/replay/replay.command.d.ts +9 -3
- package/dist/commands/replay/replay.command.js +62 -85
- package/dist/commands/replay/utils/compute-and-save-diff.d.ts +15 -0
- package/dist/commands/replay/utils/compute-and-save-diff.js +46 -0
- package/dist/commands/run-all-tests/run-all-tests.command.d.ts +4 -2
- package/dist/commands/run-all-tests/run-all-tests.command.js +22 -112
- package/dist/commands/screenshot-diff/screenshot-diff.command.d.ts +12 -12
- package/dist/commands/screenshot-diff/screenshot-diff.command.js +21 -18
- package/dist/commands/serve/serve.command.d.ts +1 -1
- package/dist/commands/serve/serve.command.js +2 -2
- package/dist/commands/show-project/show-project.command.d.ts +1 -1
- package/dist/commands/show-project/show-project.command.js +2 -2
- package/dist/commands/update-tests/update-tests.command.d.ts +1 -1
- package/dist/commands/update-tests/update-tests.command.js +2 -2
- package/dist/config/config.types.d.ts +4 -0
- package/dist/deflake-tests/deflake-tests.handler.d.ts +2 -2
- package/dist/deflake-tests/deflake-tests.handler.js +8 -20
- package/dist/index.d.ts +12 -11
- package/dist/index.js +14 -12
- package/dist/main.js +12 -12
- package/dist/parallel-tests/messages.types.d.ts +2 -2
- package/dist/parallel-tests/parallel-tests.handler.d.ts +5 -9
- package/dist/parallel-tests/parallel-tests.handler.js +14 -19
- package/dist/parallel-tests/run-all-tests.d.ts +55 -0
- package/dist/parallel-tests/run-all-tests.js +180 -0
- package/dist/parallel-tests/run-all-tests.types.d.ts +5 -0
- package/dist/parallel-tests/run-all-tests.types.js +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/github-summary.utils.d.ts +1 -2
- package/dist/utils/github-summary.utils.js +1 -3
- package/dist/utils/run-all-tests.utils.d.ts +4 -5
- package/dist/utils/run-all-tests.utils.js +4 -7
- package/package.json +2 -2
|
@@ -9,19 +9,17 @@ const os_1 = require("os");
|
|
|
9
9
|
const path_1 = require("path");
|
|
10
10
|
const common_1 = require("@alwaysmeticulous/common");
|
|
11
11
|
const loglevel_1 = __importDefault(require("loglevel"));
|
|
12
|
-
const test_run_api_1 = require("../api/test-run.api");
|
|
13
12
|
const config_utils_1 = require("../utils/config.utils");
|
|
14
13
|
const run_all_tests_utils_1 = require("../utils/run-all-tests.utils");
|
|
15
14
|
/** Handler for running Meticulous tests in parallel using child processes */
|
|
16
|
-
const runAllTestsInParallel = async ({ config,
|
|
15
|
+
const runAllTestsInParallel = async ({ config, testRun, testsToRun: queue, apiToken, commitSha, appUrl, useAssetsSnapshottedInBaseSimulation, executionOptions, screenshottingOptions, parallelTasks, deflake, replayEventsDependencies, onTestFinished, }) => {
|
|
17
16
|
const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
|
|
18
|
-
const results = [
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
});
|
|
17
|
+
const results = [];
|
|
18
|
+
const progress = {
|
|
19
|
+
runningTestCases: queue.length,
|
|
20
|
+
failedTestCases: 0,
|
|
21
|
+
passedTestCases: 0,
|
|
22
|
+
};
|
|
25
23
|
const allTasksDone = (0, common_1.defer)();
|
|
26
24
|
let inProgress = 0;
|
|
27
25
|
const maxTasks = parallelTasks !== null && parallelTasks !== void 0 ? parallelTasks : Math.max((0, os_1.cpus)().length, 1);
|
|
@@ -82,26 +80,23 @@ const runAllTestsInParallel = async ({ config, client, testRun, apiToken, commit
|
|
|
82
80
|
// Handle task completion
|
|
83
81
|
deferredResult.promise
|
|
84
82
|
.catch(() => {
|
|
83
|
+
// If it threw an error then it's something fatal, rather than just a failed diff
|
|
84
|
+
// (it resolves successfully on a failed diff)
|
|
85
85
|
const result = {
|
|
86
86
|
...testCase,
|
|
87
87
|
headReplayId: "",
|
|
88
88
|
result: "fail",
|
|
89
|
+
screenshotDiffResults: [],
|
|
89
90
|
};
|
|
90
91
|
return result;
|
|
91
92
|
})
|
|
92
93
|
.then(async (result) => {
|
|
93
94
|
--inProgress;
|
|
94
95
|
results.push(result);
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
resultData: { results },
|
|
100
|
-
})
|
|
101
|
-
.catch((error) => {
|
|
102
|
-
logger.error(`Error while pushing partial results: ${error}`);
|
|
103
|
-
})
|
|
104
|
-
.then(() => {
|
|
96
|
+
progress.failedTestCases += result.result === "fail" ? 1 : 0;
|
|
97
|
+
progress.passedTestCases += result.result === "pass" ? 1 : 0;
|
|
98
|
+
--progress.runningTestCases;
|
|
99
|
+
onTestFinished === null || onTestFinished === void 0 ? void 0 : onTestFinished(progress, results).then(() => {
|
|
105
100
|
var _a;
|
|
106
101
|
if (results.length === (((_a = config.testCases) === null || _a === void 0 ? void 0 : _a.length) || 0)) {
|
|
107
102
|
allTasksDone.resolve();
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ReplayExecutionOptions } from "@alwaysmeticulous/common";
|
|
2
|
+
import { TestRunStatus } from "../api/test-run.api";
|
|
3
|
+
import { ScreenshotAssertionsEnabledOptions } from "../command-utils/common-types";
|
|
4
|
+
import { DetailedTestCaseResult, TestCaseResult } from "../config/config.types";
|
|
5
|
+
import { TestRunProgress } from "./run-all-tests.types";
|
|
6
|
+
export interface Options {
|
|
7
|
+
testsFile: string | null;
|
|
8
|
+
executionOptions: ReplayExecutionOptions;
|
|
9
|
+
screenshottingOptions: ScreenshotAssertionsEnabledOptions;
|
|
10
|
+
apiToken: string | null;
|
|
11
|
+
commitSha: string;
|
|
12
|
+
/**
|
|
13
|
+
* The base commit to compare test results against for test cases that don't have a baseReplayId specified.
|
|
14
|
+
*/
|
|
15
|
+
baseCommitSha: string | null;
|
|
16
|
+
appUrl: string | null;
|
|
17
|
+
useAssetsSnapshottedInBaseSimulation: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* If null runs in parralel with a sensible number of parrelel tasks for the given machine.
|
|
20
|
+
*
|
|
21
|
+
* Set to 1 to disable parralelism.
|
|
22
|
+
*/
|
|
23
|
+
parallelTasks: number | null;
|
|
24
|
+
deflake: boolean;
|
|
25
|
+
githubSummary: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* If provided it will incorportate the cachedTestRunResults in any calls to store
|
|
28
|
+
* test run results in the BE, but won't include the cachedTestRunResults in the returned
|
|
29
|
+
* RunAllTestsResult.
|
|
30
|
+
*/
|
|
31
|
+
cachedTestRunResults?: TestCaseResult[];
|
|
32
|
+
onTestRunCreated?: (testRun: TestRun & {
|
|
33
|
+
status: "Running";
|
|
34
|
+
}) => void;
|
|
35
|
+
onTestFinished?: (testRun: TestRun & {
|
|
36
|
+
status: "Running";
|
|
37
|
+
}) => void;
|
|
38
|
+
}
|
|
39
|
+
export interface RunAllTestsResult {
|
|
40
|
+
testRun: TestRun & {
|
|
41
|
+
status: "Success" | "Failure";
|
|
42
|
+
};
|
|
43
|
+
testCaseResults: DetailedTestCaseResult[];
|
|
44
|
+
}
|
|
45
|
+
export interface TestRun {
|
|
46
|
+
id: string;
|
|
47
|
+
url: string;
|
|
48
|
+
status: TestRunStatus;
|
|
49
|
+
progress: TestRunProgress;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Runs all the test cases in the provided file.
|
|
53
|
+
* @returns The results of the tests that were executed (note that this does not include results from any cachedTestRunResults passed in)
|
|
54
|
+
*/
|
|
55
|
+
export declare const runAllTests: ({ testsFile, apiToken, commitSha, baseCommitSha, appUrl, useAssetsSnapshottedInBaseSimulation, executionOptions, screenshottingOptions, parallelTasks, deflake, cachedTestRunResults: cachedTestRunResults_, githubSummary, onTestRunCreated, onTestFinished: onTestFinished_, }: Options) => Promise<RunAllTestsResult>;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runAllTests = void 0;
|
|
7
|
+
const common_1 = require("@alwaysmeticulous/common");
|
|
8
|
+
const loglevel_1 = __importDefault(require("loglevel"));
|
|
9
|
+
const client_1 = require("../api/client");
|
|
10
|
+
const test_run_api_1 = require("../api/test-run.api");
|
|
11
|
+
const config_1 = require("../config/config");
|
|
12
|
+
const deflake_tests_handler_1 = require("../deflake-tests/deflake-tests.handler");
|
|
13
|
+
const replay_assets_1 = require("../local-data/replay-assets");
|
|
14
|
+
const parallel_tests_handler_1 = require("../parallel-tests/parallel-tests.handler");
|
|
15
|
+
const config_utils_1 = require("../utils/config.utils");
|
|
16
|
+
const github_summary_utils_1 = require("../utils/github-summary.utils");
|
|
17
|
+
const run_all_tests_utils_1 = require("../utils/run-all-tests.utils");
|
|
18
|
+
const version_utils_1 = require("../utils/version.utils");
|
|
19
|
+
/**
|
|
20
|
+
* Runs all the test cases in the provided file.
|
|
21
|
+
* @returns The results of the tests that were executed (note that this does not include results from any cachedTestRunResults passed in)
|
|
22
|
+
*/
|
|
23
|
+
const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appUrl, useAssetsSnapshottedInBaseSimulation, executionOptions, screenshottingOptions, parallelTasks, deflake, cachedTestRunResults: cachedTestRunResults_, githubSummary, onTestRunCreated, onTestFinished: onTestFinished_, }) => {
|
|
24
|
+
if (appUrl != null && useAssetsSnapshottedInBaseSimulation) {
|
|
25
|
+
throw new Error("Arguments useAssetsSnapshottedInBaseSimulation and appUrl are mutually exclusive");
|
|
26
|
+
}
|
|
27
|
+
const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
|
|
28
|
+
const client = (0, client_1.createClient)({ apiToken });
|
|
29
|
+
const cachedTestRunResults = cachedTestRunResults_ !== null && cachedTestRunResults_ !== void 0 ? cachedTestRunResults_ : [];
|
|
30
|
+
const config = await (0, config_1.readConfig)(testsFile || undefined);
|
|
31
|
+
const allTestCases = config.testCases || [];
|
|
32
|
+
if (!allTestCases.length) {
|
|
33
|
+
throw new Error("Error! No test case defined");
|
|
34
|
+
}
|
|
35
|
+
// Only run the uncached test cases
|
|
36
|
+
const testCases = allTestCases.filter(({ sessionId, baseReplayId, title }) => !cachedTestRunResults.find((cached) => cached.sessionId === sessionId &&
|
|
37
|
+
cached.baseReplayId === baseReplayId &&
|
|
38
|
+
cached.title === title));
|
|
39
|
+
const meticulousSha = await (0, version_utils_1.getMeticulousVersion)();
|
|
40
|
+
const replayEventsDependencies = await (0, replay_assets_1.loadReplayEventsDependencies)();
|
|
41
|
+
const testRun = await (0, test_run_api_1.createTestRun)({
|
|
42
|
+
client,
|
|
43
|
+
commitSha,
|
|
44
|
+
meticulousSha,
|
|
45
|
+
configData: config,
|
|
46
|
+
});
|
|
47
|
+
const testRunUrl = (0, test_run_api_1.getTestRunUrl)(testRun);
|
|
48
|
+
onTestRunCreated === null || onTestRunCreated === void 0 ? void 0 : onTestRunCreated({
|
|
49
|
+
id: testRun.id,
|
|
50
|
+
url: testRunUrl,
|
|
51
|
+
status: "Running",
|
|
52
|
+
progress: {
|
|
53
|
+
failedTestCases: 0,
|
|
54
|
+
passedTestCases: cachedTestRunResults.length,
|
|
55
|
+
runningTestCases: testCases.length,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
logger.info("");
|
|
59
|
+
logger.info(`Test run URL: ${testRunUrl}`);
|
|
60
|
+
logger.info("");
|
|
61
|
+
const testsToRun = await (0, run_all_tests_utils_1.getTestsToRun)({
|
|
62
|
+
testCases,
|
|
63
|
+
client,
|
|
64
|
+
baseCommitSha: baseCommitSha !== null && baseCommitSha !== void 0 ? baseCommitSha : null,
|
|
65
|
+
});
|
|
66
|
+
const storeTestRunResults = async (status, resultsSoFar) => {
|
|
67
|
+
const resultsToSendToBE = [
|
|
68
|
+
...cachedTestRunResults,
|
|
69
|
+
...resultsSoFar.map(
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
71
|
+
({ screenshotDiffResults, ...result }) => result),
|
|
72
|
+
];
|
|
73
|
+
try {
|
|
74
|
+
await (0, test_run_api_1.putTestRunResults)({
|
|
75
|
+
client,
|
|
76
|
+
testRunId: testRun.id,
|
|
77
|
+
status,
|
|
78
|
+
resultData: {
|
|
79
|
+
results: resultsToSendToBE,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
logger.error(`Error while pushing partial results: ${error}`);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const onTestFinished = async (progress, resultsSoFar) => {
|
|
88
|
+
onTestFinished_ === null || onTestFinished_ === void 0 ? void 0 : onTestFinished_({
|
|
89
|
+
id: testRun.id,
|
|
90
|
+
url: testRunUrl,
|
|
91
|
+
status: "Running",
|
|
92
|
+
progress: {
|
|
93
|
+
...progress,
|
|
94
|
+
passedTestCases: progress.passedTestCases + cachedTestRunResults.length,
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
await storeTestRunResults("Running", resultsSoFar);
|
|
98
|
+
};
|
|
99
|
+
const getResults = async () => {
|
|
100
|
+
if (parallelTasks == null || parallelTasks > 1) {
|
|
101
|
+
const results = await (0, parallel_tests_handler_1.runAllTestsInParallel)({
|
|
102
|
+
config,
|
|
103
|
+
testRun,
|
|
104
|
+
testsToRun,
|
|
105
|
+
executionOptions,
|
|
106
|
+
screenshottingOptions,
|
|
107
|
+
apiToken,
|
|
108
|
+
commitSha,
|
|
109
|
+
appUrl,
|
|
110
|
+
useAssetsSnapshottedInBaseSimulation,
|
|
111
|
+
parallelTasks,
|
|
112
|
+
deflake,
|
|
113
|
+
replayEventsDependencies,
|
|
114
|
+
onTestFinished,
|
|
115
|
+
});
|
|
116
|
+
return results;
|
|
117
|
+
}
|
|
118
|
+
const results = [];
|
|
119
|
+
const progress = {
|
|
120
|
+
runningTestCases: testsToRun.length,
|
|
121
|
+
failedTestCases: 0,
|
|
122
|
+
passedTestCases: 0,
|
|
123
|
+
};
|
|
124
|
+
for (const testCase of testsToRun) {
|
|
125
|
+
const result = await (0, deflake_tests_handler_1.deflakeReplayCommandHandler)({
|
|
126
|
+
replayTarget: (0, config_utils_1.getReplayTargetForTestCase)({
|
|
127
|
+
useAssetsSnapshottedInBaseSimulation,
|
|
128
|
+
appUrl,
|
|
129
|
+
testCase,
|
|
130
|
+
}),
|
|
131
|
+
executionOptions,
|
|
132
|
+
screenshottingOptions,
|
|
133
|
+
testCase,
|
|
134
|
+
apiToken,
|
|
135
|
+
commitSha,
|
|
136
|
+
deflake,
|
|
137
|
+
generatedBy: { type: "testRun", runId: testRun.id },
|
|
138
|
+
testRunId: testRun.id,
|
|
139
|
+
replayEventsDependencies,
|
|
140
|
+
});
|
|
141
|
+
results.push(result);
|
|
142
|
+
progress.failedTestCases += result.result === "fail" ? 1 : 0;
|
|
143
|
+
progress.passedTestCases += result.result === "pass" ? 1 : 0;
|
|
144
|
+
--progress.runningTestCases;
|
|
145
|
+
await onTestFinished(progress, results);
|
|
146
|
+
}
|
|
147
|
+
return (0, run_all_tests_utils_1.sortResults)({ results, testCases });
|
|
148
|
+
};
|
|
149
|
+
const results = await getResults();
|
|
150
|
+
const runAllFailure = results.find(({ result }) => result === "fail");
|
|
151
|
+
const overallStatus = runAllFailure ? "Failure" : "Success";
|
|
152
|
+
await storeTestRunResults(overallStatus, results);
|
|
153
|
+
logger.info("");
|
|
154
|
+
logger.info("Results");
|
|
155
|
+
logger.info("=======");
|
|
156
|
+
logger.info(`URL: ${testRunUrl}`);
|
|
157
|
+
logger.info("=======");
|
|
158
|
+
results.forEach(({ title, result }) => {
|
|
159
|
+
logger.info(`${title} => ${result}`);
|
|
160
|
+
});
|
|
161
|
+
if (githubSummary) {
|
|
162
|
+
await (0, github_summary_utils_1.writeGitHubSummary)({ testRunUrl, results });
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
testRun: {
|
|
166
|
+
url: testRunUrl,
|
|
167
|
+
id: testRun.id,
|
|
168
|
+
status: overallStatus,
|
|
169
|
+
progress: {
|
|
170
|
+
passedTestCases: results.filter(({ result }) => result === "pass")
|
|
171
|
+
.length,
|
|
172
|
+
failedTestCases: results.filter(({ result }) => result === "fail")
|
|
173
|
+
.length,
|
|
174
|
+
runningTestCases: 0,
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
testCaseResults: results,
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
exports.runAllTests = runAllTests;
|