@lambdatest/smartui-cli 3.0.10 → 3.0.12

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 (2) hide show
  1. package/dist/index.cjs +470 -369
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -4,11 +4,10 @@
4
4
  var commander = require('commander');
5
5
  var which = require('which');
6
6
  var listr2 = require('listr2');
7
- var chalk8 = require('chalk');
7
+ var chalk7 = require('chalk');
8
8
  var path2 = require('path');
9
9
  var fastify = require('fastify');
10
10
  var fs5 = require('fs');
11
- var test = require('@playwright/test');
12
11
  var Ajv = require('ajv');
13
12
  var addErrors = require('ajv-errors');
14
13
  var winston = require('winston');
@@ -16,11 +15,12 @@ var FormData = require('form-data');
16
15
  var axios = require('axios');
17
16
  var child_process = require('child_process');
18
17
  var spawn = require('cross-spawn');
18
+ var test = require('@playwright/test');
19
19
 
20
20
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
21
21
 
22
22
  var which__default = /*#__PURE__*/_interopDefault(which);
23
- var chalk8__default = /*#__PURE__*/_interopDefault(chalk8);
23
+ var chalk7__default = /*#__PURE__*/_interopDefault(chalk7);
24
24
  var path2__default = /*#__PURE__*/_interopDefault(path2);
25
25
  var fastify__default = /*#__PURE__*/_interopDefault(fastify);
26
26
  var fs5__default = /*#__PURE__*/_interopDefault(fs5);
@@ -315,326 +315,7 @@ var constants_default = {
315
315
  }
316
316
  };
317
317
 
