@lambdatest/smartui-cli 3.0.6 → 3.0.7

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 +218 -15
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -299,6 +299,19 @@ var constants_default = {
299
299
  "iPhone XR": { os: "ios", viewport: { width: 414, height: 896 } },
300
300
  "iPhone XS": { os: "ios", viewport: { width: 375, height: 812 } },
301
301
  "iPhone XS Max": { os: "ios", viewport: { width: 414, height: 896 } }
302
+ },
303
+ FIGMA_API: "https://api.figma.com/v1/",
304
+ DEFAULT_FIGMA_CONFIG: {
305
+ "depth": 2,
306
+ "figma_config": [
307
+ {
308
+ "figma_file_token": "token_for_first_figma_file",
309
+ "figma_ids": [
310
+ "id1",
311
+ "id2"
312
+ ]
313
+ }
314
+ ]
302
315
  }
303
316
  };
304
317
 
@@ -417,7 +430,7 @@ function getRenderViewports(ctx) {
417
430
  ...mobileRenderViewports[constants_default.MOBILE_OS_ANDROID]
418
431
  ];
419
432
  }
420
- var MAX_RESOURCE_SIZE = 10 * 1024 ** 2;
433
+ var MAX_RESOURCE_SIZE = 15 * 1024 ** 2;
421
434
  var ALLOWED_RESOURCES = ["document", "stylesheet", "image", "media", "font", "other"];
422
435
  var ALLOWED_STATUSES = [200, 201];
423
436
  var REQUEST_TIMEOUT = 1e4;
@@ -463,7 +476,7 @@ var processSnapshot_default = (snapshot, ctx) => __async(void 0, null, function*
463
476
  - skipping already cached resource`);
464
477
  } else if (body.length > MAX_RESOURCE_SIZE) {
465
478
  ctx.log.debug(`Handling request ${requestUrl}
466
- - skipping resource larger than 5MB`);
479
+ - skipping resource larger than 15MB`);
467
480
  } else if (!ALLOWED_STATUSES.includes(response.status())) {
468
481
  ctx.log.debug(`Handling request ${requestUrl}
469
482
  - skipping disallowed status [${response.status()}]`);
@@ -877,9 +890,56 @@ var SnapshotSchema = {
877
890
  additionalProperties: false,
878
891
  errorMessage: "Invalid snapshot"
879
892
  };
893
+ var FigmaDesignConfigSchema = {
894
+ type: "object",
895
+ properties: {
896
+ depth: {
897
+ type: "integer",
898
+ minimum: 2,
899
+ errorMessage: "Depth must be an integer and greater than 1"
900
+ },
901
+ figma_config: {
902
+ type: "array",
903
+ items: {
904
+ type: "object",
905
+ properties: {
906
+ figma_file_token: {
907
+ type: "string",
908
+ minLength: 1,
909
+ errorMessage: "figma_file_token is mandatory and cannot be empty"
910
+ },
911
+ figma_ids: {
912
+ type: "array",
913
+ items: {
914
+ type: "string",
915
+ minLength: 1,
916
+ errorMessage: "Each ID in figma_ids must be a non-empty string"
917
+ },
918
+ minItems: 1,
919
+ uniqueItems: true,
920
+ errorMessage: {
921
+ type: "figma_ids must be an array of strings",
922
+ minItems: "figma_ids cannot be empty",
923
+ uniqueItems: "figma_ids must contain unique values"
924
+ }
925
+ }
926
+ },
927
+ required: ["figma_file_token"],
928
+ additionalProperties: false
929
+ },
930
+ uniqueItems: true,
931
+ errorMessage: {
932
+ uniqueItems: "Each entry in the Figma design configuration must be unique"
933
+ }
934
+ }
935
+ },
936
+ required: ["figma_config"],
937
+ additionalProperties: false
938
+ };
880
939
  var validateConfig = ajv.compile(ConfigSchema);
881
940
  var validateWebStaticConfig = ajv.compile(WebStaticConfigSchema);
882
941
  var validateSnapshot = ajv.compile(SnapshotSchema);
942
+ var validateFigmaDesignConfig = ajv.compile(FigmaDesignConfigSchema);
883
943
 
884
944
  // src/lib/server.ts
885
945
  var server_default = (ctx) => __async(void 0, null, function* () {
@@ -922,7 +982,10 @@ var env_default = () => {
922
982
  SMARTUI_GIT_INFO_FILEPATH,
923
983
  HTTP_PROXY,
924
984
  HTTPS_PROXY,
925
- GITHUB_ACTIONS
985
+ GITHUB_ACTIONS,
986
+ FIGMA_TOKEN,
987
+ LT_USERNAME,
988
+ LT_ACCESS_KEY
926
989
  } = process.env;
927
990
  return {
928
991
  PROJECT_TOKEN,
@@ -932,7 +995,10 @@ var env_default = () => {
932
995
  SMARTUI_GIT_INFO_FILEPATH,
933
996
  HTTP_PROXY,
934
997
  HTTPS_PROXY,
935
- GITHUB_ACTIONS
998
+ GITHUB_ACTIONS,
999
+ FIGMA_TOKEN,
1000
+ LT_USERNAME,
1001
+ LT_ACCESS_KEY
936
1002
  };
937
1003
  };
938
1004
  var logContext = { task: "smartui-cli" };
@@ -1009,7 +1075,7 @@ var auth_default = (ctx) => {
1009
1075
  };
1010
1076
 
1011
1077
  // package.json
1012
- var version = "3.0.6";
1078
+ var version = "3.0.7";
1013
1079
  var package_default = {
1014
1080
  name: "@lambdatest/smartui-cli",
1015
1081
  version,
@@ -1172,6 +1238,25 @@ var httpClient = class {
1172
1238
  }
1173
1239
  }, log);
1174
1240
  }
1241
+ getFigmaFilesAndImages(figmaFileToken, figmaToken, queryParams, authToken, depth, markBaseline, buildName, log) {
1242
+ const requestBody = {
1243
+ figma_file_token: figmaFileToken,
1244
+ figma_token: figmaToken,
1245
+ query_params: queryParams,
1246
+ auth: authToken,
1247
+ depth,
1248
+ mark_base_line: markBaseline,
1249
+ build_name: buildName
1250
+ };
1251
+ return this.request({
1252
+ url: "/uploadfigma",
1253
+ method: "POST",
1254
+ headers: {
1255
+ "Content-Type": "application/json"
1256
+ },
1257
+ data: JSON.stringify(requestBody)
1258
+ }, log);
1259
+ }
1175
1260
  };
