@lambdatest/smartui-cli 4.1.55 → 4.1.56-beta.2

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 +162 -21
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -18,10 +18,10 @@ var stringify = require('json-stringify-safe');
18
18
  var FormData = require('form-data');
19
19
  var axios = require('axios');
20
20
  var https = require('https');
21
+ var uuid = require('uuid');
21
22
  var child_process = require('child_process');
22
23
  var spawn = require('cross-spawn');
23
24
  var NodeCache = require('node-cache');
24
- var uuid = require('uuid');
25
25
  var sharp = require('sharp');
26
26
  var http = require('http');
27
27
 
@@ -2432,16 +2432,28 @@ function findAvailablePort(server, startPort, log2) {
2432
2432
  return currentPort;
2433
2433
  } catch (error) {
2434
2434
  if (error.code === "EADDRINUSE") {
2435
- log2.debug(`Port ${currentPort} is in use, finding available port in range 49100-60000`);
2436
- const availablePorts = yield fp(constants_default.MIN_PORT_RANGE, constants_default.MAX_PORT_RANGE);
2437
- if (availablePorts.length > 0) {
2438
- const freePort = availablePorts[0];
2439
- yield server.listen({ port: freePort });
2440
- log2.debug(`Found and started server on port ${freePort}`);
2441
- return freePort;
2442
- } else {
2443
- throw new Error("No available ports found in range 49100-60000");
2435
+ log2.debug(`Port ${currentPort} is in use, finding available port in range ${constants_default.MIN_PORT_RANGE}-${constants_default.MAX_PORT_RANGE}`);
2436
+ const maxRetries = 3;
2437
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
2438
+ try {
2439
+ const availablePorts = yield fp(constants_default.MIN_PORT_RANGE, constants_default.MAX_PORT_RANGE);
2440
+ if (availablePorts.length > 0) {
2441
+ const freePort = availablePorts[0];
2442
+ yield server.listen({ port: freePort });
2443
+ log2.debug(`Found and started server on port ${freePort}`);
2444
+ return freePort;
2445
+ } else {
2446
+ throw new Error(`No available ports found in range ${constants_default.MIN_PORT_RANGE}-${constants_default.MAX_PORT_RANGE}`);
2447
+ }
2448
+ } catch (retryError) {
2449
+ if (retryError.code === "EADDRINUSE" && attempt < maxRetries) {
2450
+ log2.debug(`Port race condition on attempt ${attempt}, retrying...`);
2451
+ continue;
2452
+ }
2453
+ throw retryError;
2454
+ }
2444
2455
  }
2456
+ throw new Error("Failed to find available port after max retries");
2445
2457
  } else {
2446
2458
  throw error;
2447
2459
  }
@@ -2700,6 +2712,68 @@ var server_default = (ctx) => __async(null, null, function* () {
2700
2712
  return reply.code(replyCode).send(replyBody);
2701
2713
  }
2702
2714
  }));
