@japa/runner 3.0.0-8 → 3.0.0

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 (52) hide show
  1. package/build/factories/create_diverse_tests.d.ts +6 -0
  2. package/build/factories/create_diverse_tests.js +106 -0
  3. package/build/factories/main.d.ts +5 -42
  4. package/build/factories/main.js +24 -208
  5. package/build/factories/runner.d.ts +26 -0
  6. package/build/factories/runner.js +93 -0
  7. package/build/index.d.ts +9 -14
  8. package/build/index.js +202 -237
  9. package/build/modules/core/main.d.ts +63 -3
  10. package/build/modules/core/main.js +121 -21
  11. package/build/modules/core/reporters/base.d.ts +41 -0
  12. package/build/modules/core/reporters/base.js +183 -0
  13. package/build/modules/core/types.d.ts +5 -0
  14. package/build/modules/core/types.js +9 -0
  15. package/build/src/cli_parser.d.ts +14 -0
  16. package/build/src/cli_parser.js +75 -0
  17. package/build/src/config_manager.d.ts +18 -0
  18. package/build/src/config_manager.js +168 -0
  19. package/build/src/create_test.d.ts +21 -0
  20. package/build/src/create_test.js +53 -0
  21. package/build/src/debug.d.ts +3 -0
  22. package/build/src/debug.js +10 -0
  23. package/build/src/exceptions_manager.d.ts +19 -0
  24. package/build/src/exceptions_manager.js +85 -0
  25. package/build/src/files_manager.d.ts +18 -0
  26. package/build/src/files_manager.js +57 -0
  27. package/build/src/helpers.d.ts +15 -0
  28. package/build/src/helpers.js +34 -0
  29. package/build/src/hooks.d.ts +20 -0
  30. package/build/src/hooks.js +46 -0
  31. package/build/src/planner.d.ts +25 -0
  32. package/build/src/planner.js +98 -0
  33. package/build/src/plugins/retry.d.ts +20 -0
  34. package/build/src/plugins/retry.js +66 -0
  35. package/build/src/reporters/dot.d.ts +15 -0
  36. package/build/src/reporters/dot.js +41 -0
  37. package/build/src/reporters/main.d.ts +4 -9
  38. package/build/src/reporters/main.js +37 -11
  39. package/build/src/reporters/ndjson.d.ts +15 -0
  40. package/build/src/reporters/ndjson.js +86 -0
  41. package/build/src/reporters/spec.d.ts +13 -0
  42. package/build/src/reporters/spec.js +152 -0
  43. package/build/src/types.d.ts +20 -24
  44. package/build/src/types.js +9 -14
  45. package/build/src/validator.d.ts +30 -0
  46. package/build/src/validator.js +85 -0
  47. package/package.json +17 -28
  48. package/build/chunk-7THDHQFT.js +0 -283
  49. package/build/chunk-HN4AVHWN.js +0 -17
  50. package/build/chunk-MCOW34SG.js +0 -269
  51. package/build/chunk-W5IABAQU.js +0 -502
  52. package/build/main-63126780.d.ts +0 -109
