@alwaysmeticulous/cli 2.36.0 → 2.38.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/replay.api.d.ts +0 -1
- package/dist/api/replay.api.js +1 -13
- package/dist/api/test-run.api.d.ts +8 -2
- package/dist/api/test-run.api.js +21 -3
- package/dist/api/types.d.ts +9 -0
- package/dist/command-utils/common-options.d.ts +0 -10
- package/dist/command-utils/common-options.js +0 -6
- package/dist/commands/create-test/create-test.command.d.ts +0 -5
- package/dist/commands/create-test/create-test.command.js +1 -5
- package/dist/commands/replay/replay.command.d.ts +5 -25
- package/dist/commands/replay/replay.command.js +10 -54
- package/dist/commands/replay/utils/compute-diff.d.ts +3 -6
- package/dist/commands/replay/utils/compute-diff.js +83 -18
- package/dist/commands/replay/utils/exit-early-if-skip-upload-env-var-set.d.ts +1 -1
- package/dist/commands/replay/utils/exit-early-if-skip-upload-env-var-set.js +3 -3
- package/dist/commands/run-all-tests/run-all-tests.command.d.ts +4 -10
- package/dist/commands/run-all-tests/run-all-tests.command.js +6 -10
- package/dist/commands/screenshot-diff/screenshot-diff.command.d.ts +6 -8
- package/dist/commands/screenshot-diff/screenshot-diff.command.js +50 -97
- package/dist/commands/screenshot-diff/utils/get-screenshot-filename.d.ts +2 -0
- package/dist/commands/screenshot-diff/utils/get-screenshot-filename.js +18 -0
- package/dist/commands/screenshot-diff/utils/get-screenshot-identifier.d.ts +2 -0
- package/dist/commands/screenshot-diff/utils/get-screenshot-identifier.js +24 -0
- package/dist/commands/screenshot-diff/utils/has-notable-differences.d.ts +2 -0
- package/dist/commands/screenshot-diff/utils/has-notable-differences.js +10 -0
- package/dist/config/config.js +2 -3
- package/dist/config/config.types.d.ts +1 -1
- package/dist/deflake-tests/deflake-tests.handler.d.ts +1 -0
- package/dist/deflake-tests/deflake-tests.handler.js +9 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -3
- package/dist/local-data/replays.d.ts +6 -1
- package/dist/local-data/replays.js +11 -3
- package/dist/local-data/screenshot-diffs.js +1 -1
- package/dist/local-data/serve-assets-from-simulation.js +1 -1
- package/dist/parallel-tests/__tests__/mock-test-results.js +3 -1
- package/dist/parallel-tests/__tests__/parrallel-tests.handler.spec.js +1 -1
- package/dist/parallel-tests/merge-test-results.js +18 -9
- package/dist/parallel-tests/parallel-tests.handler.js +2 -1
- package/dist/parallel-tests/run-all-tests.d.ts +2 -2
- package/dist/parallel-tests/run-all-tests.js +50 -23
- package/dist/parallel-tests/screenshot-diff-results.utils.d.ts +7 -0
- package/dist/parallel-tests/screenshot-diff-results.utils.js +20 -0
- package/dist/utils/config.utils.d.ts +1 -2
- package/dist/utils/config.utils.js +1 -10
- package/dist/utils/run-all-tests.utils.d.ts +0 -1
- package/dist/utils/run-all-tests.utils.js +3 -50
- package/package.json +6 -4
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.mergeResults = void 0;
|
|
4
7
|
const utils_1 = require("@sentry/utils");
|
|
8
|
+
const fast_json_stable_stringify_1 = __importDefault(require("fast-json-stable-stringify"));
|
|
9
|
+
const screenshot_diff_results_utils_1 = require("./screenshot-diff-results.utils");
|
|
5
10
|
const mergeResults = ({ currentResult, comparisonToHeadReplay, }) => {
|
|
6
11
|
// If any of the screenshots diffs in comparisonToHeadReplay show a diff against one
|
|
7
12
|
// of the screenshots that orignally failed in currentResult then we have a flake
|
|
8
13
|
// on our hands
|
|
9
14
|
const retryDiffById = new Map();
|
|
10
|
-
comparisonToHeadReplay.
|
|
15
|
+
(0, screenshot_diff_results_utils_1.flattenScreenshotDiffResults)(comparisonToHeadReplay).forEach((result) => {
|
|
11
16
|
const hash = hashScreenshotIdentifier(result.identifier);
|
|
12
17
|
if (retryDiffById.has(hash)) {
|
|
13
18
|
throw new Error(`Received two screenshots for the same identifier '${hash}'. Screenshots should be unique.`);
|
|
14
19
|
}
|
|
15
20
|
retryDiffById.set(hash, result);
|
|
16
21
|
});
|
|
17
|
-
const newScreenshotDiffResults = currentResult.
|
|
22
|
+
const newScreenshotDiffResults = (0, screenshot_diff_results_utils_1.flattenScreenshotDiffResults)(currentResult).map((currentDiff) => {
|
|
18
23
|
if (currentDiff.outcome === "no-diff") {
|
|
19
24
|
return currentDiff;
|
|
20
25
|
}
|
|
@@ -53,7 +58,7 @@ const mergeResults = ({ currentResult, comparisonToHeadReplay, }) => {
|
|
|
53
58
|
...currentDiff,
|
|
54
59
|
diffsToHeadScreenshotOnRetries: [
|
|
55
60
|
...currentDiff.diffsToHeadScreenshotOnRetries,
|
|
56
|
-
|
|
61
|
+
withoutIdentifiers(diffWhenRetrying),
|
|
57
62
|
],
|
|
58
63
|
};
|
|
59
64
|
}
|
|
@@ -62,10 +67,11 @@ const mergeResults = ({ currentResult, comparisonToHeadReplay, }) => {
|
|
|
62
67
|
}
|
|
63
68
|
else {
|
|
64
69
|
return {
|
|
70
|
+
baseReplayId: currentDiff.baseReplayId,
|
|
65
71
|
identifier: currentDiff.identifier,
|
|
66
72
|
outcome: "flake",
|
|
67
|
-
diffToBaseScreenshot:
|
|
68
|
-
diffsToHeadScreenshotOnRetries: [
|
|
73
|
+
diffToBaseScreenshot: withoutIdentifiers(currentDiff),
|
|
74
|
+
diffsToHeadScreenshotOnRetries: [withoutIdentifiers(diffWhenRetrying)],
|
|
69
75
|
};
|
|
70
76
|
}
|
|
71
77
|
});
|
|
@@ -75,12 +81,15 @@ const mergeResults = ({ currentResult, comparisonToHeadReplay, }) => {
|
|
|
75
81
|
result: currentResult.result === "fail" && noLongerHasFailures
|
|
76
82
|
? "flake"
|
|
77
83
|
: currentResult.result,
|
|
78
|
-
|
|
84
|
+
screenshotDiffResultsByBaseReplayId: (0, screenshot_diff_results_utils_1.groupScreenshotDiffResults)(newScreenshotDiffResults),
|
|
79
85
|
};
|
|
80
86
|
};
|
|
81
87
|
exports.mergeResults = mergeResults;
|
|
82
|
-
const
|
|
83
|
-
|
|
88
|
+
const withoutIdentifiers = ({
|
|
89
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
90
|
+
identifier: _identifier,
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
92
|
+
baseReplayId: _baseReplayId, ...rest }) => rest;
|
|
84
93
|
const hashScreenshotIdentifier = (identifier) => {
|
|
85
94
|
if (identifier.type === "end-state") {
|
|
86
95
|
return "end-state";
|
|
@@ -93,7 +102,7 @@ const hashScreenshotIdentifier = (identifier) => {
|
|
|
93
102
|
// The identifier is probably from a newer version of the bundle script
|
|
94
103
|
// and we're on an old version of the CLI. Our best bet is to stringify it
|
|
95
104
|
// and use that as a hash.
|
|
96
|
-
return
|
|
105
|
+
return (0, fast_json_stable_stringify_1.default)(identifier);
|
|
97
106
|
}
|
|
98
107
|
};
|
|
99
108
|
const unknownScreenshotIdentifierType = (identifier) => {
|
|
@@ -8,6 +8,7 @@ const os_1 = require("os");
|
|
|
8
8
|
const common_1 = require("@alwaysmeticulous/common");
|
|
9
9
|
const loglevel_1 = __importDefault(require("loglevel"));
|
|
10
10
|
const merge_test_results_1 = require("./merge-test-results");
|
|
11
|
+
const screenshot_diff_results_utils_1 = require("./screenshot-diff-results.utils");
|
|
11
12
|
/** Handler for running Meticulous tests in parallel using child processes */
|
|
12
13
|
const runAllTestsInParallel = async ({ testsToRun, parallelTasks, maxRetriesOnFailure, executeTest, onTestFinished, onTestFailedToRun, }) => {
|
|
13
14
|
const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
|
|
@@ -134,7 +135,7 @@ const logRetrySummary = (nameOfTest, retryResult) => {
|
|
|
134
135
|
logger.info(`Retried taking screenshots for failed test ${nameOfTest}, but got the same results`);
|
|
135
136
|
}
|
|
136
137
|
else {
|
|
137
|
-
const numDifferingScreenshots = retryResult.
|
|
138
|
+
const numDifferingScreenshots = (0, screenshot_diff_results_utils_1.flattenScreenshotDiffResults)(retryResult).filter((result) => result.outcome !== "no-diff").length;
|
|
138
139
|
logger.info(`Retried taking screenshots for failed test ${nameOfTest}, and ${numDifferingScreenshots} screenshots came out different. Results for these screenshots are assumed to be flakes, and so will be ignored.`);
|
|
139
140
|
}
|
|
140
141
|
};
|
|
@@ -19,7 +19,6 @@ export interface Options {
|
|
|
19
19
|
*/
|
|
20
20
|
baseCommitSha: string | null;
|
|
21
21
|
appUrl: string | null;
|
|
22
|
-
useAssetsSnapshottedInBaseSimulation: boolean;
|
|
23
22
|
/**
|
|
24
23
|
* If null runs in parralel with a sensible number of parrelel tasks for the given machine.
|
|
25
24
|
*
|
|
@@ -44,6 +43,7 @@ export interface Options {
|
|
|
44
43
|
* Captured environment for this run
|
|
45
44
|
*/
|
|
46
45
|
environment?: TestRunEnvironment;
|
|
46
|
+
baseTestRunId: string | null;
|
|
47
47
|
onTestRunCreated?: (testRun: RunAllTestsTestRun & {
|
|
48
48
|
status: "Running";
|
|
49
49
|
}) => void;
|
|
@@ -61,4 +61,4 @@ export interface RunAllTestsResult {
|
|
|
61
61
|
* Runs all the test cases in the provided file.
|
|
62
62
|
* @returns The results of the tests that were executed (note that this does not include results from any cachedTestRunResults passed in)
|
|
63
63
|
*/
|
|
64
|
-
export declare const runAllTests: ({ testsFile, apiToken, commitSha, baseCommitSha, appUrl,
|
|
64
|
+
export declare const runAllTests: ({ testsFile, apiToken, commitSha, baseCommitSha, appUrl, executionOptions, screenshottingOptions, parallelTasks, deflake, maxRetriesOnFailure, cachedTestRunResults: cachedTestRunResults_, githubSummary, environment, baseTestRunId, onTestRunCreated, onTestFinished: onTestFinished_, }: Options) => Promise<RunAllTestsResult>;
|
|
@@ -23,10 +23,7 @@ const execute_test_in_child_process_1 = require("./execute-test-in-child-process
|
|
|
23
23
|
* Runs all the test cases in the provided file.
|
|
24
24
|
* @returns The results of the tests that were executed (note that this does not include results from any cachedTestRunResults passed in)
|
|
25
25
|
*/
|
|
26
|
-
const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appUrl,
|
|
27
|
-
if (appUrl != null && useAssetsSnapshottedInBaseSimulation) {
|
|
28
|
-
throw new Error("Arguments useAssetsSnapshottedInBaseSimulation and appUrl are mutually exclusive");
|
|
29
|
-
}
|
|
26
|
+
const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appUrl, executionOptions, screenshottingOptions, parallelTasks, deflake, maxRetriesOnFailure, cachedTestRunResults: cachedTestRunResults_, githubSummary, environment, baseTestRunId, onTestRunCreated, onTestFinished: onTestFinished_, }) => {
|
|
30
27
|
if (deflake && maxRetriesOnFailure > 1) {
|
|
31
28
|
throw new Error("Arguments deflake and maxRetriesOnFailure are mutually exclusive");
|
|
32
29
|
}
|
|
@@ -44,8 +41,8 @@ const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appU
|
|
|
44
41
|
throw new Error("Error! No test case defined");
|
|
45
42
|
}
|
|
46
43
|
// Only run the uncached test cases
|
|
47
|
-
const testCases = allTestCases.filter(({ sessionId,
|
|
48
|
-
cached.
|
|
44
|
+
const testCases = allTestCases.filter(({ sessionId, baseTestRunId, title }) => !cachedTestRunResults.find((cached) => cached.sessionId === sessionId &&
|
|
45
|
+
cached.baseTestRunId === baseTestRunId &&
|
|
49
46
|
cached.title === title));
|
|
50
47
|
const meticulousSha = await (0, version_utils_1.getMeticulousVersion)();
|
|
51
48
|
const replayEventsDependencies = await (0, replay_assets_1.loadReplayEventsDependencies)();
|
|
@@ -62,7 +59,6 @@ const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appU
|
|
|
62
59
|
commitSha,
|
|
63
60
|
baseCommitSha,
|
|
64
61
|
appUrl,
|
|
65
|
-
useAssetsSnapshottedInBaseSimulation,
|
|
66
62
|
parallelTasks,
|
|
67
63
|
deflake,
|
|
68
64
|
githubSummary,
|
|
@@ -86,17 +82,19 @@ const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appU
|
|
|
86
82
|
logger.info("");
|
|
87
83
|
logger.info(`Test run URL: ${testRunUrl}`);
|
|
88
84
|
logger.info("");
|
|
89
|
-
const testsToRun = await (
|
|
90
|
-
|
|
85
|
+
const testsToRun = await getTestCasesWithBaseTestRunId({
|
|
86
|
+
baseCommitSha,
|
|
87
|
+
baseTestRunId: baseTestRunId !== null && baseTestRunId !== void 0 ? baseTestRunId : null,
|
|
91
88
|
client,
|
|
92
|
-
|
|
89
|
+
logger,
|
|
90
|
+
testCases,
|
|
93
91
|
});
|
|
94
92
|
const storeTestRunResults = async (status, resultsSoFar) => {
|
|
95
93
|
const resultsToSendToBE = [
|
|
96
94
|
...cachedTestRunResults,
|
|
97
95
|
...resultsSoFar.map(
|
|
98
96
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
99
|
-
({
|
|
97
|
+
({ screenshotDiffResultsByBaseReplayId, ...result }) => result),
|
|
100
98
|
];
|
|
101
99
|
try {
|
|
102
100
|
await (0, test_run_api_1.putTestRunResults)({
|
|
@@ -127,17 +125,19 @@ const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appU
|
|
|
127
125
|
const onTestFinished = async (progress, resultsSoFar) => {
|
|
128
126
|
onProgressUpdated(progress);
|
|
129
127
|
const newResult = resultsSoFar.at(-1);
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
128
|
+
if (newResult != null) {
|
|
129
|
+
for (const [baseReplayId, screenshotDiffResults] of Object.entries(newResult.screenshotDiffResultsByBaseReplayId)) {
|
|
130
|
+
await (0, replay_diff_api_1.createReplayDiff)({
|
|
131
|
+
client,
|
|
132
|
+
headReplayId: newResult.headReplayId,
|
|
133
|
+
baseReplayId: baseReplayId,
|
|
134
|
+
testRunId: testRun.id,
|
|
135
|
+
data: {
|
|
136
|
+
screenshotAssertionsOptions: screenshottingOptions,
|
|
137
|
+
screenshotDiffResults,
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
141
|
}
|
|
142
142
|
await storeTestRunResults("Running", resultsSoFar);
|
|
143
143
|
};
|
|
@@ -146,6 +146,7 @@ const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appU
|
|
|
146
146
|
parallelTasks,
|
|
147
147
|
maxRetriesOnFailure,
|
|
148
148
|
executeTest: (testCase, isRetry) => {
|
|
149
|
+
var _a;
|
|
149
150
|
const initMessage = {
|
|
150
151
|
kind: "init",
|
|
151
152
|
data: {
|
|
@@ -157,7 +158,6 @@ const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appU
|
|
|
157
158
|
testCase,
|
|
158
159
|
deflake,
|
|
159
160
|
replayTarget: (0, config_utils_1.getReplayTargetForTestCase)({
|
|
160
|
-
useAssetsSnapshottedInBaseSimulation,
|
|
161
161
|
appUrl,
|
|
162
162
|
testCase,
|
|
163
163
|
}),
|
|
@@ -165,6 +165,7 @@ const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appU
|
|
|
165
165
|
screenshottingOptions,
|
|
166
166
|
generatedBy: { type: "testRun", runId: testRun.id },
|
|
167
167
|
testRunId: testRun.id,
|
|
168
|
+
baseTestRunId: (_a = testCase.baseTestRunId) !== null && _a !== void 0 ? _a : null,
|
|
168
169
|
replayEventsDependencies,
|
|
169
170
|
suppressScreenshotDiffLogging: isRetry,
|
|
170
171
|
},
|
|
@@ -212,3 +213,29 @@ const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appU
|
|
|
212
213
|
};
|
|
213
214
|
};
|
|
214
215
|
exports.runAllTests = runAllTests;
|
|
216
|
+
const getTestCasesWithBaseTestRunId = async ({ logger, client, baseCommitSha, baseTestRunId, testCases, }) => {
|
|
217
|
+
const defaultBaseTestRunId = baseCommitSha != null
|
|
218
|
+
? await (0, test_run_api_1.getLatestTestRunId)({
|
|
219
|
+
client,
|
|
220
|
+
commitSha: baseCommitSha,
|
|
221
|
+
})
|
|
222
|
+
: null;
|
|
223
|
+
const testsToRun = testCases.map((test) => {
|
|
224
|
+
// We use the baseTestRunId specified in the test case if it exists, otherwise we use
|
|
225
|
+
// use the baseTestRunId specified from the CLI args if it exists, otherwise we use the
|
|
226
|
+
// baseTestRunId for the base commit if it exists, otherwise we use null (don't compare screenshots).
|
|
227
|
+
const fallbackTestRunId = baseTestRunId !== null && baseTestRunId !== void 0 ? baseTestRunId : defaultBaseTestRunId;
|
|
228
|
+
if (test.baseTestRunId != null || fallbackTestRunId == null) {
|
|
229
|
+
return test;
|
|
230
|
+
}
|
|
231
|
+
return { ...test, baseTestRunId: fallbackTestRunId };
|
|
232
|
+
});
|
|
233
|
+
if (baseCommitSha != null) {
|
|
234
|
+
testsToRun
|
|
235
|
+
.filter((test) => test.baseTestRunId == null)
|
|
236
|
+
.forEach((test) => {
|
|
237
|
+
logger.warn(`Skipping comparisons for test "${test.title}" since no result to compare against stored for base commit ${baseCommitSha}`);
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
return testsToRun;
|
|
241
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ScreenshotDiffResult } from "@alwaysmeticulous/api";
|
|
2
|
+
import { DetailedTestCaseResult } from "../config/config.types";
|
|
3
|
+
export type ScreenshotDiffResultWithBaseReplayId = ScreenshotDiffResult & {
|
|
4
|
+
baseReplayId: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const flattenScreenshotDiffResults: (testCaseResult: DetailedTestCaseResult) => ScreenshotDiffResultWithBaseReplayId[];
|
|
7
|
+
export declare const groupScreenshotDiffResults: (results: ScreenshotDiffResultWithBaseReplayId[]) => Record<string, ScreenshotDiffResult[]>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.groupScreenshotDiffResults = exports.flattenScreenshotDiffResults = void 0;
|
|
4
|
+
const flattenScreenshotDiffResults = (testCaseResult) => {
|
|
5
|
+
return Object.entries(testCaseResult.screenshotDiffResultsByBaseReplayId).flatMap(([baseReplayId, diffs]) => {
|
|
6
|
+
return diffs.map((diff) => ({ ...diff, baseReplayId }));
|
|
7
|
+
});
|
|
8
|
+
};
|
|
9
|
+
exports.flattenScreenshotDiffResults = flattenScreenshotDiffResults;
|
|
10
|
+
const groupScreenshotDiffResults = (results) => {
|
|
11
|
+
const groupedResults = {};
|
|
12
|
+
results.forEach(({ baseReplayId, ...result }) => {
|
|
13
|
+
var _a;
|
|
14
|
+
const resultsForBaseReplayId = (_a = groupedResults[baseReplayId]) !== null && _a !== void 0 ? _a : [];
|
|
15
|
+
resultsForBaseReplayId.push(result);
|
|
16
|
+
groupedResults[baseReplayId] = resultsForBaseReplayId;
|
|
17
|
+
});
|
|
18
|
+
return groupedResults;
|
|
19
|
+
};
|
|
20
|
+
exports.groupScreenshotDiffResults = groupScreenshotDiffResults;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { TestCase } from "@alwaysmeticulous/api";
|
|
2
2
|
import { ReplayTarget } from "@alwaysmeticulous/common/dist/types/replay.types";
|
|
3
3
|
export declare const addTestCase: (testCase: TestCase) => Promise<void>;
|
|
4
|
-
export declare const getReplayTargetForTestCase: ({
|
|
5
|
-
useAssetsSnapshottedInBaseSimulation: boolean;
|
|
4
|
+
export declare const getReplayTargetForTestCase: ({ appUrl, testCase, }: {
|
|
6
5
|
appUrl: string | null;
|
|
7
6
|
testCase: TestCase;
|
|
8
7
|
}) => ReplayTarget;
|
|
@@ -11,7 +11,7 @@ const addTestCase = async (testCase) => {
|
|
|
11
11
|
await (0, config_1.saveConfig)(newConfig);
|
|
12
12
|
};
|
|
13
13
|
exports.addTestCase = addTestCase;
|
|
14
|
-
const getReplayTargetForTestCase = ({
|
|
14
|
+
const getReplayTargetForTestCase = ({ appUrl, testCase, }) => {
|
|
15
15
|
var _a, _b, _c;
|
|
16
16
|
if (((_a = testCase.options) === null || _a === void 0 ? void 0 : _a.simulationIdForAssets) != null) {
|
|
17
17
|
return {
|
|
@@ -19,15 +19,6 @@ const getReplayTargetForTestCase = ({ useAssetsSnapshottedInBaseSimulation, appU
|
|
|
19
19
|
simulationIdForAssets: (_b = testCase.options) === null || _b === void 0 ? void 0 : _b.simulationIdForAssets,
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
-
if (useAssetsSnapshottedInBaseSimulation) {
|
|
23
|
-
if (testCase.baseReplayId == null) {
|
|
24
|
-
throw new Error(`--useAssetsSnapshottedInBaseSimulation flag set, but test case "${testCase.title}" does not have a baseReplayId.`);
|
|
25
|
-
}
|
|
26
|
-
return {
|
|
27
|
-
type: "snapshotted-assets",
|
|
28
|
-
simulationIdForAssets: testCase.baseReplayId,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
22
|
if ((_c = testCase.options) === null || _c === void 0 ? void 0 : _c.appUrl) {
|
|
32
23
|
if (appUrl) {
|
|
33
24
|
throw new Error(`Test cases "${testCase.title}" has an "appUrl" option but --appUrl is also provided.`);
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
const common_1 = require("@alwaysmeticulous/common");
|
|
8
|
-
const loglevel_1 = __importDefault(require("loglevel"));
|
|
9
|
-
const test_run_api_1 = require("../api/test-run.api");
|
|
3
|
+
exports.sortResults = exports.mergeTestCases = void 0;
|
|
10
4
|
const mergeTestCases = (...testSuites) => {
|
|
11
5
|
const seenSessionIds = new Set();
|
|
12
6
|
return testSuites.flatMap((testSuite) => {
|
|
@@ -22,9 +16,9 @@ exports.mergeTestCases = mergeTestCases;
|
|
|
22
16
|
const sortResults = ({ results: unsorted_, testCases }) => {
|
|
23
17
|
const unsorted = [...unsorted_];
|
|
24
18
|
const results = [];
|
|
25
|
-
testCases.forEach(({ title,
|
|
19
|
+
testCases.forEach(({ title, baseTestRunId, sessionId }) => {
|
|
26
20
|
const idx = unsorted.findIndex((result) => result.title === title &&
|
|
27
|
-
result.
|
|
21
|
+
result.baseTestRunId === baseTestRunId &&
|
|
28
22
|
result.sessionId === sessionId);
|
|
29
23
|
if (idx == -1) {
|
|
30
24
|
return;
|
|
@@ -36,44 +30,3 @@ const sortResults = ({ results: unsorted_, testCases }) => {
|
|
|
36
30
|
return results;
|
|
37
31
|
};
|
|
38
32
|
exports.sortResults = sortResults;
|
|
39
|
-
const getTestsToRun = async ({ testCases, client, baseCommitSha, }) => {
|
|
40
|
-
const testCasesMissingBaseReplayId = testCases.filter((testCase) => testCase.baseReplayId == null);
|
|
41
|
-
const testCasesWithBaseReplayId = testCases.flatMap((testCase) => testCase.baseReplayId == null ? [] : [testCase]);
|
|
42
|
-
if (testCasesMissingBaseReplayId.length === 0) {
|
|
43
|
-
return testCasesWithBaseReplayId;
|
|
44
|
-
}
|
|
45
|
-
const baseReplayIdBySessionId = await getBaseReplayIdsBySessionId({
|
|
46
|
-
client,
|
|
47
|
-
baseCommitSha,
|
|
48
|
-
});
|
|
49
|
-
return testCases.flatMap((test) => {
|
|
50
|
-
if (test.baseReplayId != null) {
|
|
51
|
-
return [test];
|
|
52
|
-
}
|
|
53
|
-
const baseReplayId = baseReplayIdBySessionId[test.sessionId];
|
|
54
|
-
if (baseReplayId == null) {
|
|
55
|
-
const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
|
|
56
|
-
logger.warn(`Skipping comparisons for test "${test.title}" since no result to compare against stored for base commit ${baseCommitSha}`);
|
|
57
|
-
return [test];
|
|
58
|
-
}
|
|
59
|
-
return [{ ...test, baseReplayId }];
|
|
60
|
-
});
|
|
61
|
-
};
|
|
62
|
-
exports.getTestsToRun = getTestsToRun;
|
|
63
|
-
const getBaseReplayIdsBySessionId = async ({ client, baseCommitSha, }) => {
|
|
64
|
-
var _a, _b;
|
|
65
|
-
if (!baseCommitSha) {
|
|
66
|
-
return {};
|
|
67
|
-
}
|
|
68
|
-
const baseTestRun = await (0, test_run_api_1.getLatestTestRunResults)({
|
|
69
|
-
client,
|
|
70
|
-
commitSha: baseCommitSha,
|
|
71
|
-
});
|
|
72
|
-
const baseReplays = (_b = (_a = baseTestRun === null || baseTestRun === void 0 ? void 0 : baseTestRun.resultData) === null || _a === void 0 ? void 0 : _a.results) !== null && _b !== void 0 ? _b : [];
|
|
73
|
-
const baseReplayIdBySessionId = {};
|
|
74
|
-
// If there are multiple replays for a given session we take the last in the list
|
|
75
|
-
baseReplays.forEach((replay) => {
|
|
76
|
-
baseReplayIdBySessionId[replay.sessionId] = replay.headReplayId;
|
|
77
|
-
});
|
|
78
|
-
return baseReplayIdBySessionId;
|
|
79
|
-
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alwaysmeticulous/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.38.0",
|
|
4
4
|
"description": "The Meticulous CLI",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,10 +22,11 @@
|
|
|
22
22
|
"lint:fix": "eslint src --ext=ts,tsx,js --cache --fix",
|
|
23
23
|
"cli": "node dist/main.js",
|
|
24
24
|
"cli:dev": "ts-node src/main.ts",
|
|
25
|
+
"cli:dev-localhost": "METICULOUS_API_URL=http://localhost:3001/api/ ts-node src/main.ts",
|
|
25
26
|
"test": "jest"
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
28
|
-
"@alwaysmeticulous/common": "^2.
|
|
29
|
+
"@alwaysmeticulous/common": "^2.38.0",
|
|
29
30
|
"@sentry/node": "^7.36.0",
|
|
30
31
|
"@sentry/tracing": "^7.36.0",
|
|
31
32
|
"adm-zip": "^0.5.9",
|
|
@@ -34,6 +35,7 @@
|
|
|
34
35
|
"chalk": "^4.1.2",
|
|
35
36
|
"cosmiconfig": "^8.0.0",
|
|
36
37
|
"express": "^4.18.1",
|
|
38
|
+
"fast-json-stable-stringify": "^2.1.0",
|
|
37
39
|
"find-free-port": "^2.0.0",
|
|
38
40
|
"inquirer": "^8.2.4",
|
|
39
41
|
"luxon": "^3.2.1",
|
|
@@ -43,7 +45,7 @@
|
|
|
43
45
|
"yargs": "^17.5.1"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
46
|
-
"@alwaysmeticulous/api": "^2.
|
|
48
|
+
"@alwaysmeticulous/api": "^2.37.0",
|
|
47
49
|
"@types/express": "^4.17.14",
|
|
48
50
|
"@types/proper-lockfile": "^4.1.2"
|
|
49
51
|
},
|
|
@@ -93,5 +95,5 @@
|
|
|
93
95
|
"coverageDirectory": "../coverage",
|
|
94
96
|
"testEnvironment": "node"
|
|
95
97
|
},
|
|
96
|
-
"gitHead": "
|
|
98
|
+
"gitHead": "2c4fbc9225d5e0dc09f14a1e90a67008a5e3f376"
|
|
97
99
|
}
|