318
- // src/lib/utils.ts
319
- function delDir(dir) {
320
- if (fs5__default.default.existsSync(dir)) {
321
- fs5__default.default.rmSync(dir, { recursive: true });
322
- }
323
- }
324
- function scrollToBottomAndBackToTop({
325
- frequency = 100,
326
- timing = 8,
327
- remoteWindow = window
328
- } = {}) {
329
- return new Promise((resolve) => {
330
- let scrolls = 1;
331
- let scrollLength = remoteWindow.document.body.scrollHeight / frequency;
332
- (function scroll() {
333
- let scrollBy = scrollLength * scrolls;
334
- remoteWindow.setTimeout(() => {
335
- remoteWindow.scrollTo(0, scrollBy);
336
- if (scrolls < frequency) {
337
- scrolls += 1;
338
- scroll();
339
- }
340
- if (scrolls === frequency) {
341
- remoteWindow.setTimeout(() => {
342
- remoteWindow.scrollTo(0, 0);
343
- resolve();
344
- }, timing);
345
- }
346
- }, timing);
347
- })();
348
- });
349
- }
350
- function launchBrowsers(ctx) {
351
- return __async(this, null, function* () {
352
- let browsers = {};
353
- let launchOptions = { headless: true };
354
- if (ctx.config.web) {
355
- for (const browser of ctx.config.web.browsers) {
356
- switch (browser) {
357
- case constants_default.CHROME:
358
- browsers[constants_default.CHROME] = yield test.chromium.launch(launchOptions);
359
- break;
360
- case constants_default.SAFARI:
361
- browsers[constants_default.SAFARI] = yield test.webkit.launch(launchOptions);
362
- break;
363
- case constants_default.FIREFOX:
364
- browsers[constants_default.FIREFOX] = yield test.firefox.launch(launchOptions);
365
- break;
366
- case constants_default.EDGE:
367
- browsers[constants_default.EDGE] = yield test.chromium.launch(__spreadValues({ channel: constants_default.EDGE_CHANNEL }, launchOptions));
368
- break;
369
- }
370
- }
371
- }
372
- if (ctx.config.mobile) {
373
- for (const device of ctx.config.mobile.devices) {
374
- if (constants_default.SUPPORTED_MOBILE_DEVICES[device].os === "android" && !browsers[constants_default.CHROME])
375
- browsers[constants_default.CHROME] = yield test.chromium.launch(launchOptions);
376
- else if (constants_default.SUPPORTED_MOBILE_DEVICES[device].os === "ios" && !browsers[constants_default.SAFARI])
377
- browsers[constants_default.SAFARI] = yield test.webkit.launch(launchOptions);
378
- }
379
- }
380
- return browsers;
381
- });
382
- }
383
- function closeBrowsers(browsers) {
384
- return __async(this, null, function* () {
385
- var _a;
386
- for (const browserName of Object.keys(browsers))
387
- yield (_a = browsers[browserName]) == null ? void 0 : _a.close();
388
- });
389
- }
390
- function getWebRenderViewports(ctx) {
391
- let webRenderViewports = [];
392
- if (ctx.config.web) {
393
- for (const viewport of ctx.config.web.viewports) {
394
- webRenderViewports.push({
395
- viewport,
396
- viewportString: `${viewport.width}${viewport.height ? "x" + viewport.height : ""}`,
397
- fullPage: viewport.height ? false : true,
398
- device: false
399
- });
400
- }
401
- }
402
- return webRenderViewports;
403
- }
404
- function getMobileRenderViewports(ctx) {
405
- var _a;
406
- let mobileRenderViewports = {};
407
- mobileRenderViewports[constants_default.MOBILE_OS_IOS] = [];
408
- mobileRenderViewports[constants_default.MOBILE_OS_ANDROID] = [];
409
- if (ctx.config.mobile) {
410
- for (const device of ctx.config.mobile.devices) {
411
- let os = constants_default.SUPPORTED_MOBILE_DEVICES[device].os;
412
- let { width, height } = constants_default.SUPPORTED_MOBILE_DEVICES[device].viewport;
413
- let portrait = ctx.config.mobile.orientation === constants_default.MOBILE_ORIENTATION_PORTRAIT ? true : false;
414
- (_a = mobileRenderViewports[os]) == null ? void 0 : _a.push({
415
- viewport: { width: portrait ? width : height, height: portrait ? height : width },
416
- viewportString: `${device} (${ctx.config.mobile.orientation})`,
417
- fullPage: ctx.config.mobile.fullPage,
418
- device: true,
419
- os
420
- });
421
- }
422
- }
423
- return mobileRenderViewports;
424
- }
425
- function getRenderViewports(ctx) {
426
- let mobileRenderViewports = getMobileRenderViewports(ctx);
427
- return [
428
- ...getWebRenderViewports(ctx),
429
- ...mobileRenderViewports[constants_default.MOBILE_OS_IOS],
430
- ...mobileRenderViewports[constants_default.MOBILE_OS_ANDROID]
431
- ];
432
- }
433
- var MAX_RESOURCE_SIZE = 15 * 1024 ** 2;
434
- var ALLOWED_RESOURCES = ["document", "stylesheet", "image", "media", "font", "other"];
435
- var ALLOWED_STATUSES = [200, 201];
436
- var REQUEST_TIMEOUT = 1e4;
437
- var MIN_VIEWPORT_HEIGHT = 1080;
438
- var processSnapshot_default = (snapshot, ctx) => __async(void 0, null, function* () {
439
- ctx.log.debug(`Processing snapshot ${snapshot.name}`);
440
- let launchOptions = { headless: true };
441
- let contextOptions = {
442
- javaScriptEnabled: ctx.config.enableJavaScript,
443
- userAgent: constants_default.CHROME_USER_AGENT
444
- };
445
- if (!ctx.browser) {
446
- if (ctx.env.HTTP_PROXY || ctx.env.HTTPS_PROXY)
447
- launchOptions.proxy = { server: ctx.env.HTTP_PROXY || ctx.env.HTTPS_PROXY };
448
- ctx.browser = yield test.chromium.launch(launchOptions);
449
- ctx.log.debug(`Chromium launched with options ${JSON.stringify(launchOptions)}`);
450
- }
451
- const context = yield ctx.browser.newContext(contextOptions);
452
- ctx.log.debug(`Browser context created with options ${JSON.stringify(contextOptions)}`);
453
- const page = yield context.newPage();
454
- let cache = {};
455
- yield page.route("**/*", (route, request) => __async(void 0, null, function* () {
456
- const requestUrl = request.url();
457
- const requestHostname = new URL(requestUrl).hostname;
458
- try {
459
- if (/\.(mp3|mp4|wav|ogg|webm)$/i.test(request.url())) {
460
- throw new Error("resource type mp3/mp4/wav/ogg/webm");
461
- }
462
- ctx.config.allowedHostnames.push(new URL(snapshot.url).hostname);
463
- if (ctx.config.enableJavaScript)
464
- ALLOWED_RESOURCES.push("script");
465
- const response = yield page.request.fetch(request, { timeout: REQUEST_TIMEOUT });
466
- const body = yield response.body();
467
- if (!body) {
468
- ctx.log.debug(`Handling request ${requestUrl}
469
- - skipping no response`);
470
- } else if (!body.length) {
471
- ctx.log.debug(`Handling request ${requestUrl}
472
- - skipping empty response`);
473
- } else if (requestUrl === snapshot.url) {
474
- ctx.log.debug(`Handling request ${requestUrl}
475
- - skipping root resource`);
476
- } else if (!ctx.config.allowedHostnames.includes(requestHostname)) {
477
- ctx.log.debug(`Handling request ${requestUrl}
478
- - skipping remote resource`);
479
- } else if (cache[requestUrl]) {
480
- ctx.log.debug(`Handling request ${requestUrl}
481
- - skipping already cached resource`);
482
- } else if (body.length > MAX_RESOURCE_SIZE) {
483
- ctx.log.debug(`Handling request ${requestUrl}
484
- - skipping resource larger than 15MB`);
485
- } else if (!ALLOWED_STATUSES.includes(response.status())) {
486
- ctx.log.debug(`Handling request ${requestUrl}
487
- - skipping disallowed status [${response.status()}]`);
488
- } else if (!ALLOWED_RESOURCES.includes(request.resourceType())) {
489
- ctx.log.debug(`Handling request ${requestUrl}
490
- - skipping disallowed resource type [${request.resourceType()}]`);
491
- } else {
492
- ctx.log.debug(`Handling request ${requestUrl}
493
- - content-type ${response.headers()["content-type"]}`);
494
- cache[requestUrl] = {
495
- body: body.toString("base64"),
496
- type: response.headers()["content-type"]
497
- };
498
- }
499
- route.fulfill({
500
- status: response.status(),
501
- headers: response.headers(),
502
- body
503
- });
504
- } catch (error) {
505
- ctx.log.debug(`Handling request ${requestUrl}
506
- - aborted due to ${error.message}`);
507
- route.abort();
508
- }
509
- }));
510
- let options = snapshot.options;
511
- let optionWarnings = /* @__PURE__ */ new Set();
512
- let processedOptions = {};
513
- let selectors = [];
514
- let ignoreOrSelectDOM;
515
- let ignoreOrSelectBoxes;
516
- if (options && Object.keys(options).length) {
517
- ctx.log.debug(`Snapshot options: ${JSON.stringify(options)}`);
518
- const isNotAllEmpty = (obj) => {
519
- var _a;
520
- for (let key in obj)
521
- if ((_a = obj[key]) == null ? void 0 : _a.length)
522
- return true;
523
- return false;
524
- };
525
- if (options.element && Object.keys(options.element).length) {
526
- if (options.element.id)
527
- processedOptions.element = "#" + options.element.id;
528
- else if (options.element.class)
529
- processedOptions.element = "." + options.element.class;
530
- else if (options.element.cssSelector)
531
- processedOptions.element = options.element.cssSelector;
532
- else if (options.element.xpath)
533
- processedOptions.element = "xpath=" + options.element.xpath;
534
- } else if (options.ignoreDOM && Object.keys(options.ignoreDOM).length && isNotAllEmpty(options.ignoreDOM)) {
535
- processedOptions.ignoreBoxes = {};
536
- ignoreOrSelectDOM = "ignoreDOM";
537
- ignoreOrSelectBoxes = "ignoreBoxes";
538
- } else if (options.selectDOM && Object.keys(options.selectDOM).length && isNotAllEmpty(options.selectDOM)) {
539
- processedOptions.selectBoxes = {};
540
- ignoreOrSelectDOM = "selectDOM";
541
- ignoreOrSelectBoxes = "selectBoxes";
542
- }
543
- if (ignoreOrSelectDOM) {
544
- for (const [key, value] of Object.entries(options[ignoreOrSelectDOM])) {
545
- switch (key) {
546
- case "id":
547
- selectors.push(...value.map((e) => "#" + e));
548
- break;
549
- case "class":
550
- selectors.push(...value.map((e) => "." + e));
551
- break;
552
- case "xpath":
553
- selectors.push(...value.map((e) => "xpath=" + e));
554
- break;
555
- case "cssSelector":
556
- selectors.push(...value);
557
- break;
558
- }
559
- }
560
- }
561
- }
562
- let navigated = false;
563
- let renderViewports = getRenderViewports(ctx);
564
- for (const { viewport, viewportString, fullPage } of renderViewports) {
565
- yield page.setViewportSize({ width: viewport.width, height: viewport.height || MIN_VIEWPORT_HEIGHT });
566
- ctx.log.debug(`Page resized to ${viewport.width}x${viewport.height || MIN_VIEWPORT_HEIGHT}`);
567
- if (!navigated) {
568
- try {
569
- yield page.goto(snapshot.url, { waitUntil: "domcontentloaded" });
570
- yield new Promise((r) => setTimeout(r, 1250));
571
- if (ctx.config.waitForTimeout)
572
- yield page.waitForTimeout(ctx.config.waitForTimeout);
573
- navigated = true;
574
- ctx.log.debug(`Navigated to ${snapshot.url}`);
575
- } catch (error) {
576
- ctx.log.debug(`Navigation to discovery page failed; ${error}`);
577
- throw new Error(error.message);
578
- }
579
- }
580
- if (ctx.config.enableJavaScript && fullPage)
581
- yield page.evaluate(scrollToBottomAndBackToTop);
582
- try {
583
- yield page.waitForLoadState("networkidle", { timeout: 5e3 });
584
- ctx.log.debug("Network idle 500ms");
585
- } catch (error) {
586
- ctx.log.debug(`Network idle failed due to ${error}`);
587
- }
588
- if (processedOptions.element) {
589
- let l = yield page.locator(processedOptions.element).all();
590
- if (l.length === 0) {
591
- throw new Error(`for snapshot ${snapshot.name} viewport ${viewportString}, no element found for selector ${processedOptions.element}`);
592
- } else if (l.length > 1) {
593
- throw new Error(`for snapshot ${snapshot.name} viewport ${viewportString}, multiple elements found for selector ${processedOptions.element}`);
594
- }
595
- } else if (selectors.length) {
596
- let locators = [];
597
- if (!Array.isArray(processedOptions[ignoreOrSelectBoxes][viewportString]))
598
- processedOptions[ignoreOrSelectBoxes][viewportString] = [];
599
- for (const selector of selectors) {
600
- let l = yield page.locator(selector).all();
601
- if (l.length === 0) {
602
- optionWarnings.add(`for snapshot ${snapshot.name} viewport ${viewportString}, no element found for selector ${selector}`);
603
- continue;
604
- }
605
- locators.push(...l);
606
- }
607
- for (const locator of locators) {
608
- let bb = yield locator.boundingBox();
609
- if (bb)
610
- processedOptions[ignoreOrSelectBoxes][viewportString].push({
611
- left: bb.x,
612
- top: bb.y,
613
- right: bb.x + bb.width,
614
- bottom: bb.y + bb.height
615
- });
616
- }
617
- }
618
- }
619
- if (snapshot.dom.resources.length) {
620
- for (let resource of snapshot.dom.resources) {
621
- cache[resource.url] = {
622
- body: resource.content,
623
- type: resource.mimetype
624
- };
625
- }
626
- }
627
- return {
628
- processedSnapshot: {
629
- name: snapshot.name,
630
- url: snapshot.url,
631
- dom: Buffer.from(snapshot.dom.html).toString("base64"),
632
- resources: cache,
633
- options: processedOptions
634
- },
635
- warnings: [...optionWarnings, ...snapshot.dom.warnings]
636
- };
637
- });
318
+ // src/lib/schemaValidation.ts
638
319
  var ajv = new Ajv__default.default({ allErrors: true });
