@lambdatest/smartui-cli 2.0.4 → 2.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.cjs +395 -134
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -8,14 +8,14 @@ var chalk = require('chalk');
8
8
  var path2 = require('path');
9
9
  var fastify = require('fastify');
10
10
  var fs = require('fs');
11
- var winston = require('winston');
11
+ var test = require('@playwright/test');
12
12
  var Ajv = require('ajv');
13
13
  var addErrors = require('ajv-errors');
14
+ var winston = require('winston');
14
15
  var FormData = require('form-data');
15
16
  var axios = require('axios');
16
17
  var child_process = require('child_process');
17
18
  var spawn = require('cross-spawn');
18
- var test = require('@playwright/test');
19
19
 
20
20
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
21
21
 
@@ -66,6 +66,270 @@ var __async = (__this, __arguments, generator) => {
66
66
  step((generator = generator.apply(__this, __arguments)).next());
67
67
  });
68
68
  };
69
+ var MIN_VIEWPORT_HEIGHT = 1080;
70
+ var processSnapshot_default = (snapshot, ctx) => __async(void 0, null, function* () {
71
+ let options = snapshot.options;
72
+ let optionWarnings = /* @__PURE__ */ new Set();
73
+ let processedOptions = {};
74
+ if (options && Object.keys(options).length !== 0) {
75
+ ctx.log.debug(`Processing options: ${JSON.stringify(options)}`);
76
+ if (options.ignoreDOM && Object.keys(options.ignoreDOM).length !== 0 || options.selectDOM && Object.keys(options.selectDOM).length !== 0) {
77
+ if (!ctx.browser)
78
+ ctx.browser = yield test.chromium.launch({ headless: true });
79
+ let ignoreOrSelectDOM;
80
+ let ignoreOrSelectBoxes;
81
+ if (options.ignoreDOM && Object.keys(options.ignoreDOM).length !== 0) {
82
+ processedOptions.ignoreBoxes = {};
83
+ ignoreOrSelectDOM = "ignoreDOM";
84
+ ignoreOrSelectBoxes = "ignoreBoxes";
85
+ } else {
86
+ processedOptions.selectBoxes = {};
87
+ ignoreOrSelectDOM = "selectDOM";
88
+ ignoreOrSelectBoxes = "selectBoxes";
89
+ }
90
+ let selectors = [];
91
+ for (const [key, value] of Object.entries(options[ignoreOrSelectDOM])) {
92
+ switch (key) {
93
+ case "id":
94
+ selectors.push(...value.map((e) => "#" + e));
95
+ break;
96
+ case "class":
97
+ selectors.push(...value.map((e) => "." + e));
98
+ break;
99
+ case "xpath":
100
+ selectors.push(...value.map((e) => "xpath=" + e));
101
+ break;
102
+ case "cssSelector":
103
+ selectors.push(...value);
104
+ break;
105
+ }
106
+ }
107
+ for (const vp of ctx.webConfig.viewports) {
108
+ const page = yield ctx.browser.newPage({ viewport: { width: vp.width, height: vp.height || MIN_VIEWPORT_HEIGHT } });
109
+ yield page.setContent(snapshot.dom.html);
110
+ let viewport = `${vp.width}${vp.height ? "x" + vp.height : ""}`;
111
+ if (!Array.isArray(processedOptions[ignoreOrSelectBoxes][viewport]))
112
+ processedOptions[ignoreOrSelectBoxes][viewport] = [];
113
+ let locators = [];
114
+ let boxes = [];
115
+ for (const selector of selectors) {
116
+ let l = yield page.locator(selector).all();
117
+ if (l.length === 0) {
118
+ optionWarnings.add(`For snapshot ${snapshot.name}, no element found for selector ${selector}`);
119
+ continue;
120
+ }
121
+ locators.push(...l);
122
+ }
123
+ for (const locator of locators) {
124
+ let bb = yield locator.boundingBox();
125
+ if (bb)
126
+ boxes.push({
127
+ left: bb.x,
128
+ top: bb.y,
129
+ right: bb.x + bb.width,
130
+ bottom: bb.y + bb.height
131
+ });
132
+ }
133
+ processedOptions[ignoreOrSelectBoxes][viewport].push(...boxes);
134
+ yield page.close();
135
+ }
136
+ }
137
+ }
138
+ return {
139
+ processedSnapshot: {
140
+ name: snapshot.name,
141
+ url: snapshot.url,
142
+ dom: Buffer.from(snapshot.dom.html).toString("base64"),
143
+ options: processedOptions
144
+ },
145
+ warnings: [...optionWarnings, ...snapshot.dom.warnings]
146
+ };
147
+ });
148
+ var ajv = new Ajv__default.default({ allErrors: true });
149
+ ajv.addFormat("web-url", {
150
+ type: "string",
151
+ validate: (url) => {
152
+ const urlPattern = new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$", "i");
153
+ return urlPattern.test(url.trim());
154
+ }
155
+ });
156
+ addErrors__default.default(ajv);
157
+ var ConfigSchema = {
158
+ type: "object",
159
+ properties: {
160
+ web: {
161
+ type: "object",
162
+ properties: {
163
+ browsers: {
164
+ type: "array",
165
+ items: { type: "string", enum: ["chrome", "firefox", "edge", "safari"] },
166
+ uniqueItems: true,
167
+ maxItems: 4,
168
+ errorMessage: "Invalid config; allowed browsers - chrome, firefox, edge, safari"
169
+ },
170
+ viewports: {
171
+ type: "array",
172
+ items: {
173
+ type: "array",
174
+ oneOf: [
175
+ {
176
+ items: [{ type: "number", minimum: 320, maximum: 7680 }],
177
+ minItems: 1,
178
+ maxItems: 1
179
+ },
180
+ {
181
+ items: [
182
+ { type: "number", minimum: 320, maximum: 7680 },
183
+ { type: "number", minimum: 320, maximum: 7680 }
184
+ ],
185
+ minItems: 2,
186
+ maxItems: 2
187
+ }
188
+ ],
189
+ errorMessage: "Invalid config; width/height must be >= 320 and <= 7680"
190
+ },
191
+ uniqueItems: true,
192
+ maxItems: 5,
193
+ errorMessage: "Invalid config; max unique viewports allowed - 5"
194
+ },
195
+ waitForPageRender: {
196
+ type: "number",
197
+ minimum: 0,
198
+ maximum: 3e5,
199
+ errorMessage: "Invalid config; waitForPageRender must be > 0 and <= 300000"
200
+ },
201
+ waitForTimeout: {
202
+ type: "number",
203
+ minimum: 0,
204
+ maximum: 3e4,
205
+ errorMessage: "Invalid config; waitForTimeout must be > 0 and <= 30000"
206
+ }
207
+ },
208
+ required: ["browsers", "viewports"],
209
+ additionalProperties: false
210
+ }
211
+ },
212
+ required: ["web"],
213
+ additionalProperties: false
214
+ };
215
+ var WebStaticConfigSchema = {
216
+ type: "array",
217
+ items: {
218
+ type: "object",
219
+ properties: {
220
+ name: {
221
+ type: "string",
222
+ minLength: 1,
223
+ errorMessage: "name is mandatory and cannot be empty"
224
+ },
225
+ url: {
226
+ type: "string",
227
+ format: "web-url",
228
+ errorMessage: "url is mandatory and must be a valid web URL"
229
+ },
230
+ waitForTimeout: {
231
+ type: "number",
232
+ nullable: true,
233
+ minimum: 0,
234
+ maximum: 3e4,
235
+ errorMessage: "waitForTimeout must be > 0 and <= 30000"
236
+ }
237
+ },
238
+ required: ["name", "url"],
239
+ additionalProperties: false
240
+ },
241
+ uniqueItems: true
242
+ };
243
+ var SnapshotSchema = {
244
+ type: "object",
245
+ properties: {
246
+ name: {
247
+ type: "string",
248
+ minLength: 1,
249
+ errorMessage: "Invalid snapshot; name is mandatory and cannot be empty"
250
+ },
251
+ url: {
252
+ type: "string",
253
+ format: "web-url",
254
+ errorMessage: "Invalid snapshot; url is mandatory and must be a valid web URL"
255
+ },
256
+ dom: {
257
+ type: "object"
258
+ },
259
+ options: {
260
+ type: "object",
261
+ properties: {
262
+ ignoreDOM: {
263
+ type: "object",
264
+ properties: {
265
+ id: {
266
+ type: "array",
267
+ items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; id cannot be empty or have semicolon" },
268
+ uniqueItems: true,
269
+ errorMessage: "Invalid snapshot options; id array must have unique items"
270
+ },
271
+ class: {
272
+ type: "array",
273
+ items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; class cannot be empty or have semicolon" },
274
+ uniqueItems: true,
275
+ errorMessage: "Invalid snapshot options; class array must have unique items"
276
+ },
277
+ cssSelector: {
278
+ type: "array",
279
+ items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; cssSelector cannot be empty or have semicolon" },
280
+ uniqueItems: true,
281
+ errorMessage: "Invalid snapshot options; cssSelector array must have unique items"
282
+ },
283
+ xpath: {
284
+ type: "array",
285
+ items: { type: "string", minLength: 1 },
286
+ uniqueItems: true,
287
+ errorMessage: "Invalid snapshot options; xpath array must have unique and non-empty items"
288
+ }
289
+ }
290
+ },
291
+ selectDOM: {
292
+ type: "object",
293
+ properties: {
294
+ id: {
295
+ type: "array",
296
+ items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; id cannot be empty or have semicolon" },
297
+ uniqueItems: true,
298
+ errorMessage: "Invalid snapshot options; id array must have unique items"
299
+ },
300
+ class: {
301
+ type: "array",
302
+ items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; class cannot be empty or have semicolon" },
303
+ uniqueItems: true,
304
+ errorMessage: "Invalid snapshot options; class array must have unique items"
305
+ },
306
+ cssSelector: {
307
+ type: "array",
308
+ items: { type: "string", minLength: 1, pattern: "^[^;]*$", errorMessage: "Invalid snapshot options; cssSelector cannot be empty or have semicolon" },
309
+ uniqueItems: true,
310
+ errorMessage: "Invalid snapshot options; cssSelector array must have unique items"
311
+ },
312
+ xpath: {
313
+ type: "array",
314
+ items: { type: "string", minLength: 1 },
315
+ uniqueItems: true,
316
+ errorMessage: "Invalid snapshot options; xpath array must have unique and non-empty items"
317
+ }
318
+ }
319
+ }
320
+ },
321
+ additionalProperties: false
322
+ }
323
+ },
324
+ required: ["name", "url", "dom"],
325
+ additionalProperties: false,
326
+ errorMessage: "Invalid snapshot"
327
+ };
328
+ var validateConfig = ajv.compile(ConfigSchema);
329
+ var validateWebStaticConfig = ajv.compile(WebStaticConfigSchema);
330
+ var validateSnapshot = ajv.compile(SnapshotSchema);
331
+
332
+ // src/lib/server.ts
69
333
  var server_default = (ctx) => __async(void 0, null, function* () {
70
334
  const server = fastify__default.default({ logger: false, bodyLimit: 1e7 });
71
335
  const opts = {};
@@ -77,17 +341,19 @@ var server_default = (ctx) => __async(void 0, null, function* () {
77
341
  reply.code(200).send({ data: { dom: SMARTUI_DOM } });
78
342
  });
79
343
  server.post("/snapshot", opts, (request, reply) => __async(void 0, null, function* () {
80
- let { snapshot, testType } = request.body;
81
- snapshot.dom = Buffer.from(snapshot.dom).toString("base64");
82
344
  try {
83
- yield ctx.client.uploadSnapshot(ctx.build.id, snapshot, testType, ctx.log);
345
+ let { snapshot, testType } = request.body;
346
+ if (!validateSnapshot(snapshot))
347
+ throw new Error(validateSnapshot.errors[0].message);
348
+ let { processedSnapshot, warnings } = yield processSnapshot_default(snapshot, ctx);
349
+ yield ctx.client.uploadSnapshot(ctx.build.id, processedSnapshot, testType, ctx.log);
350
+ ctx.totalSnapshots++;
351
+ reply.code(200).send({ data: { message: "success", warnings } });
84
352
  } catch (error) {
85
- reply.code(500).send({ error: { message: error.message } });
353
+ return reply.code(500).send({ error: { message: error.message } });
86
354
  }
87
- ctx.totalSnapshots++;
88
- reply.code(200).send({ data: { message: "success" } });
89
355
  }));
90
- yield server.listen({ port: 8080 });
356
+ yield server.listen();
91
357
  let { port } = server.addresses()[0];
92
358
  process.env.SMARTUI_SERVER_ADDRESS = `http://localhost:${port}`;
93
359
  return server;
@@ -98,42 +364,47 @@ var env_default = () => {
98
364
  const {
99
365
  PROJECT_TOKEN = "",
100
366
  SMARTUI_CLIENT_API_URL = "https://api.lambdatest.com/visualui/1.0",
101
- SMARTUI_LOG_LEVEL,
102
- SMARTUI_DEBUG
367
+ LT_SDK_LOG_LEVEL,
368
+ LT_SDK_DEBUG
103
369
  } = process.env;
104
370
  return {
105
371
  PROJECT_TOKEN,
106
372
  SMARTUI_CLIENT_API_URL,
107
- SMARTUI_LOG_LEVEL,
108
- SMARTUI_DEBUG
373
+ LT_SDK_LOG_LEVEL,
374
+ LT_SDK_DEBUG
109
375
  };
110
376
  };
111
-
112
- // src/lib/logger.ts
113
- var logContext = {};
377
+ var logContext = { task: "smartui-cli" };
114
378
  function updateLogContext(newContext) {
115
379
  logContext = __spreadValues(__spreadValues({}, logContext), newContext);
116
380
  }
117
381
  var logLevel = () => {
118
382
  let env = env_default();
119
- let debug = env.SMARTUI_DEBUG === "true" ? "debug" : void 0;
120
- return debug || env.SMARTUI_LOG_LEVEL || "info";
383
+ let debug = env.LT_SDK_DEBUG === "true" ? "debug" : void 0;
384
+ return debug || env.LT_SDK_LOG_LEVEL || "info";
121
385
  };
122
386
  var logger = winston.createLogger({
123
387
  level: logLevel(),
124
388
  format: winston.format.combine(
125
389
  winston.format.timestamp(),
126
390
  winston.format.printf((info) => {
127
- let contextString;
128
- if (logContext && Object.keys(logContext).length) {
129
- contextString = Object.values(logContext).join(" | ");
391
+ let contextString = Object.values(logContext).join(" | ");
392
+ let message = typeof info.message === "object" ? JSON.stringify(info.message) : info.message;
393
+ switch (info.level) {
394
+ case "debug":
395
+ message = chalk__default.default.blue(message);
396
+ break;
397
+ case "warn":
398
+ message = chalk__default.default.yellow(message);
399
+ break;
400
+ case "error":
401
+ message = chalk__default.default.red(message);
402
+ break;
130
403
  }
131
- let message = `[${contextString}:${info.level}] `;
132
- message += info.message === "object" ? JSON.stringify(info.message) : info.message;
133
- return message;
404
+ return info.level === "info" ? message : `[${contextString}:${info.level}] ` + message;
134
405
  })
135
406
  ),
136
- transports: [new winston.transports.File({ filename: "smartui.log" })]
407
+ transports: [new winston.transports.Console()]
137
408
  });
138
409
  var logger_default = logger;
139
410
 
@@ -149,9 +420,8 @@ var startServer_default = (ctx) => {
149
420
  task.output = chalk__default.default.gray(`listening on port ${(_a = ctx2.server.addresses()[0]) == null ? void 0 : _a.port}`);
150
421
  task.title = "SmartUI started";
151
422
  } catch (error) {
152
- if (error.code === "EADDRINUSE") {
153
- task.output = chalk__default.default.gray(`port 8080 is already in use`);
154
- }
423
+ ctx2.log.debug(error);
424
+ task.output = chalk__default.default.gray(error.message);
155
425
  throw new Error("SmartUI server setup failed");
156
426
  }
157
427
  }),
@@ -168,7 +438,7 @@ var auth_default = (ctx) => {
168
438
  task.output = chalk__default.default.gray(`using project token '******#${ctx2.env.PROJECT_TOKEN.split("#").pop()}'`);
169
439
  task.title = "Authenticated with SmartUI";
170
440
  } catch (error) {
171
- ctx2.log.debug(error.message);
441
+ ctx2.log.debug(error);
172
442
  task.output = chalk__default.default.gray(error.message);
173
443
  throw new Error("Authentication failed");
174
444
  }
@@ -237,104 +507,54 @@ function createWebStaticConfig(filepath) {
237
507
  }
238
508
 
239
509
  // package.json
240
- var version = "2.0.4";
241
- var ajv = new Ajv__default.default({ allErrors: true });
242
- ajv.addFormat("web-url", {
243
- type: "string",
244
- validate: (url) => {
245
- const urlPattern = new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$", "i");
246
- return urlPattern.test(url.trim());
247
- }
248
- });
249
- addErrors__default.default(ajv);
250
- var ConfigSchema = {
251
- type: "object",
252
- properties: {
253
- web: {
254
- type: "object",
255
- properties: {
256
- browsers: {
257
- type: "array",
258
- items: { type: "string", enum: ["chrome", "firefox", "edge", "safari"] },
259
- uniqueItems: true,
260
- maxItems: 4,
261
- errorMessage: "Invalid config; allowed browsers - chrome, firefox, edge, safari"
262
- },
263
- viewports: {
264
- type: "array",
265
- items: {
266
- type: "array",
267
- oneOf: [
268
- {
269
- items: [{ type: "number", minimum: 320, maximum: 7680 }],
270
- minItems: 1,
271
- maxItems: 1
272
- },
273
- {
274
- items: [
275
- { type: "number", minimum: 320, maximum: 7680 },
276
- { type: "number", minimum: 320, maximum: 7680 }
277
- ],
278
- minItems: 2,
279
- maxItems: 2
280
- }
281
- ],
282
- errorMessage: "Invalid config; width/height must be >= 320 and <= 7680"
283
- },
284
- uniqueItems: true,
285
- maxItems: 5,
286
- errorMessage: "Invalid config; max unique viewports allowed - 5"
287
- },
288
- waitForPageRender: {
289
- type: "number",
290
- minimum: 0,
291
- maximum: 3e5,
292
- errorMessage: "Invalid config; waitForPageRender must be > 0 and <= 300000"
293
- },
294
- waitForTimeout: {
295
- type: "number",
296
- minimum: 0,
297
- maximum: 3e4,
298
- errorMessage: "Invalid config; waitForTimeout must be > 0 and <= 30000"
299
- }
300
- },
301
- required: ["browsers", "viewports"],
302
- additionalProperties: false
303
- }
510
+ var version = "2.0.6";
511
+ var package_default = {
512
+ name: "@lambdatest/smartui-cli",
513
+ version,
514
+ description: "A command line interface (CLI) to run SmartUI tests on LambdaTest",
515
+ files: [
516
+ "dist/**/*"
517
+ ],
518
+ scripts: {
519
+ build: "tsup",
520
+ release: "pnpm run build && pnpm publish --access public --no-git-checks"
304
521
  },
305
- required: ["web"],
306
- additionalProperties: false
307
- };
308
- var WebStaticConfigSchema = {
309
- type: "array",
310
- items: {
311
- type: "object",
312
- properties: {
313
- name: {
314
- type: "string",
315
- minLength: 1,
316
- errorMessage: "name is mandatory and cannot be empty"
317
- },
318
- url: {
319
- type: "string",
320
- format: "web-url",
321
- errorMessage: "url is mandatory and must be a valid web URL"
322
- },
323
- waitForTimeout: {
324
- type: "number",
325
- nullable: true,
326
- minimum: 0,
327
- maximum: 3e4,
328
- errorMessage: "waitForTimeout must be > 0 and <= 30000"
329
- }
330
- },
331
- required: ["name", "url"],
332
- additionalProperties: false
522
+ bin: {
523
+ smartui: "./dist/index.cjs"
333
524
  },
334
- uniqueItems: true
525
+ type: "module",
526
+ keywords: [
527
+ "lambdatest",
528
+ "smartui",
529
+ "cli"
530
+ ],
531
+ author: "LambdaTest <keys@lambdatest.com>",
532
+ license: "MIT",
533
+ dependencies: {
534
+ "@playwright/browser-chromium": "^1.40.1",
535
+ "@playwright/browser-firefox": "^1.40.1",
536
+ "@playwright/browser-webkit": "^1.40.1",
537
+ "@playwright/test": "^1.40.1",
538
+ "@types/cross-spawn": "^6.0.4",
539
+ "@types/node": "^20.8.9",
540
+ "@types/which": "^3.0.2",
541
+ ajv: "^8.12.0",
542
+ "ajv-errors": "^3.0.0",
543
+ axios: "^1.6.0",
544
+ chalk: "^4.1.2",
545
+ commander: "^11.1.0",
546
+ "cross-spawn": "^7.0.3",
547
+ fastify: "^4.24.3",
548
+ "form-data": "^4.0.0",
549
+ listr2: "^7.0.1",
550
+ tsup: "^7.2.0",
551
+ which: "^4.0.0",
552
+ winston: "^3.10.0"
553
+ },
554
+ devDependencies: {
555
+ typescript: "^5.3.2"
556
+ }
335
557
  };
336
- var validateConfig = ajv.compile(ConfigSchema);
337
- var validateWebStaticConfig = ajv.compile(WebStaticConfigSchema);
338
558
  var HTTP_SCHEME = "https:";
339
559
  var HTTP_SCHEME_PREFIX = "https://";
340
560
  var WWW = "www.";
@@ -405,11 +625,18 @@ var httpClient = class {
405
625
  return resp.data;
406
626
  }).catch((error) => {
407
627
  if (error.response) {
628
+ log.debug(`http response: ${JSON.stringify({
629
+ status: error.response.status,
630
+ headers: error.response.headers,
631
+ body: error.response.data
632
+ })}`);
408
633
  throw new Error(JSON.stringify(error.response.data));
409
634
  }
410
635
  if (error.request) {
636
+ log.debug(`http request failed: ${error.toJSON()}`);
411
637
  throw new Error(error.toJSON().message);
412
638
  }
639
+ log.debug(`http request failed: ${error.message}`);
413
640
  throw new Error(error.message);
414
641
  });
415
642
  });
@@ -494,6 +721,17 @@ var httpClient = class {
494
721
  throw new Error(error.message);
495
722
  });