2715
+ server.get("/smartui/results", opts, (request, reply) => __async(null, null, function* () {
2716
+ var _a;
2717
+ let replyCode;
2718
+ let replyBody;
2719
+ try {
2720
+ const { sessionId } = request.query;
2721
+ ctx.log.debug(`smartui results request: sessionId=${sessionId || "none"}`);
2722
+ let resolvedBuildId = "";
2723
+ let projectToken = "";
2724
+ if (sessionId) {
2725
+ if ((_a = ctx.sessionCapabilitiesMap) == null ? void 0 : _a.has(sessionId)) {
2726
+ const cachedCapabilities = ctx.sessionCapabilitiesMap.get(sessionId);
2727
+ resolvedBuildId = (cachedCapabilities == null ? void 0 : cachedCapabilities.buildId) || "";
2728
+ projectToken = (cachedCapabilities == null ? void 0 : cachedCapabilities.projectToken) || "";
2729
+ ctx.log.debug(`Resolved from sessionCapabilitiesMap for sessionId ${sessionId}: buildId=${resolvedBuildId}, projectToken=${projectToken ? "present" : "missing"}`);
2730
+ } else {
2731
+ try {
2732
+ const fetchedCapabilitiesResp = yield ctx.client.getSmartUICapabilities(sessionId, ctx.config, ctx.git, ctx.log, ctx.isStartExec, ctx.options.baselineBuild);
2733
+ resolvedBuildId = (fetchedCapabilitiesResp == null ? void 0 : fetchedCapabilitiesResp.buildId) || "";
2734
+ projectToken = (fetchedCapabilitiesResp == null ? void 0 : fetchedCapabilitiesResp.projectToken) || "";
2735
+ ctx.log.debug(`Fetched caps for sessionId: ${sessionId} are ${JSON.stringify(fetchedCapabilitiesResp)}`);
2736
+ if (resolvedBuildId) {
2737
+ ctx.sessionCapabilitiesMap.set(sessionId, fetchedCapabilitiesResp);
2738
+ } else if (fetchedCapabilitiesResp && (fetchedCapabilitiesResp == null ? void 0 : fetchedCapabilitiesResp.sessionId)) {
2739
+ ctx.sessionCapabilitiesMap.set(sessionId, fetchedCapabilitiesResp);
2740
+ }
2741
+ } catch (error) {
2742
+ ctx.log.debug(`Failed to fetch capabilities for sessionId ${sessionId}: ${JSON.stringify(error)}`);
2743
+ }
2744
+ }
2745
+ }
2746
+ if ((!resolvedBuildId || resolvedBuildId.length <= 30) && ctx.build && ctx.build.id) {
2747
+ resolvedBuildId = ctx.build.id;
2748
+ }
2749
+ if (!projectToken) {
2750
+ projectToken = ctx.env.PROJECT_TOKEN || "";
2751
+ }
2752
+ ctx.log.debug(`smartui results params: sessionId=${sessionId || "none"}, buildId=${resolvedBuildId}, projectToken=${projectToken ? "present" : "missing"}`);
2753
+ if (!resolvedBuildId) {
2754
+ replyCode = 404;
2755
+ replyBody = { error: { message: "Unable to determine buildId. Ensure a SmartUI build is active." } };
2756
+ return reply.code(replyCode).send(replyBody);
2757
+ }
2758
+ const resp = yield ctx.client.getScreenshotData(
2759
+ resolvedBuildId,
2760
+ false,
2761
+ ctx.log,
2762
+ projectToken,
2763
+ "",
2764
+ sessionId || "",
2765
+ "smartui-results"
2766
+ );
2767
+ replyCode = 200;
2768
+ replyBody = resp;
2769
+ } catch (error) {
2770
+ const errMsg = (error == null ? void 0 : error.message) || (typeof error === "string" ? error : JSON.stringify(error));
2771
+ ctx.log.debug(`smartui results failed; ${errMsg}`);
2772
+ replyCode = 500;
2773
+ replyBody = { error: { message: `smartui results failed; ${errMsg}` } };
2774
+ }
2775
+ return reply.code(replyCode).send(replyBody);
2776
+ }));
2703
2777
  server.get("/build/info", opts, (request, reply) => __async(null, null, function* () {
2704
2778
  let replyCode;
2705
2779
  let replyBody;
@@ -2838,6 +2912,24 @@ var logger = winston.createLogger({
2838
2912
  })
2839
2913
  ]
2840
2914
  });
2915
+ function removeFileTransport() {
2916
+ logger.transports.forEach((transport) => {
2917
+ if (transport instanceof winston.transports.File) {
2918
+ logger.remove(transport);
2919
+ }
2920
+ });
2921
+ }
2922
+ function reconfigureLogFile(newFilePath) {
2923
+ logger.transports.forEach((transport) => {
2924
+ if (transport instanceof winston.transports.File) {
2925
+ logger.remove(transport);
2926
+ }
2927
+ });
2928
+ logger.add(new winston.transports.File({
2929
+ level: "debug",
2930
+ filename: newFilePath
2931
+ }));
2932
+ }
2841
2933
  var logger_default = logger;