639
320
  ajv.addFormat("web-url", {
640
321
  type: "string",
@@ -961,35 +642,25 @@ var server_default = (ctx) => __async(void 0, null, function* () {
961
642
  reply.code(200).send({ data: { dom: SMARTUI_DOM } });
962
643
  });
963
644
  server.post("/snapshot", opts, (request, reply) => __async(void 0, null, function* () {
645
+ var _a;
964
646
  let replyCode;
965
647
  let replyBody;
966
648
  try {
967
649
  let { snapshot, testType } = request.body;
968
650
  if (!validateSnapshot(snapshot))
969
651
  throw new Error(validateSnapshot.errors[0].message);
970
- let { processedSnapshot, warnings } = yield processSnapshot_default(snapshot, ctx);
971
- yield ctx.client.uploadSnapshot(ctx.build.id, processedSnapshot, testType, ctx.log);
972
- ctx.totalSnapshots++;
652
+ ctx.testType = testType;
653
+ (_a = ctx.snapshotQueue) == null ? void 0 : _a.enqueue(snapshot);
973
654
  replyCode = 200;
974
- replyBody = { data: { message: "success", warnings } };
655
+ replyBody = { data: { message: "success", warnings: [] } };
975
656
  } catch (error) {
976
657
  ctx.log.debug(`snapshot failed; ${error}`);
977
658
  replyCode = 500;
978
659
  replyBody = { error: { message: error.message } };
979
660
  }
980
- if (ctx.browser) {
981
- for (let context of ctx.browser.contexts()) {
982
- for (let page of context.pages()) {
983
- yield page.close();
984
- ctx.log.debug(`Closed browser page`);
985
- }
986
- yield context.close();
987
- ctx.log.debug(`Closed browser context`);
988
- }
989
- }
990
661
  return reply.code(replyCode).send(replyBody);
991
662
  }));
992
- yield server.listen({ port: 49152 });
663
+ yield server.listen({ port: ctx.options.port });
993
664
  let { port } = server.addresses()[0];
994
665
  process.env.SMARTUI_SERVER_ADDRESS = `http://localhost:${port}`;
995
666
  process.env.CYPRESS_SMARTUI_SERVER_ADDRESS = `http://localhost:${port}`;
@@ -1047,13 +718,13 @@ var logger = winston.createLogger({
1047
718
  let message = typeof info.message === "object" ? JSON.stringify(info.message) : info.message;
1048
719
  switch (info.level) {
1049
720
  case "debug":
1050
- message = chalk8__default.default.blue(message);
721
+ message = chalk7__default.default.blue(message);
1051
722
  break;
1052
723
  case "warn":
1053
- message = chalk8__default.default.yellow(message);
724
+ message = chalk7__default.default.yellow(message);
1054
725
  break;
1055
726
  case "error":
1056
- message = chalk8__default.default.red(message);
727
+ message = chalk7__default.default.red(message);
1057
728
  break;
1058
729
  }
1059
730
  return info.level === "info" ? message : `[${contextString}:${info.level}] ` + message;
@@ -1072,11 +743,11 @@ var startServer_default = (ctx) => {
1072
743
  updateLogContext({ task: "startServer" });
1073
744
  try {
1074
745
  ctx2.server = yield server_default(ctx2);
1075
- task.output = chalk8__default.default.gray(`listening on port ${(_a = ctx2.server.addresses()[0]) == null ? void 0 : _a.port}`);
746
+ task.output = chalk7__default.default.gray(`listening on port ${(_a = ctx2.server.addresses()[0]) == null ? void 0 : _a.port}`);
1076
747
  task.title = "SmartUI started";
1077
748
  } catch (error) {
1078
749
  ctx2.log.debug(error);
1079
- task.output = chalk8__default.default.gray(error.message);
750
+ task.output = chalk7__default.default.gray(error.message);
1080
751
  throw new Error("SmartUI server setup failed");
1081
752
  }
1082
753
  }),
@@ -1090,11 +761,11 @@ var auth_default = (ctx) => {
1090
761
  updateLogContext({ task: "auth" });
1091
762
  try {
1092
763
  yield ctx2.client.auth(ctx2.log);
1093
- task.output = chalk8__default.default.gray(`using project token '******#${ctx2.env.PROJECT_TOKEN.split("#").pop()}'`);
764
+ task.output = chalk7__default.default.gray(`using project token '******#${ctx2.env.PROJECT_TOKEN.split("#").pop()}'`);
1094
765
  task.title = "Authenticated with SmartUI";
1095
766
  } catch (error) {
1096
767
  ctx2.log.debug(error);
1097
- task.output = chalk8__default.default.gray(error.message);
768
+ task.output = chalk7__default.default.gray(error.message);
1098
769
  throw new Error("Authentication failed");
1099
770
  }
1100
771
  }),
@@ -1103,7 +774,7 @@ var auth_default = (ctx) => {
1103
774
  };
1104
775
 
1105
776
  // package.json
1106
- var version = "3.0.10";
777
+ var version = "3.0.12";
1107
778
  var package_default = {
1108
779
  name: "@lambdatest/smartui-cli",
1109
780
  version,
@@ -1213,19 +884,19 @@ var httpClient = class {
1213
884
  params
1214
885
  }, log);
1215
886
  }
1216
- uploadSnapshot(buildId, snapshot, testType, log) {
887
+ uploadSnapshot(ctx, snapshot) {
1217
888
  return this.request({
1218
- url: `/builds/${buildId}/snapshot`,
889
+ url: `/builds/${ctx.build.id}/snapshot`,
1219
890
  method: "POST",
1220
891
  headers: { "Content-Type": "application/json" },
1221
892
  data: {
1222
893
  snapshot,
1223
894
  test: {
1224
- type: testType,
895
+ type: ctx.testType,
1225
896
  source: "cli"
1226
897
  }
1227
898
  }
1228
- }, log);
899
+ }, ctx.log);
1229
900
  }
