@lambdatest/smartui-cli 4.1.42-beta.0 → 4.1.43

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 +136 -21
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -112,7 +112,7 @@ var __async = (__this, __arguments, generator) => {
112
112
 
113
113
  // node_modules/.pnpm/find-free-port@2.0.0/node_modules/find-free-port/index.js
114
114
  var require_find_free_port = __commonJS({
115
- "node_modules/.pnpm/find-free-port@2.0.0/node_modules/find-free-port/index.js"(exports, module) {
115
+ "node_modules/.pnpm/find-free-port@2.0.0/node_modules/find-free-port/index.js"(exports$1, module) {
116
116
  var net = __require("net");
117
117
  function findFreePort(beg, ...rest) {
118
118
  const p = rest.slice(0, rest.length - 1), cb = rest[rest.length - 1];
@@ -870,6 +870,14 @@ var ConfigSchema = {
870
870
  uniqueItems: "Invalid config; duplicates in requestHeaders"
871
871
  }
872
872
  },
873
+ dedicatedProxyURL: {
874
+ type: "string",
875
+ errorMessage: "Invalid config; dedicatedProxyURL must be a string"
876
+ },
877
+ geolocation: {
878
+ type: "string",
879
+ errorMessage: "Invalid config; geolocation must be a string like 'lat,lon'"
880
+ },
873
881
  allowDuplicateSnapshotNames: {
874
882
  type: "boolean",
875
883
  errorMessage: "Invalid config; allowDuplicateSnapshotNames must be true/false"
@@ -946,6 +954,9 @@ var WebStaticConfigSchema = {
946
954
  execute: {
947
955
  type: "object",
948
956
  properties: {
957
+ beforeNavigation: {
958
+ type: "string"
959
+ },
949
960
  afterNavigation: {
950
961
  type: "string"
951
962
  },
@@ -1878,7 +1889,7 @@ function startPollingForTunnel(ctx, build_id, baseline, projectToken, buildName)
1878
1889
  function stopTunnelHelper(ctx) {
1879
1890
  return __async(this, null, function* () {
1880
1891
  ctx.log.debug("stop-tunnel:: Stopping the tunnel now");
1881
- const tunnelRunningStatus = yield tunnelInstance.isRunning();
1892
+ const tunnelRunningStatus = yield tunnelInstance == null ? void 0 : tunnelInstance.isRunning();
1882
1893
  ctx.log.debug("stop-tunnel:: Running status of tunnel before stopping ? " + tunnelRunningStatus);
1883
1894
  const status = yield tunnelInstance.stop();
1884
1895
  ctx.log.debug("stop-tunnel:: Tunnel is Stopped ? " + status);
@@ -2573,7 +2584,10 @@ var server_default = (ctx) => __async(void 0, null, function* () {
2573
2584
  lastExternalResponse = externalResponse;
2574
2585
  if (externalResponse.statusCode === 200) {
2575
2586
  replyCode = 200;
2576
- replyBody = externalResponse.data;
2587
+ replyBody = {
2588
+ data: externalResponse.data,
2589
+ error: externalResponse.error.message
2590
+ };
2577
2591
  return reply.code(replyCode).send(replyBody);
2578
2592
  } else if (externalResponse.statusCode === 202) {
2579
2593
  replyBody = externalResponse.data;
@@ -2585,22 +2599,15 @@ var server_default = (ctx) => __async(void 0, null, function* () {
2585
2599
  } else {
2586
2600
  ctx.log.debug(`Unexpected response from external API: ${JSON.stringify(externalResponse)}`);
2587
2601
  replyCode = 500;
2588
- replyBody = {
2589
- error: {
2590
- message: `Unexpected response from external API: ${externalResponse.statusCode}`,
2591
- externalApiStatus: externalResponse.statusCode
2592
- }
2593
- };
2594
- return reply.code(replyCode).send(replyBody);
2602
+ return reply.code(replyCode).send(externalResponse);
2595
2603
  }
2596
2604
  ctx.log.debug(`timeoutDuration: ${timeoutDuration}`);
2597
2605
  ctx.log.debug(`Time passed: ${Date.now() - startTime}`);
2598
2606
  if (Date.now() - startTime > timeoutDuration) {
2599
2607
  replyCode = 202;
2600
2608
  replyBody = {
2601
- data: {
2602
- message: "Request timed out-> Snapshot still processing"
2603
- }
2609
+ error: "Request timed out, Snapshot still processing",
2610
+ data: lastExternalResponse.data
2604
2611
  };
2605
2612
  return reply.code(replyCode).send(replyBody);
2606
2613
  }
@@ -2669,7 +2676,8 @@ var env_default = () => {
2669
2676
  SHOW_RENDER_ERRORS,
2670
2677
  SMARTUI_SSE_URL = "https://server-events.lambdatest.com",
2671
2678
  LT_SDK_SKIP_EXECUTION_LOGS,
2672
- MAX_CONCURRENT_PROCESSING
2679
+ MAX_CONCURRENT_PROCESSING,
2680
+ DO_NOT_USE_USER_AGENT
2673
2681
  } = process.env;
2674
2682
  return {
2675
2683
  PROJECT_TOKEN,
@@ -2696,7 +2704,8 @@ var env_default = () => {
2696
2704
  SHOW_RENDER_ERRORS: SHOW_RENDER_ERRORS === "true",
2697
2705
  SMARTUI_SSE_URL,
2698
2706
  LT_SDK_SKIP_EXECUTION_LOGS: LT_SDK_SKIP_EXECUTION_LOGS === "true",
2699
- MAX_CONCURRENT_PROCESSING: MAX_CONCURRENT_PROCESSING ? parseInt(MAX_CONCURRENT_PROCESSING, 10) : 0
2707
+ MAX_CONCURRENT_PROCESSING: MAX_CONCURRENT_PROCESSING ? parseInt(MAX_CONCURRENT_PROCESSING, 10) : 0,
2708
+ DO_NOT_USE_USER_AGENT: DO_NOT_USE_USER_AGENT === "true"
2700
2709
  };
2701
2710
  };
2702
2711
  var logContext = {};
@@ -2791,7 +2800,7 @@ var authExec_default = (ctx) => {
2791
2800
  };
2792
2801
 
2793
2802
  // package.json
2794
- var version = "4.1.42-beta.0";
2803
+ var version = "4.1.43";
2795
2804
  var package_default = {
2796
2805
  name: "@lambdatest/smartui-cli",
2797
2806
  version,
@@ -2992,12 +3001,20 @@ var httpClient = class {
2992
3001
  }
2993
3002
  }, log2);
2994
3003
  if (response && response.projectToken) {
3004
+ let orgId = 0;
3005
+ let userId = 0;
2995
3006
  this.projectToken = response.projectToken;
2996
3007
  env.PROJECT_TOKEN = response.projectToken;
2997
3008
  if (response.message && response.message.includes("Project created successfully")) {
2998
3009
  result = 2;
2999
3010
  }
3000
- return result;
3011
+ if (response.orgId) {
3012
+ orgId = response.orgId;
3013
+ }
3014
+ if (response.userId) {
3015
+ userId = response.userId;
3016
+ }
3017
+ return { authResult: result, orgId, userId };
3001
3018
  } else {
3002
3019
  throw new Error("Authentication failed, project token not received");
3003
3020
  }
@@ -3488,6 +3505,20 @@ var httpClient = class {
3488
3505
  }
3489
3506
  }, ctx.log);
3490
3507
  }
3508
+ getGeolocationProxy(geoLocation, log2) {
3509
+ return __async(this, null, function* () {
3510
+ try {
3511
+ const resp = yield this.request({
3512
+ url: "/geolocation",
3513
+ method: "GET",
3514
+ params: { geoLocation }
3515
+ }, log2);
3516
+ return resp;
3517
+ } catch (error) {
3518
+ this.handleHttpError(error, log2);
3519
+ }
3520
+ });
3521
+ }
3491
3522
  uploadPdf(ctx, form, buildName) {
3492
3523
  return __async(this, null, function* () {
3493
3524
  form.append("projectToken", this.projectToken);
@@ -3687,6 +3718,8 @@ var ctx_default = (options) => {
3687
3718
  ignoreHTTPSErrors: (_i = config.ignoreHTTPSErrors) != null ? _i : false,
3688
3719
  skipBuildCreation: (_j = config.skipBuildCreation) != null ? _j : false,
3689
3720
  tunnel: tunnelObj,
3721
+ dedicatedProxyURL: config.dedicatedProxyURL || "",
3722
+ geolocation: config.geolocation || "",
3690
3723
  userAgent: config.userAgent || "",
3691
3724
  requestHeaders: config.requestHeaders || {},
3692
3725
  allowDuplicateSnapshotNames,
@@ -4395,9 +4428,11 @@ function processSnapshot(snapshot, ctx) {
4395
4428
  };
4396
4429
  let contextOptions = {
4397
4430
  javaScriptEnabled: ctx.config.cliEnableJavaScript,
4398
- userAgent: constants_default.CHROME_USER_AGENT,
4399
4431
  ignoreHTTPSErrors: ctx.config.ignoreHTTPSErrors
4400
4432
  };
4433
+ if (!ctx.env.DO_NOT_USE_USER_AGENT) {
4434
+ contextOptions.userAgent = constants_default.CHROME_USER_AGENT;
4435
+ }
4401
4436
  if (!((_b = ctx.browser) == null ? void 0 : _b.isConnected())) {
4402
4437
  if (ctx.env.HTTP_PROXY || ctx.env.HTTPS_PROXY)
4403
4438
  launchOptions.proxy = { server: ctx.env.HTTP_PROXY || ctx.env.HTTPS_PROXY };
@@ -5542,7 +5577,7 @@ var startTunnel_default = (ctx) => {
5542
5577
 
5543
5578
  // src/commander/exec.ts
5544
5579
  var command = new commander.Command();
5545
- 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").option("--fetch-results [filename]", "Fetch results and optionally specify an output file, e.g., <filename>.json").option("--buildName <string>", "Specify the build name").option("--scheduled <string>", "Specify the schedule ID").option("--userName <string>", "Specify the LT username").option("--accessKey <string>", "Specify the LT accesskey").option("--show-render-errors", "Show render errors from SmartUI build").action(function(execCommand, _, command11) {
5580
+ 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").option("--fetch-results [filename]", "Fetch results and optionally specify an output file, e.g., <filename>.json").option("--buildName <string>", "Specify the build name").option("--scheduled <string>", "Specify the schedule ID").option("--show-render-errors", "Show render errors from SmartUI build").action(function(execCommand, _, command11) {
5546
5581
  return __async(this, null, function* () {
5547
5582
  var _a;
5548
5583
  const options = command11.optsWithGlobals();
@@ -5751,7 +5786,7 @@ var auth_default = (ctx) => {
5751
5786
  task: (ctx2, task) => __async(void 0, null, function* () {
5752
5787
  updateLogContext({ task: "auth" });
5753
5788
  try {
5754
- const authResult = yield ctx2.client.auth(ctx2.log, ctx2.env);
5789
+ const { authResult, orgId, userId } = yield ctx2.client.auth(ctx2.log, ctx2.env);
5755
5790
  if (authResult === 2) {
5756
5791
  task.output = chalk__default.default.gray(`New project '${ctx2.env.PROJECT_NAME}' created successfully`);
5757
5792
  } else if (authResult === 0) {
@@ -5759,6 +5794,8 @@ var auth_default = (ctx) => {
5759
5794
  } else if (authResult === 1) {
5760
5795
  task.output = chalk__default.default.gray(`Using existing project '${ctx2.env.PROJECT_NAME}'`);
5761
5796
  }
5797
+ ctx2.orgId = orgId;
5798
+ ctx2.userId = userId;
5762
5799
  task.title = "Authenticated with SmartUI";
5763
5800
  } catch (error) {
5764
5801
  ctx2.log.debug(error);
@@ -5808,6 +5845,7 @@ function captureScreenshotsForConfig(ctx, browsers, urlConfig, browserName, rend
5808
5845
  return __async(this, null, function* () {
5809
5846
  ctx.log.debug(`*** urlConfig ${JSON.stringify(urlConfig)}`);
5810
5847
  let { name, url, waitForTimeout, execute, pageEvent, userAgent } = urlConfig;
5848
+ let beforeNavigationScript = execute == null ? void 0 : execute.beforeNavigation;
5811
5849
  let afterNavigationScript = execute == null ? void 0 : execute.afterNavigation;
5812
5850
  let beforeSnapshotScript = execute == null ? void 0 : execute.beforeSnapshot;
5813
5851
  let waitUntilEvent = pageEvent || process.env.SMARTUI_PAGE_WAIT_UNTIL_EVENT || "load";
@@ -5818,6 +5856,69 @@ function captureScreenshotsForConfig(ctx, browsers, urlConfig, browserName, rend
5818
5856
  let contextOptions = {
5819
5857
  ignoreHTTPSErrors: ctx.config.ignoreHTTPSErrors
5820
5858
  };
5859
+ try {
5860
+ if (ctx.config.tunnel && ctx.config.tunnel.tunnelName) {
5861
+ if (ctx.tunnelDetails && ctx.tunnelDetails.tunnelPort != -1 && ctx.tunnelDetails.tunnelHost) {
5862
+ const tunnelServer = `http://${ctx.tunnelDetails.tunnelHost}:${ctx.tunnelDetails.tunnelPort}`;
5863
+ ctx.log.info(`URL Capture :: Using tunnel address: ${tunnelServer}`);
5864
+ contextOptions.proxy = { server: tunnelServer };
5865
+ } else {
5866
+ let tunnelResp = yield ctx.client.getTunnelDetails(ctx, ctx.log);
5867
+ ctx.log.debug(`Tunnel Response: ${JSON.stringify(tunnelResp)}`);
5868
+ if (tunnelResp && tunnelResp.data && tunnelResp.data.host && tunnelResp.data.port) {
5869
+ ctx.tunnelDetails = {
5870
+ tunnelHost: tunnelResp.data.host,
5871
+ tunnelPort: tunnelResp.data.port,
5872
+ tunnelName: tunnelResp.data.tunnel_name
5873
+ };
5874
+ const tunnelServer = `http://${ctx.tunnelDetails.tunnelHost}:${ctx.tunnelDetails.tunnelPort}`;
5875
+ ctx.log.info(`URL Capture :: Using tunnel address: ${tunnelServer}`);
5876
+ contextOptions.proxy = { server: tunnelServer };
5877
+ } else if (tunnelResp && tunnelResp.error) {
5878
+ if (tunnelResp.error.message) {
5879
+ ctx.log.warn(`Error while fetching tunnel details: ${tunnelResp.error.message}`);
5880
+ }
5881
+ }
5882
+ }
5883
+ } else if (ctx.config.geolocation && ctx.config.geolocation !== "") {
5884
+ if (ctx.geolocationData && ctx.geolocationData.proxy && ctx.geolocationData.username && ctx.geolocationData.password && ctx.geolocationData.geoCode === ctx.config.geolocation) {
5885
+ ctx.log.info(`URL Capture :: Using cached geolocation proxy for ${ctx.config.geolocation}`);
5886
+ contextOptions.proxy = {
5887
+ server: ctx.geolocationData.proxy,
5888
+ username: ctx.geolocationData.username,
5889
+ password: ctx.geolocationData.password
5890
+ };
5891
+ } else {
5892
+ const geoResp = yield ctx.client.getGeolocationProxy(ctx.config.geolocation, ctx.log);
5893
+ ctx.log.debug(`Geolocation proxy response: ${JSON.stringify(geoResp)}`);
5894
+ if (geoResp && geoResp.data && geoResp.data.proxy && geoResp.data.username && geoResp.data.password) {
5895
+ ctx.log.info(`URL Capture :: Using geolocation proxy for ${ctx.config.geolocation}`);
5896
+ ctx.geolocationData = {
5897
+ proxy: geoResp.data.proxy,
5898
+ username: geoResp.data.username,
5899
+ password: geoResp.data.password,
5900
+ geoCode: ctx.config.geolocation
5901
+ };
5902
+ contextOptions.proxy = {
5903
+ server: geoResp.data.proxy,
5904
+ username: geoResp.data.username,
5905
+ password: geoResp.data.password
5906
+ };
5907
+ } else {
5908
+ ctx.log.warn(`Geolocation proxy not available for '${ctx.config.geolocation}', falling back if dedicatedProxyURL present`);
5909
+ if (ctx.config.dedicatedProxyURL && ctx.config.dedicatedProxyURL !== "") {
5910
+ ctx.log.info(`URL Capture :: Using dedicated proxy: ${ctx.config.dedicatedProxyURL}`);
5911
+ contextOptions.proxy = { server: ctx.config.dedicatedProxyURL };
5912
+ }
5913
+ }
5914
+ }
5915
+ } else if (ctx.config.dedicatedProxyURL && ctx.config.dedicatedProxyURL !== "") {
5916
+ ctx.log.info(`URL Capture :: Using dedicated proxy: ${ctx.config.dedicatedProxyURL}`);
5917
+ contextOptions.proxy = { server: ctx.config.dedicatedProxyURL };
5918
+ }
5919
+ } catch (e) {
5920
+ ctx.log.debug(`Failed resolving tunnel/proxy details: ${e}`);
5921
+ }
5821
5922
  let page;
5822
5923
  if (browserName == constants_default.CHROME)
5823
5924
  contextOptions.userAgent = constants_default.CHROME_USER_AGENT;
@@ -5839,6 +5940,15 @@ function captureScreenshotsForConfig(ctx, browsers, urlConfig, browserName, rend
5839
5940
  const browser = browsers[browserName];
5840
5941
  context = yield browser == null ? void 0 : browser.newContext(contextOptions);
5841
5942
  page = yield context == null ? void 0 : context.newPage();
5943
+ if (beforeNavigationScript && beforeNavigationScript !== "") {
5944
+ const wrappedScript = new Function("page", `
5945
+ return (async () => {
5946
+ ${beforeNavigationScript}
5947
+ })();
5948
+ `);
5949
+ ctx.log.debug(`Executing before navigation script: ${wrappedScript}`);
5950
+ yield wrappedScript(page);
5951
+ }
5842
5952
  const headersObject = {};
5843
5953
  if (ctx.config.requestHeaders && Array.isArray(ctx.config.requestHeaders)) {
5844
5954
  ctx.config.requestHeaders.forEach((headerObj) => {
@@ -5854,6 +5964,11 @@ function captureScreenshotsForConfig(ctx, browsers, urlConfig, browserName, rend
5854
5964
  });
5855
5965
  });
5856
5966
  }
5967
+ if (ctx.config.basicAuthorization) {
5968
+ ctx.log.debug(`Adding basic authorization to the headers for root url`);
5969
+ let token = Buffer.from(`${ctx.config.basicAuthorization.username}:${ctx.config.basicAuthorization.password}`).toString("base64");
5970
+ headersObject["Authorization"] = `Basic ${token}`;
5971
+ }
5857
5972
  ctx.log.debug(`Combined headers: ${JSON.stringify(headersObject)}`);
5858
5973
  if (Object.keys(headersObject).length > 0) {
5859
5974
  yield page.setExtraHTTPHeaders(headersObject);
@@ -7221,7 +7336,7 @@ var uploadPdf_default = command10;
7221
7336
 
7222
7337
  // src/commander/commander.ts
7223
7338
  var program2 = new commander.Command();
7224
- program2.name("smartui").description("CLI to help you run your SmartUI tests on LambdaTest platform").version(`v${version}`).option("-c --config <filepath>", "Config file path").option("--markBaseline", "Mark this build baseline").option("--baselineBranch <string>", "Mark this build baseline").option("--baselineBuild <string>", "Mark this build baseline").option("--githubURL <string>", "GitHub URL including commitId").addCommand(exec_default2).addCommand(capture_default).addCommand(configWeb).addCommand(configStatic).addCommand(upload_default).addCommand(server_default2).addCommand(stopServer_default).addCommand(merge_default).addCommand(ping_default).addCommand(configFigma).addCommand(uploadFigma).addCommand(configWebFigma).addCommand(configAppFigma).addCommand(uploadWebFigmaCommand).addCommand(uploadAppFigmaCommand).addCommand(pingTest_default).addCommand(uploadPdf_default);
7339
+ program2.name("smartui").description("CLI to help you run your SmartUI tests on LambdaTest platform").version(`v${version}`).option("-c --config <filepath>", "Config file path").option("--markBaseline", "Mark this build baseline").option("--baselineBranch <string>", "Mark this build baseline").option("--baselineBuild <string>", "Mark this build baseline").option("--githubURL <string>", "GitHub URL including commitId").option("--userName <string>", "Specify the LT username").option("--accessKey <string>", "Specify the LT accesskey").addCommand(exec_default2).addCommand(capture_default).addCommand(configWeb).addCommand(configStatic).addCommand(upload_default).addCommand(server_default2).addCommand(stopServer_default).addCommand(merge_default).addCommand(ping_default).addCommand(configFigma).addCommand(uploadFigma).addCommand(configWebFigma).addCommand(configAppFigma).addCommand(uploadWebFigmaCommand).addCommand(uploadAppFigmaCommand).addCommand(pingTest_default).addCommand(uploadPdf_default);
7225
7340
  var commander_default = program2;
7226
7341
  (function() {
7227
7342
  return __async(this, null, function* () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdatest/smartui-cli",
3
- "version": "4.1.42-beta.0",
3
+ "version": "4.1.43",
4
4
  "description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
5
5
  "files": [
6
6
  "dist/**/*"