@featurevisor/core 1.26.0 → 1.27.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.
Files changed (102) hide show
  1. package/.eslintcache +1 -1
  2. package/CHANGELOG.md +22 -0
  3. package/coverage/clover.xml +2 -2
  4. package/coverage/lcov-report/index.html +1 -1
  5. package/coverage/lcov-report/lib/builder/allocator.js.html +1 -1
  6. package/coverage/lcov-report/lib/builder/index.html +1 -1
  7. package/coverage/lcov-report/lib/builder/revision.js.html +1 -1
  8. package/coverage/lcov-report/lib/builder/traffic.js.html +1 -1
  9. package/coverage/lcov-report/lib/tester/checkIfObjectsAreEqual.js.html +1 -1
  10. package/coverage/lcov-report/lib/tester/index.html +1 -1
  11. package/coverage/lcov-report/lib/tester/matrix.js.html +1 -1
  12. package/coverage/lcov-report/src/builder/allocator.ts.html +1 -1
  13. package/coverage/lcov-report/src/builder/index.html +1 -1
  14. package/coverage/lcov-report/src/builder/revision.ts.html +1 -1
  15. package/coverage/lcov-report/src/builder/traffic.ts.html +1 -1
  16. package/coverage/lcov-report/src/tester/checkIfObjectsAreEqual.ts.html +1 -1
  17. package/coverage/lcov-report/src/tester/index.html +1 -1
  18. package/coverage/lcov-report/src/tester/matrix.ts.html +1 -1
  19. package/lib/assess-distribution/index.d.ts +2 -0
  20. package/lib/assess-distribution/index.js +37 -1
  21. package/lib/assess-distribution/index.js.map +1 -1
  22. package/lib/benchmark/index.d.ts +2 -0
  23. package/lib/benchmark/index.js +43 -1
  24. package/lib/benchmark/index.js.map +1 -1
  25. package/lib/builder/buildProject.d.ts +2 -0
  26. package/lib/builder/buildProject.js +48 -1
  27. package/lib/builder/buildProject.js.map +1 -1
  28. package/lib/cli/cli.d.ts +26 -0
  29. package/lib/cli/cli.js +133 -0
  30. package/lib/cli/cli.js.map +1 -0
  31. package/lib/cli/index.d.ts +2 -0
  32. package/lib/cli/index.js +19 -0
  33. package/lib/cli/index.js.map +1 -0
  34. package/lib/cli/plugins.d.ts +4 -0
  35. package/lib/cli/plugins.js +37 -0
  36. package/lib/cli/plugins.js.map +1 -0
  37. package/lib/config/projectConfig.d.ts +3 -0
  38. package/lib/config/projectConfig.js +69 -1
  39. package/lib/config/projectConfig.js.map +1 -1
  40. package/lib/evaluate/index.d.ts +2 -0
  41. package/lib/evaluate/index.js +35 -1
  42. package/lib/evaluate/index.js.map +1 -1
  43. package/lib/find-duplicate-segments/index.d.ts +2 -0
  44. package/lib/find-duplicate-segments/index.js +34 -1
  45. package/lib/find-duplicate-segments/index.js.map +1 -1
  46. package/lib/find-usage/index.d.ts +2 -0
  47. package/lib/find-usage/index.js +50 -1
  48. package/lib/find-usage/index.js.map +1 -1
  49. package/lib/generate-code/index.d.ts +2 -0
  50. package/lib/generate-code/index.js +31 -1
  51. package/lib/generate-code/index.js.map +1 -1
  52. package/lib/index.d.ts +1 -0
  53. package/lib/index.js +1 -0
  54. package/lib/index.js.map +1 -1
  55. package/lib/info/index.d.ts +2 -0
  56. package/lib/info/index.js +28 -1
  57. package/lib/info/index.js.map +1 -1
  58. package/lib/init/index.d.ts +2 -0
  59. package/lib/init/index.js +65 -1
  60. package/lib/init/index.js.map +1 -1
  61. package/lib/linter/featureSchema.d.ts +71 -1
  62. package/lib/linter/featureSchema.js +147 -8
  63. package/lib/linter/featureSchema.js.map +1 -1
  64. package/lib/linter/lintProject.d.ts +3 -0
  65. package/lib/linter/lintProject.js +344 -163
  66. package/lib/linter/lintProject.js.map +1 -1
  67. package/lib/linter/printError.js +1 -3
  68. package/lib/linter/printError.js.map +1 -1
  69. package/lib/restore/index.d.ts +2 -0
  70. package/lib/restore/index.js +28 -1
  71. package/lib/restore/index.js.map +1 -1
  72. package/lib/site/index.d.ts +2 -2
  73. package/lib/site/index.js +86 -14
  74. package/lib/site/index.js.map +1 -1
  75. package/lib/tester/cliFormat.d.ts +1 -0
  76. package/lib/tester/cliFormat.js +2 -1
  77. package/lib/tester/cliFormat.js.map +1 -1
  78. package/lib/tester/testProject.d.ts +2 -0
  79. package/lib/tester/testProject.js +52 -1
  80. package/lib/tester/testProject.js.map +1 -1
  81. package/package.json +3 -2
  82. package/src/assess-distribution/index.ts +32 -0
  83. package/src/benchmark/index.ts +40 -0
  84. package/src/builder/buildProject.ts +42 -0
  85. package/src/cli/cli.ts +105 -0
  86. package/src/cli/index.ts +2 -0
  87. package/src/cli/plugins.ts +38 -0
  88. package/src/config/projectConfig.ts +28 -0
  89. package/src/evaluate/index.ts +30 -0
  90. package/src/find-duplicate-segments/index.ts +28 -0
  91. package/src/find-usage/index.ts +44 -0
  92. package/src/generate-code/index.ts +25 -0
  93. package/src/index.ts +1 -0
  94. package/src/info/index.ts +19 -0
  95. package/src/init/index.ts +21 -0
  96. package/src/linter/featureSchema.ts +194 -10
  97. package/src/linter/lintProject.ts +170 -18
  98. package/src/linter/printError.ts +1 -3
  99. package/src/restore/index.ts +19 -0
  100. package/src/site/index.ts +46 -2
  101. package/src/tester/cliFormat.ts +1 -0
  102. package/src/tester/testProject.ts +46 -0
