@lambdatest/smartui-cli 4.0.20 → 4.0.22
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 +688 -484
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4,32 +4,35 @@
|
|
|
4
4
|
var commander = require('commander');
|
|
5
5
|
var which = require('which');
|
|
6
6
|
var listr2 = require('listr2');
|
|
7
|
-
var
|
|
7
|
+
var chalk = require('chalk');
|
|
8
8
|
var path2 = require('path');
|
|
9
9
|
var fastify = require('fastify');
|
|
10
|
-
var
|
|
10
|
+
var fs6 = require('fs');
|
|
11
11
|
var Ajv = require('ajv');
|
|
12
12
|
var addErrors = require('ajv-errors');
|
|
13
|
+
var test = require('@playwright/test');
|
|
14
|
+
var util = require('util');
|
|
13
15
|
var winston = require('winston');
|
|
14
16
|
var FormData = require('form-data');
|
|
15
17
|
var axios = require('axios');
|
|
18
|
+
var https = require('https');
|
|
16
19
|
var child_process = require('child_process');
|
|
17
20
|
var spawn = require('cross-spawn');
|
|
18
|
-
var test = require('@playwright/test');
|
|
19
21
|
var uuid = require('uuid');
|
|
20
22
|
var sharp = require('sharp');
|
|
21
23
|
|
|
22
24
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
23
25
|
|
|
24
26
|
var which__default = /*#__PURE__*/_interopDefault(which);
|
|
25
|
-
var
|
|
27
|
+
var chalk__default = /*#__PURE__*/_interopDefault(chalk);
|
|
26
28
|
var path2__default = /*#__PURE__*/_interopDefault(path2);
|
|
27
29
|
var fastify__default = /*#__PURE__*/_interopDefault(fastify);
|
|
28
|
-
var
|
|
30
|
+
var fs6__default = /*#__PURE__*/_interopDefault(fs6);
|
|
29
31
|
var Ajv__default = /*#__PURE__*/_interopDefault(Ajv);
|
|
30
32
|
var addErrors__default = /*#__PURE__*/_interopDefault(addErrors);
|
|
31
33
|
var FormData__default = /*#__PURE__*/_interopDefault(FormData);
|
|
32
34
|
var axios__default = /*#__PURE__*/_interopDefault(axios);
|
|
35
|
+
var https__default = /*#__PURE__*/_interopDefault(https);
|
|
33
36
|
var spawn__default = /*#__PURE__*/_interopDefault(spawn);
|
|
34
37
|
var sharp__default = /*#__PURE__*/_interopDefault(sharp);
|
|
35
38
|
|
|
@@ -961,9 +964,285 @@ var validateWebStaticConfig = ajv.compile(WebStaticConfigSchema);
|
|
|
961
964
|
var validateSnapshot = ajv.compile(SnapshotSchema);
|
|
962
965
|
var validateFigmaDesignConfig = ajv.compile(FigmaDesignConfigSchema);
|
|
963
966
|
var validateWebFigmaConfig = ajv.compile(FigmaWebConfigSchema);
|
|
967
|
+
util.promisify(setTimeout);
|
|
968
|
+
var isPollingActive = false;
|
|
969
|
+
function delDir(dir) {
|
|
970
|
+
if (fs6__default.default.existsSync(dir)) {
|
|
971
|
+
fs6__default.default.rmSync(dir, { recursive: true });
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
function scrollToBottomAndBackToTop({
|
|
975
|
+
frequency = 100,
|
|
976
|
+
timing = 8,
|
|
977
|
+
remoteWindow = window
|
|
978
|
+
} = {}) {
|
|
979
|
+
return new Promise((resolve) => {
|
|
980
|
+
let scrolls = 1;
|
|
981
|
+
let scrollLength = remoteWindow.document.body.scrollHeight / frequency;
|
|
982
|
+
(function scroll() {
|
|
983
|
+
let scrollBy = scrollLength * scrolls;
|
|
984
|
+
remoteWindow.setTimeout(() => {
|
|
985
|
+
remoteWindow.scrollTo(0, scrollBy);
|
|
986
|
+
if (scrolls < frequency) {
|
|
987
|
+
scrolls += 1;
|
|
988
|
+
scroll();
|
|
989
|
+
}
|
|
990
|
+
if (scrolls === frequency) {
|
|
991
|
+
remoteWindow.setTimeout(() => {
|
|
992
|
+
remoteWindow.scrollTo(0, 0);
|
|
993
|
+
resolve();
|
|
994
|
+
}, timing);
|
|
995
|
+
}
|
|
996
|
+
}, timing);
|
|
997
|
+
})();
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
function launchBrowsers(ctx) {
|
|
1001
|
+
return __async(this, null, function* () {
|
|
1002
|
+
var _a;
|
|
1003
|
+
let browsers = {};
|
|
1004
|
+
const isHeadless = ((_a = process.env.HEADLESS) == null ? void 0 : _a.toLowerCase()) === "false" ? false : true;
|
|
1005
|
+
let launchOptions = { headless: isHeadless };
|
|
1006
|
+
if (ctx.config.web) {
|
|
1007
|
+
for (const browser of ctx.config.web.browsers) {
|
|
1008
|
+
switch (browser) {
|
|
1009
|
+
case constants_default.CHROME:
|
|
1010
|
+
browsers[constants_default.CHROME] = yield test.chromium.launch(launchOptions);
|
|
1011
|
+
break;
|
|
1012
|
+
case constants_default.SAFARI:
|
|
1013
|
+
browsers[constants_default.SAFARI] = yield test.webkit.launch(launchOptions);
|
|
1014
|
+
break;
|
|
1015
|
+
case constants_default.FIREFOX:
|
|
1016
|
+
browsers[constants_default.FIREFOX] = yield test.firefox.launch(launchOptions);
|
|
1017
|
+
break;
|
|
1018
|
+
case constants_default.EDGE:
|
|
1019
|
+
launchOptions.args = ["--headless=new"];
|
|
1020
|
+
browsers[constants_default.EDGE] = yield test.chromium.launch(__spreadValues({ channel: constants_default.EDGE_CHANNEL }, launchOptions));
|
|
1021
|
+
break;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
if (ctx.config.mobile) {
|
|
1026
|
+
for (const device of ctx.config.mobile.devices) {
|
|
1027
|
+
if (constants_default.SUPPORTED_MOBILE_DEVICES[device].os === "android" && !browsers[constants_default.CHROME])
|
|
1028
|
+
browsers[constants_default.CHROME] = yield test.chromium.launch(launchOptions);
|
|
1029
|
+
else if (constants_default.SUPPORTED_MOBILE_DEVICES[device].os === "ios" && !browsers[constants_default.SAFARI])
|
|
1030
|
+
browsers[constants_default.SAFARI] = yield test.webkit.launch(launchOptions);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
return browsers;
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
function closeBrowsers(browsers) {
|
|
1037
|
+
return __async(this, null, function* () {
|
|
1038
|
+
var _a;
|
|
1039
|
+
for (const browserName of Object.keys(browsers))
|
|
1040
|
+
yield (_a = browsers[browserName]) == null ? void 0 : _a.close();
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
function getWebRenderViewports(ctx) {
|
|
1044
|
+
let webRenderViewports = [];
|
|
1045
|
+
if (ctx.config.web) {
|
|
1046
|
+
for (const viewport of ctx.config.web.viewports) {
|
|
1047
|
+
webRenderViewports.push({
|
|
1048
|
+
viewport,
|
|
1049
|
+
viewportString: `${viewport.width}${viewport.height ? "x" + viewport.height : ""}`,
|
|
1050
|
+
fullPage: viewport.height ? false : true,
|
|
1051
|
+
device: false
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
return webRenderViewports;
|
|
1056
|
+
}
|
|
1057
|
+
function getWebRenderViewportsForOptions(options) {
|
|
1058
|
+
let webRenderViewports = [];
|
|
1059
|
+
if (options.web && Array.isArray(options.web.viewports)) {
|
|
1060
|
+
for (const viewport of options.web.viewports) {
|
|
1061
|
+
if (Array.isArray(viewport) && viewport.length > 0) {
|
|
1062
|
+
let viewportObj = {
|
|
1063
|
+
width: viewport[0]
|
|
1064
|
+
};
|
|
1065
|
+
if (viewport.length > 1) {
|
|
1066
|
+
viewportObj.height = viewport[1];
|
|
1067
|
+
}
|
|
1068
|
+
webRenderViewports.push({
|
|
1069
|
+
viewport: viewportObj,
|
|
1070
|
+
viewportString: `${viewport[0]}${viewport[1] ? "x" + viewport[1] : ""}`,
|
|
1071
|
+
fullPage: viewport.length === 1,
|
|
1072
|
+
device: false
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
return webRenderViewports;
|
|
1078
|
+
}
|
|
1079
|
+
function getMobileRenderViewports(ctx) {
|
|
1080
|
+
var _a;
|
|
1081
|
+
let mobileRenderViewports = {};
|
|
1082
|
+
mobileRenderViewports[constants_default.MOBILE_OS_IOS] = [];
|
|
1083
|
+
mobileRenderViewports[constants_default.MOBILE_OS_ANDROID] = [];
|
|
1084
|
+
if (ctx.config.mobile) {
|
|
1085
|
+
for (const device of ctx.config.mobile.devices) {
|
|
1086
|
+
let os = constants_default.SUPPORTED_MOBILE_DEVICES[device].os;
|
|
1087
|
+
let { width, height } = constants_default.SUPPORTED_MOBILE_DEVICES[device].viewport;
|
|
1088
|
+
let portrait = ctx.config.mobile.orientation === constants_default.MOBILE_ORIENTATION_PORTRAIT ? true : false;
|
|
1089
|
+
(_a = mobileRenderViewports[os]) == null ? void 0 : _a.push({
|
|
1090
|
+
viewport: { width: portrait ? width : height, height: portrait ? height : width },
|
|
1091
|
+
viewportString: `${device} (${ctx.config.mobile.orientation})`,
|
|
1092
|
+
fullPage: ctx.config.mobile.fullPage,
|
|
1093
|
+
device: true,
|
|
1094
|
+
os
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
return mobileRenderViewports;
|
|
1099
|
+
}
|
|
1100
|
+
function getMobileRenderViewportsForOptions(options) {
|
|
1101
|
+
var _a;
|
|
1102
|
+
let mobileRenderViewports = {};
|
|
1103
|
+
mobileRenderViewports[constants_default.MOBILE_OS_IOS] = [];
|
|
1104
|
+
mobileRenderViewports[constants_default.MOBILE_OS_ANDROID] = [];
|
|
1105
|
+
if (options.mobile) {
|
|
1106
|
+
for (const device of options.mobile.devices) {
|
|
1107
|
+
let os = constants_default.SUPPORTED_MOBILE_DEVICES[device].os;
|
|
1108
|
+
let { width, height } = constants_default.SUPPORTED_MOBILE_DEVICES[device].viewport;
|
|
1109
|
+
let orientation = options.mobile.orientation || constants_default.MOBILE_ORIENTATION_PORTRAIT;
|
|
1110
|
+
let portrait = orientation === constants_default.MOBILE_ORIENTATION_PORTRAIT;
|
|
1111
|
+
let fullPage;
|
|
1112
|
+
if (options.mobile.fullPage === void 0 || options.mobile.fullPage) {
|
|
1113
|
+
fullPage = true;
|
|
1114
|
+
} else {
|
|
1115
|
+
fullPage = false;
|
|
1116
|
+
}
|
|
1117
|
+
(_a = mobileRenderViewports[os]) == null ? void 0 : _a.push({
|
|
1118
|
+
viewport: { width: portrait ? width : height, height: portrait ? height : width },
|
|
1119
|
+
viewportString: `${device} (${orientation})`,
|
|
1120
|
+
fullPage,
|
|
1121
|
+
device: true,
|
|
1122
|
+
os
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
return mobileRenderViewports;
|
|
1127
|
+
}
|
|
1128
|
+
function getRenderViewports(ctx) {
|
|
1129
|
+
let mobileRenderViewports = getMobileRenderViewports(ctx);
|
|
1130
|
+
let webRenderViewports = getWebRenderViewports(ctx);
|
|
1131
|
+
return [
|
|
1132
|
+
...webRenderViewports,
|
|
1133
|
+
...mobileRenderViewports[constants_default.MOBILE_OS_IOS],
|
|
1134
|
+
...mobileRenderViewports[constants_default.MOBILE_OS_ANDROID]
|
|
1135
|
+
];
|
|
1136
|
+
}
|
|
1137
|
+
function getRenderViewportsForOptions(options) {
|
|
1138
|
+
let mobileRenderViewports = getMobileRenderViewportsForOptions(options);
|
|
1139
|
+
let webRenderViewports = getWebRenderViewportsForOptions(options);
|
|
1140
|
+
return [
|
|
1141
|
+
...webRenderViewports,
|
|
1142
|
+
...mobileRenderViewports[constants_default.MOBILE_OS_IOS],
|
|
1143
|
+
...mobileRenderViewports[constants_default.MOBILE_OS_ANDROID]
|
|
1144
|
+
];
|
|
1145
|
+
}
|
|
1146
|
+
process.on("SIGINT", () => __async(void 0, null, function* () {
|
|
1147
|
+
if (isPollingActive) {
|
|
1148
|
+
console.log("Fetching results interrupted. Exiting...");
|
|
1149
|
+
isPollingActive = false;
|
|
1150
|
+
} else {
|
|
1151
|
+
console.log("\nExiting gracefully...");
|
|
1152
|
+
}
|
|
1153
|
+
process.exit(0);
|
|
1154
|
+
}));
|
|
1155
|
+
function startPolling(ctx) {
|
|
1156
|
+
return __async(this, null, function* () {
|
|
1157
|
+
ctx.log.info("Fetching results in progress....");
|
|
1158
|
+
isPollingActive = true;
|
|
1159
|
+
const intervalId = setInterval(() => __async(this, null, function* () {
|
|
1160
|
+
if (!isPollingActive) {
|
|
1161
|
+
clearInterval(intervalId);
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
try {
|
|
1165
|
+
const resp = yield ctx.client.getScreenshotData(ctx.build.id, ctx.build.baseline, ctx.log);
|
|
1166
|
+
if (!resp.build) {
|
|
1167
|
+
ctx.log.info("Error: Build data is null.");
|
|
1168
|
+
clearInterval(intervalId);
|
|
1169
|
+
isPollingActive = false;
|
|
1170
|
+
}
|
|
1171
|
+
fs6__default.default.writeFileSync(ctx.options.fetchResultsFileName, JSON.stringify(resp, null, 2));
|
|
1172
|
+
ctx.log.debug(`Updated results in ${ctx.options.fetchResultsFileName}`);
|
|
1173
|
+
if (resp.build.build_status_ind === constants_default.BUILD_COMPLETE || resp.build.build_status_ind === constants_default.BUILD_ERROR) {
|
|
1174
|
+
clearInterval(intervalId);
|
|
1175
|
+
ctx.log.info(`Fetching results completed. Final results written to ${ctx.options.fetchResultsFileName}`);
|
|
1176
|
+
isPollingActive = false;
|
|
1177
|
+
let totalScreenshotsWithMismatches = 0;
|
|
1178
|
+
let totalVariantsWithMismatches = 0;
|
|
1179
|
+
const totalScreenshots = Object.keys(resp.screenshots || {}).length;
|
|
1180
|
+
let totalVariants = 0;
|
|
1181
|
+
for (const [screenshot, variants] of Object.entries(resp.screenshots || {})) {
|
|
1182
|
+
let screenshotHasMismatch = false;
|
|
1183
|
+
let variantMismatchCount = 0;
|
|
1184
|
+
totalVariants += variants.length;
|
|
1185
|
+
for (const variant of variants) {
|
|
1186
|
+
if (variant.mismatch_percentage > 0) {
|
|
1187
|
+
screenshotHasMismatch = true;
|
|
1188
|
+
variantMismatchCount++;
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
if (screenshotHasMismatch) {
|
|
1192
|
+
totalScreenshotsWithMismatches++;
|
|
1193
|
+
totalVariantsWithMismatches += variantMismatchCount;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
ctx.log.info(
|
|
1197
|
+
chalk__default.default.green.bold(
|
|
1198
|
+
`
|
|
1199
|
+
Summary of Mismatches:
|
|
1200
|
+
${chalk__default.default.yellow("Total Variants with Mismatches:")} ${chalk__default.default.white(totalVariantsWithMismatches)} out of ${chalk__default.default.white(totalVariants)}
|
|
1201
|
+
${chalk__default.default.yellow("Total Screenshots with Mismatches:")} ${chalk__default.default.white(totalScreenshotsWithMismatches)} out of ${chalk__default.default.white(totalScreenshots)}
|
|
1202
|
+
${chalk__default.default.yellow("Branch Name:")} ${chalk__default.default.white(resp.build.branch)}
|
|
1203
|
+
${chalk__default.default.yellow("Project Name:")} ${chalk__default.default.white(resp.project.name)}
|
|
1204
|
+
${chalk__default.default.yellow("Build ID:")} ${chalk__default.default.white(resp.build.build_id)}
|
|
1205
|
+
`
|
|
1206
|
+
)
|
|
1207
|
+
);
|
|
1208
|
+
}
|
|
1209
|
+
} catch (error) {
|
|
1210
|
+
if (error.message.includes("ENOTFOUND")) {
|
|
1211
|
+
ctx.log.error("Error: Network error occurred while fetching build results. Please check your connection and try again.");
|
|
1212
|
+
clearInterval(intervalId);
|
|
1213
|
+
} else {
|
|
1214
|
+
ctx.log.error(`Error fetching screenshot data: ${error.message}`);
|
|
1215
|
+
}
|
|
1216
|
+
clearInterval(intervalId);
|
|
1217
|
+
isPollingActive = false;
|
|
1218
|
+
}
|
|
1219
|
+
}), 5e3);
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
var pingIntervalId = null;
|
|
1223
|
+
function startPingPolling(ctx) {
|
|
1224
|
+
return __async(this, null, function* () {
|
|
1225
|
+
try {
|
|
1226
|
+
ctx.log.debug("Sending initial ping to server...");
|
|
1227
|
+
yield ctx.client.ping(ctx.build.id, ctx.log);
|
|
1228
|
+
ctx.log.debug("Initial ping sent successfully.");
|
|
1229
|
+
} catch (error) {
|
|
1230
|
+
ctx.log.error(`Error during initial ping: ${error.message}`);
|
|
1231
|
+
}
|
|
1232
|
+
pingIntervalId = setInterval(() => __async(this, null, function* () {
|
|
1233
|
+
try {
|
|
1234
|
+
ctx.log.debug("Sending ping to server...");
|
|
1235
|
+
yield ctx.client.ping(ctx.build.id, ctx.log);
|
|
1236
|
+
ctx.log.debug("Ping sent successfully.");
|
|
1237
|
+
} catch (error) {
|
|
1238
|
+
ctx.log.error(`Error during ping polling: ${error.message}`);
|
|
1239
|
+
}
|
|
1240
|
+
}), 10 * 60 * 1e3);
|
|
1241
|
+
});
|
|
1242
|
+
}
|
|
964
1243
|
|
|
965
1244
|
// src/lib/server.ts
|
|
966
|
-
var server_default = (ctx) => __async(
|
|
1245
|
+
var server_default = (ctx) => __async(void 0, null, function* () {
|
|
967
1246
|
const server = fastify__default.default({
|
|
968
1247
|
logger: {
|
|
969
1248
|
level: "debug",
|
|
@@ -974,14 +1253,14 @@ var server_default = (ctx) => __async(undefined, null, function* () {
|
|
|
974
1253
|
bodyLimit: 3e7
|
|
975
1254
|
});
|
|
976
1255
|
const opts = {};
|
|
977
|
-
const SMARTUI_DOM =
|
|
1256
|
+
const SMARTUI_DOM = fs6.readFileSync(path2__default.default.resolve(__dirname, "dom-serializer.js"), "utf-8");
|
|
978
1257
|
server.get("/healthcheck", opts, (_, reply) => {
|
|
979
1258
|
reply.code(200).send({ cliVersion: ctx.cliVersion });
|
|
980
1259
|
});
|
|
981
1260
|
server.get("/domserializer", opts, (request, reply) => {
|
|
982
1261
|
reply.code(200).send({ data: { dom: SMARTUI_DOM } });
|
|
983
1262
|
});
|
|
984
|
-
server.post("/snapshot", opts, (request, reply) => __async(
|
|
1263
|
+
server.post("/snapshot", opts, (request, reply) => __async(void 0, null, function* () {
|
|
985
1264
|
var _a;
|
|
986
1265
|
let replyCode;
|
|
987
1266
|
let replyBody;
|
|
@@ -1000,6 +1279,48 @@ var server_default = (ctx) => __async(undefined, null, function* () {
|
|
|
1000
1279
|
}
|
|
1001
1280
|
return reply.code(replyCode).send(replyBody);
|
|
1002
1281
|
}));
|
|
1282
|
+
server.post("/stop", opts, (_, reply) => __async(void 0, null, function* () {
|
|
1283
|
+
var _a, _b;
|
|
1284
|
+
let replyCode;
|
|
1285
|
+
let replyBody;
|
|
1286
|
+
try {
|
|
1287
|
+
if (ctx.config.delayedUpload) {
|
|
1288
|
+
ctx.log.debug("started after processing because of delayedUpload");
|
|
1289
|
+
(_a = ctx.snapshotQueue) == null ? void 0 : _a.startProcessingfunc();
|
|
1290
|
+
}
|
|
1291
|
+
yield new Promise((resolve) => {
|
|
1292
|
+
const intervalId = setInterval(() => {
|
|
1293
|
+
var _a2, _b2;
|
|
1294
|
+
if (((_a2 = ctx.snapshotQueue) == null ? void 0 : _a2.isEmpty()) && !((_b2 = ctx.snapshotQueue) == null ? void 0 : _b2.isProcessing())) {
|
|
1295
|
+
clearInterval(intervalId);
|
|
1296
|
+
resolve();
|
|
1297
|
+
}
|
|
1298
|
+
}, 1e3);
|
|
1299
|
+
});
|
|
1300
|
+
yield ctx.client.finalizeBuild(ctx.build.id, ctx.totalSnapshots, ctx.log);
|
|
1301
|
+
yield (_b = ctx.browser) == null ? void 0 : _b.close();
|
|
1302
|
+
if (ctx.server) {
|
|
1303
|
+
ctx.server.close();
|
|
1304
|
+
}
|
|
1305
|
+
let resp = yield ctx.client.getS3PreSignedURL(ctx);
|
|
1306
|
+
yield ctx.client.uploadLogs(ctx, resp.data.url);
|
|
1307
|
+
if (pingIntervalId !== null) {
|
|
1308
|
+
clearInterval(pingIntervalId);
|
|
1309
|
+
ctx.log.debug("Ping polling stopped immediately.");
|
|
1310
|
+
}
|
|
1311
|
+
replyCode = 200;
|
|
1312
|
+
replyBody = { data: { message: "success", type: "DELETE" } };
|
|
1313
|
+
} catch (error) {
|
|
1314
|
+
ctx.log.debug(error);
|
|
1315
|
+
ctx.log.debug(`stop endpoint failed; ${error}`);
|
|
1316
|
+
replyCode = 500;
|
|
1317
|
+
replyBody = { error: { message: error.message } };
|
|
1318
|
+
}
|
|
1319
|
+
return reply.code(replyCode).send(replyBody);
|
|
1320
|
+
}));
|
|
1321
|
+
server.get("/ping", opts, (_, reply) => {
|
|
1322
|
+
reply.code(200).send({ status: "Server is running", version: ctx.cliVersion });
|
|
1323
|
+
});
|
|
1003
1324
|
yield server.listen({ port: ctx.options.port });
|
|
1004
1325
|
let { port } = server.addresses()[0];
|
|
1005
1326
|
process.env.SMARTUI_SERVER_ADDRESS = `http://localhost:${port}`;
|
|
@@ -1025,7 +1346,9 @@ var env_default = () => {
|
|
|
1025
1346
|
LT_SDK_DEBUG,
|
|
1026
1347
|
BASELINE_BRANCH,
|
|
1027
1348
|
CURRENT_BRANCH,
|
|
1028
|
-
PROJECT_NAME
|
|
1349
|
+
PROJECT_NAME,
|
|
1350
|
+
SMARTUI_API_PROXY,
|
|
1351
|
+
SMARTUI_API_SKIP_CERTIFICATES
|
|
1029
1352
|
} = process.env;
|
|
1030
1353
|
return {
|
|
1031
1354
|
PROJECT_TOKEN,
|
|
@@ -1043,7 +1366,9 @@ var env_default = () => {
|
|
|
1043
1366
|
CURRENT_BRANCH,
|
|
1044
1367
|
LT_SDK_DEBUG: LT_SDK_DEBUG === "true",
|
|
1045
1368
|
SMARTUI_DO_NOT_USE_CAPTURED_COOKIES: SMARTUI_DO_NOT_USE_CAPTURED_COOKIES === "true",
|
|
1046
|
-
PROJECT_NAME
|
|
1369
|
+
PROJECT_NAME,
|
|
1370
|
+
SMARTUI_API_PROXY,
|
|
1371
|
+
SMARTUI_API_SKIP_CERTIFICATES: SMARTUI_API_SKIP_CERTIFICATES === "true"
|
|
1047
1372
|
};
|
|
1048
1373
|
};
|
|
1049
1374
|
var logContext = {};
|
|
@@ -1062,7 +1387,7 @@ var logger = winston.createLogger({
|
|
|
1062
1387
|
let message = typeof info.message === "object" ? JSON.stringify(info.message).trim() : info.message.trim();
|
|
1063
1388
|
switch (info.level) {
|
|
1064
1389
|
case "warn":
|
|
1065
|
-
message =
|
|
1390
|
+
message = chalk__default.default.yellow(message);
|
|
1066
1391
|
break;
|
|
1067
1392
|
}
|
|
1068
1393
|
return info.level === "info" ? message : `[${contextString}:${info.level}] ` + message;
|
|
@@ -1084,16 +1409,16 @@ var logger_default = logger;
|
|
|
1084
1409
|
var startServer_default = (ctx) => {
|
|
1085
1410
|
return {
|
|
1086
1411
|
title: `Setting up SmartUI server`,
|
|
1087
|
-
task: (ctx2, task) => __async(
|
|
1412
|
+
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
1088
1413
|
var _a;
|
|
1089
1414
|
updateLogContext({ task: "startServer" });
|
|
1090
1415
|
try {
|
|
1091
1416
|
ctx2.server = yield server_default(ctx2);
|
|
1092
|
-
task.output =
|
|
1417
|
+
task.output = chalk__default.default.gray(`listening on port ${(_a = ctx2.server.addresses()[0]) == null ? void 0 : _a.port}`);
|
|
1093
1418
|
task.title = "SmartUI started";
|
|
1094
1419
|
} catch (error) {
|
|
1095
1420
|
ctx2.log.debug(error);
|
|
1096
|
-
task.output =
|
|
1421
|
+
task.output = chalk__default.default.gray(error.message);
|
|
1097
1422
|
throw new Error("SmartUI server setup failed");
|
|
1098
1423
|
}
|
|
1099
1424
|
}),
|
|
@@ -1103,21 +1428,21 @@ var startServer_default = (ctx) => {
|
|
|
1103
1428
|
var auth_default = (ctx) => {
|
|
1104
1429
|
return {
|
|
1105
1430
|
title: `Authenticating with SmartUI`,
|
|
1106
|
-
task: (ctx2, task) => __async(
|
|
1431
|
+
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
1107
1432
|
updateLogContext({ task: "auth" });
|
|
1108
1433
|
try {
|
|
1109
1434
|
const authResult = yield ctx2.client.auth(ctx2.log, ctx2.env);
|
|
1110
1435
|
if (authResult === 2) {
|
|
1111
|
-
task.output =
|
|
1436
|
+
task.output = chalk__default.default.gray(`New project '${ctx2.env.PROJECT_NAME}' created successfully`);
|
|
1112
1437
|
} else if (authResult === 0) {
|
|
1113
|
-
task.output =
|
|
1438
|
+
task.output = chalk__default.default.gray(`Using existing project token '******#${ctx2.env.PROJECT_TOKEN.split("#").pop()}'`);
|
|
1114
1439
|
} else if (authResult === 1) {
|
|
1115
|
-
task.output =
|
|
1440
|
+
task.output = chalk__default.default.gray(`Using existing project '${ctx2.env.PROJECT_NAME}'`);
|
|
1116
1441
|
}
|
|
1117
1442
|
task.title = "Authenticated with SmartUI";
|
|
1118
1443
|
} catch (error) {
|
|
1119
1444
|
ctx2.log.debug(error);
|
|
1120
|
-
task.output =
|
|
1445
|
+
task.output = chalk__default.default.gray(error.message);
|
|
1121
1446
|
throw new Error("Authentication failed");
|
|
1122
1447
|
}
|
|
1123
1448
|
}),
|
|
@@ -1126,7 +1451,7 @@ var auth_default = (ctx) => {
|
|
|
1126
1451
|
};
|
|
1127
1452
|
|
|
1128
1453
|
// package.json
|
|
1129
|
-
var version = "4.0.
|
|
1454
|
+
var version = "4.0.22";
|
|
1130
1455
|
var package_default = {
|
|
1131
1456
|
name: "@lambdatest/smartui-cli",
|
|
1132
1457
|
version,
|
|
@@ -1178,14 +1503,31 @@ var package_default = {
|
|
|
1178
1503
|
}
|
|
1179
1504
|
};
|
|
1180
1505
|
var httpClient = class {
|
|
1181
|
-
constructor({ SMARTUI_CLIENT_API_URL, PROJECT_TOKEN, PROJECT_NAME, LT_USERNAME, LT_ACCESS_KEY }) {
|
|
1506
|
+
constructor({ SMARTUI_CLIENT_API_URL, PROJECT_TOKEN, PROJECT_NAME, LT_USERNAME, LT_ACCESS_KEY, SMARTUI_API_PROXY, SMARTUI_API_SKIP_CERTIFICATES }) {
|
|
1182
1507
|
this.projectToken = PROJECT_TOKEN || "";
|
|
1183
1508
|
this.projectName = PROJECT_NAME || "";
|
|
1184
1509
|
this.username = LT_USERNAME || "";
|
|
1185
1510
|
this.accessKey = LT_ACCESS_KEY || "";
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1511
|
+
let proxyUrl = null;
|
|
1512
|
+
try {
|
|
1513
|
+
const urlStr = (SMARTUI_API_PROXY == null ? void 0 : SMARTUI_API_PROXY.startsWith("http")) ? SMARTUI_API_PROXY : `http://${SMARTUI_API_PROXY}`;
|
|
1514
|
+
proxyUrl = SMARTUI_API_PROXY ? new URL(urlStr) : null;
|
|
1515
|
+
} catch (error) {
|
|
1516
|
+
console.error("Invalid proxy URL:", error);
|
|
1517
|
+
}
|
|
1518
|
+
const axiosConfig = {
|
|
1519
|
+
baseURL: SMARTUI_CLIENT_API_URL,
|
|
1520
|
+
proxy: proxyUrl ? {
|
|
1521
|
+
host: proxyUrl.hostname,
|
|
1522
|
+
port: proxyUrl.port ? Number(proxyUrl.port) : 80
|
|
1523
|
+
} : false
|
|
1524
|
+
};
|
|
1525
|
+
if (SMARTUI_API_SKIP_CERTIFICATES) {
|
|
1526
|
+
axiosConfig.httpsAgent = new https__default.default.Agent({
|
|
1527
|
+
rejectUnauthorized: false
|
|
1528
|
+
});
|
|
1529
|
+
}
|
|
1530
|
+
this.axiosInstance = axios__default.default.create(axiosConfig);
|
|
1189
1531
|
this.axiosInstance.interceptors.request.use((config) => {
|
|
1190
1532
|
config.headers["projectToken"] = this.projectToken;
|
|
1191
1533
|
config.headers["projectName"] = this.projectName;
|
|
@@ -1197,7 +1539,7 @@ var httpClient = class {
|
|
|
1197
1539
|
request(config, log2) {
|
|
1198
1540
|
return __async(this, null, function* () {
|
|
1199
1541
|
log2.debug(`http request: ${config.method} ${config.url}`);
|
|
1200
|
-
if (config && config.data) {
|
|
1542
|
+
if (config && config.data && !config.data.name) {
|
|
1201
1543
|
log2.debug(config.data);
|
|
1202
1544
|
}
|
|
1203
1545
|
return this.axiosInstance.request(config).then((resp) => {
|
|
@@ -1215,7 +1557,7 @@ var httpClient = class {
|
|
|
1215
1557
|
headers: error.response.headers,
|
|
1216
1558
|
body: error.response.data
|
|
1217
1559
|
})}`);
|
|
1218
|
-
throw new Error(((_a = error.response.data.error) == null ?
|
|
1560
|
+
throw new Error(((_a = error.response.data.error) == null ? void 0 : _a.message) || error.response.data.message || error.response.data);
|
|
1219
1561
|
}
|
|
1220
1562
|
if (error.request) {
|
|
1221
1563
|
log2.debug(`http request failed: ${error.toJSON()}`);
|
|
@@ -1248,14 +1590,15 @@ var httpClient = class {
|
|
|
1248
1590
|
}
|
|
1249
1591
|
});
|
|
1250
1592
|
}
|
|
1251
|
-
createBuild(git, config, log2, buildName) {
|
|
1593
|
+
createBuild(git, config, log2, buildName, isStartExec) {
|
|
1252
1594
|
return this.request({
|
|
1253
1595
|
url: "/build",
|
|
1254
1596
|
method: "POST",
|
|
1255
1597
|
data: {
|
|
1256
1598
|
git,
|
|
1257
1599
|
config,
|
|
1258
|
-
buildName
|
|
1600
|
+
buildName,
|
|
1601
|
+
isStartExec
|
|
1259
1602
|
}
|
|
1260
1603
|
}, log2);
|
|
1261
1604
|
}
|
|
@@ -1266,6 +1609,15 @@ var httpClient = class {
|
|
|
1266
1609
|
params: { buildId, baseline }
|
|
1267
1610
|
}, log2);
|
|
1268
1611
|
}
|
|
1612
|
+
ping(buildId, log2) {
|
|
1613
|
+
return this.request({
|
|
1614
|
+
url: "/build/ping",
|
|
1615
|
+
method: "POST",
|
|
1616
|
+
data: {
|
|
1617
|
+
buildId
|
|
1618
|
+
}
|
|
1619
|
+
}, log2);
|
|
1620
|
+
}
|
|
1269
1621
|
finalizeBuild(buildId, totalSnapshots, log2) {
|
|
1270
1622
|
let params = { buildId };
|
|
1271
1623
|
if (totalSnapshots > -1)
|
|
@@ -1309,7 +1661,7 @@ var httpClient = class {
|
|
|
1309
1661
|
}
|
|
1310
1662
|
uploadScreenshot({ id: buildId, name: buildName, baseline }, ssPath, ssName, browserName, viewport, log2) {
|
|
1311
1663
|
browserName = browserName === constants_default.SAFARI ? constants_default.WEBKIT : browserName;
|
|
1312
|
-
const file =
|
|
1664
|
+
const file = fs6__default.default.readFileSync(ssPath);
|
|
1313
1665
|
const form = new FormData__default.default();
|
|
1314
1666
|
form.append("screenshot", file, { filename: `${ssName}.png`, contentType: "image/png" });
|
|
1315
1667
|
form.append("browser", browserName);
|
|
@@ -1388,8 +1740,8 @@ var httpClient = class {
|
|
|
1388
1740
|
}, ctx.log);
|
|
1389
1741
|
}
|
|
1390
1742
|
uploadLogs(ctx, uploadURL) {
|
|
1391
|
-
const fileStream =
|
|
1392
|
-
const { size } =
|
|
1743
|
+
const fileStream = fs6__default.default.createReadStream(constants_default.LOG_FILE_PATH);
|
|
1744
|
+
const { size } = fs6__default.default.statSync(constants_default.LOG_FILE_PATH);
|
|
1393
1745
|
return this.request({
|
|
1394
1746
|
url: uploadURL,
|
|
1395
1747
|
method: "PUT",
|
|
@@ -1457,7 +1809,7 @@ var ctx_default = (options) => {
|
|
|
1457
1809
|
let buildNameObj;
|
|
1458
1810
|
try {
|
|
1459
1811
|
if (options.config) {
|
|
1460
|
-
config = JSON.parse(
|
|
1812
|
+
config = JSON.parse(fs6__default.default.readFileSync(options.config, "utf-8"));
|
|
1461
1813
|
if ((_a = config.web) == null ? void 0 : _a.resolutions) {
|
|
1462
1814
|
config.web.viewports = config.web.resolutions;
|
|
1463
1815
|
delete config.web.resolutions;
|
|
@@ -1493,7 +1845,7 @@ var ctx_default = (options) => {
|
|
|
1493
1845
|
}
|
|
1494
1846
|
if (config.web) {
|
|
1495
1847
|
webConfig = { browsers: config.web.browsers, viewports: [] };
|
|
1496
|
-
for (let viewport of (_b = config.web) == null ?
|
|
1848
|
+
for (let viewport of (_b = config.web) == null ? void 0 : _b.viewports)
|
|
1497
1849
|
webConfig.viewports.push({ width: viewport[0], height: viewport[1] || 0 });
|
|
1498
1850
|
}
|
|
1499
1851
|
if (config.mobile) {
|
|
@@ -1545,398 +1897,143 @@ var ctx_default = (options) => {
|
|
|
1545
1897
|
markBaseline: options.markBaseline ? true : false,
|
|
1546
1898
|
buildName: options.buildName || "",
|
|
1547
1899
|
port,
|
|
1548
|
-
ignoreResolutions: resolutionOff,
|
|
1549
|
-
fileExtension: extensionFiles,
|
|
1550
|
-
stripExtension: ignoreStripExtension,
|
|
1551
|
-
ignorePattern: ignoreFilePattern,
|
|
1552
|
-
fetchResults: fetchResultObj,
|
|
1553
|
-
fetchResultsFileName: fetchResultsFileObj
|
|
1554
|
-
},
|
|
1555
|
-
cliVersion: version,
|
|
1556
|
-
totalSnapshots: -1
|
|
1557
|
-
|
|
1558
|
-
};
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
}
|
|
1571
|
-
function isGitRepo() {
|
|
1572
|
-
try {
|
|
1573
|
-
executeCommand("git status");
|
|
1574
|
-
return true;
|
|
1575
|
-
} catch (error) {
|
|
1576
|
-
return false;
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
var git_default = (ctx) => {
|
|
1580
|
-
if (ctx.env.SMARTUI_GIT_INFO_FILEPATH) {
|
|
1581
|
-
let gitInfo = JSON.parse(fs5__default.default.readFileSync(ctx.env.SMARTUI_GIT_INFO_FILEPATH, "utf-8"));
|
|
1582
|
-
return {
|
|
1583
|
-
branch: ctx.env.CURRENT_BRANCH || gitInfo.branch || "",
|
|
1584
|
-
commitId: gitInfo.commit_id.slice(0, 6) || "",
|
|
1585
|
-
commitMessage: gitInfo.commit_body || "",
|
|
1586
|
-
commitAuthor: gitInfo.commit_author || "",
|
|
1587
|
-
githubURL: ctx.env.GITHUB_ACTIONS ? `${constants_default.GITHUB_API_HOST}/repos/${process.env.GITHUB_REPOSITORY}/statuses/${gitInfo.commit_id}` : "",
|
|
1588
|
-
baselineBranch: ctx.env.BASELINE_BRANCH || ""
|
|
1589
|
-
};
|
|
1590
|
-
} else {
|
|
1591
|
-
const splitCharacter = "<##>";
|
|
1592
|
-
const prettyFormat = ["%h", "%H", "%s", "%f", "%b", "%at", "%ct", "%an", "%ae", "%cn", "%ce", "%N", ""];
|
|
1593
|
-
const command4 = 'git log -1 --pretty=format:"' + prettyFormat.join(splitCharacter) + '" && git rev-parse --abbrev-ref HEAD && git tag --contains HEAD';
|
|
1594
|
-
let res = executeCommand(command4).split(splitCharacter);
|
|
1595
|
-
var branchAndTags = res[res.length - 1].split("\n").filter((n) => n);
|
|
1596
|
-
var branch = ctx.env.CURRENT_BRANCH || branchAndTags[0];
|
|
1597
|
-
branchAndTags.slice(1);
|
|
1598
|
-
return {
|
|
1599
|
-
branch: branch || "",
|
|
1600
|
-
commitId: res[0] || "",
|
|
1601
|
-
commitMessage: res[2] || "",
|
|
1602
|
-
commitAuthor: res[7] || "",
|
|
1603
|
-
githubURL: ctx.env.GITHUB_ACTIONS ? `${constants_default.GITHUB_API_HOST}/repos/${process.env.GITHUB_REPOSITORY}/statuses/${res[1]}` : "",
|
|
1604
|
-
baselineBranch: ctx.env.BASELINE_BRANCH || ""
|
|
1605
|
-
};
|
|
1606
|
-
}
|
|
1607
|
-
};
|
|
1608
|
-
var getGitInfo_default = (ctx) => {
|
|
1609
|
-
return {
|
|
1610
|
-
title: `Fetching git repo details`,
|
|
1611
|
-
skip: (ctx2) => {
|
|
1612
|
-
return !isGitRepo() && !ctx2.env.SMARTUI_GIT_INFO_FILEPATH ? "[SKIPPED] Fetching git repo details; not a git repo" : "";
|
|
1613
|
-
},
|
|
1614
|
-
task: (ctx2, task) => __async(undefined, null, function* () {
|
|
1615
|
-
if (ctx2.env.CURRENT_BRANCH && ctx2.env.CURRENT_BRANCH.trim() === "") {
|
|
1616
|
-
throw new Error("Error: The environment variable CURRENT_BRANCH cannot be empty.");
|
|
1617
|
-
}
|
|
1618
|
-
try {
|
|
1619
|
-
ctx2.git = git_default(ctx2);
|
|
1620
|
-
task.output = chalk6__default.default.gray(`branch: ${ctx2.git.branch}, commit: ${ctx2.git.commitId}, author: ${ctx2.git.commitAuthor}`);
|
|
1621
|
-
task.title = "Fetched git information";
|
|
1622
|
-
} catch (error) {
|
|
1623
|
-
ctx2.log.debug(error);
|
|
1624
|
-
task.output = chalk6__default.default.gray(`${error.message}`);
|
|
1625
|
-
throw new Error("Error fetching git repo details");
|
|
1626
|
-
}
|
|
1627
|
-
}),
|
|
1628
|
-
rendererOptions: { persistentOutput: true }
|
|
1629
|
-
};
|
|
1630
|
-
};
|
|
1631
|
-
var createBuild_default = (ctx) => {
|
|
1632
|
-
return {
|
|
1633
|
-
title: `Creating SmartUI build`,
|
|
1634
|
-
task: (ctx2, task) => __async(undefined, null, function* () {
|
|
1635
|
-
updateLogContext({ task: "createBuild" });
|
|
1636
|
-
try {
|
|
1637
|
-
let resp = yield ctx2.client.createBuild(ctx2.git, ctx2.config, ctx2.log, ctx2.build.name);
|
|
1638
|
-
ctx2.build = {
|
|
1639
|
-
id: resp.data.buildId,
|
|
1640
|
-
name: resp.data.buildName,
|
|
1641
|
-
url: resp.data.buildURL,
|
|
1642
|
-
baseline: resp.data.baseline,
|
|
1643
|
-
useKafkaFlow: resp.data.useKafkaFlow || false
|
|
1644
|
-
};
|
|
1645
|
-
task.output = chalk6__default.default.gray(`build id: ${resp.data.buildId}`);
|
|
1646
|
-
task.title = "SmartUI build created";
|
|
1647
|
-
} catch (error) {
|
|
1648
|
-
ctx2.log.debug(error);
|
|
1649
|
-
task.output = chalk6__default.default.gray(error.message);
|
|
1650
|
-
throw new Error("SmartUI build creation failed");
|
|
1651
|
-
}
|
|
1652
|
-
}),
|
|
1653
|
-
rendererOptions: { persistentOutput: true }
|
|
1654
|
-
};
|
|
1655
|
-
};
|
|
1656
|
-
var isPollingActive = false;
|
|
1657
|
-
function delDir(dir) {
|
|
1658
|
-
if (fs5__default.default.existsSync(dir)) {
|
|
1659
|
-
fs5__default.default.rmSync(dir, { recursive: true });
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
|
-
function scrollToBottomAndBackToTop({
|
|
1663
|
-
frequency = 100,
|
|
1664
|
-
timing = 8,
|
|
1665
|
-
remoteWindow = window
|
|
1666
|
-
} = {}) {
|
|
1667
|
-
return new Promise((resolve) => {
|
|
1668
|
-
let scrolls = 1;
|
|
1669
|
-
let scrollLength = remoteWindow.document.body.scrollHeight / frequency;
|
|
1670
|
-
(function scroll() {
|
|
1671
|
-
let scrollBy = scrollLength * scrolls;
|
|
1672
|
-
remoteWindow.setTimeout(() => {
|
|
1673
|
-
remoteWindow.scrollTo(0, scrollBy);
|
|
1674
|
-
if (scrolls < frequency) {
|
|
1675
|
-
scrolls += 1;
|
|
1676
|
-
scroll();
|
|
1677
|
-
}
|
|
1678
|
-
if (scrolls === frequency) {
|
|
1679
|
-
remoteWindow.setTimeout(() => {
|
|
1680
|
-
remoteWindow.scrollTo(0, 0);
|
|
1681
|
-
resolve();
|
|
1682
|
-
}, timing);
|
|
1683
|
-
}
|
|
1684
|
-
}, timing);
|
|
1685
|
-
})();
|
|
1686
|
-
});
|
|
1687
|
-
}
|
|
1688
|
-
function launchBrowsers(ctx) {
|
|
1689
|
-
return __async(this, null, function* () {
|
|
1690
|
-
var _a;
|
|
1691
|
-
let browsers = {};
|
|
1692
|
-
const isHeadless = ((_a = process.env.HEADLESS) == null ? undefined : _a.toLowerCase()) === "false" ? false : true;
|
|
1693
|
-
let launchOptions = { headless: isHeadless };
|
|
1694
|
-
if (ctx.config.web) {
|
|
1695
|
-
for (const browser of ctx.config.web.browsers) {
|
|
1696
|
-
switch (browser) {
|
|
1697
|
-
case constants_default.CHROME:
|
|
1698
|
-
browsers[constants_default.CHROME] = yield test.chromium.launch(launchOptions);
|
|
1699
|
-
break;
|
|
1700
|
-
case constants_default.SAFARI:
|
|
1701
|
-
browsers[constants_default.SAFARI] = yield test.webkit.launch(launchOptions);
|
|
1702
|
-
break;
|
|
1703
|
-
case constants_default.FIREFOX:
|
|
1704
|
-
browsers[constants_default.FIREFOX] = yield test.firefox.launch(launchOptions);
|
|
1705
|
-
break;
|
|
1706
|
-
case constants_default.EDGE:
|
|
1707
|
-
launchOptions.args = ["--headless=new"];
|
|
1708
|
-
browsers[constants_default.EDGE] = yield test.chromium.launch(__spreadValues({ channel: constants_default.EDGE_CHANNEL }, launchOptions));
|
|
1709
|
-
break;
|
|
1710
|
-
}
|
|
1711
|
-
}
|
|
1712
|
-
}
|
|
1713
|
-
if (ctx.config.mobile) {
|
|
1714
|
-
for (const device of ctx.config.mobile.devices) {
|
|
1715
|
-
if (constants_default.SUPPORTED_MOBILE_DEVICES[device].os === "android" && !browsers[constants_default.CHROME])
|
|
1716
|
-
browsers[constants_default.CHROME] = yield test.chromium.launch(launchOptions);
|
|
1717
|
-
else if (constants_default.SUPPORTED_MOBILE_DEVICES[device].os === "ios" && !browsers[constants_default.SAFARI])
|
|
1718
|
-
browsers[constants_default.SAFARI] = yield test.webkit.launch(launchOptions);
|
|
1719
|
-
}
|
|
1720
|
-
}
|
|
1721
|
-
return browsers;
|
|
1722
|
-
});
|
|
1723
|
-
}
|
|
1724
|
-
function closeBrowsers(browsers) {
|
|
1725
|
-
return __async(this, null, function* () {
|
|
1726
|
-
var _a;
|
|
1727
|
-
for (const browserName of Object.keys(browsers))
|
|
1728
|
-
yield (_a = browsers[browserName]) == null ? undefined : _a.close();
|
|
1729
|
-
});
|
|
1730
|
-
}
|
|
1731
|
-
function getWebRenderViewports(ctx) {
|
|
1732
|
-
let webRenderViewports = [];
|
|
1733
|
-
if (ctx.config.web) {
|
|
1734
|
-
for (const viewport of ctx.config.web.viewports) {
|
|
1735
|
-
webRenderViewports.push({
|
|
1736
|
-
viewport,
|
|
1737
|
-
viewportString: `${viewport.width}${viewport.height ? "x" + viewport.height : ""}`,
|
|
1738
|
-
fullPage: viewport.height ? false : true,
|
|
1739
|
-
device: false
|
|
1740
|
-
});
|
|
1741
|
-
}
|
|
1742
|
-
}
|
|
1743
|
-
return webRenderViewports;
|
|
1744
|
-
}
|
|
1745
|
-
function getWebRenderViewportsForOptions(options) {
|
|
1746
|
-
let webRenderViewports = [];
|
|
1747
|
-
if (options.web && Array.isArray(options.web.viewports)) {
|
|
1748
|
-
for (const viewport of options.web.viewports) {
|
|
1749
|
-
if (Array.isArray(viewport) && viewport.length > 0) {
|
|
1750
|
-
let viewportObj = {
|
|
1751
|
-
width: viewport[0]
|
|
1752
|
-
};
|
|
1753
|
-
if (viewport.length > 1) {
|
|
1754
|
-
viewportObj.height = viewport[1];
|
|
1755
|
-
}
|
|
1756
|
-
webRenderViewports.push({
|
|
1757
|
-
viewport: viewportObj,
|
|
1758
|
-
viewportString: `${viewport[0]}${viewport[1] ? "x" + viewport[1] : ""}`,
|
|
1759
|
-
fullPage: viewport.length === 1,
|
|
1760
|
-
device: false
|
|
1761
|
-
});
|
|
1762
|
-
}
|
|
1763
|
-
}
|
|
1764
|
-
}
|
|
1765
|
-
return webRenderViewports;
|
|
1766
|
-
}
|
|
1767
|
-
function getMobileRenderViewports(ctx) {
|
|
1768
|
-
var _a;
|
|
1769
|
-
let mobileRenderViewports = {};
|
|
1770
|
-
mobileRenderViewports[constants_default.MOBILE_OS_IOS] = [];
|
|
1771
|
-
mobileRenderViewports[constants_default.MOBILE_OS_ANDROID] = [];
|
|
1772
|
-
if (ctx.config.mobile) {
|
|
1773
|
-
for (const device of ctx.config.mobile.devices) {
|
|
1774
|
-
let os = constants_default.SUPPORTED_MOBILE_DEVICES[device].os;
|
|
1775
|
-
let { width, height } = constants_default.SUPPORTED_MOBILE_DEVICES[device].viewport;
|
|
1776
|
-
let portrait = ctx.config.mobile.orientation === constants_default.MOBILE_ORIENTATION_PORTRAIT ? true : false;
|
|
1777
|
-
(_a = mobileRenderViewports[os]) == null ? undefined : _a.push({
|
|
1778
|
-
viewport: { width: portrait ? width : height, height: portrait ? height : width },
|
|
1779
|
-
viewportString: `${device} (${ctx.config.mobile.orientation})`,
|
|
1780
|
-
fullPage: ctx.config.mobile.fullPage,
|
|
1781
|
-
device: true,
|
|
1782
|
-
os
|
|
1783
|
-
});
|
|
1784
|
-
}
|
|
1900
|
+
ignoreResolutions: resolutionOff,
|
|
1901
|
+
fileExtension: extensionFiles,
|
|
1902
|
+
stripExtension: ignoreStripExtension,
|
|
1903
|
+
ignorePattern: ignoreFilePattern,
|
|
1904
|
+
fetchResults: fetchResultObj,
|
|
1905
|
+
fetchResultsFileName: fetchResultsFileObj
|
|
1906
|
+
},
|
|
1907
|
+
cliVersion: version,
|
|
1908
|
+
totalSnapshots: -1,
|
|
1909
|
+
isStartExec: false
|
|
1910
|
+
};
|
|
1911
|
+
};
|
|
1912
|
+
function executeCommand(command7) {
|
|
1913
|
+
let dst = process.cwd();
|
|
1914
|
+
try {
|
|
1915
|
+
return child_process.execSync(command7, {
|
|
1916
|
+
cwd: dst,
|
|
1917
|
+
stdio: ["ignore"],
|
|
1918
|
+
encoding: "utf-8"
|
|
1919
|
+
});
|
|
1920
|
+
} catch (error) {
|
|
1921
|
+
throw new Error(error.message);
|
|
1785
1922
|
}
|
|
1786
|
-
return mobileRenderViewports;
|
|
1787
1923
|
}
|
|
1788
|
-
function
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
for (const device of options.mobile.devices) {
|
|
1795
|
-
let os = constants_default.SUPPORTED_MOBILE_DEVICES[device].os;
|
|
1796
|
-
let { width, height } = constants_default.SUPPORTED_MOBILE_DEVICES[device].viewport;
|
|
1797
|
-
let orientation = options.mobile.orientation || constants_default.MOBILE_ORIENTATION_PORTRAIT;
|
|
1798
|
-
let portrait = orientation === constants_default.MOBILE_ORIENTATION_PORTRAIT;
|
|
1799
|
-
let fullPage;
|
|
1800
|
-
if (options.mobile.fullPage === undefined || options.mobile.fullPage) {
|
|
1801
|
-
fullPage = true;
|
|
1802
|
-
} else {
|
|
1803
|
-
fullPage = false;
|
|
1804
|
-
}
|
|
1805
|
-
(_a = mobileRenderViewports[os]) == null ? undefined : _a.push({
|
|
1806
|
-
viewport: { width: portrait ? width : height, height: portrait ? height : width },
|
|
1807
|
-
viewportString: `${device} (${orientation})`,
|
|
1808
|
-
fullPage,
|
|
1809
|
-
device: true,
|
|
1810
|
-
os
|
|
1811
|
-
});
|
|
1812
|
-
}
|
|
1924
|
+
function isGitRepo() {
|
|
1925
|
+
try {
|
|
1926
|
+
executeCommand("git status");
|
|
1927
|
+
return true;
|
|
1928
|
+
} catch (error) {
|
|
1929
|
+
return false;
|
|
1813
1930
|
}
|
|
1814
|
-
return mobileRenderViewports;
|
|
1815
|
-
}
|
|
1816
|
-
function getRenderViewports(ctx) {
|
|
1817
|
-
let mobileRenderViewports = getMobileRenderViewports(ctx);
|
|
1818
|
-
let webRenderViewports = getWebRenderViewports(ctx);
|
|
1819
|
-
return [
|
|
1820
|
-
...webRenderViewports,
|
|
1821
|
-
...mobileRenderViewports[constants_default.MOBILE_OS_IOS],
|
|
1822
|
-
...mobileRenderViewports[constants_default.MOBILE_OS_ANDROID]
|
|
1823
|
-
];
|
|
1824
|
-
}
|
|
1825
|
-
function getRenderViewportsForOptions(options) {
|
|
1826
|
-
let mobileRenderViewports = getMobileRenderViewportsForOptions(options);
|
|
1827
|
-
let webRenderViewports = getWebRenderViewportsForOptions(options);
|
|
1828
|
-
return [
|
|
1829
|
-
...webRenderViewports,
|
|
1830
|
-
...mobileRenderViewports[constants_default.MOBILE_OS_IOS],
|
|
1831
|
-
...mobileRenderViewports[constants_default.MOBILE_OS_ANDROID]
|
|
1832
|
-
];
|
|
1833
1931
|
}
|
|
1834
|
-
|
|
1835
|
-
if (
|
|
1836
|
-
|
|
1837
|
-
|
|
1932
|
+
var git_default = (ctx) => {
|
|
1933
|
+
if (ctx.env.SMARTUI_GIT_INFO_FILEPATH) {
|
|
1934
|
+
let gitInfo = JSON.parse(fs6__default.default.readFileSync(ctx.env.SMARTUI_GIT_INFO_FILEPATH, "utf-8"));
|
|
1935
|
+
return {
|
|
1936
|
+
branch: ctx.env.CURRENT_BRANCH || gitInfo.branch || "",
|
|
1937
|
+
commitId: gitInfo.commit_id.slice(0, 6) || "",
|
|
1938
|
+
commitMessage: gitInfo.commit_body || "",
|
|
1939
|
+
commitAuthor: gitInfo.commit_author || "",
|
|
1940
|
+
githubURL: ctx.env.GITHUB_ACTIONS ? `${constants_default.GITHUB_API_HOST}/repos/${process.env.GITHUB_REPOSITORY}/statuses/${gitInfo.commit_id}` : "",
|
|
1941
|
+
baselineBranch: ctx.env.BASELINE_BRANCH || ""
|
|
1942
|
+
};
|
|
1838
1943
|
} else {
|
|
1839
|
-
|
|
1944
|
+
const splitCharacter = "<##>";
|
|
1945
|
+
const prettyFormat = ["%h", "%H", "%s", "%f", "%b", "%at", "%ct", "%an", "%ae", "%cn", "%ce", "%N", ""];
|
|
1946
|
+
const command7 = 'git log -1 --pretty=format:"' + prettyFormat.join(splitCharacter) + '" && git rev-parse --abbrev-ref HEAD && git tag --contains HEAD';
|
|
1947
|
+
let res = executeCommand(command7).split(splitCharacter);
|
|
1948
|
+
var branchAndTags = res[res.length - 1].split("\n").filter((n) => n);
|
|
1949
|
+
var branch = ctx.env.CURRENT_BRANCH || branchAndTags[0];
|
|
1950
|
+
branchAndTags.slice(1);
|
|
1951
|
+
return {
|
|
1952
|
+
branch: branch || "",
|
|
1953
|
+
commitId: res[0] || "",
|
|
1954
|
+
commitMessage: res[2] || "",
|
|
1955
|
+
commitAuthor: res[7] || "",
|
|
1956
|
+
githubURL: ctx.env.GITHUB_ACTIONS ? `${constants_default.GITHUB_API_HOST}/repos/${process.env.GITHUB_REPOSITORY}/statuses/${res[1]}` : "",
|
|
1957
|
+
baselineBranch: ctx.env.BASELINE_BRANCH || ""
|
|
1958
|
+
};
|
|
1840
1959
|
}
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1960
|
+
};
|
|
1961
|
+
var getGitInfo_default = (ctx) => {
|
|
1962
|
+
return {
|
|
1963
|
+
title: `Fetching git repo details`,
|
|
1964
|
+
skip: (ctx2) => {
|
|
1965
|
+
return !isGitRepo() && !ctx2.env.SMARTUI_GIT_INFO_FILEPATH ? "[SKIPPED] Fetching git repo details; not a git repo" : "";
|
|
1966
|
+
},
|
|
1967
|
+
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
1968
|
+
if (ctx2.env.CURRENT_BRANCH && ctx2.env.CURRENT_BRANCH.trim() === "") {
|
|
1969
|
+
throw new Error("Error: The environment variable CURRENT_BRANCH cannot be empty.");
|
|
1851
1970
|
}
|
|
1852
1971
|
try {
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
clearInterval(intervalId);
|
|
1857
|
-
isPollingActive = false;
|
|
1858
|
-
}
|
|
1859
|
-
fs5__default.default.writeFileSync(ctx.options.fetchResultsFileName, JSON.stringify(resp, null, 2));
|
|
1860
|
-
ctx.log.debug(`Updated results in ${ctx.options.fetchResultsFileName}`);
|
|
1861
|
-
if (resp.build.build_status_ind === constants_default.BUILD_COMPLETE || resp.build.build_status_ind === constants_default.BUILD_ERROR) {
|
|
1862
|
-
clearInterval(intervalId);
|
|
1863
|
-
ctx.log.info(`Fetching results completed. Final results written to ${ctx.options.fetchResultsFileName}`);
|
|
1864
|
-
isPollingActive = false;
|
|
1865
|
-
let totalScreenshotsWithMismatches = 0;
|
|
1866
|
-
let totalVariantsWithMismatches = 0;
|
|
1867
|
-
const totalScreenshots = Object.keys(resp.screenshots || {}).length;
|
|
1868
|
-
let totalVariants = 0;
|
|
1869
|
-
for (const [screenshot, variants] of Object.entries(resp.screenshots || {})) {
|
|
1870
|
-
let screenshotHasMismatch = false;
|
|
1871
|
-
let variantMismatchCount = 0;
|
|
1872
|
-
totalVariants += variants.length;
|
|
1873
|
-
for (const variant of variants) {
|
|
1874
|
-
if (variant.mismatch_percentage > 0) {
|
|
1875
|
-
screenshotHasMismatch = true;
|
|
1876
|
-
variantMismatchCount++;
|
|
1877
|
-
}
|
|
1878
|
-
}
|
|
1879
|
-
if (screenshotHasMismatch) {
|
|
1880
|
-
totalScreenshotsWithMismatches++;
|
|
1881
|
-
totalVariantsWithMismatches += variantMismatchCount;
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1884
|
-
ctx.log.info(
|
|
1885
|
-
chalk6__default.default.green.bold(
|
|
1886
|
-
`
|
|
1887
|
-
Summary of Mismatches:
|
|
1888
|
-
${chalk6__default.default.yellow("Total Variants with Mismatches:")} ${chalk6__default.default.white(totalVariantsWithMismatches)} out of ${chalk6__default.default.white(totalVariants)}
|
|
1889
|
-
${chalk6__default.default.yellow("Total Screenshots with Mismatches:")} ${chalk6__default.default.white(totalScreenshotsWithMismatches)} out of ${chalk6__default.default.white(totalScreenshots)}
|
|
1890
|
-
${chalk6__default.default.yellow("Branch Name:")} ${chalk6__default.default.white(resp.build.branch)}
|
|
1891
|
-
${chalk6__default.default.yellow("Project Name:")} ${chalk6__default.default.white(resp.project.name)}
|
|
1892
|
-
${chalk6__default.default.yellow("Build ID:")} ${chalk6__default.default.white(resp.build.build_id)}
|
|
1893
|
-
`
|
|
1894
|
-
)
|
|
1895
|
-
);
|
|
1896
|
-
}
|
|
1972
|
+
ctx2.git = git_default(ctx2);
|
|
1973
|
+
task.output = chalk__default.default.gray(`branch: ${ctx2.git.branch}, commit: ${ctx2.git.commitId}, author: ${ctx2.git.commitAuthor}`);
|
|
1974
|
+
task.title = "Fetched git information";
|
|
1897
1975
|
} catch (error) {
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
} else {
|
|
1902
|
-
ctx.log.error(`Error fetching screenshot data: ${error.message}`);
|
|
1903
|
-
}
|
|
1904
|
-
clearInterval(intervalId);
|
|
1905
|
-
isPollingActive = false;
|
|
1976
|
+
ctx2.log.debug(error);
|
|
1977
|
+
task.output = chalk__default.default.gray(`${error.message}`);
|
|
1978
|
+
throw new Error("Error fetching git repo details");
|
|
1906
1979
|
}
|
|
1907
|
-
}),
|
|
1908
|
-
|
|
1909
|
-
}
|
|
1910
|
-
|
|
1911
|
-
|
|
1980
|
+
}),
|
|
1981
|
+
rendererOptions: { persistentOutput: true }
|
|
1982
|
+
};
|
|
1983
|
+
};
|
|
1984
|
+
var createBuild_default = (ctx) => {
|
|
1985
|
+
return {
|
|
1986
|
+
title: `Creating SmartUI build`,
|
|
1987
|
+
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
1988
|
+
updateLogContext({ task: "createBuild" });
|
|
1989
|
+
try {
|
|
1990
|
+
let resp = yield ctx2.client.createBuild(ctx2.git, ctx2.config, ctx2.log, ctx2.build.name, ctx2.isStartExec);
|
|
1991
|
+
ctx2.build = {
|
|
1992
|
+
id: resp.data.buildId,
|
|
1993
|
+
name: resp.data.buildName,
|
|
1994
|
+
url: resp.data.buildURL,
|
|
1995
|
+
baseline: resp.data.baseline,
|
|
1996
|
+
useKafkaFlow: resp.data.useKafkaFlow || false
|
|
1997
|
+
};
|
|
1998
|
+
task.output = chalk__default.default.gray(`build id: ${resp.data.buildId}`);
|
|
1999
|
+
task.title = "SmartUI build created";
|
|
2000
|
+
} catch (error) {
|
|
2001
|
+
ctx2.log.debug(error);
|
|
2002
|
+
task.output = chalk__default.default.gray(error.message);
|
|
2003
|
+
throw new Error("SmartUI build creation failed");
|
|
2004
|
+
}
|
|
2005
|
+
}),
|
|
2006
|
+
rendererOptions: { persistentOutput: true }
|
|
2007
|
+
};
|
|
2008
|
+
};
|
|
1912
2009
|
var exec_default = (ctx) => {
|
|
1913
2010
|
var _a;
|
|
1914
2011
|
return {
|
|
1915
|
-
title: `Executing '${(_a = ctx.args.execCommand) == null ?
|
|
1916
|
-
task: (ctx2, task) => __async(
|
|
2012
|
+
title: `Executing '${(_a = ctx.args.execCommand) == null ? void 0 : _a.join(" ")}'`,
|
|
2013
|
+
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
1917
2014
|
if (ctx2.options.fetchResults) {
|
|
1918
2015
|
startPolling(ctx2);
|
|
1919
2016
|
}
|
|
1920
2017
|
updateLogContext({ task: "exec" });
|
|
1921
2018
|
return new Promise((resolve, reject) => {
|
|
1922
2019
|
var _a2, _b, _c;
|
|
1923
|
-
const childProcess = spawn__default.default(ctx2.args.execCommand[0], (_a2 = ctx2.args.execCommand) == null ?
|
|
2020
|
+
const childProcess = spawn__default.default(ctx2.args.execCommand[0], (_a2 = ctx2.args.execCommand) == null ? void 0 : _a2.slice(1));
|
|
1924
2021
|
let totalOutput = "";
|
|
1925
2022
|
const output = listr2.createWritable((chunk) => {
|
|
1926
2023
|
totalOutput += chunk;
|
|
1927
|
-
task.output =
|
|
2024
|
+
task.output = chalk__default.default.gray(totalOutput);
|
|
1928
2025
|
});
|
|
1929
|
-
(_b = childProcess.stdout) == null ?
|
|
1930
|
-
(_c = childProcess.stderr) == null ?
|
|
2026
|
+
(_b = childProcess.stdout) == null ? void 0 : _b.pipe(output);
|
|
2027
|
+
(_c = childProcess.stderr) == null ? void 0 : _c.pipe(output);
|
|
1931
2028
|
childProcess.on("error", (error) => {
|
|
1932
2029
|
var _a3;
|
|
1933
|
-
task.output =
|
|
1934
|
-
throw new Error(`Execution of '${(_a3 = ctx2.args.execCommand) == null ?
|
|
2030
|
+
task.output = chalk__default.default.gray(`error: ${error.message}`);
|
|
2031
|
+
throw new Error(`Execution of '${(_a3 = ctx2.args.execCommand) == null ? void 0 : _a3.join(" ")}' failed`);
|
|
1935
2032
|
});
|
|
1936
|
-
childProcess.on("close", (code, signal) => __async(
|
|
2033
|
+
childProcess.on("close", (code, signal) => __async(void 0, null, function* () {
|
|
1937
2034
|
var _a3;
|
|
1938
2035
|
if (code !== null) {
|
|
1939
|
-
task.title = `Execution of '${(_a3 = ctx2.args.execCommand) == null ?
|
|
2036
|
+
task.title = `Execution of '${(_a3 = ctx2.args.execCommand) == null ? void 0 : _a3.join(" ")}' completed; exited with code ${code}`;
|
|
1940
2037
|
} else if (signal !== null) {
|
|
1941
2038
|
throw new Error(`Child process killed with signal ${signal}`);
|
|
1942
2039
|
}
|
|
@@ -1951,7 +2048,7 @@ var exec_default = (ctx) => {
|
|
|
1951
2048
|
var processSnapshot_default = (ctx) => {
|
|
1952
2049
|
return {
|
|
1953
2050
|
title: `Processing snapshots`,
|
|
1954
|
-
task: (ctx2, task) => __async(
|
|
2051
|
+
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
1955
2052
|
var _a, _b;
|
|
1956
2053
|
try {
|
|
1957
2054
|
if (ctx2.config.delayedUpload) {
|
|
@@ -1973,19 +2070,19 @@ var processSnapshot_default = (ctx) => {
|
|
|
1973
2070
|
let output = "";
|
|
1974
2071
|
for (let snapshot of (_b = ctx2.snapshotQueue) == null ? void 0 : _b.getProcessedSnapshots()) {
|
|
1975
2072
|
if (snapshot.error)
|
|
1976
|
-
output += `${
|
|
2073
|
+
output += `${chalk__default.default.red("\u2717")} ${chalk__default.default.gray(`${snapshot.name}
|
|
1977
2074
|
[error] ${snapshot.error}`)}
|
|
1978
2075
|
`;
|
|
1979
2076
|
else
|
|
1980
|
-
output += `${
|
|
1981
|
-
${snapshot.warnings.length ?
|
|
2077
|
+
output += `${chalk__default.default.green("\u2713")} ${chalk__default.default.gray(snapshot.name)}
|
|
2078
|
+
${snapshot.warnings.length ? chalk__default.default.gray(`[warning] ${snapshot.warnings.join("\n[warning] ")}
|
|
1982
2079
|
`) : ""}`;
|
|
1983
2080
|
}
|
|
1984
2081
|
task.output = output;
|
|
1985
2082
|
task.title = "Processed snapshots";
|
|
1986
2083
|
} catch (error) {
|
|
1987
2084
|
ctx2.log.debug(error);
|
|
1988
|
-
task.output =
|
|
2085
|
+
task.output = chalk__default.default.gray(error.message);
|
|
1989
2086
|
throw new Error("Processing of snapshots failed");
|
|
1990
2087
|
}
|
|
1991
2088
|
}),
|
|
@@ -1995,16 +2092,16 @@ ${snapshot.warnings.length ? chalk6__default.default.gray(`[warning] ${snapshot.
|
|
|
1995
2092
|
var finalizeBuild_default = (ctx) => {
|
|
1996
2093
|
return {
|
|
1997
2094
|
title: `Finalizing build`,
|
|
1998
|
-
task: (ctx2, task) => __async(
|
|
2095
|
+
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
1999
2096
|
var _a, _b;
|
|
2000
2097
|
updateLogContext({ task: "finalizeBuild" });
|
|
2001
2098
|
try {
|
|
2002
2099
|
yield ctx2.client.finalizeBuild(ctx2.build.id, ctx2.totalSnapshots, ctx2.log);
|
|
2003
|
-
task.output =
|
|
2100
|
+
task.output = chalk__default.default.gray(`build url: ${ctx2.build.url}`);
|
|
2004
2101
|
task.title = "Finalized build";
|
|
2005
2102
|
} catch (error) {
|
|
2006
2103
|
ctx2.log.debug(error);
|
|
2007
|
-
task.output =
|
|
2104
|
+
task.output = chalk__default.default.gray(error.message);
|
|
2008
2105
|
throw new Error("Finalize build failed");
|
|
2009
2106
|
}
|
|
2010
2107
|
try {
|
|
@@ -2014,6 +2111,8 @@ var finalizeBuild_default = (ctx) => {
|
|
|
2014
2111
|
ctx2.log.debug(`Closed server`);
|
|
2015
2112
|
let resp = yield ctx2.client.getS3PreSignedURL(ctx2);
|
|
2016
2113
|
yield ctx2.client.uploadLogs(ctx2, resp.data.url);
|
|
2114
|
+
fs6__default.default.unlinkSync(constants_default.LOG_FILE_PATH);
|
|
2115
|
+
ctx2.log.debug(`Log file deleted: ${constants_default.LOG_FILE_PATH}`);
|
|
2017
2116
|
} catch (error) {
|
|
2018
2117
|
ctx2.log.debug(error);
|
|
2019
2118
|
}
|
|
@@ -2031,7 +2130,7 @@ function processSnapshot(snapshot, ctx) {
|
|
|
2031
2130
|
var _a, _b;
|
|
2032
2131
|
updateLogContext({ task: "discovery" });
|
|
2033
2132
|
ctx.log.debug(`Processing snapshot ${snapshot.name} ${snapshot.url}`);
|
|
2034
|
-
const isHeadless = ((_a = process.env.HEADLESS) == null ?
|
|
2133
|
+
const isHeadless = ((_a = process.env.HEADLESS) == null ? void 0 : _a.toLowerCase()) === "false" ? false : true;
|
|
2035
2134
|
let launchOptions = {
|
|
2036
2135
|
headless: isHeadless,
|
|
2037
2136
|
args: constants_default.LAUNCH_ARGS
|
|
@@ -2040,7 +2139,7 @@ function processSnapshot(snapshot, ctx) {
|
|
|
2040
2139
|
javaScriptEnabled: ctx.config.cliEnableJavaScript,
|
|
2041
2140
|
userAgent: constants_default.CHROME_USER_AGENT
|
|
2042
2141
|
};
|
|
2043
|
-
if (!((_b = ctx.browser) == null ?
|
|
2142
|
+
if (!((_b = ctx.browser) == null ? void 0 : _b.isConnected())) {
|
|
2044
2143
|
if (ctx.env.HTTP_PROXY || ctx.env.HTTPS_PROXY)
|
|
2045
2144
|
launchOptions.proxy = { server: ctx.env.HTTP_PROXY || ctx.env.HTTPS_PROXY };
|
|
2046
2145
|
if (ctx.env.SMARTUI_HTTP_PROXY || ctx.env.SMARTUI_HTTPS_PROXY)
|
|
@@ -2173,7 +2272,7 @@ function processSnapshot(snapshot, ctx) {
|
|
|
2173
2272
|
const isNotAllEmpty = (obj) => {
|
|
2174
2273
|
var _a2;
|
|
2175
2274
|
for (let key in obj)
|
|
2176
|
-
if ((_a2 = obj[key]) == null ?
|
|
2275
|
+
if ((_a2 = obj[key]) == null ? void 0 : _a2.length)
|
|
2177
2276
|
return true;
|
|
2178
2277
|
return false;
|
|
2179
2278
|
};
|
|
@@ -2301,11 +2400,11 @@ function processSnapshot(snapshot, ctx) {
|
|
|
2301
2400
|
return DEFAULT_HEIGHT;
|
|
2302
2401
|
}
|
|
2303
2402
|
const measurements = [
|
|
2304
|
-
(body == null ?
|
|
2305
|
-
(body == null ?
|
|
2306
|
-
(html == null ?
|
|
2307
|
-
(html == null ?
|
|
2308
|
-
(html == null ?
|
|
2403
|
+
(body == null ? void 0 : body.scrollHeight) || 0,
|
|
2404
|
+
(body == null ? void 0 : body.offsetHeight) || 0,
|
|
2405
|
+
(html == null ? void 0 : html.clientHeight) || 0,
|
|
2406
|
+
(html == null ? void 0 : html.scrollHeight) || 0,
|
|
2407
|
+
(html == null ? void 0 : html.offsetHeight) || 0
|
|
2309
2408
|
];
|
|
2310
2409
|
const allMeasurementsInvalid = measurements.every((measurement) => !measurement);
|
|
2311
2410
|
if (allMeasurementsInvalid) {
|
|
@@ -2420,7 +2519,7 @@ var Queue = class {
|
|
|
2420
2519
|
}
|
|
2421
2520
|
generateWebVariants(snapshot, webConfig) {
|
|
2422
2521
|
var _a, _b, _c;
|
|
2423
|
-
const browsers = (_c = (_b = webConfig.browsers) != null ? _b : (_a = this.ctx.config.web) == null ?
|
|
2522
|
+
const browsers = (_c = (_b = webConfig.browsers) != null ? _b : (_a = this.ctx.config.web) == null ? void 0 : _a.browsers) != null ? _c : [constants_default.CHROME, constants_default.EDGE, constants_default.FIREFOX, constants_default.SAFARI];
|
|
2424
2523
|
const viewports = webConfig.viewports || [];
|
|
2425
2524
|
for (const browser of browsers) {
|
|
2426
2525
|
for (const viewport of viewports) {
|
|
@@ -2434,7 +2533,7 @@ var Queue = class {
|
|
|
2434
2533
|
generateMobileVariants(snapshot, mobileConfig) {
|
|
2435
2534
|
var _a, _b, _c;
|
|
2436
2535
|
const devices = mobileConfig.devices || [];
|
|
2437
|
-
const orientation = (_c = (_b = mobileConfig.orientation) != null ? _b : (_a = this.ctx.config.mobile) == null ?
|
|
2536
|
+
const orientation = (_c = (_b = mobileConfig.orientation) != null ? _b : (_a = this.ctx.config.mobile) == null ? void 0 : _a.orientation) != null ? _c : constants_default.MOBILE_ORIENTATION_PORTRAIT;
|
|
2438
2537
|
for (const device of devices) {
|
|
2439
2538
|
const variant = `${snapshot.name}_${device}_${orientation}`;
|
|
2440
2539
|
this.variants.push(variant);
|
|
@@ -2516,7 +2615,7 @@ var Queue = class {
|
|
|
2516
2615
|
}
|
|
2517
2616
|
filterWebVariants(snapshot, webConfig) {
|
|
2518
2617
|
var _a, _b, _c;
|
|
2519
|
-
const browsers = (_c = (_b = webConfig.browsers) != null ? _b : (_a = this.ctx.config.web) == null ?
|
|
2618
|
+
const browsers = (_c = (_b = webConfig.browsers) != null ? _b : (_a = this.ctx.config.web) == null ? void 0 : _a.browsers) != null ? _c : [constants_default.CHROME, constants_default.EDGE, constants_default.FIREFOX, constants_default.SAFARI];
|
|
2520
2619
|
const viewports = webConfig.viewports || [];
|
|
2521
2620
|
let allVariantsDropped = true;
|
|
2522
2621
|
if (!snapshot.options) {
|
|
@@ -2554,8 +2653,8 @@ var Queue = class {
|
|
|
2554
2653
|
snapshot.options = {};
|
|
2555
2654
|
}
|
|
2556
2655
|
const devices = mobileConfig.devices || [];
|
|
2557
|
-
const orientation = (_c = (_b = mobileConfig.orientation) != null ? _b : (_a = this.ctx.config.mobile) == null ?
|
|
2558
|
-
const fullPage = (_f = (_e = mobileConfig.fullPage) != null ? _e : (_d = this.ctx.config.mobile) == null ?
|
|
2656
|
+
const orientation = (_c = (_b = mobileConfig.orientation) != null ? _b : (_a = this.ctx.config.mobile) == null ? void 0 : _a.orientation) != null ? _c : constants_default.MOBILE_ORIENTATION_PORTRAIT;
|
|
2657
|
+
const fullPage = (_f = (_e = mobileConfig.fullPage) != null ? _e : (_d = this.ctx.config.mobile) == null ? void 0 : _d.fullPage) != null ? _f : true;
|
|
2559
2658
|
let allVariantsDropped = true;
|
|
2560
2659
|
snapshot.options.mobile = { devices: [], orientation: constants_default.MOBILE_ORIENTATION_PORTRAIT, fullPage };
|
|
2561
2660
|
for (const device of devices) {
|
|
@@ -2580,6 +2679,9 @@ var Queue = class {
|
|
|
2580
2679
|
try {
|
|
2581
2680
|
this.processingSnapshot = snapshot == null ? void 0 : snapshot.name;
|
|
2582
2681
|
let drop = false;
|
|
2682
|
+
if (this.ctx.isStartExec) {
|
|
2683
|
+
this.ctx.log.info(`Processing Snapshot: ${snapshot == null ? void 0 : snapshot.name}`);
|
|
2684
|
+
}
|
|
2583
2685
|
if (!this.ctx.config.delayedUpload && snapshot && snapshot.name && this.snapshotNames.includes(snapshot.name)) {
|
|
2584
2686
|
drop = true;
|
|
2585
2687
|
this.ctx.log.info(`Skipping duplicate SmartUI snapshot '${snapshot.name}'. To capture duplicate screenshots, please set the 'delayedUpload' configuration as true in your config file.`);
|
|
@@ -2643,14 +2745,14 @@ var Queue = class {
|
|
|
2643
2745
|
|
|
2644
2746
|
// src/commander/exec.ts
|
|
2645
2747
|
var command = new commander.Command();
|
|
2646
|
-
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").action(function(execCommand, _,
|
|
2748
|
+
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").action(function(execCommand, _, command7) {
|
|
2647
2749
|
return __async(this, null, function* () {
|
|
2648
|
-
const options =
|
|
2750
|
+
const options = command7.optsWithGlobals();
|
|
2649
2751
|
if (options.buildName === "") {
|
|
2650
2752
|
console.log(`Error: The '--buildName' option cannot be an empty string.`);
|
|
2651
2753
|
process.exit(1);
|
|
2652
2754
|
}
|
|
2653
|
-
let ctx = ctx_default(
|
|
2755
|
+
let ctx = ctx_default(command7.optsWithGlobals());
|
|
2654
2756
|
if (!which__default.default.sync(execCommand[0], { nothrow: true })) {
|
|
2655
2757
|
ctx.log.error(`Error: Command not found "${execCommand[0]}"`);
|
|
2656
2758
|
return;
|
|
@@ -2694,13 +2796,13 @@ function createConfig(filepath) {
|
|
|
2694
2796
|
console.log("Error: Config file must have .json extension");
|
|
2695
2797
|
return;
|
|
2696
2798
|
}
|
|
2697
|
-
if (
|
|
2799
|
+
if (fs6__default.default.existsSync(filepath)) {
|
|
2698
2800
|
console.log(`Error: SmartUI Config already exists: ${filepath}`);
|
|
2699
2801
|
console.log(`To create a new file, please specify the file name like: 'smartui config:create .smartui-config.json'`);
|
|
2700
2802
|
return;
|
|
2701
2803
|
}
|
|
2702
|
-
|
|
2703
|
-
|
|
2804
|
+
fs6__default.default.mkdirSync(path2__default.default.dirname(filepath), { recursive: true });
|
|
2805
|
+
fs6__default.default.writeFileSync(filepath, JSON.stringify(constants_default.DEFAULT_CONFIG, null, 2) + "\n");
|
|
2704
2806
|
console.log(`Created SmartUI Config: ${filepath}`);
|
|
2705
2807
|
}
|
|
2706
2808
|
function createWebStaticConfig(filepath) {
|
|
@@ -2710,13 +2812,13 @@ function createWebStaticConfig(filepath) {
|
|
|
2710
2812
|
console.log("Error: Config file must have .json extension");
|
|
2711
2813
|
return;
|
|
2712
2814
|
}
|
|
2713
|
-
if (
|
|
2815
|
+
if (fs6__default.default.existsSync(filepath)) {
|
|
2714
2816
|
console.log(`Error: web-static config already exists: ${filepath}`);
|
|
2715
2817
|
console.log(`To create a new file, please specify the file name like: 'smartui config:create-web-static links.json'`);
|
|
2716
2818
|
return;
|
|
2717
2819
|
}
|
|
2718
|
-
|
|
2719
|
-
|
|
2820
|
+
fs6__default.default.mkdirSync(path2__default.default.dirname(filepath), { recursive: true });
|
|
2821
|
+
fs6__default.default.writeFileSync(filepath, JSON.stringify(constants_default.DEFAULT_WEB_STATIC_CONFIG, null, 2) + "\n");
|
|
2720
2822
|
console.log(`Created web-static config: ${filepath}`);
|
|
2721
2823
|
}
|
|
2722
2824
|
function createFigmaConfig(filepath) {
|
|
@@ -2726,13 +2828,13 @@ function createFigmaConfig(filepath) {
|
|
|
2726
2828
|
console.log("Error: designs config file must have .json extension");
|
|
2727
2829
|
return;
|
|
2728
2830
|
}
|
|
2729
|
-
if (
|
|
2831
|
+
if (fs6__default.default.existsSync(filepath)) {
|
|
2730
2832
|
console.log(`Error: designs config already exists: ${filepath}`);
|
|
2731
2833
|
console.log(`To create a new file, please specify the file name like: 'smartui config:figma-config designs.json'`);
|
|
2732
2834
|
return;
|
|
2733
2835
|
}
|
|
2734
|
-
|
|
2735
|
-
|
|
2836
|
+
fs6__default.default.mkdirSync(path2__default.default.dirname(filepath), { recursive: true });
|
|
2837
|
+
fs6__default.default.writeFileSync(filepath, JSON.stringify(constants_default.DEFAULT_FIGMA_CONFIG, null, 2) + "\n");
|
|
2736
2838
|
console.log(`Created designs config: ${filepath}`);
|
|
2737
2839
|
}
|
|
2738
2840
|
function createWebFigmaConfig(filepath) {
|
|
@@ -2742,13 +2844,13 @@ function createWebFigmaConfig(filepath) {
|
|
|
2742
2844
|
console.log("Error: figma config file must have .json extension");
|
|
2743
2845
|
return;
|
|
2744
2846
|
}
|
|
2745
|
-
if (
|
|
2847
|
+
if (fs6__default.default.existsSync(filepath)) {
|
|
2746
2848
|
console.log(`Error: figma config already exists: ${filepath}`);
|
|
2747
2849
|
console.log(`To create a new file, please specify the file name like: 'smartui config:create-figma-web <fileName>.json'`);
|
|
2748
2850
|
return;
|
|
2749
2851
|
}
|
|
2750
|
-
|
|
2751
|
-
|
|
2852
|
+
fs6__default.default.mkdirSync(path2__default.default.dirname(filepath), { recursive: true });
|
|
2853
|
+
fs6__default.default.writeFileSync(filepath, JSON.stringify(constants_default.WEB_FIGMA_CONFIG, null, 2) + "\n");
|
|
2752
2854
|
console.log(`Created figma web config: ${filepath}`);
|
|
2753
2855
|
}
|
|
2754
2856
|
function verifyFigmaWebConfig(ctx) {
|
|
@@ -2762,9 +2864,9 @@ function verifyFigmaWebConfig(ctx) {
|
|
|
2762
2864
|
if (ctx.env.LT_ACCESS_KEY == "") {
|
|
2763
2865
|
throw new Error("Missing LT_ACCESS_KEY in Environment Variables");
|
|
2764
2866
|
}
|
|
2765
|
-
let figma = ctx.config && ((_a = ctx.config) == null ?
|
|
2867
|
+
let figma = ctx.config && ((_a = ctx.config) == null ? void 0 : _a.figma) || {};
|
|
2766
2868
|
const screenshots = [];
|
|
2767
|
-
for (let c of figma == null ?
|
|
2869
|
+
for (let c of figma == null ? void 0 : figma.configs) {
|
|
2768
2870
|
if (c.screenshot_names && c.screenshot_names.length > 0 && c.figma_ids && c.figma_ids.length != c.screenshot_names.length) {
|
|
2769
2871
|
throw new Error("Mismatch in Figma Ids and Screenshot Names in figma config");
|
|
2770
2872
|
}
|
|
@@ -2840,8 +2942,8 @@ function captureScreenshotsForConfig(_0, _1, _2, _3, _4) {
|
|
|
2840
2942
|
} catch (error) {
|
|
2841
2943
|
throw new Error(`captureScreenshotsForConfig failed for browser ${browserName}; error: ${error}`);
|
|
2842
2944
|
} finally {
|
|
2843
|
-
yield page == null ?
|
|
2844
|
-
yield context == null ?
|
|
2945
|
+
yield page == null ? void 0 : page.close();
|
|
2946
|
+
yield context == null ? void 0 : context.close();
|
|
2845
2947
|
}
|
|
2846
2948
|
});
|
|
2847
2949
|
}
|
|
@@ -2905,13 +3007,13 @@ function captureScreenshots(ctx) {
|
|
|
2905
3007
|
else
|
|
2906
3008
|
yield captureScreenshotsSync(ctx, staticConfig, browsers);
|
|
2907
3009
|
delDir(`screenshots/${staticConfig.name.toLowerCase().replace(/\s/g, "_")}`);
|
|
2908
|
-
output += `${
|
|
3010
|
+
output += `${chalk__default.default.gray(staticConfig.name)} ${chalk__default.default.green("\u2713")}
|
|
2909
3011
|
`;
|
|
2910
3012
|
ctx.task.output = output;
|
|
2911
3013
|
capturedScreenshots++;
|
|
2912
3014
|
} catch (error) {
|
|
2913
3015
|
ctx.log.debug(`screenshot capture failed for ${JSON.stringify(staticConfig)}; error: ${error}`);
|
|
2914
|
-
output += `${
|
|
3016
|
+
output += `${chalk__default.default.gray(staticConfig.name)} ${chalk__default.default.red("\u2717")}
|
|
2915
3017
|
`;
|
|
2916
3018
|
ctx.task.output = output;
|
|
2917
3019
|
}
|
|
@@ -2922,7 +3024,7 @@ function captureScreenshots(ctx) {
|
|
|
2922
3024
|
});
|
|
2923
3025
|
}
|
|
2924
3026
|
function getImageDimensions(filePath) {
|
|
2925
|
-
const buffer =
|
|
3027
|
+
const buffer = fs6__default.default.readFileSync(filePath);
|
|
2926
3028
|
let width, height;
|
|
2927
3029
|
if (buffer.toString("hex", 0, 2) === "ffd8") {
|
|
2928
3030
|
let offset = 2;
|
|
@@ -2947,7 +3049,7 @@ function getImageDimensions(filePath) {
|
|
|
2947
3049
|
function isAllowedImage(filePath) {
|
|
2948
3050
|
return __async(this, null, function* () {
|
|
2949
3051
|
try {
|
|
2950
|
-
const fileBuffer =
|
|
3052
|
+
const fileBuffer = fs6__default.default.readFileSync(filePath);
|
|
2951
3053
|
const isMagicValid = constants_default.MAGIC_NUMBERS.some((magic) => fileBuffer.slice(0, magic.magic.length).equals(magic.magic));
|
|
2952
3054
|
const metadata = yield sharp__default.default(filePath).metadata();
|
|
2953
3055
|
if (metadata.format === constants_default.FILE_EXTENSION_GIFS) {
|
|
@@ -2971,10 +3073,10 @@ function uploadScreenshots(ctx) {
|
|
|
2971
3073
|
let noOfScreenshots = 0;
|
|
2972
3074
|
function processDirectory(directory, relativePath = "") {
|
|
2973
3075
|
return __async(this, null, function* () {
|
|
2974
|
-
const files =
|
|
3076
|
+
const files = fs6__default.default.readdirSync(directory);
|
|
2975
3077
|
for (let file of files) {
|
|
2976
3078
|
const filePath = path2__default.default.join(directory, file);
|
|
2977
|
-
const stat =
|
|
3079
|
+
const stat = fs6__default.default.statSync(filePath);
|
|
2978
3080
|
const relativeFilePath = path2__default.default.join(relativePath, file);
|
|
2979
3081
|
if (stat.isDirectory() && ctx.options.ignorePattern.includes(relativeFilePath)) {
|
|
2980
3082
|
ctx.log.info(`Ignoring Directory ${relativeFilePath}`);
|
|
@@ -3088,14 +3190,14 @@ function processChunk(ctx, urlConfig) {
|
|
|
3088
3190
|
try {
|
|
3089
3191
|
yield captureScreenshotsAsync(ctx, staticConfig, browsers);
|
|
3090
3192
|
delDir(`screenshots/${staticConfig.name.toLowerCase().replace(/\s/g, "_")}`);
|
|
3091
|
-
let output = `${
|
|
3193
|
+
let output = `${chalk__default.default.gray(staticConfig.name)} ${chalk__default.default.green("\u2713")}
|
|
3092
3194
|
`;
|
|
3093
3195
|
ctx.task.output = ctx.task.output ? ctx.task.output + output : output;
|
|
3094
3196
|
finalOutput += output;
|
|
3095
3197
|
capturedScreenshots++;
|
|
3096
3198
|
} catch (error) {
|
|
3097
3199
|
ctx.log.debug(`screenshot capture failed for ${JSON.stringify(staticConfig)}; error: ${error}`);
|
|
3098
|
-
let output = `${
|
|
3200
|
+
let output = `${chalk__default.default.gray(staticConfig.name)} ${chalk__default.default.red("\u2717")}
|
|
3099
3201
|
`;
|
|
3100
3202
|
ctx.task.output += output;
|
|
3101
3203
|
finalOutput += output;
|
|
@@ -3108,7 +3210,7 @@ function processChunk(ctx, urlConfig) {
|
|
|
3108
3210
|
var captureScreenshots_default = (ctx) => {
|
|
3109
3211
|
return {
|
|
3110
3212
|
title: "Capturing screenshots",
|
|
3111
|
-
task: (ctx2, task) => __async(
|
|
3213
|
+
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
3112
3214
|
try {
|
|
3113
3215
|
ctx2.task = task;
|
|
3114
3216
|
if (ctx2.options.fetchResults) {
|
|
@@ -3129,7 +3231,7 @@ var captureScreenshots_default = (ctx) => {
|
|
|
3129
3231
|
task.title = "Screenshots captured successfully";
|
|
3130
3232
|
} catch (error) {
|
|
3131
3233
|
ctx2.log.debug(error);
|
|
3132
|
-
task.output =
|
|
3234
|
+
task.output = chalk__default.default.gray(`${error.message}`);
|
|
3133
3235
|
throw new Error("Capturing screenshots failed");
|
|
3134
3236
|
}
|
|
3135
3237
|
}),
|
|
@@ -3140,20 +3242,20 @@ var captureScreenshots_default = (ctx) => {
|
|
|
3140
3242
|
|
|
3141
3243
|
// src/commander/capture.ts
|
|
3142
3244
|
var command2 = new commander.Command();
|
|
3143
|
-
command2.name("capture").description("Capture screenshots of static sites").argument("<file>", "Web static config file").option("-C, --parallel [number]", "Specify the number of instances per browser", parseInt).option("-F, --force", "forcefully apply the specified parallel instances per browser").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(file, _,
|
|
3245
|
+
command2.name("capture").description("Capture screenshots of static sites").argument("<file>", "Web static config file").option("-C, --parallel [number]", "Specify the number of instances per browser", parseInt).option("-F, --force", "forcefully apply the specified parallel instances per browser").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(file, _, command7) {
|
|
3144
3246
|
return __async(this, null, function* () {
|
|
3145
|
-
const options =
|
|
3247
|
+
const options = command7.optsWithGlobals();
|
|
3146
3248
|
if (options.buildName === "") {
|
|
3147
3249
|
console.log(`Error: The '--buildName' option cannot be an empty string.`);
|
|
3148
3250
|
process.exit(1);
|
|
3149
3251
|
}
|
|
3150
|
-
let ctx = ctx_default(
|
|
3151
|
-
if (!
|
|
3252
|
+
let ctx = ctx_default(command7.optsWithGlobals());
|
|
3253
|
+
if (!fs6__default.default.existsSync(file)) {
|
|
3152
3254
|
ctx.log.error(`Web Static Config file ${file} not found.`);
|
|
3153
3255
|
return;
|
|
3154
3256
|
}
|
|
3155
3257
|
try {
|
|
3156
|
-
ctx.webStaticConfig = JSON.parse(
|
|
3258
|
+
ctx.webStaticConfig = JSON.parse(fs6__default.default.readFileSync(file, "utf8"));
|
|
3157
3259
|
if (!validateWebStaticConfig(ctx.webStaticConfig))
|
|
3158
3260
|
throw new Error(validateWebStaticConfig.errors[0].message);
|
|
3159
3261
|
if (ctx.webStaticConfig && ctx.webStaticConfig.length === 0) {
|
|
@@ -3195,7 +3297,7 @@ var capture_default = command2;
|
|
|
3195
3297
|
var uploadScreenshots_default = (ctx) => {
|
|
3196
3298
|
return {
|
|
3197
3299
|
title: "Uploading screenshots",
|
|
3198
|
-
task: (ctx2, task) => __async(
|
|
3300
|
+
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
3199
3301
|
try {
|
|
3200
3302
|
ctx2.task = task;
|
|
3201
3303
|
if (ctx2.options.fetchResults) {
|
|
@@ -3206,7 +3308,7 @@ var uploadScreenshots_default = (ctx) => {
|
|
|
3206
3308
|
task.title = "Screenshots uploaded successfully";
|
|
3207
3309
|
} catch (error) {
|
|
3208
3310
|
ctx2.log.debug(error);
|
|
3209
|
-
task.output =
|
|
3311
|
+
task.output = chalk__default.default.gray(`${error.message}`);
|
|
3210
3312
|
throw new Error("Uploading screenshots failed");
|
|
3211
3313
|
}
|
|
3212
3314
|
}),
|
|
@@ -3221,15 +3323,15 @@ command3.name("upload").description("Upload screenshots from given directory").a
|
|
|
3221
3323
|
return val.split(",").map((ext) => ext.trim().toLowerCase());
|
|
3222
3324
|
}).option("-E, --removeExtensions", "Strips file extensions from snapshot names").option("-i, --ignoreDir <patterns>", "Comma-separated list of directories to ignore", (val) => {
|
|
3223
3325
|
return val.split(",").map((pattern) => pattern.trim());
|
|
3224
|
-
}).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, _,
|
|
3326
|
+
}).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, _, command7) {
|
|
3225
3327
|
return __async(this, null, function* () {
|
|
3226
|
-
const options =
|
|
3328
|
+
const options = command7.optsWithGlobals();
|
|
3227
3329
|
if (options.buildName === "") {
|
|
3228
3330
|
console.log(`Error: The '--buildName' option cannot be an empty string.`);
|
|
3229
3331
|
process.exit(1);
|
|
3230
3332
|
}
|
|
3231
|
-
let ctx = ctx_default(
|
|
3232
|
-
if (!
|
|
3333
|
+
let ctx = ctx_default(command7.optsWithGlobals());
|
|
3334
|
+
if (!fs6__default.default.existsSync(directory)) {
|
|
3233
3335
|
console.log(`Error: The provided directory ${directory} not found.`);
|
|
3234
3336
|
return;
|
|
3235
3337
|
}
|
|
@@ -3267,7 +3369,7 @@ command3.name("upload").description("Upload screenshots from given directory").a
|
|
|
3267
3369
|
var upload_default = command3;
|
|
3268
3370
|
|
|
3269
3371
|
// src/lib/uploadFigmaDesigns.ts
|
|
3270
|
-
var uploadFigmaDesigns_default = (ctx) => __async(
|
|
3372
|
+
var uploadFigmaDesigns_default = (ctx) => __async(void 0, null, function* () {
|
|
3271
3373
|
const depth = ctx.figmaDesignConfig.depth;
|
|
3272
3374
|
const figmaConfigs = ctx.figmaDesignConfig.figma_config;
|
|
3273
3375
|
let results = "";
|
|
@@ -3294,7 +3396,7 @@ var uploadFigmaDesigns_default = (ctx) => __async(undefined, null, function* ()
|
|
|
3294
3396
|
var uploadFigmaDesigns_default2 = (ctx) => {
|
|
3295
3397
|
return {
|
|
3296
3398
|
title: "Uploading Figma Designs",
|
|
3297
|
-
task: (ctx2, task) => __async(
|
|
3399
|
+
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
3298
3400
|
try {
|
|
3299
3401
|
ctx2.task = task;
|
|
3300
3402
|
updateLogContext({ task: "upload-figma" });
|
|
@@ -3306,7 +3408,7 @@ var uploadFigmaDesigns_default2 = (ctx) => {
|
|
|
3306
3408
|
ctx2.log.debug(`Figma designs processed: ${results}`);
|
|
3307
3409
|
} catch (error) {
|
|
3308
3410
|
ctx2.log.debug(error);
|
|
3309
|
-
task.output =
|
|
3411
|
+
task.output = chalk__default.default.gray(`${error.message}`);
|
|
3310
3412
|
throw new Error("Uploading Figma designs failed");
|
|
3311
3413
|
}
|
|
3312
3414
|
}),
|
|
@@ -3316,13 +3418,13 @@ var uploadFigmaDesigns_default2 = (ctx) => {
|
|
|
3316
3418
|
};
|
|
3317
3419
|
|
|
3318
3420
|
// src/lib/uploadWebFigma.ts
|
|
3319
|
-
var uploadWebFigma_default = (ctx) => __async(
|
|
3421
|
+
var uploadWebFigma_default = (ctx) => __async(void 0, null, function* () {
|
|
3320
3422
|
var _a, _b;
|
|
3321
|
-
const figmaConfig = ctx.config && ((_a = ctx.config) == null ?
|
|
3322
|
-
const webConfig = ctx.config && ((_b = ctx.config) == null ?
|
|
3423
|
+
const figmaConfig = ctx.config && ((_a = ctx.config) == null ? void 0 : _a.figma) || {};
|
|
3424
|
+
const webConfig = ctx.config && ((_b = ctx.config) == null ? void 0 : _b.web) || {};
|
|
3323
3425
|
let results = "";
|
|
3324
3426
|
const buildName = ctx.options.buildName;
|
|
3325
|
-
if (figmaConfig.configs && figmaConfig.configs.length > 0) {
|
|
3427
|
+
if (figmaConfig && figmaConfig.configs && figmaConfig.configs.length > 0) {
|
|
3326
3428
|
const authToken = `Basic ${Buffer.from(`${ctx.env.LT_USERNAME}:${ctx.env.LT_ACCESS_KEY}`).toString("base64")}`;
|
|
3327
3429
|
const requestBody = {
|
|
3328
3430
|
figma_token: ctx.env.FIGMA_TOKEN,
|
|
@@ -3349,7 +3451,7 @@ var uploadWebFigma_default = (ctx) => __async(undefined, null, function* () {
|
|
|
3349
3451
|
});
|
|
3350
3452
|
|
|
3351
3453
|
// src/lib/fetchFigma.ts
|
|
3352
|
-
var fetchFigma_default = (ctx) => __async(
|
|
3454
|
+
var fetchFigma_default = (ctx) => __async(void 0, null, function* () {
|
|
3353
3455
|
const buildId = ctx.build.id;
|
|
3354
3456
|
ctx.log.debug(`Fetching figma results for buildId ${buildId}`);
|
|
3355
3457
|
const startTime = Date.now();
|
|
@@ -3394,7 +3496,7 @@ function callFetchWebFigmaRecursive(startTime, buildId, ctx) {
|
|
|
3394
3496
|
var uploadWebFigma_default2 = (ctx) => {
|
|
3395
3497
|
return {
|
|
3396
3498
|
title: "Processing Web Figma",
|
|
3397
|
-
task: (ctx2, task) => __async(
|
|
3499
|
+
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
3398
3500
|
try {
|
|
3399
3501
|
ctx2.task = task;
|
|
3400
3502
|
updateLogContext({ task: "upload-figma-web" });
|
|
@@ -3403,17 +3505,17 @@ var uploadWebFigma_default2 = (ctx) => {
|
|
|
3403
3505
|
throw new Error("Uploading Web Figma Screenshot failed");
|
|
3404
3506
|
}
|
|
3405
3507
|
if (ctx2.build.id) {
|
|
3406
|
-
task.output =
|
|
3508
|
+
task.output = chalk__default.default.gray(`Build Id: ${ctx2.build.id}`);
|
|
3407
3509
|
let figmaOutput = yield fetchFigma_default(ctx2);
|
|
3408
3510
|
const jsonObject = JSON.parse(figmaOutput);
|
|
3409
3511
|
let output = JSON.stringify(jsonObject, null, 2);
|
|
3410
|
-
task.output = task.output + "\n" +
|
|
3512
|
+
task.output = task.output + "\n" + chalk__default.default.green(`${output}`);
|
|
3411
3513
|
}
|
|
3412
3514
|
task.title = "Web Figma images uploaded successfully to SmartUI";
|
|
3413
3515
|
ctx2.log.debug(`Web Figma processed: ${results}`);
|
|
3414
3516
|
} catch (error) {
|
|
3415
3517
|
ctx2.log.debug(error);
|
|
3416
|
-
task.output =
|
|
3518
|
+
task.output = chalk__default.default.gray(`${error.message}`);
|
|
3417
3519
|
throw new Error("Uploading Web Figma Screenshots failed");
|
|
3418
3520
|
}
|
|
3419
3521
|
}),
|
|
@@ -3423,16 +3525,16 @@ var uploadWebFigma_default2 = (ctx) => {
|
|
|
3423
3525
|
};
|
|
3424
3526
|
var uploadFigma = new commander.Command();
|
|
3425
3527
|
var uploadWebFigmaCommand = new commander.Command();
|
|
3426
|
-
uploadFigma.name("upload-figma").description("Capture screenshots of static sites").argument("<file>", "figma design config file").option("--markBaseline", "Mark the uploaded images as baseline").option("--buildName <buildName>", "Name of the build").action(function(file, _,
|
|
3528
|
+
uploadFigma.name("upload-figma").description("Capture screenshots of static sites").argument("<file>", "figma design config file").option("--markBaseline", "Mark the uploaded images as baseline").option("--buildName <buildName>", "Name of the build").action(function(file, _, command7) {
|
|
3427
3529
|
return __async(this, null, function* () {
|
|
3428
3530
|
var _a, _b;
|
|
3429
|
-
let ctx = ctx_default(
|
|
3430
|
-
if (!
|
|
3531
|
+
let ctx = ctx_default(command7.optsWithGlobals());
|
|
3532
|
+
if (!fs6__default.default.existsSync(file)) {
|
|
3431
3533
|
console.log(`Error: Figma Config file ${file} not found.`);
|
|
3432
3534
|
return;
|
|
3433
3535
|
}
|
|
3434
3536
|
try {
|
|
3435
|
-
ctx.figmaDesignConfig = JSON.parse(
|
|
3537
|
+
ctx.figmaDesignConfig = JSON.parse(fs6__default.default.readFileSync(file, "utf8"));
|
|
3436
3538
|
if (!validateFigmaDesignConfig(ctx.figmaDesignConfig)) {
|
|
3437
3539
|
const validationError = (_b = (_a = validateFigmaDesignConfig.errors) == null ? void 0 : _a[0]) == null ? void 0 : _b.message;
|
|
3438
3540
|
throw new Error(validationError || "Invalid figma design Config");
|
|
@@ -3464,16 +3566,16 @@ uploadFigma.name("upload-figma").description("Capture screenshots of static site
|
|
|
3464
3566
|
}
|
|
3465
3567
|
});
|
|
3466
3568
|
});
|
|
3467
|
-
uploadWebFigmaCommand.name("upload-figma-web").description("Capture screenshots of static sites").argument("<file>", "figma config config file").option("--markBaseline", "Mark the uploaded images as baseline").option("--buildName <buildName>", "Name of the build").action(function(file, _,
|
|
3569
|
+
uploadWebFigmaCommand.name("upload-figma-web").description("Capture screenshots of static sites").argument("<file>", "figma config config file").option("--markBaseline", "Mark the uploaded images as baseline").option("--buildName <buildName>", "Name of the build").action(function(file, _, command7) {
|
|
3468
3570
|
return __async(this, null, function* () {
|
|
3469
3571
|
var _a;
|
|
3470
|
-
let ctx = ctx_default(
|
|
3471
|
-
if (!
|
|
3572
|
+
let ctx = ctx_default(command7.optsWithGlobals());
|
|
3573
|
+
if (!fs6__default.default.existsSync(file)) {
|
|
3472
3574
|
console.log(`Error: figma-web config file ${file} not found.`);
|
|
3473
3575
|
return;
|
|
3474
3576
|
}
|
|
3475
3577
|
try {
|
|
3476
|
-
ctx.config = JSON.parse(
|
|
3578
|
+
ctx.config = JSON.parse(fs6__default.default.readFileSync(file, "utf8"));
|
|
3477
3579
|
ctx.log.info(JSON.stringify(ctx.config));
|
|
3478
3580
|
if (!validateWebFigmaConfig(ctx.config)) {
|
|
3479
3581
|
ctx.log.debug(JSON.stringify(validateWebFigmaConfig.errors, null, 2));
|
|
@@ -3488,7 +3590,7 @@ uploadWebFigmaCommand.name("upload-figma-web").description("Capture screenshots
|
|
|
3488
3590
|
}
|
|
3489
3591
|
verifyFigmaWebConfig(ctx);
|
|
3490
3592
|
} catch (error) {
|
|
3491
|
-
ctx.log.error(
|
|
3593
|
+
ctx.log.error(chalk__default.default.red(`Invalid figma-web config; ${error.message}`));
|
|
3492
3594
|
return;
|
|
3493
3595
|
}
|
|
3494
3596
|
let tasks = new listr2.Listr(
|
|
@@ -3516,10 +3618,112 @@ uploadWebFigmaCommand.name("upload-figma-web").description("Capture screenshots
|
|
|
3516
3618
|
}
|
|
3517
3619
|
});
|
|
3518
3620
|
});
|
|
3621
|
+
var command4 = new commander.Command();
|
|
3622
|
+
command4.name("exec:start").description("Start SmartUI server").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").action(function() {
|
|
3623
|
+
return __async(this, null, function* () {
|
|
3624
|
+
const options = command4.optsWithGlobals();
|
|
3625
|
+
if (options.buildName === "") {
|
|
3626
|
+
console.log(`Error: The '--buildName' option cannot be an empty string.`);
|
|
3627
|
+
process.exit(1);
|
|
3628
|
+
}
|
|
3629
|
+
let ctx = ctx_default(command4.optsWithGlobals());
|
|
3630
|
+
ctx.snapshotQueue = new Queue(ctx);
|
|
3631
|
+
ctx.totalSnapshots = 0;
|
|
3632
|
+
ctx.isStartExec = true;
|
|
3633
|
+
let tasks = new listr2.Listr(
|
|
3634
|
+
[
|
|
3635
|
+
auth_default(),
|
|
3636
|
+
startServer_default(),
|
|
3637
|
+
getGitInfo_default(),
|
|
3638
|
+
createBuild_default()
|
|
3639
|
+
],
|
|
3640
|
+
{
|
|
3641
|
+
rendererOptions: {
|
|
3642
|
+
icon: {
|
|
3643
|
+
[listr2.ListrDefaultRendererLogLevels.OUTPUT]: `\u2192`
|
|
3644
|
+
},
|
|
3645
|
+
color: {
|
|
3646
|
+
[listr2.ListrDefaultRendererLogLevels.OUTPUT]: listr2.color.gray
|
|
3647
|
+
}
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
);
|
|
3651
|
+
try {
|
|
3652
|
+
yield tasks.run(ctx);
|
|
3653
|
+
startPingPolling(ctx);
|
|
3654
|
+
if (ctx.options.fetchResults) {
|
|
3655
|
+
startPolling(ctx);
|
|
3656
|
+
}
|
|
3657
|
+
} catch (error) {
|
|
3658
|
+
console.error("Error during server execution:", error);
|
|
3659
|
+
}
|
|
3660
|
+
});
|
|
3661
|
+
});
|
|
3662
|
+
var server_default2 = command4;
|
|
3663
|
+
var command5 = new commander.Command();
|
|
3664
|
+
function getSmartUIServerAddress() {
|
|
3665
|
+
const serverAddress = process.env.SMARTUI_SERVER_ADDRESS || "http://localhost:49152";
|
|
3666
|
+
return serverAddress;
|
|
3667
|
+
}
|
|
3668
|
+
command5.name("exec:stop").description("Stop the SmartUI server").action(function() {
|
|
3669
|
+
return __async(this, null, function* () {
|
|
3670
|
+
try {
|
|
3671
|
+
const serverAddress = getSmartUIServerAddress();
|
|
3672
|
+
console.log(chalk__default.default.yellow(`Stopping server at ${serverAddress} from terminal...`));
|
|
3673
|
+
const response = yield axios__default.default.post(`${serverAddress}/stop`, { timeout: 15e3 }, {
|
|
3674
|
+
headers: {
|
|
3675
|
+
"Content-Type": "application/json"
|
|
3676
|
+
// Ensure the correct Content-Type header
|
|
3677
|
+
}
|
|
3678
|
+
});
|
|
3679
|
+
if (response.status === 200) {
|
|
3680
|
+
console.log(chalk__default.default.green("Server stopped successfully"));
|
|
3681
|
+
console.log(chalk__default.default.green(`Response: ${JSON.stringify(response.data)}`));
|
|
3682
|
+
} else {
|
|
3683
|
+
console.log(chalk__default.default.red("Failed to stop server"));
|
|
3684
|
+
}
|
|
3685
|
+
} catch (error) {
|
|
3686
|
+
if (error.code === "ECONNABORTED") {
|
|
3687
|
+
console.error(chalk__default.default.red("Error: SmartUI server did not respond in 15 seconds"));
|
|
3688
|
+
} else {
|
|
3689
|
+
console.error(chalk__default.default.red("Error while stopping server"));
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3692
|
+
});
|
|
3693
|
+
});
|
|
3694
|
+
var stopServer_default = command5;
|
|
3695
|
+
function getSmartUIServerAddress2() {
|
|
3696
|
+
const serverAddress = process.env.SMARTUI_SERVER_ADDRESS || "http://localhost:49152";
|
|
3697
|
+
return serverAddress;
|
|
3698
|
+
}
|
|
3699
|
+
var command6 = new commander.Command();
|
|
3700
|
+
command6.name("exec:ping").description("Ping the SmartUI server to check if it is running").action(function() {
|
|
3701
|
+
return __async(this, null, function* () {
|
|
3702
|
+
try {
|
|
3703
|
+
console.log(chalk__default.default.yellow("Pinging server..."));
|
|
3704
|
+
const serverAddress = getSmartUIServerAddress2();
|
|
3705
|
+
console.log(chalk__default.default.yellow(`Pinging server at ${serverAddress} from terminal...`));
|
|
3706
|
+
const response = yield axios__default.default.get(`${serverAddress}/ping`, { timeout: 15e3 });
|
|
3707
|
+
if (response.status === 200) {
|
|
3708
|
+
console.log(chalk__default.default.green("SmartUI Server is running"));
|
|
3709
|
+
console.log(chalk__default.default.green(`Response: ${JSON.stringify(response.data)}`));
|
|
3710
|
+
} else {
|
|
3711
|
+
console.log(chalk__default.default.red("Failed to reach the server"));
|
|
3712
|
+
}
|
|
3713
|
+
} catch (error) {
|
|
3714
|
+
if (error.code === "ECONNABORTED") {
|
|
3715
|
+
console.error(chalk__default.default.red("Error: SmartUI server did not respond in 15 seconds"));
|
|
3716
|
+
} else {
|
|
3717
|
+
console.error(chalk__default.default.red("SmartUI server is not running"));
|
|
3718
|
+
}
|
|
3719
|
+
}
|
|
3720
|
+
});
|
|
3721
|
+
});
|
|
3722
|
+
var ping_default = command6;
|
|
3519
3723
|
|
|
3520
3724
|
// src/commander/commander.ts
|
|
3521
3725
|
var program = new commander.Command();
|
|
3522
|
-
program.name("smartui").description("CLI to help you run your SmartUI tests on LambdaTest platform").version(`v${version}`).option("-c --config <filepath>", "Config file path").addCommand(exec_default2).addCommand(capture_default).addCommand(configWeb).addCommand(configStatic).addCommand(upload_default).addCommand(configFigma).addCommand(uploadFigma).addCommand(configWebFigma).addCommand(uploadWebFigmaCommand);
|
|
3726
|
+
program.name("smartui").description("CLI to help you run your SmartUI tests on LambdaTest platform").version(`v${version}`).option("-c --config <filepath>", "Config file path").addCommand(exec_default2).addCommand(capture_default).addCommand(configWeb).addCommand(configStatic).addCommand(upload_default).addCommand(server_default2).addCommand(stopServer_default).addCommand(ping_default).addCommand(configFigma).addCommand(uploadFigma).addCommand(configWebFigma).addCommand(uploadWebFigmaCommand);
|
|
3523
3727
|
var commander_default = program;
|
|
3524
3728
|
(function() {
|
|
3525
3729
|
return __async(this, null, function* () {
|
|
@@ -3529,16 +3733,16 @@ var commander_default = program;
|
|
|
3529
3733
|
let { data: { latestVersion, deprecated, additionalDescription } } = yield client.checkUpdate(log2);
|
|
3530
3734
|
log2.info(`
|
|
3531
3735
|
LambdaTest SmartUI CLI v${package_default.version}`);
|
|
3532
|
-
log2.info(
|
|
3736
|
+
log2.info(chalk__default.default.yellow(`${additionalDescription}`));
|
|
3533
3737
|
if (deprecated) {
|
|
3534
3738
|
log2.warn(`This version is deprecated. A new version ${latestVersion} is available!`);
|
|
3535
3739
|
} else if (package_default.version !== latestVersion) {
|
|
3536
|
-
log2.info(
|
|
3740
|
+
log2.info(chalk__default.default.green(`A new version ${latestVersion} is available!`));
|
|
3537
3741
|
} else
|
|
3538
|
-
log2.info(
|
|
3742
|
+
log2.info(chalk__default.default.gray("https://www.npmjs.com/package/@lambdatest/smartui-cli\n"));
|
|
3539
3743
|
} catch (error) {
|
|
3540
3744
|
log2.debug(error);
|
|
3541
|
-
log2.info(
|
|
3745
|
+
log2.info(chalk__default.default.gray("https://www.npmjs.com/package/@lambdatest/smartui-cli\n"));
|
|
3542
3746
|
}
|
|
3543
3747
|
commander_default.parse();
|
|
3544
3748
|
});
|