@japa/runner 3.0.4 → 3.0.5

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 (38) hide show
  1. package/build/chunk-52OY4QRJ.js +284 -0
  2. package/build/chunk-52OY4QRJ.js.map +1 -0
  3. package/build/chunk-CXTCA2MO.js +503 -0
  4. package/build/chunk-CXTCA2MO.js.map +1 -0
  5. package/build/chunk-MWYEWO7K.js +18 -0
  6. package/build/chunk-MWYEWO7K.js.map +1 -0
  7. package/build/chunk-PKOB3ULJ.js +270 -0
  8. package/build/chunk-PKOB3ULJ.js.map +1 -0
  9. package/build/factories/main.js +214 -29
  10. package/build/factories/main.js.map +1 -0
  11. package/build/index.js +243 -202
  12. package/build/index.js.map +1 -0
  13. package/build/modules/core/main.d.ts +0 -1
  14. package/build/modules/core/main.js +22 -121
  15. package/build/modules/core/main.js.map +1 -0
  16. package/build/src/reporters/main.js +12 -37
  17. package/build/src/reporters/main.js.map +1 -0
  18. package/build/src/types.js +15 -9
  19. package/build/src/types.js.map +1 -0
  20. package/package.json +32 -16
  21. package/build/factories/create_diverse_tests.js +0 -106
  22. package/build/factories/runner.js +0 -93
  23. package/build/modules/core/reporters/base.js +0 -183
  24. package/build/modules/core/types.js +0 -9
  25. package/build/src/cli_parser.js +0 -75
  26. package/build/src/config_manager.js +0 -168
  27. package/build/src/create_test.js +0 -53
  28. package/build/src/debug.js +0 -10
  29. package/build/src/exceptions_manager.js +0 -85
  30. package/build/src/files_manager.js +0 -57
  31. package/build/src/helpers.js +0 -34
  32. package/build/src/hooks.js +0 -46
  33. package/build/src/planner.js +0 -98
  34. package/build/src/plugins/retry.js +0 -72
  35. package/build/src/reporters/dot.js +0 -41
  36. package/build/src/reporters/ndjson.js +0 -86
  37. package/build/src/reporters/spec.js +0 -152
  38. package/build/src/validator.js +0 -85
