@japa/runner 1.1.3 → 2.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/index.d.ts CHANGED
@@ -1,17 +1,17 @@
1
- import { TestExecutor } from '@japa/core';
1
+ import { TestExecutor, ReporterContract } from '@japa/core';
2
2
  import { Test, TestContext, Group } from './src/Core';
3
- import { PluginFn, ConfigureOptions, RunnerHooksHandler, RunnerHooksCleanupHandler } from './src/Contracts';
4
- export { Test, TestContext, Group, PluginFn, RunnerHooksCleanupHandler, RunnerHooksHandler };
3
+ import { Config, PluginFn, RunnerHooksHandler, RunnerHooksCleanupHandler } from './src/Contracts';
4
+ export { Test, Config, Group, PluginFn, TestContext, ReporterContract, RunnerHooksHandler, RunnerHooksCleanupHandler, };
5
5
  /**
6
6
  * Configure the tests runner
7
7
  */
8
- export declare function configure(options: ConfigureOptions): void;
8
+ export declare function configure(options: Config): void;
9
9
  /**
10
10
  * Add a new test
11
11
  */
12
- export declare function test(title: string, callback?: TestExecutor<TestContext, undefined>): Test<TestContext, undefined>;
12
+ export declare function test(title: string, callback?: TestExecutor<TestContext, undefined>): Test<undefined>;
13
13
  export declare namespace test {
14
- var group: (title: string, callback: (group: Group<TestContext>) => void) => void;
14
+ var group: (title: string, callback: (group: Group) => void) => void;
15
15
  }
16
16
  /**
17
17
  * Run japa tests
@@ -29,4 +29,4 @@ export declare function run(): Promise<void>;
29
29
  * * --force-exit=Enable/disable force exit
30
30
  * * --timeout=Define timeout for all the tests
31
31
  */
32
- export declare function processCliArgs(argv: string[]): Partial<ConfigureOptions>;
32
+ export declare function processCliArgs(argv: string[]): Partial<Config>;
package/build/index.js CHANGED
@@ -11,7 +11,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
11
11
  return (mod && mod.__esModule) ? mod : { "default": mod };
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.processCliArgs = exports.run = exports.test = exports.configure = exports.Group = exports.TestContext = exports.Test = void 0;
14
+ exports.processCliArgs = exports.run = exports.test = exports.configure = exports.TestContext = exports.Group = exports.Test = void 0;
15
15
  const getopts_1 = __importDefault(require("getopts"));
16
16
  const path_1 = require("path");
17
17
  const fast_glob_1 = __importDefault(require("fast-glob"));
@@ -32,6 +32,11 @@ const refinerFilteringLayers = ['tests', 'groups', 'tags'];
32
32
  * test and the group both
33
33
  */
34
34
  let recentlyImportedFile;
35
+ /**
36
+ * Global timeout for tests. Fetched from runner options or suites
37
+ * options
38
+ */
39
+ let globalTimeout;
35
40
  /**
36
41
  * Function to create the test context for the test
37
42
  */
@@ -41,9 +46,9 @@ const getContext = (testInstance) => new Core_1.TestContext(testInstance);
41
46
  */
42
47
  const emitter = new core_1.Emitter();
43
48
  /**
44
- * The default suite for registering tests
49
+ * Active suite for tests
45
50
  */
46
- const suite = new core_1.Suite('default', emitter);
51
+ let activeSuite = new Core_1.Suite('default', emitter);
47
52
  /**
48
53
  * Currently active group
49
54
  */
@@ -60,6 +65,23 @@ function ensureIsConfigured(message) {
60
65
  throw new Error(message);
61
66
  }
62
67
  }
68
+ /**
69
+ * Validate suites filter to ensure a wrong suite is not
70
+ * mentioned
71
+ */
72
+ function validateSuitesFilter() {
73
+ if (!('suites' in runnerOptions)) {
74
+ return;
75
+ }
76
+ if (!runnerOptions.filters.suites || !runnerOptions.filters.suites.length) {
77
+ return;
78
+ }
79
+ const suites = runnerOptions.suites.map(({ name }) => name);
80
+ const invalidSuites = runnerOptions.filters.suites.filter((suite) => !suites.includes(suite));
81
+ if (invalidSuites.length) {
82
+ throw new Error(`Unrecognized suite "${invalidSuites[0]}". Make sure to define it in the config first`);
83
+ }
84
+ }
63
85
  /**
64
86
  * End tests. We wait for the "beforeExit" event when
65
87
  * forceExit is not set to true
@@ -100,12 +122,23 @@ function isFileAllowed(filePath, filters) {
100
122
  return filePath.replace((0, path_1.extname)(filePath), '').endsWith(matcher);
101
123
  });
102
124
  }
125
+ /**
126
+ * Returns "true" when no filters are applied or the name is part
127
+ * of the applied filter
128
+ */
129
+ function isSuiteAllowed(name, filters) {
130
+ if (!filters || !filters.length) {
131
+ return true;
132
+ }
133
+ return filters.includes(name);
134
+ }
103
135
  /**
104
136
  * Configure the tests runner
105
137
  */
