@alwaysmeticulous/cli 2.40.0 → 2.41.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.
Files changed (121) hide show
  1. package/dist/api/test-run.api.d.ts +3 -31
  2. package/dist/api/test-run.api.js +3 -96
  3. package/dist/commands/download-replay/download-replay.command.js +4 -4
  4. package/dist/commands/download-session/download-session.command.js +4 -4
  5. package/dist/commands/record/record.command.js +8 -11
  6. package/dist/commands/replay/replay.command.d.ts +11 -20
  7. package/dist/commands/replay/replay.command.js +20 -235
  8. package/dist/commands/run-all-tests/run-all-tests.command.js +5 -5
  9. package/dist/commands/show-project/show-project.command.js +2 -3
  10. package/dist/index.d.ts +0 -7
  11. package/dist/index.js +1 -13
  12. package/dist/main.js +5 -11
  13. package/dist/utils/sentry.utils.d.ts +0 -4
  14. package/dist/utils/sentry.utils.js +3 -23
  15. package/package.json +14 -32
  16. package/dist/api/client.d.ts +0 -5
  17. package/dist/api/client.js +0 -32
  18. package/dist/api/download.d.ts +0 -1
  19. package/dist/api/download.js +0 -21
  20. package/dist/api/project.api.d.ts +0 -3
  21. package/dist/api/project.api.js +0 -22
  22. package/dist/api/replay-diff.api.d.ts +0 -13
  23. package/dist/api/replay-diff.api.js +0 -32
  24. package/dist/api/replay.api.d.ts +0 -36
  25. package/dist/api/replay.api.js +0 -89
  26. package/dist/api/session.api.d.ts +0 -6
  27. package/dist/api/session.api.js +0 -45
  28. package/dist/api/types.d.ts +0 -39
  29. package/dist/api/types.js +0 -2
  30. package/dist/api/upload.d.ts +0 -1
  31. package/dist/api/upload.js +0 -18
  32. package/dist/archive/archive.d.ts +0 -4
  33. package/dist/archive/archive.js +0 -64
  34. package/dist/command-utils/common-types.d.ts +0 -20
  35. package/dist/command-utils/common-types.js +0 -2
  36. package/dist/commands/bootstrap/bootstrap.command.d.ts +0 -2
  37. package/dist/commands/bootstrap/bootstrap.command.js +0 -33
  38. package/dist/commands/create-test/create-test.command.d.ts +0 -90
  39. package/dist/commands/create-test/create-test.command.js +0 -165
  40. package/dist/commands/replay/utils/compute-diff.d.ts +0 -13
  41. package/dist/commands/replay/utils/compute-diff.js +0 -95
  42. package/dist/commands/replay/utils/exit-early-if-skip-upload-env-var-set.d.ts +0 -1
  43. package/dist/commands/replay/utils/exit-early-if-skip-upload-env-var-set.js +0 -27
  44. package/dist/commands/screenshot-diff/screenshot-diff.command.d.ts +0 -53
  45. package/dist/commands/screenshot-diff/screenshot-diff.command.js +0 -182
  46. package/dist/commands/screenshot-diff/utils/__tests__/get-screenshot-identifier.spec.d.ts +0 -1
  47. package/dist/commands/screenshot-diff/utils/__tests__/get-screenshot-identifier.spec.js +0 -25
  48. package/dist/commands/screenshot-diff/utils/get-screenshot-filename.d.ts +0 -2
  49. package/dist/commands/screenshot-diff/utils/get-screenshot-filename.js +0 -22
  50. package/dist/commands/screenshot-diff/utils/get-screenshot-identifier.d.ts +0 -2
  51. package/dist/commands/screenshot-diff/utils/get-screenshot-identifier.js +0 -39
  52. package/dist/commands/screenshot-diff/utils/has-notable-differences.d.ts +0 -2
  53. package/dist/commands/screenshot-diff/utils/has-notable-differences.js +0 -10
  54. package/dist/commands/serve/serve.command.d.ts +0 -10
  55. package/dist/commands/serve/serve.command.js +0 -31
  56. package/dist/commands/update-tests/update-tests.command.d.ts +0 -21
  57. package/dist/commands/update-tests/update-tests.command.js +0 -96
  58. package/dist/config/config.d.ts +0 -3
  59. package/dist/config/config.js +0 -69
  60. package/dist/config/config.types.d.ts +0 -16
  61. package/dist/config/config.types.js +0 -2
  62. package/dist/config/snippets.d.ts +0 -1
  63. package/dist/config/snippets.js +0 -18
  64. package/dist/errors/config.d.ts +0 -3
  65. package/dist/errors/config.js +0 -10
  66. package/dist/image/diff.utils.d.ts +0 -19
  67. package/dist/image/diff.utils.js +0 -25
  68. package/dist/image/io.utils.d.ts +0 -3
  69. package/dist/image/io.utils.js +0 -25
  70. package/dist/local-data/local-data.utils.d.ts +0 -20
  71. package/dist/local-data/local-data.utils.js +0 -92
  72. package/dist/local-data/replay-assets.d.ts +0 -3
  73. package/dist/local-data/replay-assets.js +0 -94
  74. package/dist/local-data/replays.d.ts +0 -18
  75. package/dist/local-data/replays.js +0 -87
  76. package/dist/local-data/screenshot-diffs.d.ts +0 -7
  77. package/dist/local-data/screenshot-diffs.js +0 -20
  78. package/dist/local-data/serve-assets-from-simulation.d.ts +0 -5
  79. package/dist/local-data/serve-assets-from-simulation.js +0 -52
  80. package/dist/local-data/sessions.d.ts +0 -10
  81. package/dist/local-data/sessions.js +0 -41
  82. package/dist/parallel-tests/__tests__/merge-test-results.spec.d.ts +0 -1
  83. package/dist/parallel-tests/__tests__/merge-test-results.spec.js +0 -104
  84. package/dist/parallel-tests/__tests__/mock-test-results.d.ts +0 -17
  85. package/dist/parallel-tests/__tests__/mock-test-results.js +0 -106
  86. package/dist/parallel-tests/__tests__/parrallel-tests.handler.spec.d.ts +0 -1
  87. package/dist/parallel-tests/__tests__/parrallel-tests.handler.spec.js +0 -205
  88. package/dist/parallel-tests/execute-test-in-child-process.d.ts +0 -3
  89. package/dist/parallel-tests/execute-test-in-child-process.js +0 -44
  90. package/dist/parallel-tests/merge-test-results.d.ts +0 -12
  91. package/dist/parallel-tests/merge-test-results.js +0 -106
  92. package/dist/parallel-tests/messages.types.d.ts +0 -17
  93. package/dist/parallel-tests/messages.types.js +0 -2
  94. package/dist/parallel-tests/parallel-replay.handler.d.ts +0 -3
  95. package/dist/parallel-tests/parallel-replay.handler.js +0 -56
  96. package/dist/parallel-tests/parallel-replay.types.d.ts +0 -16
  97. package/dist/parallel-tests/parallel-replay.types.js +0 -2
  98. package/dist/parallel-tests/parallel-tests.handler.d.ts +0 -14
  99. package/dist/parallel-tests/parallel-tests.handler.js +0 -194
  100. package/dist/parallel-tests/run-all-tests.d.ts +0 -73
  101. package/dist/parallel-tests/run-all-tests.js +0 -237
  102. package/dist/parallel-tests/run-all-tests.types.d.ts +0 -6
  103. package/dist/parallel-tests/run-all-tests.types.js +0 -2
  104. package/dist/parallel-tests/screenshot-diff-results.utils.d.ts +0 -7
  105. package/dist/parallel-tests/screenshot-diff-results.utils.js +0 -20
  106. package/dist/parallel-tests/task.handler.d.ts +0 -1
  107. package/dist/parallel-tests/task.handler.js +0 -86
  108. package/dist/utils/api-token.utils.d.ts +0 -1
  109. package/dist/utils/api-token.utils.js +0 -31
  110. package/dist/utils/commit-sha.utils.d.ts +0 -1
  111. package/dist/utils/commit-sha.utils.js +0 -42
  112. package/dist/utils/config.utils.d.ts +0 -7
  113. package/dist/utils/config.utils.js +0 -33
  114. package/dist/utils/github-summary.utils.d.ts +0 -5
  115. package/dist/utils/github-summary.utils.js +0 -38
  116. package/dist/utils/run-all-tests.utils.d.ts +0 -16
  117. package/dist/utils/run-all-tests.utils.js +0 -32
  118. package/dist/utils/test-run-environment.utils.d.ts +0 -2
  119. package/dist/utils/test-run-environment.utils.js +0 -25
  120. package/dist/utils/version.utils.d.ts +0 -1
  121. package/dist/utils/version.utils.js +0 -17
