@japa/runner 3.0.0-8 → 3.0.0-9

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 (74) hide show
  1. package/build/examples/dot.d.ts +1 -0
  2. package/build/examples/dot.js +11 -0
  3. package/build/examples/ndjson.d.ts +1 -0
  4. package/build/examples/ndjson.js +11 -0
  5. package/build/examples/spec.d.ts +1 -0
  6. package/build/examples/spec.js +11 -0
  7. package/build/factories/create_diverse_tests.d.ts +6 -0
  8. package/build/factories/create_diverse_tests.js +106 -0
  9. package/build/factories/main.d.ts +5 -42
  10. package/build/factories/main.js +24 -208
  11. package/build/factories/runner.d.ts +26 -0
  12. package/build/factories/runner.js +93 -0
  13. package/build/index.d.ts +9 -14
  14. package/build/index.js +202 -237
  15. package/build/modules/core/main.d.ts +63 -3
  16. package/build/modules/core/main.js +121 -21
  17. package/build/modules/core/reporters/base.d.ts +41 -0
  18. package/build/modules/core/reporters/base.js +183 -0
  19. package/build/modules/core/types.d.ts +5 -0
  20. package/build/modules/core/types.js +9 -0
  21. package/build/src/cli_parser.d.ts +14 -0
  22. package/build/src/cli_parser.js +75 -0
  23. package/build/src/config_manager.d.ts +18 -0
  24. package/build/src/config_manager.js +168 -0
  25. package/build/src/create_test.d.ts +21 -0
  26. package/build/src/create_test.js +53 -0
  27. package/build/src/debug.d.ts +3 -0
  28. package/build/src/debug.js +10 -0
  29. package/build/src/exceptions_manager.d.ts +19 -0
  30. package/build/src/exceptions_manager.js +85 -0
  31. package/build/src/files_manager.d.ts +18 -0
  32. package/build/src/files_manager.js +57 -0
  33. package/build/src/helpers.d.ts +15 -0
  34. package/build/src/helpers.js +34 -0
  35. package/build/src/hooks.d.ts +20 -0
  36. package/build/src/hooks.js +46 -0
  37. package/build/src/planner.d.ts +25 -0
  38. package/build/src/planner.js +98 -0
  39. package/build/src/plugins/retry.d.ts +20 -0
  40. package/build/src/plugins/retry.js +66 -0
  41. package/build/src/reporters/dot.d.ts +15 -0
  42. package/build/src/reporters/dot.js +41 -0
  43. package/build/src/reporters/main.d.ts +4 -9
  44. package/build/src/reporters/main.js +37 -11
  45. package/build/src/reporters/ndjson.d.ts +15 -0
  46. package/build/src/reporters/ndjson.js +86 -0
  47. package/build/src/reporters/spec.d.ts +13 -0
  48. package/build/src/reporters/spec.js +152 -0
  49. package/build/src/types.d.ts +19 -23
  50. package/build/src/types.js +9 -14
  51. package/build/src/validator.d.ts +30 -0
  52. package/build/src/validator.js +85 -0
  53. package/build/tests/base_reporter.spec.d.ts +1 -0
  54. package/build/tests/base_reporter.spec.js +111 -0
  55. package/build/tests/cli_parser.spec.d.ts +1 -0
  56. package/build/tests/cli_parser.spec.js +265 -0
  57. package/build/tests/config_manager.spec.d.ts +1 -0
  58. package/build/tests/config_manager.spec.js +741 -0
  59. package/build/tests/core.spec.d.ts +1 -0
  60. package/build/tests/core.spec.js +31 -0
  61. package/build/tests/files_manager.spec.d.ts +1 -0
  62. package/build/tests/files_manager.spec.js +153 -0
  63. package/build/tests/planner.spec.d.ts +1 -0
  64. package/build/tests/planner.spec.js +510 -0
  65. package/build/tests/runner.spec.d.ts +1 -0
  66. package/build/tests/runner.spec.js +442 -0
  67. package/build/tests_helpers/main.d.ts +7 -0
  68. package/build/tests_helpers/main.js +34 -0
  69. package/package.json +2 -17
  70. package/build/chunk-7THDHQFT.js +0 -283
  71. package/build/chunk-HN4AVHWN.js +0 -17
  72. package/build/chunk-MCOW34SG.js +0 -269
  73. package/build/chunk-W5IABAQU.js +0 -502
  74. package/build/main-63126780.d.ts +0 -109