106
138
  function configure(options) {
107
139
  const defaultOptions = {
108
140
  files: [],
141
+ suites: [],
109
142
  plugins: [],
110
143
  reporters: [],
111
144
  timeout: 2000,
@@ -115,6 +148,7 @@ function configure(options) {
115
148
  importer: (filePath) => (0, inclusion_1.default)(filePath),
116
149
  refiner: new core_1.Refiner({}),
117
150
  forceExit: false,
151
+ configureSuite: () => { },
118
152
  };
119
153
  runnerOptions = Object.assign(defaultOptions, options);
120
154
  }
@@ -132,8 +166,8 @@ function test(title, callback) {
132
166
  /**
133
167
  * Define timeout on the test when exists globally
134
168
  */
135
- if (runnerOptions.timeout !== undefined) {
136
- testInstance.timeout(runnerOptions.timeout);
169
+ if (globalTimeout !== undefined) {
170
+ testInstance.timeout(globalTimeout);
137
171
  }
138
172
  /**
139
173
  * Define test executor function
@@ -148,7 +182,7 @@ function test(title, callback) {
148
182
  activeGroup.add(testInstance);
149
183
  }
150
184
  else {
151
- suite.add(testInstance);
185
+ activeSuite.add(testInstance);
152
186
  }
153
187
  return testInstance;
154
188
  }
@@ -173,15 +207,46 @@ test.group = function (title, callback) {
173
207
  /**
174
208
  * Add group to the default suite
175
209
  */
176
- suite.add(activeGroup);
210
+ activeSuite.add(activeGroup);
177
211
  activeGroup = undefined;
178
212
  };
213
+ /**
214
+ * Collect files using the files collector function or by processing
215
+ * the glob pattern
216
+ */
217
+ async function collectFiles(files) {
218
+ if (Array.isArray(files) || typeof files === 'string') {
219
+ return await (0, fast_glob_1.default)(files, { absolute: true, onlyFiles: true });
220
+ }
221
+ else if (typeof files === 'function') {
222
+ return await files();
223
+ }
224
+ throw new Error('Invalid value for "files" property. Expected a string, array or a function');
225
+ }
226
+ /**
227
+ * Import test files using the configured importer. Also
228
+ * filter files using the file filter. (if mentioned).
229
+ */
230
+ async function importFiles(files) {
231
+ for (let file of files) {
232
+ recentlyImportedFile = file;
233
+ if (runnerOptions.filters.files && runnerOptions.filters.files.length) {
234
+ if (isFileAllowed(file, runnerOptions.filters.files)) {
235
+ await runnerOptions.importer(file);
236
+ }
237
+ }
238
+ else {
239
+ await runnerOptions.importer(file);
240
+ }
241
+ }
242
+ }
179
243
  /**
180
244
  * Run japa tests
181
245
  */
182
246
  async function run() {
183
- const runner = new core_1.Runner(emitter);
184
- runner.add(suite).manageUnHandledExceptions();
247
+ const runner = new Core_1.Runner(emitter);
248
+ runner.manageUnHandledExceptions();
249
+ runner.onSuite(runnerOptions.configureSuite);
185
250
  const hooks = new hooks_1.Hooks();
186
251
  let setupRunner;
187
252
  let teardownRunner;
@@ -196,6 +261,7 @@ async function run() {
196
261
  for (let plugin of runnerOptions.plugins) {
197
262
  await plugin(runnerOptions, runner, { Test: Core_1.Test, TestContext: Core_1.TestContext, Group: Core_1.Group });
198
263
  }
264
+ validateSuitesFilter();
199
265
  /**
200
266
  * Step 2: Notify runner about reporters
201
267
  */
@@ -216,28 +282,34 @@ async function run() {
216
282
  */
217
283
  await setupRunner.run(runner);
218
284
  /**
219
- * Step 4: Collect all test files
285
+ * Step 4: Entertain files property and import test files
286
+ * as part of the default suite
220
287
  */
221
- let files = [];
222
- if (Array.isArray(runnerOptions.files)) {
223
- files = await (0, fast_glob_1.default)(runnerOptions.files, { absolute: true, onlyFiles: true });
224
- }
225
- else if (typeof runnerOptions.files === 'function') {
226
- files = await runnerOptions.files();
288
+ if ('files' in runnerOptions && runnerOptions.files.length) {
289
+ globalTimeout = runnerOptions.timeout;
290
+ const files = await collectFiles(runnerOptions.files);
291
+ runner.add(activeSuite);
292
+ await importFiles(files);
227
293
  }
228
294
  /**
229
- * Step 5: Import files
295
+ * Step 5: Entertain suites property and import test files
296
+ * for the filtered suites.
230
297
  */
231
- for (let file of files) {
232
- recentlyImportedFile = file;
233
- if (runnerOptions.filters.files && runnerOptions.filters.files.length) {
234
- if (isFileAllowed(file, runnerOptions.filters.files)) {
235
- await runnerOptions.importer(file);
298
+ if ('suites' in runnerOptions) {
299
+ for (let suite of runnerOptions.suites) {
300
+ if (isSuiteAllowed(suite.name, runnerOptions.filters.suites)) {
301
+ if (suite.timeout !== undefined) {
302
+ globalTimeout = suite.timeout;
303
+ }
304
+ else {
305
+ globalTimeout = runnerOptions.timeout;
306
+ }
307
+ activeSuite = new Core_1.Suite(suite.name, emitter);
308
+ const files = await collectFiles(suite.files);
309
+ runner.add(activeSuite);
310
+ await importFiles(files);
236
311
  }
237
312
  }
238
- else {
239
- await runnerOptions.importer(file);
240
- }
241
313
  }
242
314
  /**
243
315
  * Step 6: Add filters to the refiner
@@ -322,12 +394,24 @@ function processCliArgs(argv) {
322
394
  processAsString(parsed, 'groups', (groups) => (config.filters.groups = groups));
323
395
  processAsString(parsed, 'tests', (tests) => (config.filters.tests = tests));
324
396
  processAsString(parsed, 'files', (files) => (config.filters.files = files));
397
+ /**
398
+ * Get suites
399
+ */
400
+ if (parsed._.length) {
401
+ processAsString({ suites: parsed._ }, 'suites', (suites) => (config.filters.suites = suites));
402
+ }
403
+ /**
404
+ * Get timeout
405
+ */
325
406
  if (parsed.timeout) {
326
407
  const value = Number(parsed.timeout);
327
408
  if (!isNaN(value)) {
328
409
  config.timeout = value;
329
410
  }
330
411
  }
412
+ /**
413
+ * Get forceExit
414
+ */
331
415
  if (parsed.forceExit) {
332
416
  config.forceExit = true;
333
417
  }
@@ -1,39 +1,57 @@
1
- import { Runner, Refiner, FilteringOptions, ReporterContract } from '@japa/core';
2
- import { Test, Group, TestContext } from '../Core';
1
+ import { Refiner, FilteringOptions, ReporterContract } from '@japa/core';
2
+ import { Test, Group, TestContext, Runner, Suite } from '../Core';
3
3
  /**
4
4
  * The cleanup function for runner hooks
5
5
  */
6
- export declare type RunnerHooksCleanupHandler = (error: null | any, runner: Runner<TestContext>) => Promise<any> | any;
6
+ export declare type RunnerHooksCleanupHandler = (error: null | any, runner: Runner) => Promise<any> | any;
7
7
  /**
8
8
  * The function that can be registered as a runner hook
9
9
  */
10
- export declare type RunnerHooksHandler = (runner: Runner<TestContext>) => Promise<any> | any | RunnerHooksCleanupHandler | Promise<RunnerHooksCleanupHandler>;
10
+ export declare type RunnerHooksHandler = (runner: Runner) => Promise<any> | any | RunnerHooksCleanupHandler | Promise<RunnerHooksCleanupHandler>;
11
11
  /**
12
12
  * Allowed filters
13
13
  */
14
14
  export declare type Filters = FilteringOptions & {
15
15
  files?: string[];
16
+ suites?: string[];
16
17
  };
17
18
  /**
18
19
  * Shape of the plugin function
19
20
  */
20
- export declare type PluginFn = (config: Required<ConfigureOptions>, runner: Runner<TestContext>, classes: {
21
+ export declare type PluginFn = (config: Required<Config>, runner: Runner, classes: {
21
22
  Test: typeof Test;
22
23
  TestContext: typeof TestContext;
23
24
  Group: typeof Group;
24
25
  }) => void | Promise<void>;
25
26
  /**
26
- * Configuration options
27
+ * Runner hooks
27
28
  */
28
- export declare type ConfigureOptions = {
29
- files: string[] | (() => string[] | Promise<string[]>);
29
+ export declare type RunnerHooks = {
30
+ setup: RunnerHooksHandler[];
31
+ teardown: RunnerHooksHandler[];
32
+ };
33
+ /**
34
+ * Base configuration options
35
+ */
36
+ export declare type BaseConfig = {
30
37
  timeout?: number;
31
38
  plugins?: PluginFn[];
32
39
  filters?: Filters;
33
- setup?: RunnerHooksHandler[];
34
- teardown?: RunnerHooksHandler[];
40
+ configureSuite?: (suite: Suite) => void;
35
41
  reporters?: ReporterContract[];
36
42
  importer?: (filePath: string) => void | Promise<void>;
37
43
  refiner?: Refiner;
38
44
  forceExit?: boolean;
39
- };
45
+ } & Partial<RunnerHooks>;
46
+ /**
47
+ * Configuration options
48
+ */
49
+ export declare type Config = BaseConfig & ({
50
+ files: string[] | (() => string[] | Promise<string[]>);
51
+ } | {
52
+ suites: {
53
+ name: string;
54
+ files: string | string[] | (() => string[] | Promise<string[]>);
55
+ timeout?: number;
56
+ }[];
57
+ });
@@ -1,6 +1,14 @@
1
- import { Test, Group, TestContext as BaseTestContext } from '@japa/core';
1
+ import { DataSetNode, Test as BaseTest, Group as BaseGroup, Suite as BaseSuite, Runner as BaseRunner, TestContext as BaseTestContext } from '@japa/core';
2
2
  export declare class TestContext extends BaseTestContext {
3
- test: Test<TestContext, any>;
4
- constructor(test: Test<TestContext, any>);
3
+ test: Test;
4
+ constructor(test: Test);
5
+ }
6
+ export declare class Test<TestData extends DataSetNode = undefined> extends BaseTest<TestContext, TestData> {
7
+ static disposeCallbacks: never[];
8
+ }
9
+ export declare class Group extends BaseGroup<TestContext> {
10
+ }
11
+ export declare class Suite extends BaseSuite<TestContext> {
12
+ }
13
+ export declare class Runner extends BaseRunner<TestContext> {
5
14
  }
6
- export { Group, Test };
@@ -8,10 +8,8 @@
8
8
  * file that was distributed with this source code.
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.Test = exports.Group = exports.TestContext = void 0;
11
+ exports.Runner = exports.Suite = exports.Group = exports.Test = exports.TestContext = void 0;
12
12
  const core_1 = require("@japa/core");
13
- Object.defineProperty(exports, "Test", { enumerable: true, get: function () { return core_1.Test; } });
14
- Object.defineProperty(exports, "Group", { enumerable: true, get: function () { return core_1.Group; } });
15
13
  class TestContext extends core_1.TestContext {
16
14
  constructor(test) {
17
15
  super();
@@ -19,3 +17,16 @@ class TestContext extends core_1.TestContext {
19
17
  }
20
18
  }
21
19
  exports.TestContext = TestContext;
20
+ class Test extends core_1.Test {
21
+ }
22
+ exports.Test = Test;
23
+ Test.disposeCallbacks = [];
24
+ class Group extends core_1.Group {
25
+ }
26
+ exports.Group = Group;
27
+ class Suite extends core_1.Suite {
28
+ }
29
+ exports.Suite = Suite;
30
+ class Runner extends core_1.Runner {
31
+ }
32
+ exports.Runner = Runner;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@japa/runner",
3
- "version": "1.1.3",
3
+ "version": "2.0.1",
4
4
  "description": "Runner for Japa testing framework",
5
5
  "main": "build/index.js",
6
6
  "files": [
@@ -35,13 +35,13 @@
35
35
  "license": "MIT",
36
36
  "devDependencies": {
37
37
  "@adonisjs/mrm-preset": "^5.0.2",
38
- "@adonisjs/require-ts": "^2.0.9",
39
- "@types/node": "^17.0.18",
38
+ "@adonisjs/require-ts": "^2.0.10",
39
+ "@types/node": "^17.0.21",
40
40
  "commitizen": "^4.2.4",
41
41
  "cz-conventional-changelog": "^3.3.0",
42
42
  "del-cli": "^4.0.1",
43
- "eslint": "^8.9.0",
44
- "eslint-config-prettier": "^8.4.0",
43
+ "eslint": "^8.10.0",
44
+ "eslint-config-prettier": "^8.5.0",
45
45
  "eslint-plugin-adonis": "^2.1.0",
46
46
  "eslint-plugin-prettier": "^4.0.0",
47
47
  "github-label-sync": "^2.0.2",
@@ -50,7 +50,7 @@
50
50
  "mrm": "^3.0.10",
51
51
  "np": "^7.6.0",
52
52
  "prettier": "^2.5.1",
53
- "typescript": "^4.5.5"
53
+ "typescript": "^4.6.2"
54
54
  },
55
55
  "mrmConfig": {
56
56
  "core": false,
@@ -105,7 +105,7 @@
105
105
  "anyBranch": false
106
106
  },
107
107
  "dependencies": {
108
- "@japa/core": "^5.1.1",
108
+ "@japa/core": "^6.0.0",
109
109
  "@japa/errors-printer": "^1.3.3",
110
110
  "@poppinss/hooks": "^6.0.2-0",
111
111
  "fast-glob": "^3.2.11",