@@ -12,16 +12,25 @@ import { checkForCircularDependencyInRequired } from "./checkCircularDependency"
12
12
  import { checkForFeatureExceedingGroupSlotPercentage } from "./checkPercentageExceedingSlot";
13
13
  import { printZodError } from "./printError";
14
14
  import { Dependencies } from "../dependencies";
15
- import { CLI_FORMAT_RED, CLI_FORMAT_UNDERLINE } from "../tester/cliFormat";
15
+ import { CLI_FORMAT_RED, CLI_FORMAT_BOLD_UNDERLINE } from "../tester/cliFormat";
16
+ import { Plugin } from "../cli";
16
17
 
17
18
  export interface LintProjectOptions {
18
19
  keyPattern?: string;
19
20
  entityType?: string;
21
+ authors?: boolean;
20
22
  }
21
23
 
22
24
  const ENTITY_NAME_REGEX = /^[a-zA-Z0-9_\-.]+$/;
23
25
  const ENTITY_NAME_REGEX_ERROR = "Names must be alphanumeric and can contain _, -, and .";
24
26
 
27
+ async function getAuthorsOfEntity(datasource, entityType, entityKey): Promise<string[]> {
28
+ const entries = await datasource.listHistoryEntries(entityType, entityKey);
29
+ const authors: string[] = Array.from(new Set(entries.map((entry) => entry.author)));
30
+
31
+ return authors;
32
+ }
33
+
25
34
  export async function lintProject(
26
35
  deps: Dependencies,
27
36
  options: LintProjectOptions = {},
@@ -80,7 +89,13 @@ export async function lintProject(
80
89
  const fullPath = getFullPathFromKey("attribute", key);
81
90
 
82
91
  if (!ENTITY_NAME_REGEX.test(key)) {
83
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
92
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
93
+
94
+ if (options.authors) {
95
+ const authors = await getAuthorsOfEntity(datasource, "attribute", key);
96
+ console.log(` Authors: ${authors.join(", ")}\n`);
97
+ }
98
+
84
99
  console.log(CLI_FORMAT_RED, ` => Error: Invalid name: "${key}"`);
85
100
  console.log(CLI_FORMAT_RED, ` ${ENTITY_NAME_REGEX_ERROR}`);
86
101
  console.log("");
@@ -93,7 +108,12 @@ export async function lintProject(
93
108
  const result = attributeZodSchema.safeParse(parsed);
94
109
 
95
110
  if (!result.success) {
96
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
111
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
112
+
113
+ if (options.authors) {
114
+ const authors = await getAuthorsOfEntity(datasource, "attribute", key);
115
+ console.log(` Authors: ${authors.join(", ")}\n`);
116
+ }
97
117
 
98
118
  if ("error" in result) {
99
119
  printZodError(result.error);
@@ -102,7 +122,13 @@ export async function lintProject(
102
122
  hasError = true;
103
123
  }
104
124
  } catch (e) {
105
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
125
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
126
+
127
+ if (options.authors) {
128
+ const authors = await getAuthorsOfEntity(datasource, "attribute", key);
129
+ console.log(` Authors: ${authors.join(", ")}\n`);
130
+ }
131
+
106
132
  console.log("");
107
133
  console.log(e);
108
134
 
@@ -130,7 +156,13 @@ export async function lintProject(
130
156
  const fullPath = getFullPathFromKey("segment", key);
131
157
 
132
158
  if (!ENTITY_NAME_REGEX.test(key)) {
133
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
159
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
160
+
161
+ if (options.authors) {
162
+ const authors = await getAuthorsOfEntity(datasource, "segment", key);
163
+ console.log(` Authors: ${authors.join(", ")}\n`);
164
+ }
165
+
134
166
  console.log(CLI_FORMAT_RED, ` => Error: Invalid name: "${key}"`);
135
167
  console.log(CLI_FORMAT_RED, ` ${ENTITY_NAME_REGEX_ERROR}`);
136
168
  console.log("");
@@ -143,7 +175,12 @@ export async function lintProject(
143
175
  const result = segmentZodSchema.safeParse(parsed);
144
176
 
145
177
  if (!result.success) {
146
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
178
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
179
+
180
+ if (options.authors) {
181
+ const authors = await getAuthorsOfEntity(datasource, "segment", key);
182
+ console.log(` Authors: ${authors.join(", ")}\n`);
183
+ }
147
184
 
148
185
  if ("error" in result) {
149
186
  printZodError(result.error);
@@ -152,7 +189,13 @@ export async function lintProject(
152
189
  hasError = true;
153
190
  }
154
191
  } catch (e) {
155
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
192
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
193
+
194
+ if (options.authors) {
195
+ const authors = await getAuthorsOfEntity(datasource, "segment", key);
196
+ console.log(` Authors: ${authors.join(", ")}\n`);
197
+ }
198
+
156
199
  console.log("");
157
200
  console.log(e);
158
201
 
@@ -182,7 +225,13 @@ export async function lintProject(
182
225
  const fullPath = getFullPathFromKey("feature", key);
183
226
 
184
227
  if (!ENTITY_NAME_REGEX.test(key)) {
185
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
228
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
229
+
230
+ if (options.authors) {
231
+ const authors = await getAuthorsOfEntity(datasource, "feature", key);
232
+ console.log(` Authors: ${authors.join(", ")}\n`);
233
+ }
234
+
186
235
  console.log(CLI_FORMAT_RED, ` => Error: Invalid name: "${key}"`);
187
236
  console.log(CLI_FORMAT_RED, ` ${ENTITY_NAME_REGEX_ERROR}`);
188
237
  console.log("");
@@ -197,7 +246,12 @@ export async function lintProject(
197
246
  const result = featureZodSchema.safeParse(parsed);
198
247
 
199
248
  if (!result.success) {
200
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
249
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
250
+
251
+ if (options.authors) {
252
+ const authors = await getAuthorsOfEntity(datasource, "feature", key);
253
+ console.log(` Authors: ${authors.join(", ")}\n`);
254
+ }
201
255
 
202
256
  if ("error" in result) {
203
257
  printZodError(result.error);
@@ -206,7 +260,13 @@ export async function lintProject(
206
260
  hasError = true;
207
261
  }
208
262
  } catch (e) {
209
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
263
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
264
+
265
+ if (options.authors) {
266
+ const authors = await getAuthorsOfEntity(datasource, "feature", key);
267
+ console.log(` Authors: ${authors.join(", ")}\n`);
268
+ }
269
+
210
270
  console.log("");
211
271
  console.log(e);
212
272
 
@@ -217,8 +277,15 @@ export async function lintProject(
217
277
  try {
218
278
  await checkForCircularDependencyInRequired(datasource, key, parsed.required);
219
279
  } catch (e) {
220
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
280
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
281
+
282
+ if (options.authors) {
283
+ const authors = await getAuthorsOfEntity(datasource, "feature", key);
284
+ console.log(` Authors: ${authors.join(", ")}\n`);
285
+ }
286
+
221
287
  console.log(CLI_FORMAT_RED, ` => Error: ${e.message}`);
288
+
222
289
  hasError = true;
223
290
  }
224
291
  }
@@ -240,8 +307,14 @@ export async function lintProject(
240
307
  const fullPath = getFullPathFromKey("group", key);
241
308
 
242
309
  if (!ENTITY_NAME_REGEX.test(key)) {
243
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
310
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
244
311
  console.log(CLI_FORMAT_RED, ` => Error: Invalid name: "${key}"`);
312
+
313
+ if (options.authors) {
314
+ const authors = await getAuthorsOfEntity(datasource, "group", key);
315
+ console.log(` Authors: ${authors.join(", ")}\n`);
316
+ }
317
+
245
318
  console.log(CLI_FORMAT_RED, ` ${ENTITY_NAME_REGEX_ERROR}`);
246
319
  console.log("");
247
320
  hasError = true;
@@ -255,7 +328,12 @@ export async function lintProject(
255
328
  const result = groupZodSchema.safeParse(parsed);
256
329
 
257
330
  if (!result.success) {
258
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
331
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
332
+
333
+ if (options.authors) {
334
+ const authors = await getAuthorsOfEntity(datasource, "group", key);
335
+ console.log(` Authors: ${authors.join(", ")}\n`);
336
+ }
259
337
 
260
338
  if ("error" in result) {
261
339
  printZodError(result.error);
@@ -264,7 +342,13 @@ export async function lintProject(
264
342
  hasError = true;
265
343
  }
266
344
  } catch (e) {
267
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
345
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
346
+
347
+ if (options.authors) {
348
+ const authors = await getAuthorsOfEntity(datasource, "group", key);
349
+ console.log(` Authors: ${authors.join(", ")}\n`);
350
+ }
351
+
268
352
  console.log("");
269
353
  console.log(e);
270
354
 
@@ -275,7 +359,7 @@ export async function lintProject(
275
359
  try {
276
360
  await checkForFeatureExceedingGroupSlotPercentage(datasource, parsed, features);
277
361
  } catch (e) {
278
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
362
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
279
363
  console.log(CLI_FORMAT_RED, ` => Error: ${e.message}`);
280
364
  hasError = true;
281
365
  }
@@ -305,7 +389,13 @@ export async function lintProject(
305
389
  const fullPath = getFullPathFromKey("test", key);
306
390
 
307
391
  if (!ENTITY_NAME_REGEX.test(key)) {
308
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
392
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
393
+
394
+ if (options.authors) {
395
+ const authors = await getAuthorsOfEntity(datasource, "test", key);
396
+ console.log(` Authors: ${authors.join(", ")}\n`);
397
+ }
398
+
309
399
  console.log(CLI_FORMAT_RED, ` => Error: Invalid name: "${key}"`);
310
400
  console.log(CLI_FORMAT_RED, ` ${ENTITY_NAME_REGEX_ERROR}`);
311
401
  console.log("");
@@ -318,7 +408,12 @@ export async function lintProject(
318
408
  const result = testsZodSchema.safeParse(parsed);
319
409
 
320
410
  if (!result.success) {
321
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
411
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
412
+
413
+ if (options.authors) {
414
+ const authors = await getAuthorsOfEntity(datasource, "test", key);
415
+ console.log(` Authors: ${authors.join(", ")}\n`);
416
+ }
322
417
 
323
418
  if ("error" in result) {
324
419
  printZodError(result.error);
@@ -329,7 +424,13 @@ export async function lintProject(
329
424
  hasError = true;
330
425
  }
331
426
  } catch (e) {
332
- console.log(CLI_FORMAT_UNDERLINE, fullPath);
427
+ console.log(CLI_FORMAT_BOLD_UNDERLINE, fullPath);
428
+
429
+ if (options.authors) {
430
+ const authors = await getAuthorsOfEntity(datasource, "test", key);
431
+ console.log(` Authors: ${authors.join(", ")}\n`);
432
+ }
433
+
333
434
  console.log("");
334
435
  console.log(e);
335
436
 
@@ -340,3 +441,54 @@ export async function lintProject(
340
441
 
341
442
  return hasError;
342
443
  }
444
+
445
+ export const lintPlugin: Plugin = {
446
+ command: "lint",
447
+ handler: async function (options) {
448
+ const { rootDirectoryPath, projectConfig, datasource, parsed } = options;
449
+
450
+ const hasError = await lintProject(
451
+ {
452
+ rootDirectoryPath,
453
+ projectConfig,
454
+ datasource,
455
+ options: parsed,
456
+ },
457
+ {
458
+ keyPattern: parsed.keyPattern,
459
+ entityType: parsed.entityType,
460
+ authors: parsed.authors,
461
+ },
462
+ );
463
+
464
+ if (hasError) {
465
+ return false;
466
+ }
467
+ },
468
+ examples: [
469
+ {
470
+ command: "lint",
471
+ description: "lint all entities",
472
+ },
473
+ {
474
+ command: "lint --entityType=feature",
475
+ description: "lint only features",
476
+ },
477
+ {
478
+ command: "lint --entityType=segment",
479
+ description: "lint only segments",
480
+ },
481
+ {
482
+ command: "lint --entityType=group",
483
+ description: "lint only groups",
484
+ },
485
+ {
486
+ command: "lint --entityType=test",
487
+ description: "lint only tests",
488
+ },
489
+ {
490
+ command: 'lint --keyPattern="abc"',
491
+ description: `lint only entities with keys containing "abc"`,
492
+ },
493
+ ],
494
+ };
@@ -22,8 +22,6 @@ export function printZodError(e: ZodError) {
22
22
  }
23
23
  }
24
24
 
25
- if (issues.length > 1) {
26
- console.error("");
27
- }
25
+ console.error("");
28
26
  });
29
27
  }
@@ -2,6 +2,7 @@ import * as path from "path";
2
2
  import { execSync } from "child_process";
3
3
 
4
4
  import { Dependencies } from "../dependencies";
5
+ import { Plugin } from "../cli";
5
6
 
6
7
  export async function restoreProject(deps: Dependencies) {
7
8
  const { rootDirectoryPath, projectConfig } = deps;
@@ -21,3 +22,21 @@ export async function restoreProject(deps: Dependencies) {
21
22
  throw new Error("Failed to restore state files.");
22
23
  }
23
24
  }
25
+
26
+ export const restorePlugin: Plugin = {
27
+ command: "restore",
28
+ handler: async function ({ rootDirectoryPath, projectConfig, datasource, parsed }) {
29
+ await restoreProject({
30
+ rootDirectoryPath,
31
+ projectConfig,
32
+ datasource,
33
+ options: parsed,
34
+ });
35
+ },
36
+ examples: [
37
+ {
38
+ command: "restore",
39
+ description: "restore state files",
40
+ },
41
+ ],
42
+ };
package/src/site/index.ts CHANGED
@@ -1,2 +1,46 @@
1
- export * from "./exportSite";
2
- export * from "./serveSite";
1
+ import { Plugin } from "../cli";
2
+ import { exportSite } from "./exportSite";
3
+ import { serveSite } from "./serveSite";
4
+
5
+ export const sitePlugin: Plugin = {
6
+ command: "site [subcommand]",
7
+ handler: async function ({ rootDirectoryPath, projectConfig, datasource, parsed }) {
8
+ const deps = {
9
+ rootDirectoryPath,
10
+ projectConfig,
11
+ datasource,
12
+ options: parsed,
13
+ };
14
+
15
+ const allowedSubcommands = ["export", "serve"];
16
+
17
+ if (!allowedSubcommands.includes(parsed.subcommand)) {
18
+ console.log("Please specify a subcommand: `export` or `serve`");
19
+ return;
20
+ }
21
+
22
+ // export
23
+ if (parsed.subcommand === "export") {
24
+ const hasError = await exportSite(deps);
25
+
26
+ if (hasError) {
27
+ return false;
28
+ }
29
+ }
30
+
31
+ // serve
32
+ if (parsed.subcommand === "serve") {
33
+ serveSite(deps);
34
+ }
35
+ },
36
+ examples: [
37
+ {
38
+ command: "site export",
39
+ description: "generate static site with project data",
40
+ },
41
+ {
42
+ command: "site serve",
43
+ description: "serve already exported site locally",
44
+ },
45
+ ],
46
+ };
@@ -3,3 +3,4 @@ export const CLI_FORMAT_GREEN = "\x1b[32m%s\x1b[0m";
3
3
 
4
4
  export const CLI_FORMAT_BOLD = "\x1b[1m%s\x1b[0m";
5
5
  export const CLI_FORMAT_UNDERLINE = "\x1b[4m%s\x1b[0m";
6
+ export const CLI_FORMAT_BOLD_UNDERLINE = "\x1b[1m\x1b[4m%s\x1b[0m";
@@ -11,6 +11,7 @@ import { printTestResult } from "./printTestResult";
11
11
 
12
12
  import { buildDatafile } from "../builder";
13
13
  import { SCHEMA_VERSION } from "../config";
14
+ import { Plugin } from "../cli";
14
15
 
15
16
  export interface TestProjectOptions {
16
17
  keyPattern?: string;
@@ -211,3 +212,48 @@ export async function testProject(
211
212
 
212
213
  return hasError;
213
214
  }
215
+
216
+ export const testPlugin: Plugin = {
217
+ command: "test",
218
+ handler: async function ({ rootDirectoryPath, projectConfig, datasource, parsed }) {
219
+ const hasError = await testProject(
220
+ {
221
+ rootDirectoryPath,
222
+ projectConfig,
223
+ datasource,
224
+ options: parsed,
225
+ },
226
+ parsed as TestProjectOptions,
227
+ );
228
+
229
+ if (hasError) {
230
+ return false;
231
+ }
232
+ },
233
+ examples: [
234
+ {
235
+ command: "test",
236
+ description: "run all tests",
237
+ },
238
+ {
239
+ command: "test --keyPattern=pattern",
240
+ description: "run tests matching key pattern",
241
+ },
242
+ {
243
+ command: "test --assertionPattern=pattern",
244
+ description: "run tests matching assertion pattern",
245
+ },
246
+ {
247
+ command: "test --onlyFailures",
248
+ description: "run only failed tests",
249
+ },
250
+ {
251
+ command: "test --showDatafile",
252
+ description: "show datafile content for each test",
253
+ },
254
+ {
255
+ command: "test --verbose",
256
+ description: "show all test results",
257
+ },
258
+ ],
259
+ };