@@ -0,0 +1,86 @@
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
+ }
@@ -0,0 +1,13 @@
1
+ import { BaseReporter } from '../../modules/core/main.js';
2
+ import { GroupStartNode, TestEndNode } from '../../modules/core/types.js';
3
+ /**
4
+ * Pretty prints the tests on the console
5
+ */
6
+ export declare class SpecReporter extends BaseReporter {
7
+ #private;
8
+ protected onTestStart(): void;
9
+ protected onTestEnd(payload: TestEndNode): void;
10
+ protected onGroupStart(payload: GroupStartNode): void;
11
+ protected onGroupEnd(): void;
12
+ protected end(): Promise<void>;
13
+ }
@@ -0,0 +1,152 @@
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,31 +1,29 @@
1
- import { HookHandler } from '@poppinss/hooks/types';
2
- import { R as Runner, S as Suite } from '../main-63126780.js';
3
- export { B as BaseReporterOptions } from '../main-63126780.js';
4
- import { FilteringOptions, NamedReporterContract } from '@japa/core/types';
5
- export * from '@japa/core/types';
6
- import { Emitter, Refiner } from '@japa/core';
7
-
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import type { HookHandler } from '@poppinss/hooks/types';
3
+ import type { Emitter, Refiner, Runner, Suite } from '../modules/core/main.js';
4
+ import type { FilteringOptions, NamedReporterContract } from '../modules/core/types.js';
5
+ export * from '../modules/core/types.js';
8
6
  /**
9
7
  * Global setup hook
10
8
  */
11
- type SetupHookState = [[runner: Runner], [error: Error | null, runner: Runner]];
12
- type SetupHookHandler = HookHandler<SetupHookState[0], SetupHookState[1]>;
9
+ export type SetupHookState = [[runner: Runner], [error: Error | null, runner: Runner]];
10
+ export type SetupHookHandler = HookHandler<SetupHookState[0], SetupHookState[1]>;
13
11
  /**
14
12
  * Global teardown hook
15
13
  */
16
- type TeardownHookState = [[runner: Runner], [error: Error | null, runner: Runner]];
17
- type TeardownHookHandler = HookHandler<TeardownHookState[0], TeardownHookState[1]>;
14
+ export type TeardownHookState = [[runner: Runner], [error: Error | null, runner: Runner]];
15
+ export type TeardownHookHandler = HookHandler<TeardownHookState[0], TeardownHookState[1]>;
18
16
  /**
19
17
  * Global set of available hooks
20
18
  */
