@lambdatest/smartui-cli 4.1.25 → 4.1.26

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 +205 -17
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -1012,6 +1012,18 @@ var SnapshotSchema = {
1012
1012
  sessionId: {
1013
1013
  type: "string",
1014
1014
  errorMessage: "Invalid snapshot options; sessionId must be a string"
1015
+ },
1016
+ contextId: {
1017
+ type: "string",
1018
+ errorMessage: "Invalid snapshot options; contextId must be a string"
1019
+ },
1020
+ sync: {
1021
+ type: "boolean",
1022
+ errorMessage: "Invalid snapshot options; sync must be a boolean"
1023
+ },
1024
+ timeout: {
1025
+ type: "number",
1026
+ errorMessage: "Invalid snapshot options; timeout must be a number"
1015
1027
  }
1016
1028
  },
1017
1029
  additionalProperties: false
@@ -1674,8 +1686,39 @@ function stopTunnelHelper(ctx) {
1674
1686
  ctx.log.debug("Tunnel is Stopped ? " + status);
1675
1687
  });
1676
1688
  }
1689
+ function calculateVariantCount(config) {
1690
+ let variantCount = 0;
1691
+ if (config.web) {
1692
+ const browsers = config.web.browsers || [];
1693
+ const viewports = config.web.viewports || [];
1694
+ variantCount += browsers.length * viewports.length;
1695
+ }
1696
+ if (config.mobile) {
1697
+ const devices = config.mobile.devices || [];
1698
+ variantCount += devices.length;
1699
+ }
1700
+ return variantCount;
1701
+ }
1702
+ function calculateVariantCountFromSnapshot(snapshot, globalConfig) {
1703
+ var _a, _b;
1704
+ let variantCount = 0;
1705
+ if ((_a = snapshot.options) == null ? void 0 : _a.web) {
1706
+ const browsers = snapshot.options.web.browsers || [];
1707
+ const viewports = snapshot.options.web.viewports || [];
1708
+ variantCount += browsers.length * viewports.length;
1709
+ }
1710
+ if ((_b = snapshot.options) == null ? void 0 : _b.mobile) {
1711
+ const devices = snapshot.options.mobile.devices || [];
1712
+ variantCount += devices.length;
1713
+ }
1714
+ if (variantCount === 0 && globalConfig) {
1715
+ variantCount = calculateVariantCount(globalConfig);
1716
+ }
1717
+ return variantCount;
1718
+ }
1677
1719
 
1678
1720
  // src/lib/server.ts
