@japa/runner 2.5.1 → 3.0.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 (54) hide show
  1. package/LICENSE.md +1 -1
  2. package/build/index.d.ts +8 -29
  3. package/build/index.js +93 -466
  4. package/build/src/cli_parser.d.ts +6 -0
  5. package/build/src/cli_parser.d.ts.map +1 -0
  6. package/build/src/cli_parser.js +49 -0
  7. package/build/src/config_manager.d.ts +7 -0
  8. package/build/src/config_manager.d.ts.map +1 -0
  9. package/build/src/config_manager.js +115 -0
  10. package/build/src/create_test.d.ts +16 -0
  11. package/build/src/create_test.d.ts.map +1 -0
  12. package/build/src/create_test.js +33 -0
  13. package/build/src/debug.d.ts +2 -1
  14. package/build/src/debug.d.ts.map +1 -0
  15. package/build/src/debug.js +2 -12
  16. package/build/src/exceptions_manager.d.ts +7 -0
  17. package/build/src/exceptions_manager.d.ts.map +1 -0
  18. package/build/src/exceptions_manager.js +58 -0
  19. package/build/src/files_manager.d.ts +7 -0
  20. package/build/src/files_manager.d.ts.map +1 -0
  21. package/build/src/files_manager.js +28 -0
  22. package/build/src/helpers.d.ts +23 -0
  23. package/build/src/helpers.d.ts.map +1 -0
  24. package/build/src/helpers.js +2 -0
  25. package/build/src/hooks.d.ts +9 -0
  26. package/build/src/hooks.d.ts.map +1 -0
  27. package/build/src/hooks.js +26 -0
  28. package/build/src/planner.d.ts +18 -0
  29. package/build/src/planner.d.ts.map +1 -0
  30. package/build/src/planner.js +67 -0
  31. package/build/src/plugins/retry.d.ts +8 -0
  32. package/build/src/plugins/retry.d.ts.map +1 -0
  33. package/build/src/plugins/retry.js +42 -0
  34. package/build/src/reporters/dot.d.ts +7 -0
  35. package/build/src/reporters/dot.d.ts.map +1 -0
  36. package/build/src/reporters/dot.js +24 -0
  37. package/build/src/reporters/main.d.ts +5 -0
  38. package/build/src/reporters/main.d.ts.map +1 -0
  39. package/build/src/reporters/main.js +21 -0
  40. package/build/src/reporters/ndjson.d.ts +12 -0
  41. package/build/src/reporters/ndjson.d.ts.map +1 -0
  42. package/build/src/reporters/ndjson.js +61 -0
  43. package/build/src/reporters/spec.d.ts +11 -0
  44. package/build/src/reporters/spec.d.ts.map +1 -0
  45. package/build/src/reporters/spec.js +103 -0
  46. package/build/src/types.d.ts +48 -49
  47. package/build/src/types.d.ts.map +1 -0
  48. package/build/src/types.js +1 -10
  49. package/build/src/validator.d.ts +11 -0
  50. package/build/src/validator.d.ts.map +1 -0
  51. package/build/src/validator.js +46 -0
  52. package/package.json +76 -83
  53. package/build/src/core/main.d.ts +0 -49
  54. package/build/src/core/main.js +0 -87