2842
2934
 
2843
2935
  // src/tasks/startServer.ts
@@ -2895,7 +2987,7 @@ var authExec_default = (ctx) => {
2895
2987
  };
2896
2988
 
2897
2989
  // package.json
2898
- var version = "4.1.55";
2990
+ var version = "4.1.56-beta.2";
2899
2991
  var package_default = {
2900
2992
  name: "@lambdatest/smartui-cli",
2901
2993
  version,
@@ -3185,12 +3277,19 @@ var httpClient = class {
3185
3277
  }
3186
3278
  }, log2);
3187
3279
  }
3188
- getScreenshotData(buildId, baseline, log2, projectToken, buildName) {
3280
+ getScreenshotData(buildId, baseline, log2, projectToken, buildName, sessionId, type) {
3189
3281
  log2.debug(`Fetching screenshot data for buildId: ${buildId} having buildName: ${buildName} with baseline: ${baseline}`);
3282
+ const params = { buildId, baseline, buildName };
3283
+ if (sessionId) {
3284
+ params.sessionId = sessionId;
3285
+ }
3286
+ if (type) {
3287
+ params.type = type;
3288
+ }
3190
3289
  return this.request({
3191
3290
  url: "/screenshot",
3192
3291
  method: "GET",
3193
- params: { buildId, baseline, buildName },
3292
+ params,
3194
3293
  headers: { projectToken }
3195
3294
  }, log2);
3196
3295
  }
@@ -3509,8 +3608,13 @@ var httpClient = class {
3509
3608
  }, ctx.log);
3510
3609
  }
