@lambdatest/smartui-cli 4.1.33 → 4.1.35
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 +261 -58
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -61,6 +61,7 @@ var sharp__default = /*#__PURE__*/_interopDefault(sharp);
|
|
|
61
61
|
var http__namespace = /*#__PURE__*/_interopNamespace(http);
|
|
62
62
|
|
|
63
63
|
var __defProp = Object.defineProperty;
|
|
64
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
64
65
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
65
66
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
66
67
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -83,6 +84,9 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
83
84
|
return require.apply(this, arguments);
|
|
84
85
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
85
86
|
});
|
|
87
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
88
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
89
|
+
};
|
|
86
90
|
var __async = (__this, __arguments, generator) => {
|
|
87
91
|
return new Promise((resolve, reject) => {
|
|
88
92
|
var fulfilled = (value) => {
|
|
@@ -104,6 +108,73 @@ var __async = (__this, __arguments, generator) => {
|
|
|
104
108
|
});
|
|
105
109
|
};
|
|
106
110
|
|
|
111
|
+
// node_modules/.pnpm/find-free-port@2.0.0/node_modules/find-free-port/index.js
|
|
112
|
+
var require_find_free_port = __commonJS({
|
|
113
|
+
"node_modules/.pnpm/find-free-port@2.0.0/node_modules/find-free-port/index.js"(exports, module) {
|
|
114
|
+
var net = __require("net");
|
|
115
|
+
function findFreePort(beg, ...rest) {
|
|
116
|
+
const p = rest.slice(0, rest.length - 1), cb = rest[rest.length - 1];
|
|
117
|
+
let [end, ip, cnt] = Array.from(p);
|
|
118
|
+
if (!ip && end && !/^\d+$/.test(end)) {
|
|
119
|
+
ip = end;
|
|
120
|
+
end = 65534;
|
|
121
|
+
} else {
|
|
122
|
+
if (end == null) {
|
|
123
|
+
end = 65534;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (cnt == null) {
|
|
127
|
+
cnt = 1;
|
|
128
|
+
}
|
|
129
|
+
const retcb = cb;
|
|
130
|
+
const res = [];
|
|
131
|
+
const probe = function(ip2, port, cb2) {
|
|
132
|
+
const s = net.createConnection({ port, host: ip2 });
|
|
133
|
+
s.on("connect", function() {
|
|
134
|
+
s.end();
|
|
135
|
+
cb2(null, port + 1);
|
|
136
|
+
});
|
|
137
|
+
s.on("error", (err) => {
|
|
138
|
+
cb2(port);
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
var onprobe = function(port, nextPort) {
|
|
142
|
+
if (port) {
|
|
143
|
+
res.push(port);
|
|
144
|
+
if (res.length >= cnt) {
|
|
145
|
+
retcb(null, ...res);
|
|
146
|
+
} else {
|
|
147
|
+
setImmediate(() => probe(ip, port + 1, onprobe));
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
if (nextPort >= end) {
|
|
151
|
+
retcb(new Error("No available ports"));
|
|
152
|
+
} else {
|
|
153
|
+
setImmediate(() => probe(ip, nextPort, onprobe));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
return probe(ip, beg, onprobe);
|
|
158
|
+
}
|
|
159
|
+
function findFreePortPmfy(beg, ...rest) {
|
|
160
|
+
const last = rest[rest.length - 1];
|
|
161
|
+
if (typeof last === "function") {
|
|
162
|
+
findFreePort(beg, ...rest);
|
|
163
|
+
} else {
|
|
164
|
+
return new Promise((resolve, reject) => {
|
|
165
|
+
findFreePort(beg, ...rest, (err, ...ports) => {
|
|
166
|
+
if (err)
|
|
167
|
+
reject(err);
|
|
168
|
+
else
|
|
169
|
+
resolve(ports);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
module.exports = findFreePortPmfy;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
107
178
|
// src/lib/constants.ts
|
|
108
179
|
var constants_default = {
|
|
109
180
|
// default configs
|
|
@@ -152,6 +223,8 @@ var constants_default = {
|
|
|
152
223
|
EDGE: "edge",
|
|
153
224
|
EDGE_CHANNEL: "msedge",
|
|
154
225
|
WEBKIT: "webkit",
|
|
226
|
+
MIN_PORT_RANGE: 49100,
|
|
227
|
+
MAX_PORT_RANGE: 6e4,
|
|
155
228
|
// discovery browser launch arguments
|
|
156
229
|
LAUNCH_ARGS: [
|
|
157
230
|
// disable the translate popup and optimization downloads
|
|
@@ -785,6 +858,10 @@ var ConfigSchema = {
|
|
|
785
858
|
type: "boolean",
|
|
786
859
|
errorMessage: "Invalid config; useLambdaInternal must be true/false"
|
|
787
860
|
},
|
|
861
|
+
useRemoteDiscovery: {
|
|
862
|
+
type: "boolean",
|
|
863
|
+
errorMessage: "Invalid config; useRemoteDiscovery must be true/false"
|
|
864
|
+
},
|
|
788
865
|
useExtendedViewport: {
|
|
789
866
|
type: "boolean",
|
|
790
867
|
errorMessage: "Invalid config; useExtendedViewport must be true/false"
|
|
@@ -1089,6 +1166,14 @@ var SnapshotSchema = {
|
|
|
1089
1166
|
minimum: 0,
|
|
1090
1167
|
maximum: 100,
|
|
1091
1168
|
errorMessage: "Invalid snapshot options; rejectionThreshold must be a number between 0 and 100"
|
|
1169
|
+
},
|
|
1170
|
+
customCookies: {
|
|
1171
|
+
type: "array",
|
|
1172
|
+
items: {
|
|
1173
|
+
type: "object",
|
|
1174
|
+
minProperties: 1
|
|
1175
|
+
},
|
|
1176
|
+
errorMessage: "Invalid snapshot options; customCookies must be an array of objects with string properties"
|
|
1092
1177
|
}
|
|
1093
1178
|
},
|
|
1094
1179
|
additionalProperties: false
|
|
@@ -1810,10 +1895,11 @@ function startPdfPolling(ctx) {
|
|
|
1810
1895
|
const maxAttempts = 60;
|
|
1811
1896
|
console.log(chalk__default.default.yellow("Waiting for results..."));
|
|
1812
1897
|
const interval = setInterval(() => __async(this, null, function* () {
|
|
1898
|
+
var _a;
|
|
1813
1899
|
attempts++;
|
|
1814
1900
|
try {
|
|
1815
1901
|
const response = yield ctx.client.fetchPdfResults(ctx);
|
|
1816
|
-
if (response.screenshots) {
|
|
1902
|
+
if (response.screenshots && ((_a = response.build) == null ? void 0 : _a.build_status) === constants_default.BUILD_COMPLETE) {
|
|
1817
1903
|
clearInterval(interval);
|
|
1818
1904
|
const pdfGroups = groupScreenshotsByPdf(response.screenshots);
|
|
1819
1905
|
const pdfsWithMismatches = countPdfsWithMismatches(pdfGroups);
|
|
@@ -1971,7 +2057,32 @@ function validateCoordinates(coordString, pageHeight, pageWidth, snapshotName) {
|
|
|
1971
2057
|
}
|
|
1972
2058
|
|
|
1973
2059
|
// src/lib/server.ts
|
|
2060
|
+
var fp = require_find_free_port();
|
|
1974
2061
|
var uploadDomToS3ViaEnv = process.env.USE_LAMBDA_INTERNAL || false;
|
|
2062
|
+
function findAvailablePort(server, startPort, log2) {
|
|
2063
|
+
return __async(this, null, function* () {
|
|
2064
|
+
let currentPort = startPort;
|
|
2065
|
+
try {
|
|
2066
|
+
yield server.listen({ port: currentPort });
|
|
2067
|
+
return currentPort;
|
|
2068
|
+
} catch (error) {
|
|
2069
|
+
if (error.code === "EADDRINUSE") {
|
|
2070
|
+
log2.debug(`Port ${currentPort} is in use, finding available port in range 49100-60000`);
|
|
2071
|
+
const availablePorts = yield fp(constants_default.MIN_PORT_RANGE, constants_default.MAX_PORT_RANGE);
|
|
2072
|
+
if (availablePorts.length > 0) {
|
|
2073
|
+
const freePort = availablePorts[0];
|
|
2074
|
+
yield server.listen({ port: freePort });
|
|
2075
|
+
log2.debug(`Found and started server on port ${freePort}`);
|
|
2076
|
+
return freePort;
|
|
2077
|
+
} else {
|
|
2078
|
+
throw new Error("No available ports found in range 49100-60000");
|
|
2079
|
+
}
|
|
2080
|
+
} else {
|
|
2081
|
+
throw error;
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
});
|
|
2085
|
+
}
|
|
1975
2086
|
var server_default = (ctx) => __async(void 0, null, function* () {
|
|
1976
2087
|
const server = fastify__default.default({
|
|
1977
2088
|
logger: {
|
|
@@ -2221,10 +2332,18 @@ var server_default = (ctx) => __async(void 0, null, function* () {
|
|
|
2221
2332
|
return reply.code(replyCode).send(replyBody);
|
|
2222
2333
|
}
|
|
2223
2334
|
}));
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2335
|
+
if (ctx.sourceCommand && ctx.sourceCommand === "exec-start") {
|
|
2336
|
+
yield server.listen({ port: ctx.options.port });
|
|
2337
|
+
let { port } = server.addresses()[0];
|
|
2338
|
+
process.env.SMARTUI_SERVER_ADDRESS = `http://localhost:${port}`;
|
|
2339
|
+
process.env.CYPRESS_SMARTUI_SERVER_ADDRESS = `http://localhost:${port}`;
|
|
2340
|
+
ctx.log.debug(`Server started successfully on port ${port}`);
|
|
2341
|
+
} else {
|
|
2342
|
+
const actualPort = yield findAvailablePort(server, ctx.options.port, ctx.log);
|
|
2343
|
+
process.env.SMARTUI_SERVER_ADDRESS = `http://localhost:${actualPort}`;
|
|
2344
|
+
process.env.CYPRESS_SMARTUI_SERVER_ADDRESS = `http://localhost:${actualPort}`;
|
|
2345
|
+
ctx.log.debug(`Server started successfully on port ${actualPort}`);
|
|
2346
|
+
}
|
|
2228
2347
|
return server;
|
|
2229
2348
|
});
|
|
2230
2349
|
|
|
@@ -2369,7 +2488,7 @@ var authExec_default = (ctx) => {
|
|
|
2369
2488
|
};
|
|
2370
2489
|
|
|
2371
2490
|
// package.json
|
|
2372
|
-
var version = "4.1.
|
|
2491
|
+
var version = "4.1.35";
|
|
2373
2492
|
var package_default = {
|
|
2374
2493
|
name: "@lambdatest/smartui-cli",
|
|
2375
2494
|
version,
|
|
@@ -2425,6 +2544,7 @@ var package_default = {
|
|
|
2425
2544
|
"simple-swizzle": "0.2.2"
|
|
2426
2545
|
},
|
|
2427
2546
|
devDependencies: {
|
|
2547
|
+
"find-free-port": "^2.0.0",
|
|
2428
2548
|
typescript: "^5.3.2"
|
|
2429
2549
|
}
|
|
2430
2550
|
};
|
|
@@ -3041,6 +3161,9 @@ var httpClient = class {
|
|
|
3041
3161
|
if (ctx.build.name !== void 0 && ctx.build.name !== "") {
|
|
3042
3162
|
form.append("buildName", buildName);
|
|
3043
3163
|
}
|
|
3164
|
+
if (ctx.options.markBaseline) {
|
|
3165
|
+
form.append("markBaseline", ctx.options.markBaseline.toString());
|
|
3166
|
+
}
|
|
3044
3167
|
try {
|
|
3045
3168
|
const response = yield this.axiosInstance.request({
|
|
3046
3169
|
url: ctx.env.SMARTUI_UPLOAD_URL + "/pdf/upload",
|
|
@@ -3110,6 +3233,7 @@ var ctx_default = (options) => {
|
|
|
3110
3233
|
let buildNameObj;
|
|
3111
3234
|
let allowDuplicateSnapshotNames = false;
|
|
3112
3235
|
let useLambdaInternal = false;
|
|
3236
|
+
let useRemoteDiscovery = false;
|
|
3113
3237
|
let useExtendedViewport = false;
|
|
3114
3238
|
let loadDomContent = false;
|
|
3115
3239
|
try {
|
|
@@ -3184,6 +3308,9 @@ var ctx_default = (options) => {
|
|
|
3184
3308
|
if (config.useLambdaInternal) {
|
|
3185
3309
|
useLambdaInternal = true;
|
|
3186
3310
|
}
|
|
3311
|
+
if (config.useRemoteDiscovery) {
|
|
3312
|
+
useRemoteDiscovery = true;
|
|
3313
|
+
}
|
|
3187
3314
|
if (config.useExtendedViewport) {
|
|
3188
3315
|
useExtendedViewport = true;
|
|
3189
3316
|
}
|
|
@@ -3219,6 +3346,7 @@ var ctx_default = (options) => {
|
|
|
3219
3346
|
requestHeaders: config.requestHeaders || {},
|
|
3220
3347
|
allowDuplicateSnapshotNames,
|
|
3221
3348
|
useLambdaInternal,
|
|
3349
|
+
useRemoteDiscovery,
|
|
3222
3350
|
useExtendedViewport,
|
|
3223
3351
|
loadDomContent,
|
|
3224
3352
|
approvalThreshold: config.approvalThreshold,
|
|
@@ -3268,6 +3396,7 @@ var ctx_default = (options) => {
|
|
|
3268
3396
|
isSnapshotCaptured: false,
|
|
3269
3397
|
sessionCapabilitiesMap: /* @__PURE__ */ new Map(),
|
|
3270
3398
|
buildToSnapshotCountMap: /* @__PURE__ */ new Map(),
|
|
3399
|
+
sessionIdToSnapshotNameMap: /* @__PURE__ */ new Map(),
|
|
3271
3400
|
fetchResultsForBuild: new Array(),
|
|
3272
3401
|
orgId: 0,
|
|
3273
3402
|
userId: 0,
|
|
@@ -3425,7 +3554,7 @@ var createBuildExec_default = (ctx) => {
|
|
|
3425
3554
|
}
|
|
3426
3555
|
task.output = chalk__default.default.gray(`build id: ${resp.data.buildId}`);
|
|
3427
3556
|
task.title = "SmartUI build created";
|
|
3428
|
-
if (ctx2.env.USE_REMOTE_DISCOVERY) {
|
|
3557
|
+
if (ctx2.env.USE_REMOTE_DISCOVERY || ctx2.config.useRemoteDiscovery) {
|
|
3429
3558
|
task.output += chalk__default.default.gray(`
|
|
3430
3559
|
Using remote discovery for this build`);
|
|
3431
3560
|
}
|
|
@@ -3887,6 +4016,39 @@ function processSnapshot(snapshot, ctx) {
|
|
|
3887
4016
|
ctx.log.debug("No valid cookies to add");
|
|
3888
4017
|
}
|
|
3889
4018
|
}
|
|
4019
|
+
let options = snapshot.options;
|
|
4020
|
+
if ((options == null ? void 0 : options.customCookies) && Array.isArray(options.customCookies) && options.customCookies.length > 0) {
|
|
4021
|
+
ctx.log.debug(`Setting ${options.customCookies.length} custom cookies`);
|
|
4022
|
+
const validCustomCookies = options.customCookies.filter((cookie) => {
|
|
4023
|
+
if (!cookie.name || !cookie.value || !cookie.domain) {
|
|
4024
|
+
ctx.log.debug(`Skipping invalid custom cookie: missing required fields (name, value, or domain)`);
|
|
4025
|
+
return false;
|
|
4026
|
+
}
|
|
4027
|
+
if (cookie.sameSite && !["Strict", "Lax", "None"].includes(cookie.sameSite)) {
|
|
4028
|
+
ctx.log.debug(`Skipping invalid custom cookie: invalid sameSite value '${cookie.sameSite}'`);
|
|
4029
|
+
return false;
|
|
4030
|
+
}
|
|
4031
|
+
return true;
|
|
4032
|
+
}).map((cookie) => ({
|
|
4033
|
+
name: cookie.name,
|
|
4034
|
+
value: cookie.value,
|
|
4035
|
+
domain: cookie.domain,
|
|
4036
|
+
path: cookie.path || "/",
|
|
4037
|
+
httpOnly: cookie.httpOnly || false,
|
|
4038
|
+
secure: cookie.secure || false,
|
|
4039
|
+
sameSite: cookie.sameSite || "Lax"
|
|
4040
|
+
}));
|
|
4041
|
+
if (validCustomCookies.length > 0) {
|
|
4042
|
+
try {
|
|
4043
|
+
yield context.addCookies(validCustomCookies);
|
|
4044
|
+
ctx.log.debug(`Successfully added ${validCustomCookies.length} custom cookies`);
|
|
4045
|
+
} catch (error) {
|
|
4046
|
+
ctx.log.debug(`Failed to add custom cookies: ${error}`);
|
|
4047
|
+
}
|
|
4048
|
+
} else {
|
|
4049
|
+
ctx.log.debug("No valid custom cookies to add");
|
|
4050
|
+
}
|
|
4051
|
+
}
|
|
3890
4052
|
const page = yield context.newPage();
|
|
3891
4053
|
let cache = {};
|
|
3892
4054
|
if (snapshot.dom.resources.length) {
|
|
@@ -4042,7 +4204,6 @@ function processSnapshot(snapshot, ctx) {
|
|
|
4042
4204
|
route.abort();
|
|
4043
4205
|
}
|
|
4044
4206
|
}));
|
|
4045
|
-
let options = snapshot.options;
|
|
4046
4207
|
let optionWarnings = /* @__PURE__ */ new Set();
|
|
4047
4208
|
let selectors = [];
|
|
4048
4209
|
let ignoreOrSelectDOM;
|
|
@@ -4118,13 +4279,13 @@ function processSnapshot(snapshot, ctx) {
|
|
|
4118
4279
|
for (const [key, value] of Object.entries(options[ignoreOrSelectDOM])) {
|
|
4119
4280
|
switch (key) {
|
|
4120
4281
|
case "id":
|
|
4121
|
-
selectors.push(...value.map((e) => "#" + e));
|
|
4282
|
+
selectors.push(...value.map((e) => e.startsWith("#") ? e : "#" + e));
|
|
4122
4283
|
break;
|
|
4123
4284
|
case "class":
|
|
4124
|
-
selectors.push(...value.map((e) => "." + e));
|
|
4285
|
+
selectors.push(...value.map((e) => e.startsWith(".") ? e : "." + e));
|
|
4125
4286
|
break;
|
|
4126
4287
|
case "xpath":
|
|
4127
|
-
selectors.push(...value.map((e) => "xpath=" + e));
|
|
4288
|
+
selectors.push(...value.map((e) => e.startsWith("xpath=") ? e : "xpath=" + e));
|
|
4128
4289
|
break;
|
|
4129
4290
|
case "cssSelector":
|
|
4130
4291
|
selectors.push(...value);
|
|
@@ -4182,6 +4343,9 @@ function processSnapshot(snapshot, ctx) {
|
|
|
4182
4343
|
yield new Promise((r) => setTimeout(r, 1250));
|
|
4183
4344
|
if (ctx.config.waitForTimeout)
|
|
4184
4345
|
yield page.waitForTimeout(ctx.config.waitForTimeout);
|
|
4346
|
+
yield page.waitForLoadState("networkidle", { timeout: 1e4 }).catch(() => {
|
|
4347
|
+
ctx.log.debug("networkidle event failed to fire within 10s");
|
|
4348
|
+
});
|
|
4185
4349
|
navigated = true;
|
|
4186
4350
|
ctx.log.debug(`Navigated to ${snapshot.url}`);
|
|
4187
4351
|
} catch (error) {
|
|
@@ -4239,14 +4403,7 @@ function processSnapshot(snapshot, ctx) {
|
|
|
4239
4403
|
}
|
|
4240
4404
|
}
|
|
4241
4405
|
}
|
|
4242
|
-
if (
|
|
4243
|
-
let l = yield page.locator(processedOptions.element).all();
|
|
4244
|
-
if (l.length === 0) {
|
|
4245
|
-
throw new Error(`for snapshot ${snapshot.name} viewport ${viewportString}, no element found for selector ${processedOptions.element}`);
|
|
4246
|
-
} else if (l.length > 1) {
|
|
4247
|
-
throw new Error(`for snapshot ${snapshot.name} viewport ${viewportString}, multiple elements found for selector ${processedOptions.element}`);
|
|
4248
|
-
}
|
|
4249
|
-
} else if (selectors.length) {
|
|
4406
|
+
if (selectors.length) {
|
|
4250
4407
|
let height = 0;
|
|
4251
4408
|
height = yield page.evaluate(() => {
|
|
4252
4409
|
const DEFAULT_HEIGHT = 16384;
|
|
@@ -4271,7 +4428,6 @@ function processSnapshot(snapshot, ctx) {
|
|
|
4271
4428
|
return Math.max(...measurements);
|
|
4272
4429
|
});
|
|
4273
4430
|
ctx.log.debug(`Calculated content height: ${height}`);
|
|
4274
|
-
let locators = [];
|
|
4275
4431
|
if (!Array.isArray(processedOptions[ignoreOrSelectBoxes][viewportString]))
|
|
4276
4432
|
processedOptions[ignoreOrSelectBoxes][viewportString] = [];
|
|
4277
4433
|
for (const selector of selectors) {
|
|
@@ -4294,44 +4450,75 @@ function processSnapshot(snapshot, ctx) {
|
|
|
4294
4450
|
if (renderViewports.length > 1) {
|
|
4295
4451
|
optionWarnings.add(`for snapshot ${snapshot.name} viewport ${viewportString}, coordinates may not be accurate for multiple viewports`);
|
|
4296
4452
|
}
|
|
4297
|
-
|
|
4453
|
+
__spreadValues({
|
|
4298
4454
|
type: "coordinates"
|
|
4299
4455
|
}, validation.coords);
|
|
4300
|
-
locators.push(coordinateElement);
|
|
4301
|
-
continue;
|
|
4302
|
-
}
|
|
4303
|
-
let l = yield page.locator(selector).all();
|
|
4304
|
-
if (l.length === 0) {
|
|
4305
|
-
optionWarnings.add(`for snapshot ${snapshot.name} viewport ${viewportString}, no element found for selector ${selector}`);
|
|
4306
4456
|
continue;
|
|
4307
|
-
}
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4457
|
+
} else {
|
|
4458
|
+
const isXPath = selector.startsWith("xpath=");
|
|
4459
|
+
const selectorValue = isXPath ? selector.substring(6) : selector;
|
|
4460
|
+
const boxes = yield page.evaluate(({ selectorValue: selectorValue2, isXPath: isXPath2 }) => {
|
|
4461
|
+
try {
|
|
4462
|
+
const DEFAULT_HEIGHT = 16384;
|
|
4463
|
+
const DEFAULT_WIDTH = 7680;
|
|
4464
|
+
const body = document.body;
|
|
4465
|
+
const html = document.documentElement;
|
|
4466
|
+
let pageHeight;
|
|
4467
|
+
let pageWidth;
|
|
4468
|
+
if (!body || !html) {
|
|
4469
|
+
pageHeight = DEFAULT_HEIGHT;
|
|
4470
|
+
pageWidth = DEFAULT_WIDTH;
|
|
4471
|
+
} else {
|
|
4472
|
+
const measurements = [
|
|
4473
|
+
(body == null ? void 0 : body.scrollHeight) || 0,
|
|
4474
|
+
(body == null ? void 0 : body.offsetHeight) || 0,
|
|
4475
|
+
(html == null ? void 0 : html.clientHeight) || 0,
|
|
4476
|
+
(html == null ? void 0 : html.scrollHeight) || 0,
|
|
4477
|
+
(html == null ? void 0 : html.offsetHeight) || 0
|
|
4478
|
+
];
|
|
4479
|
+
const allMeasurementsInvalid = measurements.every((measurement) => !measurement);
|
|
4480
|
+
if (allMeasurementsInvalid) {
|
|
4481
|
+
pageHeight = DEFAULT_HEIGHT;
|
|
4482
|
+
} else {
|
|
4483
|
+
pageHeight = Math.max(...measurements);
|
|
4484
|
+
}
|
|
4485
|
+
const measurementsWidth = [
|
|
4486
|
+
(body == null ? void 0 : body.scrollWidth) || 0,
|
|
4487
|
+
(body == null ? void 0 : body.offsetWidth) || 0,
|
|
4488
|
+
(html == null ? void 0 : html.clientWidth) || 0,
|
|
4489
|
+
(html == null ? void 0 : html.scrollWidth) || 0,
|
|
4490
|
+
(html == null ? void 0 : html.offsetWidth) || 0
|
|
4491
|
+
];
|
|
4492
|
+
const allMeasurementsInvalidWidth = measurementsWidth.every((measurement) => !measurement);
|
|
4493
|
+
if (allMeasurementsInvalidWidth) {
|
|
4494
|
+
pageWidth = DEFAULT_WIDTH;
|
|
4495
|
+
} else {
|
|
4496
|
+
pageWidth = Math.max(...measurementsWidth);
|
|
4497
|
+
}
|
|
4498
|
+
}
|
|
4499
|
+
let elements = [];
|
|
4500
|
+
if (isXPath2) {
|
|
4501
|
+
const xpathResult = document.evaluate(
|
|
4502
|
+
selectorValue2,
|
|
4503
|
+
document,
|
|
4504
|
+
null,
|
|
4505
|
+
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
|
|
4506
|
+
null
|
|
4507
|
+
);
|
|
4508
|
+
for (let i = 0; i < xpathResult.snapshotLength; i++) {
|
|
4509
|
+
elements.push(xpathResult.snapshotItem(i));
|
|
4510
|
+
}
|
|
4511
|
+
} else {
|
|
4512
|
+
elements = Array.from(document.querySelectorAll(selectorValue2));
|
|
4513
|
+
}
|
|
4514
|
+
return elements;
|
|
4515
|
+
} catch (error) {
|
|
4516
|
+
}
|
|
4517
|
+
}, { selectorValue, isXPath });
|
|
4518
|
+
if (boxes && boxes.length >= 1) {
|
|
4519
|
+
processedOptions[ignoreOrSelectBoxes][viewportString].push(...boxes);
|
|
4333
4520
|
} else {
|
|
4334
|
-
|
|
4521
|
+
optionWarnings.add(`for snapshot ${snapshot.name} viewport ${viewportString}, no element found for selector ${selector}`);
|
|
4335
4522
|
}
|
|
4336
4523
|
}
|
|
4337
4524
|
}
|
|
@@ -4616,8 +4803,24 @@ var Queue = class {
|
|
|
4616
4803
|
this.ctx.log.info(`Processing Snapshot: ${snapshot == null ? void 0 : snapshot.name}`);
|
|
4617
4804
|
}
|
|
4618
4805
|
if (!this.ctx.config.delayedUpload && snapshot && snapshot.name && this.snapshotNames.includes(snapshot.name) && !this.ctx.config.allowDuplicateSnapshotNames) {
|
|
4619
|
-
|
|
4620
|
-
|
|
4806
|
+
if (this.ctx.sessionIdToSnapshotNameMap && snapshot.options && snapshot.options.sessionId) {
|
|
4807
|
+
if (this.ctx.sessionIdToSnapshotNameMap.has(snapshot.options.sessionId)) {
|
|
4808
|
+
console.log(`snapshot.options.sessionId`, snapshot.options.sessionId, `this.ctx.sessionIdToSnapshotNameMap`, JSON.stringify([...this.ctx.sessionIdToSnapshotNameMap]));
|
|
4809
|
+
const existingNames = this.ctx.sessionIdToSnapshotNameMap.get(snapshot.options.sessionId) || [];
|
|
4810
|
+
if (existingNames.includes(snapshot.name)) {
|
|
4811
|
+
drop = true;
|
|
4812
|
+
this.ctx.log.info(`Skipping123 duplicate SmartUI snapshot '${snapshot.name}'. To capture duplicate screenshots, please set the 'allowDuplicateSnapshotNames' or 'delayedUpload' configuration as true in your config file.`);
|
|
4813
|
+
} else {
|
|
4814
|
+
existingNames.push(snapshot.name);
|
|
4815
|
+
this.ctx.sessionIdToSnapshotNameMap.set(snapshot.options.sessionId, existingNames);
|
|
4816
|
+
}
|
|
4817
|
+
} else {
|
|
4818
|
+
this.ctx.sessionIdToSnapshotNameMap.set(snapshot.options.sessionId, [snapshot.name]);
|
|
4819
|
+
}
|
|
4820
|
+
} else {
|
|
4821
|
+
drop = true;
|
|
4822
|
+
this.ctx.log.info(`Skipping duplicate SmartUI snapshot '${snapshot.name}'. To capture duplicate screenshots, please set the 'allowDuplicateSnapshotNames' or 'delayedUpload' configuration as true in your config file.`);
|
|
4823
|
+
}
|
|
4621
4824
|
}
|
|
4622
4825
|
if (this.ctx.config.delayedUpload && snapshot && snapshot.name && this.snapshotNames.includes(snapshot.name)) {
|
|
4623
4826
|
drop = this.filterExistingVariants(snapshot, this.ctx.config);
|
|
@@ -4644,7 +4847,7 @@ var Queue = class {
|
|
|
4644
4847
|
}
|
|
4645
4848
|
}
|
|
4646
4849
|
let processedSnapshot, warnings, discoveryErrors;
|
|
4647
|
-
if (this.ctx.env.USE_REMOTE_DISCOVERY) {
|
|
4850
|
+
if (this.ctx.env.USE_REMOTE_DISCOVERY || this.ctx.config.useRemoteDiscovery) {
|
|
4648
4851
|
this.ctx.log.debug(`Using remote discovery`);
|
|
4649
4852
|
let result = yield prepareSnapshot(snapshot, this.ctx);
|
|
4650
4853
|
processedSnapshot = result.processedSnapshot;
|
|
@@ -6441,7 +6644,7 @@ function uploadPdfs(ctx, pdfPath) {
|
|
|
6441
6644
|
|
|
6442
6645
|
// src/commander/uploadPdf.ts
|
|
6443
6646
|
var command10 = new commander.Command();
|
|
6444
|
-
command10.name("upload-pdf").description("Upload PDFs for visual comparison").argument("<directory>", "Path of the directory containing PDFs").option("--fetch-results [filename]", "Fetch results and optionally specify an output file, e.g., <filename>.json").option("--buildName <string>", "Specify the build name").action(function(directory, _, command11) {
|
|
6647
|
+
command10.name("upload-pdf").description("Upload PDFs for visual comparison").argument("<directory>", "Path of the directory containing PDFs").option("--fetch-results [filename]", "Fetch results and optionally specify an output file, e.g., <filename>.json").option("--buildName <string>", "Specify the build name").option("--markBaseline", "Mark this build baseline").action(function(directory, _, command11) {
|
|
6445
6648
|
return __async(this, null, function* () {
|
|
6446
6649
|
const options = command11.optsWithGlobals();
|
|
6447
6650
|
if (options.buildName === "") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lambdatest/smartui-cli",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.35",
|
|
4
4
|
"description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/**/*"
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"simple-swizzle": "0.2.2"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
+
"find-free-port": "^2.0.0",
|
|
50
51
|
"typescript": "^5.3.2"
|
|
51
52
|
},
|
|
52
53
|
"scripts": {
|