@lambdatest/smartui-cli 4.1.31 → 4.1.32

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 +197 -83
  2. package/package.json +4 -1
package/dist/index.cjs CHANGED
@@ -11,7 +11,7 @@ var fs5 = require('fs');
11
11
  var Ajv = require('ajv');
12
12
  var addErrors = require('ajv-errors');
13
13
  var test = require('@playwright/test');
14
- var util = require('util');
14
+ var util$1 = require('util');
15
15
  var winston = require('winston');
16
16
  var stringify = require('json-stringify-safe');
17
17
  var FormData = require('form-data');
@@ -751,6 +751,11 @@ var ConfigSchema = {
751
751
  logFile: {
752
752
  type: "string",
753
753
  errorMessage: "Invalid config; logFile should be a string value"
754
+ },
755
+ environment: {
756
+ type: "string",
757
+ enum: ["stage", "prod"],
758
+ errorMessage: "Invalid config; environment should be a string value either stage or prod"
754
759
  }
755
760
  },
756
761
  required: ["type"],
@@ -787,6 +792,18 @@ var ConfigSchema = {
787
792
  loadDomContent: {
788
793
  type: "boolean",
789
794
  errorMessage: "Invalid config; loadDomContent must be true/false"
795
+ },
796
+ approvalThreshold: {
797
+ type: "number",
798
+ minimum: 0,
799
+ maximum: 100,
800
+ errorMessage: "Invalid config; approvalThreshold must be a number"
801
+ },
802
+ rejectionThreshold: {
803
+ type: "number",
804
+ minimum: 0,
805
+ maximum: 100,
806
+ errorMessage: "Invalid config; rejectionThreshold must be a number"
790
807
  }
791
808
  },
