@lambdatest/smartui-cli 2.0.2 → 2.0.4

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 CHANGED
@@ -9,11 +9,13 @@ var path2 = require('path');
9
9
  var fastify = require('fastify');
10
10
  var fs = require('fs');
11
11
  var winston = require('winston');
12
+ var Ajv = require('ajv');
13
+ var addErrors = require('ajv-errors');
12
14
  var FormData = require('form-data');
13
15
  var axios = require('axios');
14
16
  var child_process = require('child_process');
15
17
  var spawn = require('cross-spawn');
16
- var playwright = require('playwright');
18
+ var test = require('@playwright/test');
17
19
 
18
20
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
19
21
 
@@ -22,6 +24,8 @@ var chalk__default = /*#__PURE__*/_interopDefault(chalk);
22
24
  var path2__default = /*#__PURE__*/_interopDefault(path2);
23
25
  var fastify__default = /*#__PURE__*/_interopDefault(fastify);
24
26
  var fs__default = /*#__PURE__*/_interopDefault(fs);
27
+ var Ajv__default = /*#__PURE__*/_interopDefault(Ajv);
28
+ var addErrors__default = /*#__PURE__*/_interopDefault(addErrors);
25
29
  var FormData__default = /*#__PURE__*/_interopDefault(FormData);
26
30
  var axios__default = /*#__PURE__*/_interopDefault(axios);
27
31
  var spawn__default = /*#__PURE__*/_interopDefault(spawn);
@@ -80,6 +84,7 @@ var server_default = (ctx) => __async(void 0, null, function* () {
80
84
  } catch (error) {
81
85
  reply.code(500).send({ error: { message: error.message } });
82
86
  }
87
+ ctx.totalSnapshots++;
83
88
  reply.code(200).send({ data: { message: "success" } });
84
89
  }));
85
90
  yield server.listen({ port: 8080 });
@@ -164,6 +169,7 @@ var auth_default = (ctx) => {
164
169
  task.title = "Authenticated with SmartUI";
165
170
  } catch (error) {
166
171
  ctx2.log.debug(error.message);
172
+ task.output = chalk__default.default.gray(error.message);
167
173
  throw new Error("Authentication failed");
168
174
  }
169
175
  }),
@@ -181,7 +187,7 @@ var DEFAULT_WEB_STATIC_CONFIG = [
181
187
  "url": "https://example.com/"
182
188
  }
183
189
  ];
