@adonisjs/assembler 5.4.2 → 5.5.2-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.
@@ -3,4 +3,5 @@ export declare const DEFAULT_BUILD_DIR = "build";
3
3
  export declare const RCFILE_NAME = ".adonisrc.json";
4
4
  export declare const ENV_FILES: string[];
5
5
  export declare const SERVER_ENTRY_FILE = "server.ts";
6
+ export declare const TESTS_ENTRY_FILE = "tests.ts";
6
7
  export declare const TSCONFIG_FILE_NAME = "tsconfig.json";
@@ -8,10 +8,11 @@
8
8
  * file that was distributed with this source code.
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.TSCONFIG_FILE_NAME = exports.SERVER_ENTRY_FILE = exports.ENV_FILES = exports.RCFILE_NAME = exports.DEFAULT_BUILD_DIR = exports.ACE_FILE_NAME = void 0;
11
+ exports.TSCONFIG_FILE_NAME = exports.TESTS_ENTRY_FILE = exports.SERVER_ENTRY_FILE = exports.ENV_FILES = exports.RCFILE_NAME = exports.DEFAULT_BUILD_DIR = exports.ACE_FILE_NAME = void 0;
12
12
  exports.ACE_FILE_NAME = 'ace';
13
13
  exports.DEFAULT_BUILD_DIR = 'build';
14
14
  exports.RCFILE_NAME = '.adonisrc.json';
15
15
  exports.ENV_FILES = ['.env', '.env.testing'];
16
16
  exports.SERVER_ENTRY_FILE = 'server.ts';
17
+ exports.TESTS_ENTRY_FILE = 'tests.ts';
17
18
  exports.TSCONFIG_FILE_NAME = 'tsconfig.json';
@@ -0,0 +1,8 @@
1
+ export declare type JapaFlags = Partial<{
2
+ '_': string[];
3
+ '--tags': string[];
4
+ '--ignore-tags': string[];
5
+ '--files': string[];
6
+ '--timeout': number;
7
+ '--force-exit': boolean;
8
+ }>;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /*
3
+ * @adonisjs/assembler
4
+ *
5
+ * (c) Harminder Virk <virk@adonisjs.com>
6
+ *
7
+ * For the full copyright and license information, please view the LICENSE
8
+ * file that was distributed with this source code.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -18,6 +18,10 @@ export declare class RcFile {
18
18
  * A matcher to know if a file is part of the meta files globs
19
19
  */
20
20
  isMetaFile: (filePath: string) => boolean;
21
+ /**
22
+ * A matcher to know if file is a test file or not
23
+ */
24
+ isTestsFile: (filePath: string) => boolean;
21
25
  /**
22
26
  * A matcher to know if a file is part of the restart server files globs
23
27
  */
@@ -47,6 +51,10 @@ export declare class RcFile {
47
51
  * to be copied
48
52
  */
49
53
  getMetaFilesGlob(): string[];
54
+ /**
55
+ * Returns an array of globs for the test files
56
+ */
57
+ getTestsFileGlob(): string[];
50
58
  /**
51
59
  * Reloads the rcfile.json
52
60
  */
@@ -59,5 +67,6 @@ export declare class RcFile {
59
67
  reload: boolean;
60
68
  rcFile: boolean;
61
69
  metaFile: boolean;
70
+ testFile: boolean;
62
71
  };
63
72
  }
@@ -39,6 +39,10 @@ class RcFile {
39
39
  * A matcher to know if a file is part of the meta files globs
40
40
  */
41
41
  this.isMetaFile = (0, picomatch_1.default)(this.getMetaFilesGlob());
42
+ /**
43
+ * A matcher to know if file is a test file or not
44
+ */
45
+ this.isTestsFile = (0, picomatch_1.default)(this.getTestsFileGlob());
42
46
  /**
43
47
  * A matcher to know if a file is part of the restart server files globs
44
48
  */
@@ -90,6 +94,17 @@ class RcFile {
90
94
  .map(({ pattern }) => pattern)
91
95
  .concat([paths_1.ACE_FILE_NAME]);
92
96
  }
97
+ /**
98
+ * Returns an array of globs for the test files
99
+ */
100
+ getTestsFileGlob() {
101
+ return this.application.rcFile.tests.suites.reduce((result, suite) => {
102
+ if (suite.files) {
103
+ result = result.concat(suite.files);
104
+ }
105
+ return result;
106
+ }, []);
107
+ }
93
108
  /**
94
109
  * Reloads the rcfile.json
95
110
  */
@@ -109,6 +124,7 @@ class RcFile {
109
124
  reload: true,
110
125
  rcFile: true,
111
126
  metaFile: true,
127
+ testFile: false,
112
128
  };
113
129
  }