792
809
  anyOf: [
@@ -1048,6 +1065,18 @@ var SnapshotSchema = {
1048
1065
  useExtendedViewport: {
1049
1066
  type: "boolean",
1050
1067
  errorMessage: "Invalid snapshot options; useExtendedViewport must be a boolean"
1068
+ },
1069
+ approvalThreshold: {
1070
+ type: "number",
1071
+ minimum: 0,
1072
+ maximum: 100,
1073
+ errorMessage: "Invalid snapshot options; approvalThreshold must be a number between 0 and 100"
1074
+ },
1075
+ rejectionThreshold: {
1076
+ type: "number",
1077
+ minimum: 0,
1078
+ maximum: 100,
1079
+ errorMessage: "Invalid snapshot options; rejectionThreshold must be a number between 0 and 100"
1051
1080
  }
1052
1081
  },
1053
1082
  additionalProperties: false
@@ -1335,8 +1364,9 @@ var validateConfigForScheduled = (config) => {
1335
1364
  return true;
1336
1365
  };
1337
1366
  validateConfigForScheduled.errors = null;
1367
+ var util = __require("util");
1338
1368
  var lambdaTunnel = __require("@lambdatest/node-tunnel");
1339
- util.promisify(setTimeout);
1369
+ util$1.promisify(setTimeout);
1340
1370
  var tunnelInstance;
1341
1371
  function delDir(dir) {
1342
1372
  if (fs5__default.default.existsSync(dir)) {
@@ -1526,9 +1556,9 @@ function startPolling(ctx, build_id, baseline, projectToken) {
1526
1556
  try {
1527
1557
  let resp;
1528
1558
  if (build_id) {
1529
- resp = yield ctx.client.getScreenshotData(build_id, baseline, ctx.log, projectToken);
1559
+ resp = yield ctx.client.getScreenshotData(build_id, baseline, ctx.log, projectToken, "");
1530
1560
  } else if (ctx.build && ctx.build.id) {
1531
- resp = yield ctx.client.getScreenshotData(ctx.build.id, ctx.build.baseline, ctx.log, "");
1561
+ resp = yield ctx.client.getScreenshotData(ctx.build.id, ctx.build.baseline, ctx.log, "", "");
1532
1562
  } else {
1533
1563
  return;
1534
1564
  }
@@ -1600,11 +1630,12 @@ function startPingPolling(ctx) {
1600
1630
  } catch (error) {
1601
1631
  ctx.log.error(`Error during initial ping: ${error.message}`);
1602
1632
  }
1633
+ let sourceCommand = ctx.sourceCommand ? ctx.sourceCommand : "";
1603
1634
  pingIntervalId = setInterval(() => __async(this, null, function* () {
1604
1635
  try {
1605
- ctx.log.debug("Sending ping to server...");
1636
+ ctx.log.debug("Sending ping to server... " + sourceCommand);
1606
1637
  yield ctx.client.ping(ctx.build.id, ctx.log);
1607
- ctx.log.debug("Ping sent successfully.");
1638
+ ctx.log.debug("Ping sent successfully. " + sourceCommand);
1608
1639
  } catch (error) {
1609
1640
  ctx.log.error(`Error during ping polling: ${error.message}`);
1610
1641
  }
@@ -1654,6 +1685,9 @@ function startTunnelBinary(ctx) {
1654
1685
  tunnelArguments.tunnelName = randomTunnelName;
1655
1686
  ctx.config.tunnel.tunnelName = randomTunnelName;
1656
1687
  }
1688
+ if (tunnelConfig == null ? void 0 : tunnelConfig.environment) {
1689
+ tunnelArguments.environment = tunnelConfig.environment;
1690
+ }
1657
1691
  ctx.log.debug(`tunnel config ${JSON.stringify(tunnelArguments)}`);
1658
1692
  if (((_a = ctx.config.tunnel) == null ? void 0 : _a.type) === "auto") {
1659
1693
  tunnelInstance = new lambdaTunnel();
@@ -1664,50 +1698,59 @@ function startTunnelBinary(ctx) {
1664
1698
  }
1665
1699
  });
1666
1700
  }
1667
- function startPollingForTunnel(ctx, build_id, baseline, projectToken) {
1701
+ var isTunnelPolling = null;
1702
+ function startPollingForTunnel(ctx, build_id, baseline, projectToken, buildName) {
1668
1703
  return __async(this, null, function* () {
1704
+ if (isTunnelPolling) {
1705
+ ctx.log.debug("Tunnel polling is already active. Skipping for build_id: " + build_id);
1706
+ return;
1707
+ }
1669
1708
  const intervalId = setInterval(() => __async(this, null, function* () {
1670
1709
  try {
1671
1710
  let resp;
1672
- if (build_id) ; else if (ctx.build && ctx.build.id) {
1673
- resp = yield ctx.client.getScreenshotData(ctx.build.id, ctx.build.baseline, ctx.log, "");
1711
+ if (build_id) {
1712
+ resp = yield ctx.client.getScreenshotData(build_id, baseline, ctx.log, projectToken, buildName);
1713
+ } else if (ctx.build && ctx.build.id) {
1714
+ resp = yield ctx.client.getScreenshotData(ctx.build.id, ctx.build.baseline, ctx.log, "", "");
1674
1715
  } else {
1716
+ ctx.log.debug("No build information available for polling tunnel status.");
1717
+ clearInterval(intervalId);
1718
+ yield stopTunnelHelper(ctx);
1675
1719
  return;
1676
1720
  }
1721
+ ctx.log.debug(" resp from polling for tunnel status: " + JSON.stringify(resp));
1677
1722
  if (!resp.build) {
1678
1723
  ctx.log.info("Error: Build data is null.");
1679
1724
  clearInterval(intervalId);
1680
- const tunnelRunningStatus = yield tunnelInstance.isRunning();
1681
- ctx.log.debug("Running status of tunnel before stopping ? " + tunnelRunningStatus);
1682
- const status = yield tunnelInstance.stop();
1683
- ctx.log.debug("Tunnel is Stopped ? " + status);
1725
+ yield stopTunnelHelper(ctx);
1684
1726
  return;
1685
1727
  }
1686
1728
  if (resp.build.build_status_ind === constants_default.BUILD_COMPLETE || resp.build.build_status_ind === constants_default.BUILD_ERROR) {
1687
1729
  clearInterval(intervalId);
1688
- const tunnelRunningStatus = yield tunnelInstance.isRunning();
1689
- ctx.log.debug("Running status of tunnel before stopping ? " + tunnelRunningStatus);
1690
- const status = yield tunnelInstance.stop();
1691
- ctx.log.debug("Tunnel is Stopped ? " + status);
1730
+ yield stopTunnelHelper(ctx);
1731
+ return;
1692
1732
  }
1693
1733
  } catch (error) {
1694
- if (error.message.includes("ENOTFOUND")) {
1734
+ if (error == null ? void 0 : error.message.includes("ENOTFOUND")) {
1695
1735
  ctx.log.error("Error: Network error occurred while fetching build status while polling. Please check your connection and try again.");
1696
1736
  clearInterval(intervalId);
1697
1737
  } else {
1698
- ctx.log.error(`Error fetching build status while polling: ${error.message}`);
1738
+ ctx.log.debug(util.inspect(error, { showHidden: false, depth: null }));
1739
+ ctx.log.error(`Error fetching build status while polling: ${JSON.stringify(error)}`);
1699
1740
  }
1700
1741
  clearInterval(intervalId);
1701
1742
  }
1702
1743
  }), 5e3);
1744
+ isTunnelPolling = intervalId;
1703
1745
  });
1704
1746
  }
1705
1747
  function stopTunnelHelper(ctx) {
1706
1748
  return __async(this, null, function* () {
1749
+ ctx.log.debug("stop-tunnel:: Stopping the tunnel now");
1707
1750
  const tunnelRunningStatus = yield tunnelInstance.isRunning();
1708
- ctx.log.debug("Running status of tunnel before stopping ? " + tunnelRunningStatus);
1751
+ ctx.log.debug("stop-tunnel:: Running status of tunnel before stopping ? " + tunnelRunningStatus);
1709
1752
  const status = yield tunnelInstance.stop();
1710
- ctx.log.debug("Tunnel is Stopped ? " + status);
1753
+ ctx.log.debug("stop-tunnel:: Tunnel is Stopped ? " + status);
1711
1754
  });
1712
1755
  }
1713
1756
  function calculateVariantCount(config) {
@@ -1936,23 +1979,28 @@ var server_default = (ctx) => __async(void 0, null, function* () {
1936
1979
  reply.code(200).send({ data: { dom: SMARTUI_DOM } });
1937
1980
  });
1938
1981
  server.post("/snapshot", opts, (request, reply) => __async(void 0, null, function* () {
1939
- var _a, _b, _c, _d, _e;
1982
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1940
1983
  let replyCode;
1941
1984
  let replyBody;
1942
1985
  try {
1943
1986
  let { snapshot, testType } = request.body;
1944
1987
  if (!validateSnapshot(snapshot))
1945
1988
  throw new Error(validateSnapshot.errors[0].message);
1946
- const sessionId = (_a = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _a.sessionId;
1989
+ if (((_a = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _a.approvalThreshold) !== void 0 && ((_b = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _b.rejectionThreshold) !== void 0) {
1990
+ if (((_c = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _c.rejectionThreshold) <= ((_d = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _d.approvalThreshold)) {
1991
+ throw new Error(`Invalid snapshot options; rejectionThreshold (${snapshot.options.rejectionThreshold}) must be greater than approvalThreshold (${snapshot.options.approvalThreshold})`);
1992
+ }
1993
+ }
1994
+ const sessionId = (_e = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _e.sessionId;
1947
1995
  let capsBuildId = "";
1948
- const contextId = (_b = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _b.contextId;
1996
+ const contextId = (_f = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _f.contextId;
1949
1997
  if (sessionId) {
1950
- if ((_c = ctx.sessionCapabilitiesMap) == null ? void 0 : _c.has(sessionId)) {
1998
+ if ((_g = ctx.sessionCapabilitiesMap) == null ? void 0 : _g.has(sessionId)) {
1951
1999
  const cachedCapabilities = ctx.sessionCapabilitiesMap.get(sessionId);
1952
2000
  capsBuildId = (cachedCapabilities == null ? void 0 : cachedCapabilities.buildId) || "";
1953
2001
  } else {
1954
2002
  try {
1955
- let fetchedCapabilitiesResp = yield ctx.client.getSmartUICapabilities(sessionId, ctx.config, ctx.git, ctx.log);
2003
+ let fetchedCapabilitiesResp = yield ctx.client.getSmartUICapabilities(sessionId, ctx.config, ctx.git, ctx.log, ctx.isStartExec);
1956
2004
  capsBuildId = (fetchedCapabilitiesResp == null ? void 0 : fetchedCapabilitiesResp.buildId) || "";
1957
2005
  ctx.log.debug(`fetch caps for sessionId: ${sessionId} are ${JSON.stringify(fetchedCapabilitiesResp)}`);
1958
2006
  if (capsBuildId) {
@@ -1978,9 +2026,9 @@ var server_default = (ctx) => __async(void 0, null, function* () {
1978
2026
  ctx.log.debug(`Marking contextId as captured and added to queue: ${contextId}`);
1979
2027
  }
1980
2028
  if (contextId) {
1981
- (_d = ctx.snapshotQueue) == null ? void 0 : _d.enqueueFront(snapshot);
2029
+ (_h = ctx.snapshotQueue) == null ? void 0 : _h.enqueueFront(snapshot);
1982
2030
  } else {
1983
- (_e = ctx.snapshotQueue) == null ? void 0 : _e.enqueue(snapshot);
2031
+ (_i = ctx.snapshotQueue) == null ? void 0 : _i.enqueue(snapshot);
1984
2032
  }
1985
2033
  ctx.isSnapshotCaptured = true;
1986
2034
  replyCode = 200;
@@ -1993,10 +2041,11 @@ var server_default = (ctx) => __async(void 0, null, function* () {
1993
2041
  return reply.code(replyCode).send(replyBody);
1994
2042
  }));
1995
2043
  server.post("/stop", opts, (_, reply) => __async(void 0, null, function* () {
1996
- var _a, _b, _c;
2044
+ var _a, _b, _c, _d;
1997
2045
  let replyCode;
1998
2046
  let replyBody;
1999
2047
  try {
2048
+ ctx.log.info("Received stop command. Finalizing build ...");
2000
2049
  if (ctx.config.delayedUpload) {
2001
2050
  ctx.log.debug("started after processing because of delayedUpload");
2002
2051
  (_a = ctx.snapshotQueue) == null ? void 0 : _a.startProcessingfunc();
@@ -2010,6 +2059,8 @@ var server_default = (ctx) => __async(void 0, null, function* () {
2010
2059
  }
2011
2060
  }, 1e3);
2012
2061
  });
2062
+ let buildUrls = `build url: ${ctx.build.url}
2063
+ `;
2013
2064
  for (const [sessionId, capabilities] of ctx.sessionCapabilitiesMap.entries()) {
2014
2065
  try {
2015
2066
  const buildId = (capabilities == null ? void 0 : capabilities.buildId) || "";
@@ -2017,8 +2068,12 @@ var server_default = (ctx) => __async(void 0, null, function* () {
2017
2068
  const totalSnapshots = (capabilities == null ? void 0 : capabilities.snapshotCount) || 0;
2018
2069
  const sessionBuildUrl = (capabilities == null ? void 0 : capabilities.buildURL) || "";
2019
2070
  const testId = (capabilities == null ? void 0 : capabilities.id) || "";
2071
+ ctx.log.debug(`Capabilities for sessionId ${sessionId}: ${JSON.stringify(capabilities)}`);
2020
2072
  if (buildId && projectToken) {
2021
2073
  yield ctx.client.finalizeBuildForCapsWithToken(buildId, totalSnapshots, projectToken, ctx.log);
2074
+ if (ctx.autoTunnelStarted) {
2075
+ yield startPollingForTunnel(ctx, buildId, false, projectToken, capabilities == null ? void 0 : capabilities.buildName);
2076
+ }
2022
2077
  }
2023
2078
  if (testId && buildId) {
2024
2079
  buildUrls += `TestId ${testId}: ${sessionBuildUrl}
@@ -2039,7 +2094,13 @@ var server_default = (ctx) => __async(void 0, null, function* () {
2039
2094
  ctx.log.debug(`Skipping upload of CLI logs as useLambdaInternal is set`);
2040
2095
  }
2041
2096
  }
2042
- yield (_c = ctx.browser) == null ? void 0 : _c.close();
2097
+ if (ctx.tunnelDetails && ctx.tunnelDetails.tunnelHost != "" && ((_c = ctx.build) == null ? void 0 : _c.id)) {
2098
+ yield startPollingForTunnel(ctx, ctx.build.id, false, "", "");
2099
+ }
2100
+ if (ctx.autoTunnelStarted && isTunnelPolling === null) {
2101
+ yield stopTunnelHelper(ctx);
2102
+ }
2103
+ yield (_d = ctx.browser) == null ? void 0 : _d.close();
2043
2104
  if (ctx.server) {
2044
2105
  ctx.server.close();
2045
2106
  }
@@ -2055,6 +2116,7 @@ var server_default = (ctx) => __async(void 0, null, function* () {
2055
2116
  replyCode = 500;
2056
2117
  replyBody = { error: { message: error.message } };
2057
2118
  }
2119
+ ctx.log.info("Stop command processed. Tearing down server.");
2058
2120
  return reply.code(replyCode).send(replyBody);
2059
2121
  }));
2060
2122
  server.get("/ping", opts, (_, reply) => {
@@ -2295,7 +2357,7 @@ var authExec_default = (ctx) => {
2295
2357
  };
2296
2358
 
2297
2359
  // package.json
2298
- var version = "4.1.31";
2360
+ var version = "4.1.32";
2299
2361
  var package_default = {
2300
2362
  name: "@lambdatest/smartui-cli",
2301
2363
  version,
@@ -2347,6 +2409,9 @@ var package_default = {
2347
2409
  which: "^4.0.0",
2348
2410
  winston: "^3.10.0"
2349
2411
  },
2412
+ overrides: {
2413
+ "simple-swizzle": "0.2.2"
2414
+ },
2350
2415
  devDependencies: {
2351
2416
  typescript: "^5.3.2"
2352
2417
  }
@@ -2406,8 +2471,9 @@ var httpClient = class {
2406
2471
  this.axiosInstance.interceptors.response.use(
2407
2472
  (response) => response,
2408
2473
  (error) => __async(this, null, function* () {
2474
+ var _a;
2409
2475
  const { config } = error;
2410
- if (config && config.url === "/screenshot" && config.method === "post") {
2476
+ if (config && config.url === "/screenshot" && config.method === "post" && ((_a = error == null ? void 0 : error.response) == null ? void 0 : _a.status) !== 401) {
2411
2477
  if (!config.retryCount) {
2412
2478
  config.retryCount = 0;
2413
2479
  config.retry = 2;
@@ -2566,11 +2632,12 @@ var httpClient = class {
2566
2632
  }
2567
2633
  }, log2);
2568
2634
  }
2569
- getScreenshotData(buildId, baseline, log2, projectToken) {
2635
+ getScreenshotData(buildId, baseline, log2, projectToken, buildName) {
2636
+ log2.debug(`Fetching screenshot data for buildId: ${buildId} having buildName: ${buildName} with baseline: ${baseline}`);
2570
2637
  return this.request({
2571
2638
  url: "/screenshot",
2572
2639
  method: "GET",
2573
- params: { buildId, baseline },
2640
+ params: { buildId, baseline, buildName },
2574
2641
  headers: { projectToken }
2575
2642
  }, log2);
2576
2643
  }
@@ -2600,7 +2667,7 @@ var httpClient = class {
2600
2667
  }
2601
2668
  }, log2);
2602
2669
  }
2603
- getSmartUICapabilities(sessionId, config, git, log2) {
2670
+ getSmartUICapabilities(sessionId, config, git, log2, isStartExec) {
2604
2671
  return this.request({
2605
2672
  url: "/sessions/capabilities",
2606
2673
  method: "GET",
@@ -2609,7 +2676,8 @@ var httpClient = class {
2609
2676
  },
2610
2677
  data: {
2611
2678
  git,
2612
- config
2679
+ config,
2680
+ isStartExec
2613
2681
  },
2614
2682
  headers: {
2615
2683
  projectToken: "",
@@ -2658,24 +2726,31 @@ var httpClient = class {
2658
2726
  }
2659
2727
  }, ctx.log);
2660
2728
  }
2661
- processSnapshot(ctx, snapshot, snapshotUuid, discoveryErrors, variantCount, sync = false) {
2729
+ processSnapshot(ctx, snapshot, snapshotUuid, discoveryErrors, variantCount, sync = false, approvalThreshold, rejectionThreshold) {
2730
+ const requestData = {
2731
+ name: snapshot.name,
2732
+ url: snapshot.url,
2733
+ snapshotUuid,
2734
+ variantCount,
2735
+ test: {
2736
+ type: ctx.testType,
2737
+ source: "cli"
2738
+ },
2739
+ discoveryErrors,
2740
+ doRemoteDiscovery: snapshot.options.doRemoteDiscovery,
2741
+ sync
2742
+ };
2743
+ if (approvalThreshold !== void 0) {
2744
+ requestData.approvalThreshold = approvalThreshold;
2745
+ }
2746
+ if (rejectionThreshold !== void 0) {
2747
+ requestData.rejectionThreshold = rejectionThreshold;
2748
+ }
2662
2749
  return this.request({
2663
2750
  url: `/build/${ctx.build.id}/snapshot`,
2664
2751
  method: "POST",
2665
2752
  headers: { "Content-Type": "application/json" },
2666
- data: {
2667
- name: snapshot.name,
2668
- url: snapshot.url,
2669
- snapshotUuid,
2670
- variantCount,
2671
- test: {
2672
- type: ctx.testType,
2673
- source: "cli"
2674
- },
2675
- doRemoteDiscovery: snapshot.options.doRemoteDiscovery,
2676
- discoveryErrors,
2677
- sync
2678
- }
2753
+ data: requestData
2679
2754
  }, ctx.log);
2680
2755
  }
2681
2756
  processSnapshotCaps(ctx, snapshot, snapshotUuid, capsBuildId, capsProjectToken, discoveryErrors) {
@@ -3032,6 +3107,11 @@ var ctx_default = (options) => {
3032
3107
  config.web.viewports = config.web.resolutions;
3033
3108
  delete config.web.resolutions;
3034
3109
  }
3110
+ if (config.approvalThreshold && config.rejectionThreshold) {
3111
+ if (config.rejectionThreshold <= config.approvalThreshold) {
3112
+ throw new Error("Invalid config; rejectionThreshold must be greater than approvalThreshold");
3113
+ }
3114
+ }
3035
3115
  let validateConfigFn = options.scheduled ? validateConfigForScheduled : validateConfig;
3036
3116
  if (!validateConfigFn(config)) {
3037
3117
  throw new Error(validateConfigFn.errors[0].message);
@@ -3128,7 +3208,9 @@ var ctx_default = (options) => {
3128
3208
  allowDuplicateSnapshotNames,
3129
3209
  useLambdaInternal,
3130
3210
  useExtendedViewport,
3131
- loadDomContent
3211
+ loadDomContent,
3212
+ approvalThreshold: config.approvalThreshold,
3213
+ rejectionThreshold: config.rejectionThreshold
3132
3214
  },
3133
3215
  uploadFilePath: "",
3134
3216
  webStaticConfig: [],
@@ -3304,7 +3386,6 @@ var createBuildExec_default = (ctx) => {
3304
3386
  return {
3305
3387
  title: `Creating SmartUI build`,
3306
3388
  task: (ctx2, task) => __async(void 0, null, function* () {
3307
- var _a, _b, _c;
3308
3389
  updateLogContext({ task: "createBuild" });
3309
3390
  try {
3310
3391
  if (ctx2.authenticatedInitially && !ctx2.config.skipBuildCreation) {
@@ -3332,17 +3413,17 @@ var createBuildExec_default = (ctx) => {
3332
3413
  }
3333
3414
  task.output = chalk__default.default.gray(`build id: ${resp.data.buildId}`);
3334
3415
  task.title = "SmartUI build created";
3416
+ if (ctx2.env.USE_REMOTE_DISCOVERY) {
3417
+ task.output += chalk__default.default.gray(`
3418
+ Using remote discovery for this build`);
3419
+ }
3335
3420
  } else {
3336
3421
  task.output = chalk__default.default.gray(`Empty PROJECT_TOKEN and PROJECT_NAME. Skipping Creation of Build!`);
3337
3422
  task.title = "Skipped SmartUI build creation";
3338
- if (ctx2.config.tunnel && ((_a = ctx2.config.tunnel) == null ? void 0 : _a.type) === "auto") {
3339
- yield stopTunnelHelper(ctx2);
3340
- }
3341
3423
  }
3342
- if (ctx2.config.tunnel && ((_b = ctx2.config.tunnel) == null ? void 0 : _b.type) === "auto") {
3343
- startPingPolling(ctx2);
3344
- if (ctx2.build && ctx2.build.id) {
3345
- startPollingForTunnel(ctx2, "", false, "");
3424
+ if (ctx2.autoTunnelStarted) {
3425
+ if (ctx2.build && ctx2.build.id && ctx2.sourceCommand != "exec-start") {
3426
+ startPingPolling(ctx2);
3346
3427
  }
3347
3428
  }
3348
3429
  if (ctx2.config.tunnel) {
@@ -3355,6 +3436,13 @@ var createBuildExec_default = (ctx) => {
3355
3436
  tunnelName: tunnelResp.data.tunnel_name
3356
3437
  };
3357
3438
  ctx2.log.debug(`Tunnel Details: ${JSON.stringify(ctx2.tunnelDetails)}`);
3439
+ if (process.env.USE_REMOTE_DISCOVERY === void 0) {
3440
+ ctx2.env.USE_REMOTE_DISCOVERY = true;
3441
+ process.env.USE_REMOTE_DISCOVERY = "true";
3442
+ task.output += chalk__default.default.gray(`
3443
+ Using remote discovery by default for this build`);
3444
+ }
3445
+ ctx2.log.debug(`USE_REMOTE_DISCOVERY is set to ${ctx2.env.USE_REMOTE_DISCOVERY}`);
3358
3446
  } else if (tunnelResp && tunnelResp.error) {
3359
3447
  if (tunnelResp.error.message) {
3360
3448
  if (tunnelResp.error.code && tunnelResp.error.code === 400) {
@@ -3367,7 +3455,7 @@ var createBuildExec_default = (ctx) => {
3367
3455
  }
3368
3456
  } catch (error) {
3369
3457
  ctx2.log.debug(error);
3370
- if (ctx2.config.tunnel && ((_c = ctx2.config.tunnel) == null ? void 0 : _c.type) === "auto") {
3458
+ if (ctx2.autoTunnelStarted) {
3371
3459
  yield stopTunnelHelper(ctx2);
3372
3460
  }
3373
3461
  task.output = chalk__default.default.gray(error.message);
@@ -3425,7 +3513,7 @@ var processSnapshot_default = (ctx) => {
3425
3513
  return {
3426
3514
  title: `Processing snapshots`,
3427
3515
  task: (ctx2, task) => __async(void 0, null, function* () {
3428
- var _a, _b;
3516
+ var _a, _b, _c, _d;
3429
3517
  try {
3430
3518
  if (ctx2.config.delayedUpload) {
3431
3519
  ctx2.log.debug("started after processing because of delayedUpload");
@@ -3434,12 +3522,12 @@ var processSnapshot_default = (ctx) => {
3434
3522
  yield new Promise((resolve) => {
3435
3523
  let output2 = "";
3436
3524
  const intervalId = setInterval(() => {
3437
- var _a2, _b2, _c;
3525
+ var _a2, _b2, _c2;
3438
3526
  if (((_a2 = ctx2.snapshotQueue) == null ? void 0 : _a2.isEmpty()) && !((_b2 = ctx2.snapshotQueue) == null ? void 0 : _b2.isProcessing())) {
3439
3527
  clearInterval(intervalId);
3440
3528
  resolve();
3441
3529
  } else {
3442
- task.title = `Processing snapshot ${(_c = ctx2.snapshotQueue) == null ? void 0 : _c.getProcessingSnapshot()}`;
3530
+ task.title = `Processing snapshot ${(_c2 = ctx2.snapshotQueue) == null ? void 0 : _c2.getProcessingSnapshot()}`;
3443
3531
  }
3444
3532
  }, 500);
3445
3533
  });
@@ -3457,6 +3545,9 @@ ${snapshot.warnings.length ? chalk__default.default.gray(`[warning] ${snapshot.w
3457
3545
  }
3458
3546
  task.output = output;
3459
3547
  task.title = "Processed snapshots";
3548
+ if (((_d = (_c = ctx2.snapshotQueue) == null ? void 0 : _c.getProcessedSnapshots()) == null ? void 0 : _d.length) === 0) {
3549
+ task.title = "No snapshots processed";
3550
+ }
3460
3551
  } catch (error) {
3461
3552
  ctx2.log.debug(error);
3462
3553
  task.output = chalk__default.default.gray(error.message);
@@ -3472,7 +3563,7 @@ var finalizeBuild_default = (ctx) => {
3472
3563
  return {
3473
3564
  title: `Finalizing build`,
3474
3565
  task: (ctx2, task) => __async(void 0, null, function* () {
3475
- var _a, _b;
3566
+ var _a, _b, _c;
3476
3567
  updateLogContext({ task: "finalizeBuild" });
3477
3568
  try {
3478
3569
  if (ctx2.build.id) {
@@ -3486,11 +3577,11 @@ var finalizeBuild_default = (ctx) => {
3486
3577
  task.output = chalk__default.default.gray(error.message);
3487
3578
  throw new Error("Finalize build failed");
3488
3579
  }
3489
- let buildUrls2 = `build url: ${ctx2.build.url}
3580
+ let buildUrls = `build url: ${ctx2.build.url}
3490
3581
  `;
3491
3582
  if (pingIntervalId !== null) {
3492
3583
  clearInterval(pingIntervalId);
3493
- ctx2.log.debug("Ping polling stopped immediately.");
3584
+ ctx2.log.debug("Ping polling stopped immediately from Finalize Build");
3494
3585
  }
3495
3586
  for (const [sessionId, capabilities] of ctx2.sessionCapabilitiesMap.entries()) {
3496
3587
  try {
@@ -3512,23 +3603,33 @@ var finalizeBuild_default = (ctx) => {
3512
3603
  ctx2.fetchResultsForBuild.push(buildId);
3513
3604
  }
3514
3605
  }
3606
+ ctx2.log.debug(`Capabilities for sessionId ${sessionId}: ${JSON.stringify(capabilities)}`);
3515
3607
  if (buildId && projectToken) {
3516
3608
  yield ctx2.client.finalizeBuildForCapsWithToken(buildId, totalSnapshots, projectToken, ctx2.log);
3609
+ if (ctx2.autoTunnelStarted) {
3610
+ yield startPollingForTunnel(ctx2, buildId, false, projectToken, capabilities == null ? void 0 : capabilities.buildName);
3611
+ }
3517
3612
  }
3518
3613
  if (testId && buildId) {
3519
- buildUrls2 += `TestId ${testId}: ${sessionBuildUrl}
3614
+ buildUrls += `TestId ${testId}: ${sessionBuildUrl}
3520
3615
  `;
3521
3616
  }
3522
3617
  } catch (error) {
3523
3618
  ctx2.log.debug(`Error finalizing build for session ${sessionId}: ${error.message}`);
3524
3619
  }
3525
3620
  }
3526
- task.output = chalk__default.default.gray(buildUrls2);
3621
+ task.output = chalk__default.default.gray(buildUrls);
3527
3622
  task.title = "Finalized build";
3623
+ if (ctx2.tunnelDetails && ctx2.tunnelDetails.tunnelHost != "" && ((_a = ctx2.build) == null ? void 0 : _a.id)) {
3624
+ yield startPollingForTunnel(ctx2, ctx2.build.id, false, "", "");
3625
+ }
3626
+ if (ctx2.autoTunnelStarted && isTunnelPolling === null) {
3627
+ yield stopTunnelHelper(ctx2);
3628
+ }
3528
3629
  try {
3529
- yield (_a = ctx2.browser) == null ? void 0 : _a.close();
3630
+ yield (_b = ctx2.browser) == null ? void 0 : _b.close();
3530
3631
  ctx2.log.debug(`Closed browser`);
3531
- yield (_b = ctx2.server) == null ? void 0 : _b.close();
3632
+ yield (_c = ctx2.server) == null ? void 0 : _c.close();
3532
3633
  ctx2.log.debug(`Closed server`);
3533
3634
  if (ctx2.isSnapshotCaptured) {
3534
3635
  let uploadCLILogsToS3 = ctx2.config.useLambdaInternal || uploadDomToS3ViaEnv2;
@@ -4488,7 +4589,7 @@ var Queue = class {
4488
4589
  }
4489
4590
  processNext() {
4490
4591
  return __async(this, null, function* () {
4491
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
4592
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
4492
4593
  if (!this.isEmpty()) {
4493
4594
  let snapshot;
4494
4595
  if (this.ctx.config.delayedUpload) {
@@ -4577,7 +4678,7 @@ var Queue = class {
4577
4678
  useKafkaFlow: resp.data.useKafkaFlow || false
4578
4679
  };
4579
4680
  } else {
4580
- if (this.ctx.config.tunnel && ((_d = this.ctx.config.tunnel) == null ? void 0 : _d.type) === "auto") {
4681
+ if (this.ctx.autoTunnelStarted) {
4581
4682
  yield stopTunnelHelper(this.ctx);
4582
4683
  }
4583
4684
  throw new Error("SmartUI capabilities are missing in env variables or in driver capabilities");
@@ -4591,7 +4692,7 @@ var Queue = class {
4591
4692
  if (this.ctx.build && this.ctx.build.useKafkaFlow) {
4592
4693
  let snapshotUuid = uuid.v4();
4593
4694
  let snapshotUploadResponse;
4594
- if (((_e = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _e.contextId) && ((_f = this.ctx.contextToSnapshotMap) == null ? void 0 : _f.has(snapshot.options.contextId))) {
4695
+ if (((_d = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _d.contextId) && ((_e = this.ctx.contextToSnapshotMap) == null ? void 0 : _e.has(snapshot.options.contextId))) {
4595
4696
  snapshotUuid = snapshot.options.contextId;
4596
4697
  }
4597
4698
  let uploadDomToS3 = this.ctx.config.useLambdaInternal || uploadDomToS3ViaEnv3;
@@ -4617,16 +4718,18 @@ var Queue = class {
4617
4718
  this.ctx.log.debug(`Closed browser context for snapshot ${snapshot.name}`);
4618
4719
  }
4619
4720
  }
4620
- if ((_g = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _g.contextId) {
4621
- (_i = this.ctx.contextToSnapshotMap) == null ? void 0 : _i.set((_h = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _h.contextId, 2);
4721
+ if ((_f = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _f.contextId) {
4722
+ (_h = this.ctx.contextToSnapshotMap) == null ? void 0 : _h.set((_g = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _g.contextId, 2);
4622
4723
  }
4623
4724
  this.processNext();
4624
4725
  } else {
4625
- yield this.ctx.client.processSnapshot(this.ctx, processedSnapshot, snapshotUuid, discoveryErrors, calculateVariantCountFromSnapshot(processedSnapshot, this.ctx.config), (_j = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _j.sync);
4626
- if (((_k = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _k.contextId) && ((_l = this.ctx.contextToSnapshotMap) == null ? void 0 : _l.has(snapshot.options.contextId))) {
4726
+ let approvalThreshold = ((_i = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _i.approvalThreshold) || this.ctx.config.approvalThreshold;
4727
+ let rejectionThreshold = ((_j = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _j.rejectionThreshold) || this.ctx.config.rejectionThreshold;
4728
+ yield this.ctx.client.processSnapshot(this.ctx, processedSnapshot, snapshotUuid, discoveryErrors, calculateVariantCountFromSnapshot(processedSnapshot, this.ctx.config), (_k = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _k.sync, approvalThreshold, rejectionThreshold);
4729
+ if (((_l = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _l.contextId) && ((_m = this.ctx.contextToSnapshotMap) == null ? void 0 : _m.has(snapshot.options.contextId))) {
4627
4730
  this.ctx.contextToSnapshotMap.set(snapshot.options.contextId, 1);
4628
4731
  }
4629
- this.ctx.log.debug(`ContextId: ${(_m = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _m.contextId} status set to uploaded`);
4732
+ this.ctx.log.debug(`ContextId: ${(_n = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _n.contextId} status set to uploaded`);
4630
4733
  }
4631
4734
  } else {
4632
4735
  this.ctx.log.info(`Uploading snapshot to S3`);
@@ -4639,7 +4742,7 @@ var Queue = class {
4639
4742
  } catch (error) {
4640
4743
  this.ctx.log.debug(`snapshot failed; ${error}`);
4641
4744
  this.processedSnapshots.push({ name: snapshot == null ? void 0 : snapshot.name, error: error.message });
4642
- if (((_n = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _n.contextId) && this.ctx.contextToSnapshotMap) {
4745
+ if (((_o = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _o.contextId) && this.ctx.contextToSnapshotMap) {
4643
4746
  this.ctx.contextToSnapshotMap.set(snapshot.options.contextId, 2);
4644
4747
  }
4645
4748
  }
@@ -4680,6 +4783,7 @@ var startTunnel_default = (ctx) => {
4680
4783
  try {
4681
4784
  yield startTunnelBinary(ctx2);
4682
4785
  ctx2.isStartExec = true;
4786
+ ctx2.autoTunnelStarted = true;
4683
4787
  task.title = "Tunnel Started";
4684
4788
  task.output = chalk__default.default.gray("Tunnel started successfully");
4685
4789
  } catch (error) {
@@ -4710,6 +4814,7 @@ command.name("exec").description("Run test commands around SmartUI").argument("<
4710
4814
  ctx.args.execCommand = execCommand;
4711
4815
  ctx.snapshotQueue = new Queue(ctx);
4712
4816
  ctx.totalSnapshots = 0;
4817
+ ctx.sourceCommand = "exec";
4713
4818
  let tasks = new listr2.Listr(
4714
4819
  [
4715
4820
  authExec_default(),
@@ -5526,7 +5631,8 @@ var uploadWebFigma_default = (ctx) => __async(void 0, null, function* () {
5526
5631
  web: webConfig,
5527
5632
  figma: figmaConfig,
5528
5633
  smartIgnore: ctx.config.smartIgnore,
5529
- git: ctx.git
5634
+ git: ctx.git,
5635
+ markBaseline: ctx.options.markBaseline
5530
5636
  };
5531
5637
  const responseData = yield ctx.client.processWebFigma(requestBody, ctx.log);
5532
5638
  ctx.log.debug("responseData : " + JSON.stringify(responseData));
@@ -5641,7 +5747,8 @@ var uploadAppFigma_default = (ctx) => __async(void 0, null, function* () {
5641
5747
  figma: figmaConfig,
5642
5748
  smartIgnore: ctx.config.smartIgnore,
5643
5749
  git: ctx.git,
5644
- platformType: "app"
5750
+ platformType: "app",
5751
+ markBaseline: ctx.options.markBaseline
5645
5752
  };
5646
5753
  const responseData = yield ctx.client.processWebFigma(requestBody, ctx.log);
5647
5754
  ctx.log.debug("responseData : " + JSON.stringify(responseData));
@@ -5850,6 +5957,7 @@ uploadAppFigmaCommand.name("upload-figma-app").description("Capture figma screen
5850
5957
  var command4 = new commander.Command();
5851
5958
  command4.name("exec:start").description("Start SmartUI server").option("-P, --port <number>", "Port number for the server").option("--fetch-results [filename]", "Fetch results and optionally specify an output file, e.g., <filename>.json").option("--buildName <string>", "Specify the build name").action(function() {
5852
5959
  return __async(this, null, function* () {
5960
+ var _a;
5853
5961
  const options = command4.optsWithGlobals();
5854
5962
  if (options.buildName === "") {
5855
5963
  console.log(`Error: The '--buildName' option cannot be an empty string.`);
@@ -5859,11 +5967,13 @@ command4.name("exec:start").description("Start SmartUI server").option("-P, --po
5859
5967
  ctx.snapshotQueue = new Queue(ctx);
5860
5968
  ctx.totalSnapshots = 0;
5861
5969
  ctx.isStartExec = true;
5970
+ ctx.sourceCommand = "exec-start";
5862
5971
  let tasks = new listr2.Listr(
5863
5972
  [
5864
5973
  authExec_default(),
5865
5974
  startServer_default(),
5866
5975
  getGitInfo_default(),
5976
+ ...ctx.config.tunnel && ((_a = ctx.config.tunnel) == null ? void 0 : _a.type) === "auto" ? [startTunnel_default()] : [],
5867
5977
  createBuildExec_default()
5868
5978
  ],
5869
5979
  {
@@ -5879,7 +5989,7 @@ command4.name("exec:start").description("Start SmartUI server").option("-P, --po
5879
5989
  );
5880
5990
  try {
5881
5991
  yield tasks.run(ctx);
5882
- if (ctx.build && ctx.build.id) {
5992
+ if (ctx.build && ctx.build.id && !ctx.autoTunnelStarted) {
5883
5993
  startPingPolling(ctx);
5884
5994
  }
5885
5995
  if (ctx.options.fetchResults && ctx.build && ctx.build.id) {
@@ -5887,6 +5997,7 @@ command4.name("exec:start").description("Start SmartUI server").option("-P, --po
5887
5997
  }
5888
5998
  } catch (error) {
5889
5999
  console.error("Error during server execution:", error);
6000
+ process.exit(1);
5890
6001
  }
5891
6002
  });
5892
6003
  });
@@ -5914,8 +6025,11 @@ command5.name("exec:stop").description("Stop the SmartUI server").action(functio
5914
6025
  console.log(chalk__default.default.red("Failed to stop server"));
5915
6026
  }
5916
6027
  } catch (error) {
5917
- if (error.code === "ECONNABORTED") {
6028
+ if (error && error.code === "ECONNABORTED") {
5918
6029
  console.error(chalk__default.default.red("Error: SmartUI server did not respond in 15 seconds"));
6030
+ }
6031
+ if (error && error.code === "ECONNREFUSED") {
6032
+ console.error(chalk__default.default.red("Error: Looks like smartui cli server is already stopped"));
5919
6033
  } else {
5920
6034
  console.error(chalk__default.default.red("Error while stopping server"));
5921
6035
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdatest/smartui-cli",
3
- "version": "4.1.31",
3
+ "version": "4.1.32",
4
4
  "description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
5
5
  "files": [
6
6
  "dist/**/*"
@@ -43,6 +43,9 @@
43
43
  "which": "^4.0.0",
44
44
  "winston": "^3.10.0"
45
45
  },
46
+ "overrides": {
47
+ "simple-swizzle": "0.2.2"
48
+ },
46
49
  "devDependencies": {
47
50
  "typescript": "^5.3.2"
48
51
  },