@japa/runner 3.0.0-0 → 3.0.0-1
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.
- package/build/factories/main.d.ts +3 -0
- package/build/factories/main.d.ts.map +1 -0
- package/build/factories/main.js +2 -0
- package/build/factories/runner.d.ts +10 -0
- package/build/factories/runner.d.ts.map +1 -0
- package/build/factories/runner.js +155 -0
- package/build/modules/core/main.d.ts +29 -0
- package/build/modules/core/main.d.ts.map +1 -0
- package/build/modules/core/main.js +68 -0
- package/build/modules/core/reporters/base.d.ts +21 -0
- package/build/modules/core/reporters/base.d.ts.map +1 -0
- package/build/modules/core/reporters/base.js +136 -0
- package/build/modules/core/types.d.ts +6 -0
- package/build/modules/core/types.d.ts.map +1 -0
- package/build/modules/core/types.js +1 -0
- package/package.json +3 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../factories/main.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAK3C,eAAO,MAAM,MAAM,qBAA4B,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Config } from '../src/types.js';
|
|
2
|
+
import { Suite, Emitter } from '../modules/core/main.js';
|
|
3
|
+
export declare class RunnerFactory {
|
|
4
|
+
#private;
|
|
5
|
+
configure(config: Config, argv?: string[]): this;
|
|
6
|
+
withSuites(suites: Suite[]): this;
|
|
7
|
+
useEmitter(emitter: Emitter): this;
|
|
8
|
+
run(): Promise<import("@japa/core/types").RunnerSummary>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../factories/runner.ts"],"names":[],"mappings":"AAeA,OAAO,EAAW,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAGjD,OAAO,EAAS,KAAK,EAAU,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAOvE,qBAAa,aAAa;;IAmJxB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE;IAUzC,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE;IAQ1B,UAAU,CAAC,OAAO,EAAE,OAAO;IAQrB,GAAG;CAoCV"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { Planner } from '../src/planner.js';
|
|
4
|
+
import { GlobalHooks } from '../src/hooks.js';
|
|
5
|
+
import { CliParser } from '../src/cli_parser.js';
|
|
6
|
+
import { ConfigManager } from '../src/config_manager.js';
|
|
7
|
+
import { createTest, createTestGroup } from '../src/create_test.js';
|
|
8
|
+
import { Suite, Runner, Emitter } from '../modules/core/main.js';
|
|
9
|
+
export class RunnerFactory {
|
|
10
|
+
#emitter = new Emitter();
|
|
11
|
+
#config;
|
|
12
|
+
#cliArgs;
|
|
13
|
+
#suites;
|
|
14
|
+
#file = fileURLToPath(import.meta.url);
|
|
15
|
+
get #refiner() {
|
|
16
|
+
return this.#config.refiner;
|
|
17
|
+
}
|
|
18
|
+
#createSuites() {
|
|
19
|
+
return [
|
|
20
|
+
new Suite('unit', this.#emitter, this.#refiner),
|
|
21
|
+
new Suite('functional', this.#emitter, this.#refiner),
|
|
22
|
+
];
|
|
23
|
+
}
|
|
24
|
+
#createAdditionTests(group) {
|
|
25
|
+
createTest('add two numbers', this.#emitter, this.#refiner, { group, file: this.#file }).run(() => {
|
|
26
|
+
assert.equal(2 + 2, 4);
|
|
27
|
+
});
|
|
28
|
+
createTest('add three numbers', this.#emitter, this.#refiner, {
|
|
29
|
+
group,
|
|
30
|
+
file: this.#file,
|
|
31
|
+
}).run(() => {
|
|
32
|
+
assert.equal(2 + 2 + 2, 6);
|
|
33
|
+
});
|
|
34
|
+
createTest('add group of numbers', this.#emitter, this.#refiner, { group, file: this.#file });
|
|
35
|
+
createTest('use math.js lib', this.#emitter, this.#refiner, { group, file: this.#file }).skip(true, 'Library work pending');
|
|
36
|
+
createTest('add multiple numbers', this.#emitter, this.#refiner, {
|
|
37
|
+
file: this.#file,
|
|
38
|
+
group,
|
|
39
|
+
}).run(() => {
|
|
40
|
+
assert.equal(2 + 2 + 2 + 2, 6);
|
|
41
|
+
});
|
|
42
|
+
createTest('add floating numbers', this.#emitter, this.#refiner, { group, file: this.#file })
|
|
43
|
+
.run(() => {
|
|
44
|
+
assert.equal(2 + 2.2 + 2.1, 6);
|
|
45
|
+
})
|
|
46
|
+
.fails('Have to add support for floating numbers');
|
|
47
|
+
}
|
|
48
|
+
#createUserStoreTests(group) {
|
|
49
|
+
createTest('Validate user data', this.#emitter, this.#refiner, {
|
|
50
|
+
group,
|
|
51
|
+
file: this.#file,
|
|
52
|
+
}).run(() => { });
|
|
53
|
+
createTest('Disallow duplicate emails', this.#emitter, this.#refiner, {
|
|
54
|
+
group,
|
|
55
|
+
file: this.#file,
|
|
56
|
+
}).run(() => { });
|
|
57
|
+
createTest('Disallow duplicate emails across tenants', this.#emitter, this.#refiner, {
|
|
58
|
+
group,
|
|
59
|
+
file: this.#file,
|
|
60
|
+
}).run(() => {
|
|
61
|
+
const users = ['', ''];
|
|
62
|
+
assert.equal(users.length, 1);
|
|
63
|
+
});
|
|
64
|
+
createTest('Normalize email before persisting it', this.#emitter, this.#refiner, {
|
|
65
|
+
group,
|
|
66
|
+
file: this.#file,
|
|
67
|
+
}).skip(true, 'Have to build a normalizer');
|
|
68
|
+
createTest('Send email verification mail', this.#emitter, this.#refiner, {
|
|
69
|
+
group,
|
|
70
|
+
file: this.#file,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
#createUnitTests(suite) {
|
|
74
|
+
const additionGroup = createTestGroup('Maths#add', this.#emitter, this.#refiner, {
|
|
75
|
+
suite,
|
|
76
|
+
file: this.#file,
|
|
77
|
+
});
|
|
78
|
+
this.#createAdditionTests(additionGroup);
|
|
79
|
+
createTest('A top level test inside a suite', this.#emitter, this.#refiner, {
|
|
80
|
+
suite,
|
|
81
|
+
file: this.#file,
|
|
82
|
+
}).run(() => { });
|
|
83
|
+
}
|
|
84
|
+
#createFunctionalTests(suite) {
|
|
85
|
+
const usersStoreGroup = createTestGroup('Users/store', this.#emitter, this.#refiner, {
|
|
86
|
+
suite,
|
|
87
|
+
file: this.#file,
|
|
88
|
+
});
|
|
89
|
+
this.#createUserStoreTests(usersStoreGroup);
|
|
90
|
+
const usersListGroup = createTestGroup('Users/list', this.#emitter, this.#refiner, {
|
|
91
|
+
suite,
|
|
92
|
+
file: this.#file,
|
|
93
|
+
});
|
|
94
|
+
usersListGroup.setup(() => {
|
|
95
|
+
throw new Error('Unable to cleanup database');
|
|
96
|
+
});
|
|
97
|
+
createTest('A test that will never because the group hooks fails', this.#emitter, this.#refiner, { group: usersListGroup });
|
|
98
|
+
createTest('A top level test inside functional suite', this.#emitter, this.#refiner, {
|
|
99
|
+
suite,
|
|
100
|
+
file: this.#file,
|
|
101
|
+
}).run(() => { });
|
|
102
|
+
}
|
|
103
|
+
async #registerPlugins(runner) {
|
|
104
|
+
for (let plugin of this.#config.plugins) {
|
|
105
|
+
await plugin({
|
|
106
|
+
config: this.#config,
|
|
107
|
+
runner,
|
|
108
|
+
emitter: this.#emitter,
|
|
109
|
+
cliArgs: this.#cliArgs,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
configure(config, argv) {
|
|
114
|
+
this.#cliArgs = new CliParser().parse(argv || []);
|
|
115
|
+
this.#config = new ConfigManager(config, this.#cliArgs).hydrate();
|
|
116
|
+
return this;
|
|
117
|
+
}
|
|
118
|
+
withSuites(suites) {
|
|
119
|
+
this.#suites = suites;
|
|
120
|
+
return this;
|
|
121
|
+
}
|
|
122
|
+
useEmitter(emitter) {
|
|
123
|
+
this.#emitter = emitter;
|
|
124
|
+
return this;
|
|
125
|
+
}
|
|
126
|
+
async run() {
|
|
127
|
+
const runner = new Runner(this.#emitter);
|
|
128
|
+
await this.#registerPlugins(runner);
|
|
129
|
+
const { config, reporters, refinerFilters } = await new Planner(this.#config).plan();
|
|
130
|
+
const globalHooks = new GlobalHooks();
|
|
131
|
+
globalHooks.apply(config);
|
|
132
|
+
reporters.forEach((reporter) => {
|
|
133
|
+
runner.registerReporter(reporter);
|
|
134
|
+
});
|
|
135
|
+
refinerFilters.forEach((filter) => {
|
|
136
|
+
config.refiner.add(filter.layer, filter.filters);
|
|
137
|
+
});
|
|
138
|
+
if (this.#suites) {
|
|
139
|
+
this.#suites.forEach((suite) => runner.add(suite));
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const [unit, functional] = this.#createSuites();
|
|
143
|
+
this.#createUnitTests(unit);
|
|
144
|
+
runner.add(unit);
|
|
145
|
+
this.#createFunctionalTests(functional);
|
|
146
|
+
runner.add(functional);
|
|
147
|
+
}
|
|
148
|
+
await globalHooks.setup(runner);
|
|
149
|
+
await runner.start();
|
|
150
|
+
await runner.exec();
|
|
151
|
+
await runner.end();
|
|
152
|
+
await globalHooks.teardown(null, runner);
|
|
153
|
+
return runner.getSummary();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Emitter, Refiner, Test as BaseTest, Suite as BaseSuite, Group as BaseGroup, Runner as BaseRunner, TestContext as BaseTestContext } from '@japa/core';
|
|
2
|
+
import { BaseReporter } from './reporters/base.js';
|
|
3
|
+
import type { DataSetNode, TestHooksCleanupHandler } from './types.js';
|
|
4
|
+
declare module '@japa/core' {
|
|
5
|
+
interface Test<Context extends Record<any, any>, TestData extends DataSetNode = undefined> {
|
|
6
|
+
throws(message: string | RegExp, errorConstructor?: any): this;
|
|
7
|
+
}
|
|
8
|
+
interface TestContext {
|
|
9
|
+
cleanup: (cleanupCallback: TestHooksCleanupHandler<TestContext>) => void;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export { Emitter, Refiner, BaseReporter };
|
|
13
|
+
export declare class TestContext extends BaseTestContext {
|
|
14
|
+
test: Test;
|
|
15
|
+
cleanup: (cleanupCallback: TestHooksCleanupHandler<TestContext>) => void;
|
|
16
|
+
constructor(test: Test);
|
|
17
|
+
}
|
|
18
|
+
export declare class Test<TestData extends DataSetNode = undefined> extends BaseTest<TestContext, TestData> {
|
|
19
|
+
static executedCallbacks: never[];
|
|
20
|
+
static executingCallbacks: never[];
|
|
21
|
+
throws(message: string | RegExp, errorConstructor?: any): this;
|
|
22
|
+
}
|
|
23
|
+
export declare class Group extends BaseGroup<TestContext> {
|
|
24
|
+
}
|
|
25
|
+
export declare class Suite extends BaseSuite<TestContext> {
|
|
26
|
+
}
|
|
27
|
+
export declare class Runner extends BaseRunner<TestContext> {
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=main.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../modules/core/main.ts"],"names":[],"mappings":"AASA,OAAO,EACL,OAAO,EACP,OAAO,EACP,IAAI,IAAI,QAAQ,EAChB,KAAK,IAAI,SAAS,EAClB,KAAK,IAAI,SAAS,EAClB,MAAM,IAAI,UAAU,EACpB,WAAW,IAAI,eAAe,EAC/B,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAEtE,OAAO,QAAQ,YAAY,CAAC;IAC1B,UAAU,IAAI,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,QAAQ,SAAS,WAAW,GAAG,SAAS;QACvF,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,gBAAgB,CAAC,EAAE,GAAG,GAAG,IAAI,CAAA;KAC/D;IACD,UAAU,WAAW;QACnB,OAAO,EAAE,CAAC,eAAe,EAAE,uBAAuB,CAAC,WAAW,CAAC,KAAK,IAAI,CAAA;KACzE;CACF;AAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,CAAA;AAKzC,qBAAa,WAAY,SAAQ,eAAe;IAO3B,IAAI,EAAE,IAAI;IAFrB,OAAO,EAAE,CAAC,eAAe,EAAE,uBAAuB,CAAC,WAAW,CAAC,KAAK,IAAI,CAAA;gBAE7D,IAAI,EAAE,IAAI;CAM9B;AAMD,qBAAa,IAAI,CAAC,QAAQ,SAAS,WAAW,GAAG,SAAS,CAAE,SAAQ,QAAQ,CAC1E,WAAW,EACX,QAAQ,CACT;IAIC,MAAM,CAAC,iBAAiB,UAAK;IAK7B,MAAM,CAAC,kBAAkB,UAAK;IAO9B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,gBAAgB,CAAC,EAAE,GAAG;CAgExD;AAMD,qBAAa,KAAM,SAAQ,SAAS,CAAC,WAAW,CAAC;CAAG;AAOpD,qBAAa,KAAM,SAAQ,SAAS,CAAC,WAAW,CAAC;CAAG;AAKpD,qBAAa,MAAO,SAAQ,UAAU,CAAC,WAAW,CAAC;CAAG"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Emitter, Refiner, Test as BaseTest, Suite as BaseSuite, Group as BaseGroup, Runner as BaseRunner, TestContext as BaseTestContext, } from '@japa/core';
|
|
2
|
+
import { inspect } from 'node:util';
|
|
3
|
+
import { AssertionError } from 'node:assert';
|
|
4
|
+
import { BaseReporter } from './reporters/base.js';
|
|
5
|
+
export { Emitter, Refiner, BaseReporter };
|
|
6
|
+
export class TestContext extends BaseTestContext {
|
|
7
|
+
test;
|
|
8
|
+
constructor(test) {
|
|
9
|
+
super();
|
|
10
|
+
this.test = test;
|
|
11
|
+
this.cleanup = (cleanupCallback) => {
|
|
12
|
+
test.cleanup(cleanupCallback);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class Test extends BaseTest {
|
|
17
|
+
static executedCallbacks = [];
|
|
18
|
+
static executingCallbacks = [];
|
|
19
|
+
throws(message, errorConstructor) {
|
|
20
|
+
const errorInPoint = new AssertionError({});
|
|
21
|
+
const existingExecutor = this.options.executor;
|
|
22
|
+
if (!existingExecutor) {
|
|
23
|
+
throw new Error('Cannot use "test.throws" method without a test callback');
|
|
24
|
+
}
|
|
25
|
+
this.options.executor = async (...args) => {
|
|
26
|
+
let raisedException;
|
|
27
|
+
try {
|
|
28
|
+
await existingExecutor(...args);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
raisedException = error;
|
|
32
|
+
}
|
|
33
|
+
if (!raisedException) {
|
|
34
|
+
errorInPoint.message = 'Expected test to throw an exception';
|
|
35
|
+
throw errorInPoint;
|
|
36
|
+
}
|
|
37
|
+
if (errorConstructor && !(raisedException instanceof errorConstructor)) {
|
|
38
|
+
errorInPoint.message = `Expected test to throw "${inspect(errorConstructor)}"`;
|
|
39
|
+
throw errorInPoint;
|
|
40
|
+
}
|
|
41
|
+
const exceptionMessage = raisedException.message;
|
|
42
|
+
if (!exceptionMessage || typeof exceptionMessage !== 'string') {
|
|
43
|
+
errorInPoint.message = 'Expected test to throw an exception with message property';
|
|
44
|
+
throw errorInPoint;
|
|
45
|
+
}
|
|
46
|
+
if (typeof message === 'string') {
|
|
47
|
+
if (exceptionMessage !== message) {
|
|
48
|
+
errorInPoint.message = `Expected test to throw "${message}". Instead received "${raisedException.message}"`;
|
|
49
|
+
errorInPoint.actual = raisedException.message;
|
|
50
|
+
errorInPoint.expected = message;
|
|
51
|
+
throw errorInPoint;
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (!message.test(exceptionMessage)) {
|
|
56
|
+
errorInPoint.message = `Expected test error to match "${message}" regular expression`;
|
|
57
|
+
throw errorInPoint;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export class Group extends BaseGroup {
|
|
64
|
+
}
|
|
65
|
+
export class Suite extends BaseSuite {
|
|
66
|
+
}
|
|
67
|
+
export class Runner extends BaseRunner {
|
|
68
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { TestEndNode, SuiteEndNode, GroupEndNode, TestStartNode, RunnerSummary, RunnerEndNode, GroupStartNode, SuiteStartNode, RunnerStartNode, BaseReporterOptions } from '../types.js';
|
|
2
|
+
import { Emitter, Runner } from '../main.js';
|
|
3
|
+
export declare abstract class BaseReporter {
|
|
4
|
+
#private;
|
|
5
|
+
runner?: Runner;
|
|
6
|
+
currentFileName?: string;
|
|
7
|
+
currentSuiteName?: string;
|
|
8
|
+
currentGroupName?: string;
|
|
9
|
+
constructor(options?: BaseReporterOptions);
|
|
10
|
+
protected onTestStart(_: TestStartNode): void;
|
|
11
|
+
protected onTestEnd(_: TestEndNode): void;
|
|
12
|
+
protected onGroupStart(_: GroupStartNode): void;
|
|
13
|
+
protected onGroupEnd(_: GroupEndNode): void;
|
|
14
|
+
protected onSuiteStart(_: SuiteStartNode): void;
|
|
15
|
+
protected onSuiteEnd(_: SuiteEndNode): void;
|
|
16
|
+
protected start(_: RunnerStartNode): Promise<void>;
|
|
17
|
+
protected end(_: RunnerEndNode): Promise<void>;
|
|
18
|
+
protected printSummary(summary: RunnerSummary): Promise<void>;
|
|
19
|
+
boot(runner: Runner, emitter: Emitter): void;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../modules/core/reporters/base.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,eAAe,EACf,mBAAmB,EACpB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAO5C,8BAAsB,YAAY;;IAEhC,MAAM,CAAC,EAAE,MAAM,CAAA;IAKf,eAAe,CAAC,EAAE,MAAM,CAAA;IAKxB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAKzB,gBAAgB,CAAC,EAAE,MAAM,CAAA;gBAEb,OAAO,GAAE,mBAAwB;IAsG7C,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI;IAC7C,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,WAAW;IAElC,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,cAAc;IACxC,SAAS,CAAC,UAAU,CAAC,CAAC,EAAE,YAAY;IAEpC,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,cAAc;IACxC,SAAS,CAAC,UAAU,CAAC,CAAC,EAAE,YAAY;cAEpB,KAAK,CAAC,CAAC,EAAE,eAAe;cACxB,GAAG,CAAC,CAAC,EAAE,aAAa;cAKpB,YAAY,CAAC,OAAO,EAAE,aAAa;IAqBnD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;CAyCtC"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import ms from 'ms';
|
|
2
|
+
import colors from '@poppinss/colors';
|
|
3
|
+
import { ErrorsPrinter } from '@japa/errors-printer';
|
|
4
|
+
const ansi = colors.ansi();
|
|
5
|
+
export class BaseReporter {
|
|
6
|
+
#options;
|
|
7
|
+
runner;
|
|
8
|
+
currentFileName;
|
|
9
|
+
currentSuiteName;
|
|
10
|
+
currentGroupName;
|
|
11
|
+
constructor(options = {}) {
|
|
12
|
+
this.#options = Object.assign({ stackLinesCount: 2 }, options);
|
|
13
|
+
}
|
|
14
|
+
#printAggregates(summary) {
|
|
15
|
+
const tests = [];
|
|
16
|
+
if (summary.aggregates.passed) {
|
|
17
|
+
tests.push(ansi.green(`${summary.aggregates.passed} passed`));
|
|
18
|
+
}
|
|
19
|
+
if (summary.aggregates.failed) {
|
|
20
|
+
tests.push(ansi.red(`${summary.aggregates.failed} failed`));
|
|
21
|
+
}
|
|
22
|
+
if (summary.aggregates.todo) {
|
|
23
|
+
tests.push(ansi.cyan(`${summary.aggregates.todo} todo`));
|
|
24
|
+
}
|
|
25
|
+
if (summary.aggregates.skipped) {
|
|
26
|
+
tests.push(ansi.yellow(`${summary.aggregates.skipped} skipped`));
|
|
27
|
+
}
|
|
28
|
+
if (summary.aggregates.regression) {
|
|
29
|
+
tests.push(ansi.magenta(`${summary.aggregates.regression} regression`));
|
|
30
|
+
}
|
|
31
|
+
this.runner.summaryBuilder.use(() => {
|
|
32
|
+
return [
|
|
33
|
+
{
|
|
34
|
+
key: ansi.dim('Tests'),
|
|
35
|
+
value: `${tests.join(', ')} ${ansi.dim(`(${summary.aggregates.total})`)}`,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
key: ansi.dim('Time'),
|
|
39
|
+
value: ansi.dim(ms(summary.duration)),
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
});
|
|
43
|
+
console.log(this.runner.summaryBuilder.build().join('\n'));
|
|
44
|
+
}
|
|
45
|
+
#aggregateErrors(summary) {
|
|
46
|
+
const errorsList = [];
|
|
47
|
+
summary.failureTree.forEach((suite) => {
|
|
48
|
+
suite.errors.forEach((error) => errorsList.push({ title: suite.name, ...error }));
|
|
49
|
+
suite.children.forEach((testOrGroup) => {
|
|
50
|
+
if (testOrGroup.type === 'test') {
|
|
51
|
+
testOrGroup.errors.forEach((error) => {
|
|
52
|
+
errorsList.push({ title: `${suite.name} / ${testOrGroup.title}`, ...error });
|
|
53
|
+
});
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
testOrGroup.errors.forEach((error) => {
|
|
57
|
+
errorsList.push({ title: testOrGroup.name, ...error });
|
|
58
|
+
});
|
|
59
|
+
testOrGroup.children.forEach((test) => {
|
|
60
|
+
test.errors.forEach((error) => {
|
|
61
|
+
errorsList.push({ title: `${testOrGroup.name} / ${test.title}`, ...error });
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
return errorsList;
|
|
67
|
+
}
|
|
68
|
+
async #printErrors(summary) {
|
|
69
|
+
if (!summary.failureTree.length) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const errorPrinter = new ErrorsPrinter({
|
|
73
|
+
stackLinesCount: this.#options.stackLinesCount,
|
|
74
|
+
framesMaxLimit: this.#options.framesMaxLimit,
|
|
75
|
+
});
|
|
76
|
+
errorPrinter.printSectionHeader('ERRORS');
|
|
77
|
+
await errorPrinter.printErrors(this.#aggregateErrors(summary));
|
|
78
|
+
}
|
|
79
|
+
onTestStart(_) { }
|
|
80
|
+
onTestEnd(_) { }
|
|
81
|
+
onGroupStart(_) { }
|
|
82
|
+
onGroupEnd(_) { }
|
|
83
|
+
onSuiteStart(_) { }
|
|
84
|
+
onSuiteEnd(_) { }
|
|
85
|
+
async start(_) { }
|
|
86
|
+
async end(_) { }
|
|
87
|
+
async printSummary(summary) {
|
|
88
|
+
await this.#printErrors(summary);
|
|
89
|
+
console.log('');
|
|
90
|
+
if (summary.aggregates.total === 0 && !summary.hasError) {
|
|
91
|
+
console.log(ansi.bgYellow().black(' NO TESTS EXECUTED '));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (summary.hasError) {
|
|
95
|
+
console.log(ansi.bgRed().black(' FAILED '));
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
console.log(ansi.bgGreen().black(' PASSED '));
|
|
99
|
+
}
|
|
100
|
+
console.log('');
|
|
101
|
+
this.#printAggregates(summary);
|
|
102
|
+
}
|
|
103
|
+
boot(runner, emitter) {
|
|
104
|
+
this.runner = runner;
|
|
105
|
+
emitter.on('test:start', (payload) => {
|
|
106
|
+
this.currentFileName = payload.meta.fileName;
|
|
107
|
+
this.onTestStart(payload);
|
|
108
|
+
});
|
|
109
|
+
emitter.on('test:end', (payload) => {
|
|
110
|
+
this.onTestEnd(payload);
|
|
111
|
+
});
|
|
112
|
+
emitter.on('group:start', (payload) => {
|
|
113
|
+
this.currentGroupName = payload.title;
|
|
114
|
+
this.currentFileName = payload.meta.fileName;
|
|
115
|
+
this.onGroupStart(payload);
|
|
116
|
+
});
|
|
117
|
+
emitter.on('group:end', (payload) => {
|
|
118
|
+
this.currentGroupName = undefined;
|
|
119
|
+
this.onGroupEnd(payload);
|
|
120
|
+
});
|
|
121
|
+
emitter.on('suite:start', (payload) => {
|
|
122
|
+
this.currentSuiteName = payload.name;
|
|
123
|
+
this.onSuiteStart(payload);
|
|
124
|
+
});
|
|
125
|
+
emitter.on('suite:end', (payload) => {
|
|
126
|
+
this.currentSuiteName = undefined;
|
|
127
|
+
this.onSuiteEnd(payload);
|
|
128
|
+
});
|
|
129
|
+
emitter.on('runner:start', async (payload) => {
|
|
130
|
+
await this.start(payload);
|
|
131
|
+
});
|
|
132
|
+
emitter.on('runner:end', async (payload) => {
|
|
133
|
+
await this.end(payload);
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../modules/core/types.ts"],"names":[],"mappings":"AASA,cAAc,kBAAkB,CAAA;AAEhC,MAAM,MAAM,mBAAmB,GAAG;IAChC,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@japa/core/types';
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@japa/runner",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-1",
|
|
4
4
|
"description": "Runner for Japa testing framework",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
8
|
+
"build/factories",
|
|
9
|
+
"build/modules",
|
|
8
10
|
"build/src",
|
|
9
11
|
"build/index.d.ts",
|
|
10
12
|
"build/index.js"
|