114
130
  /**
@@ -119,6 +135,7 @@ class RcFile {
119
135
  reload: true,
120
136
  rcFile: false,
121
137
  metaFile: true,
138
+ testFile: false,
122
139
  };
123
140
  }
124
141
  /**
@@ -129,6 +146,18 @@ class RcFile {
129
146
  reload: false,
130
147
  rcFile: false,
131
148
  metaFile: true,
149
+ testFile: false,
150
+ };
151
+ }
152
+ /**
153
+ * File is part of one of the tests suite
154
+ */
155
+ if (this.isTestsFile(filePath)) {
156
+ return {
157
+ reload: false,
158
+ rcFile: false,
159
+ metaFile: false,
160
+ testFile: true,
132
161
  };
133
162
  }
134
163
  /**
@@ -138,6 +167,7 @@ class RcFile {
138
167
  reload: false,
139
168
  rcFile: false,
140
169
  metaFile: false,
170
+ testFile: false,
141
171
  };
142
172
  }
143
173
  }
@@ -0,0 +1,66 @@
1
+ import { logger as uiLogger } from '@poppinss/cliui';
2
+ import { JapaFlags } from '../Contracts';
3
+ /**
4
+ * Exposes the API to watch project for compilition changes and
5
+ * run/re-run tests
6
+ */
7
+ export declare class TestsServer {
8
+ private appRoot;
9
+ private filters;
10
+ private nodeArgs;
11
+ private logger;
12
+ /**
13
+ * A boolean to know if we are watching for filesystem
14
+ */
15
+ private watchingFileSystem;
16
+ /**
17
+ * Boolean to hold the current state of tests. This is avoid
18
+ * re-running the tests when one run is in progress
19
+ */
20
+ private busy;
21
+ /**
22
+ * Reference to the typescript compiler
23
+ */
24
+ private ts;
25
+ /**
26
+ * Reference to the RCFile
27
+ */
28
+ private rcFile;
29
+ /**
30
+ * Manifest instance to generate ace manifest file
31
+ */
32
+ private manifest;
33
+ /**
34
+ * Require-ts watch helpers
35
+ */
36
+ private watchHelpers;
37
+ /**
38
+ * A method to know if the file is part of the selected suites
39
+ * or not
40
+ */
41
+ private isTestSuiteFile;
42
+ /**
43
+ * Find if the test file part of the applied file filters
44
+ */
45
+ private isTestFile;
46
+ constructor(appRoot: string, filters: JapaFlags, nodeArgs?: string[], logger?: typeof uiLogger);
47
+ /**
48
+ * Returns the glob paths for test suites. Returns all if no
49
+ * filter is applied. Otherwise only the filtered suites
50
+ * are picked.
51
+ */
52
+ private getFilesForSelectedSuites;
53
+ /**
54
+ * Kill current process
55
+ */
56
+ private kill;
57
+ /**
58
+ * Run tests. Use [[watch]] to also watch for file
59
+ * changes
60
+ */
61
+ run(filePath?: string): Promise<void>;
62
+ /**
63
+ * Build and watch for file changes
64
+ */
65
+ watch(poll?: boolean): Promise<void>;
66
+ }
@@ -0,0 +1,317 @@
1
+ "use strict";
2
+ /*
3
+ * @adonisjs/assembler
4
+ *
5
+ * (c) Harminder Virk <virk@adonisjs.com>
6
+ *
7
+ * For the full copyright and license information, please view the LICENSE
8
+ * file that was distributed with this source code.
9
+ */
10
+ var __importDefault = (this && this.__importDefault) || function (mod) {
11
+ return (mod && mod.__esModule) ? mod : { "default": mod };
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.TestsServer = void 0;
15
+ const path_1 = require("path");
16
+ const picomatch_1 = __importDefault(require("picomatch"));
17
+ const cliui_1 = require("@poppinss/cliui");
18
+ const require_ts_1 = require("@adonisjs/require-ts");
19
+ const Ts_1 = require("../Ts");
20
+ const RcFile_1 = require("../RcFile");
21
+ const Manifest_1 = require("../Manifest");
22
+ const process_1 = require("./process");
23
+ const paths_1 = require("../../config/paths");
24
+ /**
25
+ * Exposes the API to watch project for compilition changes and
26
+ * run/re-run tests
27
+ */
28
+ class TestsServer {
29
+ constructor(appRoot, filters, nodeArgs = [], logger = cliui_1.logger) {
30
+ this.appRoot = appRoot;
31
+ this.filters = filters;
32
+ this.nodeArgs = nodeArgs;
33
+ this.logger = logger;
34
+ /**
35
+ * A boolean to know if we are watching for filesystem
36
+ */
37
+ this.watchingFileSystem = false;
38
+ /**
39
+ * Boolean to hold the current state of tests. This is avoid
40
+ * re-running the tests when one run is in progress
41
+ */
42
+ this.busy = false;
43
+ /**
44
+ * Reference to the typescript compiler
45
+ */
46
+ this.ts = new Ts_1.Ts(this.appRoot, this.logger);
47
+ /**
48
+ * Reference to the RCFile
49
+ */
50
+ this.rcFile = new RcFile_1.RcFile(this.appRoot);
51
+ /**
52
+ * Manifest instance to generate ace manifest file
53
+ */
54
+ this.manifest = new Manifest_1.Manifest(this.appRoot, this.logger);
55
+ /**
56
+ * Require-ts watch helpers
57
+ */
58
+ this.watchHelpers = (0, require_ts_1.getWatcherHelpers)(this.appRoot);
59
+ /**
60
+ * A method to know if the file is part of the selected suites
61
+ * or not
62
+ */
63
+ this.isTestSuiteFile = (0, picomatch_1.default)(this.getFilesForSelectedSuites());
64
+ /**
65
+ * Find if the test file part of the applied file filters
66
+ */
67
+ this.isTestFile = (filePath) => {
68
+ if (!this.filters['--files']) {
69
+ return true;
70
+ }
71
+ const fileName = filePath.replace((0, path_1.extname)(filePath), '');
72
+ return !!this.filters['--files'].find((filter) => {
73
+ if (filePath.endsWith(filter)) {
74
+ return true;
75
+ }
76
+ return fileName.endsWith(filter) || fileName.endsWith(`${filter}.spec`);
77
+ });
78
+ };
79
+ }
80
+ /**
81
+ * Returns the glob paths for test suites. Returns all if no
82
+ * filter is applied. Otherwise only the filtered suites
83
+ * are picked.
84
+ */
85
+ getFilesForSelectedSuites() {
86
+ return this.rcFile.application.rcFile.tests.suites.reduce((result, suite) => {
87
+ if (!suite.files) {
88
+ return result;
89
+ }
90
+ if (!this.filters['--suites'] || this.filters['--suites'].includes(suite.name)) {
91
+ result = result.concat(suite.files);
92
+ }
93
+ return result;
94
+ }, []);
95
+ }
96
+ /**
97
+ * Kill current process
98
+ */
99
+ kill() {
100
+ process.exit();
101
+ }
102
+ /**
103
+ * Run tests. Use [[watch]] to also watch for file
104
+ * changes
105
+ */
106
+ async run(filePath) {
107
+ if (this.busy) {
108
+ return;
109
+ }
110
+ const filters = { ...this.filters };
111
+ /**
112
+ * Overwrite files filter when a specific file path
113
+ * is mentioned
114
+ */
115
+ if (filePath) {
116
+ filters['--files'] = [filePath];
117
+ }
118
+ this.busy = true;
119
+ const { hasErrors } = await new process_1.TestProcess(paths_1.TESTS_ENTRY_FILE, this.appRoot, filters, this.nodeArgs, this.logger, {}).run();
120
+ this.busy = false;
121
+ if (!this.watchingFileSystem) {
122
+ if (hasErrors) {
123
+ process.exitCode = 1;
124
+ }
125
+ this.kill();
126
+ }
127
+ }
128
+ /**
129
+ * Build and watch for file changes
130
+ */
131
+ async watch(poll = false) {
132
+ this.watchingFileSystem = true;
133
+ /**
134
+ * Clear require-ts cache
135
+ */
136
+ this.watchHelpers.clear();
137
+ /**
138
+ * Run tests
139
+ */
140
+ await this.run();
141
+ /**
142
+ * Parse config to find the files excluded inside
143
+ * tsconfig file
144
+ */
145
+ const config = this.ts.parseConfig();
146
+ if (!config) {
147
+ this.logger.warning('Cannot start watcher because of errors in the tsconfig file');
148
+ return;
149
+ }
150
+ /**
151
+ * Stick file watcher
152
+ */
153
+ const watcher = this.ts.tsCompiler.watcher(config, 'raw');
154
+ /**
155
+ * Watcher is ready after first compile
156
+ */
157
+ watcher.on('watcher:ready', () => {
158
+ this.logger.info('watching file system for changes');
159
+ });
160
+ /**
161
+ * Source file removed
162
+ */
163
+ watcher.on('source:unlink', async ({ absPath, relativePath }) => {
164
+ this.watchHelpers.clear(absPath);
165
+ if (this.busy) {
166
+ return;
167
+ }
168
+ this.logger.action('delete').succeeded(relativePath);
169
+ /**
170
+ * Generate manifest when filePath is a commands path
171
+ */
172
+ if (this.rcFile.isCommandsPath(relativePath)) {
173
+ this.manifest.generate();
174
+ }
175
+ /**
176
+ * Run all tests when any of the source, except the
177
+ * test file changes
178
+ */
179
+ if (!this.rcFile.isTestsFile(relativePath)) {
180
+ await this.run();
181
+ }
182
+ });
183
+ /**
184
+ * Source file added
185
+ */
186
+ watcher.on('source:add', async ({ absPath, relativePath }) => {
187
+ this.watchHelpers.clear(absPath);
188
+ if (this.busy) {
189
+ return;
190
+ }
191
+ this.logger.action('add').succeeded(relativePath);
192
+ /**
193
+ * Run all tests when any of the source, except the
194
+ * test file changes
195
+ */
196
+ if (!this.rcFile.isTestsFile(relativePath)) {
197
+ await this.run();
198
+ return;
199
+ }
200
+ /**
201
+ * Run only the changed file if it part of the test
202
+ * suites (respecting filters)
203
+ */
204
+ if (this.isTestSuiteFile(relativePath) && this.isTestFile(relativePath)) {
205
+ await this.run(relativePath);
206
+ }
207
+ });
208
+ /**
209
+ * Source file changed
210
+ */
211
+ watcher.on('source:change', async ({ absPath, relativePath }) => {
212
+ this.watchHelpers.clear(absPath);
213
+ if (this.busy) {
214
+ return;
215
+ }
216
+ this.logger.action('update').succeeded(relativePath);
217
+ /**
218
+ * Generate manifest when filePath is a commands path
219
+ */
220
+ if (this.rcFile.isCommandsPath(relativePath)) {
221
+ this.manifest.generate();
222
+ }
223
+ /**
224
+ * Run all tests when any of the source, except the
225
+ * test file changes
226
+ */
227
+ if (!this.rcFile.isTestsFile(relativePath)) {
228
+ await this.run();
229
+ return;
230
+ }
231
+ /**
232
+ * Run only the changed file if it part of the test
233
+ * suites (respecting filters)
234
+ */
235
+ if (this.isTestSuiteFile(relativePath) && this.isTestFile(relativePath)) {
236
+ await this.run(relativePath);
237
+ }
238
+ });
239
+ /**
240
+ * New file added
241
+ */
242
+ watcher.on('add', async ({ relativePath }) => {
243
+ if (this.busy) {
244
+ return;
245
+ }
246
+ if (paths_1.ENV_FILES.includes(relativePath)) {
247
+ this.logger.action('create').succeeded(relativePath);
248
+ await this.run();
249
+ return;
250
+ }
251
+ const metaData = this.rcFile.getMetaData(relativePath);
252
+ if (!metaData.metaFile) {
253
+ return;
254
+ }
255
+ this.logger.action('create').succeeded(relativePath);
256
+ await this.run();
257
+ });
258
+ /**
259
+ * File changed
260
+ */
261
+ watcher.on('change', async ({ relativePath }) => {
262
+ if (this.busy) {
263
+ return;
264
+ }
265
+ if (paths_1.ENV_FILES.includes(relativePath)) {
266
+ this.logger.action('update').succeeded(relativePath);
267
+ await this.run();
268
+ return;
269
+ }
270
+ const metaData = this.rcFile.getMetaData(relativePath);
271
+ if (!metaData.metaFile) {
272
+ return;
273
+ }
274
+ this.logger.action('update').succeeded(relativePath);
275
+ await this.run();
276
+ });
277
+ /**
278
+ * File removed
279
+ */
280
+ watcher.on('unlink', async ({ relativePath }) => {
281
+ if (this.busy) {
282
+ return;
283
+ }
284
+ if (paths_1.ENV_FILES.includes(relativePath)) {
285
+ this.logger.action('delete').succeeded(relativePath);
286
+ await this.run();
287
+ return;
288
+ }
289
+ const metaData = this.rcFile.getMetaData(relativePath);
290
+ if (!metaData.metaFile) {
291
+ return;
292
+ }
293
+ if (metaData.rcFile) {
294
+ this.logger.info('cannot continue after deletion of .adonisrc.json file');
295
+ watcher.chokidar.close();
296
+ this.kill();
297
+ return;
298
+ }
299
+ this.logger.action('delete').succeeded(relativePath);
300
+ await this.run();
301
+ });
302
+ /**
303
+ * Start the watcher
304
+ */
305
+ watcher.watch(['.'], {
306
+ usePolling: poll,
307
+ });
308
+ /**
309
+ * Kill when watcher recieves an error
310
+ */
311
+ watcher.chokidar.on('error', (error) => {
312
+ this.logger.fatal(error);
313
+ this.kill();
314
+ });
315
+ }
316
+ }
317
+ exports.TestsServer = TestsServer;
@@ -0,0 +1,22 @@
1
+ import { logger as uiLogger } from '@poppinss/cliui';
2
+ import { JapaFlags } from '../Contracts';
3
+ /**
4
+ * Exposes the API to run tests as a child process.
5
+ */
6
+ export declare class TestProcess {
7
+ private sourceFile;
8
+ private projectRoot;
9
+ private filters;
10
+ private logger;
11
+ private env;
12
+ private nodeArgs;
13
+ constructor(sourceFile: string, projectRoot: string, filters: JapaFlags, nodeArgs: string[] | undefined, logger: typeof uiLogger, env?: {
14
+ [key: string]: string;
15
+ });
16
+ /**
17
+ * Start the HTTP server as a child process.
18
+ */
19
+ run(): Promise<{
20
+ hasErrors: boolean;
21
+ }>;
22
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ /*
3
+ * @adonisjs/assembler
4
+ *
5
+ * (c) Harminder Virk <virk@adonisjs.com>
6
+ *
7
+ * For the full copyright and license information, please view the LICENSE
8
+ * file that was distributed with this source code.
9
+ */
10
+ var __importDefault = (this && this.__importDefault) || function (mod) {
11
+ return (mod && mod.__esModule) ? mod : { "default": mod };
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.TestProcess = void 0;
15
+ const execa_1 = __importDefault(require("execa"));
16
+ /**
17
+ * Exposes the API to run tests as a child process.
18
+ */
19
+ class TestProcess {
20
+ constructor(sourceFile, projectRoot, filters, nodeArgs = [], logger, env = {}) {
21
+ this.sourceFile = sourceFile;
22
+ this.projectRoot = projectRoot;
23
+ this.filters = filters;
24
+ this.logger = logger;
25
+ this.env = env;
26
+ this.nodeArgs = nodeArgs.reduce((result, arg) => {
27
+ result = result.concat(arg.split(' '));
28
+ return result;
29
+ }, []);
30
+ }
31
+ /**
32
+ * Start the HTTP server as a child process.
33
+ */
34
+ async run() {
35
+ this.logger.info('running tests...');
36
+ const filters = Object.keys(this.filters).reduce((result, filter) => {
37
+ const value = this.filters[filter];
38
+ if (filter !== '_') {
39
+ result.push(filter);
40
+ }
41
+ if (Array.isArray(value)) {
42
+ result.push(...value);
43
+ }
44
+ else {
45
+ result.push(value);
46
+ }
47
+ return result;
48
+ }, []);
49
+ try {
50
+ await execa_1.default.node(this.sourceFile, filters, {
51
+ stdio: 'inherit',
52
+ cwd: this.projectRoot,
53
+ env: {
54
+ FORCE_COLOR: 'true',
55
+ ...this.env,
56
+ },
57
+ nodeOptions: ['-r', '@adonisjs/assembler/build/register'].concat(this.nodeArgs),
58
+ });
59
+ return { hasErrors: false };
60
+ }
61
+ catch {
62
+ return { hasErrors: true };
63
+ }
64
+ }
65
+ }
66
+ exports.TestProcess = TestProcess;
@@ -0,0 +1,45 @@
1
+ /*
2
+ |--------------------------------------------------------------------------
3
+ | Tests
4
+ |--------------------------------------------------------------------------
5
+ |
6
+ | The contents in this file boots the AdonisJS application and configures
7
+ | the Japa tests runner.
8
+ |
9
+ | For the most part you will never edit this file. The configuration
10
+ | for the tests can be controlled via ".adonisrc.json" and
11
+ | "tests/bootstrap.ts" files.
12
+ |
13
+ */
14
+
15
+ process.env.NODE_ENV = 'testing'
16
+
17
+ import 'reflect-metadata'
18
+ import sourceMapSupport from 'source-map-support'
19
+ import { Ignitor } from '@adonisjs/core/build/standalone'
20
+ import { configure, processCliArgs, run, RunnerHooksHandler } from '@japa/runner'
21
+
22
+ sourceMapSupport.install({ handleUncaughtExceptions: false })
23
+
24
+ const kernel = new Ignitor(__dirname).kernel('test')
25
+
26
+ kernel
27
+ .boot()
28
+ .then(() => import('./tests/bootstrap'))
29
+ .then(({ runnerHooks, ...config }) => {
30
+ const app: RunnerHooksHandler[] = [() => kernel.start()]
31
+
32
+ configure({
33
+ ...kernel.application.rcFile.tests,
34
+ ...processCliArgs(process.argv.slice(2)),
35
+ ...config,
36
+ ...{
37
+ importer: (filePath) => import(filePath),
38
+ setup: app.concat(runnerHooks.setup),
39
+ teardown: runnerHooks.teardown,
40
+ },
41
+ cwd: kernel.application.appRoot
42
+ })
43
+
44
+ run()
45
+ })
@@ -0,0 +1,5 @@
1
+ import { test } from '@japa/runner'
2
+
3
+ test.group('{{ name }}', () => {
4
+ // Write your test here
5
+ })
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Contract source: https://github.com/adonisjs/core/blob/master/templates/contracts/tests.txt
3
+ *
4
+ * Feel free to let us know via PR, if you find something broken in this contract
5
+ * file.
6
+ */
7
+
8
+ import '@japa/runner'
9
+
10
+ declare module '@japa/runner' {
11
+ interface TestContext {
12
+ // Extend context
13
+ }
14
+
15
+ interface Test<DataSet> {
16
+ // Extend test
17
+ }
18
+ }