@@ -1,35 +1,7 @@
1
- import { TestRunConfigData } from "@alwaysmeticulous/api";
1
+ import { TestCaseResult } from "@alwaysmeticulous/api";
2
2
  import { AxiosInstance } from "axios";
3
- import { TestCaseResult } from "../config/config.types";
4
- import { ScreenshotLocator, TestRun, TestRunStatus } from "./types";
5
- export declare const getTestRun: (options: {
6
- client: AxiosInstance;
7
- testRunId: string;
8
- }) => Promise<TestRun | null>;
9
- export declare const createTestRun: (options: {
10
- client: AxiosInstance;
11
- commitSha: string;
12
- meticulousSha: string;
13
- configData: TestRunConfigData;
14
- }) => Promise<TestRun>;
15
- export declare const putTestRunResults: (options: {
16
- client: AxiosInstance;
17
- testRunId: string;
18
- status: TestRunStatus;
19
- resultData: {
20
- [key: string]: any;
21
- };
22
- }) => Promise<TestRun>;
23
- export declare const getTestRunUrl: (testRun: TestRun) => string;
24
- export interface GetLatestTestRunResultsOptions {
3
+ export interface GetCachedTestRunResultsOptions {
25
4
  client: AxiosInstance;
26
5
  commitSha: string;
27
6
  }
28
- export declare const getCachedTestRunResults: ({ client, commitSha, }: GetLatestTestRunResultsOptions) => Promise<TestCaseResult[]>;
29
- export declare const getLatestTestRunId: (opts: GetLatestTestRunResultsOptions) => Promise<string | null>;
30
- export interface GetBaseScreenshotLocatorsOptions {
31
- client: AxiosInstance;
32
- testRunId: string;
33
- sessionId: string;
34
- }
35
- export declare const getBaseScreenshots: ({ client, testRunId, sessionId, }: GetBaseScreenshotLocatorsOptions) => Promise<ScreenshotLocator[]>;
7
+ export declare const getCachedTestRunResults: ({ client, commitSha, }: GetCachedTestRunResultsOptions) => Promise<TestCaseResult[]>;
@@ -1,73 +1,12 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.getBaseScreenshots = exports.getLatestTestRunId = exports.getCachedTestRunResults = exports.getTestRunUrl = exports.putTestRunResults = exports.createTestRun = exports.getTestRun = void 0;
6
+ exports.getCachedTestRunResults = void 0;
7
+ const client_1 = require("@alwaysmeticulous/client");
30
8
  const common_1 = require("@alwaysmeticulous/common");
31
- const axios_1 = __importStar(require("axios"));
32
9
  const loglevel_1 = __importDefault(require("loglevel"));
33
- const getTestRun = async ({ client, testRunId }) => {
34
- const { data } = await client.get(`test-runs/${testRunId}`).catch((error) => {
35
- var _a;
36
- if (axios_1.default.isAxiosError(error)) {
37
- if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
38
- return { data: null };
39
- }
40
- }
41
- throw error;
42
- });
43
- return data;
44
- };
45
- exports.getTestRun = getTestRun;
46
- const createTestRun = async ({ client, commitSha, meticulousSha, configData, }) => {
47
- const { data } = await client.post("test-runs", {
48
- commitSha,
49
- meticulousSha,
50
- configData,
51
- });
52
- return data;
53
- };
54
- exports.createTestRun = createTestRun;
55
- const putTestRunResults = async ({ client, testRunId, status, resultData }) => {
56
- const { data } = await client.put(`test-runs/${testRunId}/results`, {
57
- status,
58
- resultData,
59
- });
60
- return data;
61
- };
62
- exports.putTestRunResults = putTestRunResults;
63
- const getTestRunUrl = (testRun) => {
64
- const { project } = testRun;
65
- const organizationName = encodeURIComponent(project.organization.name);
66
- const projectName = encodeURIComponent(project.name);
67
- const testRunUrl = `https://app.meticulous.ai/projects/${organizationName}/${projectName}/test-runs/${testRun.id}`;
68
- return testRunUrl;
69
- };
70
- exports.getTestRunUrl = getTestRunUrl;
71
10
  const getCachedTestRunResults = async ({ client, commitSha, }) => {
72
11
  var _a, _b, _c;
73
12
  const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
@@ -75,40 +14,8 @@ const getCachedTestRunResults = async ({ client, commitSha, }) => {
75
14
  logger.warn("Test run cache not supported: no commit hash");
76
15
  return [];
77
16
  }
78
- const results = (_c = (_b = (_a = (await getLatestTestRunResults({ client, commitSha }))) === null || _a === void 0 ? void 0 : _a.resultData) === null || _b === void 0 ? void 0 : _b.results) !== null && _c !== void 0 ? _c : [];
17
+ const results = (_c = (_b = (_a = (await (0, client_1.getLatestTestRunResults)({ client, commitSha }))) === null || _a === void 0 ? void 0 : _a.resultData) === null || _b === void 0 ? void 0 : _b.results) !== null && _c !== void 0 ? _c : [];
79
18
  // Only return passing tests
80
19
  return results.filter(({ result }) => result === "pass");
81
20
  };
