@japa/runner 3.0.4 → 3.1.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 (40) hide show
  1. package/build/chunk-52OY4QRJ.js +284 -0
  2. package/build/chunk-52OY4QRJ.js.map +1 -0
  3. package/build/chunk-IKX2FPUC.js +505 -0
  4. package/build/chunk-IKX2FPUC.js.map +1 -0
  5. package/build/chunk-OBDV3O36.js +18 -0
  6. package/build/chunk-OBDV3O36.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/files_manager.d.ts +1 -1
  17. package/build/src/reporters/main.js +12 -37
  18. package/build/src/reporters/main.js.map +1 -0
  19. package/build/src/types.d.ts +8 -0
  20. package/build/src/types.js +15 -9
  21. package/build/src/types.js.map +1 -0
  22. package/package.json +42 -26
  23. package/build/factories/create_diverse_tests.js +0 -106
  24. package/build/factories/runner.js +0 -93
  25. package/build/modules/core/reporters/base.js +0 -183
  26. package/build/modules/core/types.js +0 -9
  27. package/build/src/cli_parser.js +0 -75
  28. package/build/src/config_manager.js +0 -168
  29. package/build/src/create_test.js +0 -53
  30. package/build/src/debug.js +0 -10
  31. package/build/src/exceptions_manager.js +0 -85
  32. package/build/src/files_manager.js +0 -57
  33. package/build/src/helpers.js +0 -34
  34. package/build/src/hooks.js +0 -46
  35. package/build/src/planner.js +0 -98
  36. package/build/src/plugins/retry.js +0 -72
  37. package/build/src/reporters/dot.js +0 -41
  38. package/build/src/reporters/ndjson.js +0 -86
  39. package/build/src/reporters/spec.js +0 -152
  40. package/build/src/validator.js +0 -85