496
723
  }
724
+ checkUpdate(log) {
725
+ return this.request({
726
+ url: `/packageinfo`,
727
+ method: "GET",
728
+ headers: { "Content-Type": "application/json" },
729
+ params: {
730
+ packageName: package_default.name,
731
+ packageVersion: package_default.version
732
+ }
733
+ }, log);
734
+ }
497
735
  };
498
736
  var ctx_default = (options) => {
499
737
  let env = env_default();
@@ -592,6 +830,7 @@ var getGitInfo_default = (ctx) => {
592
830
  task.output = chalk__default.default.gray(`branch: ${ctx2.git.branch}, commit: ${ctx2.git.commitId}, author: ${ctx2.git.commitAuthor}`);
593
831
  task.title = "Fetched git information";
594
832
  } catch (error) {
833
+ ctx2.log.debug(error);
595
834
  task.output = chalk__default.default.gray(`${error.message}`);
596
835
  throw new Error("Error fetching git repo details");
597
836
  }
@@ -616,6 +855,7 @@ var createBuild_default = (ctx) => {
616
855
  task.output = chalk__default.default.gray(`build id: ${resp.data.buildId}`);
617
856
  task.title = "SmartUI build created";
618
857
  } catch (error) {
858
+ ctx2.log.debug(error);
619
859
  task.output = chalk__default.default.gray(JSON.parse(error.message).message);
620
860
  throw new Error("SmartUI build creation failed");
621
861
  }
@@ -669,9 +909,9 @@ var finalizeBuild_default = (ctx) => {
669
909
  task.output = chalk__default.default.gray(`build url: ${ctx2.build.url}`);
670
910
  task.title = "Finalized build";
671
911
  } catch (error) {
672
- ctx2.log.debug(error.message);
912
+ ctx2.log.debug(error);
673
913
  task.output = chalk__default.default.gray(error.message);
674
- throw new Error("Finalize build error");
914
+ throw new Error("Finalize build failed");
675
915
  }
676
916
  }),