@@ -1,502 +0,0 @@
1
- import {
2
- dot,
3
- ndjson,
4
- spec
5
- } from "./chunk-7THDHQFT.js";
6
- import {
7
- Group,
8
- Refiner,
9
- Test,
10
- TestContext
11
- } from "./chunk-MCOW34SG.js";
12
-
13
- // src/debug.ts
14
- import { debuglog } from "node:util";
15
- var debug_default = debuglog("japa:runner");
16
-
17
- // src/validator.ts
18
- var Validator = class {
19
- /**
20
- * Ensures the japa is configured. Otherwise raises an exception
21
- */
22
- ensureIsConfigured(config) {
23
- if (!config) {
24
- throw new Error(
25
- `Cannot run tests. Make sure to call "configure" method before the "run" method`
26
- );
27
- }
28
- }
29
- /**
30
- * Ensures the japa is in planning phase
31
- */
32
- ensureIsInPlanningPhase(phase) {
33
- if (phase !== "planning") {
34
- throw new Error(
35
- `Cannot import japa test file directly. It must be imported by calling the "japa.run" method`
36
- );
37
- }
38
- }
39
- /**
40
- * Ensures the suites filter uses a subset of the user configured suites.
41
- */
42
- validateSuitesFilter(config) {
43
- if (!config.filters.suites || !config.filters.suites.length) {
44
- return;
45
- }
46
- if (!("suites" in config) || !config.suites.length) {
47
- throw new Error(`Cannot apply suites filter. You have not configured any test suites`);
48
- }
49
- const suites = config.suites.map(({ name }) => name);
50
- const unknownSuites = config.filters.suites.filter((suite) => !suites.includes(suite));
51
- if (unknownSuites.length) {
52
- throw new Error(`Cannot apply suites filter. "${unknownSuites[0]}" suite is not configured`);
53
- }
54
- }
55
- /**
56
- * Ensure there are unique suites
57
- */
58
- validateSuitesForUniqueness(config) {
59
- if (!("suites" in config)) {
60
- return;
61
- }
62
- const suites = /* @__PURE__ */ new Set();
63
- config.suites.forEach(({ name }) => {
64
- if (suites.has(name)) {
65
- throw new Error(`Duplicate suite "${name}"`);
66
- }
67
- suites.add(name);
68
- });
69
- suites.clear();
70
- }
71
- /**
72
- * Ensure the activated reporters are in the list of defined
73
- * reporters
74
- */
75
- validateActivatedReporters(config) {
76
- const reportersList = config.reporters.list.map(({ name }) => name);
77
- const unknownReporters = config.reporters.activated.filter(
78
- (name) => !reportersList.includes(name)
79
- );
80
- if (unknownReporters.length) {
81
- throw new Error(
82
- `Invalid reporter "${unknownReporters[0]}". Make sure to register it first inside the "reporters.list" array`
83
- );
84
- }
85
- }
86
- };
87
- var validator_default = new Validator();
88
-
89
- // src/files_manager.ts
90
- import slash from "slash";
91
- import fastGlob from "fast-glob";
92
- import { pathToFileURL } from "node:url";
93
- var FILE_SUFFIX_EXPRESSION = /(\.spec|\.test)?\.[js|ts|jsx|tsx|mjs|mts|cjs|cts]+$/;
94
- var FilesManager = class {
95
- /**
96
- * Returns a collection of files from the user defined
97
- * glob or the implementation function
98
- */
99
- async getFiles(cwd, files) {
100
- if (Array.isArray(files) || typeof files === "string") {
101
- const testFiles = await fastGlob(files, {
102
- absolute: true,
103
- onlyFiles: true,
104
- cwd
105
- });
106
- return testFiles.map((file) => pathToFileURL(file));
107
- }
108
- return await files();
109
- }
110
- /**
111
- * Applies file name filter on a collection of file
112
- * URLs
113
- */
114
- grep(files, filters) {
115
- return files.filter((file) => {
116
- const filename = slash(file.pathname);
117
- const filenameWithoutTestSuffix = filename.replace(FILE_SUFFIX_EXPRESSION, "");
118
- return !!filters.find((filter) => {
119
- if (filename.endsWith(filter)) {
120
- return true;
121
- }
122
- const filterSegments = filter.split("/").reverse();
123
- const fileSegments = filenameWithoutTestSuffix.split("/").reverse();
124
- return filterSegments.every((segment, index) => {
125
- return fileSegments[index] && (segment === "*" || fileSegments[index].endsWith(segment));
126
- });
127
- });
128
- });
129
- }
130
- };
131
-
132
- // src/planner.ts
133
- var Planner = class {
134
- #config;
135
- #fileManager = new FilesManager();
136
- constructor(config) {
137
- validator_default.validateActivatedReporters(config);
138
- validator_default.validateSuitesFilter(config);
139
- validator_default.validateSuitesForUniqueness(config);
140
- this.#config = config;
141
- }
142
- /**
143
- * Returns a list of reporters based upon the activated
144
- * reporters list.
145
- */
146
- #getActivatedReporters() {
147
- return this.#config.reporters.activated.map((activated) => {
148
- return this.#config.reporters.list.find(({ name }) => activated === name);
149
- });
150
- }
151
- /**
152
- * A generic method to collect files from the user defined
153
- * files glob and apply the files filter
154
- */
155
- async #collectFiles(files) {
156
- let filesURLs = await this.#fileManager.getFiles(this.#config.cwd, files);
157
- if (this.#config.filters.files && this.#config.filters.files.length) {
158
- filesURLs = this.#fileManager.grep(filesURLs, this.#config.filters.files);
159
- }
160
- return filesURLs;
161
- }
162
- /**
163
- * Returns a collection of suites and their associated
164
- * test files by applying all the filters
165
- */
166
- async #getSuites() {
167
- let suites = [];
168
- let suitesFilters = this.#config.filters.suites || [];
169
- if ("files" in this.#config) {
170
- suites.push({
171
- name: "default",
172
- files: this.#config.files,
173
- timeout: this.#config.timeout,
174
- retries: this.#config.retries,
175
- filesURLs: await this.#collectFiles(this.#config.files)
176
- });
177
- }
178
- if ("suites" in this.#config) {
179
- for (let suite of this.#config.suites) {
180
- if (!suitesFilters.length || suitesFilters.includes(suite.name)) {
181
- suites.push({
182
- ...suite,
183
- filesURLs: await this.#collectFiles(suite.files)
184
- });
185
- }
186
- }
187
- }
188
- return suites;
189
- }
190
- /**
191
- * Returns a list of filters to the passed to the refiner
192
- */
193
- #getRefinerFilters() {
194
- return Object.keys(this.#config.filters).reduce(
195
- (result, layer) => {
196
- if (layer === "tests" || layer === "tags" || layer === "groups") {
197
- result.push({ layer, filters: this.#config.filters[layer] });
198
- }
199
- return result;
200
- },
201
- []
202
- );
203
- }
204
- /**
205
- * Creates a plan for running the tests
206
- */
207
- async plan() {
208
- const suites = await this.#getSuites();
209
- const reporters = this.#getActivatedReporters();
210
- const refinerFilters = this.#getRefinerFilters();
211
- return {
212
- reporters,
213
- suites,
214
- refinerFilters,
215
- config: this.#config
216
- };
217
- }
218
- };
219
-
220
- // src/hooks.ts
221
- import Hooks from "@poppinss/hooks";
222
- var GlobalHooks = class {
223
- #hooks = new Hooks();
224
- #setupRunner;
225
- #teardownRunner;
226
- /**
227
- * Apply hooks from the config
228
- */
229
- apply(config) {
230
- config.setup.forEach((hook) => this.#hooks.add("setup", hook));
231
- config.teardown.forEach((hook) => this.#hooks.add("teardown", hook));
232
- }
233
- /**
234
- * Perform setup
235
- */
236
- async setup(runner) {
237
- this.#setupRunner = this.#hooks.runner("setup");
238
- this.#teardownRunner = this.#hooks.runner("teardown");
239
- await this.#setupRunner.run(runner);
240
- }
241
- /**
242
- * Perform cleanup
243
- */
244
- async teardown(error, runner) {
245
- if (this.#setupRunner) {
246
- await this.#setupRunner.cleanup(error, runner);
247
- }
248
- if (this.#teardownRunner) {
249
- if (!error) {
250
- await this.#teardownRunner.run(runner);
251
- }
252
- await this.#teardownRunner.cleanup(error, runner);
253
- }
254
- }
255
- };
256
-
257
- // src/cli_parser.ts
258
- import getopts from "getopts";
259
- import colors from "@poppinss/colors";
260
- var ansi = colors.ansi();
261
- var OPTIONS = {
262
- string: ["tests", "groups", "tags", "files", "timeout", "retries", "reporter", "failed"],
263
- boolean: ["help", "matchAll", "failed"],
264
- alias: {
265
- forceExit: "force-exit",
266
- matchAll: "match-all",
267
- help: "h"
268
- }
269
- };
270
- var GET_HELP = () => `
271
- ${ansi.yellow("@japa/runner v2.3.0")}
272
-
273
- ${ansi.green("--tests")} ${ansi.dim("Filter tests by the test title")}
274
- ${ansi.green("--groups")} ${ansi.dim("Filter tests by the group title")}
275
- ${ansi.green("--tags")} ${ansi.dim("Filter tests by tags")}
276
- ${ansi.green("--files")} ${ansi.dim("Filter tests by the file name")}
277
- ${ansi.green("--force-exit")} ${ansi.dim("Forcefully exit the process")}
278
- ${ansi.green("--timeout")} ${ansi.dim("Define default timeout for all tests")}
279
- ${ansi.green("--retries")} ${ansi.dim("Define default retries for all tests")}
280
- ${ansi.green("--reporter")} ${ansi.dim("Activate one or more test reporters")}
281
- ${ansi.green("--failed")} ${ansi.dim("Run tests failed during the last run")}
282
- ${ansi.green("-h, --help")} ${ansi.dim("View help")}
283
-
284
- ${ansi.yellow("Examples:")}
285
- ${ansi.dim('node bin/test.js --tags="@github"')}
286
- ${ansi.dim('node bin/test.js --tags="~@github"')}
287
- ${ansi.dim('node bin/test.js --tags="@github,@slow,@integration" --match-all')}
288
- ${ansi.dim("node bin/test.js --force-exit")}
289
- ${ansi.dim('node bin/test.js --files="user"')}
290
- ${ansi.dim('node bin/test.js --files="functional/user"')}
291
- ${ansi.dim('node bin/test.js --files="unit/user"')}
292
-
293
- ${ansi.yellow("Notes:")}
294
- - When groups and tests filters are applied together. We will first filter the
295
- tests by group title and then apply the tests title filter.
296
- - The timeout defined on test object takes precedence over the ${ansi.green("--timeout")} flag.
297
- - The retries defined on test object takes precedence over the ${ansi.green("--retries")} flag.
298
- - The ${ansi.green("--files")} flag checks for the file names ending with the filter substring.
299
- `;
300
- var CliParser = class {
301
- /**
302
- * Parses command-line arguments
303
- */
304
- parse(argv) {
305
- return getopts(argv, OPTIONS);
306
- }
307
- /**
308
- * Returns the help string
309
- */
310
- getHelp() {
311
- return GET_HELP();
312
- }
313
- };
314
-
315
- // src/config_manager.ts
316
- var NOOP = () => {
317
- };
318
- var DEFAULTS = {
319
- files: [],
320
- timeout: 2e3,
321
- retries: 0,
322
- forceExit: false,
323
- plugins: [],
324
- reporters: {
325
- activated: ["spec"],
326
- list: [spec(), ndjson(), dot()]
327
- },
328
- importer: (filePath) => import(filePath.href),
329
- configureSuite: () => {
330
- }
331
- };
332
- var ConfigManager = class {
333
- #config;
334
- #cliArgs;
335
- constructor(config, cliArgs) {
336
- this.#config = config;
337
- this.#cliArgs = cliArgs;
338
- }
339
- /**
340
- * Processes a CLI argument and converts it to an
341
- * array of strings
342
- */
343
- #processAsArray(value) {
344
- return Array.isArray(value) ? value : value.split(",").map((item) => item.trim());
345
- }
346
- /**
347
- * Returns a copy of filters based upon the CLI
348
- * arguments.
349
- */
350
- #getCLIFilters() {
351
- const filters = {};
352
- if (this.#cliArgs.tags) {
353
- filters.tags = this.#processAsArray(this.#cliArgs.tags);
354
- }
355
- if (this.#cliArgs.tests) {
356
- filters.tests = this.#processAsArray(this.#cliArgs.tests);
357
- }
358
- if (this.#cliArgs.files) {
359
- filters.files = this.#processAsArray(this.#cliArgs.files);
360
- }
361
- if (this.#cliArgs.groups) {
362
- filters.groups = this.#processAsArray(this.#cliArgs.groups);
363
- }
364
- if (this.#cliArgs._ && this.#cliArgs._.length) {
365
- filters.suites = this.#processAsArray(this.#cliArgs._);
366
- }
367
- return filters;
368
- }
369
- /**
370
- * Returns the timeout from the CLI args
371
- */
372
- #getCLITimeout() {
373
- if (this.#cliArgs.timeout) {
374
- const value = Number(this.#cliArgs.timeout);
375
- if (!Number.isNaN(value)) {
376
- return value;
377
- }
378
- }
379
- }
380
- /**
381
- * Returns the retries from the CLI args
382
- */
383
- #getCLIRetries() {
384
- if (this.#cliArgs.retries) {
385
- const value = Number(this.#cliArgs.retries);
386
- if (!Number.isNaN(value)) {
387
- return value;
388
- }
389
- }
390
- }
391
- /**
392
- * Returns the forceExit property from the CLI args
393
- */
394
- #getCLIForceExit() {
395
- if (this.#cliArgs.forceExit) {
396
- return true;
397
- }
398
- }
399
- /**
400
- * Returns reporters selected using the commandline
401
- * --reporter flag
402
- */
403
- #getCLIReporters() {
404
- if (this.#cliArgs.reporter) {
405
- return this.#processAsArray(this.#cliArgs.reporter);
406
- }
407
- }
408
- /**
409
- * Hydrates the config with user defined options and the
410
- * command-line flags.
411
- */
412
- hydrate() {
413
- const cliFilters = this.#getCLIFilters();
414
- const cliRetries = this.#getCLIRetries();
415
- const cliTimeout = this.#getCLITimeout();
416
- const cliReporters = this.#getCLIReporters();
417
- const cliForceExit = this.#getCLIForceExit();
418
- debug_default("filters applied using CLI flags %O", cliFilters);
419
- const baseConfig = {
420
- cwd: this.#config.cwd ?? process.cwd(),
421
- filters: Object.assign({}, this.#config.filters ?? {}, cliFilters),
422
- importer: this.#config.importer ?? DEFAULTS.importer,
423
- refiner: this.#config.refiner ?? new Refiner(),
424
- retries: cliRetries ?? this.#config.retries ?? DEFAULTS.retries,
425
- timeout: cliTimeout ?? this.#config.timeout ?? DEFAULTS.timeout,
426
- plugins: this.#config.plugins ?? DEFAULTS.plugins,
427
- forceExit: cliForceExit ?? this.#config.forceExit ?? DEFAULTS.forceExit,
428
- reporters: this.#config.reporters ? {
429
- activated: this.#config.reporters.activated,
430
- list: this.#config.reporters.list || DEFAULTS.reporters.list
431
- } : DEFAULTS.reporters,
432
- configureSuite: this.#config.configureSuite ?? DEFAULTS.configureSuite,
433
- setup: this.#config.setup || [],
434
- teardown: this.#config.teardown || []
435
- };
436
- if (cliReporters) {
437
- baseConfig.reporters.activated = cliReporters;
438
- }
439
- if ("files" in this.#config) {
440
- return {
441
- files: this.#config.files,
442
- ...baseConfig
443
- };
444
- }
445
- return {
446
- suites: this.#config.suites.map((suite) => {
447
- return {
448
- name: suite.name,
449
- files: suite.files,
450
- timeout: cliTimeout ?? suite.timeout ?? baseConfig.timeout,
451
- retries: cliRetries ?? suite.retries ?? baseConfig.retries,
452
- configure: suite.configure || NOOP
453
- };
454
- }),
455
- ...baseConfig
456
- };
457
- }
458
- };
459
-
460
- // src/create_test.ts
461
- var contextBuilder = (testInstance) => new TestContext(testInstance);
462
- function createTest(title, emitter, refiner, options) {
463
- const testInstance = new Test(title, contextBuilder, emitter, refiner, options.group);
464
- testInstance.options.meta.suite = options.suite;
465
- testInstance.options.meta.group = options.group;
466
- testInstance.options.meta.fileName = options.file;
467
- if (options.timeout !== void 0) {
468
- testInstance.timeout(options.timeout);
469
- }
470
- if (options.retries !== void 0) {
471
- testInstance.retry(options.retries);
472
- }
473
- if (options.group) {
474
- options.group.add(testInstance);
475
- } else if (options.suite) {
476
- options.suite.add(testInstance);
477
- }
478
- return testInstance;
479
- }
480
- function createTestGroup(title, emitter, refiner, options) {
481
- if (options.group) {
482
- throw new Error("Nested groups are not supported by Japa");
483
- }
484
- const group = new Group(title, emitter, refiner);
485
- group.options.meta.suite = options.suite;
486
- group.options.meta.fileName = options.file;
487
- if (options.suite) {
488
- options.suite.add(group);
489
- }
490
- return group;
491
- }
492
-
493
- export {
494
- debug_default,
495
- validator_default,
496
- Planner,
497
- GlobalHooks,
498
- CliParser,
499
- ConfigManager,
500
- createTest,
501
- createTestGroup
502
- };
@@ -1,109 +0,0 @@
1
- import { Emitter, TestContext as TestContext$1, Test as Test$1, Group as Group$1, Suite as Suite$1, Runner as Runner$1 } from '@japa/core';
2
- import { TestStartNode, TestEndNode, GroupStartNode, GroupEndNode, SuiteStartNode, SuiteEndNode, RunnerStartNode, RunnerEndNode, RunnerSummary, DataSetNode, TestHooksCleanupHandler } from '@japa/core/types';
3
-
4
- type BaseReporterOptions = {
5
- stackLinesCount?: number;
6
- framesMaxLimit?: number;
7
- };
8
-
9
- /**
10
- * Base reporter to build custom reporters on top of
11
- */
12
- declare abstract class BaseReporter {
13
- #private;
14
- runner?: Runner;
15
- /**
16
- * Path to the file for which the tests are getting executed
17
- */
18
- currentFileName?: string;
19
- /**
20
- * Suite for which the tests are getting executed
21
- */
22
- currentSuiteName?: string;
23
- /**
24
- * Group for which the tests are getting executed
25
- */
26
- currentGroupName?: string;
27
- constructor(options?: BaseReporterOptions);
28
- /**
29
- * Handlers to capture events
30
- */
31
- protected onTestStart(_: TestStartNode): void;
32
- protected onTestEnd(_: TestEndNode): void;
33
- protected onGroupStart(_: GroupStartNode): void;
34
- protected onGroupEnd(_: GroupEndNode): void;
35
- protected onSuiteStart(_: SuiteStartNode): void;
36
- protected onSuiteEnd(_: SuiteEndNode): void;
37
- protected start(_: RunnerStartNode): Promise<void>;
38
- protected end(_: RunnerEndNode): Promise<void>;
39
- /**
40
- * Print tests summary
41
- */
42
- protected printSummary(summary: RunnerSummary): Promise<void>;
43
- /**
44
- * Invoked by the tests runner when tests are about to start
45
- */
46
- boot(runner: Runner, emitter: Emitter): void;
47
- }
48
-
49
- declare module '@japa/core' {
50
- interface Test<Context extends Record<any, any>, TestData extends DataSetNode = undefined> {
51
- throws(message: string | RegExp, errorConstructor?: any): this;
52
- }
53
- interface TestContext {
54
- cleanup: (cleanupCallback: TestHooksCleanupHandler<TestContext>) => void;
55
- }
56
- }
57
-
58
- /**
59
- * Test context carries context data for a given test.
60
- */
61
- declare class TestContext extends TestContext$1 {
62
- test: Test;
63
- /**
64
- * Register a cleanup function that runs after the test finishes
65
- * successfully or with an error.
66
- */
67
- cleanup: (cleanupCallback: TestHooksCleanupHandler<TestContext>) => void;
68
- constructor(test: Test);
69
- }
70
- /**
71
- * Test class represents an individual test and exposes API to tweak
72
- * its runtime behavior.
73
- */
74
- declare class Test<TestData extends DataSetNode = undefined> extends Test$1<TestContext, TestData> {
75
- /**
76
- * @inheritdoc
77
- */
78
- static executedCallbacks: never[];
79
- /**
80
- * @inheritdoc
81
- */
82
- static executingCallbacks: never[];
83
- /**
84
- * Assert the test callback throws an exception when a certain
85
- * error message and optionally is an instance of a given
86
- * Error class.
87
- */
88
- throws(message: string | RegExp, errorConstructor?: any): this;
89
- }
90
- /**
91
- * TestGroup is used to bulk configure a collection of tests and
92
- * define lifecycle hooks for them
93
- */
94
- declare class Group extends Group$1<TestContext> {
95
- }
96
- /**
97
- * A suite is a collection of tests created around a given
98
- * testing type. For example: A suite for unit tests, a
99
- * suite for functional tests and so on.
100
- */
101
- declare class Suite extends Suite$1<TestContext> {
102
- }
103
- /**
104
- * Runner class is used to execute the tests
105
- */
106
- declare class Runner extends Runner$1<TestContext> {
107
- }
108
-
109
- export { BaseReporterOptions as B, Group as G, Runner as R, Suite as S, TestContext as T, Test as a, BaseReporter as b };