@@ -1,168 +0,0 @@
1
- /*
2
- * @japa/runner
3
- *
4
- * (c) Japa
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- import debug from './debug.js';
10
- import { Refiner } from '../modules/core/main.js';
11
- import { dot, ndjson, spec } from './reporters/main.js';
12
- export const NOOP = () => { };
13
- /**
14
- * Defaults to use for configuration
15
- */
16
- const DEFAULTS = {
17
- files: [],
18
- timeout: 2000,
19
- retries: 0,
20
- forceExit: false,
21
- plugins: [],
22
- reporters: {
23
- activated: ['spec'],
24
- list: [spec(), ndjson(), dot()],
25
- },
26
- importer: (filePath) => import(filePath.href),
27
- configureSuite: () => { },
28
- };
29
- /**
30
- * Config manager is used to hydrate the configuration by merging
31
- * the defaults, user defined config and the command line
32
- * flags.
33
- *
34
- * The command line flags have the upmost priority
35
- */
36
- export class ConfigManager {
37
- #config;
38
- #cliArgs;
39
- constructor(config, cliArgs) {
40
- this.#config = config;
41
- this.#cliArgs = cliArgs;
42
- }
43
- /**
44
- * Processes a CLI argument and converts it to an
45
- * array of strings
46
- */
47
- #processAsArray(value) {
48
- return Array.isArray(value) ? value : value.split(',').map((item) => item.trim());
49
- }
50
- /**
51
- * Returns a copy of filters based upon the CLI
52
- * arguments.
53
- */
54
- #getCLIFilters() {
55
- const filters = {};
56
- if (this.#cliArgs.tags) {
57
- filters.tags = this.#processAsArray(this.#cliArgs.tags);
58
- }
59
- if (this.#cliArgs.tests) {
60
- filters.tests = this.#processAsArray(this.#cliArgs.tests);
61
- }
62
- if (this.#cliArgs.files) {
63
- filters.files = this.#processAsArray(this.#cliArgs.files);
64
- }
65
- if (this.#cliArgs.groups) {
66
- filters.groups = this.#processAsArray(this.#cliArgs.groups);
67
- }
68
- if (this.#cliArgs._ && this.#cliArgs._.length) {
69
- filters.suites = this.#processAsArray(this.#cliArgs._);
70
- }
71
- return filters;
72
- }
73
- /**
74
- * Returns the timeout from the CLI args
75
- */
76
- #getCLITimeout() {
77
- if (this.#cliArgs.timeout) {
78
- const value = Number(this.#cliArgs.timeout);
79
- if (!Number.isNaN(value)) {
80
- return value;
81
- }
82
- }
83
- }
84
- /**
85
- * Returns the retries from the CLI args
86
- */
87
- #getCLIRetries() {
88
- if (this.#cliArgs.retries) {
89
- const value = Number(this.#cliArgs.retries);
90
- if (!Number.isNaN(value)) {
91
- return value;
92
- }
93
- }
94
- }
95
- /**
96
- * Returns the forceExit property from the CLI args
97
- */
98
- #getCLIForceExit() {
99
- if (this.#cliArgs.forceExit) {
100
- return true;
101
- }
102
- }
103
- /**
104
- * Returns reporters selected using the commandline
105
- * --reporter flag
106
- */
107
- #getCLIReporters() {
108
- if (this.#cliArgs.reporters) {
109
- return this.#processAsArray(this.#cliArgs.reporters);
110
- }
111
- }
112
- /**
113
- * Hydrates the config with user defined options and the
114
- * command-line flags.
115
- */
116
- hydrate() {
117
- const cliFilters = this.#getCLIFilters();
118
- const cliRetries = this.#getCLIRetries();
119
- const cliTimeout = this.#getCLITimeout();
120
- const cliReporters = this.#getCLIReporters();
121
- const cliForceExit = this.#getCLIForceExit();
122
- debug('filters applied using CLI flags %O', cliFilters);
123
- const baseConfig = {
124
- cwd: this.#config.cwd ?? process.cwd(),
125
- filters: Object.assign({}, this.#config.filters ?? {}, cliFilters),
126
- importer: this.#config.importer ?? DEFAULTS.importer,
127
- refiner: this.#config.refiner ?? new Refiner(),
128
- retries: cliRetries ?? this.#config.retries ?? DEFAULTS.retries,
129
- timeout: cliTimeout ?? this.#config.timeout ?? DEFAULTS.timeout,
130
- plugins: this.#config.plugins ?? DEFAULTS.plugins,
131
- forceExit: cliForceExit ?? this.#config.forceExit ?? DEFAULTS.forceExit,
132
- reporters: this.#config.reporters
133
- ? {
134
- activated: this.#config.reporters.activated,
135
- list: this.#config.reporters.list || DEFAULTS.reporters.list,
136
- }
137
- : DEFAULTS.reporters,
138
- configureSuite: this.#config.configureSuite ?? DEFAULTS.configureSuite,
139
- setup: this.#config.setup || [],
140
- teardown: this.#config.teardown || [],
141
- };
142
- /**
143
- * Overwrite activated reporters when defined using CLI
144
- * flag
145
- */
146
- if (cliReporters) {
147
- baseConfig.reporters.activated = cliReporters;
148
- }
149
- if ('files' in this.#config) {
150
- return {
151
- files: this.#config.files,
152
- ...baseConfig,
153
- };
154
- }
155
- return {
156
- suites: this.#config.suites.map((suite) => {
157
- return {
158
- name: suite.name,
159
- files: suite.files,
160
- timeout: cliTimeout ?? suite.timeout ?? baseConfig.timeout,
161
- retries: cliRetries ?? suite.retries ?? baseConfig.retries,
162
- configure: suite.configure || NOOP,
163
- };
164
- }),
165
- ...baseConfig,
166
- };
167
- }
168
- }
@@ -1,53 +0,0 @@
1
- /*
2
- * @japa/runner
3
- *
4
- * (c) Japa
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- import { Group, Test, TestContext } from '../modules/core/main.js';
10
- /**
11
- * Function to create the test context for the test
12
- */
13
- const contextBuilder = (testInstance) => new TestContext(testInstance);
14
- /**
15
- * Create a new instance of the Test
16
- */
17
- export function createTest(title, emitter, refiner, options) {
18
- const testInstance = new Test(title, contextBuilder, emitter, refiner, options.group);
19
- testInstance.options.meta.suite = options.suite;
20
- testInstance.options.meta.group = options.group;
21
- testInstance.options.meta.fileName = options.file;
22
- if (options.timeout !== undefined) {
23
- testInstance.timeout(options.timeout);
24
- }
25
- if (options.retries !== undefined) {
26
- testInstance.retry(options.retries);
27
- }
28
- /**
29
- * Register test as a child either with the group or the suite
30
- */
31
- if (options.group) {
32
- options.group.add(testInstance);
33
- }
34
- else if (options.suite) {
35
- options.suite.add(testInstance);
36
- }
37
- return testInstance;
38
- }
39
- /**
40
- * Create a new instance of the Group
41
- */
42
- export function createTestGroup(title, emitter, refiner, options) {
43
- if (options.group) {
44
- throw new Error('Nested groups are not supported by Japa');
45
- }
46
- const group = new Group(title, emitter, refiner);
47
- group.options.meta.suite = options.suite;
48
- group.options.meta.fileName = options.file;
49
- if (options.suite) {
50
- options.suite.add(group);
51
- }
52
- return group;
53
- }
@@ -1,10 +0,0 @@
1
- /*
2
- * @japa/runner
3
- *
4
- * (c) Japa
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- import { debuglog } from 'node:util';
10
- export default debuglog('japa:runner');
@@ -1,85 +0,0 @@
1
- /*
2
- * @japa/runner
3
- *
4
- * (c) Japa
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- import { ErrorsPrinter } from '@japa/errors-printer';
10
- /**
11
- * Handles uncaught exceptions and prints them to the
12
- * console
13
- */
14
- export class ExceptionsManager {
15
- #exceptionsBuffer = [];
16
- #rejectionsBuffer = [];
17
- #state = 'watching';
18
- #errorsPrinter = new ErrorsPrinter({ stackLinesCount: 2, framesMaxLimit: 4 });
19
- hasErrors = false;
20
- /**
21
- * Monitors unhandled exceptions and rejections. The exceptions
22
- * are stacked in a buffer, so that we do not clutter the
23
- * tests output and once the tests are over, we will
24
- * print them to the console.
25
- *
26
- * In case the tests are completed, we will print errors as they
27
- * happen.
28
- */
29
- monitor() {
30
- process.on('uncaughtException', async (error) => {
31
- this.hasErrors = true;
32
- if (this.#state === 'watching') {
33
- this.#exceptionsBuffer.push(error);
34
- }
35
- else {
36
- this.#errorsPrinter.printSectionBorder('[Unhandled Error]');
37
- await this.#errorsPrinter.printError(error);
38
- process.exitCode = 1;
39
- }
40
- });
41
- process.on('unhandledRejection', async (error) => {
42
- this.hasErrors = true;
43
- if (this.#state === 'watching') {
44
- this.#rejectionsBuffer.push(error);
45
- }
46
- else {
47
- this.#errorsPrinter.printSectionBorder('[Unhandled Rejection]');
48
- await this.#errorsPrinter.printError(error);
49
- process.exitCode = 1;
50
- }
51
- });
52
- }
53
- async flow() {
54
- if (this.#state === 'flowing') {
55
- return;
56
- }
57
- this.#state = 'flowing';
58
- /**
59
- * Print exceptions
60
- */
61
- if (this.#exceptionsBuffer.length) {
62
- let exceptionsCount = this.#exceptionsBuffer.length;
63
- let exceptionsIndex = this.#exceptionsBuffer.length;
64
- this.#errorsPrinter.printSectionHeader('Unhandled Errors');
65
- for (let exception of this.#exceptionsBuffer) {
66
- await this.#errorsPrinter.printError(exception);
67
- this.#errorsPrinter.printSectionBorder(`[${++exceptionsIndex}/${exceptionsCount}]`);
68
- }
69
- this.#exceptionsBuffer = [];
70
- }
71
- /**
72
- * Print rejections
73
- */
74
- if (this.#rejectionsBuffer.length) {
75
- let rejectionsCount = this.#exceptionsBuffer.length;
76
- let rejectionsIndex = this.#exceptionsBuffer.length;
77
- this.#errorsPrinter.printSectionBorder('Unhandled Rejections');
78
- for (let rejection of this.#rejectionsBuffer) {
79
- await this.#errorsPrinter.printError(rejection);
80
- this.#errorsPrinter.printSectionBorder(`[${++rejectionsIndex}/${rejectionsCount}]`);
81
- }
82
- this.#rejectionsBuffer = [];
83
- }
84
- }
85
- }
@@ -1,57 +0,0 @@
1
- /*
2
- * @japa/runner
3
- *
4
- * (c) Japa
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- import slash from 'slash';
10
- import fastGlob from 'fast-glob';
11
- import { pathToFileURL } from 'node:url';
12
- /**
13
- * The expression to remove file extension and optionally
14
- * .spec|.test from the test file name
15
- */
16
- const FILE_SUFFIX_EXPRESSION = /(\.spec|\.test)?\.[js|ts|jsx|tsx|mjs|mts|cjs|cts]+$/;
17
- /**
18
- * Files manager exposes the API to collect, filter and import test
19
- * files based upon the config
20
- */
21
- export class FilesManager {
22
- /**
23
- * Returns a collection of files from the user defined
24
- * glob or the implementation function
25
- */
26
- async getFiles(cwd, files) {
27
- if (Array.isArray(files) || typeof files === 'string') {
28
- const testFiles = await fastGlob(files, {
29
- absolute: true,
30
- onlyFiles: true,
31
- cwd: cwd,
32
- });
33
- return testFiles.map((file) => pathToFileURL(file));
34
- }
35
- return await files();
36
- }
37
- /**
38
- * Applies file name filter on a collection of file
39
- * URLs
40
- */
41
- grep(files, filters) {
42
- return files.filter((file) => {
43
- const filename = slash(file.pathname);
44
- const filenameWithoutTestSuffix = filename.replace(FILE_SUFFIX_EXPRESSION, '');
45
- return !!filters.find((filter) => {
46
- if (filename.endsWith(filter)) {
47
- return true;
48
- }
49
- const filterSegments = filter.split('/').reverse();
50
- const fileSegments = filenameWithoutTestSuffix.split('/').reverse();
51
- return filterSegments.every((segment, index) => {
52
- return fileSegments[index] && (segment === '*' || fileSegments[index].endsWith(segment));
53
- });
54
- });
55
- });
56
- }
57
- }
@@ -1,34 +0,0 @@
1
- /*
2
- * @japa/runner
3
- *
4
- * (c) Japa
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- import useColors from '@poppinss/colors';
10
- export const colors = useColors.ansi();
11
- /**
12
- * A collection of platform specific icons
13
- */
14
- export const icons = process.platform === 'win32' && !process.env.WT_SESSION
15
- ? {
16
- tick: '√',
17
- cross: '×',
18
- bullet: '*',
19
- nodejs: '♦',
20
- pointer: '>',
21
- info: 'i',
22
- warning: '‼',
23
- squareSmallFilled: '[█]',
24
- }
25
- : {
26
- tick: '✔',
27
- cross: '✖',
28
- bullet: '●',
29
- nodejs: '⬢',
30
- pointer: '❯',
31
- info: 'ℹ',
32
- warning: '⚠',
33
- squareSmallFilled: '◼',
34
- };
@@ -1,46 +0,0 @@
1
- /*
2
- * @japa/runner
3
- *
4
- * (c) Japa
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- import Hooks from '@poppinss/hooks';
10
- /**
11
- * Exposes API for working with global hooks
12
- */
13
- export class GlobalHooks {
14
- #hooks = new Hooks();
15
- #setupRunner;
16
- #teardownRunner;
17
- /**
18
- * Apply hooks from the config
19
- */
20
- apply(config) {
21
- config.setup.forEach((hook) => this.#hooks.add('setup', hook));
22
- config.teardown.forEach((hook) => this.#hooks.add('teardown', hook));
23
- }
24
- /**
25
- * Perform setup
26
- */
27
- async setup(runner) {
28
- this.#setupRunner = this.#hooks.runner('setup');
29
- this.#teardownRunner = this.#hooks.runner('teardown');
30
- await this.#setupRunner.run(runner);
31
- }
32
- /**
33
- * Perform cleanup
34
- */
35
- async teardown(error, runner) {
36
- if (this.#setupRunner) {
37
- await this.#setupRunner.cleanup(error, runner);
38
- }
39
- if (this.#teardownRunner) {
40
- if (!error) {
41
- await this.#teardownRunner.run(runner);
42
- }
43
- await this.#teardownRunner.cleanup(error, runner);
44
- }
45
- }
46
- }
@@ -1,98 +0,0 @@
1
- /*
2
- * @japa/runner
3
- *
4
- * (c) Japa
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- import validator from './validator.js';
10
- import { FilesManager } from './files_manager.js';
11
- /**
12
- * The tests planner is used to plan the tests by doing all
13
- * the heavy lifting of executing plugins, registering
14
- * reporters, filtering tests and so on.
15
- */
16
- export class Planner {
17
- #config;
18
- #fileManager = new FilesManager();
19
- constructor(config) {
20
- validator.validateActivatedReporters(config);
21
- validator.validateSuitesFilter(config);
22
- validator.validateSuitesForUniqueness(config);
23
- this.#config = config;
24
- }
25
- /**
26
- * Returns a list of reporters based upon the activated
27
- * reporters list.
28
- */
29
- #getActivatedReporters() {
30
- return this.#config.reporters.activated.map((activated) => {
31
- return this.#config.reporters.list.find(({ name }) => activated === name);
32
- });
33
- }
34
- /**
35
- * A generic method to collect files from the user defined
36
- * files glob and apply the files filter
37
- */
38
- async #collectFiles(files) {
39
- let filesURLs = await this.#fileManager.getFiles(this.#config.cwd, files);
40
- if (this.#config.filters.files && this.#config.filters.files.length) {
41
- filesURLs = this.#fileManager.grep(filesURLs, this.#config.filters.files);
42
- }
43
- return filesURLs;
44
- }
45
- /**
46
- * Returns a collection of suites and their associated
47
- * test files by applying all the filters
48
- */
49
- async #getSuites() {
50
- let suites = [];
51
- let suitesFilters = this.#config.filters.suites || [];
52
- if ('files' in this.#config) {
53
- suites.push({
54
- name: 'default',
55
- files: this.#config.files,
56
- timeout: this.#config.timeout,
57
- retries: this.#config.retries,
58
- filesURLs: await this.#collectFiles(this.#config.files),
59
- });
60
- }
61
- if ('suites' in this.#config) {
62
- for (let suite of this.#config.suites) {
63
- if (!suitesFilters.length || suitesFilters.includes(suite.name)) {
64
- suites.push({
65
- ...suite,
66
- filesURLs: await this.#collectFiles(suite.files),
67
- });
68
- }
69
- }
70
- }
71
- return suites;
72
- }
73
- /**
74
- * Returns a list of filters to the passed to the refiner
75
- */
76
- #getRefinerFilters() {
77
- return Object.keys(this.#config.filters).reduce((result, layer) => {
78
- if (layer === 'tests' || layer === 'tags' || layer === 'groups') {
79
- result.push({ layer, filters: this.#config.filters[layer] });
80
- }
81
- return result;
82
- }, []);
83
- }
84
- /**
85
- * Creates a plan for running the tests
86
- */
87
- async plan() {
88
- const suites = await this.#getSuites();
89
- const reporters = this.#getActivatedReporters();
90
- const refinerFilters = this.#getRefinerFilters();
91
- return {
92
- reporters,
93
- suites,
94
- refinerFilters,
95
- config: this.#config,
96
- };
97
- }
98
- }
@@ -1,72 +0,0 @@
1
- /*
2
- * @japa/runner
3
- *
4
- * (c) Japa
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- import { join } from 'node:path';
10
- import findCacheDirectory from 'find-cache-dir';
11
- import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
12
- import { colors } from '../helpers.js';
13
- /**
14
- * Paths to the cache directory and the summary file
15
- */
16
- const CACHE_DIR = findCacheDirectory({ name: '@japa/runner' });
17
- const SUMMARY_FILE = CACHE_DIR ? join(CACHE_DIR, 'summary.json') : undefined;
18
- /**
19
- * Returns an object with the title of the tests failed during
20
- * the last run.
21
- */
22
- export async function getFailedTests() {
23
- try {
24
- const summary = await readFile(SUMMARY_FILE, 'utf-8');
25
- return JSON.parse(summary);
26
- }
27
- catch (error) {
28
- if (error.code === 'ENOENT') {
29
- return {};
30
- }
31
- throw new Error('Unable to read failed tests cache file', { cause: error });
32
- }
33
- }
34
- /**
35
- * Writes failing tests to the cache directory
36
- */
37
- export async function cacheFailedTests(tests) {
38
- await mkdir(CACHE_DIR, { recursive: true });
39
- await writeFile(SUMMARY_FILE, JSON.stringify({ tests: tests }));
40
- }
41
- /**
42
- * Clears the cache dir
43
- */
44
- export async function clearCache() {
45
- await unlink(SUMMARY_FILE);
46
- }
47
- /**
48
- * Exposes the API to run failing tests using the "failed" CLI flag.
49
- */
50
- export const retryPlugin = async function retry({ config, cliArgs }) {
51
- if (!SUMMARY_FILE) {
52
- return;
53
- }
54
- config.teardown.push(async (runner) => {
55
- const summary = runner.getSummary();
56
- await cacheFailedTests(summary.failedTestsTitles);
57
- });
58
- if (cliArgs.failed) {
59
- try {
60
- const { tests } = await getFailedTests();
61
- if (!tests || !tests.length) {
62
- console.log(colors.bgYellow().black(' No failing tests found. Running all the tests '));
63
- return;
64
- }
65
- config.filters.tests = tests;
66
- }
67
- catch (error) {
68
- console.log(colors.bgRed().black(' Unable to read failed tests. Running all the tests '));
69
- console.log(colors.red(error));
70
- }
71
- }
72
- };
@@ -1,41 +0,0 @@
1
- /*
2
- * @japa/runner
3
- *
4
- * (c) Japa
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- import { colors, icons } from '../helpers.js';
10
- import { BaseReporter } from '../../modules/core/reporters/base.js';
11
- /**
12
- * Minimal reporter that prints each test as an icon.
13
- */
14
- export class DotReporter extends BaseReporter {
15
- /**
16
- * When a test ended
17
- */
18
- onTestEnd(payload) {
19
- let output = '';
20
- if (payload.isTodo) {
21
- output = colors.cyan(icons.info);
22
- }
23
- else if (payload.hasError || payload.isFailing) {
24
- output = payload.hasError ? colors.magenta(icons.squareSmallFilled) : colors.red(icons.cross);
25
- }
26
- else if (payload.isSkipped) {
27
- output = colors.yellow(icons.bullet);
28
- }
29
- else {
30
- output = colors.green(icons.tick);
31
- }
32
- process.stdout.write(`${output}`);
33
- }
34
- /**
35
- * When test runner ended
36
- */
37
- async end() {
38
- console.log('');
39
- await this.printSummary(this.runner.getSummary());
40
- }
41
- }