@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.
- package/dist/index.cjs +75 -13
- 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)
|
|
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":
|
|
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.
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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;
|