@@ -0,0 +1,49 @@
1
+ import getopts from 'getopts';
2
+ import colors from '@poppinss/colors';
3
+ const ansi = colors.ansi();
4
+ const OPTIONS = {
5
+ string: ['tests', 'groups', 'tags', 'files', 'timeout', 'retries', 'reporter'],
6
+ boolean: ['help', 'matchAll'],
7
+ alias: {
8
+ forceExit: 'force-exit',
9
+ matchAll: 'match-all',
10
+ help: 'h',
11
+ },
12
+ };
13
+ const GET_HELP = () => `
14
+ ${ansi.yellow('@japa/runner v2.3.0')}
15
+
16
+ ${ansi.green('--tests')} ${ansi.dim('Filter tests by the test title')}
17
+ ${ansi.green('--groups')} ${ansi.dim('Filter tests by the group title')}
18
+ ${ansi.green('--tags')} ${ansi.dim('Filter tests by tags')}
19
+ ${ansi.green('--files')} ${ansi.dim('Filter tests by the file name')}
20
+ ${ansi.green('--force-exit')} ${ansi.dim('Forcefully exit the process')}
21
+ ${ansi.green('--timeout')} ${ansi.dim('Define default timeout for all tests')}
22
+ ${ansi.green('--retries')} ${ansi.dim('Define default retries for all tests')}
23
+ ${ansi.green('--reporter')} ${ansi.dim('Activate one or more test reporters')}
24
+ ${ansi.green('-h, --help')} ${ansi.dim('View help')}
25
+
26
+ ${ansi.yellow('Examples:')}
27
+ ${ansi.dim('node bin/test.js --tags="@github"')}
28
+ ${ansi.dim('node bin/test.js --tags="~@github"')}
29
+ ${ansi.dim('node bin/test.js --tags="@github,@slow,@integration" --match-all')}
30
+ ${ansi.dim('node bin/test.js --force-exit')}
31
+ ${ansi.dim('node bin/test.js --files="user"')}
32
+ ${ansi.dim('node bin/test.js --files="functional/user"')}
33
+ ${ansi.dim('node bin/test.js --files="unit/user"')}
34
+
35
+ ${ansi.yellow('Notes:')}
36
+ - When groups and tests filters are applied together. We will first filter the
37
+ tests by group title and then apply the tests title filter.
38
+ - The timeout defined on test object takes precedence over the ${ansi.green('--timeout')} flag.
39
+ - The retries defined on test object takes precedence over the ${ansi.green('--retries')} flag.
40
+ - The ${ansi.green('--files')} flag checks for the file names ending with the filter substring.
41
+ `;
42
+ export class CliParser {
43
+ parse(argv) {
44
+ return getopts(argv, OPTIONS);
45
+ }
46
+ getHelp() {
47
+ return GET_HELP();
48
+ }
49
+ }
@@ -0,0 +1,7 @@
1
+ import type { CLIArgs, Config } from './types.js';
2
+ export declare class ConfigManager {
3
+ #private;
4
+ constructor(config: Config, cliArgs: CLIArgs);
5
+ hydrate(): Required<Config>;
6
+ }
7
+ //# sourceMappingURL=config_manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config_manager.d.ts","sourceRoot":"","sources":["../../src/config_manager.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAW,MAAM,YAAY,CAAA;AA0B1D,qBAAa,aAAa;;gBAIZ,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAsF5C,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC;CAoD5B"}
@@ -0,0 +1,115 @@
1
+ import debug from './debug.js';
2
+ import { spec } from './reporters/main.js';
3
+ import { Refiner } from '../modules/core/main.js';
4
+ const DEFAULTS = {
5
+ files: [],
6
+ timeout: 2000,
7
+ retries: 0,
8
+ forceExit: false,
9
+ plugins: [],
10
+ reporters: {
11
+ activated: ['spec'],
12
+ list: [spec()],
13
+ },
14
+ importer: (filePath) => import(filePath.href),
15
+ configureSuite: () => { },
16
+ };
17
+ export class ConfigManager {
18
+ #config;
19
+ #cliArgs;
20
+ constructor(config, cliArgs) {
21
+ this.#config = config;
22
+ this.#cliArgs = cliArgs;
23
+ }
24
+ #processAsArray(value) {
25
+ return Array.isArray(value) ? value : value.split(',').map((item) => item.trim());
26
+ }
27
+ #getCLIFilters() {
28
+ const filters = {};
29
+ if (this.#cliArgs.tags) {
30
+ filters.tags = this.#processAsArray(this.#cliArgs.tags);
31
+ }
32
+ if (this.#cliArgs.tests) {
33
+ filters.tests = this.#processAsArray(this.#cliArgs.tests);
34
+ }
35
+ if (this.#cliArgs.files) {
36
+ filters.files = this.#processAsArray(this.#cliArgs.files);
37
+ }
38
+ if (this.#cliArgs.groups) {
39
+ filters.groups = this.#processAsArray(this.#cliArgs.groups);
40
+ }
41
+ if (this.#cliArgs._ && this.#cliArgs._.length) {
42
+ filters.suites = this.#processAsArray(this.#cliArgs._);
43
+ }
44
+ return filters;
45
+ }
46
+ #getCLITimeout() {
47
+ if (this.#cliArgs.timeout) {
48
+ const value = Number(this.#cliArgs.timeout);
49
+ if (!Number.isNaN(value)) {
50
+ return value;
51
+ }
52
+ }
53
+ }
54
+ #getCLIRetries() {
55
+ if (this.#cliArgs.retries) {
56
+ const value = Number(this.#cliArgs.retries);
57
+ if (!Number.isNaN(value)) {
58
+ return value;
59
+ }
60
+ }
61
+ }
62
+ #getCLIForceExit() {
63
+ if (this.#cliArgs.forceExit) {
64
+ return true;
65
+ }
66
+ }
67
+ #getCLIReporters() {
68
+ if (this.#cliArgs.reporter) {
69
+ return this.#processAsArray(this.#cliArgs.reporter);
70
+ }
71
+ }
72
+ hydrate() {
73
+ const cliFilters = this.#getCLIFilters();
74
+ const cliRetries = this.#getCLIRetries();
75
+ const cliTimeout = this.#getCLITimeout();
76
+ const cliReporters = this.#getCLIReporters();
77
+ const cliForceExit = this.#getCLIForceExit();
78
+ debug('filters applied using CLI flags %O', cliFilters);
79
+ const baseConfig = {
80
+ cwd: this.#config.cwd ?? process.cwd(),
81
+ filters: Object.assign({}, this.#config.filters ?? {}, cliFilters),
82
+ importer: this.#config.importer ?? DEFAULTS.importer,
83
+ refiner: this.#config.refiner ?? new Refiner(),
84
+ retries: cliRetries ?? this.#config.retries ?? DEFAULTS.retries,
85
+ timeout: cliTimeout ?? this.#config.timeout ?? DEFAULTS.timeout,
86
+ plugins: this.#config.plugins ?? DEFAULTS.plugins,
87
+ forceExit: cliForceExit ?? this.#config.forceExit ?? DEFAULTS.forceExit,
88
+ reporters: this.#config.reporters ?? DEFAULTS.reporters,
89
+ configureSuite: this.#config.configureSuite ?? DEFAULTS.configureSuite,
90
+ setup: this.#config.setup || [],
91
+ teardown: this.#config.teardown || [],
92
+ };
93
+ if (cliReporters) {
94
+ baseConfig.reporters.activated = cliReporters;
95
+ }
96
+ if ('files' in this.#config) {
97
+ return {
98
+ files: this.#config.files,
99
+ ...baseConfig,
100
+ };
101
+ }
102
+ return {
103
+ suites: this.#config.suites.map((suite) => {
104
+ return {
105
+ name: suite.name,
106
+ files: suite.files,
107
+ timeout: cliTimeout ?? suite.timeout ?? baseConfig.timeout,
108
+ retries: cliRetries ?? suite.retries ?? baseConfig.retries,
109
+ configure: suite.configure,
110
+ };
111
+ }),
112
+ ...baseConfig,
113
+ };
114
+ }
115
+ }
@@ -0,0 +1,16 @@
1
+ import { Emitter, Group, Refiner, Suite, Test } from '../modules/core/main.js';
2
+ export declare function createTest(title: string, emitter: Emitter, refiner: Refiner, options: {
3
+ group?: Group;
4
+ suite?: Suite;
5
+ file?: string;
6
+ timeout?: number;
7
+ retries?: number;
8
+ }): Test<undefined>;
9
+ export declare function createTestGroup(title: string, emitter: Emitter, refiner: Refiner, options: {
10
+ group?: Group;
11
+ suite?: Suite;
12
+ file?: string;
13
+ timeout?: number;
14
+ retries?: number;
15
+ }): Group;
16
+ //# sourceMappingURL=create_test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_test.d.ts","sourceRoot":"","sources":["../../src/create_test.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAe,MAAM,yBAAyB,CAAA;AAU3F,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE;IACP,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,mBAwBF;AAKD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE;IACP,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,SAeF"}
@@ -0,0 +1,33 @@
1
+ import { Group, Test, TestContext } from '../modules/core/main.js';
2
+ const contextBuilder = (testInstance) => new TestContext(testInstance);
3
+ export function createTest(title, emitter, refiner, options) {
4
+ const testInstance = new Test(title, contextBuilder, emitter, refiner, options.group);
5
+ testInstance.options.meta.suite = options.suite;
6
+ testInstance.options.meta.group = options.group;
7
+ testInstance.options.meta.fileName = options.file;
8
+ if (options.timeout !== undefined) {
9
+ testInstance.timeout(options.timeout);
10
+ }
11
+ if (options.retries !== undefined) {
12
+ testInstance.retry(options.retries);
13
+ }
14
+ if (options.group) {
15
+ options.group.add(testInstance);
16
+ }
17
+ else if (options.suite) {
18
+ options.suite.add(testInstance);
19
+ }
20
+ return testInstance;
21
+ }
22
+ export function createTestGroup(title, emitter, refiner, options) {
23
+ if (options.group) {
24
+ throw new Error('Nested groups are not supported by Japa');
25
+ }
26
+ const group = new Group(title, emitter, refiner);
27
+ group.options.meta.suite = options.suite;
28
+ group.options.meta.fileName = options.file;
29
+ if (options.suite) {
30
+ options.suite.add(group);
31
+ }
32
+ return group;
33
+ }
@@ -1,3 +1,4 @@
1
- /// <reference types="node" />
1
+ /// <reference types="@types/node" resolution-mode="require"/>
2
2
  declare const _default: import("util").DebugLogger;