21
- type HooksEvents = {
19
+ export type HooksEvents = {
22
20
  setup: SetupHookState;
23
21
  teardown: TeardownHookState;
24
22
  };
25
23
  /**
26
24
  * Parsed command-line arguments
27
25
  */
28
- type CLIArgs = {
26
+ export type CLIArgs = {
29
27
  _?: string[];
30
28
  tags?: string | string[];
31
29
  files?: string | string[];
@@ -42,7 +40,7 @@ type CLIArgs = {
42
40
  /**
43
41
  * Set of filters you can apply to run only specific tests
44
42
  */
45
- type Filters = FilteringOptions & {
43
+ export type Filters = FilteringOptions & {
46
44
  files?: string[];
47
45
  suites?: string[];
48
46
  };
@@ -50,7 +48,7 @@ type Filters = FilteringOptions & {
50
48
  * Plugin function receives an instance of the runner,
51
49
  * emitter, config and the hooks
52
50
  */
53
- type PluginFn = (japa: {
51
+ export type PluginFn = (japa: {
54
52
  config: NormalizedConfig;
55
53
  cliArgs: CLIArgs;
56
54
  runner: Runner;
@@ -59,7 +57,7 @@ type PluginFn = (japa: {
59
57
  /**
60
58
  * Base configuration options
61
59
  */
62
- type BaseConfig = {
60
+ export type BaseConfig = {
63
61
  /**
64
62
  * Current working directory. It is required to search for
65
63
  * the test files
@@ -122,11 +120,11 @@ type BaseConfig = {
122
120
  * A collection of test files defined as a glob or a callback
123
121
  * function that returns an array of URLs
124
122
  */
125
- type TestFiles = string | string[] | (() => URL[] | Promise<URL[]>);
123
+ export type TestFiles = string | string[] | (() => URL[] | Promise<URL[]>);
126
124
  /**
127
125
  * A test suite to register tests under a named suite
128
126
  */
129
- type TestSuite = {
127
+ export type TestSuite = {
130
128
  /**
131
129
  * A unique name for the suite
132
130
  */
@@ -153,7 +151,7 @@ type TestSuite = {
153
151
  /**
154
152
  * BaseConfig after normalized by the config manager
155
153
  */
156
- type NormalizedBaseConfig = Required<Omit<BaseConfig, 'reporters'>> & {
154
+ export type NormalizedBaseConfig = Required<Omit<BaseConfig, 'reporters'>> & {
157
155
  reporters: {
158
156
  activated: string[];
159
157
  list: NamedReporterContract[];
@@ -162,7 +160,7 @@ type NormalizedBaseConfig = Required<Omit<BaseConfig, 'reporters'>> & {
162
160
  /**
163
161
  * Configuration options
164
162
  */
165
- type Config = BaseConfig & ({
163
+ export type Config = BaseConfig & ({
166
164
  files: TestFiles;
167
165
  } | {
168
166
  suites: TestSuite[];
@@ -170,10 +168,8 @@ type Config = BaseConfig & ({
170
168
  /**
171
169
  * Config after normalized by the config manager
172
170
  */
173
- type NormalizedConfig = NormalizedBaseConfig & ({
171
+ export type NormalizedConfig = NormalizedBaseConfig & ({
174
172
  files: TestFiles;
175
173
  } | {
176
174
  suites: Required<TestSuite>[];
177
175
  });
178
-
179
- export { BaseConfig, CLIArgs, Config, Filters, HooksEvents, NormalizedBaseConfig, NormalizedConfig, PluginFn, SetupHookHandler, SetupHookState, TeardownHookHandler, TeardownHookState, TestFiles, TestSuite };
@@ -1,14 +1,9 @@
1
- import {
2
- __reExport
3
- } from "../chunk-HN4AVHWN.js";
4
-
5
- // src/types.ts
6
- var types_exports2 = {};
7
-
8
- // modules/core/types.ts
9
- var types_exports = {};
10
- __reExport(types_exports, types_star);
11
- import * as types_star from "@japa/core/types";
12
-
13
- // src/types.ts
14
- __reExport(types_exports2, types_exports);
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
+ export * from '../modules/core/types.js';
@@ -0,0 +1,30 @@
1
+ import { NormalizedConfig } from './types.js';
2
+ /**
3
+ * Validator encapsulates the validations to perform before running
4
+ * the tests
5
+ */
6
+ declare class Validator {
7
+ /**
8
+ * Ensures the japa is configured. Otherwise raises an exception
9
+ */
10
+ ensureIsConfigured(config: NormalizedConfig | undefined): void;
11
+ /**
12
+ * Ensures the japa is in planning phase
13
+ */
14
+ ensureIsInPlanningPhase(phase: 'idle' | 'planning' | 'executing'): void;
15
+ /**
16
+ * Ensures the suites filter uses a subset of the user configured suites.
17
+ */
18
+ validateSuitesFilter(config: NormalizedConfig): void;
19
+ /**
20
+ * Ensure there are unique suites
21
+ */
22
+ validateSuitesForUniqueness(config: NormalizedConfig): void;
23
+ /**
24
+ * Ensure the activated reporters are in the list of defined
25
+ * reporters
26
+ */
27
+ validateActivatedReporters(config: NormalizedConfig): void;
28
+ }
29
+ declare const _default: Validator;
30
+ export default _default;
@@ -0,0 +1,85 @@
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();
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,111 @@
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 { test } from 'node:test';
10
+ import chaiSubset from 'chai-subset';
11
+ import { assert, default as chai } from 'chai';
12
+ chai.use(chaiSubset);
13
+ import { wrapAssertions } from '../tests_helpers/main.js';
14
+ import { Test, Suite, Group, Runner, Refiner, Emitter, TestContext, BaseReporter, } from '../modules/core/main.js';
15
+ test.describe('Base reporter', () => {
16
+ test('extend base reporter to create a custom reporter', async () => {
17
+ const stack = [];
18
+ class MyReporter extends BaseReporter {
19
+ async start() {
20
+ stack.push('reporter started');
21
+ }
22
+ }
23
+ const emitter = new Emitter();
24
+ const runner = new Runner(emitter);
25
+ runner.registerReporter((r, e) => new MyReporter({}).boot(r, e));
26
+ await runner.start();
27
+ await wrapAssertions(() => {
28
+ assert.deepEqual(stack, ['reporter started']);
29
+ });
30
+ });
31
+ test('invoke handlers when suite, groups and tests are executed', async () => {
32
+ const stack = [];
33
+ let summary;
34
+ class MyReporter extends BaseReporter {
35
+ async start() {
36
+ stack.push('reporter started');
37
+ }
38
+ async end() {
39
+ summary = this.runner.getSummary();
40
+ stack.push('reporter ended');
41
+ }
42
+ onTestStart(t) {
43
+ assert.equal(t.title.expanded, '2 + 2');
44
+ assert.equal(this.currentSuiteName, 'unit');
45
+ assert.equal(this.currentGroupName, 'default');
46
+ stack.push('test started');
47
+ }
48
+ onTestEnd(t) {
49
+ assert.equal(t.title.expanded, '2 + 2');
50
+ assert.isFalse(t.hasError);
51
+ stack.push('test ended');
52
+ }
53
+ onGroupStart(g) {
54
+ assert.equal(g.title, 'default');
55
+ assert.equal(this.currentSuiteName, 'unit');
56
+ stack.push('group started');
57
+ }
58
+ onGroupEnd(g) {
59
+ assert.equal(g.title, 'default');
60
+ assert.isFalse(g.hasError);
61
+ stack.push('group ended');
62
+ }
63
+ onSuiteStart(s) {
64
+ assert.equal(s.name, 'unit');
65
+ stack.push('suite started');
66
+ }
67
+ onSuiteEnd(s) {
68
+ assert.equal(s.name, 'unit');
69
+ stack.push('suite ended');
70
+ }
71
+ }
72
+ const emitter = new Emitter();
73
+ const runner = new Runner(emitter);
74
+ const refiner = new Refiner();
75
+ const suite = new Suite('unit', emitter, refiner);
76
+ const group = new Group('default', emitter, refiner);
77
+ const t = new Test('2 + 2', (_t) => new TestContext(_t), emitter, refiner, group);
78
+ group.add(t);
79
+ suite.add(group);
80
+ runner.add(suite);
81
+ runner.registerReporter((r, e) => new MyReporter({}).boot(r, e));
82
+ await runner.start();
83
+ await runner.exec();
84
+ await runner.end();
85
+ await wrapAssertions(() => {
86
+ assert.deepEqual(stack, [
87
+ 'reporter started',
88
+ 'suite started',
89
+ 'group started',
90
+ 'test started',
91
+ 'test ended',
92
+ 'group ended',
93
+ 'suite ended',
94
+ 'reporter ended',
95
+ ]);
96
+ assert.containSubset(summary, {
97
+ aggregates: {
98
+ total: 1,
99
+ failed: 0,
100
+ passed: 0,
101
+ regression: 0,
102
+ skipped: 0,
103
+ todo: 1,
104
+ },
105
+ hasError: false,
106
+ failureTree: [],
107
+ failedTestsTitles: [],
108
+ });
109
+ });
110
+ });
111
+ });
@@ -0,0 +1 @@
1
+ export {};