1176
1261
  var ctx_default = (options) => {
1177
1262
  var _a, _b;
@@ -1234,16 +1319,18 @@ var ctx_default = (options) => {
1234
1319
  },
1235
1320
  args: {},
1236
1321
  options: {
1237
- parallel: options.parallel ? true : false
1322
+ parallel: options.parallel ? true : false,
1323
+ markBaseline: options.markBaseline ? true : false,
1324
+ buildName: options.buildName || ""
1238
1325
  },
1239
1326
  cliVersion: version,
1240
1327
  totalSnapshots: -1
1241
1328
  };
1242
1329
  };
1243
- function executeCommand(command3) {
1330
+ function executeCommand(command4) {
1244
1331
  let dst = process.cwd();
1245
1332
  try {
1246
- return child_process.execSync(command3, {
1333
+ return child_process.execSync(command4, {
1247
1334
  cwd: dst,
1248
1335
  stdio: ["ignore"],
1249
1336
  encoding: "utf-8"
@@ -1273,8 +1360,8 @@ var git_default = (ctx) => {
1273
1360
  } else {
1274
1361
  const splitCharacter = "<##>";
1275
1362
  const prettyFormat = ["%h", "%H", "%s", "%f", "%b", "%at", "%ct", "%an", "%ae", "%cn", "%ce", "%N", ""];
1276
- const command3 = 'git log -1 --pretty=format:"' + prettyFormat.join(splitCharacter) + '" && git rev-parse --abbrev-ref HEAD && git tag --contains HEAD';
1277
- let res = executeCommand(command3).split(splitCharacter);
1363
+ const command4 = 'git log -1 --pretty=format:"' + prettyFormat.join(splitCharacter) + '" && git rev-parse --abbrev-ref HEAD && git tag --contains HEAD';
1364
+ let res = executeCommand(command4).split(splitCharacter);
1278
1365
  var branchAndTags = res[res.length - 1].split("\n").filter((n) => n);
1279
1366
  var branch = branchAndTags[0];
1280
1367
  branchAndTags.slice(1);
@@ -1389,10 +1476,10 @@ var finalizeBuild_default = (ctx) => {
1389
1476
 
1390
1477
  // src/commander/exec.ts
1391
1478
  var command = new commander.Command();
1392
- command.name("exec").description("Run test commands around SmartUI").argument("<command...>", "Command supplied for running tests").action(function(execCommand, _, command3) {
1479
+ command.name("exec").description("Run test commands around SmartUI").argument("<command...>", "Command supplied for running tests").action(function(execCommand, _, command4) {
1393
1480
  return __async(this, null, function* () {
1394
1481
  var _a, _b;
1395
- let ctx = ctx_default(command3.optsWithGlobals());
1482
+ let ctx = ctx_default(command4.optsWithGlobals());
1396
1483
  if (!which__default.default.sync(execCommand[0], { nothrow: true })) {
1397
1484
  ctx.log.error(`Error: Command not found "${execCommand[0]}"`);
1398
1485
  return;
@@ -1462,10 +1549,27 @@ function createWebStaticConfig(filepath) {
1462
1549
  fs5__default.default.writeFileSync(filepath, JSON.stringify(constants_default.DEFAULT_WEB_STATIC_CONFIG, null, 2) + "\n");
1463
1550
  console.log(`Created web-static config: ${filepath}`);
1464
1551
  }
1552
+ function createFigmaConfig(filepath) {
1553
+ filepath = filepath || "designs.json";
1554
+ let filetype = path2__default.default.extname(filepath);
1555
+ if (filetype != ".json") {
1556
+ console.log("Error: designs config file must have .json extension");
1557
+ return;
1558
+ }
1559
+ if (fs5__default.default.existsSync(filepath)) {
1560
+ console.log(`Error: designs config already exists: ${filepath}`);
1561
+ console.log(`To create a new file, please specify the file name like: 'smartui config:figma-config designs.json'`);
1562
+ return;
1563
+ }
1564
+ fs5__default.default.mkdirSync(path2__default.default.dirname(filepath), { recursive: true });
1565
+ fs5__default.default.writeFileSync(filepath, JSON.stringify(constants_default.DEFAULT_FIGMA_CONFIG, null, 2) + "\n");
1566
+ console.log(`Created designs config: ${filepath}`);
1567
+ }
1465
1568
 
1466
1569
  // src/commander/config.ts
1467
1570
  var configWeb = new commander.Command();
1468
1571
  var configStatic = new commander.Command();
1572
+ var configFigma = new commander.Command();
1469
1573
  configWeb.name("config:create").description("Create SmartUI config file").argument("[filepath]", "Optional config filepath").action(function(filepath, options) {
1470
1574
  return __async(this, null, function* () {
1471
1575
  createConfig(filepath);
@@ -1476,6 +1580,11 @@ configStatic.name("config:create-web-static").description("Create Web Static con
1476
1580
  createWebStaticConfig(filepath);
1477
1581
  });
1478
1582
  });
1583
+ configFigma.name("config:create-figma").description("Create figma designs config file").argument("[filepath]", "Optional config filepath").action(function(filepath, options) {
1584
+ return __async(this, null, function* () {
1585
+ createFigmaConfig(filepath);
1586
+ });
1587
+ });
1479
1588
  function captureScreenshotsForConfig(_0, _1, _2, _3, _4) {
1480
1589
  return __async(this, arguments, function* (ctx, browsers, { name, url, waitForTimeout }, browserName, renderViewports) {
1481
1590
  let pageOptions = { waitUntil: process.env.SMARTUI_PAGE_WAIT_UNTIL_EVENT || "load" };
@@ -1614,9 +1723,9 @@ var captureScreenshots_default = (ctx) => {
1614
1723
 
1615
1724
  // src/commander/capture.ts
1616
1725
  var command2 = new commander.Command();
1617
- 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) {
1726
+ 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, _, command4) {
1618
1727
  return __async(this, null, function* () {
1619
- let ctx = ctx_default(command3.optsWithGlobals());
1728
+ let ctx = ctx_default(command4.optsWithGlobals());
1620
1729
  if (!fs5__default.default.existsSync(file)) {
1621
1730
  console.log(`Error: Web Static Config file ${file} not found.`);
1622
1731
  return;
@@ -1657,9 +1766,103 @@ command2.name("capture").description("Capture screenshots of static sites").argu
1657
1766
  });
1658
1767
  var capture_default = command2;
1659
1768
 
1769
+ // src/lib/uploadFigmaDesigns.ts
1770
+ var uploadFigmaDesigns_default = (ctx) => __async(void 0, null, function* () {
1771
+ const depth = ctx.figmaDesignConfig.depth;
1772
+ const figmaConfigs = ctx.figmaDesignConfig.figma_config;
1773
+ let results = "";
1774
+ let figmaFileToken = "";
1775
+ const markBaseline = ctx.options.markBaseline;
1776
+ const buildName = ctx.options.buildName;
1777
+ for (const config of figmaConfigs) {
1778
+ figmaFileToken = config.figma_file_token;
1779
+ let queryParams = "";
1780
+ if (config.figma_ids && config.figma_ids.length > 0) {
1781
+ const fileIds = config.figma_ids.join(",");
1782
+ queryParams += `?ids=${fileIds}`;
1783
+ }
1784
+ const authToken = `Basic ${Buffer.from(`${ctx.env.LT_USERNAME}:${ctx.env.LT_ACCESS_KEY}`).toString("base64")}`;
1785
+ const responseData = yield ctx.client.getFigmaFilesAndImages(figmaFileToken, ctx.env.FIGMA_TOKEN, queryParams, authToken, depth, markBaseline, buildName, ctx.log);
1786
+ if (responseData.data.message == "success") {
1787
+ results = responseData.data.message;
1788
+ }
1789
+ }
1790
+ return results;
1791
+ });
1792
+
1793
+ // src/tasks/uploadFigmaDesigns.ts
1794
+ var uploadFigmaDesigns_default2 = (ctx) => {
1795
+ return {
1796
+ title: "Uploading Figma Designs",
1797
+ task: (ctx2, task) => __async(void 0, null, function* () {
1798
+ try {
1799
+ ctx2.task = task;
1800
+ updateLogContext({ task: "upload-figma" });
1801
+ let results = yield uploadFigmaDesigns_default(ctx2);
1802
+ if (results != "success") {
1803
+ throw new Error("Uploading Figma designs failed");
1804
+ }
1805
+ task.title = "Figma designs images uploaded successfully to SmartUI";
1806
+ ctx2.log.debug(`Figma designs processed: ${results}`);
1807
+ } catch (error) {
1808
+ ctx2.log.debug(error);
1809
+ task.output = chalk8__default.default.gray(`${error.message}`);
1810
+ throw new Error("Uploading Figma designs failed");
1811
+ }
1812
+ }),
1813
+ rendererOptions: { persistentOutput: true },
1814
+ exitOnError: false
1815
+ };
1816
+ };
1817
+
1818
+ // src/commander/uploadFigma.ts
1819
+ var command3 = new commander.Command();
1820
+ command3.name("upload-figma").description("Capture screenshots of static sites").argument("<file>", "figma design config file").option("--markBaseline", "Mark the uploaded images as baseline").option("--buildName <buildName>", "Name of the build").action(function(file, _, command4) {
1821
+ return __async(this, null, function* () {
1822
+ var _a, _b;
1823
+ let ctx = ctx_default(command4.optsWithGlobals());
1824
+ if (!fs5__default.default.existsSync(file)) {
1825
+ console.log(`Error: Figma Config file ${file} not found.`);
1826
+ return;
1827
+ }
1828
+ try {
1829
+ ctx.figmaDesignConfig = JSON.parse(fs5__default.default.readFileSync(file, "utf8"));
1830
+ if (!validateFigmaDesignConfig(ctx.figmaDesignConfig)) {
1831
+ const validationError = (_b = (_a = validateFigmaDesignConfig.errors) == null ? void 0 : _a[0]) == null ? void 0 : _b.message;
1832
+ throw new Error(validationError || "Invalid figma design Config");
1833
+ }
1834
+ } catch (error) {
1835
+ console.log(`[smartui] Error: Invalid figma design Config; ${error.message}`);
1836
+ return;
1837
+ }
1838
+ let tasks = new listr2.Listr(
1839
+ [
1840
+ auth_default(),
1841
+ uploadFigmaDesigns_default2()
1842
+ ],
1843
+ {
1844
+ rendererOptions: {
1845
+ icon: {
1846
+ [listr2.ListrDefaultRendererLogLevels.OUTPUT]: `\u2192`
1847
+ },
1848
+ color: {
1849
+ [listr2.ListrDefaultRendererLogLevels.OUTPUT]: listr2.color.gray
1850
+ }
1851
+ }
1852
+ }
1853
+ );
1854
+ try {
1855
+ yield tasks.run(ctx);
1856
+ } catch (error) {
1857
+ console.log("\nRefer docs: https://www.lambdatest.com/support/docs/smart-visual-regression-testing/");
1858
+ }
1859
+ });
1860
+ });
1861
+ var uploadFigma_default = command3;
1862
+
1660
1863
  // src/commander/commander.ts
1661
1864
  var program = new commander.Command();
1662
- 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);
1865
+ program.name("smartui").description("CLI to help you run your SmartUI tests on LambdaTest platform").version(`v${version}`).option("-c --config <filepath>", "Config file path").addCommand(exec_default2).addCommand(capture_default).addCommand(configWeb).addCommand(configStatic).addCommand(configFigma).addCommand(uploadFigma_default);
1663
1866
  var commander_default = program;
1664
1867
  (function() {
1665
1868
  return __async(this, null, function* () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdatest/smartui-cli",
3
- "version": "3.0.6",
3
+ "version": "3.0.7",
4
4
  "description": "A command line interface (CLI) to run SmartUI tests on LambdaTest",
5
5
  "files": [
6
6
  "dist/**/*"