1721
+ var uploadDomToS3ViaEnv = process.env.USE_LAMBDA_INTERNAL || false;
1679
1722
  var server_default = (ctx) => __async(void 0, null, function* () {
1680
1723
  const server = fastify__default.default({
1681
1724
  logger: {
@@ -1695,7 +1738,7 @@ var server_default = (ctx) => __async(void 0, null, function* () {
1695
1738
  reply.code(200).send({ data: { dom: SMARTUI_DOM } });
1696
1739
  });
1697
1740
  server.post("/snapshot", opts, (request, reply) => __async(void 0, null, function* () {
1698
- var _a, _b, _c;
1741
+ var _a, _b, _c, _d, _e;
1699
1742
  let replyCode;
1700
1743
  let replyBody;
1701
1744
  try {
@@ -1704,8 +1747,9 @@ var server_default = (ctx) => __async(void 0, null, function* () {
1704
1747
  throw new Error(validateSnapshot.errors[0].message);
1705
1748
  const sessionId = (_a = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _a.sessionId;
1706
1749
  let capsBuildId = "";
1750
+ const contextId = (_b = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _b.contextId;
1707
1751
  if (sessionId) {
1708
- if ((_b = ctx.sessionCapabilitiesMap) == null ? void 0 : _b.has(sessionId)) {
1752
+ if ((_c = ctx.sessionCapabilitiesMap) == null ? void 0 : _c.has(sessionId)) {
1709
1753
  const cachedCapabilities = ctx.sessionCapabilitiesMap.get(sessionId);
1710
1754
  capsBuildId = (cachedCapabilities == null ? void 0 : cachedCapabilities.buildId) || "";
1711
1755
  } else {
@@ -1728,7 +1772,19 @@ var server_default = (ctx) => __async(void 0, null, function* () {
1728
1772
  }
1729
1773
  }
1730
1774
  ctx.testType = testType;
1731
- (_c = ctx.snapshotQueue) == null ? void 0 : _c.enqueue(snapshot);
1775
+ if (contextId && !ctx.contextToSnapshotMap) {
1776
+ ctx.contextToSnapshotMap = /* @__PURE__ */ new Map();
1777
+ ctx.log.debug(`Initialized empty context mapping map for contextId: ${contextId}`);
1778
+ }
1779
+ if (contextId && ctx.contextToSnapshotMap) {
1780
+ ctx.contextToSnapshotMap.set(contextId, 0);
1781
+ ctx.log.debug(`Marking contextId as captured and added to queue: ${contextId}`);
1782
+ }
1783
+ if (contextId) {
1784
+ (_d = ctx.snapshotQueue) == null ? void 0 : _d.enqueueFront(snapshot);
1785
+ } else {
1786
+ (_e = ctx.snapshotQueue) == null ? void 0 : _e.enqueue(snapshot);
1787
+ }
1732
1788
  ctx.isSnapshotCaptured = true;
1733
1789
  replyCode = 200;
1734
1790
  replyBody = { data: { message: "success", warnings: [] } };
@@ -1740,7 +1796,7 @@ var server_default = (ctx) => __async(void 0, null, function* () {
1740
1796
  return reply.code(replyCode).send(replyBody);
1741
1797
  }));
1742
1798
  server.post("/stop", opts, (_, reply) => __async(void 0, null, function* () {
1743
- var _a, _b;
1799
+ var _a, _b, _c;
1744
1800
  let replyCode;
1745
1801
  let replyBody;
1746
1802
  try {
@@ -1762,8 +1818,15 @@ var server_default = (ctx) => __async(void 0, null, function* () {
1762
1818
  if (ctx.server) {
1763
1819
  ctx.server.close();
1764
1820
  }
1765
- let resp = yield ctx.client.getS3PreSignedURL(ctx);
1766
- yield ctx.client.uploadLogs(ctx, resp.data.url);
1821
+ let uploadCLILogsToS3 = ((_c = ctx == null ? void 0 : ctx.config) == null ? void 0 : _c.useLambdaInternal) || uploadDomToS3ViaEnv;
1822
+ if (!uploadCLILogsToS3) {
1823
+ ctx.log.debug(`Log file to be uploaded`);
1824
+ let resp = yield ctx.client.getS3PreSignedURL(ctx);
1825
+ yield ctx.client.uploadLogs(ctx, resp.data.url);
1826
+ } else {
1827
+ ctx.log.debug(`Log file to be uploaded via LSRS`);
1828
+ let resp = ctx.client.sendCliLogsToLSRS(ctx);
1829
+ }
1767
1830
  if (pingIntervalId !== null) {
1768
1831
  clearInterval(pingIntervalId);
1769
1832
  ctx.log.debug("Ping polling stopped immediately.");
@@ -1781,6 +1844,93 @@ var server_default = (ctx) => __async(void 0, null, function* () {
1781
1844
  server.get("/ping", opts, (_, reply) => {
1782
1845
  reply.code(200).send({ status: "Server is running", version: ctx.cliVersion });
1783
1846
  });
1847
+ server.get("/snapshot/status", opts, (request, reply) => __async(void 0, null, function* () {
1848
+ var _a;
1849
+ let replyCode;
1850
+ let replyBody;
1851
+ try {
1852
+ ctx.log.debug(`request.query : ${JSON.stringify(request.query)}`);
1853
+ const { contextId, pollTimeout, snapshotName } = request.query;
1854
+ if (!contextId || !snapshotName) {
1855
+ throw new Error("contextId and snapshotName are required parameters");
1856
+ }
1857
+ const timeoutDuration = pollTimeout * 1e3 || 3e4;
1858
+ if ((_a = ctx.contextToSnapshotMap) == null ? void 0 : _a.has(contextId)) {
1859
+ let contextStatus = ctx.contextToSnapshotMap.get(contextId);
1860
+ while (contextStatus == 0) {
1861
+ yield new Promise((resolve) => setTimeout(resolve, 5e3));
1862
+ contextStatus = ctx.contextToSnapshotMap.get(contextId);
1863
+ }
1864
+ if (contextStatus == 2) {
1865
+ throw new Error("Snapshot Failed");
1866
+ }
1867
+ ctx.log.debug("Snapshot uploaded successfully");
1868
+ let lastExternalResponse = null;
1869
+ const startTime = Date.now();
1870
+ while (true) {
1871
+ try {
1872
+ const externalResponse = yield ctx.client.getSnapshotStatus(
1873
+ snapshotName,
1874
+ contextId,
1875
+ ctx
1876
+ );
1877
+ lastExternalResponse = externalResponse;
1878
+ if (externalResponse.statusCode === 200) {
1879
+ replyCode = 200;
1880
+ replyBody = externalResponse.data;
1881
+ return reply.code(replyCode).send(replyBody);
1882
+ } else if (externalResponse.statusCode === 202) {
1883
+ replyBody = externalResponse.data;
1884
+ ctx.log.debug(`External API attempt: Still processing, Pending Screenshots ${externalResponse.snapshotCount}`);
1885
+ yield new Promise((resolve) => setTimeout(resolve, 5e3));
1886
+ } else if (externalResponse.statusCode === 404) {
1887
+ ctx.log.debug(`Snapshot still processing, not uploaded`);
1888
+ yield new Promise((resolve) => setTimeout(resolve, 5e3));
1889
+ } else {
1890
+ ctx.log.debug(`Unexpected response from external API: ${JSON.stringify(externalResponse)}`);
1891
+ replyCode = 500;
1892
+ replyBody = {
1893
+ error: {
1894
+ message: `Unexpected response from external API: ${externalResponse.statusCode}`,
1895
+ externalApiStatus: externalResponse.statusCode
1896
+ }
1897
+ };
1898
+ return reply.code(replyCode).send(replyBody);
1899
+ }
1900
+ ctx.log.debug(`timeoutDuration: ${timeoutDuration}`);
1901
+ ctx.log.debug(`Time passed: ${Date.now() - startTime}`);
1902
+ if (Date.now() - startTime > timeoutDuration) {
1903
+ replyCode = 202;
1904
+ replyBody = {
1905
+ data: {
1906
+ message: "Request timed out-> Snapshot still processing"
1907
+ }
1908
+ };
1909
+ return reply.code(replyCode).send(replyBody);
1910
+ }
1911
+ } catch (externalApiError) {
1912
+ ctx.log.debug(`External API call failed: ${externalApiError.message}`);
1913
+ replyCode = 500;
1914
+ replyBody = {
1915
+ error: {
1916
+ message: `External API call failed: ${externalApiError.message}`
1917
+ }
1918
+ };
1919
+ return reply.code(replyCode).send(replyBody);
1920
+ }
1921
+ }
1922
+ } else {
1923
+ replyCode = 404;
1924
+ replyBody = { error: { message: `No snapshot found for contextId: ${contextId}` } };
1925
+ return reply.code(replyCode).send(replyBody);
1926
+ }
1927
+ } catch (error) {
1928
+ ctx.log.debug(`snapshot status failed; ${error}`);
1929
+ replyCode = 500;
1930
+ replyBody = { error: { message: error.message } };
1931
+ return reply.code(replyCode).send(replyBody);
1932
+ }
1933
+ }));
1784
1934
  yield server.listen({ port: ctx.options.port });
1785
1935
  let { port } = server.addresses()[0];
1786
1936
  process.env.SMARTUI_SERVER_ADDRESS = `http://localhost:${port}`;
@@ -1927,7 +2077,7 @@ var authExec_default = (ctx) => {
1927
2077
  };
1928
2078
 
1929
2079
  // package.json
1930
- var version = "4.1.25";
2080
+ var version = "4.1.26";
1931
2081
  var package_default = {
1932
2082
  name: "@lambdatest/smartui-cli",
1933
2083
  version,
@@ -2268,7 +2418,7 @@ var httpClient = class {
2268
2418
  }
2269
2419
  }, ctx.log);
2270
2420
  }
2271
- processSnapshot(ctx, snapshot, snapshotUuid, discoveryErrors) {
2421
+ processSnapshot(ctx, snapshot, snapshotUuid, discoveryErrors, variantCount, sync = false) {
2272
2422
  return this.request({
2273
2423
  url: `/build/${ctx.build.id}/snapshot`,
2274
2424
  method: "POST",
@@ -2277,12 +2427,14 @@ var httpClient = class {
2277
2427
  name: snapshot.name,
2278
2428
  url: snapshot.url,
2279
2429
  snapshotUuid,
2430
+ variantCount,
2280
2431
  test: {
2281
2432
  type: ctx.testType,
2282
2433
  source: "cli"
2283
2434
  },
2284
2435
  doRemoteDiscovery: snapshot.options.doRemoteDiscovery,
2285
- discoveryErrors
2436
+ discoveryErrors,
2437
+ sync
2286
2438
  }
2287
2439
  }, ctx.log);
2288
2440
  }
@@ -2546,6 +2698,15 @@ var httpClient = class {
2546
2698
  data: requestData
2547
2699
  }, ctx.log);
2548
2700
  }
2701
+ getSnapshotStatus(snapshotName, snapshotUuid, ctx) {
2702
+ return this.request({
2703
+ url: `/snapshot/status?buildId=${ctx.build.id}&snapshotName=${snapshotName}&snapshotUUID=${snapshotUuid}`,
2704
+ method: "GET",
2705
+ headers: {
2706
+ "Content-Type": "application/json"
2707
+ }
2708
+ }, ctx.log);
2709
+ }
2549
2710
  };
2550
2711
  var ctx_default = (options) => {
2551
2712
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
@@ -2633,6 +2794,9 @@ var ctx_default = (options) => {
2633
2794
  if (config.useLambdaInternal) {
2634
2795
  useLambdaInternal = true;
2635
2796
  }
2797
+ if (config.waitForPageRender && config.waitForPageRender < 3e4) {
2798
+ config.waitForPageRender = 3e4;
2799
+ }
2636
2800
  return {
2637
2801
  env,
2638
2802
  log: logger_default,
@@ -2978,7 +3142,7 @@ ${snapshot.warnings.length ? chalk__default.default.gray(`[warning] ${snapshot.w
2978
3142
  rendererOptions: { persistentOutput: true }
2979
3143
  };
2980
3144
  };
2981
- var uploadDomToS3ViaEnv = process.env.USE_LAMBDA_INTERNAL || false;
3145
+ var uploadDomToS3ViaEnv2 = process.env.USE_LAMBDA_INTERNAL || false;
2982
3146
  var finalizeBuild_default = (ctx) => {
2983
3147
  return {
2984
3148
  title: `Finalizing build`,
@@ -3043,7 +3207,7 @@ var finalizeBuild_default = (ctx) => {
3043
3207
  yield (_b = ctx2.server) == null ? void 0 : _b.close();
3044
3208
  ctx2.log.debug(`Closed server`);
3045
3209
  if (ctx2.isSnapshotCaptured) {
3046
- let uploadCLILogsToS3 = ctx2.config.useLambdaInternal || uploadDomToS3ViaEnv;
3210
+ let uploadCLILogsToS3 = ctx2.config.useLambdaInternal || uploadDomToS3ViaEnv2;
3047
3211
  if (!uploadCLILogsToS3) {
3048
3212
  ctx2.log.debug(`Log file to be uploaded`);
3049
3213
  let resp = yield ctx2.client.getS3PreSignedURL(ctx2);
@@ -3715,7 +3879,7 @@ function processSnapshot(snapshot, ctx) {
3715
3879
  };
3716
3880
  });
3717
3881
  }
3718
- var uploadDomToS3ViaEnv2 = process.env.USE_LAMBDA_INTERNAL || false;
3882
+ var uploadDomToS3ViaEnv3 = process.env.USE_LAMBDA_INTERNAL || false;
3719
3883
  var Queue = class {
3720
3884
  constructor(ctx) {
3721
3885
  this.snapshots = [];
@@ -3735,6 +3899,15 @@ var Queue = class {
3735
3899
  }
3736
3900
  }
3737
3901
  }
3902
+ enqueueFront(item) {
3903
+ this.snapshots.unshift(item);
3904
+ if (!this.ctx.config.delayedUpload) {
3905
+ if (!this.processing) {
3906
+ this.processing = true;
3907
+ this.processNext();
3908
+ }
3909
+ }
3910
+ }
3738
3911
  startProcessingfunc() {
3739
3912
  if (!this.processing) {
3740
3913
  this.processing = true;
@@ -3928,7 +4101,7 @@ var Queue = class {
3928
4101
  }
3929
4102
  processNext() {
3930
4103
  return __async(this, null, function* () {
3931
- var _a, _b, _c, _d;
4104
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
3932
4105
  if (!this.isEmpty()) {
3933
4106
  let snapshot;
3934
4107
  if (this.ctx.config.delayedUpload) {
@@ -3984,9 +4157,10 @@ var Queue = class {
3984
4157
  discoveryErrors = result.discoveryErrors;
3985
4158
  }
3986
4159
  if (useCapsBuildId) {
4160
+ this.ctx.log.info(`Using cached buildId: ${capsBuildId}`);
3987
4161
  if (useKafkaFlowCaps) {
3988
4162
  const snapshotUuid = uuid.v4();
3989
- let uploadDomToS3 = this.ctx.config.useLambdaInternal || uploadDomToS3ViaEnv2;
4163
+ let uploadDomToS3 = this.ctx.config.useLambdaInternal || uploadDomToS3ViaEnv3;
3990
4164
  if (!uploadDomToS3) {
3991
4165
  this.ctx.log.debug(`Uploading dom to S3 for snapshot using presigned URL for CAPS`);
3992
4166
  const presignedResponse = yield this.ctx.client.getS3PresignedURLForSnapshotUploadCaps(this.ctx, processedSnapshot.name, snapshotUuid, capsBuildId, capsProjectToken);
@@ -4028,9 +4202,12 @@ var Queue = class {
4028
4202
  }
4029
4203
  }
4030
4204
  if (this.ctx.build && this.ctx.build.useKafkaFlow) {
4031
- const snapshotUuid = uuid.v4();
4205
+ let snapshotUuid = uuid.v4();
4032
4206
  let snapshotUploadResponse;
4033
- let uploadDomToS3 = this.ctx.config.useLambdaInternal || uploadDomToS3ViaEnv2;
4207
+ 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))) {
4208
+ snapshotUuid = snapshot.options.contextId;
4209
+ }
4210
+ let uploadDomToS3 = this.ctx.config.useLambdaInternal || uploadDomToS3ViaEnv3;
4034
4211
  if (!uploadDomToS3) {
4035
4212
  this.ctx.log.debug(`Uploading dom to S3 for snapshot using presigned URL`);
4036
4213
  const presignedResponse = yield this.ctx.client.getS3PresignedURLForSnapshotUpload(this.ctx, processedSnapshot.name, snapshotUuid);
@@ -4053,11 +4230,19 @@ var Queue = class {
4053
4230
  this.ctx.log.debug(`Closed browser context for snapshot ${snapshot.name}`);
4054
4231
  }
4055
4232
  }
4233
+ if ((_g = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _g.contextId) {
4234
+ (_i = this.ctx.contextToSnapshotMap) == null ? void 0 : _i.set((_h = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _h.contextId, 2);
4235
+ }
4056
4236
  this.processNext();
4057
4237
  } else {
4058
- yield this.ctx.client.processSnapshot(this.ctx, processedSnapshot, snapshotUuid, discoveryErrors);
4238
+ 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);
4239
+ 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))) {
4240
+ this.ctx.contextToSnapshotMap.set(snapshot.options.contextId, 1);
4241
+ }
4242
+ this.ctx.log.debug(`ContextId: ${(_m = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _m.contextId} status set to uploaded`);
4059
4243
  }
4060
4244
  } else {
4245
+ this.ctx.log.info(`Uploading snapshot to S3`);
4061
4246
  yield this.ctx.client.uploadSnapshot(this.ctx, processedSnapshot, discoveryErrors);
4062
4247
  }
4063
4248
  this.ctx.totalSnapshots++;
@@ -4067,6 +4252,9 @@ var Queue = class {
4067
4252
  } catch (error) {
4068
4253
  this.ctx.log.debug(`snapshot failed; ${error}`);
4069
4254
  this.processedSnapshots.push({ name: snapshot == null ? void 0 : snapshot.name, error: error.message });
4255
+ if (((_n = snapshot == null ? void 0 : snapshot.options) == null ? void 0 : _n.contextId) && this.ctx.contextToSnapshotMap) {
4256
+ this.ctx.contextToSnapshotMap.set(snapshot.options.contextId, 2);
4257
+ }
4070
4258
  }
4071
4259
  if (this.ctx.browser) {
4072
4260
  for (let context of this.ctx.browser.contexts()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdatest/smartui-cli",
3
- "version": "4.1.25",
3
+ "version": "4.1.26",
4
4
  "description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
5
5
  "files": [
6
6
  "dist/**/*"