@alwaysmeticulous/cli 2.37.0 → 2.39.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/command-utils/common-options.d.ts +0 -10
- package/dist/command-utils/common-options.js +0 -6
- package/dist/commands/bootstrap/bootstrap.command.js +1 -1
- package/dist/commands/create-test/create-test.command.d.ts +0 -5
- package/dist/commands/create-test/create-test.command.js +1 -2
- package/dist/commands/replay/replay.command.d.ts +1 -6
- package/dist/commands/replay/replay.command.js +1 -2
- package/dist/commands/run-all-tests/run-all-tests.command.d.ts +5 -10
- package/dist/commands/run-all-tests/run-all-tests.command.js +7 -8
- package/dist/parallel-tests/__tests__/merge-test-results.spec.js +4 -2
- package/dist/parallel-tests/__tests__/parrallel-tests.handler.spec.js +30 -0
- package/dist/parallel-tests/merge-test-results.d.ts +3 -1
- package/dist/parallel-tests/merge-test-results.js +20 -8
- package/dist/parallel-tests/messages.types.d.ts +2 -2
- package/dist/parallel-tests/parallel-replay.handler.d.ts +3 -0
- package/dist/{deflake-tests/deflake-tests.handler.js → parallel-tests/parallel-replay.handler.js} +2 -21
- package/dist/{deflake-tests/deflake-tests.handler.d.ts → parallel-tests/parallel-replay.types.d.ts} +1 -7
- package/dist/parallel-tests/parallel-replay.types.js +2 -0
- package/dist/parallel-tests/parallel-tests.handler.d.ts +1 -0
- package/dist/parallel-tests/parallel-tests.handler.js +30 -7
- package/dist/parallel-tests/run-all-tests.d.ts +11 -2
- package/dist/parallel-tests/run-all-tests.js +3 -7
- package/dist/parallel-tests/task.handler.js +2 -2
- package/package.json +4 -4
|
@@ -20,11 +20,6 @@ export declare const OPTIONS: {
|
|
|
20
20
|
readonly description: "Enables bypass CSP in the browser (danger: this could mean you tests hit your production backend)";
|
|
21
21
|
readonly default: false;
|
|
22
22
|
};
|
|
23
|
-
readonly padTime: {
|
|
24
|
-
readonly boolean: true;
|
|
25
|
-
readonly description: "Pad replay time according to recording duration. Please note this option will be ignored if running with the '--skipPauses' option.";
|
|
26
|
-
readonly default: true;
|
|
27
|
-
};
|
|
28
23
|
readonly shiftTime: {
|
|
29
24
|
readonly boolean: true;
|
|
30
25
|
readonly description: "Shift time during simulation to be set as the recording time";
|
|
@@ -120,11 +115,6 @@ export declare const COMMON_REPLAY_OPTIONS: {
|
|
|
120
115
|
readonly description: "Enables bypass CSP in the browser (danger: this could mean you tests hit your production backend)";
|
|
121
116
|
readonly default: false;
|
|
122
117
|
};
|
|
123
|
-
padTime: {
|
|
124
|
-
readonly boolean: true;
|
|
125
|
-
readonly description: "Pad replay time according to recording duration. Please note this option will be ignored if running with the '--skipPauses' option.";
|
|
126
|
-
readonly default: true;
|
|
127
|
-
};
|
|
128
118
|
shiftTime: {
|
|
129
119
|
readonly boolean: true;
|
|
130
120
|
readonly description: "Shift time during simulation to be set as the recording time";
|
|
@@ -33,11 +33,6 @@ exports.OPTIONS = {
|
|
|
33
33
|
description: "Enables bypass CSP in the browser (danger: this could mean you tests hit your production backend)",
|
|
34
34
|
default: false,
|
|
35
35
|
},
|
|
36
|
-
padTime: {
|
|
37
|
-
boolean: true,
|
|
38
|
-
description: "Pad replay time according to recording duration. Please note this option will be ignored if running with the '--skipPauses' option.",
|
|
39
|
-
default: true,
|
|
40
|
-
},
|
|
41
36
|
shiftTime: {
|
|
42
37
|
boolean: true,
|
|
43
38
|
description: "Shift time during simulation to be set as the recording time",
|
|
@@ -109,7 +104,6 @@ exports.COMMON_REPLAY_OPTIONS = {
|
|
|
109
104
|
headless: exports.OPTIONS.headless,
|
|
110
105
|
devTools: exports.OPTIONS.devTools,
|
|
111
106
|
bypassCSP: exports.OPTIONS.bypassCSP,
|
|
112
|
-
padTime: exports.OPTIONS.padTime,
|
|
113
107
|
shiftTime: exports.OPTIONS.shiftTime,
|
|
114
108
|
networkStubbing: exports.OPTIONS.networkStubbing,
|
|
115
109
|
skipPauses: exports.OPTIONS.skipPauses,
|
|
@@ -22,7 +22,7 @@ const handler = async () => {
|
|
|
22
22
|
logger.info(`Setting up ${chalk_1.default.green("test:meticulous")} script...`);
|
|
23
23
|
await (0, npm_set_script_utils_1.npmSetScript)({
|
|
24
24
|
script: "test:meticulous",
|
|
25
|
-
command: "meticulous run-all-tests --headless --parallelize
|
|
25
|
+
command: "meticulous run-all-tests --headless --parallelize",
|
|
26
26
|
});
|
|
27
27
|
};
|
|
28
28
|
exports.bootstrapCommand = (0, command_builder_1.buildCommand)("bootstrap")
|
|
@@ -20,11 +20,6 @@ export declare const createTestCommand: import("yargs").CommandModule<unknown, i
|
|
|
20
20
|
readonly description: "Enables bypass CSP in the browser (danger: this could mean you tests hit your production backend)";
|
|
21
21
|
readonly default: false;
|
|
22
22
|
};
|
|
23
|
-
padTime: {
|
|
24
|
-
readonly boolean: true;
|
|
25
|
-
readonly description: "Pad replay time according to recording duration. Please note this option will be ignored if running with the '--skipPauses' option.";
|
|
26
|
-
readonly default: true;
|
|
27
|
-
};
|
|
28
23
|
shiftTime: {
|
|
29
24
|
readonly boolean: true;
|
|
30
25
|
readonly description: "Shift time during simulation to be set as the recording time";
|
|
@@ -59,7 +59,7 @@ apiToken, commitSha, devTools, bypassCSP,
|
|
|
59
59
|
// Record options
|
|
60
60
|
width, height, uploadIntervalMs, incognito, trace,
|
|
61
61
|
// Replay options
|
|
62
|
-
headless, screenshotSelector,
|
|
62
|
+
headless, screenshotSelector, shiftTime, networkStubbing, moveBeforeClick, cookiesFile, disableRemoteFonts, noSandbox, skipPauses, }) => {
|
|
63
63
|
const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
|
|
64
64
|
logger.info("Creating a new Meticulous test");
|
|
65
65
|
logger.info("Step 1: record a new test");
|
|
@@ -96,7 +96,6 @@ headless, screenshotSelector, padTime, shiftTime, networkStubbing, moveBeforeCli
|
|
|
96
96
|
bypassCSP,
|
|
97
97
|
screenshot: true,
|
|
98
98
|
screenshotSelector,
|
|
99
|
-
padTime,
|
|
100
99
|
shiftTime,
|
|
101
100
|
disableRemoteFonts,
|
|
102
101
|
noSandbox,
|
|
@@ -36,7 +36,7 @@ interface AdditionalReplayOptions {
|
|
|
36
36
|
cookiesFile: string | null | undefined;
|
|
37
37
|
debugger: boolean;
|
|
38
38
|
}
|
|
39
|
-
export declare const rawReplayCommandHandler: ({ apiToken, commitSha, sessionId, appUrl, simulationIdForAssets, headless, devTools, bypassCSP, screenshot, screenshotSelector, diffThreshold, diffPixelThreshold,
|
|
39
|
+
export declare const rawReplayCommandHandler: ({ apiToken, commitSha, sessionId, appUrl, simulationIdForAssets, headless, devTools, bypassCSP, screenshot, screenshotSelector, diffThreshold, diffPixelThreshold, shiftTime, networkStubbing, moveBeforeClick, cookiesFile, disableRemoteFonts, noSandbox, skipPauses, maxDurationMs, maxEventCount, storyboard, essentialFeaturesOnly, debugger: enableStepThroughDebugger, }: RawReplayCommandHandlerOptions) => Promise<Replay>;
|
|
40
40
|
export declare const getReplayTarget: ({ appUrl, simulationIdForAssets, }: {
|
|
41
41
|
appUrl: string | null;
|
|
42
42
|
simulationIdForAssets: string | null;
|
|
@@ -72,11 +72,6 @@ export declare const replayCommand: import("yargs").CommandModule<unknown, impor
|
|
|
72
72
|
readonly description: "Enables bypass CSP in the browser (danger: this could mean you tests hit your production backend)";
|
|
73
73
|
readonly default: false;
|
|
74
74
|
};
|
|
75
|
-
padTime: {
|
|
76
|
-
readonly boolean: true;
|
|
77
|
-
readonly description: "Pad replay time according to recording duration. Please note this option will be ignored if running with the '--skipPauses' option.";
|
|
78
|
-
readonly default: true;
|
|
79
|
-
};
|
|
80
75
|
shiftTime: {
|
|
81
76
|
readonly boolean: true;
|
|
82
77
|
readonly description: "Shift time during simulation to be set as the recording time";
|
|
@@ -232,12 +232,11 @@ const serveOrGetAppUrl = async (client, replayTarget) => {
|
|
|
232
232
|
const unknownReplayTargetType = (replayTarget) => {
|
|
233
233
|
throw new Error(`Unknown type of replay target: ${JSON.stringify(replayTarget)}`);
|
|
234
234
|
};
|
|
235
|
-
const rawReplayCommandHandler = async ({ apiToken, commitSha, sessionId, appUrl, simulationIdForAssets, headless, devTools, bypassCSP, screenshot, screenshotSelector, diffThreshold, diffPixelThreshold,
|
|
235
|
+
const rawReplayCommandHandler = async ({ apiToken, commitSha, sessionId, appUrl, simulationIdForAssets, headless, devTools, bypassCSP, screenshot, screenshotSelector, diffThreshold, diffPixelThreshold, shiftTime, networkStubbing, moveBeforeClick, cookiesFile, disableRemoteFonts, noSandbox, skipPauses, maxDurationMs, maxEventCount, storyboard, essentialFeaturesOnly, debugger: enableStepThroughDebugger, }) => {
|
|
236
236
|
const executionOptions = {
|
|
237
237
|
headless,
|
|
238
238
|
devTools,
|
|
239
239
|
bypassCSP,
|
|
240
|
-
padTime,
|
|
241
240
|
shiftTime,
|
|
242
241
|
networkStubbing,
|
|
243
242
|
skipPauses,
|
|
@@ -30,11 +30,6 @@ export declare const runAllTestsCommand: import("yargs").CommandModule<unknown,
|
|
|
30
30
|
readonly description: "Enables bypass CSP in the browser (danger: this could mean you tests hit your production backend)";
|
|
31
31
|
readonly default: false;
|
|
32
32
|
};
|
|
33
|
-
readonly padTime: {
|
|
34
|
-
readonly boolean: true;
|
|
35
|
-
readonly description: "Pad replay time according to recording duration. Please note this option will be ignored if running with the '--skipPauses' option.";
|
|
36
|
-
readonly default: true;
|
|
37
|
-
};
|
|
38
33
|
readonly shiftTime: {
|
|
39
34
|
readonly boolean: true;
|
|
40
35
|
readonly description: "Shift time during simulation to be set as the recording time";
|
|
@@ -102,16 +97,16 @@ export declare const runAllTestsCommand: import("yargs").CommandModule<unknown,
|
|
|
102
97
|
readonly description: "Number of tasks to run in parallel (defaults to two per CPU)";
|
|
103
98
|
readonly coerce: (value: number | null | undefined) => number | null | undefined;
|
|
104
99
|
};
|
|
105
|
-
readonly deflake: {
|
|
106
|
-
readonly boolean: true;
|
|
107
|
-
readonly description: "Attempt to deflake failing tests";
|
|
108
|
-
readonly default: false;
|
|
109
|
-
};
|
|
110
100
|
readonly maxRetriesOnFailure: {
|
|
111
101
|
readonly number: true;
|
|
112
102
|
readonly description: "If set to a value greater than 0 then will re-run any replays that give a screenshot diff and mark them as a flake if the screenshot generated on one of the retryed replays differs from that in the first replay.";
|
|
113
103
|
readonly default: 0;
|
|
114
104
|
};
|
|
105
|
+
readonly rerunTestsNTimes: {
|
|
106
|
+
readonly number: true;
|
|
107
|
+
readonly description: "If set to a value greater than 0 then will re-run all replays the specified number of times and mark them as a flake if the screenshot generated on one of the retryed replays differs from that in the first replay.";
|
|
108
|
+
readonly default: 0;
|
|
109
|
+
};
|
|
115
110
|
readonly useCache: {
|
|
116
111
|
readonly boolean: true;
|
|
117
112
|
readonly description: "Use result cache";
|
|
@@ -7,12 +7,11 @@ const command_builder_1 = require("../../command-utils/command-builder");
|
|
|
7
7
|
const common_options_1 = require("../../command-utils/common-options");
|
|
8
8
|
const run_all_tests_1 = require("../../parallel-tests/run-all-tests");
|
|
9
9
|
const commit_sha_utils_1 = require("../../utils/commit-sha.utils");
|
|
10
|
-
const handler = async ({ apiToken, commitSha: commitSha_, baseCommitSha, appUrl, headless, devTools, bypassCSP, diffThreshold, diffPixelThreshold,
|
|
10
|
+
const handler = async ({ apiToken, commitSha: commitSha_, baseCommitSha, appUrl, headless, devTools, bypassCSP, diffThreshold, diffPixelThreshold, shiftTime, networkStubbing, githubSummary, parallelize, parallelTasks: parrelelTasks_, maxRetriesOnFailure, rerunTestsNTimes, useCache, testsFile, disableRemoteFonts, noSandbox, skipPauses, moveBeforeClick, maxDurationMs, maxEventCount, storyboard, essentialFeaturesOnly, baseTestRunId, }) => {
|
|
11
11
|
const executionOptions = {
|
|
12
12
|
headless,
|
|
13
13
|
devTools,
|
|
14
14
|
bypassCSP,
|
|
15
|
-
padTime,
|
|
16
15
|
shiftTime,
|
|
17
16
|
networkStubbing,
|
|
18
17
|
disableRemoteFonts,
|
|
@@ -48,8 +47,8 @@ const handler = async ({ apiToken, commitSha: commitSha_, baseCommitSha, appUrl,
|
|
|
48
47
|
baseTestRunId: baseTestRunId !== null && baseTestRunId !== void 0 ? baseTestRunId : null,
|
|
49
48
|
appUrl: appUrl !== null && appUrl !== void 0 ? appUrl : null,
|
|
50
49
|
parallelTasks: parrelelTasks !== null && parrelelTasks !== void 0 ? parrelelTasks : null,
|
|
51
|
-
deflake,
|
|
52
50
|
maxRetriesOnFailure,
|
|
51
|
+
rerunTestsNTimes,
|
|
53
52
|
cachedTestRunResults,
|
|
54
53
|
githubSummary,
|
|
55
54
|
});
|
|
@@ -90,16 +89,16 @@ exports.runAllTestsCommand = (0, command_builder_1.buildCommand)("run-all-tests"
|
|
|
90
89
|
return value;
|
|
91
90
|
},
|
|
92
91
|
},
|
|
93
|
-
deflake: {
|
|
94
|
-
boolean: true,
|
|
95
|
-
description: "Attempt to deflake failing tests",
|
|
96
|
-
default: false,
|
|
97
|
-
},
|
|
98
92
|
maxRetriesOnFailure: {
|
|
99
93
|
number: true,
|
|
100
94
|
description: "If set to a value greater than 0 then will re-run any replays that give a screenshot diff and mark them as a flake if the screenshot generated on one of the retryed replays differs from that in the first replay.",
|
|
101
95
|
default: 0,
|
|
102
96
|
},
|
|
97
|
+
rerunTestsNTimes: {
|
|
98
|
+
number: true,
|
|
99
|
+
description: "If set to a value greater than 0 then will re-run all replays the specified number of times and mark them as a flake if the screenshot generated on one of the retryed replays differs from that in the first replay.",
|
|
100
|
+
default: 0,
|
|
101
|
+
},
|
|
103
102
|
useCache: {
|
|
104
103
|
boolean: true,
|
|
105
104
|
description: "Use result cache",
|
|
@@ -12,14 +12,16 @@ describe("mergeResults", () => {
|
|
|
12
12
|
});
|
|
13
13
|
expect(mergedResult).toEqual((0, mock_test_results_1.testResult)("fail", [(0, mock_test_results_1.diff)(0), (0, mock_test_results_1.noDiff)(1)]));
|
|
14
14
|
});
|
|
15
|
-
it("
|
|
15
|
+
it("doesn't ignore diffs to screenshots which originally passed", () => {
|
|
16
16
|
const currentResult = (0, mock_test_results_1.testResult)("pass", [(0, mock_test_results_1.noDiff)(0), (0, mock_test_results_1.noDiff)(1)]);
|
|
17
17
|
const comparisonToHeadReplay = (0, mock_test_results_1.testResult)("fail", [(0, mock_test_results_1.noDiff)(0), (0, mock_test_results_1.diff)(1)]);
|
|
18
18
|
const mergedResult = (0, merge_test_results_1.mergeResults)({
|
|
19
19
|
currentResult,
|
|
20
20
|
comparisonToHeadReplay,
|
|
21
21
|
});
|
|
22
|
-
expect(mergedResult).toEqual(
|
|
22
|
+
expect(mergedResult).toEqual(
|
|
23
|
+
// All screenshots are either "no-diff" or "flake" thus the overall result is "flake"
|
|
24
|
+
(0, mock_test_results_1.testResult)("flake", [(0, mock_test_results_1.noDiff)(0), (0, mock_test_results_1.flake)(1, (0, mock_test_results_1.noDiff)(), [(0, mock_test_results_1.diff)()])]));
|
|
23
25
|
});
|
|
24
26
|
it("marks screenshots as flakes if the screenshot comparison originally failed, but the second retry gives a different screenshot again", () => {
|
|
25
27
|
const currentResult = (0, mock_test_results_1.testResult)("fail", [(0, mock_test_results_1.noDiff)(0), (0, mock_test_results_1.diff)(1), (0, mock_test_results_1.diff)(2)]);
|
|
@@ -17,6 +17,7 @@ describe("runAllTestsInParallel", () => {
|
|
|
17
17
|
testsToRun: [testCase(0), testCase(1), testCase(2), testCase(3)],
|
|
18
18
|
parallelTasks: 2,
|
|
19
19
|
maxRetriesOnFailure: 0,
|
|
20
|
+
rerunTestsNTimes: 0,
|
|
20
21
|
executeTest: async (testCase) => {
|
|
21
22
|
var _a;
|
|
22
23
|
testsStarted++;
|
|
@@ -77,6 +78,7 @@ describe("runAllTestsInParallel", () => {
|
|
|
77
78
|
testsToRun: [testCase(0), testCase(1), testCase(2), testCase(3)],
|
|
78
79
|
parallelTasks: 2,
|
|
79
80
|
maxRetriesOnFailure: 0,
|
|
81
|
+
rerunTestsNTimes: 0,
|
|
80
82
|
executeTest: async (testCase) => {
|
|
81
83
|
var _a;
|
|
82
84
|
await testRunPromises[parseInt((_a = testCase.title) !== null && _a !== void 0 ? _a : "")].promise;
|
|
@@ -109,6 +111,7 @@ describe("runAllTestsInParallel", () => {
|
|
|
109
111
|
testsToRun: [testCase(0)],
|
|
110
112
|
parallelTasks: 2,
|
|
111
113
|
maxRetriesOnFailure: 0,
|
|
114
|
+
rerunTestsNTimes: 0,
|
|
112
115
|
executeTest: async (testCase) => {
|
|
113
116
|
return (0, mock_test_results_1.testResult)("fail", [(0, mock_test_results_1.diff)(0)], testCase);
|
|
114
117
|
},
|
|
@@ -121,6 +124,7 @@ describe("runAllTestsInParallel", () => {
|
|
|
121
124
|
testsToRun: [testCase(0)],
|
|
122
125
|
parallelTasks: 2,
|
|
123
126
|
maxRetriesOnFailure: 10,
|
|
127
|
+
rerunTestsNTimes: 0,
|
|
124
128
|
executeTest: async (testCase, isRetry) => {
|
|
125
129
|
if (!isRetry) {
|
|
126
130
|
return (0, mock_test_results_1.testResult)("fail", [(0, mock_test_results_1.diff)(0), (0, mock_test_results_1.diff)(1)], testCase);
|
|
@@ -145,6 +149,7 @@ describe("runAllTestsInParallel", () => {
|
|
|
145
149
|
testsToRun: [testCase(0)],
|
|
146
150
|
parallelTasks: 2,
|
|
147
151
|
maxRetriesOnFailure: 3,
|
|
152
|
+
rerunTestsNTimes: 0,
|
|
148
153
|
executeTest: async (testCase, isRetry) => {
|
|
149
154
|
if (!isRetry) {
|
|
150
155
|
return (0, mock_test_results_1.testResult)("fail", [(0, mock_test_results_1.diff)(0), (0, mock_test_results_1.diff)(1)], testCase);
|
|
@@ -156,6 +161,31 @@ describe("runAllTestsInParallel", () => {
|
|
|
156
161
|
(0, mock_test_results_1.testResult)("fail", [(0, mock_test_results_1.diff)(0), (0, mock_test_results_1.flake)(1, (0, mock_test_results_1.diff)(), [(0, mock_test_results_1.diff)(), (0, mock_test_results_1.diff)(), (0, mock_test_results_1.diff)()])], testCase(0)),
|
|
157
162
|
]);
|
|
158
163
|
});
|
|
164
|
+
it("retries N times if rerunTestsNTimes > 0", async () => {
|
|
165
|
+
let rerunNum = 0;
|
|
166
|
+
const results = await (0, parallel_tests_handler_1.runAllTestsInParallel)({
|
|
167
|
+
testsToRun: [testCase(0)],
|
|
168
|
+
parallelTasks: 2,
|
|
169
|
+
maxRetriesOnFailure: 0,
|
|
170
|
+
rerunTestsNTimes: 3,
|
|
171
|
+
executeTest: async (testCase, isRetry) => {
|
|
172
|
+
if (!isRetry) {
|
|
173
|
+
return (0, mock_test_results_1.testResult)("pass", [(0, mock_test_results_1.diff)(0), (0, mock_test_results_1.noDiff)(1)], testCase);
|
|
174
|
+
}
|
|
175
|
+
if (rerunNum === 2) {
|
|
176
|
+
return (0, mock_test_results_1.testResult)("fail", [(0, mock_test_results_1.missingHead)(0), (0, mock_test_results_1.diff)(1)], testCase);
|
|
177
|
+
}
|
|
178
|
+
rerunNum++;
|
|
179
|
+
return (0, mock_test_results_1.testResult)("pass", [(0, mock_test_results_1.noDiff)(0), (0, mock_test_results_1.noDiff)(1)], testCase);
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
expect(rerunNum).toEqual(2);
|
|
183
|
+
expect(results).toEqual([
|
|
184
|
+
(0, mock_test_results_1.testResult)(
|
|
185
|
+
// Flake outcome is returned iff all screenshots are flaky.
|
|
186
|
+
"flake", [(0, mock_test_results_1.flake)(0, (0, mock_test_results_1.diff)(), [(0, mock_test_results_1.missingHead)()]), (0, mock_test_results_1.flake)(1, (0, mock_test_results_1.noDiff)(), [(0, mock_test_results_1.diff)()])], testCase(0)),
|
|
187
|
+
]);
|
|
188
|
+
});
|
|
159
189
|
});
|
|
160
190
|
const testCase = (num) => ({
|
|
161
191
|
sessionId: "mock-session-id",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ScreenshotDiffResult } from "@alwaysmeticulous/api";
|
|
2
|
+
import { DetailedTestCaseResult, TestCaseResult } from "../config/config.types";
|
|
2
3
|
export interface ResultsToMerge {
|
|
3
4
|
currentResult: DetailedTestCaseResult;
|
|
4
5
|
/**
|
|
@@ -8,3 +9,4 @@ export interface ResultsToMerge {
|
|
|
8
9
|
comparisonToHeadReplay: DetailedTestCaseResult;
|
|
9
10
|
}
|
|
10
11
|
export declare const mergeResults: ({ currentResult, comparisonToHeadReplay, }: ResultsToMerge) => DetailedTestCaseResult;
|
|
12
|
+
export declare const testRunOutcomeFromDiffResults: (currentResult: TestCaseResult["result"], newScreenshotDiffResults: ScreenshotDiffResult[]) => TestCaseResult["result"];
|
|
@@ -3,9 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.mergeResults = void 0;
|
|
6
|
+
exports.testRunOutcomeFromDiffResults = exports.mergeResults = void 0;
|
|
7
7
|
const utils_1 = require("@sentry/utils");
|
|
8
8
|
const fast_json_stable_stringify_1 = __importDefault(require("fast-json-stable-stringify"));
|
|
9
|
+
const has_notable_differences_1 = require("../commands/screenshot-diff/utils/has-notable-differences");
|
|
9
10
|
const screenshot_diff_results_utils_1 = require("./screenshot-diff-results.utils");
|
|
10
11
|
const mergeResults = ({ currentResult, comparisonToHeadReplay, }) => {
|
|
11
12
|
// If any of the screenshots diffs in comparisonToHeadReplay show a diff against one
|
|
@@ -20,9 +21,6 @@ const mergeResults = ({ currentResult, comparisonToHeadReplay, }) => {
|
|
|
20
21
|
retryDiffById.set(hash, result);
|
|
21
22
|
});
|
|
22
23
|
const newScreenshotDiffResults = (0, screenshot_diff_results_utils_1.flattenScreenshotDiffResults)(currentResult).map((currentDiff) => {
|
|
23
|
-
if (currentDiff.outcome === "no-diff") {
|
|
24
|
-
return currentDiff;
|
|
25
|
-
}
|
|
26
24
|
const hash = hashScreenshotIdentifier(currentDiff.identifier);
|
|
27
25
|
const diffWhenRetrying = retryDiffById.get(hash);
|
|
28
26
|
// diffWhenRetrying is null in the case that there is a base screenshot for the base replay,
|
|
@@ -75,12 +73,9 @@ const mergeResults = ({ currentResult, comparisonToHeadReplay, }) => {
|
|
|
75
73
|
};
|
|
76
74
|
}
|
|
77
75
|
});
|
|
78
|
-
const noLongerHasFailures = newScreenshotDiffResults.every(({ outcome }) => outcome === "flake" || outcome === "no-diff");
|
|
79
76
|
return {
|
|
80
77
|
...currentResult,
|
|
81
|
-
result: currentResult.result
|
|
82
|
-
? "flake"
|
|
83
|
-
: currentResult.result,
|
|
78
|
+
result: (0, exports.testRunOutcomeFromDiffResults)(currentResult.result, newScreenshotDiffResults),
|
|
84
79
|
screenshotDiffResultsByBaseReplayId: (0, screenshot_diff_results_utils_1.groupScreenshotDiffResults)(newScreenshotDiffResults),
|
|
85
80
|
};
|
|
86
81
|
};
|
|
@@ -108,3 +103,20 @@ const hashScreenshotIdentifier = (identifier) => {
|
|
|
108
103
|
const unknownScreenshotIdentifierType = (identifier) => {
|
|
109
104
|
utils_1.logger.error(`Unknown type of screenshot identifier: ${JSON.stringify(identifier)}`);
|
|
110
105
|
};
|
|
106
|
+
const testRunOutcomeFromDiffResults = (currentResult, newScreenshotDiffResults) => {
|
|
107
|
+
// If a test run is already flakey, we don't want to overwrite that with a 'fail' result.
|
|
108
|
+
if (currentResult === "flake") {
|
|
109
|
+
return "flake";
|
|
110
|
+
}
|
|
111
|
+
const hasOnlyFlakes = newScreenshotDiffResults.every(({ outcome }) => outcome === "flake" || outcome === "no-diff");
|
|
112
|
+
if (hasOnlyFlakes) {
|
|
113
|
+
return "flake";
|
|
114
|
+
}
|
|
115
|
+
// If we've had a test run has already failed, we don't want to overwrite that with a 'pass' result.
|
|
116
|
+
// Otherwise, if there are any notable differences, we want to fail the test run.
|
|
117
|
+
return currentResult === "fail" ||
|
|
118
|
+
(0, has_notable_differences_1.hasNotableDifferences)(newScreenshotDiffResults)
|
|
119
|
+
? "fail"
|
|
120
|
+
: "pass";
|
|
121
|
+
};
|
|
122
|
+
exports.testRunOutcomeFromDiffResults = testRunOutcomeFromDiffResults;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import log from "loglevel";
|
|
2
2
|
import { DetailedTestCaseResult } from "../config/config.types";
|
|
3
|
-
import {
|
|
3
|
+
import { ParallelTestsReplayOptions } from "./parallel-replay.types";
|
|
4
4
|
export interface InitMessage {
|
|
5
5
|
kind: "init";
|
|
6
6
|
data: {
|
|
7
7
|
logLevel: log.LogLevel[keyof log.LogLevel];
|
|
8
8
|
dataDir: string;
|
|
9
|
-
replayOptions:
|
|
9
|
+
replayOptions: ParallelTestsReplayOptions;
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
export interface ResultMessage {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { DetailedTestCaseResult } from "../config/config.types";
|
|
2
|
+
import { ParallelTestsReplayOptions } from "./parallel-replay.types";
|
|
3
|
+
export declare const handleReplay: ({ testCase, replayTarget, executionOptions, screenshottingOptions, apiToken, commitSha, generatedBy, testRunId, replayEventsDependencies, suppressScreenshotDiffLogging, baseTestRunId, }: ParallelTestsReplayOptions) => Promise<DetailedTestCaseResult>;
|
package/dist/{deflake-tests/deflake-tests.handler.js → parallel-tests/parallel-replay.handler.js}
RENAMED
|
@@ -1,11 +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"));
|
|
3
|
+
exports.handleReplay = void 0;
|
|
9
4
|
const replay_command_1 = require("../commands/replay/replay.command");
|
|
10
5
|
const has_notable_differences_1 = require("../commands/screenshot-diff/utils/has-notable-differences");
|
|
11
6
|
const handleReplay = async ({ testCase, replayTarget, executionOptions, screenshottingOptions, apiToken, commitSha, generatedBy, testRunId, replayEventsDependencies, suppressScreenshotDiffLogging, baseTestRunId, }) => {
|
|
@@ -35,21 +30,7 @@ const handleReplay = async ({ testCase, replayTarget, executionOptions, screensh
|
|
|
35
30
|
screenshotDiffResultsByBaseReplayId,
|
|
36
31
|
};
|
|
37
32
|
};
|
|
38
|
-
|
|
39
|
-
const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
|
|
40
|
-
const firstResult = await handleReplay(otherOptions);
|
|
41
|
-
if (firstResult.result === "pass" || !deflake) {
|
|
42
|
-
return firstResult;
|
|
43
|
-
}
|
|
44
|
-
const secondResult = await handleReplay(otherOptions);
|
|
45
|
-
if (secondResult.result === "fail") {
|
|
46
|
-
return secondResult;
|
|
47
|
-
}
|
|
48
|
-
const thirdResult = await handleReplay(otherOptions);
|
|
49
|
-
logger.info(`FLAKE: ${thirdResult.title} => ${thirdResult.result}`);
|
|
50
|
-
return thirdResult;
|
|
51
|
-
};
|
|
52
|
-
exports.deflakeReplayCommandHandler = deflakeReplayCommandHandler;
|
|
33
|
+
exports.handleReplay = handleReplay;
|
|
53
34
|
const applyTestCaseExecutionOptionOverrides = (executionOptionsFromCliFlags, overridesFromTestCase) => {
|
|
54
35
|
var _a;
|
|
55
36
|
// Options specified in the test case override those passed as CLI flags
|
package/dist/{deflake-tests/deflake-tests.handler.d.ts → parallel-tests/parallel-replay.types.d.ts}
RENAMED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { TestCase } from "@alwaysmeticulous/api";
|
|
2
2
|
import { GeneratedBy, ReplayEventsDependencies, ReplayExecutionOptions, ReplayTarget } from "@alwaysmeticulous/common";
|
|
3
3
|
import { ScreenshotAssertionsEnabledOptions } from "../command-utils/common-types";
|
|
4
|
-
|
|
5
|
-
export interface DeflakeReplayCommandHandlerOptions extends HandleReplayOptions {
|
|
6
|
-
deflake: boolean;
|
|
7
|
-
}
|
|
8
|
-
interface HandleReplayOptions {
|
|
4
|
+
export interface ParallelTestsReplayOptions {
|
|
9
5
|
replayTarget: ReplayTarget;
|
|
10
6
|
executionOptions: ReplayExecutionOptions;
|
|
11
7
|
screenshottingOptions: ScreenshotAssertionsEnabledOptions;
|
|
@@ -18,5 +14,3 @@ interface HandleReplayOptions {
|
|
|
18
14
|
replayEventsDependencies: ReplayEventsDependencies;
|
|
19
15
|
suppressScreenshotDiffLogging: boolean;
|
|
20
16
|
}
|
|
21
|
-
export declare const deflakeReplayCommandHandler: ({ deflake, ...otherOptions }: DeflakeReplayCommandHandlerOptions) => Promise<DetailedTestCaseResult>;
|
|
22
|
-
export {};
|
|
@@ -5,6 +5,7 @@ export interface RunAllTestsInParallelOptions {
|
|
|
5
5
|
testsToRun: TestCase[];
|
|
6
6
|
parallelTasks: number | null;
|
|
7
7
|
maxRetriesOnFailure: number;
|
|
8
|
+
rerunTestsNTimes: number;
|
|
8
9
|
executeTest: (testCase: TestCase, isRetry: boolean) => Promise<DetailedTestCaseResult>;
|
|
9
10
|
onTestFinished?: (progress: TestRunProgress, resultsSoFar: DetailedTestCaseResult[]) => Promise<void>;
|
|
10
11
|
onTestFailedToRun?: (progress: TestRunProgress) => Promise<void>;
|
|
@@ -10,7 +10,10 @@ const loglevel_1 = __importDefault(require("loglevel"));
|
|
|
10
10
|
const merge_test_results_1 = require("./merge-test-results");
|
|
11
11
|
const screenshot_diff_results_utils_1 = require("./screenshot-diff-results.utils");
|
|
12
12
|
/** Handler for running Meticulous tests in parallel using child processes */
|
|
13
|
-
const runAllTestsInParallel = async ({ testsToRun, parallelTasks, maxRetriesOnFailure, executeTest, onTestFinished, onTestFailedToRun, }) => {
|
|
13
|
+
const runAllTestsInParallel = async ({ testsToRun, parallelTasks, maxRetriesOnFailure, rerunTestsNTimes, executeTest, onTestFinished, onTestFailedToRun, }) => {
|
|
14
|
+
if (maxRetriesOnFailure && rerunTestsNTimes) {
|
|
15
|
+
throw new Error("maxRetriesOnFailure and rerunTestsNTimes are mutually exclusive.");
|
|
16
|
+
}
|
|
14
17
|
const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
|
|
15
18
|
let nextId = 0;
|
|
16
19
|
let queue = testsToRun.map((test) => ({
|
|
@@ -47,8 +50,16 @@ const runAllTestsInParallel = async ({ testsToRun, parallelTasks, maxRetriesOnFa
|
|
|
47
50
|
.then(async (result) => {
|
|
48
51
|
var _a;
|
|
49
52
|
const resultsForTestCase = resultsByTestId.get(id);
|
|
53
|
+
// Re-run the test if needed, comparing to the base replay.
|
|
54
|
+
if (!isRetry) {
|
|
55
|
+
queue.push(...Array.from(new Array(rerunTestsNTimes)).map(() => ({
|
|
56
|
+
...testCase,
|
|
57
|
+
id,
|
|
58
|
+
baseReplayId: result === null || result === void 0 ? void 0 : result.headReplayId,
|
|
59
|
+
})));
|
|
60
|
+
}
|
|
50
61
|
if (resultsForTestCase != null && result != null) {
|
|
51
|
-
logRetrySummary(testName({ id, ...testCase }), result);
|
|
62
|
+
logRetrySummary(testName({ id, ...testCase }), result, resultsForTestCase.currentResult);
|
|
52
63
|
}
|
|
53
64
|
if (resultsForTestCase != null &&
|
|
54
65
|
resultsForTestCase.currentResult.result === "flake") {
|
|
@@ -81,8 +92,15 @@ const runAllTestsInParallel = async ({ testsToRun, parallelTasks, maxRetriesOnFa
|
|
|
81
92
|
// Our work is done for this test case if the first result was a pass,
|
|
82
93
|
// we've performed all the retries, or one of the retries already proved
|
|
83
94
|
// the result as flakey
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
let isFinalResult;
|
|
96
|
+
if (rerunTestsNTimes > 0) {
|
|
97
|
+
isFinalResult = numberOfRetriesExecuted >= rerunTestsNTimes;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
isFinalResult =
|
|
101
|
+
mergedResult.result !== "fail" ||
|
|
102
|
+
numberOfRetriesExecuted >= maxRetriesOnFailure;
|
|
103
|
+
}
|
|
86
104
|
if (isFinalResult) {
|
|
87
105
|
// Cancel any replays that are still scheduled
|
|
88
106
|
queue = queue.filter((otherReplay) => otherReplay.id !== id);
|
|
@@ -119,7 +137,12 @@ const runAllTestsInParallel = async ({ testsToRun, parallelTasks, maxRetriesOnFa
|
|
|
119
137
|
}
|
|
120
138
|
++inProgress;
|
|
121
139
|
if (resultsByTestId.has(testCase.id)) {
|
|
122
|
-
|
|
140
|
+
if (maxRetriesOnFailure > 0) {
|
|
141
|
+
logger.info(`Test ${testName(testCase)} failed. Retrying to check for flakes...`);
|
|
142
|
+
}
|
|
143
|
+
else if (rerunTestsNTimes > 0) {
|
|
144
|
+
logger.info(`Re-running ${testName(testCase)} to check for flakes...`);
|
|
145
|
+
}
|
|
123
146
|
}
|
|
124
147
|
startTask(testCase);
|
|
125
148
|
process.nextTick(checkNextTask);
|
|
@@ -129,10 +152,10 @@ const runAllTestsInParallel = async ({ testsToRun, parallelTasks, maxRetriesOnFa
|
|
|
129
152
|
return finalResults;
|
|
130
153
|
};
|
|
131
154
|
exports.runAllTestsInParallel = runAllTestsInParallel;
|
|
132
|
-
const logRetrySummary = (nameOfTest, retryResult) => {
|
|
155
|
+
const logRetrySummary = (nameOfTest, retryResult, resultSoFar) => {
|
|
133
156
|
const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
|
|
134
157
|
if (retryResult.result === "pass") {
|
|
135
|
-
logger.info(`Retried taking screenshots for failed test ${nameOfTest}, but got the same results`);
|
|
158
|
+
logger.info(`Retried taking screenshots for${resultSoFar.result == "fail" ? " failed" : ""} test ${nameOfTest}, but got the same results`);
|
|
136
159
|
}
|
|
137
160
|
else {
|
|
138
161
|
const numDifferingScreenshots = (0, screenshot_diff_results_utils_1.flattenScreenshotDiffResults)(retryResult).filter((result) => result.outcome !== "no-diff").length;
|
|
@@ -25,13 +25,22 @@ export interface Options {
|
|
|
25
25
|
* Set to 1 to disable parralelism.
|
|
26
26
|
*/
|
|
27
27
|
parallelTasks: number | null;
|
|
28
|
-
deflake: boolean;
|
|
29
28
|
/**
|
|
30
29
|
* If set to a value greater than 1 then will re-run any replays that give a screenshot diff
|
|
31
30
|
* and mark them as a flake if the screenshot generated on one of the retryed replays differs from that
|
|
32
31
|
* in the first replay.
|
|
33
32
|
*/
|
|
34
33
|
maxRetriesOnFailure: number;
|
|
34
|
+
/**
|
|
35
|
+
* If set to a value greater than 0 then will re-run all replays the specified number of times
|
|
36
|
+
* and mark them as a flake if the screenshot generated on one of the retryed replays differs from that
|
|
37
|
+
* in the first replay.
|
|
38
|
+
*
|
|
39
|
+
* This is useful for checking flake rates.
|
|
40
|
+
*
|
|
41
|
+
* This option is mutually exclusive with maxRetriesOnFailure.
|
|
42
|
+
*/
|
|
43
|
+
rerunTestsNTimes: number;
|
|
35
44
|
githubSummary: boolean;
|
|
36
45
|
/**
|
|
37
46
|
* If provided it will incorportate the cachedTestRunResults in any calls to store
|
|
@@ -61,4 +70,4 @@ export interface RunAllTestsResult {
|
|
|
61
70
|
* Runs all the test cases in the provided file.
|
|
62
71
|
* @returns The results of the tests that were executed (note that this does not include results from any cachedTestRunResults passed in)
|
|
63
72
|
*/
|
|
64
|
-
export declare const runAllTests: ({ testsFile, apiToken, commitSha, baseCommitSha, appUrl, executionOptions, screenshottingOptions, parallelTasks,
|
|
73
|
+
export declare const runAllTests: ({ testsFile, apiToken, commitSha, baseCommitSha, appUrl, executionOptions, screenshottingOptions, parallelTasks, maxRetriesOnFailure, rerunTestsNTimes, cachedTestRunResults: cachedTestRunResults_, githubSummary, environment, baseTestRunId, onTestRunCreated, onTestFinished: onTestFinished_, }: Options) => Promise<RunAllTestsResult>;
|
|
@@ -12,21 +12,18 @@ const replay_diff_api_1 = require("../api/replay-diff.api");
|
|
|
12
12
|
const test_run_api_1 = require("../api/test-run.api");
|
|
13
13
|
const config_1 = require("../config/config");
|
|
14
14
|
const replay_assets_1 = require("../local-data/replay-assets");
|
|
15
|
-
const parallel_tests_handler_1 = require("../parallel-tests/parallel-tests.handler");
|
|
16
15
|
const config_utils_1 = require("../utils/config.utils");
|
|
17
16
|
const github_summary_utils_1 = require("../utils/github-summary.utils");
|
|
18
17
|
const run_all_tests_utils_1 = require("../utils/run-all-tests.utils");
|
|
19
18
|
const test_run_environment_utils_1 = require("../utils/test-run-environment.utils");
|
|
20
19
|
const version_utils_1 = require("../utils/version.utils");
|
|
21
20
|
const execute_test_in_child_process_1 = require("./execute-test-in-child-process");
|
|
21
|
+
const parallel_tests_handler_1 = require("./parallel-tests.handler");
|
|
22
22
|
/**
|
|
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, executionOptions, screenshottingOptions, parallelTasks,
|
|
27
|
-
if (deflake && maxRetriesOnFailure > 1) {
|
|
28
|
-
throw new Error("Arguments deflake and maxRetriesOnFailure are mutually exclusive");
|
|
29
|
-
}
|
|
26
|
+
const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appUrl, executionOptions, screenshottingOptions, parallelTasks, maxRetriesOnFailure, rerunTestsNTimes, cachedTestRunResults: cachedTestRunResults_, githubSummary, environment, baseTestRunId, onTestRunCreated, onTestFinished: onTestFinished_, }) => {
|
|
30
27
|
const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
|
|
31
28
|
const client = (0, client_1.createClient)({ apiToken });
|
|
32
29
|
const project = await (0, project_api_1.getProject)(client);
|
|
@@ -60,7 +57,6 @@ const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appU
|
|
|
60
57
|
baseCommitSha,
|
|
61
58
|
appUrl,
|
|
62
59
|
parallelTasks,
|
|
63
|
-
deflake,
|
|
64
60
|
githubSummary,
|
|
65
61
|
},
|
|
66
62
|
environment: (0, test_run_environment_utils_1.getEnvironment)(environment),
|
|
@@ -145,6 +141,7 @@ const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appU
|
|
|
145
141
|
testsToRun,
|
|
146
142
|
parallelTasks,
|
|
147
143
|
maxRetriesOnFailure,
|
|
144
|
+
rerunTestsNTimes,
|
|
148
145
|
executeTest: (testCase, isRetry) => {
|
|
149
146
|
var _a;
|
|
150
147
|
const initMessage = {
|
|
@@ -156,7 +153,6 @@ const runAllTests = async ({ testsFile, apiToken, commitSha, baseCommitSha, appU
|
|
|
156
153
|
apiToken,
|
|
157
154
|
commitSha,
|
|
158
155
|
testCase,
|
|
159
|
-
deflake,
|
|
160
156
|
replayTarget: (0, config_utils_1.getReplayTargetForTestCase)({
|
|
161
157
|
appUrl,
|
|
162
158
|
testCase,
|
|
@@ -30,9 +30,9 @@ const common_1 = require("@alwaysmeticulous/common");
|
|
|
30
30
|
const Sentry = __importStar(require("@sentry/node"));
|
|
31
31
|
const loglevel_1 = __importDefault(require("loglevel"));
|
|
32
32
|
const luxon_1 = require("luxon");
|
|
33
|
-
const deflake_tests_handler_1 = require("../deflake-tests/deflake-tests.handler");
|
|
34
33
|
const logger_utils_1 = require("../utils/logger.utils");
|
|
35
34
|
const sentry_utils_1 = require("../utils/sentry.utils");
|
|
35
|
+
const parallel_replay_handler_1 = require("./parallel-replay.handler");
|
|
36
36
|
const INIT_TIMEOUT = luxon_1.Duration.fromObject({ second: 1 });
|
|
37
37
|
const waitForInitMessage = () => {
|
|
38
38
|
return Promise.race([
|
|
@@ -67,7 +67,7 @@ const main = async () => {
|
|
|
67
67
|
const { logLevel, dataDir, replayOptions } = initMessage.data;
|
|
68
68
|
logger.setLevel(logLevel);
|
|
69
69
|
(0, common_1.setMeticulousLocalDataDir)(dataDir);
|
|
70
|
-
const result = await (0,
|
|
70
|
+
const result = await (0, parallel_replay_handler_1.handleReplay)(replayOptions);
|
|
71
71
|
const resultMessage = {
|
|
72
72
|
kind: "result",
|
|
73
73
|
data: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alwaysmeticulous/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.39.0",
|
|
4
4
|
"description": "The Meticulous CLI",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"test": "jest"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@alwaysmeticulous/common": "^2.
|
|
29
|
+
"@alwaysmeticulous/common": "^2.39.0",
|
|
30
30
|
"@sentry/node": "^7.36.0",
|
|
31
31
|
"@sentry/tracing": "^7.36.0",
|
|
32
32
|
"adm-zip": "^0.5.9",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"yargs": "^17.5.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@alwaysmeticulous/api": "^2.
|
|
48
|
+
"@alwaysmeticulous/api": "^2.39.0",
|
|
49
49
|
"@types/express": "^4.17.14",
|
|
50
50
|
"@types/proper-lockfile": "^4.1.2"
|
|
51
51
|
},
|
|
@@ -95,5 +95,5 @@
|
|
|
95
95
|
"coverageDirectory": "../coverage",
|
|
96
96
|
"testEnvironment": "node"
|
|
97
97
|
},
|
|
98
|
-
"gitHead": "
|
|
98
|
+
"gitHead": "b6488b15a8233fcd1380b1607ec254d5d3bc0378"
|
|
99
99
|
}
|