@lambdatest/smartui-cli 4.1.38-beta.1 → 4.1.39

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 +75 -13
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -297,6 +297,7 @@ var constants_default = {
297
297
  MOBILE_ORIENTATION_PORTRAIT: "portrait",
298
298
  MOBILE_ORIENTATION_LANDSCAPE: "landscape",
299
299
  // build status
300
+ BUILD_RUNNING: "running",
300
301
  BUILD_COMPLETE: "completed",
301
302
  BUILD_ERROR: "error",
302
303
  // CI
@@ -1920,7 +1921,7 @@ function startPdfPolling(ctx) {
1920
1921
  attempts++;
1921
1922
  try {
1922
1923
  const response = yield ctx.client.fetchPdfResults(ctx);
1923
- if (response.screenshots && ((_a = response.build) == null ? void 0 : _a.build_status) === constants_default.BUILD_COMPLETE) {
1924
+ if (response.screenshots && ((_a = response.build) == null ? void 0 : _a.build_status) !== constants_default.BUILD_RUNNING) {
1924
1925
  clearInterval(interval);
1925
1926
  const pdfGroups = groupScreenshotsByPdf(response.screenshots);
1926
1927
  const pdfsWithMismatches = countPdfsWithMismatches(pdfGroups);
@@ -2086,12 +2087,13 @@ function listenToSmartUISSE(baseURL, accessToken, ctx, onEvent) {
2086
2087
  const url = `${baseURL}/api/v1/sse/smartui`;
2087
2088
  const abortController = new AbortController();
2088
2089
  try {
2090
+ const cookieKey = baseURL === "https://server-events.lambdatest.com" ? "accessToken" : "stageAccessToken";
2089
2091
  const response = yield fetch(url, {
2090
2092
  method: "GET",
2091
2093
  headers: {
2092
2094
  "Accept": "text/event-stream",
2093
2095
  "Cache-Control": "no-cache",
2094
- "Cookie": `stageAccessToken=Basic ${accessToken}`
2096
+ "Cookie": `${cookieKey}=Basic ${accessToken}`
2095
2097
  },
2096
2098
  signal: abortController.signal
2097
2099
  });
@@ -2269,7 +2271,7 @@ var server_default = (ctx) => __async(void 0, null, function* () {
2269
2271
  capsBuildId = (cachedCapabilities == null ? void 0 : cachedCapabilities.buildId) || "";
2270
2272
  } else {
2271
2273
  try {
2272
- let fetchedCapabilitiesResp = yield ctx.client.getSmartUICapabilities(sessionId, ctx.config, ctx.git, ctx.log, ctx.isStartExec);
2274
+ let fetchedCapabilitiesResp = yield ctx.client.getSmartUICapabilities(sessionId, ctx.config, ctx.git, ctx.log, ctx.isStartExec, ctx.options.baselineBuild);
2273
2275
  capsBuildId = (fetchedCapabilitiesResp == null ? void 0 : fetchedCapabilitiesResp.buildId) || "";
2274
2276
  ctx.log.debug(`fetch caps for sessionId: ${sessionId} are ${JSON.stringify(fetchedCapabilitiesResp)}`);
2275
2277
  if (capsBuildId) {
@@ -2397,7 +2399,8 @@ var server_default = (ctx) => __async(void 0, null, function* () {
2397
2399
  let replyBody;
2398
2400
  try {
2399
2401
  ctx.log.debug(`request.query : ${JSON.stringify(request.query)}`);
2400
- const { contextId, pollTimeout, snapshotName } = request.query;
2402
+ const { contextId, pollTimeout, snapshotName: rawSnapshotName } = request.query;
2403
+ const snapshotName = rawSnapshotName == null ? void 0 : rawSnapshotName.trim();
2401
2404
  if (!contextId || !snapshotName) {
2402
2405
  throw new Error("contextId and snapshotName are required parameters");
2403
2406
  }
@@ -2650,7 +2653,7 @@ var authExec_default = (ctx) => {
2650
2653
  };
2651
2654
 
2652
2655
  // package.json
2653
- var version = "4.1.38-beta.1";
2656
+ var version = "4.1.39";
2654
2657
  var package_default = {
2655
2658
  name: "@lambdatest/smartui-cli",
2656
2659
  version,
@@ -2961,7 +2964,7 @@ var httpClient = class {
2961
2964
  }
2962
2965
  }, log2);
2963
2966
  }
2964
- getSmartUICapabilities(sessionId, config, git, log2, isStartExec) {
2967
+ getSmartUICapabilities(sessionId, config, git, log2, isStartExec, baselineBuild) {
2965
2968
  return this.request({
2966
2969
  url: "/sessions/capabilities",
2967
2970
  method: "GET",
@@ -2971,7 +2974,8 @@ var httpClient = class {
2971
2974
  data: {
2972
2975
  git,
2973
2976
  config,
2974
- isStartExec
2977
+ isStartExec,
2978
+ baselineBuild
2975
2979
  },
2976
2980
  headers: {
2977
2981
  projectToken: "",
@@ -3328,8 +3332,13 @@ var httpClient = class {
3328
3332
  }
3329
3333
  getSnapshotStatus(buildId, snapshotName, snapshotUuid, ctx) {
3330
3334
  return this.request({
3331
- url: `/snapshot/status?buildId=${buildId}&snapshotName=${snapshotName}&snapshotUUID=${snapshotUuid}`,
3335
+ url: `/snapshot/status`,
3332
3336
  method: "GET",
3337
+ params: {
3338
+ buildId,
3339
+ snapshotName,
3340
+ snapshotUUID: snapshotUuid
3341
+ },
3333
3342
  headers: {
3334
3343
  "Content-Type": "application/json"
3335
3344
  }
@@ -3719,7 +3728,8 @@ var createBuildExec_default = (ctx) => {
3719
3728
  name: resp.data.buildName,
3720
3729
  url: resp.data.buildURL,
3721
3730
  baseline: resp.data.baseline,
3722
- useKafkaFlow: resp.data.useKafkaFlow || false
3731
+ useKafkaFlow: resp.data.useKafkaFlow || false,
3732
+ checkPendingRequests: resp.data.checkPendingRequests || false
3723
3733
  };
3724
3734
  process.env.SMARTUI_BUILD_ID = resp.data.buildId;
3725
3735
  process.env.SMARTUI_BUILD_NAME = resp.data.buildName;
@@ -4005,8 +4015,20 @@ var globalCache = new NodeCache__default.default({ stdTTL: 3600, checkperiod: 60
4005
4015
  var MAX_RESOURCE_SIZE = 15 * 1024 ** 2;
4006
4016
  var ALLOWED_RESOURCES = ["document", "stylesheet", "image", "media", "font", "other"];
4007
4017
  var ALLOWED_STATUSES = [200, 201];
4008
- var REQUEST_TIMEOUT = 18e5;
4018
+ var REQUEST_TIMEOUT = 18e4;
4009
4019
  var MIN_VIEWPORT_HEIGHT = 1080;
4020
+ var MAX_WAIT_FOR_REQUEST_CALL = 3e4;
4021
+ var normalizeSameSite = (value) => {
4022
+ if (!value)
4023
+ return "Lax";
4024
+ const normalized = value.trim().toLowerCase();
4025
+ const mapping = {
4026
+ "lax": "Lax",
4027
+ "strict": "Strict",
4028
+ "none": "None"
4029
+ };
4030
+ return mapping[normalized] || value;
4031
+ };
4010
4032
  function prepareSnapshot(snapshot, ctx) {
4011
4033
  return __async(this, null, function* () {
4012
4034
  let processedOptions = {};
@@ -4229,7 +4251,8 @@ function processSnapshot(snapshot, ctx) {
4229
4251
  ctx.log.debug(`Skipping invalid custom cookie: missing required fields (name, value, or domain)`);
4230
4252
  return false;
4231
4253
  }
4232
- if (cookie.sameSite && !["Strict", "Lax", "None"].includes(cookie.sameSite)) {
4254
+ const sameSiteValue = normalizeSameSite(cookie.sameSite);
4255
+ if (!["Strict", "Lax", "None"].includes(sameSiteValue)) {
4233
4256
  ctx.log.debug(`Skipping invalid custom cookie: invalid sameSite value '${cookie.sameSite}'`);
4234
4257
  return false;
4235
4258
  }
@@ -4241,7 +4264,7 @@ function processSnapshot(snapshot, ctx) {
4241
4264
  path: cookie.path || "/",
4242
4265
  httpOnly: cookie.httpOnly || false,
4243
4266
  secure: cookie.secure || false,
4244
- sameSite: cookie.sameSite || "Lax"
4267
+ sameSite: normalizeSameSite(cookie.sameSite)
4245
4268
  }));
4246
4269
  if (validCustomCookies.length > 0) {
4247
4270
  try {
@@ -4265,6 +4288,7 @@ function processSnapshot(snapshot, ctx) {
4265
4288
  };
4266
4289
  }
4267
4290
  }
4291
+ const pendingRequests = /* @__PURE__ */ new Set();
4268
4292
  yield page.route("**/*", (route, request) => __async(this, null, function* () {
4269
4293
  var _a2;
4270
4294
  const requestUrl = request.url();
@@ -4314,8 +4338,14 @@ function processSnapshot(snapshot, ctx) {
4314
4338
  body = globalCache.get(requestUrl).body;
4315
4339
  } else {
4316
4340
  ctx.log.debug(`Resource not found in cache or global cache ${requestUrl} fetching from server`);
4341
+ if (ctx.build.checkPendingRequests) {
4342
+ pendingRequests.add(requestUrl);
4343
+ }
4317
4344
  response = yield page.request.fetch(request, requestOptions);
4318
4345
  body = yield response.body();
4346
+ if (ctx.build.checkPendingRequests) {
4347
+ pendingRequests.delete(requestUrl);
4348
+ }
4319
4349
  }
4320
4350
  if (!body) {
4321
4351
  ctx.log.debug(`Handling request ${requestUrl}
@@ -4347,8 +4377,14 @@ function processSnapshot(snapshot, ctx) {
4347
4377
  }
4348
4378
  let responseOfRetry, bodyOfRetry;
4349
4379
  ctx.log.debug(`Resource had a disallowed status ${requestUrl} fetching from server again`);
4380
+ if (ctx.build.checkPendingRequests) {
4381
+ pendingRequests.add(requestUrl);
4382
+ }
4350
4383
  responseOfRetry = yield page.request.fetch(request, requestOptions);
4351
4384
  bodyOfRetry = yield responseOfRetry.body();
4385
+ if (ctx.build.checkPendingRequests) {
4386
+ pendingRequests.delete(requestUrl);
4387
+ }
4352
4388
  if (responseOfRetry && responseOfRetry.status() && ALLOWED_STATUSES.includes(responseOfRetry.status())) {
4353
4389
  ctx.log.debug(`Handling request after retry ${requestUrl}
4354
4390
  - content-type ${responseOfRetry.headers()["content-type"]}`);
@@ -4356,6 +4392,12 @@ function processSnapshot(snapshot, ctx) {
4356
4392
  body: bodyOfRetry.toString("base64"),
4357
4393
  type: responseOfRetry.headers()["content-type"]
4358
4394
  };
4395
+ if (ctx.config.useGlobalCache) {
4396
+ globalCache.set(requestUrl, {
4397
+ body: bodyOfRetry.toString("base64"),
4398
+ type: responseOfRetry.headers()["content-type"]
4399
+ });
4400
+ }
4359
4401
  route.fulfill({
4360
4402
  status: responseOfRetry.status(),
4361
4403
  headers: responseOfRetry.headers(),
@@ -4732,6 +4774,25 @@ function processSnapshot(snapshot, ctx) {
4732
4774
  processedOptions.selectDOM = options == null ? void 0 : options.selectDOM;
4733
4775
  ctx.log.debug(`Processed options: ${JSON.stringify(processedOptions)}`);
4734
4776
  }
4777
+ const checkPending = () => __async(this, null, function* () {
4778
+ let startTime = Date.now();
4779
+ ctx.log.debug(`${pendingRequests.size} Pending requests before wait for ${snapshot.name}: ${Array.from(pendingRequests)}`);
4780
+ while (pendingRequests.size > 0) {
4781
+ const elapsedTime = Date.now() - startTime;
4782
+ if (elapsedTime >= MAX_WAIT_FOR_REQUEST_CALL) {
4783
+ ctx.log.debug(`Timeout reached (${MAX_WAIT_FOR_REQUEST_CALL / 1e3}s). Stopping wait for pending requests.`);
4784
+ ctx.log.debug(`${pendingRequests.size} Pending requests after wait for ${snapshot.name}: ${Array.from(pendingRequests)}`);
4785
+ break;
4786
+ }
4787
+ yield new Promise((resolve) => setTimeout(resolve, 1e3));
4788
+ }
4789
+ if (pendingRequests.size === 0) {
4790
+ ctx.log.debug(`No pending requests for ${snapshot.name}.`);
4791
+ }
4792
+ });
4793
+ if (ctx.build.checkPendingRequests) {
4794
+ yield checkPending();
4795
+ }
4735
4796
  let hasBrowserErrors = false;
4736
4797
  for (let browser in discoveryErrors.browsers) {
4737
4798
  if (discoveryErrors.browsers[browser]) {
@@ -5465,7 +5526,8 @@ var createBuild_default = (ctx) => {
5465
5526
  name: resp.data.buildName,
5466
5527
  url: resp.data.buildURL,
5467
5528
  baseline: resp.data.baseline,
5468
- useKafkaFlow: resp.data.useKafkaFlow || false
5529
+ useKafkaFlow: resp.data.useKafkaFlow || false,
5530
+ checkPendingRequests: resp.data.checkPendingRequests || false
5469
5531
  };
5470
5532
  process.env.SMARTUI_BUILD_ID = resp.data.buildId;
5471
5533
  process.env.SMARTUI_BUILD_NAME = resp.data.buildName;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdatest/smartui-cli",
3
- "version": "4.1.38-beta.1",
3
+ "version": "4.1.39",
4
4
  "description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
5
5
  "files": [
6
6
  "dist/**/*"