@lambdatest/smartui-cli 2.0.9 → 3.0.1
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 +696 -264
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
var commander = require('commander');
|
|
5
5
|
var which = require('which');
|
|
6
6
|
var listr2 = require('listr2');
|
|
7
|
-
var
|
|
7
|
+
var chalk8 = require('chalk');
|
|
8
8
|
var path2 = require('path');
|
|
9
9
|
var fastify = require('fastify');
|
|
10
|
-
var
|
|
10
|
+
var fs4 = require('fs');
|
|
11
11
|
var test = require('@playwright/test');
|
|
12
12
|
var Ajv = require('ajv');
|
|
13
13
|
var addErrors = require('ajv-errors');
|
|
@@ -20,10 +20,10 @@ var spawn = require('cross-spawn');
|
|
|
20
20
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
21
21
|
|
|
22
22
|
var which__default = /*#__PURE__*/_interopDefault(which);
|
|
23
|
-
var
|
|
23
|
+
var chalk8__default = /*#__PURE__*/_interopDefault(chalk8);
|
|
24
24
|
var path2__default = /*#__PURE__*/_interopDefault(path2);
|
|
25
25
|
var fastify__default = /*#__PURE__*/_interopDefault(fastify);
|
|
26
|
-
var
|
|
26
|
+
var fs4__default = /*#__PURE__*/_interopDefault(fs4);
|
|
27
27
|
var Ajv__default = /*#__PURE__*/_interopDefault(Ajv);
|
|
28
28
|
var addErrors__default = /*#__PURE__*/_interopDefault(addErrors);
|
|
29
29
|
var FormData__default = /*#__PURE__*/_interopDefault(FormData);
|
|
@@ -66,9 +66,241 @@ var __async = (__this, __arguments, generator) => {
|
|
|
66
66
|
step((generator = generator.apply(__this, __arguments)).next());
|
|
67
67
|
});
|
|
68
68
|
};
|
|
69
|
+
|
|
70
|
+
// src/lib/constants.ts
|
|
71
|
+
var constants_default = {
|
|
72
|
+
// default configs
|
|
73
|
+
DEFAULT_CONFIG: {
|
|
74
|
+
web: {
|
|
75
|
+
browsers: [
|
|
76
|
+
"chrome",
|
|
77
|
+
"firefox",
|
|
78
|
+
"safari",
|
|
79
|
+
"edge"
|
|
80
|
+
],
|
|
81
|
+
viewports: [
|
|
82
|
+
[1920],
|
|
83
|
+
[1366],
|
|
84
|
+
[1028]
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
mobile: {
|
|
88
|
+
devices: [
|
|
89
|
+
"iPhone 14",
|
|
90
|
+
"Galaxy S24"
|
|
91
|
+
],
|
|
92
|
+
fullPage: true,
|
|
93
|
+
orientation: "portrait"
|
|
94
|
+
},
|
|
95
|
+
waitForTimeout: 1e3,
|
|
96
|
+
enableJavaScript: false,
|
|
97
|
+
allowedHostnames: []
|
|
98
|
+
},
|
|
99
|
+
DEFAULT_WEB_STATIC_CONFIG: [
|
|
100
|
+
{
|
|
101
|
+
"name": "lambdatest-home-page",
|
|
102
|
+
"url": "https://www.lambdatest.com",
|
|
103
|
+
"waitForTimeout": 1e3
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "example-page",
|
|
107
|
+
"url": "https://example.com/"
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
// browsers
|
|
111
|
+
CHROME: "chrome",
|
|
112
|
+
SAFARI: "safari",
|
|
113
|
+
FIREFOX: "firefox",
|
|
114
|
+
EDGE: "edge",
|
|
115
|
+
EDGE_CHANNEL: "msedge",
|
|
116
|
+
WEBKIT: "webkit",
|
|
117
|
+
// viewports
|
|
118
|
+
MIN_VIEWPORT_HEIGHT: 1080,
|
|
119
|
+
// mobile
|
|
120
|
+
MOBILE_OS_ANDROID: "android",
|
|
121
|
+
MOBILE_OS_IOS: "ios",
|
|
122
|
+
MOBILE_ORIENTATION_PORTRAIT: "portrait",
|
|
123
|
+
MOBILE_ORIENTATION_LANDSCAPE: "landscape",
|
|
124
|
+
// CI
|
|
125
|
+
GITHUB_API_HOST: "https://api.github.com",
|
|
126
|
+
SUPPORTED_MOBILE_DEVICES: {
|
|
127
|
+
"Blackberry KEY2 LE": { os: "android", viewport: { width: 412, height: 618 } },
|
|
128
|
+
"Galaxy A12": { os: "android", viewport: { width: 360, height: 800 } },
|
|
129
|
+
"Galaxy A21s": { os: "android", viewport: { width: 412, height: 915 } },
|
|
130
|
+
"Galaxy A22": { os: "android", viewport: { width: 358, height: 857 } },
|
|
131
|
+
"Galaxy A31": { os: "android", viewport: { width: 412, height: 915 } },
|
|
132
|
+
"Galaxy A32": { os: "android", viewport: { width: 412, height: 915 } },
|
|
133
|
+
"Galaxy A51": { os: "android", viewport: { width: 412, height: 915 } },
|
|
134
|
+
"Galaxy A7": { os: "android", viewport: { width: 412, height: 846 } },
|
|
135
|
+
"Galaxy A70": { os: "android", viewport: { width: 412, height: 915 } },
|
|
136
|
+
"Galaxy A8": { os: "android", viewport: { width: 360, height: 740 } },
|
|
137
|
+
"Galaxy A8 Plus": { os: "android", viewport: { width: 412, height: 846 } },
|
|
138
|
+
"Galaxy J7 Prime": { os: "android", viewport: { width: 360, height: 640 } },
|
|
139
|
+
"Galaxy M12": { os: "android", viewport: { width: 412, height: 915 } },
|
|
140
|
+
"Galaxy M31": { os: "android", viewport: { width: 412, height: 892 } },
|
|
141
|
+
"Galaxy Note10": { os: "android", viewport: { width: 412, height: 869 } },
|
|
142
|
+
"Galaxy Note10 Plus": { os: "android", viewport: { width: 412, height: 869 } },
|
|
143
|
+
"Galaxy Note20": { os: "android", viewport: { width: 412, height: 915 } },
|
|
144
|
+
"Galaxy Note20 Ultra": { os: "android", viewport: { width: 412, height: 869 } },
|
|
145
|
+
"Galaxy S10": { os: "android", viewport: { width: 360, height: 760 } },
|
|
146
|
+
"Galaxy S10 Plus": { os: "android", viewport: { width: 412, height: 869 } },
|
|
147
|
+
"Galaxy S10e": { os: "android", viewport: { width: 412, height: 740 } },
|
|
148
|
+
"Galaxy S20": { os: "android", viewport: { width: 360, height: 800 } },
|
|
149
|
+
"Galaxy S20 FE": { os: "android", viewport: { width: 412, height: 914 } },
|
|
150
|
+
"Galaxy S20 Ultra": { os: "android", viewport: { width: 412, height: 915 } },
|
|
151
|
+
"Galaxy S20 Plus": { os: "android", viewport: { width: 384, height: 854 } },
|
|
152
|
+
"Galaxy S21": { os: "android", viewport: { width: 360, height: 800 } },
|
|
153
|
+
"Galaxy S21 FE": { os: "android", viewport: { width: 360, height: 780 } },
|
|
154
|
+
"Galaxy S21 Ultra": { os: "android", viewport: { width: 384, height: 854 } },
|
|
155
|
+
"Galaxy S21 Plus": { os: "android", viewport: { width: 360, height: 800 } },
|
|
156
|
+
"Galaxy S22": { os: "android", viewport: { width: 360, height: 780 } },
|
|
157
|
+
"Galaxy S22 Ultra": { os: "android", viewport: { width: 384, height: 854 } },
|
|
158
|
+
"Galaxy S23": { os: "android", viewport: { width: 360, height: 645 } },
|
|
159
|
+
"Galaxy S23 Plus": { os: "android", viewport: { width: 360, height: 648 } },
|
|
160
|
+
"Galaxy S23 Ultra": { os: "android", viewport: { width: 384, height: 689 } },
|
|
161
|
+
"Galaxy S24": { os: "android", viewport: { width: 360, height: 780 } },
|
|
162
|
+
"Galaxy S24 Plus": { os: "android", viewport: { width: 384, height: 832 } },
|
|
163
|
+
"Galaxy S24 Ultra": { os: "android", viewport: { width: 384, height: 832 } },
|
|
164
|
+
"Galaxy S7": { os: "android", viewport: { width: 360, height: 640 } },
|
|
165
|
+
"Galaxy S7 Edge": { os: "android", viewport: { width: 360, height: 640 } },
|
|
166
|
+
"Galaxy S8": { os: "android", viewport: { width: 360, height: 740 } },
|
|
167
|
+
"Galaxy S8 Plus": { os: "android", viewport: { width: 360, height: 740 } },
|
|
168
|
+
"Galaxy S9": { os: "android", viewport: { width: 360, height: 740 } },
|
|
169
|
+
"Galaxy S9 Plus": { os: "android", viewport: { width: 360, height: 740 } },
|
|
170
|
+
"Galaxy Tab A7 Lite": { os: "android", viewport: { width: 534, height: 894 } },
|
|
171
|
+
"Galaxy Tab A8": { os: "android", viewport: { width: 800, height: 1280 } },
|
|
172
|
+
"Galaxy Tab S3": { os: "android", viewport: { width: 1024, height: 768 } },
|
|
173
|
+
"Galaxy Tab S4": { os: "android", viewport: { width: 712, height: 1138 } },
|
|
174
|
+
"Galaxy Tab S7": { os: "android", viewport: { width: 800, height: 1192 } },
|
|
175
|
+
"Galaxy Tab S8": { os: "android", viewport: { width: 753, height: 1205 } },
|
|
176
|
+
"Galaxy Tab S8 Plus": { os: "android", viewport: { width: 825, height: 1318 } },
|
|
177
|
+
"Huawei Mate 20 Pro": { os: "android", viewport: { width: 360, height: 780 } },
|
|
178
|
+
"Huawei P20 Pro": { os: "android", viewport: { width: 360, height: 747 } },
|
|
179
|
+
"Huawei P30": { os: "android", viewport: { width: 360, height: 780 } },
|
|
180
|
+
"Huawei P30 Pro": { os: "android", viewport: { width: 360, height: 780 } },
|
|
181
|
+
"Microsoft Surface Duo": { os: "android", viewport: { width: 1114, height: 705 } },
|
|
182
|
+
"Moto G7 Play": { os: "android", viewport: { width: 360, height: 760 } },
|
|
183
|
+
"Moto G9 Play": { os: "android", viewport: { width: 393, height: 786 } },
|
|
184
|
+
"Moto G Stylus (2022)": { os: "android", viewport: { width: 432, height: 984 } },
|
|
185
|
+
"Nexus 5": { os: "android", viewport: { width: 360, height: 640 } },
|
|
186
|
+
"Nexus 5X": { os: "android", viewport: { width: 412, height: 732 } },
|
|
187
|
+
"Nokia 5": { os: "android", viewport: { width: 360, height: 640 } },
|
|
188
|
+
"Nothing Phone (1)": { os: "android", viewport: { width: 412, height: 915 } },
|
|
189
|
+
"OnePlus 10 Pro": { os: "android", viewport: { width: 412, height: 919 } },
|
|
190
|
+
"OnePlus 11": { os: "android", viewport: { width: 360, height: 804 } },
|
|
191
|
+
"OnePlus 6": { os: "android", viewport: { width: 412, height: 869 } },
|
|
192
|
+
"OnePlus 6T": { os: "android", viewport: { width: 412, height: 892 } },
|
|
193
|
+
"OnePlus 7": { os: "android", viewport: { width: 412, height: 892 } },
|
|
194
|
+
"OnePlus 7T": { os: "android", viewport: { width: 412, height: 914 } },
|
|
195
|
+
"OnePlus 8": { os: "android", viewport: { width: 412, height: 915 } },
|
|
196
|
+
"OnePlus 9": { os: "android", viewport: { width: 411, height: 915 } },
|
|
197
|
+
"OnePlus 9 Pro": { os: "android", viewport: { width: 412, height: 919 } },
|
|
198
|
+
"OnePlus Nord": { os: "android", viewport: { width: 412, height: 914 } },
|
|
199
|
+
"OnePlus Nord 2": { os: "android", viewport: { width: 412, height: 915 } },
|
|
200
|
+
"OnePlus Nord CE": { os: "android", viewport: { width: 412, height: 915 } },
|
|
201
|
+
"Oppo A12": { os: "android", viewport: { width: 360, height: 760 } },
|
|
202
|
+
"Oppo A15": { os: "android", viewport: { width: 360, height: 800 } },
|
|
203
|
+
"Oppo A54": { os: "android", viewport: { width: 360, height: 800 } },
|
|
204
|
+
"Oppo A5s": { os: "android", viewport: { width: 360, height: 760 } },
|
|
205
|
+
"Oppo F17": { os: "android", viewport: { width: 360, height: 800 } },
|
|
206
|
+
"Oppo K10": { os: "android", viewport: { width: 360, height: 804 } },
|
|
207
|
+
"Pixel 3": { os: "android", viewport: { width: 412, height: 823 } },
|
|
208
|
+
"Pixel 3 XL": { os: "android", viewport: { width: 412, height: 846 } },
|
|
209
|
+
"Pixel 3a": { os: "android", viewport: { width: 412, height: 823 } },
|
|
210
|
+
"Pixel 4": { os: "android", viewport: { width: 392, height: 830 } },
|
|
211
|
+
"Pixel 4 XL": { os: "android", viewport: { width: 412, height: 823 } },
|
|
212
|
+
"Pixel 4a": { os: "android", viewport: { width: 393, height: 851 } },
|
|
213
|
+
"Pixel 5": { os: "android", viewport: { width: 393, height: 851 } },
|
|
214
|
+
"Pixel 6": { os: "android", viewport: { width: 393, height: 786 } },
|
|
215
|
+
"Pixel 6 Pro": { os: "android", viewport: { width: 412, height: 892 } },
|
|
216
|
+
"Pixel 7": { os: "android", viewport: { width: 412, height: 915 } },
|
|
217
|
+
"Pixel 7 Pro": { os: "android", viewport: { width: 412, height: 892 } },
|
|
218
|
+
"Pixel 8": { os: "android", viewport: { width: 412, height: 915 } },
|
|
219
|
+
"Pixel 8 Pro": { os: "android", viewport: { width: 448, height: 998 } },
|
|
220
|
+
"Poco M2 Pro": { os: "android", viewport: { width: 393, height: 873 } },
|
|
221
|
+
"POCO X3 Pro": { os: "android", viewport: { width: 393, height: 873 } },
|
|
222
|
+
"Realme 5i": { os: "android", viewport: { width: 360, height: 800 } },
|
|
223
|
+
"Realme 7i": { os: "android", viewport: { width: 360, height: 800 } },
|
|
224
|
+
"Realme 8i": { os: "android", viewport: { width: 360, height: 804 } },
|
|
225
|
+
"Realme C21Y": { os: "android", viewport: { width: 360, height: 800 } },
|
|
226
|
+
"Realme C21": { os: "android", viewport: { width: 360, height: 800 } },
|
|
227
|
+
"Realme GT2 Pro": { os: "android", viewport: { width: 360, height: 804 } },
|
|
228
|
+
"Redmi 8": { os: "android", viewport: { width: 360, height: 760 } },
|
|
229
|
+
"Redmi 9": { os: "android", viewport: { width: 360, height: 800 } },
|
|
230
|
+
"Redmi 9C": { os: "android", viewport: { width: 360, height: 800 } },
|
|
231
|
+
"Redmi Note 10 Pro": { os: "android", viewport: { width: 393, height: 873 } },
|
|
232
|
+
"Redmi Note 8": { os: "android", viewport: { width: 393, height: 851 } },
|
|
233
|
+
"Redmi Note 8 Pro": { os: "android", viewport: { width: 393, height: 851 } },
|
|
234
|
+
"Redmi Note 9": { os: "android", viewport: { width: 393, height: 851 } },
|
|
235
|
+
"Redmi Note 9 Pro Max": { os: "android", viewport: { width: 393, height: 873 } },
|
|
236
|
+
"Redmi Y2": { os: "android", viewport: { width: 360, height: 720 } },
|
|
237
|
+
"Tecno Spark 7": { os: "android", viewport: { width: 360, height: 800 } },
|
|
238
|
+
"Vivo Y22": { os: "android", viewport: { width: 385, height: 860 } },
|
|
239
|
+
"Vivo T1": { os: "android", viewport: { width: 393, height: 873 } },
|
|
240
|
+
"Vivo V7": { os: "android", viewport: { width: 360, height: 720 } },
|
|
241
|
+
"Vivo Y11": { os: "android", viewport: { width: 360, height: 722 } },
|
|
242
|
+
"Vivo Y12": { os: "android", viewport: { width: 360, height: 722 } },
|
|
243
|
+
"Vivo Y20g": { os: "android", viewport: { width: 385, height: 854 } },
|
|
244
|
+
"Vivo Y50": { os: "android", viewport: { width: 393, height: 786 } },
|
|
245
|
+
"Xiaomi 12 Pro": { os: "android", viewport: { width: 412, height: 915 } },
|
|
246
|
+
"Xperia Z5": { os: "android", viewport: { width: 360, height: 640 } },
|
|
247
|
+
"Xperia Z5 Dual": { os: "android", viewport: { width: 360, height: 640 } },
|
|
248
|
+
"Zenfone 6": { os: "android", viewport: { width: 412, height: 892 } },
|
|
249
|
+
"iPad 10.2 (2019)": { os: "ios", viewport: { width: 810, height: 1080 } },
|
|
250
|
+
"iPad 10.2 (2020)": { os: "ios", viewport: { width: 834, height: 1194 } },
|
|
251
|
+
"iPad 10.2 (2021)": { os: "ios", viewport: { width: 810, height: 1080 } },
|
|
252
|
+
"iPad 9.7 (2017)": { os: "ios", viewport: { width: 768, height: 1024 } },
|
|
253
|
+
"iPad Air (2019)": { os: "ios", viewport: { width: 834, height: 1112 } },
|
|
254
|
+
"iPad Air (2020)": { os: "ios", viewport: { width: 820, height: 1180 } },
|
|
255
|
+
"iPad Air (2022)": { os: "ios", viewport: { width: 820, height: 1180 } },
|
|
256
|
+
"iPad mini (2019)": { os: "ios", viewport: { width: 768, height: 1024 } },
|
|
257
|
+
"iPad mini (2021)": { os: "ios", viewport: { width: 744, height: 1133 } },
|
|
258
|
+
"iPad Pro 11 (2021)": { os: "ios", viewport: { width: 834, height: 1194 } },
|
|
259
|
+
"iPad Pro 11 (2022)": { os: "ios", viewport: { width: 834, height: 1194 } },
|
|
260
|
+
"iPad Pro 12.9 (2018)": { os: "ios", viewport: { width: 1024, height: 1366 } },
|
|
261
|
+
"iPad Pro 12.9 (2020)": { os: "ios", viewport: { width: 1024, height: 1366 } },
|
|
262
|
+
"iPad Pro 12.9 (2021)": { os: "ios", viewport: { width: 1024, height: 1366 } },
|
|
263
|
+
"iPad Pro 12.9 (2022)": { os: "ios", viewport: { width: 1024, height: 1366 } },
|
|
264
|
+
"iPhone 11": { os: "ios", viewport: { width: 375, height: 812 } },
|
|
265
|
+
"iPhone 11 Pro": { os: "ios", viewport: { width: 375, height: 812 } },
|
|
266
|
+
"iPhone 11 Pro Max": { os: "ios", viewport: { width: 414, height: 896 } },
|
|
267
|
+
"iPhone 12": { os: "ios", viewport: { width: 390, height: 844 } },
|
|
268
|
+
"iPhone 12 Mini": { os: "ios", viewport: { width: 375, height: 812 } },
|
|
269
|
+
"iPhone 12 Pro": { os: "ios", viewport: { width: 390, height: 844 } },
|
|
270
|
+
"iPhone 12 Pro Max": { os: "ios", viewport: { width: 428, height: 926 } },
|
|
271
|
+
"iPhone 13": { os: "ios", viewport: { width: 390, height: 844 } },
|
|
272
|
+
"iPhone 13 Mini": { os: "ios", viewport: { width: 390, height: 844 } },
|
|
273
|
+
"iPhone 13 Pro": { os: "ios", viewport: { width: 390, height: 844 } },
|
|
274
|
+
"iPhone 13 Pro Max": { os: "ios", viewport: { width: 428, height: 926 } },
|
|
275
|
+
"iPhone 14": { os: "ios", viewport: { width: 390, height: 844 } },
|
|
276
|
+
"iPhone 14 Plus": { os: "ios", viewport: { width: 428, height: 926 } },
|
|
277
|
+
"iPhone 14 Pro": { os: "ios", viewport: { width: 390, height: 844 } },
|
|
278
|
+
"iPhone 14 Pro Max": { os: "ios", viewport: { width: 428, height: 928 } },
|
|
279
|
+
"iPhone 15": { os: "ios", viewport: { width: 393, height: 852 } },
|
|
280
|
+
"iPhone 15 Plus": { os: "ios", viewport: { width: 430, height: 932 } },
|
|
281
|
+
"iPhone 15 Pro": { os: "ios", viewport: { width: 393, height: 852 } },
|
|
282
|
+
"iPhone 15 Pro Max": { os: "ios", viewport: { width: 430, height: 932 } },
|
|
283
|
+
"iPhone 6": { os: "ios", viewport: { width: 375, height: 667 } },
|
|
284
|
+
"iPhone 6s": { os: "ios", viewport: { width: 375, height: 667 } },
|
|
285
|
+
"iPhone 6s Plus": { os: "ios", viewport: { width: 414, height: 736 } },
|
|
286
|
+
"iPhone 7": { os: "ios", viewport: { width: 375, height: 667 } },
|
|
287
|
+
"iPhone 7 Plus": { os: "ios", viewport: { width: 414, height: 736 } },
|
|
288
|
+
"iPhone 8": { os: "ios", viewport: { width: 375, height: 667 } },
|
|
289
|
+
"iPhone 8 Plus": { os: "ios", viewport: { width: 414, height: 736 } },
|
|
290
|
+
"iPhone SE (2016)": { os: "ios", viewport: { width: 320, height: 568 } },
|
|
291
|
+
"iPhone SE (2020)": { os: "ios", viewport: { width: 375, height: 667 } },
|
|
292
|
+
"iPhone SE (2022)": { os: "ios", viewport: { width: 375, height: 667 } },
|
|
293
|
+
"iPhone X": { os: "ios", viewport: { width: 375, height: 812 } },
|
|
294
|
+
"iPhone XR": { os: "ios", viewport: { width: 414, height: 896 } },
|
|
295
|
+
"iPhone XS": { os: "ios", viewport: { width: 375, height: 812 } },
|
|
296
|
+
"iPhone XS Max": { os: "ios", viewport: { width: 414, height: 896 } }
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
// src/lib/utils.ts
|
|
69
301
|
function delDir(dir) {
|
|
70
|
-
if (
|
|
71
|
-
|
|
302
|
+
if (fs4__default.default.existsSync(dir)) {
|
|
303
|
+
fs4__default.default.rmSync(dir, { recursive: true });
|
|
72
304
|
}
|
|
73
305
|
}
|
|
74
306
|
function scrollToBottomAndBackToTop({
|
|
@@ -97,9 +329,93 @@ function scrollToBottomAndBackToTop({
|
|
|
97
329
|
})();
|
|
98
330
|
});
|
|
99
331
|
}
|
|
332
|
+
function launchBrowsers(ctx) {
|
|
333
|
+
return __async(this, null, function* () {
|
|
334
|
+
let browsers = {};
|
|
335
|
+
let launchOptions = { headless: true };
|
|
336
|
+
if (ctx.config.web) {
|
|
337
|
+
for (const browser of ctx.config.web.browsers) {
|
|
338
|
+
switch (browser) {
|
|
339
|
+
case constants_default.CHROME:
|
|
340
|
+
browsers[constants_default.CHROME] = yield test.chromium.launch(launchOptions);
|
|
341
|
+
break;
|
|
342
|
+
case constants_default.SAFARI:
|
|
343
|
+
browsers[constants_default.SAFARI] = yield test.webkit.launch(launchOptions);
|
|
344
|
+
break;
|
|
345
|
+
case constants_default.FIREFOX:
|
|
346
|
+
browsers[constants_default.FIREFOX] = yield test.firefox.launch(launchOptions);
|
|
347
|
+
break;
|
|
348
|
+
case constants_default.EDGE:
|
|
349
|
+
browsers[constants_default.EDGE] = yield test.chromium.launch(__spreadValues({ channel: constants_default.EDGE_CHANNEL }, launchOptions));
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (ctx.config.mobile) {
|
|
355
|
+
for (const device of ctx.config.mobile.devices) {
|
|
356
|
+
if (constants_default.SUPPORTED_MOBILE_DEVICES[device].os === "android" && !browsers[constants_default.CHROME])
|
|
357
|
+
browsers[constants_default.CHROME] = yield test.chromium.launch(launchOptions);
|
|
358
|
+
else if (constants_default.SUPPORTED_MOBILE_DEVICES[device].os === "ios" && !browsers[constants_default.SAFARI])
|
|
359
|
+
browsers[constants_default.SAFARI] = yield test.webkit.launch(launchOptions);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return browsers;
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
function closeBrowsers(browsers) {
|
|
366
|
+
return __async(this, null, function* () {
|
|
367
|
+
var _a;
|
|
368
|
+
for (const browserName of Object.keys(browsers))
|
|
369
|
+
yield (_a = browsers[browserName]) == null ? void 0 : _a.close();
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
function getWebRenderViewports(ctx) {
|
|
373
|
+
let webRenderViewports = [];
|
|
374
|
+
if (ctx.config.web) {
|
|
375
|
+
for (const viewport of ctx.config.web.viewports) {
|
|
376
|
+
webRenderViewports.push({
|
|
377
|
+
viewport,
|
|
378
|
+
viewportString: `${viewport.width}${viewport.height ? "x" + viewport.height : ""}`,
|
|
379
|
+
fullPage: viewport.height ? false : true,
|
|
380
|
+
device: false
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return webRenderViewports;
|
|
385
|
+
}
|
|
386
|
+
function getMobileRenderViewports(ctx) {
|
|
387
|
+
var _a;
|
|
388
|
+
let mobileRenderViewports = {};
|
|
389
|
+
mobileRenderViewports[constants_default.MOBILE_OS_IOS] = [];
|
|
390
|
+
mobileRenderViewports[constants_default.MOBILE_OS_ANDROID] = [];
|
|
391
|
+
if (ctx.config.mobile) {
|
|
392
|
+
for (const device of ctx.config.mobile.devices) {
|
|
393
|
+
let os = constants_default.SUPPORTED_MOBILE_DEVICES[device].os;
|
|
394
|
+
let { width, height } = constants_default.SUPPORTED_MOBILE_DEVICES[device].viewport;
|
|
395
|
+
let portrait = ctx.config.mobile.orientation === constants_default.MOBILE_ORIENTATION_PORTRAIT ? true : false;
|
|
396
|
+
(_a = mobileRenderViewports[os]) == null ? void 0 : _a.push({
|
|
397
|
+
viewport: { width: portrait ? width : height, height: portrait ? height : width },
|
|
398
|
+
viewportString: `${device} (${ctx.config.mobile.orientation})`,
|
|
399
|
+
fullPage: ctx.config.mobile.fullPage,
|
|
400
|
+
device: true,
|
|
401
|
+
os
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return mobileRenderViewports;
|
|
406
|
+
}
|
|
407
|
+
function getRenderViewports(ctx) {
|
|
408
|
+
let mobileRenderViewports = getMobileRenderViewports(ctx);
|
|
409
|
+
return [
|
|
410
|
+
...getWebRenderViewports(ctx),
|
|
411
|
+
...mobileRenderViewports[constants_default.MOBILE_OS_IOS],
|
|
412
|
+
...mobileRenderViewports[constants_default.MOBILE_OS_ANDROID]
|
|
413
|
+
];
|
|
414
|
+
}
|
|
100
415
|
var MAX_RESOURCE_SIZE = 5 * 1024 ** 2;
|
|
101
416
|
var ALLOWED_RESOURCES = ["document", "stylesheet", "image", "media", "font", "other"];
|
|
102
417
|
var ALLOWED_STATUSES = [200, 201];
|
|
418
|
+
var REQUEST_TIMEOUT = 1e4;
|
|
103
419
|
var MIN_VIEWPORT_HEIGHT = 1080;
|
|
104
420
|
var processSnapshot_default = (snapshot, ctx) => __async(void 0, null, function* () {
|
|
105
421
|
ctx.log.debug(`Processing snapshot ${snapshot.name}`);
|
|
@@ -110,13 +426,13 @@ var processSnapshot_default = (snapshot, ctx) => __async(void 0, null, function*
|
|
|
110
426
|
let cache = {};
|
|
111
427
|
yield page.route("**/*", (route, request) => __async(void 0, null, function* () {
|
|
112
428
|
const requestUrl = request.url();
|
|
113
|
-
const snapshotHostname = new URL(snapshot.url).hostname;
|
|
114
429
|
const requestHostname = new URL(requestUrl).hostname;
|
|
115
430
|
try {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (ctx.webConfig.enableJavaScript)
|
|
431
|
+
ctx.config.allowedHostnames.push(new URL(snapshot.url).hostname);
|
|
432
|
+
if (ctx.config.enableJavaScript)
|
|
119
433
|
ALLOWED_RESOURCES.push("script");
|
|
434
|
+
const response = yield page.request.fetch(request, { timeout: REQUEST_TIMEOUT });
|
|
435
|
+
const body = yield response.body();
|
|
120
436
|
if (!body) {
|
|
121
437
|
ctx.log.debug(`Handling request ${requestUrl}
|
|
122
438
|
- skipping no response`);
|
|
@@ -126,7 +442,7 @@ var processSnapshot_default = (snapshot, ctx) => __async(void 0, null, function*
|
|
|
126
442
|
} else if (requestUrl === snapshot.url) {
|
|
127
443
|
ctx.log.debug(`Handling request ${requestUrl}
|
|
128
444
|
- skipping root resource`);
|
|
129
|
-
} else if (requestHostname
|
|
445
|
+
} else if (!ctx.config.allowedHostnames.includes(requestHostname)) {
|
|
130
446
|
ctx.log.debug(`Handling request ${requestUrl}
|
|
131
447
|
- skipping remote resource`);
|
|
132
448
|
} else if (cache[requestUrl]) {
|
|
@@ -138,7 +454,7 @@ var processSnapshot_default = (snapshot, ctx) => __async(void 0, null, function*
|
|
|
138
454
|
} else if (!ALLOWED_STATUSES.includes(response.status())) {
|
|
139
455
|
ctx.log.debug(`Handling request ${requestUrl}
|
|
140
456
|
- skipping disallowed status [${response.status()}]`);
|
|
141
|
-
} else if (!
|
|
457
|
+
} else if (!ALLOWED_RESOURCES.includes(request.resourceType())) {
|
|
142
458
|
ctx.log.debug(`Handling request ${requestUrl}
|
|
143
459
|
- skipping disallowed resource type [${request.resourceType()}]`);
|
|
144
460
|
} else {
|
|
@@ -155,48 +471,66 @@ var processSnapshot_default = (snapshot, ctx) => __async(void 0, null, function*
|
|
|
155
471
|
body
|
|
156
472
|
});
|
|
157
473
|
} catch (error) {
|
|
158
|
-
ctx.log.debug(`Handling request ${requestUrl}
|
|
474
|
+
ctx.log.debug(`Handling request ${requestUrl}
|
|
475
|
+
- aborted due to ${error.message}`);
|
|
159
476
|
route.abort();
|
|
160
477
|
}
|
|
161
478
|
}));
|
|
162
479
|
let options = snapshot.options;
|
|
163
480
|
let optionWarnings = /* @__PURE__ */ new Set();
|
|
164
481
|
let processedOptions = {};
|
|
165
|
-
let
|
|
482
|
+
let selectors = [];
|
|
166
483
|
let ignoreOrSelectDOM;
|
|
167
484
|
let ignoreOrSelectBoxes;
|
|
168
485
|
if (options && Object.keys(options).length) {
|
|
169
486
|
ctx.log.debug(`Snapshot options: ${JSON.stringify(options)}`);
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
487
|
+
const isNotAllEmpty = (obj) => {
|
|
488
|
+
var _a;
|
|
489
|
+
for (let key in obj)
|
|
490
|
+
if ((_a = obj[key]) == null ? void 0 : _a.length)
|
|
491
|
+
return true;
|
|
492
|
+
return false;
|
|
493
|
+
};
|
|
494
|
+
if (options.element && Object.keys(options.element).length) {
|
|
495
|
+
if (options.element.id)
|
|
496
|
+
processedOptions.element = "#" + options.element.id;
|
|
497
|
+
else if (options.element.class)
|
|
498
|
+
processedOptions.element = "." + options.element.class;
|
|
499
|
+
else if (options.element.cssSelector)
|
|
500
|
+
processedOptions.element = options.element.cssSelector;
|
|
501
|
+
else if (options.element.xpath)
|
|
502
|
+
processedOptions.element = "xpath=" + options.element.xpath;
|
|
503
|
+
} else if (options.ignoreDOM && Object.keys(options.ignoreDOM).length && isNotAllEmpty(options.ignoreDOM)) {
|
|
504
|
+
processedOptions.ignoreBoxes = {};
|
|
505
|
+
ignoreOrSelectDOM = "ignoreDOM";
|
|
506
|
+
ignoreOrSelectBoxes = "ignoreBoxes";
|
|
507
|
+
} else if (options.selectDOM && Object.keys(options.selectDOM).length && isNotAllEmpty(options.selectDOM)) {
|
|
508
|
+
processedOptions.selectBoxes = {};
|
|
509
|
+
ignoreOrSelectDOM = "selectDOM";
|
|
510
|
+
ignoreOrSelectBoxes = "selectBoxes";
|
|
511
|
+
}
|
|
512
|
+
if (ignoreOrSelectDOM) {
|
|
180
513
|
for (const [key, value] of Object.entries(options[ignoreOrSelectDOM])) {
|
|
181
514
|
switch (key) {
|
|
182
515
|
case "id":
|
|
183
|
-
|
|
516
|
+
selectors.push(...value.map((e) => "#" + e));
|
|
184
517
|
break;
|
|
185
518
|
case "class":
|
|
186
|
-
|
|
519
|
+
selectors.push(...value.map((e) => "." + e));
|
|
187
520
|
break;
|
|
188
521
|
case "xpath":
|
|
189
|
-
|
|
522
|
+
selectors.push(...value.map((e) => "xpath=" + e));
|
|
190
523
|
break;
|
|
191
524
|
case "cssSelector":
|
|
192
|
-
|
|
525
|
+
selectors.push(...value);
|
|
193
526
|
break;
|
|
194
527
|
}
|
|
195
528
|
}
|
|
196
529
|
}
|
|
197
530
|
}
|
|
198
531
|
let navigated = false;
|
|
199
|
-
|
|
532
|
+
let renderViewports = getRenderViewports(ctx);
|
|
533
|
+
for (const { viewport, viewportString, fullPage } of renderViewports) {
|
|
200
534
|
yield page.setViewportSize({ width: viewport.width, height: viewport.height || MIN_VIEWPORT_HEIGHT });
|
|
201
535
|
ctx.log.debug(`Page resized to ${viewport.width}x${viewport.height || MIN_VIEWPORT_HEIGHT}`);
|
|
202
536
|
if (!navigated) {
|
|
@@ -204,20 +538,25 @@ var processSnapshot_default = (snapshot, ctx) => __async(void 0, null, function*
|
|
|
204
538
|
navigated = true;
|
|
205
539
|
ctx.log.debug(`Navigated to ${snapshot.url}`);
|
|
206
540
|
}
|
|
207
|
-
if (
|
|
541
|
+
if (fullPage)
|
|
208
542
|
yield page.evaluate(scrollToBottomAndBackToTop);
|
|
209
543
|
yield page.waitForLoadState("networkidle");
|
|
210
544
|
ctx.log.debug("Network idle 500ms");
|
|
211
|
-
if (
|
|
212
|
-
let
|
|
545
|
+
if (processedOptions.element) {
|
|
546
|
+
let l = yield page.locator(processedOptions.element).all();
|
|
547
|
+
if (l.length === 0) {
|
|
548
|
+
throw new Error(`for snapshot ${snapshot.name} viewport ${viewportString}, no element found for selector ${processedOptions.element}`);
|
|
549
|
+
} else if (l.length > 1) {
|
|
550
|
+
throw new Error(`for snapshot ${snapshot.name} viewport ${viewportString}, multiple elements found for selector ${processedOptions.element}`);
|
|
551
|
+
}
|
|
552
|
+
} else if (selectors.length) {
|
|
553
|
+
let locators = [];
|
|
213
554
|
if (!Array.isArray(processedOptions[ignoreOrSelectBoxes][viewportString]))
|
|
214
555
|
processedOptions[ignoreOrSelectBoxes][viewportString] = [];
|
|
215
|
-
|
|
216
|
-
let boxes = [];
|
|
217
|
-
for (const selector of selectors2) {
|
|
556
|
+
for (const selector of selectors) {
|
|
218
557
|
let l = yield page.locator(selector).all();
|
|
219
558
|
if (l.length === 0) {
|
|
220
|
-
optionWarnings.add(`
|
|
559
|
+
optionWarnings.add(`for snapshot ${snapshot.name} viewport ${viewportString}, no element found for selector ${selector}`);
|
|
221
560
|
continue;
|
|
222
561
|
}
|
|
223
562
|
locators.push(...l);
|
|
@@ -225,14 +564,13 @@ var processSnapshot_default = (snapshot, ctx) => __async(void 0, null, function*
|
|
|
225
564
|
for (const locator of locators) {
|
|
226
565
|
let bb = yield locator.boundingBox();
|
|
227
566
|
if (bb)
|
|
228
|
-
|
|
567
|
+
processedOptions[ignoreOrSelectBoxes][viewportString].push({
|
|
229
568
|
left: bb.x,
|
|
230
569
|
top: bb.y,
|
|
231
570
|
right: bb.x + bb.width,
|
|
232
571
|
bottom: bb.y + bb.height
|
|
233
572
|
});
|
|
234
573
|
}
|
|
235
|
-
processedOptions[ignoreOrSelectBoxes][viewportString].push(...boxes);
|
|
236
574
|
}
|
|
237
575
|
}
|
|
238
576
|
yield page.close();
|
|
@@ -269,10 +607,10 @@ var ConfigSchema = {
|
|
|
269
607
|
properties: {
|
|
270
608
|
browsers: {
|
|
271
609
|
type: "array",
|
|
272
|
-
items: { type: "string", enum: [
|
|
610
|
+
items: { type: "string", enum: [constants_default.CHROME, constants_default.FIREFOX, constants_default.SAFARI, constants_default.EDGE] },
|
|
273
611
|
uniqueItems: true,
|
|
274
612
|
maxItems: 4,
|
|
275
|
-
errorMessage:
|
|
613
|
+
errorMessage: `Invalid config; allowed browsers - ${constants_default.CHROME}, ${constants_default.FIREFOX}, ${constants_default.SAFARI}, ${constants_default.EDGE}`
|
|
276
614
|
},
|
|
277
615
|
viewports: {
|
|
278
616
|
type: "array",
|
|
@@ -298,29 +636,80 @@ var ConfigSchema = {
|
|
|
298
636
|
uniqueItems: true,
|
|
299
637
|
maxItems: 5,
|
|
300
638
|
errorMessage: "Invalid config; max unique viewports allowed - 5"
|
|
639
|
+
}
|
|
640
|
+
},
|
|
641
|
+
required: ["browsers", "viewports"],
|
|
642
|
+
additionalProperties: false
|
|
643
|
+
},
|
|
644
|
+
mobile: {
|
|
645
|
+
type: "object",
|
|
646
|
+
properties: {
|
|
647
|
+
devices: {
|
|
648
|
+
type: "array",
|
|
649
|
+
items: {
|
|
650
|
+
type: "string",
|
|
651
|
+
enum: Object.keys(constants_default.SUPPORTED_MOBILE_DEVICES),
|
|
652
|
+
minLength: 1,
|
|
653
|
+
errorMessage: {
|
|
654
|
+
enum: "Invalid config; unsupported mobile devices",
|
|
655
|
+
minLength: "Invalid config; mobile device cannot be empty"
|
|
656
|
+
}
|
|
657
|
+
},
|
|
658
|
+
uniqueItems: true,
|
|
659
|
+
maxItems: 20,
|
|
660
|
+
errorMessage: {
|
|
661
|
+
uniqueItems: "Invalid config; duplicate mobile devices",
|
|
662
|
+
maxItems: "Invalid config; max mobile devices allowed - 20"
|
|
663
|
+
}
|
|
301
664
|
},
|
|
302
|
-
|
|
303
|
-
type: "number",
|
|
304
|
-
minimum: 0,
|
|
305
|
-
maximum: 3e5,
|
|
306
|
-
errorMessage: "Invalid config; waitForPageRender must be > 0 and <= 300000"
|
|
307
|
-
},
|
|
308
|
-
waitForTimeout: {
|
|
309
|
-
type: "number",
|
|
310
|
-
minimum: 0,
|
|
311
|
-
maximum: 3e4,
|
|
312
|
-
errorMessage: "Invalid config; waitForTimeout must be > 0 and <= 30000"
|
|
313
|
-
},
|
|
314
|
-
enableJavaScript: {
|
|
665
|
+
fullPage: {
|
|
315
666
|
type: "boolean",
|
|
316
|
-
errorMessage: "Invalid config;
|
|
667
|
+
errorMessage: "Invalid config; fullPage must be true/false"
|
|
668
|
+
},
|
|
669
|
+
orientation: {
|
|
670
|
+
type: "string",
|
|
671
|
+
enum: [constants_default.MOBILE_ORIENTATION_PORTRAIT, constants_default.MOBILE_ORIENTATION_LANDSCAPE],
|
|
672
|
+
errorMessage: `Invalid config; orientation must be ${constants_default.MOBILE_ORIENTATION_PORTRAIT}/${constants_default.MOBILE_ORIENTATION_LANDSCAPE}`
|
|
317
673
|
}
|
|
318
674
|
},
|
|
319
|
-
required: ["
|
|
675
|
+
required: ["devices"],
|
|
320
676
|
additionalProperties: false
|
|
677
|
+
},
|
|
678
|
+
waitForPageRender: {
|
|
679
|
+
type: "number",
|
|
680
|
+
minimum: 0,
|
|
681
|
+
maximum: 3e5,
|
|
682
|
+
errorMessage: "Invalid config; waitForPageRender must be > 0 and <= 300000"
|
|
683
|
+
},
|
|
684
|
+
waitForTimeout: {
|
|
685
|
+
type: "number",
|
|
686
|
+
minimum: 0,
|
|
687
|
+
maximum: 3e4,
|
|
688
|
+
errorMessage: "Invalid config; waitForTimeout must be > 0 and <= 30000"
|
|
689
|
+
},
|
|
690
|
+
enableJavaScript: {
|
|
691
|
+
type: "boolean",
|
|
692
|
+
errorMessage: "Invalid config; enableJavaScript must be true/false"
|
|
693
|
+
},
|
|
694
|
+
allowedHostnames: {
|
|
695
|
+
type: "array",
|
|
696
|
+
items: {
|
|
697
|
+
type: "string",
|
|
698
|
+
minLength: 1,
|
|
699
|
+
errorMessage: {
|
|
700
|
+
minLength: "Invalid config; allowed hostname cannot be empty"
|
|
701
|
+
}
|
|
702
|
+
},
|
|
703
|
+
uniqueItems: true,
|
|
704
|
+
errorMessage: {
|
|
705
|
+
uniqueItems: "Invalid config; duplicates in allowedHostnames"
|
|
706
|
+
}
|
|
321
707
|
}
|
|
322
708
|
},
|
|
323
|
-
|
|
709
|
+
anyOf: [
|
|
710
|
+
{ required: ["web"] },
|
|
711
|
+
{ required: ["mobile"] }
|
|
712
|
+
],
|
|
324
713
|
additionalProperties: false
|
|
325
714
|
};
|
|
326
715
|
var WebStaticConfigSchema = {
|
|
@@ -370,32 +759,56 @@ var SnapshotSchema = {
|
|
|
370
759
|
options: {
|
|
371
760
|
type: "object",
|
|
372
761
|
properties: {
|
|
762
|
+
element: {
|
|
763
|
+
type: "object",
|
|
764
|
+
properties: {
|
|
765
|
+
id: {
|
|
766
|
+
type: "string",
|
|
767
|
+
pattern: "^[^;]*$",
|
|
768
|
+
errorMessage: "Invalid snapshot options; element id cannot be empty or have semicolon"
|
|
769
|
+
},
|
|
770
|
+
class: {
|
|
771
|
+
type: "string",
|
|
772
|
+
pattern: "^[^;]*$",
|
|
773
|
+
errorMessage: "Invalid snapshot options; element class cannot be empty or have semicolon"
|
|
774
|
+
},
|
|
775
|
+
cssSelector: {
|
|
776
|
+
type: "string",
|
|
777
|
+
pattern: "^[^;]*$",
|
|
778
|
+
errorMessage: "Invalid snapshot options; element cssSelector cannot be empty or have semicolon"
|
|
779
|
+
},
|
|
780
|
+
xpath: {
|
|
781
|
+
type: "string",
|
|
782
|
+
errorMessage: "Invalid snapshot options; element xpath cannot be empty"
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
},
|
|
373
786
|
ignoreDOM: {
|
|
374
787
|
type: "object",
|
|
375
788
|
properties: {
|
|
376
789
|
id: {
|
|
377
790
|
type: "array",
|
|
378
|
-
items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; id cannot be empty or have semicolon" },
|
|
791
|
+
items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; ignoreDOM id cannot be empty or have semicolon" },
|
|
379
792
|
uniqueItems: true,
|
|
380
|
-
errorMessage: "Invalid snapshot options; id array must have unique items"
|
|
793
|
+
errorMessage: "Invalid snapshot options; ignoreDOM id array must have unique items"
|
|
381
794
|
},
|
|
382
795
|
class: {
|
|
383
796
|
type: "array",
|
|
384
|
-
items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; class cannot be empty or have semicolon" },
|
|
797
|
+
items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; ignoreDOM class cannot be empty or have semicolon" },
|
|
385
798
|
uniqueItems: true,
|
|
386
|
-
errorMessage: "Invalid snapshot options; class array must have unique items"
|
|
799
|
+
errorMessage: "Invalid snapshot options; ignoreDOM class array must have unique items"
|
|
387
800
|
},
|
|
388
801
|
cssSelector: {
|
|
389
802
|
type: "array",
|
|
390
|
-
items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; cssSelector cannot be empty or have semicolon" },
|
|
803
|
+
items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; ignoreDOM cssSelector cannot be empty or have semicolon" },
|
|
391
804
|
uniqueItems: true,
|
|
392
|
-
errorMessage: "Invalid snapshot options; cssSelector array must have unique items"
|
|
805
|
+
errorMessage: "Invalid snapshot options; ignoreDOM cssSelector array must have unique items"
|
|
393
806
|
},
|
|
394
807
|
xpath: {
|
|
395
808
|
type: "array",
|
|
396
809
|
items: { type: "string", minLength: 1 },
|
|
397
810
|
uniqueItems: true,
|
|
398
|
-
errorMessage: "Invalid snapshot options; xpath array must have unique and non-empty items"
|
|
811
|
+
errorMessage: "Invalid snapshot options; ignoreDOM xpath array must have unique and non-empty items"
|
|
399
812
|
}
|
|
400
813
|
}
|
|
401
814
|
},
|
|
@@ -404,27 +817,27 @@ var SnapshotSchema = {
|
|
|
404
817
|
properties: {
|
|
405
818
|
id: {
|
|
406
819
|
type: "array",
|
|
407
|
-
items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; id cannot be empty or have semicolon" },
|
|
820
|
+
items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; selectDOM id cannot be empty or have semicolon" },
|
|
408
821
|
uniqueItems: true,
|
|
409
|
-
errorMessage: "Invalid snapshot options; id array must have unique items"
|
|
822
|
+
errorMessage: "Invalid snapshot options; selectDOM id array must have unique items"
|
|
410
823
|
},
|
|
411
824
|
class: {
|
|
412
825
|
type: "array",
|
|
413
|
-
items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; class cannot be empty or have semicolon" },
|
|
826
|
+
items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; selectDOM class cannot be empty or have semicolon" },
|
|
414
827
|
uniqueItems: true,
|
|
415
|
-
errorMessage: "Invalid snapshot options; class array must have unique items"
|
|
828
|
+
errorMessage: "Invalid snapshot options; selectDOM class array must have unique items"
|
|
416
829
|
},
|
|
417
830
|
cssSelector: {
|
|
418
831
|
type: "array",
|
|
419
|
-
items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; cssSelector cannot be empty or have semicolon" },
|
|
832
|
+
items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; selectDOM cssSelector cannot be empty or have semicolon" },
|
|
420
833
|
uniqueItems: true,
|
|
421
|
-
errorMessage: "Invalid snapshot options; cssSelector array must have unique items"
|
|
834
|
+
errorMessage: "Invalid snapshot options; selectDOM cssSelector array must have unique items"
|
|
422
835
|
},
|
|
423
836
|
xpath: {
|
|
424
837
|
type: "array",
|
|
425
838
|
items: { type: "string", minLength: 1 },
|
|
426
839
|
uniqueItems: true,
|
|
427
|
-
errorMessage: "Invalid snapshot options; xpath array must have unique and non-empty items"
|
|
840
|
+
errorMessage: "Invalid snapshot options; selectDOM xpath array must have unique and non-empty items"
|
|
428
841
|
}
|
|
429
842
|
}
|
|
430
843
|
}
|
|
@@ -444,7 +857,7 @@ var validateSnapshot = ajv.compile(SnapshotSchema);
|
|
|
444
857
|
var server_default = (ctx) => __async(void 0, null, function* () {
|
|
445
858
|
const server = fastify__default.default({ logger: false, bodyLimit: 1e7 });
|
|
446
859
|
const opts = {};
|
|
447
|
-
const SMARTUI_DOM =
|
|
860
|
+
const SMARTUI_DOM = fs4.readFileSync(path2__default.default.resolve(__dirname, "dom-serializer.js"), "utf-8");
|
|
448
861
|
server.get("/healthcheck", opts, (_, reply) => {
|
|
449
862
|
reply.code(200).send({ cliVersion: ctx.cliVersion });
|
|
450
863
|
});
|
|
@@ -477,13 +890,15 @@ var env_default = () => {
|
|
|
477
890
|
PROJECT_TOKEN = "",
|
|
478
891
|
SMARTUI_CLIENT_API_URL = "https://api.lambdatest.com/visualui/1.0",
|
|
479
892
|
LT_SDK_LOG_LEVEL,
|
|
480
|
-
LT_SDK_DEBUG
|
|
893
|
+
LT_SDK_DEBUG,
|
|
894
|
+
GITHUB_ACTIONS
|
|
481
895
|
} = process.env;
|
|
482
896
|
return {
|
|
483
897
|
PROJECT_TOKEN,
|
|
484
898
|
SMARTUI_CLIENT_API_URL,
|
|
485
899
|
LT_SDK_LOG_LEVEL,
|
|
486
|
-
LT_SDK_DEBUG
|
|
900
|
+
LT_SDK_DEBUG,
|
|
901
|
+
GITHUB_ACTIONS
|
|
487
902
|
};
|
|
488
903
|
};
|
|
489
904
|
var logContext = { task: "smartui-cli" };
|
|
@@ -504,13 +919,13 @@ var logger = winston.createLogger({
|
|
|
504
919
|
let message = typeof info.message === "object" ? JSON.stringify(info.message) : info.message;
|
|
505
920
|
switch (info.level) {
|
|
506
921
|
case "debug":
|
|
507
|
-
message =
|
|
922
|
+
message = chalk8__default.default.blue(message);
|
|
508
923
|
break;
|
|
509
924
|
case "warn":
|
|
510
|
-
message =
|
|
925
|
+
message = chalk8__default.default.yellow(message);
|
|
511
926
|
break;
|
|
512
927
|
case "error":
|
|
513
|
-
message =
|
|
928
|
+
message = chalk8__default.default.red(message);
|
|
514
929
|
break;
|
|
515
930
|
}
|
|
516
931
|
return info.level === "info" ? message : `[${contextString}:${info.level}] ` + message;
|
|
@@ -529,11 +944,11 @@ var startServer_default = (ctx) => {
|
|
|
529
944
|
updateLogContext({ task: "startServer" });
|
|
530
945
|
try {
|
|
531
946
|
ctx2.server = yield server_default(ctx2);
|
|
532
|
-
task.output =
|
|
947
|
+
task.output = chalk8__default.default.gray(`listening on port ${(_a = ctx2.server.addresses()[0]) == null ? void 0 : _a.port}`);
|
|
533
948
|
task.title = "SmartUI started";
|
|
534
949
|
} catch (error) {
|
|
535
950
|
ctx2.log.debug(error);
|
|
536
|
-
task.output =
|
|
951
|
+
task.output = chalk8__default.default.gray(error.message);
|
|
537
952
|
throw new Error("SmartUI server setup failed");
|
|
538
953
|
}
|
|
539
954
|
}),
|
|
@@ -547,80 +962,20 @@ var auth_default = (ctx) => {
|
|
|
547
962
|
updateLogContext({ task: "auth" });
|
|
548
963
|
try {
|
|
549
964
|
yield ctx2.client.auth(ctx2.log);
|
|
550
|
-
task.output =
|
|
965
|
+
task.output = chalk8__default.default.gray(`using project token '******#${ctx2.env.PROJECT_TOKEN.split("#").pop()}'`);
|
|
551
966
|
task.title = "Authenticated with SmartUI";
|
|
552
967
|
} catch (error) {
|
|
553
968
|
ctx2.log.debug(error);
|
|
554
|
-
task.output =
|
|
969
|
+
task.output = chalk8__default.default.gray(error.message);
|
|
555
970
|
throw new Error("Authentication failed");
|
|
556
971
|
}
|
|
557
972
|
}),
|
|
558
973
|
rendererOptions: { persistentOutput: true }
|
|
559
974
|
};
|
|
560
975
|
};
|
|
561
|
-
var DEFAULT_WEB_STATIC_CONFIG = [
|
|
562
|
-
{
|
|
563
|
-
"name": "lambdatest-home-page",
|
|
564
|
-
"url": "https://www.lambdatest.com",
|
|
565
|
-
"waitForTimeout": 1e3
|
|
566
|
-
},
|
|
567
|
-
{
|
|
568
|
-
"name": "example-page",
|
|
569
|
-
"url": "https://example.com/"
|
|
570
|
-
}
|
|
571
|
-
];
|
|
572
|
-
var DEFAULT_CONFIG = {
|
|
573
|
-
web: {
|
|
574
|
-
browsers: [
|
|
575
|
-
"chrome",
|
|
576
|
-
"firefox",
|
|
577
|
-
"safari",
|
|
578
|
-
"edge"
|
|
579
|
-
],
|
|
580
|
-
viewports: [
|
|
581
|
-
[1920],
|
|
582
|
-
[1366],
|
|
583
|
-
[360]
|
|
584
|
-
],
|
|
585
|
-
waitForTimeout: 1e3,
|
|
586
|
-
enableJavaScript: false
|
|
587
|
-
}
|
|
588
|
-
};
|
|
589
|
-
function createConfig(filepath) {
|
|
590
|
-
filepath = filepath || ".smartui.json";
|
|
591
|
-
let filetype = path2__default.default.extname(filepath);
|
|
592
|
-
if (filetype != ".json") {
|
|
593
|
-
console.log("Error: Config file must have .json extension");
|
|
594
|
-
return;
|
|
595
|
-
}
|
|
596
|
-
if (fs2__default.default.existsSync(filepath)) {
|
|
597
|
-
console.log(`Error: SmartUI Config already exists: ${filepath}`);
|
|
598
|
-
console.log(`To create a new file, please specify the file name like: 'smartui config:create .smartui-config.json'`);
|
|
599
|
-
return;
|
|
600
|
-
}
|
|
601
|
-
fs2__default.default.mkdirSync(path2__default.default.dirname(filepath), { recursive: true });
|
|
602
|
-
fs2__default.default.writeFileSync(filepath, JSON.stringify(DEFAULT_CONFIG, null, 2) + "\n");
|
|
603
|
-
console.log(`Created SmartUI Config: ${filepath}`);
|
|
604
|
-
}
|
|
605
|
-
function createWebStaticConfig(filepath) {
|
|
606
|
-
filepath = filepath || "url.json";
|
|
607
|
-
let filetype = path2__default.default.extname(filepath);
|
|
608
|
-
if (filetype != ".json") {
|
|
609
|
-
console.log("Error: Config file must have .json extension");
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
|
-
if (fs2__default.default.existsSync(filepath)) {
|
|
613
|
-
console.log(`Error: web-static config already exists: ${filepath}`);
|
|
614
|
-
console.log(`To create a new file, please specify the file name like: 'smartui config:create-web-static links.json'`);
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
617
|
-
fs2__default.default.mkdirSync(path2__default.default.dirname(filepath), { recursive: true });
|
|
618
|
-
fs2__default.default.writeFileSync(filepath, JSON.stringify(DEFAULT_WEB_STATIC_CONFIG, null, 2) + "\n");
|
|
619
|
-
console.log(`Created web-static config: ${filepath}`);
|
|
620
|
-
}
|
|
621
976
|
|
|
622
977
|
// package.json
|
|
623
|
-
var version = "
|
|
978
|
+
var version = "3.0.1";
|
|
624
979
|
var package_default = {
|
|
625
980
|
name: "@lambdatest/smartui-cli",
|
|
626
981
|
version,
|
|
@@ -686,13 +1041,14 @@ var httpClient = class {
|
|
|
686
1041
|
})}`);
|
|
687
1042
|
return resp.data;
|
|
688
1043
|
}).catch((error) => {
|
|
1044
|
+
var _a;
|
|
689
1045
|
if (error.response) {
|
|
690
1046
|
log.debug(`http response: ${JSON.stringify({
|
|
691
1047
|
status: error.response.status,
|
|
692
1048
|
headers: error.response.headers,
|
|
693
1049
|
body: error.response.data
|
|
694
1050
|
})}`);
|
|
695
|
-
throw new Error(
|
|
1051
|
+
throw new Error((_a = error.response.data.error) == null ? void 0 : _a.message);
|
|
696
1052
|
}
|
|
697
1053
|
if (error.request) {
|
|
698
1054
|
log.debug(`http request failed: ${error.toJSON()}`);
|
|
@@ -709,24 +1065,13 @@ var httpClient = class {
|
|
|
709
1065
|
method: "GET"
|
|
710
1066
|
}, log);
|
|
711
1067
|
}
|
|
712
|
-
createBuild(
|
|
1068
|
+
createBuild(git, config, log) {
|
|
713
1069
|
return this.request({
|
|
714
1070
|
url: "/build",
|
|
715
1071
|
method: "POST",
|
|
716
1072
|
data: {
|
|
717
|
-
git
|
|
718
|
-
|
|
719
|
-
commitId,
|
|
720
|
-
commitAuthor,
|
|
721
|
-
commitMessage,
|
|
722
|
-
githubURL
|
|
723
|
-
},
|
|
724
|
-
config: {
|
|
725
|
-
browsers: config.browsers,
|
|
726
|
-
resolutions: config.viewports,
|
|
727
|
-
waitForPageRender: config.waitForPageRender,
|
|
728
|
-
waitForTimeout: config.waitForTimeout
|
|
729
|
-
}
|
|
1073
|
+
git,
|
|
1074
|
+
config
|
|
730
1075
|
}
|
|
731
1076
|
}, log);
|
|
732
1077
|
}
|
|
@@ -754,28 +1099,27 @@ var httpClient = class {
|
|
|
754
1099
|
}
|
|
755
1100
|
}, log);
|
|
756
1101
|
}
|
|
757
|
-
uploadScreenshot({ id: buildId, name: buildName, baseline }, ssPath, ssName, browserName, viewport,
|
|
758
|
-
|
|
1102
|
+
uploadScreenshot({ id: buildId, name: buildName, baseline }, ssPath, ssName, browserName, viewport, log) {
|
|
1103
|
+
browserName = browserName === constants_default.SAFARI ? constants_default.WEBKIT : browserName;
|
|
1104
|
+
const file = fs4__default.default.readFileSync(ssPath);
|
|
759
1105
|
const form = new FormData__default.default();
|
|
760
|
-
form.append("
|
|
1106
|
+
form.append("screenshot", file, { filename: `${ssName}.png`, contentType: "image/png" });
|
|
761
1107
|
form.append("browser", browserName);
|
|
762
|
-
form.append("
|
|
1108
|
+
form.append("viewport", viewport);
|
|
763
1109
|
form.append("buildId", buildId);
|
|
764
1110
|
form.append("buildName", buildName);
|
|
765
1111
|
form.append("screenshotName", ssName);
|
|
766
1112
|
form.append("baseline", baseline.toString());
|
|
767
|
-
form.append("completed", completed.toString());
|
|
768
1113
|
return this.axiosInstance.request({
|
|
769
1114
|
url: `/screenshot`,
|
|
770
1115
|
method: "POST",
|
|
771
1116
|
headers: form.getHeaders(),
|
|
772
1117
|
data: form
|
|
773
1118
|
}).then(() => {
|
|
774
|
-
|
|
775
|
-
delDir("screenshots");
|
|
1119
|
+
log.debug(`${ssName} for ${browserName} ${viewport} uploaded successfully`);
|
|
776
1120
|
}).catch((error) => {
|
|
777
1121
|
if (error.response) {
|
|
778
|
-
throw new Error(
|
|
1122
|
+
throw new Error(error.response.data.error.message);
|
|
779
1123
|
}
|
|
780
1124
|
if (error.request) {
|
|
781
1125
|
throw new Error(error.toJSON().message);
|
|
@@ -796,35 +1140,49 @@ var httpClient = class {
|
|
|
796
1140
|
}
|
|
797
1141
|
};
|
|
798
1142
|
var ctx_default = (options) => {
|
|
1143
|
+
var _a, _b;
|
|
799
1144
|
let env = env_default();
|
|
800
|
-
let
|
|
801
|
-
let
|
|
1145
|
+
let webConfig;
|
|
1146
|
+
let mobileConfig;
|
|
1147
|
+
let config = constants_default.DEFAULT_CONFIG;
|
|
802
1148
|
try {
|
|
803
1149
|
if (options.config) {
|
|
804
|
-
config = JSON.parse(
|
|
805
|
-
if (config.web.resolutions) {
|
|
1150
|
+
config = JSON.parse(fs4__default.default.readFileSync(options.config, "utf-8"));
|
|
1151
|
+
if ((_a = config.web) == null ? void 0 : _a.resolutions) {
|
|
806
1152
|
config.web.viewports = config.web.resolutions;
|
|
807
1153
|
delete config.web.resolutions;
|
|
808
1154
|
}
|
|
1155
|
+
if (!validateConfig(config)) {
|
|
1156
|
+
throw new Error(validateConfig.errors[0].message);
|
|
1157
|
+
}
|
|
809
1158
|
}
|
|
810
|
-
if (!validateConfig(config))
|
|
811
|
-
throw new Error(validateConfig.errors[0].message);
|
|
812
1159
|
} catch (error) {
|
|
813
1160
|
console.log(`[smartui] Error: ${error.message}`);
|
|
814
1161
|
process.exit();
|
|
815
1162
|
}
|
|
816
|
-
|
|
817
|
-
|
|
1163
|
+
if (config.web) {
|
|
1164
|
+
webConfig = { browsers: config.web.browsers, viewports: [] };
|
|
1165
|
+
for (let viewport of (_b = config.web) == null ? void 0 : _b.viewports)
|
|
1166
|
+
webConfig.viewports.push({ width: viewport[0], height: viewport[1] || 0 });
|
|
1167
|
+
}
|
|
1168
|
+
if (config.mobile) {
|
|
1169
|
+
mobileConfig = {
|
|
1170
|
+
devices: config.mobile.devices,
|
|
1171
|
+
fullPage: config.mobile.fullPage || true,
|
|
1172
|
+
orientation: config.mobile.orientation || constants_default.MOBILE_ORIENTATION_PORTRAIT
|
|
1173
|
+
};
|
|
1174
|
+
}
|
|
818
1175
|
return {
|
|
819
1176
|
env,
|
|
820
1177
|
log: logger_default,
|
|
821
1178
|
client: new httpClient(env),
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
waitForPageRender: config.
|
|
826
|
-
waitForTimeout: config.
|
|
827
|
-
enableJavaScript: config.
|
|
1179
|
+
config: {
|
|
1180
|
+
web: webConfig,
|
|
1181
|
+
mobile: mobileConfig,
|
|
1182
|
+
waitForPageRender: config.waitForPageRender || 0,
|
|
1183
|
+
waitForTimeout: config.waitForTimeout || 0,
|
|
1184
|
+
enableJavaScript: config.enableJavaScript || false,
|
|
1185
|
+
allowedHostnames: config.allowedHostnames || []
|
|
828
1186
|
},
|
|
829
1187
|
webStaticConfig: [],
|
|
830
1188
|
git: {
|
|
@@ -838,10 +1196,12 @@ var ctx_default = (options) => {
|
|
|
838
1196
|
id: "",
|
|
839
1197
|
name: "",
|
|
840
1198
|
baseline: false,
|
|
841
|
-
url: ""
|
|
842
|
-
projectId: ""
|
|
1199
|
+
url: ""
|
|
843
1200
|
},
|
|
844
1201
|
args: {},
|
|
1202
|
+
options: {
|
|
1203
|
+
parallel: options.parallel ? true : false
|
|
1204
|
+
},
|
|
845
1205
|
cliVersion: version,
|
|
846
1206
|
totalSnapshots: -1
|
|
847
1207
|
};
|
|
@@ -866,7 +1226,7 @@ function isGitRepo() {
|
|
|
866
1226
|
return false;
|
|
867
1227
|
}
|
|
868
1228
|
}
|
|
869
|
-
var git_default = () => {
|
|
1229
|
+
var git_default = (ctx) => {
|
|
870
1230
|
const splitCharacter = "<##>";
|
|
871
1231
|
const prettyFormat = ["%h", "%H", "%s", "%f", "%b", "%at", "%ct", "%an", "%ae", "%cn", "%ce", "%N", ""];
|
|
872
1232
|
const command3 = 'git log -1 --pretty=format:"' + prettyFormat.join(splitCharacter) + '" && git rev-parse --abbrev-ref HEAD && git tag --contains HEAD';
|
|
@@ -878,7 +1238,8 @@ var git_default = () => {
|
|
|
878
1238
|
branch,
|
|
879
1239
|
commitId: res[0] || "",
|
|
880
1240
|
commitMessage: res[2] || "",
|
|
881
|
-
commitAuthor: res[7] || ""
|
|
1241
|
+
commitAuthor: res[7] || "",
|
|
1242
|
+
githubURL: ctx.env.GITHUB_ACTIONS ? `${constants_default.GITHUB_API_HOST}/repos/${process.env.GITHUB_REPOSITORY}/statuses/${res[1]}` : ""
|
|
882
1243
|
};
|
|
883
1244
|
};
|
|
884
1245
|
var getGitInfo_default = (ctx) => {
|
|
@@ -889,12 +1250,12 @@ var getGitInfo_default = (ctx) => {
|
|
|
889
1250
|
},
|
|
890
1251
|
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
891
1252
|
try {
|
|
892
|
-
ctx2.git = git_default();
|
|
893
|
-
task.output =
|
|
1253
|
+
ctx2.git = git_default(ctx2);
|
|
1254
|
+
task.output = chalk8__default.default.gray(`branch: ${ctx2.git.branch}, commit: ${ctx2.git.commitId}, author: ${ctx2.git.commitAuthor}`);
|
|
894
1255
|
task.title = "Fetched git information";
|
|
895
1256
|
} catch (error) {
|
|
896
1257
|
ctx2.log.debug(error);
|
|
897
|
-
task.output =
|
|
1258
|
+
task.output = chalk8__default.default.gray(`${error.message}`);
|
|
898
1259
|
throw new Error("Error fetching git repo details");
|
|
899
1260
|
}
|
|
900
1261
|
}),
|
|
@@ -907,19 +1268,18 @@ var createBuild_default = (ctx) => {
|
|
|
907
1268
|
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
908
1269
|
updateLogContext({ task: "createBuild" });
|
|
909
1270
|
try {
|
|
910
|
-
let resp = yield ctx2.client.createBuild(ctx2.git, ctx2.
|
|
1271
|
+
let resp = yield ctx2.client.createBuild(ctx2.git, ctx2.config, ctx2.log);
|
|
911
1272
|
ctx2.build = {
|
|
912
1273
|
id: resp.data.buildId,
|
|
913
1274
|
name: resp.data.buildName,
|
|
914
|
-
url: resp.buildURL,
|
|
915
|
-
baseline: resp.data.baseline
|
|
916
|
-
projectId: resp.data.projectId
|
|
1275
|
+
url: resp.data.buildURL,
|
|
1276
|
+
baseline: resp.data.baseline
|
|
917
1277
|
};
|
|
918
|
-
task.output =
|
|
1278
|
+
task.output = chalk8__default.default.gray(`build id: ${resp.data.buildId}`);
|
|
919
1279
|
task.title = "SmartUI build created";
|
|
920
1280
|
} catch (error) {
|
|
921
1281
|
ctx2.log.debug(error);
|
|
922
|
-
task.output =
|
|
1282
|
+
task.output = chalk8__default.default.gray(error.message);
|
|
923
1283
|
throw new Error("SmartUI build creation failed");
|
|
924
1284
|
}
|
|
925
1285
|
}),
|
|
@@ -938,13 +1298,13 @@ var exec_default = (ctx) => {
|
|
|
938
1298
|
let totalOutput = "";
|
|
939
1299
|
const output = listr2.createWritable((chunk) => {
|
|
940
1300
|
totalOutput += chunk;
|
|
941
|
-
task.output =
|
|
1301
|
+
task.output = chalk8__default.default.gray(totalOutput);
|
|
942
1302
|
});
|
|
943
1303
|
(_b = childProcess.stdout) == null ? void 0 : _b.pipe(output);
|
|
944
1304
|
(_c = childProcess.stderr) == null ? void 0 : _c.pipe(output);
|
|
945
1305
|
childProcess.on("error", (error) => {
|
|
946
1306
|
var _a3;
|
|
947
|
-
task.output =
|
|
1307
|
+
task.output = chalk8__default.default.gray(`error: ${error.message}`);
|
|
948
1308
|
throw new Error(`Execution of '${(_a3 = ctx2.args.execCommand) == null ? void 0 : _a3.join(" ")}' failed`);
|
|
949
1309
|
});
|
|
950
1310
|
childProcess.on("close", (code, signal) => __async(void 0, null, function* () {
|
|
@@ -970,11 +1330,11 @@ var finalizeBuild_default = (ctx) => {
|
|
|
970
1330
|
try {
|
|
971
1331
|
yield new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
972
1332
|
yield ctx2.client.finalizeBuild(ctx2.build.id, ctx2.totalSnapshots, ctx2.log);
|
|
973
|
-
task.output =
|
|
1333
|
+
task.output = chalk8__default.default.gray(`build url: ${ctx2.build.url}`);
|
|
974
1334
|
task.title = "Finalized build";
|
|
975
1335
|
} catch (error) {
|
|
976
1336
|
ctx2.log.debug(error);
|
|
977
|
-
task.output =
|
|
1337
|
+
task.output = chalk8__default.default.gray(error.message);
|
|
978
1338
|
throw new Error("Finalize build failed");
|
|
979
1339
|
}
|
|
980
1340
|
}),
|
|
@@ -1025,6 +1385,40 @@ command.name("exec").description("Run test commands around SmartUI").argument("<
|
|
|
1025
1385
|
});
|
|
1026
1386
|
});
|
|
1027
1387
|
var exec_default2 = command;
|
|
1388
|
+
function createConfig(filepath) {
|
|
1389
|
+
filepath = filepath || ".smartui.json";
|
|
1390
|
+
let filetype = path2__default.default.extname(filepath);
|
|
1391
|
+
if (filetype != ".json") {
|
|
1392
|
+
console.log("Error: Config file must have .json extension");
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
if (fs4__default.default.existsSync(filepath)) {
|
|
1396
|
+
console.log(`Error: SmartUI Config already exists: ${filepath}`);
|
|
1397
|
+
console.log(`To create a new file, please specify the file name like: 'smartui config:create .smartui-config.json'`);
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1400
|
+
fs4__default.default.mkdirSync(path2__default.default.dirname(filepath), { recursive: true });
|
|
1401
|
+
fs4__default.default.writeFileSync(filepath, JSON.stringify(constants_default.DEFAULT_CONFIG, null, 2) + "\n");
|
|
1402
|
+
console.log(`Created SmartUI Config: ${filepath}`);
|
|
1403
|
+
}
|
|
1404
|
+
function createWebStaticConfig(filepath) {
|
|
1405
|
+
filepath = filepath || "url.json";
|
|
1406
|
+
let filetype = path2__default.default.extname(filepath);
|
|
1407
|
+
if (filetype != ".json") {
|
|
1408
|
+
console.log("Error: Config file must have .json extension");
|
|
1409
|
+
return;
|
|
1410
|
+
}
|
|
1411
|
+
if (fs4__default.default.existsSync(filepath)) {
|
|
1412
|
+
console.log(`Error: web-static config already exists: ${filepath}`);
|
|
1413
|
+
console.log(`To create a new file, please specify the file name like: 'smartui config:create-web-static links.json'`);
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
fs4__default.default.mkdirSync(path2__default.default.dirname(filepath), { recursive: true });
|
|
1417
|
+
fs4__default.default.writeFileSync(filepath, JSON.stringify(constants_default.DEFAULT_WEB_STATIC_CONFIG, null, 2) + "\n");
|
|
1418
|
+
console.log(`Created web-static config: ${filepath}`);
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
// src/commander/config.ts
|
|
1028
1422
|
var configWeb = new commander.Command();
|
|
1029
1423
|
var configStatic = new commander.Command();
|
|
1030
1424
|
configWeb.name("config:create").description("Create SmartUI config file").argument("[filepath]", "Optional config filepath").action(function(filepath, options) {
|
|
@@ -1037,73 +1431,107 @@ configStatic.name("config:create-web-static").description("Create Web Static con
|
|
|
1037
1431
|
createWebStaticConfig(filepath);
|
|
1038
1432
|
});
|
|
1039
1433
|
});
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1434
|
+
function captureScreenshotsForConfig(_0, _1, _2, _3, _4) {
|
|
1435
|
+
return __async(this, arguments, function* (ctx, browsers, { name, url, waitForTimeout }, browserName, renderViewports) {
|
|
1436
|
+
let pageOptions = { waitUntil: process.env.SMARTUI_PAGE_WAIT_UNTIL_EVENT || "load" };
|
|
1437
|
+
let ssId = name.toLowerCase().replace(/\s/g, "_");
|
|
1438
|
+
let context;
|
|
1439
|
+
let page;
|
|
1440
|
+
try {
|
|
1441
|
+
const browser = browsers[browserName];
|
|
1442
|
+
context = yield browser == null ? void 0 : browser.newContext();
|
|
1443
|
+
page = yield context == null ? void 0 : context.newPage();
|
|
1444
|
+
yield page == null ? void 0 : page.goto(url.trim(), pageOptions);
|
|
1445
|
+
for (let { viewport, viewportString, fullPage } of renderViewports) {
|
|
1446
|
+
let ssPath = `screenshots/${ssId}/${`${browserName}-${viewport.width}x${viewport.height}`}-${ssId}.png`;
|
|
1447
|
+
yield page == null ? void 0 : page.setViewportSize({ width: viewport.width, height: viewport.height || constants_default.MIN_VIEWPORT_HEIGHT });
|
|
1448
|
+
if (fullPage)
|
|
1449
|
+
yield page == null ? void 0 : page.evaluate(scrollToBottomAndBackToTop);
|
|
1450
|
+
yield page == null ? void 0 : page.waitForTimeout(waitForTimeout || 0);
|
|
1451
|
+
yield page == null ? void 0 : page.screenshot({ path: ssPath, fullPage });
|
|
1452
|
+
yield ctx.client.uploadScreenshot(ctx.build, ssPath, name, browserName, viewportString, ctx.log);
|
|
1453
|
+
}
|
|
1454
|
+
} catch (error) {
|
|
1455
|
+
throw new Error(`captureScreenshotsForConfig failed for browser ${browserName}; error: ${error}`);
|
|
1456
|
+
} finally {
|
|
1457
|
+
yield page == null ? void 0 : page.close();
|
|
1458
|
+
yield context == null ? void 0 : context.close();
|
|
1459
|
+
}
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
function captureScreenshotsAsync(ctx, staticConfig, browsers) {
|
|
1463
|
+
return __async(this, null, function* () {
|
|
1464
|
+
let capturePromises = [];
|
|
1465
|
+
if (ctx.config.web) {
|
|
1466
|
+
for (let browserName of ctx.config.web.browsers) {
|
|
1467
|
+
let webRenderViewports = getWebRenderViewports(ctx);
|
|
1468
|
+
capturePromises.push(captureScreenshotsForConfig(ctx, browsers, staticConfig, browserName, webRenderViewports));
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
if (ctx.config.mobile) {
|
|
1472
|
+
let mobileRenderViewports = getMobileRenderViewports(ctx);
|
|
1473
|
+
if (mobileRenderViewports[constants_default.MOBILE_OS_IOS].length) {
|
|
1474
|
+
capturePromises.push(captureScreenshotsForConfig(ctx, browsers, staticConfig, constants_default.SAFARI, mobileRenderViewports[constants_default.MOBILE_OS_IOS]));
|
|
1475
|
+
}
|
|
1476
|
+
if (mobileRenderViewports[constants_default.MOBILE_OS_ANDROID].length) {
|
|
1477
|
+
capturePromises.push(captureScreenshotsForConfig(ctx, browsers, staticConfig, constants_default.CHROME, mobileRenderViewports[constants_default.MOBILE_OS_ANDROID]));
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
return Promise.all(capturePromises);
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
function captureScreenshotsSync(ctx, staticConfig, browsers) {
|
|
1484
|
+
return __async(this, null, function* () {
|
|
1485
|
+
if (ctx.config.web) {
|
|
1486
|
+
for (let browserName of ctx.config.web.browsers) {
|
|
1487
|
+
let webRenderViewports = getWebRenderViewports(ctx);
|
|
1488
|
+
yield captureScreenshotsForConfig(ctx, browsers, staticConfig, browserName, webRenderViewports);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
if (ctx.config.mobile) {
|
|
1492
|
+
let mobileRenderViewports = getMobileRenderViewports(ctx);
|
|
1493
|
+
if (mobileRenderViewports[constants_default.MOBILE_OS_IOS].length) {
|
|
1494
|
+
yield captureScreenshotsForConfig(ctx, browsers, staticConfig, constants_default.SAFARI, mobileRenderViewports[constants_default.MOBILE_OS_IOS]);
|
|
1495
|
+
}
|
|
1496
|
+
if (mobileRenderViewports[constants_default.MOBILE_OS_ANDROID].length) {
|
|
1497
|
+
yield captureScreenshotsForConfig(ctx, browsers, staticConfig, constants_default.CHROME, mobileRenderViewports[constants_default.MOBILE_OS_ANDROID]);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
});
|
|
1501
|
+
}
|
|
1502
|
+
function captureScreenshots(ctx) {
|
|
1048
1503
|
return __async(this, null, function* () {
|
|
1049
|
-
var _a;
|
|
1050
1504
|
delDir("screenshots");
|
|
1051
|
-
let
|
|
1052
|
-
let totalViewports = ctx.webConfig.viewports.length;
|
|
1053
|
-
let totalScreenshots = screenshots.length;
|
|
1505
|
+
let browsers = {};
|
|
1054
1506
|
let capturedScreenshots = 0;
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1507
|
+
let output = "";
|
|
1508
|
+
try {
|
|
1509
|
+
browsers = yield launchBrowsers(ctx);
|
|
1510
|
+
} catch (error) {
|
|
1511
|
+
yield closeBrowsers(browsers);
|
|
1512
|
+
ctx.log.debug(error);
|
|
1513
|
+
throw new Error(`Failed launching browsers`);
|
|
1514
|
+
}
|
|
1515
|
+
for (let staticConfig of ctx.webStaticConfig) {
|
|
1060
1516
|
try {
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
browser = yield test.firefox.launch(launchOptions);
|
|
1070
|
-
break;
|
|
1071
|
-
case BROWSER_EDGE:
|
|
1072
|
-
launchOptions.channel = EDGE_CHANNEL;
|
|
1073
|
-
browser = yield test.chromium.launch(launchOptions);
|
|
1074
|
-
break;
|
|
1075
|
-
}
|
|
1076
|
-
const context = yield browser.newContext();
|
|
1077
|
-
for (let j = 0; j < totalScreenshots; j++) {
|
|
1078
|
-
let screenshot = screenshots[j];
|
|
1079
|
-
let screenshotId = screenshot.name.toLowerCase().replace(/\s/g, "-");
|
|
1080
|
-
const page = yield context.newPage();
|
|
1081
|
-
yield page.goto(screenshot.url.trim(), pageOptions);
|
|
1082
|
-
for (let k = 0; k < totalViewports; k++) {
|
|
1083
|
-
let { width, height } = ctx.webConfig.viewports[k];
|
|
1084
|
-
let ssName = `${browserName}-${width}x${height}-${screenshotId}.png`;
|
|
1085
|
-
let ssPath = `screenshots/${screenshotId}/${ssName}.png`;
|
|
1086
|
-
yield page.setViewportSize({ width, height: height || MIN_VIEWPORT_HEIGHT2 });
|
|
1087
|
-
if (height === 0)
|
|
1088
|
-
yield page.evaluate(scrollToBottomAndBackToTop);
|
|
1089
|
-
yield page.waitForTimeout(screenshot.waitForTimeout || 0);
|
|
1090
|
-
yield page.screenshot({ path: ssPath, fullPage: height ? false : true });
|
|
1091
|
-
let completed = i == totalBrowsers - 1 && j == totalScreenshots - 1 && k == totalViewports - 1 ? true : false;
|
|
1092
|
-
browserName = browserName === BROWSER_SAFARI ? PW_WEBKIT : browserName;
|
|
1093
|
-
ctx.client.uploadScreenshot(ctx.build, ssPath, screenshot.name, browserName, `${width}x${height}`, completed);
|
|
1094
|
-
capturedScreenshots++;
|
|
1095
|
-
ctx.task.output = chalk__default.default.gray(`screenshots captured: ${capturedScreenshots}/${totalBrowsers * totalViewports * totalScreenshots}`);
|
|
1096
|
-
}
|
|
1097
|
-
yield page.close();
|
|
1098
|
-
}
|
|
1099
|
-
yield browser.close();
|
|
1517
|
+
if (ctx.options.parallel)
|
|
1518
|
+
yield captureScreenshotsAsync(ctx, staticConfig, browsers);
|
|
1519
|
+
else
|
|
1520
|
+
yield captureScreenshotsSync(ctx, staticConfig, browsers);
|
|
1521
|
+
output += `${chalk8__default.default.gray(staticConfig.name)} ${chalk8__default.default.green("\u2713")}
|
|
1522
|
+
`;
|
|
1523
|
+
ctx.task.output = output;
|
|
1524
|
+
capturedScreenshots++;
|
|
1100
1525
|
} catch (error) {
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1526
|
+
ctx.log.debug(`screenshot capture failed for ${JSON.stringify(staticConfig)}; error: ${error}`);
|
|
1527
|
+
output += `${chalk8__default.default.gray(staticConfig.name)} ${chalk8__default.default.red("\u2717")}
|
|
1528
|
+
`;
|
|
1529
|
+
ctx.task.output = output;
|
|
1104
1530
|
}
|
|
1105
1531
|
}
|
|
1106
|
-
|
|
1532
|
+
yield closeBrowsers(browsers);
|
|
1533
|
+
delDir("screenshots");
|
|
1534
|
+
return { capturedScreenshots, output };
|
|
1107
1535
|
});
|
|
1108
1536
|
}
|
|
1109
1537
|
var captureScreenshots_default = (ctx) => {
|
|
@@ -1112,11 +1540,15 @@ var captureScreenshots_default = (ctx) => {
|
|
|
1112
1540
|
task: (ctx2, task) => __async(void 0, null, function* () {
|
|
1113
1541
|
try {
|
|
1114
1542
|
ctx2.task = task;
|
|
1115
|
-
|
|
1543
|
+
updateLogContext({ task: "capture" });
|
|
1544
|
+
let { capturedScreenshots, output } = yield captureScreenshots(ctx2);
|
|
1545
|
+
if (capturedScreenshots != ctx2.webStaticConfig.length) {
|
|
1546
|
+
throw new Error(output);
|
|
1547
|
+
}
|
|
1116
1548
|
task.title = "Screenshots captured successfully";
|
|
1117
|
-
task.output = chalk__default.default.gray(`total screenshots: ${totalScreenshots}`);
|
|
1118
1549
|
} catch (error) {
|
|
1119
|
-
|
|
1550
|
+
ctx2.log.debug(error);
|
|
1551
|
+
task.output = chalk8__default.default.gray(`${error.message}`);
|
|
1120
1552
|
throw new Error("Capturing screenshots failed");
|
|
1121
1553
|
}
|
|
1122
1554
|
}),
|
|
@@ -1127,15 +1559,15 @@ var captureScreenshots_default = (ctx) => {
|
|
|
1127
1559
|
|
|
1128
1560
|
// src/commander/capture.ts
|
|
1129
1561
|
var command2 = new commander.Command();
|
|
1130
|
-
command2.name("capture").description("Capture screenshots of static sites").argument("<file>", "Web static config file").action(function(file, _, command3) {
|
|
1562
|
+
command2.name("capture").description("Capture screenshots of static sites").argument("<file>", "Web static config file").option("--parallel", "Capture parallely on all browsers").action(function(file, _, command3) {
|
|
1131
1563
|
return __async(this, null, function* () {
|
|
1132
1564
|
let ctx = ctx_default(command3.optsWithGlobals());
|
|
1133
|
-
if (!
|
|
1565
|
+
if (!fs4__default.default.existsSync(file)) {
|
|
1134
1566
|
console.log(`Error: Web Static Config file ${file} not found.`);
|
|
1135
1567
|
return;
|
|
1136
1568
|
}
|
|
1137
1569
|
try {
|
|
1138
|
-
ctx.webStaticConfig = JSON.parse(
|
|
1570
|
+
ctx.webStaticConfig = JSON.parse(fs4__default.default.readFileSync(file, "utf8"));
|
|
1139
1571
|
if (!validateWebStaticConfig(ctx.webStaticConfig))
|
|
1140
1572
|
throw new Error(validateWebStaticConfig.errors[0].message);
|
|
1141
1573
|
} catch (error) {
|
|
@@ -1186,13 +1618,13 @@ LambdaTest SmartUI CLI v${package_default.version}`);
|
|
|
1186
1618
|
log.warn(`This version is deprecated. A new version ${latestVersion} is available!
|
|
1187
1619
|
`);
|
|
1188
1620
|
else if (package_default.version !== latestVersion)
|
|
1189
|
-
log.info(
|
|
1621
|
+
log.info(chalk8__default.default.gray(`A new version ${latestVersion} is available!
|
|
1190
1622
|
`));
|
|
1191
1623
|
else
|
|
1192
|
-
log.info(
|
|
1624
|
+
log.info(chalk8__default.default.gray("https://www.npmjs.com/package/@lambdatest/smartui-cli\n"));
|
|
1193
1625
|
} catch (error) {
|
|
1194
1626
|
log.debug(error);
|
|
1195
|
-
log.info(
|
|
1627
|
+
log.info(chalk8__default.default.gray("https://www.npmjs.com/package/@lambdatest/smartui-cli\n"));
|
|
1196
1628
|
}
|
|
1197
1629
|
commander_default.parse();
|
|
1198
1630
|
});
|