184
- var DEFAULT_WEB_CONFIG = {
190
+ var DEFAULT_CONFIG = {
185
191
  web: {
186
192
  browsers: [
187
193
  "chrome",
@@ -190,27 +196,28 @@ var DEFAULT_WEB_CONFIG = {
190
196
  "edge"
191
197
  ],
192
198
  viewports: [
193
- [1920, 1080],
194
- [1366, 768],
195
- [360, 640]
196
- ]
199
+ [1920],
200
+ [1366],
201
+ [360]
202
+ ],
203
+ waitForTimeout: 1e3
197
204
  }
198
205
  };
199
- function createWebConfig(filepath) {
200
- filepath = filepath || "smartui-web.json";
206
+ function createConfig(filepath) {
207
+ filepath = filepath || ".smartui.json";
201
208
  let filetype = path2__default.default.extname(filepath);
202
209
  if (filetype != ".json") {
203
210
  console.log("Error: Config file must have .json extension");
204
211
  return;
205
212
  }
206
213
  if (fs__default.default.existsSync(filepath)) {
207
- console.log(`Error: SmartUI Web Config already exists: ${filepath}`);
208
- console.log(`To create a new file, please specify the file name like: 'smartui config:create-web webConfig.json'`);
214
+ console.log(`Error: SmartUI Config already exists: ${filepath}`);
215
+ console.log(`To create a new file, please specify the file name like: 'smartui config:create .smartui-config.json'`);
209
216
  return;
210
217
  }
211
218
  fs__default.default.mkdirSync(path2__default.default.dirname(filepath), { recursive: true });
212
- fs__default.default.writeFileSync(filepath, JSON.stringify(DEFAULT_WEB_CONFIG, null, 2) + "\n");
213
- console.log(`Created SmartUI Web Config: ${filepath}`);
219
+ fs__default.default.writeFileSync(filepath, JSON.stringify(DEFAULT_CONFIG, null, 2) + "\n");
220
+ console.log(`Created SmartUI Config: ${filepath}`);
214
221
  }
215
222
  function createWebStaticConfig(filepath) {
216
223
  filepath = filepath || "url.json";
@@ -221,7 +228,7 @@ function createWebStaticConfig(filepath) {
221
228
  }
222
229
  if (fs__default.default.existsSync(filepath)) {
223
230
  console.log(`Error: web-static config already exists: ${filepath}`);
224
- console.log(`To create a new file, please specify the file name like: 'smartui config:create-web links.json'`);
231
+ console.log(`To create a new file, please specify the file name like: 'smartui config:create-web-static links.json'`);
225
232
  return;
226
233
  }
227
234
  fs__default.default.mkdirSync(path2__default.default.dirname(filepath), { recursive: true });
@@ -230,12 +237,153 @@ function createWebStaticConfig(filepath) {
230
237
  }
231
238
 
232
239
  // package.json
233
- var version = "2.0.2";
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
+ }
304
+ },
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
333
+ },
334
+ uniqueItems: true
335
+ };
336
+ var validateConfig = ajv.compile(ConfigSchema);
337
+ var validateWebStaticConfig = ajv.compile(WebStaticConfigSchema);
338
+ var HTTP_SCHEME = "https:";
339
+ var HTTP_SCHEME_PREFIX = "https://";
340
+ var WWW = "www.";
234
341
  function delDir(dir) {
235
342
  if (fs__default.default.existsSync(dir)) {
236
343
  fs__default.default.rmSync(dir, { recursive: true });
237
344
  }
238
345
  }
346
+ function ensureHttps(urlString) {
347
+ try {
348
+ if (urlString && urlString.startsWith(WWW)) {
349
+ urlString = HTTP_SCHEME_PREFIX + urlString;
350
+ }
351
+ let url = new URL(urlString);
352
+ if (url.protocol !== HTTP_SCHEME) {
353
+ url.protocol = HTTP_SCHEME;
354
+ }
355
+ return url.toString();
356
+ } catch (error) {
357
+ console.error("Invalid URL: " + urlString, error);
358
+ return null;
359
+ }
360
+ }
361
+ function scrollToBottomAndBackToTop({
362
+ frequency = 100,
363
+ timing = 8,
364
+ remoteWindow = window
365
+ } = {}) {
366
+ return new Promise((resolve) => {
367
+ let scrolls = 1;
368
+ let scrollLength = remoteWindow.document.body.scrollHeight / frequency;
369
+ (function scroll() {
370
+ let scrollBy = scrollLength * scrolls;
371
+ remoteWindow.setTimeout(() => {
372
+ remoteWindow.scrollTo(0, scrollBy);
373
+ if (scrolls < frequency) {
374
+ scrolls += 1;
375
+ scroll();
376
+ }
377
+ if (scrolls === frequency) {
378
+ remoteWindow.setTimeout(() => {
379
+ remoteWindow.scrollTo(0, 0);
380
+ resolve();
381
+ }, timing);
382
+ }
383
+ }, timing);
384
+ })();
385
+ });
386
+ }
239
387
 
240
388
  // src/lib/httpClient.ts
241
389
  var httpClient = class {
@@ -286,18 +434,21 @@ var httpClient = class {
286
434
  },
287
435
  config: {
288
436
  browsers: config.browsers,
289
- resolutions: config.viewports
437
+ resolutions: config.viewports,
438
+ waitForPageRender: config.waitForPageRender,
439
+ waitForTimeout: config.waitForTimeout
290
440
  }
291
441
  }
292
442
  }, log);
293
443
  }