3
3
  export default _default;
4
+ //# sourceMappingURL=debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/debug.ts"],"names":[],"mappings":";;AAUA,wBAAsC"}
@@ -1,12 +1,2 @@
1
- "use strict";
2
- /*
3
- * @japa/runner
4
- *
5
- * (c) Japa.dev
6
- *
7
- * For the full copyright and license information, please view the LICENSE
8
- * file that was distributed with this source code.
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- const util_1 = require("util");
12
- exports.default = (0, util_1.debuglog)('japa:runner');
1
+ import { debuglog } from 'node:util';
2
+ export default debuglog('japa:runner');
@@ -0,0 +1,7 @@
1
+ export declare class ExceptionsManager {
2
+ #private;
3
+ hasErrors: boolean;
4
+ monitor(): void;
5
+ flow(): Promise<void>;
6
+ }
7
+ //# sourceMappingURL=exceptions_manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exceptions_manager.d.ts","sourceRoot":"","sources":["../../src/exceptions_manager.ts"],"names":[],"mappings":"AAeA,qBAAa,iBAAiB;;IAM5B,SAAS,EAAE,OAAO,CAAQ;IAW1B,OAAO;IAwBD,IAAI;CAmCX"}
@@ -0,0 +1,58 @@
1
+ import { ErrorsPrinter } from '@japa/errors-printer';
2
+ export class ExceptionsManager {
3
+ #exceptionsBuffer = [];
4
+ #rejectionsBuffer = [];
5
+ #state = 'watching';
6
+ #errorsPrinter = new ErrorsPrinter({ stackLinesCount: 2, framesMaxLimit: 4 });
7
+ hasErrors = false;
8
+ monitor() {
9
+ process.on('uncaughtException', async (error) => {
10
+ this.hasErrors = true;
11
+ if (this.#state === 'watching') {
12
+ this.#exceptionsBuffer.push(error);
13
+ }
14
+ else {
15
+ this.#errorsPrinter.printSectionBorder('[Unhandled Error]');
16
+ await this.#errorsPrinter.printError(error);
17
+ process.exitCode = 1;
18
+ }
19
+ });
20
+ process.on('unhandledRejection', async (error) => {
21
+ this.hasErrors = true;
22
+ if (this.#state === 'watching') {
23
+ this.#rejectionsBuffer.push(error);
24
+ }
25
+ else {
26
+ this.#errorsPrinter.printSectionBorder('[Unhandled Rejection]');
27
+ await this.#errorsPrinter.printError(error);
28
+ process.exitCode = 1;
29
+ }
30
+ });
31
+ }
32
+ async flow() {
33
+ if (this.#state === 'flowing') {
34
+ return;
35
+ }
36
+ this.#state = 'flowing';
37
+ if (this.#exceptionsBuffer.length) {
38
+ let exceptionsCount = this.#exceptionsBuffer.length;
39
+ let exceptionsIndex = this.#exceptionsBuffer.length;
40
+ this.#errorsPrinter.printSectionHeader('Unhandled Errors');
41
+ for (let exception of this.#exceptionsBuffer) {
42
+ await this.#errorsPrinter.printError(exception);
43
+ this.#errorsPrinter.printSectionBorder(`[${++exceptionsIndex}/${exceptionsCount}]`);
44
+ }
45
+ this.#exceptionsBuffer = [];
46
+ }
47
+ if (this.#rejectionsBuffer.length) {
48
+ let rejectionsCount = this.#exceptionsBuffer.length;
49
+ let rejectionsIndex = this.#exceptionsBuffer.length;
50
+ this.#errorsPrinter.printSectionBorder('Unhandled Rejections');
51
+ for (let rejection of this.#rejectionsBuffer) {
52
+ await this.#errorsPrinter.printError(rejection);
53
+ this.#errorsPrinter.printSectionBorder(`[${++rejectionsIndex}/${rejectionsCount}]`);
54
+ }
55
+ this.#rejectionsBuffer = [];
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,7 @@
1
+ /// <reference types="@types/node" resolution-mode="require"/>
2
+ import type { TestFiles } from './types.js';
3
+ export declare class FilesManager {
4
+ getFiles(cwd: string, files: TestFiles): Promise<URL[]>;
5
+ grep(files: URL[], filters: string[]): URL[];
6
+ }
7
+ //# sourceMappingURL=files_manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files_manager.d.ts","sourceRoot":"","sources":["../../src/files_manager.ts"],"names":[],"mappings":";AAYA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAY3C,qBAAa,YAAY;IAKjB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAiB7D,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAG,EAAE;CAY7C"}
@@ -0,0 +1,28 @@
1
+ import { sep } from 'node:path';
2
+ import fastGlob from 'fast-glob';
3
+ import { pathToFileURL } from 'node:url';
4
+ const FILE_SUFFIX_EXPRESSION = /(\.spec|\.test)?\.[js|ts|jsx|tsx|mjs|mts|cjs|cts]+$/;
5
+ export class FilesManager {
6
+ async getFiles(cwd, files) {
7
+ if (Array.isArray(files) || typeof files === 'string') {
8
+ const testFiles = await fastGlob(files, {
9
+ absolute: true,
10
+ onlyFiles: true,
11
+ cwd: cwd,
12
+ });
13
+ return testFiles.map((file) => pathToFileURL(file));
14
+ }
15
+ return await files();
16
+ }
17
+ grep(files, filters) {
18
+ return files.filter((file) => {
19
+ return !!filters.find((filter) => {
20
+ const filterSegments = filter.split('/').reverse();
21
+ const fileSegments = file.pathname.replace(FILE_SUFFIX_EXPRESSION, '').split(sep).reverse();
22
+ return filterSegments.every((segment, index) => {
23
+ return fileSegments[index] && (segment === '*' || fileSegments[index].endsWith(segment));
24
+ });
25
+ });
26
+ });
27
+ }
28
+ }
@@ -0,0 +1,23 @@
1
+ declare const _default: {
2
+ colors: import("@poppinss/colors/types").Colors;
3
+ logger: import("@poppinss/cliui").Logger;
4
+ table: (tableOptions?: Partial<import("@poppinss/cliui/types").TableOptions> | undefined) => import("@poppinss/cliui").Table;
5
+ tasks: (tasksOptions?: Partial<import("@poppinss/cliui/types").TaskManagerOptions> | undefined) => import("@poppinss/cliui").TaskManager;
6
+ icons: {
7
+ tick: string;
8
+ cross: string;
9
+ bullet: string;
10
+ nodejs: string;
11
+ pointer: string;
12
+ info: string;
13
+ warning: string;
14
+ squareSmallFilled: string;
15
+ };
16
+ sticker: () => import("@poppinss/cliui").Instructions;
17
+ instructions: () => import("@poppinss/cliui").Instructions;
18
+ switchMode(modeToUse: "raw" | "silent" | "normal"): void;
19
+ useRenderer(rendererToUse: import("@poppinss/cliui/types").RendererContract): void;
20
+ useColors(colorsToUse: import("@poppinss/colors/types").Colors): void;
21
+ };
22
+ export default _default;
23
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAUA,wBAAsB"}
@@ -0,0 +1,2 @@
1
+ import { cliui } from '@poppinss/cliui';
2
+ export default cliui();
@@ -0,0 +1,9 @@
1
+ import { Runner } from '../modules/core/main.js';
2
+ import type { Config } from './types.js';
3
+ export declare class GlobalHooks {
4
+ #private;
5
+ apply(config: Required<Config>): void;
6
+ setup(runner: Runner): Promise<void>;
7
+ teardown(error: Error | null, runner: Runner): Promise<void>;
8
+ }
9
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/hooks.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAkD,MAAM,YAAY,CAAA;AAKxF,qBAAa,WAAW;;IAQtB,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC;IAQxB,KAAK,CAAC,MAAM,EAAE,MAAM;IASpB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM;CAWnD"}
@@ -0,0 +1,26 @@
1
+ import Hooks from '@poppinss/hooks';
2
+ export class GlobalHooks {
3
+ #hooks = new Hooks();
4
+ #setupRunner;
5
+ #teardownRunner;
6
+ apply(config) {
7
+ config.setup.forEach((hook) => this.#hooks.add('setup', hook));
8
+ config.teardown.forEach((hook) => this.#hooks.add('teardown', hook));
9
+ }
10
+ async setup(runner) {
11
+ this.#setupRunner = this.#hooks.runner('setup');
12
+ this.#teardownRunner = this.#hooks.runner('teardown');
13
+ await this.#setupRunner.run(runner);
14
+ }
15
+ async teardown(error, runner) {
16
+ if (this.#setupRunner) {
17
+ await this.#setupRunner.cleanup(error, runner);
18
+ }
19
+ if (this.#teardownRunner) {
20
+ if (!error) {
21
+ await this.#teardownRunner.run(runner);
22
+ }
23
+ await this.#teardownRunner.cleanup(error, runner);
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,18 @@
1
+ /// <reference types="@types/node" resolution-mode="require"/>
2
+ import type { Config, TestSuite } from './types.js';
3
+ export declare class Planner {
4
+ #private;
5
+ constructor(config: Required<Config>);
6
+ plan(): Promise<{
7
+ reporters: import("@japa/core/types").NamedReporterContract[];
8
+ suites: (TestSuite & {
9
+ filesURLs: URL[];
10
+ })[];
11
+ refinerFilters: {
12
+ layer: "tags" | "tests" | "groups";
13
+ filters: string[];
14
+ }[];
15
+ config: Required<Config>;
16
+ }>;
17
+ }
18
+ //# sourceMappingURL=planner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../../src/planner.ts"],"names":[],"mappings":";AAWA,OAAO,KAAK,EAAE,MAAM,EAAa,SAAS,EAAE,MAAM,YAAY,CAAA;AAO9D,qBAAa,OAAO;;gBAIN,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC;IA6E9B,IAAI;;;;;;;;;;;CAWX"}
@@ -0,0 +1,67 @@
1
+ import validator from './validator.js';
2
+ import { FilesManager } from './files_manager.js';
3
+ export class Planner {
4
+ #config;
5
+ #fileManager = new FilesManager();
6
+ constructor(config) {
7
+ validator.validateActivatedReporters(config);
8
+ validator.validateSuitesFilter(config);
9
+ validator.validateSuitesForUniqueness(config);
10
+ this.#config = config;
11
+ }
12
+ #getActivatedReporters() {
13
+ return this.#config.reporters.activated.map((activated) => {
14
+ return this.#config.reporters.list.find(({ name }) => activated === name);
15
+ });
16
+ }
17
+ async #collectFiles(files) {
18
+ let filesURLs = await this.#fileManager.getFiles(this.#config.cwd, files);
19
+ if (this.#config.filters.files && this.#config.filters.files.length) {
20
+ filesURLs = this.#fileManager.grep(filesURLs, this.#config.filters.files);
21
+ }
22
+ return filesURLs;
23
+ }
24
+ async #getSuites() {
25
+ let suites = [];
26
+ let suitesFilters = this.#config.filters.suites || [];
27
+ if ('files' in this.#config) {
28
+ suites.push({
29
+ name: 'default',
30
+ files: this.#config.files,
31
+ timeout: this.#config.timeout,
32
+ retries: this.#config.retries,
33
+ filesURLs: await this.#collectFiles(this.#config.files),
34
+ });
35
+ }
36
+ if ('suites' in this.#config) {
37
+ for (let suite of this.#config.suites) {
38
+ if (!suitesFilters.length || suitesFilters.includes(suite.name)) {
39
+ suites.push({
40
+ ...suite,
41
+ filesURLs: await this.#collectFiles(suite.files),
42
+ });
43
+ }
44
+ }
45
+ }
46
+ return suites;
47
+ }
48
+ #getRefinerFilters() {
49
+ return Object.keys(this.#config.filters).reduce((result, layer) => {
50
+ if (layer === 'tests' || layer === 'tags' || layer === 'groups') {
51
+ result.push({ layer, filters: this.#config.filters[layer] });
52
+ }
53
+ return result;
54
+ }, []);
55
+ }
56
+ async plan() {
57
+ const suites = await this.#getSuites();
58
+ const reporters = this.#getActivatedReporters();
59
+ const refinerFilters = this.#getRefinerFilters();
60
+ return {
61
+ reporters,
62
+ suites,
63
+ refinerFilters,
64
+ config: this.#config,
65
+ };
66
+ }
67
+ }
@@ -0,0 +1,8 @@
1
+ import type { PluginFn } from '../types.js';
2
+ export declare function getFailedTests(): Promise<{
3
+ tests?: string[];
4
+ }>;
5
+ export declare function cacheFailedTests(tests: string[]): Promise<void>;
6
+ export declare function clearCache(): Promise<void>;
7
+ export declare const retryPlugin: PluginFn;
8
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../../src/plugins/retry.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAY3C,wBAAsB,cAAc,IAAI,OAAO,CAAC;IAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAUpE;AAKD,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,iBAGrD;AAKD,wBAAsB,UAAU,kBAE/B;AAKD,eAAO,MAAM,WAAW,EAAE,QAkBzB,CAAA"}
@@ -0,0 +1,42 @@
1
+ import { join } from 'node:path';
2
+ import findCacheDirectory from 'find-cache-dir';
3
+ import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
4
+ import cliui from '../helpers.js';
5
+ const CACHE_DIR = findCacheDirectory({ name: '@japa/runner' });
6
+ const SUMMARY_FILE = CACHE_DIR ? join(CACHE_DIR, 'summary.json') : undefined;
7
+ export async function getFailedTests() {
8
+ try {
9
+ const summary = await readFile(SUMMARY_FILE, 'utf-8');
10
+ return JSON.parse(summary);
11
+ }
12
+ catch (error) {
13
+ if (error.code === 'ENOENT') {
14
+ return {};
15
+ }
16
+ throw new Error('Unable to read failed tests cache file', { cause: error });
17
+ }
18
+ }
19
+ export async function cacheFailedTests(tests) {
20
+ await mkdir(CACHE_DIR, { recursive: true });
21
+ await writeFile(SUMMARY_FILE, JSON.stringify({ tests: tests }));
22
+ }
23
+ export async function clearCache() {
24
+ await unlink(SUMMARY_FILE);
25
+ }
26
+ export const retryPlugin = async function retry({ config, cliArgs }) {
27
+ if (!SUMMARY_FILE) {
28
+ return;
29
+ }
30
+ config.teardown.push(async (runner) => {
31
+ const summary = runner.getSummary();
32
+ await cacheFailedTests(summary.failedTestsTitles);
33
+ });
34
+ if (cliArgs.retry) {
35
+ const { tests } = await getFailedTests();
36
+ if (!tests || !tests.length) {
37
+ console.log(cliui.colors.bgYellow().black(' No failing tests found. Running all the tests '));
38
+ return;
39
+ }
40
+ config.filters.tests = tests;
41
+ }
42
+ };
@@ -0,0 +1,7 @@
1
+ import type { TestEndNode } from '../../modules/core/types.js';
2
+ import { BaseReporter } from '../../modules/core/reporters/base.js';
3
+ export declare class DotReporter extends BaseReporter {
4
+ protected onTestEnd(payload: TestEndNode): void;
5
+ protected end(): Promise<void>;
6
+ }
7
+ //# sourceMappingURL=dot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dot.d.ts","sourceRoot":"","sources":["../../../src/reporters/dot.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAA;AAKnE,qBAAa,WAAY,SAAQ,YAAY;IAI3C,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,WAAW;cAkBxB,GAAG;CAIpB"}
@@ -0,0 +1,24 @@
1
+ import cliui from '../helpers.js';
2
+ import { BaseReporter } from '../../modules/core/reporters/base.js';
3
+ export class DotReporter extends BaseReporter {
4
+ onTestEnd(payload) {
5
+ let output = '';
6
+ if (payload.isTodo) {
7
+ output = cliui.colors.cyan('-');
8
+ }
9
+ else if (payload.hasError || payload.isFailing) {
10
+ output = cliui.colors.red('×');
11
+ }
12
+ else if (payload.isSkipped) {
13
+ output = cliui.colors.yellow('-');
14
+ }
15
+ else {
16
+ output = cliui.colors.green('•');
17
+ }
18
+ process.stdout.write(`${output}`);
19
+ }
20
+ async end() {
21
+ console.log('');
22
+ await this.printSummary(this.runner.getSummary());
23
+ }
24
+ }
@@ -0,0 +1,5 @@
1
+ import type { BaseReporterOptions, NamedReporterContract } from '../types.js';
2
+ export declare const spec: (options?: BaseReporterOptions) => NamedReporterContract;
3
+ export declare const dot: (options?: BaseReporterOptions) => NamedReporterContract;
4
+ export declare const ndjson: (options?: BaseReporterOptions) => NamedReporterContract;
5
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/reporters/main.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAK7E,eAAO,MAAM,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,qBAKrD,CAAA;AAKD,eAAO,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,qBAKpD,CAAA;AAKD,eAAO,MAAM,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,qBAKvD,CAAA"}