1230
901
  uploadScreenshot({ id: buildId, name: buildName, baseline }, ssPath, ssName, browserName, viewport, log) {
1231
902
  browserName = browserName === constants_default.SAFARI ? constants_default.WEBKIT : browserName;
@@ -1292,6 +963,7 @@ var ctx_default = (options) => {
1292
963
  let webConfig;
1293
964
  let mobileConfig;
1294
965
  let config = constants_default.DEFAULT_CONFIG;
966
+ let port;
1295
967
  try {
1296
968
  if (options.config) {
1297
969
  config = JSON.parse(fs5__default.default.readFileSync(options.config, "utf-8"));
@@ -1303,6 +975,10 @@ var ctx_default = (options) => {
1303
975
  throw new Error(validateConfig.errors[0].message);
1304
976
  }
1305
977
  }
978
+ port = parseInt(options.port || "49152", 10);
979
+ if (isNaN(port) || port < 1 || port > 65535) {
980
+ throw new Error("Invalid port number. Port number must be an integer between 1 and 65535.");
981
+ }
1306
982
  } catch (error) {
1307
983
  console.log(`[smartui] Error: ${error.message}`);
1308
984
  process.exit();
@@ -1349,7 +1025,8 @@ var ctx_default = (options) => {
1349
1025
  options: {
1350
1026
  parallel: options.parallel ? true : false,
1351
1027
  markBaseline: options.markBaseline ? true : false,
1352
- buildName: options.buildName || ""
1028
+ buildName: options.buildName || "",
1029
+ port
1353
1030
  },
1354
1031
  cliVersion: version,
1355
1032
  totalSnapshots: -1
@@ -1416,11 +1093,11 @@ var getGitInfo_default = (ctx) => {
1416
1093
  }
1417
1094
  try {
1418
1095
  ctx2.git = git_default(ctx2);
1419
- task.output = chalk8__default.default.gray(`branch: ${ctx2.git.branch}, commit: ${ctx2.git.commitId}, author: ${ctx2.git.commitAuthor}`);
1096
+ task.output = chalk7__default.default.gray(`branch: ${ctx2.git.branch}, commit: ${ctx2.git.commitId}, author: ${ctx2.git.commitAuthor}`);
1420
1097
  task.title = "Fetched git information";
1421
1098
  } catch (error) {
1422
1099
  ctx2.log.debug(error);
1423
- task.output = chalk8__default.default.gray(`${error.message}`);
1100
+ task.output = chalk7__default.default.gray(`${error.message}`);
1424
1101
  throw new Error("Error fetching git repo details");
1425
1102
  }
1426
1103
  }),
@@ -1440,11 +1117,11 @@ var createBuild_default = (ctx) => {
1440
1117
  url: resp.data.buildURL,
1441
1118
  baseline: resp.data.baseline
1442
1119
  };
1443
- task.output = chalk8__default.default.gray(`build id: ${resp.data.buildId}`);
1120
+ task.output = chalk7__default.default.gray(`build id: ${resp.data.buildId}`);
1444
1121
  task.title = "SmartUI build created";
1445
1122
  } catch (error) {
1446
1123
  ctx2.log.debug(error);
1447
- task.output = chalk8__default.default.gray(error.message);
1124
+ task.output = chalk7__default.default.gray(error.message);
1448
1125
  throw new Error("SmartUI build creation failed");
1449
1126
  }
1450
1127
  }),