294
- finalizeBuild(buildId, log) {
444
+ finalizeBuild(buildId, totalSnapshots, log) {
445
+ let params = { buildId };
446
+ if (totalSnapshots > -1)
447
+ params.totalSnapshots = totalSnapshots;
295
448
  return this.request({
296
449
  url: "/build",
297
450
  method: "DELETE",
298
- params: {
299
- buildId
300
- }
451
+ params
301
452
  }, log);
302
453
  }
303
454
  uploadSnapshot(buildId, snapshot, testType, log) {
@@ -347,26 +498,34 @@ var httpClient = class {
347
498
  var ctx_default = (options) => {
348
499
  let env = env_default();
349
500
  let viewports = [];
350
- let webConfig = DEFAULT_WEB_CONFIG;
501
+ let config = DEFAULT_CONFIG;
351
502
  try {
352
503
  if (options.config) {
353
- webConfig = JSON.parse(fs__default.default.readFileSync(options.config, "utf-8"));
354
- }
355
- for (let viewport of webConfig.web.viewports) {
356
- viewports.push({ width: viewport[0], height: viewport[1] });
504
+ config = JSON.parse(fs__default.default.readFileSync(options.config, "utf-8"));
505
+ if (config.web.resolutions) {
506
+ config.web.viewports = config.web.resolutions;
507
+ delete config.web.resolutions;
508
+ }
357
509
  }
510
+ if (!validateConfig(config))
511
+ throw new Error(validateConfig.errors[0].message);
358
512
  } catch (error) {
359
- throw new Error(error.message);
513
+ console.log(`[smartui] Error: ${error.message}`);
514
+ process.exit();
360
515
  }
516
+ for (let viewport of config.web.viewports)
517
+ viewports.push({ width: viewport[0], height: viewport[1] || 0 });
361
518
  return {
362
519
  env,
363
520
  log: logger_default,
364
521
  client: new httpClient(env),
365
- config: {
366
- browsers: webConfig.web.browsers,
367
- viewports
522
+ webConfig: {
523
+ browsers: config.web.browsers,
524
+ viewports,
525
+ waitForPageRender: config.web.waitForPageRender || 0,
526
+ waitForTimeout: config.web.waitForTimeout || 0
368
527
  },
369
- staticConfig: [],
528
+ webStaticConfig: [],
370
529
  git: {
371
530
  branch: "",
372
531
  commitId: "",
@@ -382,7 +541,8 @@ var ctx_default = (options) => {
382
541
  projectId: ""
383
542
  },
384
543
  args: {},
385
- cliVersion: version
544
+ cliVersion: version,
545
+ totalSnapshots: -1
386
546
  };
387
547
  };
388
548
  function executeCommand(command3) {
@@ -445,7 +605,7 @@ var createBuild_default = (ctx) => {
445
605
  task: (ctx2, task) => __async(void 0, null, function* () {
446
606
  updateLogContext({ task: "createBuild" });
447
607
  try {
448
- let resp = yield ctx2.client.createBuild(ctx2.git, ctx2.config, ctx2.log);
608
+ let resp = yield ctx2.client.createBuild(ctx2.git, ctx2.webConfig, ctx2.log);
449
609
  ctx2.build = {
450
610
  id: resp.data.buildId,
451
611
  name: resp.data.buildName,
@@ -495,21 +655,22 @@ var exec_default = (ctx) => {
495
655
  }));
496
656
  });
497
657
  }),
498
- rendererOptions: { persistentOutput: true }
658
+ rendererOptions: { persistentOutput: true },
659
+ exitOnError: false
499
660
  };
500
661
  };
501
- var finalizeBuild_default = (ctx, waitTime) => {
662
+ var finalizeBuild_default = (ctx) => {
502
663
  return {
503
664
  title: `Finalizing build`,
504
665
  task: (ctx2, task) => __async(void 0, null, function* () {
505
666
  try {
506
- if (waitTime > 0) {
507
- yield new Promise((resolve) => setTimeout(resolve, waitTime));
508
- yield ctx2.client.finalizeBuild(ctx2.build.id, ctx2.log);
509
- }
667
+ yield new Promise((resolve) => setTimeout(resolve, 2e3));
668
+ yield ctx2.client.finalizeBuild(ctx2.build.id, ctx2.totalSnapshots, ctx2.log);
510
669
  task.output = chalk__default.default.gray(`build url: ${ctx2.build.url}`);
511
670
  task.title = "Finalized build";
512
671
  } catch (error) {
672
+ ctx2.log.debug(error.message);
673
+ task.output = chalk__default.default.gray(error.message);
513
674
  throw new Error("Finalize build error");
514
675
  }
515
676
  }),
@@ -528,6 +689,7 @@ command.name("exec").description("Run test commands around SmartUI").argument("<
528
689
  return;
529
690
  }
530
691
  ctx.args.execCommand = execCommand;
692
+ ctx.totalSnapshots = 0;
531
693
  let tasks = new listr2.Listr(
532
694
  [
533
695
  auth_default(),
@@ -535,7 +697,7 @@ command.name("exec").description("Run test commands around SmartUI").argument("<
535
697
  getGitInfo_default(),
536
698
  createBuild_default(),
537
699
  exec_default(ctx),
538
- finalizeBuild_default(ctx, 3e4)
700
+ finalizeBuild_default()
539
701
  ],
540
702
  {
541
703
  rendererOptions: {
@@ -560,12 +722,12 @@ command.name("exec").description("Run test commands around SmartUI").argument("<
560
722
  var exec_default2 = command;
561
723
  var configWeb = new commander.Command();
562
724
  var configStatic = new commander.Command();
563
- configWeb.name("config:create-web").description("Create SmartUI Web config file").argument("[filepath]", "Optional config filepath").action(function(filepath, options) {
725
+ configWeb.name("config:create").description("Create SmartUI config file").argument("[filepath]", "Optional config filepath").action(function(filepath, options) {
564
726
  return __async(this, null, function* () {
565
- createWebConfig(filepath);
727
+ createConfig(filepath);
566
728
  });
567
729
  });
568
- configStatic.name("config:web-static").description("Create Web Static config file").argument("[filepath]", "Optional config filepath").action(function(filepath, options) {
730
+ configStatic.name("config:create-web-static").description("Create Web Static config file").argument("[filepath]", "Optional config filepath").action(function(filepath, options) {
569
731
  return __async(this, null, function* () {
570
732
  createWebStaticConfig(filepath);
571
733
  });
@@ -575,51 +737,70 @@ var BROWSER_SAFARI = "safari";
575
737
  var BROWSER_FIREFOX = "firefox";
576
738
  var BROWSER_EDGE = "edge";
577
739
  var EDGE_CHANNEL = "msedge";
740
+ var PW_WEBKIT = "webkit";
741
+ var MIN_RESOLUTION_HEIGHT = 320;
578
742
  function captureScreenshots(ctx, screenshots) {
579
743
  return __async(this, null, function* () {
580
744
  var _a;
581
745
  delDir("screenshots");
582
- let totalBrowsers = ctx.config.browsers.length;
583
- let totalViewports = ctx.config.viewports.length;
746
+ let totalBrowsers = ctx.webConfig.browsers.length;
747
+ let totalViewports = ctx.webConfig.viewports.length;
584
748
  let totalScreenshots = screenshots.length;
749
+ let capturedScreenshots = 0;
585
750
  for (let i = 0; i < totalBrowsers; i++) {
586
- let browserName = (_a = ctx.config.browsers[i]) == null ? void 0 : _a.toLowerCase();
751
+ let browserName = (_a = ctx.webConfig.browsers[i]) == null ? void 0 : _a.toLowerCase();
587
752
  let browser;
588
753
  let launchOptions = { headless: true };
589
- switch (browserName) {
590
- case BROWSER_CHROME:
591
- browser = yield playwright.chromium.launch(launchOptions);
592
- break;
593
- case BROWSER_SAFARI:
594
- browser = yield playwright.webkit.launch(launchOptions);
595
- break;
596
- case BROWSER_FIREFOX:
597
- browser = yield playwright.firefox.launch(launchOptions);
598
- break;
599
- case BROWSER_EDGE:
600
- launchOptions.channel = EDGE_CHANNEL;
601
- browser = yield playwright.chromium.launch(launchOptions);
602
- break;
603
- }
604
- const context = yield browser.newContext();
605
- for (let j = 0; j < totalScreenshots; j++) {
606
- let screenshot = screenshots[j];
607
- let screenshotId = screenshot.name.toLowerCase().replace(/\s/g, "-");
608
- const page = yield context.newPage();
609
- yield page.goto(screenshot.url);
610
- yield page.waitForTimeout(screenshot.waitForTimeout || 0);
611
- for (let k = 0; k < totalViewports; k++) {
612
- let { width, height } = ctx.config.viewports[k];
613
- let ssName = `${browserName}-${width}x${height}-${screenshotId}.png`;
614
- let ssPath = `screenshots/${screenshotId}/${ssName}.png`;
615
- yield page.setViewportSize({ width, height });
616
- yield page.screenshot({ path: ssPath, fullPage: true });
617
- let completed = i == totalBrowsers - 1 && j == totalScreenshots - 1 && k == totalViewports - 1 ? true : false;
618
- ctx.client.uploadScreenshot(ctx.build, ssPath, screenshot.name, browserName, `${width}x${height}`, completed);
754
+ let pageOptions = { waitUntil: process.env.SMARTUI_PAGE_WAIT_UNTIL_EVENT || "load" };
755
+ try {
756
+ switch (browserName) {
757
+ case BROWSER_CHROME:
758
+ browser = yield test.chromium.launch(launchOptions);
759
+ break;
760
+ case BROWSER_SAFARI:
761
+ browser = yield test.webkit.launch(launchOptions);
762
+ break;
763
+ case BROWSER_FIREFOX:
764
+ browser = yield test.firefox.launch(launchOptions);
765
+ break;
766
+ case BROWSER_EDGE:
767
+ launchOptions.channel = EDGE_CHANNEL;
768
+ browser = yield test.chromium.launch(launchOptions);
769
+ break;
619
770
  }
620
- yield page.close();
771
+ const context = yield browser.newContext();
772
+ for (let j = 0; j < totalScreenshots; j++) {
773
+ let screenshot = screenshots[j];
774
+ let screenshotId = screenshot.name.toLowerCase().replace(/\s/g, "-");
775
+ const page = yield context.newPage();
776
+ if (screenshot.url) {
777
+ screenshot.url = screenshot.url.trim();
778
+ screenshot.url = ensureHttps(screenshot.url);
779
+ }
780
+ yield page.goto(screenshot.url, pageOptions);
781
+ for (let k = 0; k < totalViewports; k++) {
782
+ let { width, height } = ctx.webConfig.viewports[k];
783
+ let ssName = `${browserName}-${width}x${height}-${screenshotId}.png`;
784
+ let ssPath = `screenshots/${screenshotId}/${ssName}.png`;
785
+ yield page.setViewportSize({ width, height: height || MIN_RESOLUTION_HEIGHT });
786
+ if (height === 0)
787
+ yield page.evaluate(scrollToBottomAndBackToTop);
788
+ yield page.waitForTimeout(screenshot.waitForTimeout || 0);
789
+ yield page.screenshot({ path: ssPath, fullPage: height ? false : true });
790
+ let completed = i == totalBrowsers - 1 && j == totalScreenshots - 1 && k == totalViewports - 1 ? true : false;
791
+ browserName = browserName === BROWSER_SAFARI ? PW_WEBKIT : browserName;
792
+ ctx.client.uploadScreenshot(ctx.build, ssPath, screenshot.name, browserName, `${width}x${height}`, completed);
793
+ capturedScreenshots++;
794
+ ctx.task.output = chalk__default.default.gray(`screenshots captured: ${capturedScreenshots}/${totalBrowsers * totalViewports * totalScreenshots}`);
795
+ }
796
+ yield page.close();
797
+ }
798
+ yield browser.close();
799
+ } catch (error) {
800
+ if (browser)
801
+ yield browser.close();
802
+ throw error;
621
803
  }
622
- yield browser.close();
623
804
  }
624
805
  return totalBrowsers * totalViewports * totalScreenshots;
625
806
  });
@@ -629,16 +810,17 @@ var captureScreenshots_default = (ctx) => {
629
810
  title: "Capturing screenshots",
630
811
  task: (ctx2, task) => __async(void 0, null, function* () {
631
812
  try {
632
- let { staticConfig: screenshots } = ctx2;
633
- let totalScreenshots = yield captureScreenshots(ctx2, screenshots);
813
+ ctx2.task = task;
814
+ let totalScreenshots = yield captureScreenshots(ctx2, ctx2.webStaticConfig);
634
815
  task.title = "Screenshots captured successfully";
635
816
  task.output = chalk__default.default.gray(`total screenshots: ${totalScreenshots}`);
636
817
  } catch (error) {
637
- console.error(error);
818
+ task.output = chalk__default.default.gray(`${error.message}`);
638
819
  throw new Error("Capturing screenshots failed");
639
820
  }
640
821
  }),
641
- rendererOptions: { persistentOutput: true }
822
+ rendererOptions: { persistentOutput: true },
823
+ exitOnError: false
642
824
  };
643
825
  };
644
826
 
@@ -647,13 +829,25 @@ var command2 = new commander.Command();
647
829
  command2.name("capture").description("Capture screenshots of static sites").argument("<file>", "Web static config file").action(function(file, _, command3) {
648
830
  return __async(this, null, function* () {
649
831
  let ctx = ctx_default(command3.optsWithGlobals());
832
+ if (!fs__default.default.existsSync(file)) {
833
+ console.log(`Error: Web Static Config file ${file} not found.`);
834
+ return;
835
+ }
836
+ try {
837
+ ctx.webStaticConfig = JSON.parse(fs__default.default.readFileSync(file, "utf8"));
838
+ if (!validateWebStaticConfig(ctx.webStaticConfig))
839
+ throw new Error(validateWebStaticConfig.errors[0].message);
840
+ } catch (error) {
841
+ console.log(`[smartui] Error: Invalid Web Static Config; ${error.message}`);
842
+ return;
843
+ }
650
844
  let tasks = new listr2.Listr(
651
845
  [
652
846
  auth_default(),
653
847
  getGitInfo_default(),
654
848
  createBuild_default(),
655
849
  captureScreenshots_default(),
656
- finalizeBuild_default(ctx, 0)
850
+ finalizeBuild_default()
657
851
  ],
658
852
  {
659
853
  rendererOptions: {
@@ -667,11 +861,6 @@ command2.name("capture").description("Capture screenshots of static sites").argu
667
861
  }
668
862
  );
669
863
  try {
670
- if (!fs__default.default.existsSync(file)) {
671
- console.log(`Error: Config file ${file} not found.`);
672
- return;
673
- }
674
- ctx.staticConfig = JSON.parse(fs__default.default.readFileSync(file, "utf8"));
675
864
  yield tasks.run(ctx);
676
865
  } catch (error) {
677
866
  console.log("\nRefer docs: https://www.lambdatest.com/support/docs/smart-visual-regression-testing/");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdatest/smartui-cli",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
5
5
  "files": [
6
6
  "dist/**/*"
@@ -17,9 +17,15 @@
17
17
  "author": "LambdaTest <keys@lambdatest.com>",
18
18
  "license": "MIT",
19
19
  "dependencies": {
20
+ "@playwright/browser-chromium": "^1.40.1",
21
+ "@playwright/browser-firefox": "^1.40.1",
22
+ "@playwright/browser-webkit": "^1.40.1",
23
+ "@playwright/test": "^1.40.1",
20
24
  "@types/cross-spawn": "^6.0.4",
21
25
  "@types/node": "^20.8.9",
22
26
  "@types/which": "^3.0.2",
27
+ "ajv": "^8.12.0",
28
+ "ajv-errors": "^3.0.0",
23
29
  "axios": "^1.6.0",
24
30
  "chalk": "^4.1.2",
25
31
  "commander": "^11.1.0",
@@ -27,7 +33,6 @@
27
33
  "fastify": "^4.24.3",
28
34
  "form-data": "^4.0.0",
29
35
  "listr2": "^7.0.1",
30
- "playwright": "^1.39.0",
31
36
  "tsup": "^7.2.0",
32
37
  "which": "^4.0.0",
33
38
  "winston": "^3.10.0"