@alwaysmeticulous/cli 1.4.1 → 1.5.1

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.
@@ -1,11 +1,17 @@
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.debugReplay = void 0;
7
+ const common_1 = require("@alwaysmeticulous/common");
8
+ const loglevel_1 = __importDefault(require("loglevel"));
4
9
  const client_1 = require("../../api/client");
5
10
  const replay_assets_1 = require("../../local-data/replay-assets");
6
11
  const sessions_1 = require("../../local-data/sessions");
7
12
  const sentry_utils_1 = require("../../utils/sentry.utils");
8
13
  const handler = async ({ apiToken, sessionId, appUrl, devTools, networkStubbing, moveBeforeClick, cookiesFile, }) => {
14
+ const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
9
15
  const client = (0, client_1.createClient)({ apiToken });
10
16
  // 1. Check session files
11
17
  await (0, sessions_1.getOrFetchRecordedSession)(client, sessionId);
@@ -21,8 +27,8 @@ const handler = async ({ apiToken, sessionId, appUrl, devTools, networkStubbing,
21
27
  createReplayer = replayDebugger.createReplayer;
22
28
  }
23
29
  catch (error) {
24
- console.error("Error: could not import @alwaysmeticulous/replay-debugger");
25
- console.error(error);
30
+ logger.error("Error: could not import @alwaysmeticulous/replay-debugger");
31
+ logger.error(error);
26
32
  process.exit(1);
27
33
  }
28
34
  // 5. Start replay debugger
@@ -1,7 +1,11 @@
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.record = void 0;
4
7
  const common_1 = require("@alwaysmeticulous/common");
8
+ const loglevel_1 = __importDefault(require("loglevel"));
5
9
  const path_1 = require("path");
6
10
  const client_1 = require("../../api/client");
7
11
  const project_api_1 = require("../../api/project.api");
@@ -10,9 +14,10 @@ const replay_assets_1 = require("../../local-data/replay-assets");
10
14
  const commit_sha_utils_1 = require("../../utils/commit-sha.utils");
11
15
  const sentry_utils_1 = require("../../utils/sentry.utils");
12
16
  const handler = async ({ apiToken, commitSha: commitSha_, devTools, width, height, uploadIntervalMs, incognito, trace, }) => {
13
- const logger = trace ? await common_1.DebugLogger.create() : null;
14
- logger === null || logger === void 0 ? void 0 : logger.log("Record options:");
15
- logger === null || logger === void 0 ? void 0 : logger.logObject({
17
+ const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
18
+ const debugLogger = trace ? await common_1.DebugLogger.create() : null;
19
+ debugLogger === null || debugLogger === void 0 ? void 0 : debugLogger.log("Record options:");
20
+ debugLogger === null || debugLogger === void 0 ? void 0 : debugLogger.logObject({
16
21
  apiToken,
17
22
  commitSha: commitSha_,
18
23
  devTools,
@@ -22,27 +27,28 @@ const handler = async ({ apiToken, commitSha: commitSha_, devTools, width, heigh
22
27
  incognito,
23
28
  trace,
24
29
  });
30
+ logger.info("Preparing recording...");
25
31
  // 1. Fetch the recording token
26
32
  const client = (0, client_1.createClient)({ apiToken });
27
33
  const project = await (0, project_api_1.getProject)(client);
28
34
  if (!project) {
29
- console.error("Could not retrieve project data. Is the API token correct?");
30
- logger === null || logger === void 0 ? void 0 : logger.log("Could not retrieve project data. Is the API token correct?");
35
+ logger.error("Could not retrieve project data. Is the API token correct?");
36
+ debugLogger === null || debugLogger === void 0 ? void 0 : debugLogger.log("Could not retrieve project data. Is the API token correct?");
31
37
  process.exit(1);
32
38
  }
33
39
  const recordingToken = project.recordingToken;
34
40
  if (!recordingToken) {
35
- console.error("Could not retrieve recording token.");
36
- logger === null || logger === void 0 ? void 0 : logger.log("Could not retrieve recording token.");
41
+ logger.error("Could not retrieve recording token.");
42
+ debugLogger === null || debugLogger === void 0 ? void 0 : debugLogger.log("Could not retrieve recording token.");
37
43
  process.exit(1);
38
44
  }
39
- console.log(`Recording token: ${recordingToken}`);
45
+ logger.debug(`Recording token: ${recordingToken}`);
40
46
  // 2. Guess commit SHA1
41
47
  const commitSha = (await (0, commit_sha_utils_1.getCommitSha)(commitSha_)) || "unknown";
42
- console.log(`Commit: ${commitSha}`);
48
+ logger.debug(`Commit: ${commitSha}`);
43
49
  // 3. Load recording snippets
44
50
  const recordingSnippet = await (0, replay_assets_1.fetchAsset)("https://snippet.meticulous.ai/v1/stagingMeticulousSnippet.js");
45
- const fetchStallSnippet = await (0, replay_assets_1.fetchAsset)("https://snippet.meticulous.ai/record/v1/fetch-stall.bundle.js");
51
+ const earlyNetworkRecorderSnippet = await (0, replay_assets_1.fetchAsset)("https://snippet.meticulous.ai/record/v1/network-recorder.bundle.js");
46
52
  // 4. Load recording package
47
53
  let recordSession;
48
54
  try {
@@ -50,10 +56,10 @@ const handler = async ({ apiToken, commitSha: commitSha_, devTools, width, heigh
50
56
  recordSession = record.recordSession;
51
57
  }
52
58
  catch (error) {
53
- console.error("Error: could not import @alwaysmeticulous/record");
54
- console.error(error);
55
- logger === null || logger === void 0 ? void 0 : logger.log("Error: could not import @alwaysmeticulous/record");
56
- logger === null || logger === void 0 ? void 0 : logger.log(`${error}`);
59
+ logger.error("Error: could not import @alwaysmeticulous/record");
60
+ logger.error(error);
61
+ debugLogger === null || debugLogger === void 0 ? void 0 : debugLogger.log("Error: could not import @alwaysmeticulous/record");
62
+ debugLogger === null || debugLogger === void 0 ? void 0 : debugLogger.log(`${error}`);
57
63
  process.exit(1);
58
64
  }
59
65
  const cookieDir = (0, path_1.join)((0, common_1.getMeticulousLocalDataDir)(), "cookies");
@@ -67,23 +73,23 @@ const handler = async ({ apiToken, commitSha: commitSha_, devTools, width, heigh
67
73
  appCommitHash: commitSha,
68
74
  devTools,
69
75
  recordingSnippet,
70
- fetchStallSnippet,
76
+ earlyNetworkRecorderSnippet,
71
77
  width,
72
78
  height,
73
79
  uploadIntervalMs,
74
80
  incognito,
75
81
  cookieDir,
76
- logger,
82
+ debugLogger,
77
83
  onDetectedSession: (sessionId) => {
78
84
  (0, session_api_1.postSessionIdNotification)(client, sessionId, recordingCommandId).catch((error) => {
79
- console.error(`Warning: error while notifying session recording ${sessionId}`);
80
- console.error(error);
81
- logger === null || logger === void 0 ? void 0 : logger.log(`Warning: error while notifying session recording ${sessionId}`);
82
- logger === null || logger === void 0 ? void 0 : logger.log(`${error}`);
85
+ logger.error(`Warning: error while notifying session recording ${sessionId}`);
86
+ logger.error(error);
87
+ debugLogger === null || debugLogger === void 0 ? void 0 : debugLogger.log(`Warning: error while notifying session recording ${sessionId}`);
88
+ debugLogger === null || debugLogger === void 0 ? void 0 : debugLogger.log(`${error}`);
83
89
  });
84
90
  },
85
91
  }).catch((error) => {
86
- logger === null || logger === void 0 ? void 0 : logger.log(`${error}`);
92
+ debugLogger === null || debugLogger === void 0 ? void 0 : debugLogger.log(`${error}`);
87
93
  throw error;
88
94
  });
89
95
  };
@@ -1,8 +1,12 @@
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.replay = exports.replayCommandHandler = void 0;
4
7
  const common_1 = require("@alwaysmeticulous/common");
5
8
  const promises_1 = require("fs/promises");
9
+ const loglevel_1 = __importDefault(require("loglevel"));
6
10
  const luxon_1 = require("luxon");
7
11
  const path_1 = require("path");
8
12
  const client_1 = require("../../api/client");
@@ -19,13 +23,14 @@ const sentry_utils_1 = require("../../utils/sentry.utils");
19
23
  const version_utils_1 = require("../../utils/version.utils");
20
24
  const screenshot_diff_command_1 = require("../screenshot-diff/screenshot-diff.command");
21
25
  const replayCommandHandler = async ({ apiToken, commitSha: commitSha_, sessionId, appUrl, headless, devTools, bypassCSP, screenshot, screenshotSelector, baseReplayId: baseReplayId_, diffThreshold, diffPixelThreshold, save, exitOnMismatch, padTime, networkStubbing, moveBeforeClick, cookies, cookiesFile, }) => {
26
+ const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
22
27
  const client = (0, client_1.createClient)({ apiToken });
23
28
  // 1. Check session files
24
29
  const session = await (0, sessions_1.getOrFetchRecordedSession)(client, sessionId);
25
30
  const sessionData = await (0, sessions_1.getOrFetchRecordedSessionData)(client, sessionId);
26
31
  // 2. Guess commit SHA1
27
32
  const commitSha = (await (0, commit_sha_utils_1.getCommitSha)(commitSha_)) || "unknown";
28
- console.log(`Commit: ${commitSha}`);
33
+ logger.debug(`Commit: ${commitSha}`);
29
34
  const meticulousSha = await (0, version_utils_1.getMeticulousVersion)();
30
35
  // 3. Load replay assets
31
36
  const reanimator = await (0, replay_assets_1.fetchAsset)("https://snippet.meticulous.ai/replay/v1/reanimator.bundle.js");
@@ -39,8 +44,8 @@ const replayCommandHandler = async ({ apiToken, commitSha: commitSha_, sessionId
39
44
  replayEvents = replayer.replayEvents;
40
45
  }
41
46
  catch (error) {
42
- console.error("Error: could not import @alwaysmeticulous/replayer");
43
- console.error(error);
47
+ logger.error("Error: could not import @alwaysmeticulous/replayer");
48
+ logger.error(error);
44
49
  process.exit(1);
45
50
  }
46
51
  // Report replay start
@@ -91,14 +96,14 @@ const replayCommandHandler = async ({ apiToken, commitSha: commitSha_, sessionId
91
96
  };
92
97
  await (0, promises_1.writeFile)((0, path_1.join)(tempDir, "replayEventsParams.json"), JSON.stringify(replayEventsParams));
93
98
  // 7. Perform replay
94
- console.log("Starting replay...");
99
+ logger.info("Starting replay...");
95
100
  const startTime = luxon_1.DateTime.utc();
96
101
  const { eventsFinishedPromise, writesFinishedPromise } = await replayEvents(replayEventsParams);
97
102
  await eventsFinishedPromise;
98
103
  await writesFinishedPromise;
99
104
  const endTime = luxon_1.DateTime.utc();
100
- console.log(`Replay time: ${endTime.diff(startTime).as("seconds")} seconds`);
101
- console.log("Sending replay results to Meticulous");
105
+ logger.info(`Replay time: ${endTime.diff(startTime).as("seconds")} seconds`);
106
+ logger.info("Sending replay results to Meticulous");
102
107
  // 8. Create a Zip archive containing the replay files
103
108
  const archivePath = await (0, archive_1.createReplayArchive)(tempDir);
104
109
  // 9. Get upload URL
@@ -111,7 +116,7 @@ const replayCommandHandler = async ({ apiToken, commitSha: commitSha_, sessionId
111
116
  });
112
117
  const uploadUrlData = await (0, replay_api_1.getReplayPushUrl)(client, replay.id);
113
118
  if (!uploadUrlData) {
114
- console.error("Error: Could not get a push URL from the Meticulous API");
119
+ logger.error("Error: Could not get a push URL from the Meticulous API");
115
120
  process.exit(1);
116
121
  }
117
122
  const uploadUrl = uploadUrlData.pushUrl;
@@ -120,20 +125,22 @@ const replayCommandHandler = async ({ apiToken, commitSha: commitSha_, sessionId
120
125
  await (0, upload_1.uploadArchive)(uploadUrl, archivePath);
121
126
  }
122
127
  catch (error) {
123
- await (0, replay_api_1.putReplayPushedStatus)(client, replay.id, "failure", replayCommandId).catch(console.error);
124
- console.error(error);
128
+ await (0, replay_api_1.putReplayPushedStatus)(client, replay.id, "failure", replayCommandId).catch(logger.error);
129
+ logger.error(error);
125
130
  process.exit(1);
126
131
  }
127
132
  // 11. Report successful upload to Meticulous
128
133
  const updatedProjectBuild = await (0, replay_api_1.putReplayPushedStatus)(client, replay.id, "success", replayCommandId);
129
- console.log("Replay artifacts successfully sent to Meticulous");
130
- console.log(updatedProjectBuild);
134
+ logger.info("Replay artifacts successfully sent to Meticulous");
135
+ logger.debug(updatedProjectBuild);
131
136
  const replayUrl = (0, replay_api_1.getReplayUrl)(replay);
132
- console.log(`View replay at: ${replayUrl}`);
137
+ logger.info("=======");
138
+ logger.info(`View replay at: ${replayUrl}`);
139
+ logger.info("=======");
133
140
  // 12. Diff against base replay screenshot if one is provided
134
141
  const baseReplayId = baseReplayId_ || "";
135
142
  if (screenshot && baseReplayId) {
136
- console.log(`Diffing final state screenshot against replay ${baseReplayId}`);
143
+ logger.info(`Diffing final state screenshot against replay ${baseReplayId}`);
137
144
  await (0, replays_1.getOrFetchReplay)(client, baseReplayId);
138
145
  await (0, replays_1.getOrFetchReplayArchive)(client, baseReplayId);
139
146
  const baseScreenshot = await (0, replays_1.readReplayScreenshot)(baseReplayId);
@@ -152,7 +159,7 @@ const replayCommandHandler = async ({ apiToken, commitSha: commitSha_, sessionId
152
159
  // 13. Add test case to meticulous.json if --save option is passed
153
160
  if (save) {
154
161
  if (!screenshot) {
155
- console.error("Warning: saving a new test case without screenshot enabled.");
162
+ logger.error("Warning: saving a new test case without screenshot enabled.");
156
163
  }
157
164
  const meticulousConfig = await (0, config_1.readConfig)();
158
165
  const newConfig = {
@@ -11,6 +11,8 @@ interface Options {
11
11
  padTime: boolean;
12
12
  networkStubbing: boolean;
13
13
  githubSummary?: boolean | null | undefined;
14
+ parallelize?: boolean | null | undefined;
15
+ parallelTasks?: number | null | undefined;
14
16
  }
15
17
  export declare const runAllTests: CommandModule<unknown, Options>;
16
18
  export {};
@@ -1,21 +1,28 @@
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.runAllTests = void 0;
7
+ const common_1 = require("@alwaysmeticulous/common");
8
+ const loglevel_1 = __importDefault(require("loglevel"));
4
9
  const client_1 = require("../../api/client");
5
10
  const test_run_api_1 = require("../../api/test-run.api");
6
11
  const config_1 = require("../../config/config");
12
+ const parallel_tests_handler_1 = require("../../parallel-tests/parallel-tests.handler");
7
13
  const commit_sha_utils_1 = require("../../utils/commit-sha.utils");
8
14
  const github_summary_utils_1 = require("../../utils/github-summary.utils");
9
15
  const sentry_utils_1 = require("../../utils/sentry.utils");
10
16
  const version_utils_1 = require("../../utils/version.utils");
11
17
  const replay_command_1 = require("../replay/replay.command");
12
18
  const screenshot_diff_command_1 = require("../screenshot-diff/screenshot-diff.command");
13
- const handler = async ({ apiToken, commitSha: commitSha_, appUrl, headless, devTools, bypassCSP, diffThreshold, diffPixelThreshold, padTime, networkStubbing, githubSummary, }) => {
19
+ const handler = async ({ apiToken, commitSha: commitSha_, appUrl, headless, devTools, bypassCSP, diffThreshold, diffPixelThreshold, padTime, networkStubbing, githubSummary, parallelize, parallelTasks, }) => {
20
+ const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
14
21
  const client = (0, client_1.createClient)({ apiToken });
15
22
  const config = await (0, config_1.readConfig)();
16
23
  const testCases = config.testCases || [];
17
24
  if (!testCases.length) {
18
- console.error("Error! No test case defined");
25
+ logger.error("Error! No test case defined");
19
26
  process.exit(1);
20
27
  }
21
28
  const commitSha = (await (0, commit_sha_utils_1.getCommitSha)(commitSha_)) || "unknown";
@@ -27,54 +34,78 @@ const handler = async ({ apiToken, commitSha: commitSha_, appUrl, headless, devT
27
34
  configData: config,
28
35
  });
29
36
  const testRunUrl = (0, test_run_api_1.getTestRunUrl)(testRun);
30
- console.log("");
31
- console.log(`Test run URL: ${testRunUrl}`);
32
- console.log("");
33
- const results = [];
34
- for (const testCase of testCases) {
35
- const { sessionId, baseReplayId, options } = testCase;
36
- const replayPromise = (0, replay_command_1.replayCommandHandler)({
37
- apiToken,
38
- commitSha,
39
- sessionId,
40
- appUrl,
41
- headless,
42
- devTools,
43
- bypassCSP,
44
- screenshot: true,
45
- baseReplayId,
46
- diffThreshold,
47
- diffPixelThreshold,
48
- save: false,
49
- exitOnMismatch: false,
50
- padTime,
51
- networkStubbing,
52
- ...options,
53
- });
54
- const result = await replayPromise
55
- .then((replay) => ({
56
- ...testCase,
57
- headReplayId: replay.id,
58
- result: "pass",
59
- }))
60
- .catch((error) => {
61
- if (error instanceof screenshot_diff_command_1.DiffError && error.extras) {
62
- return {
63
- ...testCase,
64
- headReplayId: error.extras.headReplayId,
65
- result: "fail",
66
- };
67
- }
68
- return { ...testCase, headReplayId: "", result: "fail" };
69
- });
70
- results.push(result);
71
- await (0, test_run_api_1.putTestRunResults)({
72
- client,
73
- testRunId: testRun.id,
74
- status: "Running",
75
- resultData: { results },
76
- });
77
- }
37
+ logger.info("");
38
+ logger.info(`Test run URL: ${testRunUrl}`);
39
+ logger.info("");
40
+ const getResults = async () => {
41
+ if (parallelize) {
42
+ const results = await (0, parallel_tests_handler_1.runAllTestsInParallel)({
43
+ config,
44
+ client,
45
+ testRun,
46
+ apiToken,
47
+ commitSha,
48
+ appUrl,
49
+ headless,
50
+ devTools,
51
+ bypassCSP,
52
+ diffThreshold,
53
+ diffPixelThreshold,
54
+ padTime,
55
+ networkStubbing,
56
+ parallelTasks,
57
+ });
58
+ return results;
59
+ }
60
+ const results = [];
61
+ for (const testCase of testCases) {
62
+ const { sessionId, baseReplayId, options } = testCase;
63
+ const replayPromise = (0, replay_command_1.replayCommandHandler)({
64
+ apiToken,
65
+ commitSha,
66
+ sessionId,
67
+ appUrl,
68
+ headless,
69
+ devTools,
70
+ bypassCSP,
71
+ screenshot: true,
72
+ baseReplayId,
73
+ diffThreshold,
74
+ diffPixelThreshold,
75
+ save: false,
76
+ exitOnMismatch: false,
77
+ padTime,
78
+ networkStubbing,
79
+ ...options,
80
+ });
81
+ const result = await replayPromise
82
+ .then((replay) => ({
83
+ ...testCase,
84
+ headReplayId: replay.id,
85
+ result: "pass",
86
+ }))
87
+ .catch((error) => {
88
+ if (error instanceof screenshot_diff_command_1.DiffError && error.extras) {
89
+ return {
90
+ ...testCase,
91
+ headReplayId: error.extras.headReplayId,
92
+ result: "fail",
93
+ };
94
+ }
95
+ logger.error(error);
96
+ return { ...testCase, headReplayId: "", result: "fail" };
97
+ });
98
+ results.push(result);
99
+ await (0, test_run_api_1.putTestRunResults)({
100
+ client,
101
+ testRunId: testRun.id,
102
+ status: "Running",
103
+ resultData: { results },
104
+ });
105
+ }
106
+ return results;
107
+ };
108
+ const results = await getResults();
78
109
  const runAllFailure = results.find(({ result }) => result === "fail");
79
110
  await (0, test_run_api_1.putTestRunResults)({
80
111
  client,
@@ -82,13 +113,13 @@ const handler = async ({ apiToken, commitSha: commitSha_, appUrl, headless, devT
82
113
  status: runAllFailure ? "Failure" : "Success",
83
114
  resultData: { results },
84
115
  });
85
- console.log("");
86
- console.log("Results");
87
- console.log("=======");
88
- console.log(`URL: ${testRunUrl}`);
89
- console.log("=======");
116
+ logger.info("");
117
+ logger.info("Results");
118
+ logger.info("=======");
119
+ logger.info(`URL: ${testRunUrl}`);
120
+ logger.info("=======");
90
121
  results.forEach(({ title, result }) => {
91
- console.log(`${title} => ${result}`);
122
+ logger.info(`${title} => ${result}`);
92
123
  });
93
124
  if (githubSummary) {
94
125
  await (0, github_summary_utils_1.writeGitHubSummary)({ testRun, results });
@@ -142,6 +173,20 @@ exports.runAllTests = {
142
173
  description: "Stub network requests during replay",
143
174
  default: true,
144
175
  },
176
+ parallelize: {
177
+ boolean: true,
178
+ description: "Run tests in parallel",
179
+ },
180
+ parallelTasks: {
181
+ number: true,
182
+ description: "Number of tasks to run in parallel",
183
+ coerce: (value) => {
184
+ if (typeof value === "number" && value <= 0) {
185
+ return null;
186
+ }
187
+ return value;
188
+ },
189
+ },
145
190
  },
146
191
  handler: (0, sentry_utils_1.wrapHandler)(handler),
147
192
  };
@@ -1,6 +1,11 @@
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.screenshotDiff = exports.diffScreenshots = exports.DiffError = void 0;
7
+ const common_1 = require("@alwaysmeticulous/common");
8
+ const loglevel_1 = __importDefault(require("loglevel"));
4
9
  const client_1 = require("../../api/client");
5
10
  const replay_api_1 = require("../../api/replay.api");
6
11
  const diff_utils_1 = require("../../image/diff.utils");
@@ -16,6 +21,7 @@ class DiffError extends Error {
16
21
  }
17
22
  exports.DiffError = DiffError;
18
23
  const diffScreenshots = async ({ client, baseReplayId, headReplayId, baseScreenshot, headScreenshot, threshold: threshold_, pixelThreshold, exitOnMismatch, }) => {
24
+ const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
19
25
  const threshold = threshold_ || DEFAULT_MISMATCH_THRESHOLD;
20
26
  const pixelmatchOptions = pixelThreshold ? { threshold: pixelThreshold } : null;
21
27
  try {
@@ -24,11 +30,11 @@ const diffScreenshots = async ({ client, baseReplayId, headReplayId, baseScreens
24
30
  head: headScreenshot,
25
31
  ...(pixelmatchOptions ? pixelmatchOptions : {}),
26
32
  });
27
- console.log({ mismatchPixels, mismatchFraction });
28
- console.log(`${Math.round(mismatchFraction * 100)}% pixel mismatch (threshold is ${Math.round(threshold * 100)}%) => ${mismatchFraction > threshold ? "FAIL!" : "PASS"}`);
33
+ logger.debug({ mismatchPixels, mismatchFraction });
34
+ logger.info(`${Math.round(mismatchFraction * 100)}% pixel mismatch (threshold is ${Math.round(threshold * 100)}%) => ${mismatchFraction > threshold ? "FAIL!" : "PASS"}`);
29
35
  await (0, screenshot_diffs_1.writeScreenshotDiff)({ baseReplayId, headReplayId, diff });
30
36
  const diffUrl = await (0, replay_api_1.getDiffUrl)(client, baseReplayId, headReplayId);
31
- console.log(`View screenshot diff at ${diffUrl}`);
37
+ logger.info(`View screenshot diff at ${diffUrl}`);
32
38
  await (0, replay_api_1.postScreenshotDiffStats)(client, {
33
39
  baseReplayId,
34
40
  headReplayId,
@@ -39,7 +45,7 @@ const diffScreenshots = async ({ client, baseReplayId, headReplayId, baseScreens
39
45
  },
40
46
  });
41
47
  if (mismatchFraction > threshold) {
42
- console.log("Screenshots do not match!");
48
+ logger.info("Screenshots do not match!");
43
49
  if (exitOnMismatch) {
44
50
  process.exit(1);
45
51
  }
@@ -52,7 +58,9 @@ const diffScreenshots = async ({ client, baseReplayId, headReplayId, baseScreens
52
58
  }
53
59
  }
54
60
  catch (error) {
55
- console.log(error);
61
+ if (!(error instanceof DiffError)) {
62
+ logger.error(error);
63
+ }
56
64
  if (exitOnMismatch) {
57
65
  process.exit(1);
58
66
  }
@@ -1,17 +1,23 @@
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.showProject = void 0;
7
+ const common_1 = require("@alwaysmeticulous/common");
8
+ const loglevel_1 = __importDefault(require("loglevel"));
4
9
  const client_1 = require("../../api/client");
5
10
  const project_api_1 = require("../../api/project.api");
6
11
  const sentry_utils_1 = require("../../utils/sentry.utils");
7
12
  const handler = async ({ apiToken }) => {
13
+ const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
8
14
  const client = (0, client_1.createClient)({ apiToken });
9
15
  const project = await (0, project_api_1.getProject)(client);
10
16
  if (!project) {
11
- console.error("Could not retrieve project data. Is the API token correct?");
17
+ logger.error("Could not retrieve project data. Is the API token correct?");
12
18
  process.exit(1);
13
19
  }
14
- console.log(project);
20
+ logger.info(project);
15
21
  };
16
22
  exports.showProject = {
17
23
  command: "show-project",
@@ -1,4 +1,7 @@
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.uploadBuild = void 0;
4
7
  const client_1 = require("../../api/client");
@@ -6,36 +9,39 @@ const project_build_api_1 = require("../../api/project-build.api");
6
9
  const project_api_1 = require("../../api/project.api");
7
10
  const upload_1 = require("../../api/upload");
8
11
  const archive_1 = require("../../archive/archive");
12
+ const loglevel_1 = __importDefault(require("loglevel"));
9
13
  const commit_sha_utils_1 = require("../../utils/commit-sha.utils");
10
14
  const sentry_utils_1 = require("../../utils/sentry.utils");
15
+ const common_1 = require("@alwaysmeticulous/common");
11
16
  const handler = async ({ apiToken, commitSha: commitSha_, dist, }) => {
17
+ const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
12
18
  // 1. Print project name
13
19
  const client = (0, client_1.createClient)({ apiToken });
14
20
  const project = await (0, project_api_1.getProject)(client);
15
21
  if (!project) {
16
- console.error("Error: Could not retrieve project data. Is the API token correct?");
22
+ logger.error("Error: Could not retrieve project data. Is the API token correct?");
17
23
  process.exit(1);
18
24
  }
19
25
  const projectName = `${project.organization.name}/${project.name}`;
20
- console.log(`Project: ${projectName}`);
26
+ logger.info(`Project: ${projectName}`);
21
27
  // 2. Guess commit SHA1
22
28
  const commitSha = await (0, commit_sha_utils_1.getCommitSha)(commitSha_);
23
29
  if (!commitSha) {
24
- console.error("Error: Could not guess commit SHA1, aborting");
30
+ logger.error("Error: Could not guess commit SHA1, aborting");
25
31
  process.exit(1);
26
32
  }
27
- console.log(`Commit: ${commitSha}`);
33
+ logger.info(`Commit: ${commitSha}`);
28
34
  // 3. Create zip archive of build artifacts
29
- console.log(`Uploading build artifacts from: ${dist}`);
35
+ logger.info(`Uploading build artifacts from: ${dist}`);
30
36
  try {
31
37
  await (0, archive_1.checkDistFolder)(dist);
32
38
  }
33
39
  catch (error) {
34
40
  if (error instanceof Error) {
35
- console.error(`Error: ${error.message}`);
41
+ logger.error(`Error: ${error.message}`);
36
42
  }
37
43
  else {
38
- console.error(`Error: ${error}`);
44
+ logger.error(`Error: ${error}`);
39
45
  }
40
46
  process.exit(1);
41
47
  }
@@ -44,7 +50,7 @@ const handler = async ({ apiToken, commitSha: commitSha_, dist, }) => {
44
50
  const projectBuild = await (0, project_build_api_1.createProjectBuild)(client, commitSha);
45
51
  const uploadUrlData = await (0, project_build_api_1.getProjectBuildPushUrl)(client, projectBuild.id);
46
52
  if (!uploadUrlData) {
47
- console.error("Error: Could not get a push URL from the Meticulous API");
53
+ logger.error("Error: Could not get a push URL from the Meticulous API");
48
54
  process.exit(1);
49
55
  }
50
56
  const uploadUrl = uploadUrlData.pushUrl;
@@ -53,14 +59,14 @@ const handler = async ({ apiToken, commitSha: commitSha_, dist, }) => {
53
59
  await (0, upload_1.uploadArchive)(uploadUrl, archivePath);
54
60
  }
55
61
  catch (error) {
56
- await (0, project_build_api_1.putProjectBuildPushedStatus)(client, projectBuild.id, "failure").catch((updateError) => console.error(updateError));
57
- console.error(error);
62
+ await (0, project_build_api_1.putProjectBuildPushedStatus)(client, projectBuild.id, "failure").catch((updateError) => logger.error(updateError));
63
+ logger.error(error);
58
64
  process.exit(1);
59
65
  }
60
66
  // 6. Report successful upload to Meticulous
61
67
  const updatedProjectBuild = await (0, project_build_api_1.putProjectBuildPushedStatus)(client, projectBuild.id, "success");
62
- console.log("Build artifacts successfully sent to Meticulous");
63
- console.log(updatedProjectBuild);
68
+ logger.info("Build artifacts successfully sent to Meticulous");
69
+ logger.debug(updatedProjectBuild);
64
70
  await (0, archive_1.deleteArchive)(archivePath);
65
71
  };
66
72
  exports.uploadBuild = {
@@ -7,6 +7,7 @@ exports.fetchAsset = exports.saveAssetMetadata = exports.loadAssetMetadata = voi
7
7
  const common_1 = require("@alwaysmeticulous/common");
8
8
  const axios_1 = __importDefault(require("axios"));
9
9
  const promises_1 = require("fs/promises");
10
+ const loglevel_1 = __importDefault(require("loglevel"));
10
11
  const path_1 = require("path");
11
12
  const loadAssetMetadata = async () => {
12
13
  const assetsDir = (0, path_1.join)((0, common_1.getMeticulousLocalDataDir)(), "assets");
@@ -29,6 +30,7 @@ const saveAssetMetadata = async (assetMetadata) => {
29
30
  };
30
31
  exports.saveAssetMetadata = saveAssetMetadata;
31
32
  const fetchAsset = async (fetchUrl) => {
33
+ const logger = loglevel_1.default.getLogger(common_1.METICULOUS_LOGGER_NAME);
32
34
  const assetsDir = (0, path_1.join)((0, common_1.getMeticulousLocalDataDir)(), "assets");
33
35
  const assetMetadata = await (0, exports.loadAssetMetadata)();
34
36
  const etag = (await axios_1.default.head(fetchUrl)).headers["etag"] || "";
@@ -38,17 +40,17 @@ const fetchAsset = async (fetchUrl) => {
38
40
  : (0, path_1.basename)(new URL(fetchUrl).pathname);
39
41
  const filePath = (0, path_1.join)(assetsDir, fileName);
40
42
  if (entry && etag === entry.etag) {
41
- console.log(`${fetchUrl} already present`);
43
+ logger.debug(`${fetchUrl} already present`);
42
44
  return filePath;
43
45
  }
44
46
  const contents = (await axios_1.default.get(fetchUrl)).data;
45
47
  await (0, promises_1.writeFile)(filePath, contents);
46
48
  if (entry) {
47
- console.log(`${fetchUrl} updated`);
49
+ logger.debug(`${fetchUrl} updated`);
48
50
  entry.etag = etag;
49
51
  }
50
52
  else {
51
- console.log(`${fetchUrl} downloaded`);
53
+ logger.debug(`${fetchUrl} downloaded`);
52
54
  assetMetadata.assets.push({ fileName, etag, fetchUrl });
53
55
  }
54
56
  await (0, exports.saveAssetMetadata)(assetMetadata);