677
917
  rendererOptions: { persistentOutput: true }
@@ -682,10 +922,10 @@ var finalizeBuild_default = (ctx) => {
682
922
  var command = new commander.Command();
683
923
  command.name("exec").description("Run test commands around SmartUI").argument("<command...>", "Command supplied for running tests").action(function(execCommand, _, command3) {
684
924
  return __async(this, null, function* () {
685
- var _a;
925
+ var _a, _b;
686
926
  let ctx = ctx_default(command3.optsWithGlobals());
687
927
  if (!which__default.default.sync(execCommand[0], { nothrow: true })) {
688
- console.log(`Error: Command not found "${execCommand[0]}"`);
928
+ ctx.log.error(`Error: Command not found "${execCommand[0]}"`);
689
929
  return;
690
930
  }
691
931
  ctx.args.execCommand = execCommand;
@@ -713,9 +953,10 @@ command.name("exec").description("Run test commands around SmartUI").argument("<
713
953
  try {
714
954
  yield tasks.run(ctx);
715
955
  } catch (error) {
716
- console.log("\nRefer docs: https://www.lambdatest.com/support/docs/smart-visual-regression-testing/");
956
+ ctx.log.info("\nRefer docs: https://www.lambdatest.com/support/docs/smart-visual-regression-testing/");
717
957
  } finally {
718
958
  yield (_a = ctx.server) == null ? void 0 : _a.close();
959
+ yield (_b = ctx.browser) == null ? void 0 : _b.close();
719
960
  }
720
961
  });
721
962
  });
@@ -738,7 +979,7 @@ var BROWSER_FIREFOX = "firefox";
738
979
  var BROWSER_EDGE = "edge";
739
980
  var EDGE_CHANNEL = "msedge";
740
981
  var PW_WEBKIT = "webkit";
741
- var MIN_RESOLUTION_HEIGHT = 320;
982
+ var MIN_VIEWPORT_HEIGHT2 = 1080;
742
983
  function captureScreenshots(ctx, screenshots) {
743
984
  return __async(this, null, function* () {
744
985
  var _a;
@@ -782,7 +1023,7 @@ function captureScreenshots(ctx, screenshots) {
782
1023
  let { width, height } = ctx.webConfig.viewports[k];
783
1024
  let ssName = `${browserName}-${width}x${height}-${screenshotId}.png`;
784
1025
  let ssPath = `screenshots/${screenshotId}/${ssName}.png`;
785
- yield page.setViewportSize({ width, height: height || MIN_RESOLUTION_HEIGHT });
1026
+ yield page.setViewportSize({ width, height: height || MIN_VIEWPORT_HEIGHT2 });
786
1027
  if (height === 0)
787
1028
  yield page.evaluate(scrollToBottomAndBackToTop);
788
1029
  yield page.waitForTimeout(screenshot.waitForTimeout || 0);
@@ -873,6 +1114,26 @@ var capture_default = command2;
873
1114
  var program = new commander.Command();
874
1115
  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);
875
1116
  var commander_default = program;
876
-
877
- // src/index.ts
878
- commander_default.parse();
1117
+ (function() {
1118
+ return __async(this, null, function* () {
1119
+ let client = new httpClient(env_default());
1120
+ let log = logger_default;
1121
+ try {
1122
+ log.info(`
1123
+ LambdaTest SmartUI CLI v${package_default.version}`);
1124
+ let { data: { latestVersion, deprecated } } = yield client.checkUpdate(log);
1125
+ if (deprecated)
1126
+ log.warn(`This version is deprecated. A new version ${latestVersion} is available!
1127
+ `);
1128
+ else if (package_default.version !== latestVersion)
1129
+ log.info(chalk__default.default.gray(`A new version ${latestVersion} is available!
1130
+ `));
1131
+ else
1132
+ log.info(chalk__default.default.gray("https://www.npmjs.com/package/@lambdatest/smartui-cli\n"));
1133
+ } catch (error) {
1134
+ log.debug(error);
1135
+ log.info(chalk__default.default.gray("https://www.npmjs.com/package/@lambdatest/smartui-cli\n"));
1136
+ }
1137
+ commander_default.parse();
1138
+ });
1139
+ })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdatest/smartui-cli",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
5
5
  "files": [
6
6
  "dist/**/*"