@@ -1463,13 +1140,13 @@ var exec_default = (ctx) => {
1463
1140
  let totalOutput = "";
1464
1141
  const output = listr2.createWritable((chunk) => {
1465
1142
  totalOutput += chunk;
1466
- task.output = chalk8__default.default.gray(totalOutput);
1143
+ task.output = chalk7__default.default.gray(totalOutput);
1467
1144
  });
1468
1145
  (_b = childProcess.stdout) == null ? void 0 : _b.pipe(output);
1469
1146
  (_c = childProcess.stderr) == null ? void 0 : _c.pipe(output);
1470
1147
  childProcess.on("error", (error) => {
1471
1148
  var _a3;
1472
- task.output = chalk8__default.default.gray(`error: ${error.message}`);
1149
+ task.output = chalk7__default.default.gray(`error: ${error.message}`);
1473
1150
  throw new Error(`Execution of '${(_a3 = ctx2.args.execCommand) == null ? void 0 : _a3.join(" ")}' failed`);
1474
1151
  });
1475
1152
  childProcess.on("close", (code, signal) => __async(void 0, null, function* () {
@@ -1487,6 +1164,46 @@ var exec_default = (ctx) => {
1487
1164
  exitOnError: false
1488
1165
  };
1489
1166
  };
1167
+ var processSnapshot_default = (ctx) => {
1168
+ return {
1169
+ title: `Processing snapshots`,
1170
+ task: (ctx2, task) => __async(void 0, null, function* () {
1171
+ var _a;
1172
+ try {
1173
+ yield new Promise((resolve) => {
1174
+ let output2 = "";
1175
+ const intervalId = setInterval(() => {
1176
+ var _a2, _b, _c;
1177
+ if (((_a2 = ctx2.snapshotQueue) == null ? void 0 : _a2.isEmpty()) && !((_b = ctx2.snapshotQueue) == null ? void 0 : _b.isProcessing())) {
1178
+ clearInterval(intervalId);
1179
+ resolve();
1180
+ } else {
1181
+ task.title = `Processing snapshot ${(_c = ctx2.snapshotQueue) == null ? void 0 : _c.getProcessingSnapshot()}`;
1182
+ }
1183
+ }, 500);
1184
+ });
1185
+ let output = "";
1186
+ for (let snapshot of (_a = ctx2.snapshotQueue) == null ? void 0 : _a.getProcessedSnapshots()) {
1187
+ if (snapshot.error)
1188
+ output += `${chalk7__default.default.red("\u2717")} ${chalk7__default.default.gray(`${snapshot.name}
1189
+ [error] ${snapshot.error}`)}
1190
+ `;
1191
+ else
1192
+ output += `${chalk7__default.default.green("\u2713")} ${chalk7__default.default.gray(snapshot.name)}
1193
+ ${snapshot.warnings.length ? chalk7__default.default.gray(`[warning] ${snapshot.warnings.join("\n[warning] ")}
1194
+ `) : ""}`;
1195
+ }
1196
+ task.output = output;
1197
+ task.title = "Processed snapshots";
1198
+ } catch (error) {
1199
+ ctx2.log.debug(error);
1200
+ task.output = chalk7__default.default.gray(error.message);
1201
+ throw new Error("Processing of snapshots failed");
1202
+ }
1203
+ }),
1204
+ rendererOptions: { persistentOutput: true }
1205
+ };
1206
+ };
1490
1207
  var finalizeBuild_default = (ctx) => {
1491
1208
  return {
1492
1209
  title: `Finalizing build`,
@@ -1495,21 +1212,401 @@ var finalizeBuild_default = (ctx) => {
1495
1212
  try {
1496
1213
  yield new Promise((resolve) => setTimeout(resolve, 2e3));
1497
1214
  yield ctx2.client.finalizeBuild(ctx2.build.id, ctx2.totalSnapshots, ctx2.log);
1498
- task.output = chalk8__default.default.gray(`build url: ${ctx2.build.url}`);
1215
+ task.output = chalk7__default.default.gray(`build url: ${ctx2.build.url}`);
1499
1216
  task.title = "Finalized build";
1500
1217
  } catch (error) {
1501
1218
  ctx2.log.debug(error);
1502
- task.output = chalk8__default.default.gray(error.message);
1219
+ task.output = chalk7__default.default.gray(error.message);
1503
1220
  throw new Error("Finalize build failed");
1504
1221
  }
1505
1222
  }),
1506
1223
  rendererOptions: { persistentOutput: true }
1507
1224
  };
1508
1225
  };
1226
+ function delDir(dir) {
1227
+ if (fs5__default.default.existsSync(dir)) {
1228
+ fs5__default.default.rmSync(dir, { recursive: true });
1229
+ }
1230
+ }
1231
+ function scrollToBottomAndBackToTop({
1232
+ frequency = 100,
1233
+ timing = 8,
1234
+ remoteWindow = window
1235
+ } = {}) {
1236
+ return new Promise((resolve) => {
1237
+ let scrolls = 1;
1238
+ let scrollLength = remoteWindow.document.body.scrollHeight / frequency;
1239
+ (function scroll() {
1240
+ let scrollBy = scrollLength * scrolls;
1241
+ remoteWindow.setTimeout(() => {
1242
+ remoteWindow.scrollTo(0, scrollBy);
1243
+ if (scrolls < frequency) {
1244
+ scrolls += 1;
1245
+ scroll();
1246
+ }
1247
+ if (scrolls === frequency) {
1248
+ remoteWindow.setTimeout(() => {
1249
+ remoteWindow.scrollTo(0, 0);
1250
+ resolve();
1251
+ }, timing);
1252
+ }
1253
+ }, timing);
1254
+ })();
1255
+ });
1256
+ }
1257
+ function launchBrowsers(ctx) {
1258
+ return __async(this, null, function* () {
1259
+ let browsers = {};
1260
+ let launchOptions = { headless: true };
1261
+ if (ctx.config.web) {
1262
+ for (const browser of ctx.config.web.browsers) {
1263
+ switch (browser) {
1264
+ case constants_default.CHROME:
1265
+ browsers[constants_default.CHROME] = yield test.chromium.launch(launchOptions);
1266
+ break;
1267
+ case constants_default.SAFARI:
1268
+ browsers[constants_default.SAFARI] = yield test.webkit.launch(launchOptions);
1269
+ break;
1270
+ case constants_default.FIREFOX:
1271
+ browsers[constants_default.FIREFOX] = yield test.firefox.launch(launchOptions);
1272
+ break;
1273
+ case constants_default.EDGE:
1274
+ browsers[constants_default.EDGE] = yield test.chromium.launch(__spreadValues({ channel: constants_default.EDGE_CHANNEL }, launchOptions));
1275
+ break;
1276
+ }
1277
+ }
1278
+ }
1279
+ if (ctx.config.mobile) {
1280
+ for (const device of ctx.config.mobile.devices) {
1281
+ if (constants_default.SUPPORTED_MOBILE_DEVICES[device].os === "android" && !browsers[constants_default.CHROME])
1282
+ browsers[constants_default.CHROME] = yield test.chromium.launch(launchOptions);
1283
+ else if (constants_default.SUPPORTED_MOBILE_DEVICES[device].os === "ios" && !browsers[constants_default.SAFARI])
1284
+ browsers[constants_default.SAFARI] = yield test.webkit.launch(launchOptions);
1285
+ }
1286
+ }
1287
+ return browsers;
1288
+ });
1289
+ }
1290
+ function closeBrowsers(browsers) {
1291
+ return __async(this, null, function* () {
1292
+ var _a;
1293
+ for (const browserName of Object.keys(browsers))
1294
+ yield (_a = browsers[browserName]) == null ? void 0 : _a.close();
1295
+ });
1296
+ }
1297
+ function getWebRenderViewports(ctx) {
1298
+ let webRenderViewports = [];
1299
+ if (ctx.config.web) {
1300
+ for (const viewport of ctx.config.web.viewports) {
1301
+ webRenderViewports.push({
1302
+ viewport,
1303
+ viewportString: `${viewport.width}${viewport.height ? "x" + viewport.height : ""}`,
1304
+ fullPage: viewport.height ? false : true,
1305
+ device: false
1306
+ });
1307
+ }
1308
+ }
1309
+ return webRenderViewports;
1310
+ }
1311
+ function getMobileRenderViewports(ctx) {
1312
+ var _a;
1313
+ let mobileRenderViewports = {};
1314
+ mobileRenderViewports[constants_default.MOBILE_OS_IOS] = [];
1315
+ mobileRenderViewports[constants_default.MOBILE_OS_ANDROID] = [];
1316
+ if (ctx.config.mobile) {
1317
+ for (const device of ctx.config.mobile.devices) {
1318
+ let os = constants_default.SUPPORTED_MOBILE_DEVICES[device].os;
1319
+ let { width, height } = constants_default.SUPPORTED_MOBILE_DEVICES[device].viewport;
1320
+ let portrait = ctx.config.mobile.orientation === constants_default.MOBILE_ORIENTATION_PORTRAIT ? true : false;
1321
+ (_a = mobileRenderViewports[os]) == null ? void 0 : _a.push({
1322
+ viewport: { width: portrait ? width : height, height: portrait ? height : width },
1323
+ viewportString: `${device} (${ctx.config.mobile.orientation})`,
1324
+ fullPage: ctx.config.mobile.fullPage,
1325
+ device: true,
1326
+ os
1327
+ });
1328
+ }
1329
+ }
1330
+ return mobileRenderViewports;
1331
+ }
1332
+ function getRenderViewports(ctx) {
1333
+ let mobileRenderViewports = getMobileRenderViewports(ctx);
1334
+ return [
1335
+ ...getWebRenderViewports(ctx),
1336
+ ...mobileRenderViewports[constants_default.MOBILE_OS_IOS],
1337
+ ...mobileRenderViewports[constants_default.MOBILE_OS_ANDROID]
1338
+ ];
1339
+ }
1340
+ var MAX_RESOURCE_SIZE = 15 * 1024 ** 2;
1341
+ var ALLOWED_RESOURCES = ["document", "stylesheet", "image", "media", "font", "other"];
1342
+ var ALLOWED_STATUSES = [200, 201];
1343
+ var REQUEST_TIMEOUT = 1e4;
1344
+ var MIN_VIEWPORT_HEIGHT = 1080;
1345
+ var Queue = class {
1346
+ constructor(ctx) {
1347
+ this.snapshots = [];
1348
+ this.processedSnapshots = [];
1349
+ this.processing = false;
1350
+ this.processingSnapshot = "";
1351
+ this.ctx = ctx;
1352
+ }
1353
+ enqueue(item) {
1354
+ this.snapshots.push(item);
1355
+ if (!this.processing) {
1356
+ this.processing = true;
1357
+ this.processNext();
1358
+ }
1359
+ }
1360
+ processNext() {
1361
+ return __async(this, null, function* () {
1362
+ if (!this.isEmpty()) {
1363
+ const snapshot = this.snapshots.shift();
1364
+ try {
1365
+ this.processingSnapshot = snapshot == null ? void 0 : snapshot.name;
1366
+ let { processedSnapshot, warnings } = yield processSnapshot(snapshot, this.ctx);
1367
+ yield this.ctx.client.uploadSnapshot(this.ctx, processedSnapshot);
1368
+ this.ctx.totalSnapshots++;
1369
+ this.processedSnapshots.push({ name: snapshot.name, warnings });
1370
+ } catch (error) {
1371
+ this.ctx.log.debug(`snapshot failed; ${error}`);
1372
+ this.processedSnapshots.push({ name: snapshot.name, error: error.message });
1373
+ }
1374
+ if (this.ctx.browser) {
1375
+ for (let context of this.ctx.browser.contexts()) {
1376
+ for (let page of context.pages()) {
1377
+ yield page.close();
1378
+ this.ctx.log.debug(`Closed browser page for snapshot ${snapshot.name}`);
1379
+ }
1380
+ yield context.close();
1381
+ this.ctx.log.debug(`Closed browser context for snapshot ${snapshot.name}`);
1382
+ }
1383
+ }
1384
+ this.processNext();
1385
+ } else {
1386
+ this.processing = false;
1387
+ }
1388
+ });
1389
+ }
1390
+ isProcessing() {
1391
+ return this.processing;
1392
+ }
1393
+ getProcessingSnapshot() {
1394
+ return this.processingSnapshot;
1395
+ }
1396
+ getProcessedSnapshots() {
1397
+ return this.processedSnapshots;
1398
+ }
1399
+ isEmpty() {
1400
+ return this.snapshots.length ? false : true;
1401
+ }
1402
+ };
1403
+ function processSnapshot(snapshot, ctx) {
1404
+ return __async(this, null, function* () {
1405
+ var _a;
1406
+ ctx.log.debug(`Processing snapshot ${snapshot.name}`);
1407
+ let launchOptions = { headless: true };
1408
+ let contextOptions = {
1409
+ javaScriptEnabled: ctx.config.enableJavaScript,
1410
+ userAgent: constants_default.CHROME_USER_AGENT
1411
+ };
1412
+ if (!((_a = ctx.browser) == null ? void 0 : _a.isConnected())) {
1413
+ if (ctx.env.HTTP_PROXY || ctx.env.HTTPS_PROXY)
1414
+ launchOptions.proxy = { server: ctx.env.HTTP_PROXY || ctx.env.HTTPS_PROXY };
1415
+ ctx.browser = yield test.chromium.launch(launchOptions);
1416
+ ctx.log.debug(`Chromium launched with options ${JSON.stringify(launchOptions)}`);
1417
+ }
1418
+ const context = yield ctx.browser.newContext(contextOptions);
1419
+ ctx.log.debug(`Browser context created with options ${JSON.stringify(contextOptions)}`);
1420
+ const page = yield context.newPage();
1421
+ let cache = {};
1422
+ yield page.route("**/*", (route, request) => __async(this, null, function* () {
1423
+ const requestUrl = request.url();
1424
+ const requestHostname = new URL(requestUrl).hostname;
1425
+ try {
1426
+ if (/\.(mp3|mp4|wav|ogg|webm)$/i.test(request.url())) {
1427
+ throw new Error("resource type mp3/mp4/wav/ogg/webm");
1428
+ }
1429
+ ctx.config.allowedHostnames.push(new URL(snapshot.url).hostname);
1430
+ if (ctx.config.enableJavaScript)
1431
+ ALLOWED_RESOURCES.push("script");
1432
+ const response = yield page.request.fetch(request, { timeout: REQUEST_TIMEOUT });
1433
+ const body = yield response.body();
1434
+ if (!body) {
1435
+ ctx.log.debug(`Handling request ${requestUrl}
1436
+ - skipping no response`);
1437
+ } else if (!body.length) {
1438
+ ctx.log.debug(`Handling request ${requestUrl}
1439
+ - skipping empty response`);
1440
+ } else if (requestUrl === snapshot.url) {
1441
+ ctx.log.debug(`Handling request ${requestUrl}
1442
+ - skipping root resource`);
1443
+ } else if (!ctx.config.allowedHostnames.includes(requestHostname)) {
1444
+ ctx.log.debug(`Handling request ${requestUrl}
1445
+ - skipping remote resource`);
1446
+ } else if (cache[requestUrl]) {
1447
+ ctx.log.debug(`Handling request ${requestUrl}
1448
+ - skipping already cached resource`);
1449
+ } else if (body.length > MAX_RESOURCE_SIZE) {
1450
+ ctx.log.debug(`Handling request ${requestUrl}
1451
+ - skipping resource larger than 15MB`);
1452
+ } else if (!ALLOWED_STATUSES.includes(response.status())) {
1453
+ ctx.log.debug(`Handling request ${requestUrl}
1454
+ - skipping disallowed status [${response.status()}]`);
1455
+ } else if (!ALLOWED_RESOURCES.includes(request.resourceType())) {
1456
+ ctx.log.debug(`Handling request ${requestUrl}
1457
+ - skipping disallowed resource type [${request.resourceType()}]`);
1458
+ } else {
1459
+ ctx.log.debug(`Handling request ${requestUrl}
1460
+ - content-type ${response.headers()["content-type"]}`);
1461
+ cache[requestUrl] = {
1462
+ body: body.toString("base64"),
1463
+ type: response.headers()["content-type"]
1464
+ };
1465
+ }
1466
+ route.fulfill({
1467
+ status: response.status(),
1468
+ headers: response.headers(),
1469
+ body
1470
+ });
1471
+ } catch (error) {
1472
+ ctx.log.debug(`Handling request ${requestUrl}
1473
+ - aborted due to ${error.message}`);
1474
+ route.abort();
1475
+ }
1476
+ }));
1477
+ let options = snapshot.options;
1478
+ let optionWarnings = /* @__PURE__ */ new Set();
1479
+ let processedOptions = {};
1480
+ let selectors = [];
1481
+ let ignoreOrSelectDOM;
1482
+ let ignoreOrSelectBoxes;
1483
+ if (options && Object.keys(options).length) {
1484
+ ctx.log.debug(`Snapshot options: ${JSON.stringify(options)}`);
1485
+ const isNotAllEmpty = (obj) => {
1486
+ var _a2;
1487
+ for (let key in obj)
1488
+ if ((_a2 = obj[key]) == null ? void 0 : _a2.length)
1489
+ return true;
1490
+ return false;
1491
+ };
1492
+ if (options.element && Object.keys(options.element).length) {
1493
+ if (options.element.id)
1494
+ processedOptions.element = "#" + options.element.id;
1495
+ else if (options.element.class)
1496
+ processedOptions.element = "." + options.element.class;
1497
+ else if (options.element.cssSelector)
1498
+ processedOptions.element = options.element.cssSelector;
1499
+ else if (options.element.xpath)
1500
+ processedOptions.element = "xpath=" + options.element.xpath;
1501
+ } else if (options.ignoreDOM && Object.keys(options.ignoreDOM).length && isNotAllEmpty(options.ignoreDOM)) {
1502
+ processedOptions.ignoreBoxes = {};
1503
+ ignoreOrSelectDOM = "ignoreDOM";
1504
+ ignoreOrSelectBoxes = "ignoreBoxes";
1505
+ } else if (options.selectDOM && Object.keys(options.selectDOM).length && isNotAllEmpty(options.selectDOM)) {
1506
+ processedOptions.selectBoxes = {};
1507
+ ignoreOrSelectDOM = "selectDOM";
1508
+ ignoreOrSelectBoxes = "selectBoxes";
1509
+ }
1510
+ if (ignoreOrSelectDOM) {
1511
+ for (const [key, value] of Object.entries(options[ignoreOrSelectDOM])) {
1512
+ switch (key) {
1513
+ case "id":
1514
+ selectors.push(...value.map((e) => "#" + e));
1515
+ break;
1516
+ case "class":
1517
+ selectors.push(...value.map((e) => "." + e));
1518
+ break;
1519
+ case "xpath":
1520
+ selectors.push(...value.map((e) => "xpath=" + e));
1521
+ break;
1522
+ case "cssSelector":
1523
+ selectors.push(...value);
1524
+ break;
1525
+ }
1526
+ }
1527
+ }
1528
+ }
1529
+ let navigated = false;
1530
+ let renderViewports = getRenderViewports(ctx);
1531
+ for (const { viewport, viewportString, fullPage } of renderViewports) {
1532
+ yield page.setViewportSize({ width: viewport.width, height: viewport.height || MIN_VIEWPORT_HEIGHT });
1533
+ ctx.log.debug(`Page resized to ${viewport.width}x${viewport.height || MIN_VIEWPORT_HEIGHT}`);
1534
+ if (!navigated) {
1535
+ try {
1536
+ yield page.goto(snapshot.url, { waitUntil: "domcontentloaded" });
1537
+ yield new Promise((r) => setTimeout(r, 1250));
1538
+ if (ctx.config.waitForTimeout)
1539
+ yield page.waitForTimeout(ctx.config.waitForTimeout);
1540
+ navigated = true;
1541
+ ctx.log.debug(`Navigated to ${snapshot.url}`);
1542
+ } catch (error) {
1543
+ ctx.log.debug(`Navigation to discovery page failed; ${error}`);
1544
+ throw new Error(error.message);
1545
+ }
1546
+ }
1547
+ if (ctx.config.enableJavaScript && fullPage)
1548
+ yield page.evaluate(scrollToBottomAndBackToTop);
1549
+ try {
1550
+ yield page.waitForLoadState("networkidle", { timeout: 5e3 });
1551
+ ctx.log.debug("Network idle 500ms");
1552
+ } catch (error) {
1553
+ ctx.log.debug(`Network idle failed due to ${error}`);
1554
+ }
1555
+ if (processedOptions.element) {
1556
+ let l = yield page.locator(processedOptions.element).all();
1557
+ if (l.length === 0) {
1558
+ throw new Error(`for snapshot ${snapshot.name} viewport ${viewportString}, no element found for selector ${processedOptions.element}`);
1559
+ } else if (l.length > 1) {
1560
+ throw new Error(`for snapshot ${snapshot.name} viewport ${viewportString}, multiple elements found for selector ${processedOptions.element}`);
1561
+ }
1562
+ } else if (selectors.length) {
1563
+ let locators = [];
1564
+ if (!Array.isArray(processedOptions[ignoreOrSelectBoxes][viewportString]))
1565
+ processedOptions[ignoreOrSelectBoxes][viewportString] = [];
1566
+ for (const selector of selectors) {
1567
+ let l = yield page.locator(selector).all();
1568
+ if (l.length === 0) {
1569
+ optionWarnings.add(`for snapshot ${snapshot.name} viewport ${viewportString}, no element found for selector ${selector}`);
1570
+ continue;
1571
+ }
1572
+ locators.push(...l);
1573
+ }
1574
+ for (const locator of locators) {
1575
+ let bb = yield locator.boundingBox();
1576
+ if (bb)
1577
+ processedOptions[ignoreOrSelectBoxes][viewportString].push({
1578
+ left: bb.x,
1579
+ top: bb.y,
1580
+ right: bb.x + bb.width,
1581
+ bottom: bb.y + bb.height
1582
+ });
1583
+ }
1584
+ }
1585
+ }
1586
+ if (snapshot.dom.resources.length) {
1587
+ for (let resource of snapshot.dom.resources) {
1588
+ cache[resource.url] = {
1589
+ body: resource.content,
1590
+ type: resource.mimetype
1591
+ };
1592
+ }
1593
+ }
1594
+ return {
1595
+ processedSnapshot: {
1596
+ name: snapshot.name,
1597
+ url: snapshot.url,
1598
+ dom: Buffer.from(snapshot.dom.html).toString("base64"),
1599
+ resources: cache,
1600
+ options: processedOptions
1601
+ },
1602
+ warnings: [...optionWarnings, ...snapshot.dom.warnings]
1603
+ };
1604
+ });
1605
+ }
1509
1606
 
1510
1607
  // src/commander/exec.ts
1511
1608
  var command = new commander.Command();
1512
- command.name("exec").description("Run test commands around SmartUI").argument("<command...>", "Command supplied for running tests").action(function(execCommand, _, command4) {
1609
+ command.name("exec").description("Run test commands around SmartUI").argument("<command...>", "Command supplied for running tests").option("-P, --port <number>", "Port number for the server").action(function(execCommand, _, command4) {
1513
1610
  return __async(this, null, function* () {
1514
1611
  var _a, _b;
1515
1612
  let ctx = ctx_default(command4.optsWithGlobals());
@@ -1518,6 +1615,7 @@ command.name("exec").description("Run test commands around SmartUI").argument("<
1518
1615
  return;
1519
1616
  }
1520
1617
  ctx.args.execCommand = execCommand;
1618
+ ctx.snapshotQueue = new Queue(ctx);
1521
1619
  ctx.totalSnapshots = 0;
1522
1620
  let tasks = new listr2.Listr(
1523
1621
  [
@@ -1526,6 +1624,7 @@ command.name("exec").description("Run test commands around SmartUI").argument("<
1526
1624
  getGitInfo_default(),
1527
1625
  createBuild_default(),
1528
1626
  exec_default(ctx),
1627
+ processSnapshot_default(),
1529
1628
  finalizeBuild_default()
1530
1629
  ],
1531
1630
  {
@@ -1544,8 +1643,10 @@ command.name("exec").description("Run test commands around SmartUI").argument("<
1544
1643
  } catch (error) {
1545
1644
  ctx.log.info("\nRefer docs: https://www.lambdatest.com/support/docs/smart-visual-regression-testing/");
1546
1645
  } finally {
1547
- yield (_a = ctx.server) == null ? void 0 : _a.close();
1548
- yield (_b = ctx.browser) == null ? void 0 : _b.close();
1646
+ yield (_a = ctx.browser) == null ? void 0 : _a.close();
1647
+ ctx.log.debug(`Closed browser`);
1648
+ yield (_b = ctx.server) == null ? void 0 : _b.close();
1649
+ ctx.log.debug(`Closed server`);
1549
1650
  }
1550
1651
  });
1551
1652
  });
@@ -1715,13 +1816,13 @@ function captureScreenshots(ctx) {
1715
1816
  else
1716
1817
  yield captureScreenshotsSync(ctx, staticConfig, browsers);
1717
1818
  delDir(`screenshots/${staticConfig.name.toLowerCase().replace(/\s/g, "_")}`);
1718
- output += `${chalk8__default.default.gray(staticConfig.name)} ${chalk8__default.default.green("\u2713")}
1819
+ output += `${chalk7__default.default.gray(staticConfig.name)} ${chalk7__default.default.green("\u2713")}
1719
1820
  `;
1720
1821
  ctx.task.output = output;
1721
1822
  capturedScreenshots++;
1722
1823
  } catch (error) {
1723
1824
  ctx.log.debug(`screenshot capture failed for ${JSON.stringify(staticConfig)}; error: ${error}`);
1724
- output += `${chalk8__default.default.gray(staticConfig.name)} ${chalk8__default.default.red("\u2717")}
1825
+ output += `${chalk7__default.default.gray(staticConfig.name)} ${chalk7__default.default.red("\u2717")}
1725
1826
  `;
1726
1827
  ctx.task.output = output;
1727
1828
  }
@@ -1745,7 +1846,7 @@ var captureScreenshots_default = (ctx) => {
1745
1846
  task.title = "Screenshots captured successfully";
1746
1847
  } catch (error) {
1747
1848
  ctx2.log.debug(error);
1748
- task.output = chalk8__default.default.gray(`${error.message}`);
1849
+ task.output = chalk7__default.default.gray(`${error.message}`);
1749
1850
  throw new Error("Capturing screenshots failed");
1750
1851
  }
1751
1852
  }),
@@ -1839,7 +1940,7 @@ var uploadFigmaDesigns_default2 = (ctx) => {
1839
1940
  ctx2.log.debug(`Figma designs processed: ${results}`);
1840
1941
  } catch (error) {
1841
1942
  ctx2.log.debug(error);
1842
- task.output = chalk8__default.default.gray(`${error.message}`);
1943
+ task.output = chalk7__default.default.gray(`${error.message}`);
1843
1944
  throw new Error("Uploading Figma designs failed");
1844
1945
  }
1845
1946
  }),
@@ -1909,13 +2010,13 @@ LambdaTest SmartUI CLI v${package_default.version}`);
1909
2010
  log.warn(`This version is deprecated. A new version ${latestVersion} is available!
1910
2011
  `);
1911
2012
  else if (package_default.version !== latestVersion)
1912
- log.info(chalk8__default.default.gray(`A new version ${latestVersion} is available!
2013
+ log.info(chalk7__default.default.gray(`A new version ${latestVersion} is available!
1913
2014
  `));
1914
2015
  else
1915
- log.info(chalk8__default.default.gray("https://www.npmjs.com/package/@lambdatest/smartui-cli\n"));
2016
+ log.info(chalk7__default.default.gray("https://www.npmjs.com/package/@lambdatest/smartui-cli\n"));
1916
2017
  } catch (error) {
1917
2018
  log.debug(error);
1918
- log.info(chalk8__default.default.gray("https://www.npmjs.com/package/@lambdatest/smartui-cli\n"));
2019
+ log.info(chalk7__default.default.gray("https://www.npmjs.com/package/@lambdatest/smartui-cli\n"));
1919
2020
  }
1920
2021
  commander_default.parse();
1921
2022
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdatest/smartui-cli",
3
- "version": "3.0.10",
3
+ "version": "3.0.12",
4
4
  "description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
5
5
  "files": [
6
6
  "dist/**/*"