@@ -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
- }
@@ -1,86 +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 { relative } from 'node:path';
10
- import { serializeError } from 'serialize-error';
11
- import { BaseReporter } from '../../modules/core/main.js';
12
- /**
13
- * Prints tests progress as JSON. Each event is emitted
14
- * independently
15
- */
16
- export class NdJSONReporter extends BaseReporter {
17
- /**
18
- * Returns the filename relative from the current working dir
19
- */
20
- #getRelativeFilename(fileName) {
21
- return relative(process.cwd(), fileName);
22
- }
23
- /**
24
- * Serialize errors to JSON
25
- */
26
- #serializeErrors(errors) {
27
- return errors.map((error) => ({
28
- phase: error.phase,
29
- error: serializeError(error.error),
30
- }));
31
- }
32
- onTestEnd(payload) {
33
- console.log(JSON.stringify({
34
- event: 'test:end',
35
- filePath: this.currentFileName,
36
- relativePath: this.currentFileName
37
- ? this.#getRelativeFilename(this.currentFileName)
38
- : undefined,
39
- title: payload.title,
40
- duration: payload.duration,
41
- failReason: payload.failReason,
42
- isFailing: payload.isFailing,
43
- skipReason: payload.skipReason,
44
- isSkipped: payload.isSkipped,
45
- isTodo: payload.isTodo,
46
- isPinned: payload.isPinned,
47
- retryAttempt: payload.retryAttempt,
48
- retries: payload.retries,
49
- errors: this.#serializeErrors(payload.errors),
50
- }));
51
- }
52
- onGroupStart(payload) {
53
- console.log(JSON.stringify({
54
- event: 'group:start',
55
- title: payload.title,
56
- }));
57
- }
58
- onGroupEnd(payload) {
59
- JSON.stringify({
60
- event: 'group:end',
61
- title: payload.title,
62
- errors: this.#serializeErrors(payload.errors),
63
- });
64
- }
65
- onSuiteStart(payload) {
66
- console.log(JSON.stringify({
67
- event: 'suite:start',
68
- ...payload,
69
- }));
70
- }
71
- onSuiteEnd(payload) {
72
- console.log(JSON.stringify({
73
- event: 'suite:end',
74
- ...payload,
75
- }));
76
- }
77
- async end() {
78
- const summary = this.runner.getSummary();
79
- console.log(JSON.stringify({
80
- aggregates: summary.aggregates,
81
- duration: summary.duration,
82
- failedTestsTitles: summary.failedTestsTitles,
83
- hasError: summary.hasError,
84
- }));
85
- }
86
- }
@@ -1,152 +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 ms from 'ms';
10
- import { relative } from 'node:path';
11
- import { colors, icons } from '../helpers.js';
12
- import { BaseReporter } from '../../modules/core/main.js';
13
- /**
14
- * Pretty prints the tests on the console
15
- */
16
- export class SpecReporter extends BaseReporter {
17
- /**
18
- * Tracking if the first event we get is for a test without any parent group
19
- * We need this to decide the display style for tests without groups.
20
- */
21
- #isFirstLoneTest = true;
22
- /**
23
- * Returns the icon for the test
24
- */
25
- #getTestIcon(payload) {
26
- if (payload.isTodo) {
27
- return colors.cyan(icons.info);
28
- }
29
- if (payload.isFailing) {
30
- return payload.hasError ? colors.magenta(icons.squareSmallFilled) : colors.red(icons.cross);
31
- }
32
- if (payload.hasError) {
33
- return colors.red(icons.cross);
34
- }
35
- if (payload.isSkipped) {
36
- return colors.yellow(icons.bullet);
37
- }
38
- return colors.green(icons.tick);
39
- }
40
- /**
41
- * Returns the test message
42
- */
43
- #getTestMessage(payload) {
44
- const message = typeof payload.title === 'string' ? payload.title : payload.title.expanded;
45
- if (payload.isTodo) {
46
- return colors.blue(message);
47
- }
48
- if (payload.isFailing) {
49
- return payload.hasError ? colors.magenta(message) : colors.red(message);
50
- }
51
- if (payload.hasError) {
52
- return colors.red(message);
53
- }
54
- if (payload.isSkipped) {
55
- return colors.yellow(message);
56
- }
57
- return colors.grey(message);
58
- }
59
- /**
60
- * Returns the subtext message for the test
61
- */
62
- #getSubText(payload) {
63
- if (payload.isSkipped && payload.skipReason) {
64
- return colors.yellow(payload.skipReason);
65
- }
66
- if (!payload.isFailing) {
67
- return;
68
- }
69
- if (!payload.hasError) {
70
- return colors.magenta(`Test marked with ".fails()" must finish with an error`);
71
- }
72
- if (payload.failReason) {
73
- return colors.magenta(payload.failReason);
74
- }
75
- const testErrorMessage = payload.errors.find((error) => error.phase === 'test');
76
- if (testErrorMessage && testErrorMessage.error) {
77
- return colors.magenta(testErrorMessage.error.message);
78
- }
79
- }
80
- /**
81
- * Returns the filename relative from the current working dir
82
- */
83
- #getRelativeFilename(fileName) {
84
- return relative(process.cwd(), fileName);
85
- }
86
- /**
87
- * Prints the test details
88
- */
89
- #printTest(payload) {
90
- const icon = this.#getTestIcon(payload);
91
- const message = this.#getTestMessage(payload);
92
- const prefix = payload.isPinned ? colors.yellow('[PINNED] ') : '';
93
- const indentation = this.currentFileName || this.currentGroupName ? ' ' : '';
94
- const duration = colors.dim(`(${ms(Number(payload.duration.toFixed(2)))})`);
95
- const retries = payload.retryAttempt && payload.retryAttempt > 1
96
- ? colors.dim(`(x${payload.retryAttempt}) `)
97
- : '';
98
- let subText = this.#getSubText(payload);
99
- subText = subText ? `\n${indentation} ${subText}` : '';
100
- console.log(`${indentation}${icon} ${prefix}${retries}${message} ${duration}${subText}`);
101
- }
102
- /**
103
- * Prints the group name
104
- */
105
- #printGroup(payload) {
106
- const title = this.currentSuiteName !== 'default'
107
- ? `${this.currentSuiteName} / ${payload.title}`
108
- : payload.title;
109
- const suffix = this.currentFileName
110
- ? colors.dim(` (${this.#getRelativeFilename(this.currentFileName)})`)
111
- : '';
112
- console.log(`\n${title}${suffix}`);
113
- }
114
- onTestStart() {
115
- /**
116
- * Display the filename when
117
- *
118
- * - The filename exists
119
- * - The test is not under a group
120
- * - Test is first in a sequence
121
- */
122
- if (this.currentFileName && this.#isFirstLoneTest) {
123
- console.log(`\n${colors.dim(this.#getRelativeFilename(this.currentFileName))}`);
124
- }
125
- this.#isFirstLoneTest = false;
126
- }
127
- onTestEnd(payload) {
128
- this.#printTest(payload);
129
- }
130
- onGroupStart(payload) {
131
- /**
132
- * When a group starts, we mark the upcoming test as NOT a
133
- * lone test
134
- */
135
- this.#isFirstLoneTest = false;
136
- this.#printGroup(payload);
137
- }
138
- onGroupEnd() {
139
- /**
140
- * When the group ends we assume that the next test can
141
- * be out of the group, hence a lone test.
142
- *
143
- * If this assumption is false, then the `onGroupStart` method
144
- * will toggle the boolean
145
- */
146
- this.#isFirstLoneTest = true;
147
- }
148
- async end() {
149
- const summary = this.runner.getSummary();
150
- await this.printSummary(summary);
151
- }
152
- }
@@ -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
- /**
10
- * Validator encapsulates the validations to perform before running
11
- * the tests
12
- */
13
- class Validator {
14
- /**
15
- * Ensures the japa is configured. Otherwise raises an exception
16
- */
17
- ensureIsConfigured(config) {
18
- if (!config) {
19
- throw new Error(`Cannot run tests. Make sure to call "configure" method before the "run" method`);
20
- }
21
- }
22
- /**
23
- * Ensures the japa is in planning phase
24
- */
25
- ensureIsInPlanningPhase(phase) {
26
- if (phase !== 'planning') {
27
- throw new Error(`Cannot import japa test file directly. It must be imported by calling the "japa.run" method`);
28
- }
29
- }
30
- /**
31
- * Ensures the suites filter uses a subset of the user configured suites.
32
- */
33
- validateSuitesFilter(config) {
34
- /**
35
- * Do not perform any validation if no filters are applied
36
- * in the first place
37
- */
38
- if (!config.filters.suites || !config.filters.suites.length) {
39
- return;
40
- }
41
- /**
42
- * Notify user they have applied the suites filter but forgot to define
43
- * suites
44
- */
45
- if (!('suites' in config) || !config.suites.length) {
46
- throw new Error(`Cannot apply suites filter. You have not configured any test suites`);
47
- }
48
- const suites = config.suites.map(({ name }) => name);
49
- /**
50
- * Find unknown suites and report the error
51
- */
52
- const unknownSuites = config.filters.suites.filter((suite) => !suites.includes(suite));
53
- if (unknownSuites.length) {
54
- throw new Error(`Cannot apply suites filter. "${unknownSuites[0]}" suite is not configured`);
55
- }
56
- }
57
- /**
58
- * Ensure there are unique suites
59
- */
60
- validateSuitesForUniqueness(config) {
61
- if (!('suites' in config)) {
62
- return;
63
- }
64
- const suites = new Set();
65
- config.suites.forEach(({ name }) => {
66
- if (suites.has(name)) {
67
- throw new Error(`Duplicate suite "${name}"`);
68
- }
69
- suites.add(name);
70
- });
71
- suites.clear();
72
- }
73
- /**
74
- * Ensure the activated reporters are in the list of defined
75
- * reporters
76
- */
77
- validateActivatedReporters(config) {
78
- const reportersList = config.reporters.list.map(({ name }) => name);
79
- const unknownReporters = config.reporters.activated.filter((name) => !reportersList.includes(name));
80
- if (unknownReporters.length) {
81
- throw new Error(`Invalid reporter "${unknownReporters[0]}". Make sure to register it first inside the "reporters.list" array`);
82
- }
83
- }
84
- }
85
- export default new Validator();