82
21
  exports.getCachedTestRunResults = getCachedTestRunResults;
83
- const getLatestTestRunResults = async ({ client, commitSha, }) => {
84
- var _a;
85
- const { data } = await client
86
- .get(`test-runs/cache?commitSha=${encodeURIComponent(commitSha)}`)
87
- .catch((error) => {
88
- var _a;
89
- if (error instanceof axios_1.AxiosError && ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
90
- return { data: null };
91
- }
92
- throw error;
93
- });
94
- return (_a = data) !== null && _a !== void 0 ? _a : null;
95
- };
96
- const getLatestTestRunId = async (opts) => {
97
- var _a, _b;
98
- return (_b = (_a = (await getLatestTestRunResults(opts))) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : null;
99
- };
100
- exports.getLatestTestRunId = getLatestTestRunId;
101
- const getBaseScreenshots = async ({ client, testRunId, sessionId, }) => {
102
- var _a;
103
- const { data } = await client
104
- .get(`test-runs/${encodeURIComponent(testRunId)}/base-screenshots?sessionId=${encodeURIComponent(sessionId)}`)
105
- .catch((error) => {
106
- var _a;
107
- if (error instanceof axios_1.AxiosError && ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
108
- return { data: null };
109
- }
110
- throw error;
111
- });
112
- return (_a = data) !== null && _a !== void 0 ? _a : [];
113
- };
114
- exports.getBaseScreenshots = getBaseScreenshots;
@@ -4,17 +4,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.downloadReplayCommand = void 0;
7
+ const client_1 = require("@alwaysmeticulous/client");
7
8
  const common_1 = require("@alwaysmeticulous/common");
9
+ const downloading_helpers_1 = require("@alwaysmeticulous/downloading-helpers");
8
10
  const loglevel_1 = __importDefault(require("loglevel"));
9
- const client_1 = require("../../api/client");
10
11
  const command_builder_1 = require("../../command-utils/command-builder");
11
- const replays_1 = require("../../local-data/replays");
12
12
  const handler = async ({ apiToken, replayId, }) => {
13
13
  const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
14
14
  const client = (0, client_1.createClient)({ apiToken });
15
- const { fileName: replayMetadataFileName } = await (0, replays_1.getOrFetchReplay)(client, replayId);
15
+ const { fileName: replayMetadataFileName } = await (0, downloading_helpers_1.getOrFetchReplay)(client, replayId);
16
16
  logger.info(`Downloaded replay metadata to: ${replayMetadataFileName}`);
17
- const { fileName: replayFolderFilePath } = await (0, replays_1.getOrFetchReplayArchive)(client, replayId);
17
+ const { fileName: replayFolderFilePath } = await (0, downloading_helpers_1.getOrFetchReplayArchive)(client, replayId);
18
18
  logger.info(`Downloaded replay data to: ${replayFolderFilePath}`);
19
19
  };
20
20
  exports.downloadReplayCommand = (0, command_builder_1.buildCommand)("download-simulation")
@@ -4,17 +4,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.downloadSessionCommand = void 0;
7
+ const client_1 = require("@alwaysmeticulous/client");
7
8
  const common_1 = require("@alwaysmeticulous/common");
9
+ const downloading_helpers_1 = require("@alwaysmeticulous/downloading-helpers");
8
10
  const loglevel_1 = __importDefault(require("loglevel"));
9
- const client_1 = require("../../api/client");
10
11
  const command_builder_1 = require("../../command-utils/command-builder");
11
- const sessions_1 = require("../../local-data/sessions");
12
12
  const handler = async ({ apiToken, sessionId, }) => {
13
13
  const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
14
14
  const client = (0, client_1.createClient)({ apiToken });
15
- const { fileName: sessionMetadataFileName } = await (0, sessions_1.getOrFetchRecordedSession)(client, sessionId);
15
+ const { fileName: sessionMetadataFileName } = await (0, downloading_helpers_1.getOrFetchRecordedSession)(client, sessionId);
16
16
  logger.info(`Downloaded session metadata to: ${sessionMetadataFileName}`);
17
- const { fileName: sessionFileName } = await (0, sessions_1.getOrFetchRecordedSessionData)(client, sessionId);
17
+ const { fileName: sessionFileName } = await (0, downloading_helpers_1.getOrFetchRecordedSessionData)(client, sessionId);
18
18
  logger.info(`Downloaded session data to: ${sessionFileName}`);
19
19
  };
20
20
  exports.downloadSessionCommand = (0, command_builder_1.buildCommand)("download-session")
@@ -5,14 +5,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.recordCommand = exports.recordCommandHandler = void 0;
7
7
  const path_1 = require("path");
8
+ const client_1 = require("@alwaysmeticulous/client");
8
9
  const common_1 = require("@alwaysmeticulous/common");
10
+ const downloading_helpers_1 = require("@alwaysmeticulous/downloading-helpers");
9
11
  const loglevel_1 = __importDefault(require("loglevel"));
10
- const client_1 = require("../../api/client");
11
- const project_api_1 = require("../../api/project.api");
12
- const session_api_1 = require("../../api/session.api");
13
12
  const command_builder_1 = require("../../command-utils/command-builder");
14
- const replay_assets_1 = require("../../local-data/replay-assets");
15
- const commit_sha_utils_1 = require("../../utils/commit-sha.utils");
16
13
  const recordCommandHandler = async ({ apiToken, commitSha: commitSha_, devTools, bypassCSP, width, height, uploadIntervalMs, incognito, trace, onDetectedSession: onDetectedSession_, }) => {
17
14
  const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
18
15
  const debugLogger = trace ? await common_1.DebugLogger.create() : null;
@@ -30,7 +27,7 @@ const recordCommandHandler = async ({ apiToken, commitSha: commitSha_, devTools,
30
27
  logger.info("Preparing recording...");
31
28
  // 1. Fetch the recording token
32
29
  const client = (0, client_1.createClient)({ apiToken });
33
- const project = await (0, project_api_1.getProject)(client);
30
+ const project = await (0, client_1.getProject)(client);
34
31
  if (!project) {
35
32
  logger.error("Could not retrieve project data. Is the API token correct?");
36
33
  debugLogger === null || debugLogger === void 0 ? void 0 : debugLogger.log("Could not retrieve project data. Is the API token correct?");
@@ -44,11 +41,11 @@ const recordCommandHandler = async ({ apiToken, commitSha: commitSha_, devTools,
44
41
  }
45
42
  logger.debug(`Recording token: ${recordingToken}`);
46
43
  // 2. Guess commit SHA1
47
- const commitSha = (await (0, commit_sha_utils_1.getCommitSha)(commitSha_)) || "unknown";
44
+ const commitSha = (await (0, common_1.getCommitSha)(commitSha_)) || "unknown";
48
45
  logger.debug(`Commit: ${commitSha}`);
49
46
  // 3. Load recording snippets
50
- const recordingSnippet = await (0, replay_assets_1.fetchAsset)("v1/stagingMeticulousSnippet.js");
51
- const earlyNetworkRecorderSnippet = await (0, replay_assets_1.fetchAsset)("record/v1/network-recorder.bundle.js");
47
+ const recordingSnippet = await (0, downloading_helpers_1.fetchAsset)("v1/stagingMeticulousSnippet.js");
48
+ const earlyNetworkRecorderSnippet = await (0, downloading_helpers_1.fetchAsset)("record/v1/network-recorder.bundle.js");
52
49
  // 4. Load recording package
53
50
  let recordSession;
54
51
  try {
@@ -64,13 +61,13 @@ const recordCommandHandler = async ({ apiToken, commitSha: commitSha_, devTools,
64
61
  }
65
62
  const cookieDir = (0, path_1.join)((0, common_1.getMeticulousLocalDataDir)(), "cookies");
66
63
  // Report recording start
67
- const recordingCommandId = await (0, session_api_1.getRecordingCommandId)(client);
64
+ const recordingCommandId = await (0, client_1.getRecordingCommandId)(client);
68
65
  // 5. Start recording
69
66
  const onDetectedSession = (sessionId) => {
70
67
  if (onDetectedSession_) {
71
68
  onDetectedSession_(sessionId);
72
69
  }
73
- (0, session_api_1.postSessionIdNotification)(client, sessionId, recordingCommandId).catch((error) => {
70
+ (0, client_1.postSessionIdNotification)(client, sessionId, recordingCommandId).catch((error) => {
74
71
  logger.error(`Warning: error while notifying session recording ${sessionId}`);
75
72
  logger.error(error);
76
73
  debugLogger === null || debugLogger === void 0 ? void 0 : debugLogger.log(`Warning: error while notifying session recording ${sessionId}`);
@@ -1,41 +1,28 @@
1
1
  /// <reference types="yargs" />
2
- import { ScreenshotDiffResult } from "@alwaysmeticulous/api";
3
- import { GeneratedBy, Replay, ReplayEventsDependencies, ReplayExecutionOptions, ReplayTarget } from "@alwaysmeticulous/common";
4
- import { ScreenshotAssertionsOptions, ScreenshotDiffOptions } from "../../command-utils/common-types";
5
- export interface ReplayOptions extends AdditionalReplayOptions {
6
- replayTarget: ReplayTarget;
7
- executionOptions: ReplayExecutionOptions;
8
- screenshottingOptions: ScreenshotAssertionsOptions;
9
- generatedBy: GeneratedBy;
10
- testRunId: string | null;
11
- replayEventsDependencies: ReplayEventsDependencies;
12
- suppressScreenshotDiffLogging: boolean;
13
- }
14
- export interface ReplayResult {
2
+ import { Replay, ScreenshotDiffOptions, ScreenshotDiffResult } from "@alwaysmeticulous/api";
3
+ import { ReplayExecutionOptions, ReplayTarget } from "@alwaysmeticulous/sdk-bundles-api";
4
+ export interface ReplayAndStoreResultsResult {
15
5
  replay: Replay;
16
6
  /**
17
7
  * Empty if screenshottingOptions.enabled was false.
18
8
  */
19
9
  screenshotDiffResultsByBaseReplayId: Record<string, ScreenshotDiffResult[]>;
20
10
  }
21
- export declare const replayCommandHandler: ({ replayTarget, executionOptions, screenshottingOptions, apiToken, sessionId, commitSha: commitSha_, baseTestRunId, cookiesFile, generatedBy, testRunId, replayEventsDependencies, debugger: enableStepThroughDebugger, suppressScreenshotDiffLogging, }: ReplayOptions) => Promise<ReplayResult>;
22
- export interface RawReplayCommandHandlerOptions extends ScreenshotDiffOptions, Omit<ReplayExecutionOptions, "maxDurationMs" | "maxEventCount">, Omit<AdditionalReplayOptions, "baseTestRunId"> {
11
+ export interface RawReplayCommandHandlerOptions extends ScreenshotDiffOptions, Omit<ReplayExecutionOptions, "maxDurationMs" | "maxEventCount"> {
23
12
  screenshot: boolean;
24
13
  appUrl: string | null | undefined;
25
14
  simulationIdForAssets: string | null | undefined;
26
15
  maxDurationMs: number | null | undefined;
27
16
  maxEventCount: number | null | undefined;
28
17
  storyboard: boolean;
29
- }
30
- interface AdditionalReplayOptions {
31
18
  apiToken: string | null | undefined;
32
19
  commitSha: string | null | undefined;
33
20
  sessionId: string;
34
- baseTestRunId: string | null | undefined;
35
21
  cookiesFile: string | null | undefined;
36
22
  debugger: boolean;
23
+ baseReplayId: string | null | undefined;
37
24
  }
38
- export declare const rawReplayCommandHandler: ({ apiToken, commitSha, sessionId, appUrl, simulationIdForAssets, headless, devTools, bypassCSP, screenshot, diffThreshold, diffPixelThreshold, shiftTime, networkStubbing, moveBeforeClick, cookiesFile, disableRemoteFonts, noSandbox, skipPauses, maxDurationMs, maxEventCount, storyboard, essentialFeaturesOnly, debugger: enableStepThroughDebugger, }: RawReplayCommandHandlerOptions) => Promise<Replay>;
25
+ export declare const rawReplayCommandHandler: ({ apiToken, commitSha, sessionId, appUrl, simulationIdForAssets, headless, devTools, bypassCSP, screenshot, baseReplayId, diffThreshold, diffPixelThreshold, shiftTime, networkStubbing, moveBeforeClick, cookiesFile, disableRemoteFonts, noSandbox, skipPauses, maxDurationMs, maxEventCount, storyboard, essentialFeaturesOnly, debugger: enableStepThroughDebugger, }: RawReplayCommandHandlerOptions) => Promise<Replay>;
39
26
  export declare const getReplayTarget: ({ appUrl, simulationIdForAssets, }: {
40
27
  appUrl: string | null;
41
28
  simulationIdForAssets: string | null;
@@ -147,5 +134,9 @@ export declare const replayCommand: import("yargs").CommandModule<unknown, impor
147
134
  string: true;
148
135
  description: string;
149
136
  };
137
+ baseReplayId: {
138
+ string: true;
139
+ description: string;
140
+ alias: string;
141
+ };
150
142
  }>>;
151
- export {};
@@ -1,238 +1,13 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
2
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.replayCommand = exports.getReplayTarget = exports.rawReplayCommandHandler = exports.replayCommandHandler = void 0;
30
- const promises_1 = require("fs/promises");
31
- const path_1 = require("path");
32
- const common_1 = require("@alwaysmeticulous/common");
33
- const Sentry = __importStar(require("@sentry/node"));
34
- const loglevel_1 = __importDefault(require("loglevel"));
35
- const luxon_1 = require("luxon");
36
- const client_1 = require("../../api/client");
37
- const replay_api_1 = require("../../api/replay.api");
38
- const upload_1 = require("../../api/upload");
39
- const archive_1 = require("../../archive/archive");
3
+ exports.replayCommand = exports.getReplayTarget = exports.rawReplayCommandHandler = void 0;
4
+ const replay_orchestrator_1 = require("@alwaysmeticulous/replay-orchestrator");
40
5
  const command_builder_1 = require("../../command-utils/command-builder");
41
6
  const common_options_1 = require("../../command-utils/common-options");
42
- const local_data_utils_1 = require("../../local-data/local-data.utils");
43
- const replay_assets_1 = require("../../local-data/replay-assets");
44
- const serve_assets_from_simulation_1 = require("../../local-data/serve-assets-from-simulation");
45
- const sessions_1 = require("../../local-data/sessions");
46
- const commit_sha_utils_1 = require("../../utils/commit-sha.utils");
47
- const version_utils_1 = require("../../utils/version.utils");
48
- const compute_diff_1 = require("./utils/compute-diff");
49
- const exit_early_if_skip_upload_env_var_set_1 = require("./utils/exit-early-if-skip-upload-env-var-set");
50
- const replayCommandHandler = async ({ replayTarget, executionOptions, screenshottingOptions, apiToken, sessionId, commitSha: commitSha_, baseTestRunId, cookiesFile, generatedBy, testRunId, replayEventsDependencies, debugger: enableStepThroughDebugger, suppressScreenshotDiffLogging, }) => {
51
- var _a;
52
- if (executionOptions.headless === true &&
53
- enableStepThroughDebugger === true) {
54
- throw new Error("Cannot run with both --debugger flag and --headless flag at the same time.");
55
- }
56
- const rootTransaction = (_a = Sentry.getCurrentHub().getScope()) === null || _a === void 0 ? void 0 : _a.getTransaction();
57
- const handlerSpanContext = {
58
- name: "replay.command_handler",
59
- description: "Handle the replay command",
60
- op: "replay.command_handler",
61
- };
62
- let transaction;
63
- if (rootTransaction) {
64
- transaction = rootTransaction.startChild(handlerSpanContext);
65
- }
66
- else {
67
- transaction = Sentry.startTransaction(handlerSpanContext);
68
- }
69
- Sentry.getCurrentHub().configureScope((scope) => scope.setSpan(transaction));
70
- const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
71
- const client = (0, client_1.createClient)({ apiToken });
72
- // 1. Check session files
73
- const fetchSessions = transaction.startChild({ op: "fetchingSessions" });
74
- const { data: session } = await (0, sessions_1.getOrFetchRecordedSession)(client, sessionId);
75
- const { data: sessionData } = await (0, sessions_1.getOrFetchRecordedSessionData)(client, sessionId);
76
- fetchSessions.finish();
77
- // 2. Guess commit SHA1
78
- const commitSha = (await (0, commit_sha_utils_1.getCommitSha)(commitSha_)) || "unknown";
79
- logger.debug(`Commit: ${commitSha}`);
80
- const meticulousSha = await (0, version_utils_1.getMeticulousVersion)();
81
- // 3. If simulationIdForAssets specified then download assets & spin up local server
82
- const serveOrGetAppUrlSpan = transaction.startChild({
83
- op: "serveOrGetAppUrl",
84
- });
85
- const { appUrl, closeServer } = await serveOrGetAppUrl(client, replayTarget);
86
- serveOrGetAppUrlSpan.finish();
87
- // 4. Load replay package
88
- let replayEvents;
89
- try {
90
- logger.debug("Loading replayer package...");
91
- const replayer = await require("@alwaysmeticulous/replayer");
92
- replayEvents = replayer.replayEvents;
93
- }
94
- catch (error) {
95
- logger.error("Error: could not import @alwaysmeticulous/replayer");
96
- logger.error(error);
97
- process.exit(1);
98
- }
99
- // Report replay start
100
- logger.debug("Reporting replay started...");
101
- const replayCommandId = await (0, replay_api_1.getReplayCommandId)(client, sessionId);
102
- // 5. Create replay directory
103
- logger.debug("Creating directory to store replay output...");
104
- await (0, promises_1.mkdir)((0, path_1.join)((0, common_1.getMeticulousLocalDataDir)(), "replays"), {
105
- recursive: true,
106
- });
107
- const tempDirName = (0, local_data_utils_1.sanitizeFilename)(`${new Date().toISOString()}-`);
108
- const tempDir = await (0, promises_1.mkdtemp)((0, path_1.join)((0, common_1.getMeticulousLocalDataDir)(), "replays", tempDirName));
109
- // 6. Create and save replay parameters
110
- logger.debug("Snapshotting replay parameters...");
111
- const replayEventsParams = {
112
- appUrl: appUrl !== null && appUrl !== void 0 ? appUrl : null,
113
- replayExecutionOptions: executionOptions,
114
- browser: null,
115
- outputDir: tempDir,
116
- session,
117
- recordingId: "manual-replay",
118
- meticulousSha: "meticulousSha",
119
- generatedBy,
120
- testRunId,
121
- dependencies: replayEventsDependencies,
122
- enableStepThroughDebugger,
123
- screenshottingOptions,
124
- cookiesFile: cookiesFile !== null && cookiesFile !== void 0 ? cookiesFile : null,
125
- };
126
- await (0, promises_1.writeFile)((0, path_1.join)(tempDir, "replayEventsParams.json"), JSON.stringify(replayEventsParams));
127
- // 7. Perform replay
128
- logger.debug("Beggining replay...");
129
- const startTime = luxon_1.DateTime.utc();
130
- await replayEvents({
131
- ...replayEventsParams,
132
- sessionData,
133
- parentPerformanceSpan: transaction.startChild({ op: "replayEvents" }),
134
- });
135
- closeServer === null || closeServer === void 0 ? void 0 : closeServer();
136
- const endTime = luxon_1.DateTime.utc();
137
- logger.info(`Simulation time: ${endTime.diff(startTime).as("seconds")} seconds`);
138
- (0, exit_early_if_skip_upload_env_var_set_1.exitEarlyIfSkipUploadEnvVarSet)(baseTestRunId);
139
- logger.info("Sending simulation results to Meticulous");
140
- // 8. Create a Zip archive containing the replay files
141
- const createReplayArchiveSpan = transaction.startChild({
142
- op: "createArchiveAndUpload",
143
- });
144
- const archivePath = await (0, archive_1.createReplayArchive)(tempDir);
145
- createReplayArchiveSpan.finish();
146
- try {
147
- // 9. Get upload URL
148
- const getReplayPushUrlSpan = transaction.startChild({
149
- op: "getReplayPushUrl",
150
- });
151
- const replay = await (0, replay_api_1.createReplay)({
152
- client,
153
- commitSha,
154
- sessionId,
155
- meticulousSha,
156
- version: "v2",
157
- metadata: { generatedBy },
158
- });
159
- const uploadUrlData = await (0, replay_api_1.getReplayPushUrl)(client, replay.id);
160
- if (!uploadUrlData) {
161
- logger.error("Error: Could not get a push URL from the Meticulous API");
162
- process.exit(1);
163
- }
164
- const uploadUrl = uploadUrlData.pushUrl;
165
- getReplayPushUrlSpan.finish();
166
- // 10. Send archive to S3
167
- const uploadArchiveSpan = transaction.startChild({ op: "uploadArchive" });
168
- try {
169
- await (0, upload_1.uploadArchive)(uploadUrl, archivePath);
170
- }
171
- catch (error) {
172
- await (0, replay_api_1.putReplayPushedStatus)(client, replay.id, "failure", replayCommandId).catch(logger.error);
173
- logger.error(error);
174
- process.exit(1);
175
- }
176
- uploadArchiveSpan.finish();
177
- // 11. Report successful upload to Meticulous
178
- const updatedProjectBuild = await (0, replay_api_1.putReplayPushedStatus)(client, replay.id, "success", replayCommandId);
179
- logger.info("Simulation artifacts successfully sent to Meticulous");
180
- logger.debug(updatedProjectBuild);
181
- const replayUrl = (0, replay_api_1.getReplayUrl)(replay);
182
- logger.info("=======");
183
- logger.info(`View simulation at: ${replayUrl}`);
184
- logger.info("=======");
185
- // 12. Diff against base replay screenshot if one is provided
186
- const computeDiffSpan = transaction.startChild({
187
- op: "computeDiff",
188
- });
189
- const computeDiffsLogger = loglevel_1.default.getLogger(`METICULOUS_LOGGER_NAME/compute-diffs`);
190
- if (suppressScreenshotDiffLogging) {
191
- computeDiffsLogger.setLevel("ERROR", false);
192
- }
193
- else {
194
- computeDiffsLogger.setLevel(logger.getLevel(), false);
195
- }
196
- const screenshotDiffResultsByBaseReplayId = screenshottingOptions.enabled && baseTestRunId
197
- ? await (0, compute_diff_1.computeDiff)({
198
- client,
199
- baseTestRunId,
200
- sessionId,
201
- headReplayId: replay.id,
202
- tempDir,
203
- screenshottingOptions,
204
- logger: computeDiffsLogger,
205
- })
206
- : {};
207
- computeDiffSpan.finish();
208
- return { replay, screenshotDiffResultsByBaseReplayId };
7
+ const rawReplayCommandHandler = async ({ apiToken, commitSha, sessionId, appUrl, simulationIdForAssets, headless, devTools, bypassCSP, screenshot, baseReplayId, diffThreshold, diffPixelThreshold, shiftTime, networkStubbing, moveBeforeClick, cookiesFile, disableRemoteFonts, noSandbox, skipPauses, maxDurationMs, maxEventCount, storyboard, essentialFeaturesOnly, debugger: enableStepThroughDebugger, }) => {
8
+ if (!screenshot && storyboard) {
9
+ throw new Error("Cannot take storyboard screenshots without taking end state screenshots. Please set '--screenshot' to true, or '--storyboard' to false.");
209
10
  }
210
- finally {
211
- await (0, archive_1.deleteArchive)(archivePath);
212
- transaction.finish();
213
- }
214
- };
215
- exports.replayCommandHandler = replayCommandHandler;
216
- const serveOrGetAppUrl = async (client, replayTarget) => {
217
- if (replayTarget.type === "snapshotted-assets") {
218
- const server = await (0, serve_assets_from_simulation_1.serveAssetsFromSimulation)(client, replayTarget.simulationIdForAssets);
219
- return {
220
- appUrl: server.url,
221
- closeServer: server.closeServer,
222
- };
223
- }
224
- if (replayTarget.type === "url") {
225
- return { appUrl: replayTarget.appUrl };
226
- }
227
- if (replayTarget.type === "original-recorded-url") {
228
- return {};
229
- }
230
- return unknownReplayTargetType(replayTarget);
231
- };
232
- const unknownReplayTargetType = (replayTarget) => {
233
- throw new Error(`Unknown type of replay target: ${JSON.stringify(replayTarget)}`);
234
- };
235
- const rawReplayCommandHandler = async ({ apiToken, commitSha, sessionId, appUrl, simulationIdForAssets, headless, devTools, bypassCSP, screenshot, diffThreshold, diffPixelThreshold, shiftTime, networkStubbing, moveBeforeClick, cookiesFile, disableRemoteFonts, noSandbox, skipPauses, maxDurationMs, maxEventCount, storyboard, essentialFeaturesOnly, debugger: enableStepThroughDebugger, }) => {
236
11
  const executionOptions = {
237
12
  headless,
238
13
  devTools,
@@ -254,12 +29,19 @@ const rawReplayCommandHandler = async ({ apiToken, commitSha, sessionId, appUrl,
254
29
  const screenshottingOptions = screenshot
255
30
  ? {
256
31
  enabled: true,
257
- diffOptions: { diffPixelThreshold, diffThreshold },
258
32
  storyboardOptions,
33
+ compareTo: baseReplayId != null
34
+ ? {
35
+ type: "specific-replay",
36
+ replayId: baseReplayId,
37
+ diffOptions: { diffThreshold, diffPixelThreshold },
38
+ }
39
+ : {
40
+ type: "do-not-compare",
41
+ },
259
42
  }
260
43
  : { enabled: false };
261
- const replayEventsDependencies = await (0, replay_assets_1.loadReplayEventsDependencies)();
262
- const { replay } = await (0, exports.replayCommandHandler)({
44
+ const { replay } = await (0, replay_orchestrator_1.replayAndStoreResults)({
263
45
  replayTarget: (0, exports.getReplayTarget)({
264
46
  appUrl: appUrl !== null && appUrl !== void 0 ? appUrl : null,
265
47
  simulationIdForAssets: simulationIdForAssets !== null && simulationIdForAssets !== void 0 ? simulationIdForAssets : null,
@@ -271,9 +53,7 @@ const rawReplayCommandHandler = async ({ apiToken, commitSha, sessionId, appUrl,
271
53
  cookiesFile,
272
54
  sessionId,
273
55
  generatedBy: generatedByOption,
274
- baseTestRunId: null,
275
56
  testRunId: null,
276
- replayEventsDependencies,
277
57
  debugger: enableStepThroughDebugger,
278
58
  suppressScreenshotDiffLogging: false,
279
59
  });
@@ -326,6 +106,11 @@ exports.replayCommand = (0, command_builder_1.buildCommand)("simulate")
326
106
  string: true,
327
107
  description: "Path to cookies to inject before simulation",
328
108
  },
109
+ baseReplayId: {
110
+ string: true,
111
+ description: "Base simulation id to diff the screenshots against",
112
+ alias: "baseSimulationId",
113
+ },
329
114
  ...common_options_1.COMMON_REPLAY_OPTIONS,
330
115
  ...common_options_1.SCREENSHOT_DIFF_OPTIONS,
331
116
  })
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runAllTestsCommand = void 0;
4
- const client_1 = require("../../api/client");
4
+ const client_1 = require("@alwaysmeticulous/client");
5
+ const common_1 = require("@alwaysmeticulous/common");
6
+ const replay_orchestrator_1 = require("@alwaysmeticulous/replay-orchestrator");
5
7
  const test_run_api_1 = require("../../api/test-run.api");
6
8
  const command_builder_1 = require("../../command-utils/command-builder");
7
9
  const common_options_1 = require("../../command-utils/common-options");
8
- const run_all_tests_1 = require("../../parallel-tests/run-all-tests");
9
- const commit_sha_utils_1 = require("../../utils/commit-sha.utils");
10
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,
@@ -31,12 +31,12 @@ const handler = async ({ apiToken, commitSha: commitSha_, baseCommitSha, appUrl,
31
31
  storyboardOptions,
32
32
  };
33
33
  const parrelelTasks = parallelize ? parrelelTasks_ : 1;
34
- const commitSha = (await (0, commit_sha_utils_1.getCommitSha)(commitSha_)) || "unknown";
34
+ const commitSha = (await (0, common_1.getCommitSha)(commitSha_)) || "unknown";
35
35
  const client = (0, client_1.createClient)({ apiToken });
36
36
  const cachedTestRunResults = useCache
37
37
  ? await (0, test_run_api_1.getCachedTestRunResults)({ client, commitSha })
38
38
  : [];
39
- const { testRun } = await (0, run_all_tests_1.runAllTests)({
39
+ const { testRun } = await (0, replay_orchestrator_1.executeTestRun)({
40
40
  testsFile: testsFile !== null && testsFile !== void 0 ? testsFile : null,
41
41
  executionOptions,
42
42
  screenshottingOptions,
@@ -4,15 +4,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.showProjectCommand = void 0;
7
+ const client_1 = require("@alwaysmeticulous/client");
7
8
  const common_1 = require("@alwaysmeticulous/common");
8
9
  const loglevel_1 = __importDefault(require("loglevel"));
9
- const client_1 = require("../../api/client");
10
- const project_api_1 = require("../../api/project.api");
11
10
  const command_builder_1 = require("../../command-utils/command-builder");
12
11
  const handler = async ({ apiToken }) => {
13
12
  const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
14
13
  const client = (0, client_1.createClient)({ apiToken });
15
- const project = await (0, project_api_1.getProject)(client);
14
+ const project = await (0, client_1.getProject)(client);
16
15
  if (!project) {
17
16
  logger.error("Could not retrieve project data. Is the API token correct?");
18
17
  process.exit(1);