3511
3610
  uploadLogs(ctx, uploadURL) {
3512
- const fileStream = fs6__default.default.createReadStream(constants_default.LOG_FILE_PATH);
3513
- const { size } = fs6__default.default.statSync(constants_default.LOG_FILE_PATH);
3611
+ if (!ctx.logFilePath) {
3612
+ ctx.log.debug("Log file disabled, skipping log upload");
3613
+ return Promise.resolve();
3614
+ }
3615
+ const logPath = ctx.logFilePath;
3616
+ const fileStream = fs6__default.default.createReadStream(logPath);
3617
+ const { size } = fs6__default.default.statSync(logPath);
3514
3618
  return this.request({
3515
3619
  url: uploadURL,
3516
3620
  method: "PUT",
@@ -3526,8 +3630,13 @@ var httpClient = class {
3526
3630
  }, ctx.log);
3527
3631
  }
3528
3632
  uploadLogsForCaps(ctx, uploadURL) {
3529
- const logContent = fs6__default.default.readFileSync(constants_default.LOG_FILE_PATH);
3530
- const { size } = fs6__default.default.statSync(constants_default.LOG_FILE_PATH);
3633
+ if (!ctx.logFilePath) {
3634
+ ctx.log.debug("Log file disabled, skipping log upload");
3635
+ return Promise.resolve();
3636
+ }
3637
+ const logPath = ctx.logFilePath;
3638
+ const logContent = fs6__default.default.readFileSync(logPath);
3639
+ const { size } = fs6__default.default.statSync(logPath);
3531
3640
  return this.request({
3532
3641
  url: uploadURL,
3533
3642
  method: "PUT",
@@ -3543,7 +3652,12 @@ var httpClient = class {
3543
3652
  }, ctx.log);
3544
3653
  }
3545
3654
  sendCliLogsToLSRS(ctx) {
3546
- const logContent = fs6__default.default.readFileSync(constants_default.LOG_FILE_PATH, "utf-8");
3655
+ if (!ctx.logFilePath) {
3656
+ ctx.log.debug("Log file disabled, skipping log upload");
3657
+ return Promise.resolve();
3658
+ }
3659
+ const logPath = ctx.logFilePath;
3660
+ const logContent = fs6__default.default.readFileSync(logPath, "utf-8");
3547
3661
  return this.request({
3548
3662
  url: `/upload/logs`,
3549
3663
  method: "POST",
@@ -3555,7 +3669,12 @@ var httpClient = class {
3555
3669
  }, ctx.log);
3556
3670
  }
3557
3671
  sendCliLogsToLSRSForCaps(ctx, capsBuildId, capsProjectToken) {
3558
- const logContent = fs6__default.default.readFileSync(constants_default.LOG_FILE_PATH, "utf-8");
3672
+ if (!ctx.logFilePath) {
3673
+ ctx.log.debug("Log file disabled, skipping log upload");
3674
+ return Promise.resolve();
3675
+ }
3676
+ const logPath = ctx.logFilePath;
3677
+ const logContent = fs6__default.default.readFileSync(logPath, "utf-8");
3559
3678
  return this.request({
3560
3679
  url: `/upload/logs`,
3561
3680
  method: "POST",
@@ -3851,6 +3970,26 @@ var ctx_default = (options) => {
3851
3970
  if (config.waitForPageRender && config.waitForPageRender < 3e4) {
3852
3971
  config.waitForPageRender = 3e4;
3853
3972
  }
3973
+ let disableLogFile = options.disableLogFile ? true : false;
3974
+ if (disableLogFile) {
3975
+ removeFileTransport();
3976
+ logger_default.debug("File logging disabled via --disableLogFile flag");
3977
+ }
3978
+ let logFileUUID;
3979
+ let logFilePath = disableLogFile ? void 0 : constants_default.LOG_FILE_PATH;
3980
+ if (!disableLogFile && options.createUniqueLogFile) {
3981
+ logFileUUID = uuid.v4();
3982
+ logFilePath = `.smartui-${logFileUUID}.log`;
3983
+ reconfigureLogFile(logFilePath);
3984
+ try {
3985
+ if (fs6__default.default.existsSync(logFilePath)) {
3986
+ fs6__default.default.unlinkSync(logFilePath);
3987
+ }
3988
+ } catch (error) {
3989
+ logger_default.debug(`Could not delete existing unique log file: ${error.message}`);
3990
+ }
3991
+ logger_default.debug(`Using unique log file: ${logFilePath} (UUID: ${logFileUUID})`);
3992
+ }
3854
3993
  return {
3855
3994
  env,
3856
3995
  log: logger_default,
@@ -3947,7 +4086,9 @@ var ctx_default = (options) => {
3947
4086
  mergeBuildSourceId: "",
3948
4087
  mergeBuildTargetId: "",
3949
4088
  mergeByBranch: false,
3950
- mergeByBuild: false
4089
+ mergeByBuild: false,
4090
+ logFileUUID,
4091
+ logFilePath
3951
4092
  };
3952
4093
  };
3953
4094
 
@@ -7642,7 +7783,7 @@ var uploadPdf_default = command10;
7642
7783
 
7643
7784
  // src/commander/commander.ts
7644
7785
  var program2 = new commander.Command();
7645
- 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("--gitURL <string>", "Git 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);
7786
+ 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("--gitURL <string>", "Git URL including commitId").option("--userName <string>", "Specify the LT username").option("--accessKey <string>", "Specify the LT accesskey").option("--createUniqueLogFile", "Create a unique log file for each CLI execution to avoid file lock issues in parallel runs").option("--disableLogFile", "Disable writing logs to a file").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);
7646
7787
  var commander_default = program2;
7647
7788
  (function() {
7648
7789
  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.55",
3
+ "version": "4.1.56-beta.2",
4
4
  "description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
5
5
  "files": [
6
6
  "dist/**/*"