diff --git a/docs/05-command-line.md b/docs/05-command-line.md index c46759e39..5e133f4e2 100644 --- a/docs/05-command-line.md +++ b/docs/05-command-line.md @@ -20,8 +20,9 @@ Positionals: Options: --version Show version number [boolean] --color Force color output [boolean] - --config JavaScript file for AVA to read its config from, - instead of using package.json or ava.config.js files + --config Specific JavaScript file for AVA to read its config + from, instead of using package.json or ava.config.* + files --help Show help [boolean] --concurrency, -c Max number of test files running at the same time (Default: CPU cores) [number] diff --git a/docs/06-configuration.md b/docs/06-configuration.md index cbce09db3..6442ecf71 100644 --- a/docs/06-configuration.md +++ b/docs/06-configuration.md @@ -4,7 +4,7 @@ Translations: [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/do **This documents the upcoming AVA 3 release. See the [AVA 2](https://github.com/avajs/ava/blob/v2.4.0/docs/06-configuration.md) documentation instead.** -All of the [CLI options][CLI] can be configured in the `ava` section of either your `package.json` file, or an `ava.config.js` file. This allows you to modify the default behavior of the `ava` command, so you don't have to repeatedly type the same options on the command prompt. +All of the [CLI options][CLI] can be configured in the `ava` section of either your `package.json` file, or an `ava.config.*` file. This allows you to modify the default behavior of the `ava` command, so you don't have to repeatedly type the same options on the command prompt. To ignore files, prefix the pattern with an `!` (exclamation mark). @@ -40,7 +40,7 @@ Arguments passed to the CLI will always take precedence over the CLI options con ## Options -- `files`: an array of glob patterns to select test files. Files with an underscore prefix are ignored. By default only selects files with `js` extensions, even if the pattern matches other files. Specify `extensions` to allow other file extensions +- `files`: an array of glob patterns to select test files. Files with an underscore prefix are ignored. By default only selects files with `cjs`, `mjs` & `js` extensions, even if the pattern matches other files. Specify `extensions` to allow other file extensions - `ignoredByWatcher`: an array of glob patterns to match files that, even if changed, are ignored by the watcher. See the [watch mode recipe for details](https://github.com/avajs/ava/blob/master/docs/recipes/watch-mode.md) - `match`: not typically useful in the `package.json` configuration, but equivalent to [specifying `--match` on the CLI](./05-command-line.md#running-tests-with-matching-titles) - `cache`: cache compiled files under `node_modules/.cache/ava`. If `false`, files are cached in a temporary directory instead @@ -50,7 +50,7 @@ Arguments passed to the CLI will always take precedence over the CLI options con - `tap`: if `true`, enables the [TAP reporter](./05-command-line.md#tap-reporter) - `verbose`: if `true`, enables verbose output - `snapshotDir`: specifies a fixed location for storing snapshot files. Use this if your snapshots are ending up in the wrong location -- `extensions`: extensions of test files. Setting this overrides the default `"js"` value, so make sure to include that extension in the list +- `extensions`: extensions of test files. Setting this overrides the default `["cjs", "mjs", "js"]` value, so make sure to include those extensions in the list - `require`: extra modules to require before tests are run. Modules are required in the [worker processes](./01-writing-tests.md#process-isolation) - `timeout`: Timeouts in AVA behave differently than in other test frameworks. AVA resets a timer after each test, forcing tests to quit if no new test results were received within the specified timeout. This can be used to handle stalled tests. See our [timeout documentation](./07-test-timeouts.md) for more options. @@ -58,26 +58,34 @@ Note that providing files on the CLI overrides the `files` option. Provide the `babel` option (and install [`@ava/babel`](https://github.com/avajs/babel) as an additional dependency) to enable Babel compilation. -## Using `ava.config.js` +## Using `ava.config.*` files -To use an `ava.config.js` file: +Rather than specifying the configuration in the `package.json` file you can use `ava.config.js` or `ava.config.cjs` files. -1. It must be in the same directory as your `package.json` +To use these files: + +1. They must be in the same directory as your `package.json` 2. Your `package.json` must not contain an `ava` property (or, if it does, it must be an empty object) -3. You must use `export default`, though [`require()`](https://nodejs.org/api/modules.html#modules_require_id) is available to load non-ES modules +3. You must not both have an `ava.config.js` *and* an `ava.config.cjs` file + +AVA recognizes `ava.config.mjs` files but refuses to load them. + +### `ava.config.js` -The config file must have a default export, using ES modules. It can either be a plain object or a factory function which returns a plain object: +For `ava.config.js` files you must use `export default`. You cannot use ["module scope"](https://nodejs.org/docs/latest-v12.x/api/modules.html#modules_the_module_scope). You cannot import dependencies. + +The default export can either be a plain object or a factory function which returns a plain object: ```js export default { - require: ['esm'] + require: ['./_my-test-helper'] }; ``` ```js export default function factory() { return { - require: ['esm'] + require: ['./_my-test-helper'] }; }; ``` @@ -100,34 +108,74 @@ export default ({projectDir}) => { Note that the final configuration must not be a promise. +### `ava.config.cjs` + +For `ava.config.cjs` files you must assign `module.exports`. ["Module scope"](https://nodejs.org/docs/latest-v12.x/api/modules.html#modules_the_module_scope) is available. You can `require()` dependencies. + +The module export can either be a plain object or a factory function which returns a plain object: + +```js +module.exports = { + require: ['./_my-test-helper'] +}; +``` + +```js +module.exports = () => { + return { + require: ['./_my-test-helper'] + }; +}; +``` + +The factory function is called with an object containing a `projectDir` property, which you could use to change the returned configuration: + +```js +module.exports = ({projectDir}) => { + if (projectDir === '/Users/username/projects/my-project') { + return { + // Config A + }; + } + + return { + // Config B + }; +}; +``` + +Note that the final configuration must not be a promise. + ## Alternative configuration files -The [CLI] lets you specify a specific configuration file, using the `--config` flag. This file is processed just like an `ava.config.js` file would be. When the `--config` flag is set, the provided file will override all configuration from the `package.json` and `ava.config.js` files. The configuration is not merged. +The [CLI] lets you specify a specific configuration file, using the `--config` flag. This file must have either a `.js` or `.cjs` extension and is processed like an `ava.config.js` or `ava.config.cjs` file would be. + +When the `--config` flag is set, the provided file will override all configuration from the `package.json` and `ava.config.js` or `ava.config.cjs` files. The configuration is not merged. The configuration file *must* be in the same directory as the `package.json` file. You can use this to customize configuration for a specific test run. For instance, you may want to run unit tests separately from integration tests: -`ava.config.js`: +`ava.config.cjs`: ```js -export default { +module.exports = { files: ['unit-tests/**/*'] }; ``` -`integration-tests.config.js`: +`integration-tests.config.cjs`: ```js -import baseConfig from './ava.config.js'; +const baseConfig = require('./ava.config.cjs'); -export default { +module.exports = { ...baseConfig, files: ['integration-tests/**/*'] }; ``` -You can now run your unit tests through `npx ava` and the integration tests through `npx ava --config integration-tests.config.js`. +You can now run your unit tests through `npx ava` and the integration tests through `npx ava --config integration-tests.config.cjs`. ## Object printing depth diff --git a/docs/recipes/es-modules.md b/docs/recipes/es-modules.md index 60d4cbc71..4f66139a3 100644 --- a/docs/recipes/es-modules.md +++ b/docs/recipes/es-modules.md @@ -2,17 +2,21 @@ Translations: [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/docs/recipes/es-modules.md) -As of Node.js 8.5.0, [ES modules](http://2ality.com/2017/09/native-esm-node.html) are natively supported, but behind the `--experimental-modules` command line flag. It works using the `.mjs` file extension. AVA does not currently support the command line option or the new file extension, but you *can* use the [`esm`](https://github.com/standard-things/esm) module to use the new syntax. +As of Node.js 13, [ECMAScript modules](https://nodejs.org/docs/latest/api/esm.html#esm_introduction) are natively supported in Node.js itself. AVA does not quite support them *yet*, but we're close. + +For the time being, AVA *does* select test files with the `.mjs` extension, however it refuses to load them. Similarly the `package.json` `"type": "module"` field is recognized, but if set AVA will refuse to load test files with the `.js` extension. + +For now, your best bet is to use the [`esm`](https://github.com/standard-things/esm) package. Make sure to use the `.js` extension and *do not* set `"type": "module"` in `package.json`. Here's how you get it working with AVA. -First, install [`esm`](https://github.com/standard-things/esm): +First, install `esm`: ``` $ npm install esm ``` -Configure it in your `package.json` or `ava.config.js` file, and add it to AVA's `"require"` option as well. Make sure to add it as the first item. +Configure it in your `package.json` or `ava.config.*` file, and add it to AVA's `"require"` option as well. Make sure to add it as the first item. **`package.json`:** @@ -29,7 +33,7 @@ Configure it in your `package.json` or `ava.config.js` file, and add it to AVA's You can now use native ES modules with AVA: ```js -// sum.mjs +// sum.js export default function sum(a, b) { return a + b; }; @@ -38,24 +42,9 @@ export default function sum(a, b) { ```js // test.js const test = require('ava'); -const sum = require('./sum.mjs'); +const sum = require('./sum'); test('2 + 2 = 4', t => { t.is(sum(2, 2), 4); }); ``` - -You need to configure AVA to recognize `.mjs` extensions; - -**`package.json`:** - -```json -{ - "ava": { - "extensions": [ - "js", - "mjs" - ] - } -} -``` diff --git a/docs/recipes/flow.md b/docs/recipes/flow.md index c766da019..9660b0a43 100644 --- a/docs/recipes/flow.md +++ b/docs/recipes/flow.md @@ -8,7 +8,7 @@ Until [1.4.1](https://github.com/avajs/ava/releases/tag/v1.4.1) AVA came bundled This guide assumes you've already set up Flow for your project. Note that AVA's definition as been tested with version 0.95.1. -We recommend you use AVA's [Babel support](https://github.com/avajs/babel) to strip Flow type annotations and declarations. AVA automatically applies your project's Babel configuration, so everything may just work without changes. Alternatively install [`@babel/plugin-transform-flow-strip-types`](https://www.npmjs.com/package/@babel/plugin-transform-flow-strip-types) and customize AVA's configuration in the `package.json` file (or the `ava.config.js` file) as follows. +We recommend you use AVA's [Babel support](https://github.com/avajs/babel) to strip Flow type annotations and declarations. AVA automatically applies your project's Babel configuration, so everything may just work without changes. Alternatively install [`@babel/plugin-transform-flow-strip-types`](https://www.npmjs.com/package/@babel/plugin-transform-flow-strip-types) and customize AVA's configuration in the `package.json` file (or the `ava.config.*` file) as follows. **`package.json`:** diff --git a/docs/recipes/react.md b/docs/recipes/react.md index 24df46504..c875bce4d 100644 --- a/docs/recipes/react.md +++ b/docs/recipes/react.md @@ -6,7 +6,7 @@ Translations: [Español](https://github.com/avajs/ava-docs/blob/master/es_ES/doc When you [enable Babel](https://github.com/avajs/babel), AVA will automatically extend your regular (project-level) Babel configuration. You should be able to use React in your test files without any additional configuration. -However if you want to set it up explicitly, add the preset to the test options in AVA's Babel pipeline by modifying your `package.json` or `ava.config.js` file. +However if you want to set it up explicitly, add the preset to the test options in AVA's Babel pipeline by modifying your `package.json` or `ava.config.*` file. **`package.json`:** diff --git a/docs/recipes/watch-mode.md b/docs/recipes/watch-mode.md index 169ff9bff..b0fe65e63 100644 --- a/docs/recipes/watch-mode.md +++ b/docs/recipes/watch-mode.md @@ -47,7 +47,7 @@ And then use: $ npm run watch:test ``` -Finally you could configure AVA to *always* run in watch mode by setting the `watch` key in the [`ava` section of your `package.json`, or `ava.config.js` file][config]. +Finally you could configure AVA to *always* run in watch mode by setting the `watch` key in the [`ava` section of your `package.json`, or `ava.config.*` file][config]. **`package.json`:** @@ -67,9 +67,9 @@ AVA uses [`chokidar`] as the file watcher. Note that even if you see warnings ab ## Ignoring changes -By default AVA watches for changes to all files, except for those with a `.snap.md` extension, `ava.config.js` and files in [certain directories](https://github.com/novemberborn/ignore-by-default/blob/master/index.js) as provided by the [`ignore-by-default`] package. +By default AVA watches for changes to all files, except for those with a `.snap.md` extension, `ava.config.*` and files in [certain directories](https://github.com/novemberborn/ignore-by-default/blob/master/index.js) as provided by the [`ignore-by-default`] package. -You can configure additional patterns for files to ignore in the [`ava` section of your `package.json`, or `ava.config.js` file][config], using the `ignoredByWatcher` key. +You can configure additional patterns for files to ignore in the [`ava` section of your `package.json`, or `ava.config.*` file][config], using the `ignoredByWatcher` key. If your tests write to disk they may trigger the watcher to rerun your tests. Configuring additional ignore patterns helps avoid this. @@ -77,7 +77,7 @@ If your tests write to disk they may trigger the watcher to rerun your tests. Co AVA tracks which source files your test files depend on. If you change such a dependency only the test file that depends on it will be rerun. AVA will rerun all tests if it cannot determine which test file depends on the changed source file. -Dependency tracking works for required modules. Custom extensions and transpilers are supported, provided you [added them in your `package.json` or `ava.config.js` file][config], and not from inside your test file. Files accessed using the `fs` module are not tracked. +Dependency tracking works for required modules. Custom extensions and transpilers are supported, provided you [added them in your `package.json` or `ava.config.*` file][config], and not from inside your test file. Files accessed using the `fs` module are not tracked. ## Watch mode and the `.only` modifier diff --git a/lib/api.js b/lib/api.js index 3213882db..e88ef024b 100644 --- a/lib/api.js +++ b/lib/api.js @@ -42,7 +42,7 @@ class Api extends Emittery { constructor(options) { super(); - this.options = {match: [], ...options}; + this.options = {match: [], moduleTypes: {}, ...options}; this.options.require = resolveModules(this.options.require); this._cacheDir = null; diff --git a/lib/cli.js b/lib/cli.js index 9076fc0d9..d3e2aa151 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -7,6 +7,7 @@ const arrify = require('arrify'); const yargs = require('yargs'); const Promise = require('bluebird'); const isCi = require('is-ci'); +const readPkg = require('read-pkg'); const loadConfig = require('./load-config'); // Bluebird specific @@ -113,7 +114,7 @@ exports.run = async () => { // eslint-disable-line complexity type: 'boolean' }, config: { - description: 'JavaScript file for AVA to read its config from, instead of using package.json or ava.config.js files' + description: 'Specific JavaScript file for AVA to read its config from, instead of using package.json or ava.config.* files' } }) .command('* [...]', 'Run tests', yargs => yargs.options(FLAGS).positional('pattern', { @@ -254,6 +255,23 @@ exports.run = async () => { // eslint-disable-line complexity const {normalizeGlobs, normalizePatterns} = require('./globs'); const validateEnvironmentVariables = require('./environment-variables'); + let pkg; + try { + pkg = readPkg.sync({cwd: projectDir}); + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } + } + + const {type: defaultModuleType = 'commonjs'} = pkg || {}; + + const moduleTypes = { + cjs: 'commonjs', + mjs: 'module', + js: defaultModuleType + }; + let babelProvider; if (Reflect.has(conf, 'babel')) { try { @@ -306,6 +324,7 @@ exports.run = async () => { // eslint-disable-line complexity failFast: combined.failFast, failWithoutAssertions: combined.failWithoutAssertions !== false, globs, + moduleTypes, environmentVariables, match, parallelRuns, diff --git a/lib/extensions.js b/lib/extensions.js index debc23ddf..b74a23b7e 100644 --- a/lib/extensions.js +++ b/lib/extensions.js @@ -24,10 +24,19 @@ module.exports = (configuredExtensions, babelProvider) => { throw new Error(`Unexpected duplicate extensions in options: '${[...duplicates].join('\', \'')}'.`); } - // Unless the default was used by `babelProvider`, as long as the extensions aren't explicitly set to be the empty - // array, set the default. - if (!seen.has('js') && configuredExtensions === undefined) { - seen.add('js'); + // Unless the default was used by `babelProvider`, as long as the extensions aren't explicitly set, set the default. + if (configuredExtensions === undefined) { + if (!seen.has('cjs')) { + seen.add('cjs'); + } + + if (!seen.has('mjs')) { + seen.add('mjs'); + } + + if (!seen.has('js')) { + seen.add('js'); + } } return [...seen]; diff --git a/lib/globs.js b/lib/globs.js index c4b255d18..764796e1f 100644 --- a/lib/globs.js +++ b/lib/globs.js @@ -14,7 +14,8 @@ const defaultMicromatchIgnorePatterns = [ const defaultIgnoredByWatcherPatterns = [ '**/*.snap.md', // No need to rerun tests when the Markdown files change. - 'ava.config.js' // Config is not reloaded so avoid rerunning tests when it changes. + 'ava.config.js', // Config is not reloaded so avoid rerunning tests when it changes. + 'ava.config.cjs' // Config is not reloaded so avoid rerunning tests when it changes. ]; const buildExtensionPattern = extensions => extensions.length === 1 ? extensions[0] : `{${extensions.join(',')}}`; diff --git a/lib/load-config.js b/lib/load-config.js index 17cf53dc0..ceb63e8a0 100644 --- a/lib/load-config.js +++ b/lib/load-config.js @@ -1,6 +1,7 @@ 'use strict'; +const fs = require('fs'); const path = require('path'); -const esm = require('esm'); +const vm = require('vm'); const isPlainObject = require('is-plain-object'); const pkgConf = require('pkg-conf'); @@ -8,48 +9,132 @@ const NO_SUCH_FILE = Symbol('no ava.config.js file'); const MISSING_DEFAULT_EXPORT = Symbol('missing default export'); const EXPERIMENTS = new Set(['tryAssertion']); +class LegacyCommonJsAccessError extends Error { + constructor(thing, fileForErrorMessage) { + super(`${thing} is not available in ${fileForErrorMessage}. Use a .cjs file instead`); + this.name = 'LegacyCommonJsAccessError'; + } +} + +// *Very* rudimentary support for loading ava.config.js files containing an `export default` statement. +const evaluateJsConfig = (configFile, fileForErrorMessage) => { + const contents = fs.readFileSync(configFile, 'utf8'); + const script = new vm.Script(`'use strict';(()=>{let __export__;\n${contents.replace(/export default/g, '__export__ =')};return __export__;})()`, { + filename: configFile, + lineOffset: -1 + }); + return { + default: script.runInNewContext({ + get __dirname() { + throw new LegacyCommonJsAccessError('__dirname', fileForErrorMessage); + }, + get __filename() { + throw new LegacyCommonJsAccessError('__filename', fileForErrorMessage); + }, + get module() { + throw new LegacyCommonJsAccessError('module', fileForErrorMessage); + }, + get exports() { + throw new LegacyCommonJsAccessError('exports', fileForErrorMessage); + }, + get require() { + throw new LegacyCommonJsAccessError('require()', fileForErrorMessage); + } + }) + }; +}; + +const loadJsConfig = ({projectDir, configFile = path.join(projectDir, 'ava.config.js')}) => { + if (!configFile.endsWith('.js')) { + return null; + } + + const fileForErrorMessage = path.relative(projectDir, configFile); + + let config; + try { + ({default: config = MISSING_DEFAULT_EXPORT} = evaluateJsConfig(configFile, fileForErrorMessage)); + } catch (error) { + if (error.code === 'ENOENT') { + return null; + } + + if (error.name === 'LegacyCommonJsAccessError') { + throw error; + } else { + throw Object.assign(new Error(`Error loading ${fileForErrorMessage}`), {parent: error}); + } + } + + if (config === MISSING_DEFAULT_EXPORT) { + throw new Error(`${fileForErrorMessage} must have a default export, using ES module syntax`); + } + + return {config, fileForErrorMessage}; +}; + +const loadCjsConfig = ({projectDir, configFile = path.join(projectDir, 'ava.config.cjs')}) => { + if (!configFile.endsWith('.cjs')) { + return null; + } + + const fileForErrorMessage = path.relative(projectDir, configFile); + try { + return {config: require(configFile), fileForErrorMessage}; + } catch (error) { + if (error.code === 'MODULE_NOT_FOUND') { + return null; + } + + throw Object.assign(new Error(`Error loading ${fileForErrorMessage}`), {parent: error}); + } +}; + +const loadMjsConfig = ({projectDir, configFile = path.join(projectDir, 'ava.config.mjs')}) => { + if (!configFile.endsWith('.mjs')) { + return null; + } + + const fileForErrorMessage = path.relative(projectDir, configFile); + try { + fs.readFileSync(configFile); + } catch (error) { + if (error.code === 'ENOENT') { + return null; + } + + throw Object.assign(new Error(`Error loading ${fileForErrorMessage}`), {parent: error}); + } + + throw new Error(`AVA cannot yet load ${fileForErrorMessage} files`); +}; + function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) { // eslint-disable-line complexity let packageConf = pkgConf.sync('ava', {cwd: resolveFrom}); const filepath = pkgConf.filepath(packageConf); const projectDir = filepath === null ? resolveFrom : path.dirname(filepath); - const fileForErrorMessage = configFile || 'ava.config.js'; - const allowConflictWithPackageJson = Boolean(configFile); - if (configFile) { configFile = path.resolve(configFile); // Relative to CWD if (path.basename(configFile) !== path.relative(projectDir, configFile)) { throw new Error('Config files must be located next to the package.json file'); } - } else { - configFile = path.join(projectDir, 'ava.config.js'); - } - let fileConf; - try { - ({default: fileConf = MISSING_DEFAULT_EXPORT} = esm(module, { - cjs: { - cache: false, - extensions: false, - interop: false, - mutableNamespace: false, - namedExports: false, - paths: false, - vars: true - }, - force: true, - mode: 'all' - })(configFile)); - } catch (error) { - if (error && error.code === 'MODULE_NOT_FOUND') { - fileConf = NO_SUCH_FILE; - } else { - throw Object.assign(new Error(`Error loading ${fileForErrorMessage}`), {parent: error}); + if (!configFile.endsWith('.js') && !configFile.endsWith('.cjs') && !configFile.endsWith('.mjs')) { + throw new Error('Config files must have .js, .cjs or .mjs extensions'); } } - if (fileConf === MISSING_DEFAULT_EXPORT) { - throw new Error(`${fileForErrorMessage} must have a default export, using ES module syntax`); + const allowConflictWithPackageJson = Boolean(configFile); + + let [{config: fileConf, fileForErrorMessage} = {config: NO_SUCH_FILE, fileForErrorMessage: undefined}, ...conflicting] = [ + loadJsConfig({projectDir, configFile}), + loadCjsConfig({projectDir, configFile}), + loadMjsConfig({projectDir, configFile}) + ].filter(result => result !== null); + + if (conflicting.length > 0) { + throw new Error(`Conflicting configuration in ${fileForErrorMessage} and ${conflicting.map(({fileForErrorMessage}) => fileForErrorMessage).join(' & ')}`); } if (fileConf !== NO_SUCH_FILE) { diff --git a/lib/worker/subprocess.js b/lib/worker/subprocess.js index a0d2627b5..383ab1156 100644 --- a/lib/worker/subprocess.js +++ b/lib/worker/subprocess.js @@ -120,8 +120,20 @@ ipc.options.then(options => { runner.powerAssert = babelProvider.powerAssert; } + const extensionsToLoadAsModules = Object.entries(options.moduleTypes) + .filter(([, type]) => type === 'module') + .map(([extension]) => extension); + let requireFn = require; const load = ref => { + for (const extension of extensionsToLoadAsModules) { + if (ref.endsWith(`.${extension}`)) { + ipc.send({type: 'internal-error', err: serializeError('Internal runner error', false, new Error('AVA cannot yet load ESM files.'))}); + exit(1); + return; + } + } + if (babelProvider !== undefined && babelProvider.canLoad(ref)) { return babelProvider.load(ref, {requireFn}); } diff --git a/package-lock.json b/package-lock.json index ea683a0e8..51ca973e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,7 +63,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", - "dev": true, "requires": { "@babel/highlight": "^7.0.0" } @@ -738,7 +737,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", - "dev": true, "requires": { "chalk": "^2.0.0", "esutils": "^2.0.2", @@ -749,7 +747,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -758,7 +755,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -769,7 +765,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -777,20 +772,17 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -1097,8 +1089,7 @@ "@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", - "dev": true + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==" }, "abbrev": { "version": "1.1.0", @@ -3594,7 +3585,8 @@ "esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", - "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==" + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "dev": true }, "espower-location-detector": { "version": "1.0.0", @@ -4978,8 +4970,7 @@ "hosted-git-info": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz", - "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=", - "dev": true + "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=" }, "http-cache-semantics": { "version": "4.0.3", @@ -5784,8 +5775,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-types": { "version": "1.0.0", @@ -5953,8 +5943,7 @@ "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", - "dev": true + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" }, "load-json-file": { "version": "4.0.0", @@ -5968,6 +5957,16 @@ "strip-bom": "^3.0.0" }, "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -7253,13 +7252,14 @@ } }, "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", "requires": { + "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" } }, "parse-ms": { @@ -7666,14 +7666,45 @@ } }, "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "resolve": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", + "integrity": "sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" + } } }, "read-pkg-up": { @@ -7713,6 +7744,17 @@ "requires": { "p-limit": "^2.0.0" } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } } } }, @@ -8084,8 +8126,7 @@ "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" }, "semver-diff": { "version": "3.1.1", @@ -8450,7 +8491,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", - "dev": true, "requires": { "spdx-license-ids": "^1.0.2" } @@ -8458,14 +8498,12 @@ "spdx-expression-parse": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", - "dev": true + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" }, "spdx-license-ids": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", - "dev": true + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" }, "split-string": { "version": "3.1.0", @@ -10641,7 +10679,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "dev": true, "requires": { "spdx-correct": "~1.0.0", "spdx-expression-parse": "~1.0.0" @@ -11325,6 +11362,17 @@ "requires": { "locate-path": "^2.0.0" } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } } } }, @@ -11629,6 +11677,19 @@ "requires": { "find-up": "^2.0.0", "read-pkg": "^3.0.0" + }, + "dependencies": { + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + } } } } diff --git a/package.json b/package.json index 20807a39a..6d582927a 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,6 @@ "del": "^5.1.0", "emittery": "^0.5.1", "equal-length": "^1.0.0", - "esm": "^3.2.25", "figures": "^3.1.0", "get-port": "^5.1.0", "globby": "^10.0.1", @@ -104,6 +103,7 @@ "pkg-conf": "^3.1.0", "plur": "^3.1.1", "pretty-ms": "^5.1.0", + "read-pkg": "^5.2.0", "resolve-cwd": "^3.0.0", "slash": "^3.0.0", "source-map-support": "^0.5.16", @@ -124,6 +124,7 @@ "@types/node": "^10.17.11", "cli-table3": "^0.5.1", "delay": "^4.3.0", + "esm": "^3.2.25", "execa": "^4.0.0", "get-stream": "^5.1.0", "git-branch": "^2.0.1", diff --git a/test/fixture/cjs.cjs b/test/fixture/cjs.cjs new file mode 100644 index 000000000..d8fad5326 --- /dev/null +++ b/test/fixture/cjs.cjs @@ -0,0 +1,5 @@ +const test = require('../..'); + +test('pass', t => { + t.pass(); +}); diff --git a/test/fixture/environment-variables/ava.config.js b/test/fixture/environment-variables/ava.config.js index d8f79e8de..e64b98605 100644 --- a/test/fixture/environment-variables/ava.config.js +++ b/test/fixture/environment-variables/ava.config.js @@ -1,5 +1,3 @@ -const config = require('.'); - export default { - environmentVariables: {[config.name]: config.value} + environmentVariables: {MY_ENVIRONMENT_VARIABLE: 'some value'} }; diff --git a/test/fixture/environment-variables/index.js b/test/fixture/environment-variables/index.js deleted file mode 100644 index 58dbeb10c..000000000 --- a/test/fixture/environment-variables/index.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; - -module.exports = { - name: 'MY_ENVIRONMENT_VARIABLE', - value: 'some value' -}; diff --git a/test/fixture/environment-variables/test.js b/test/fixture/environment-variables/test.js index 32649d148..9ff79c537 100644 --- a/test/fixture/environment-variables/test.js +++ b/test/fixture/environment-variables/test.js @@ -1,6 +1,5 @@ const test = require('../../..'); -const {name, value} = require('.'); test('works', t => { - t.is(process.env[name], value); + t.is(process.env.MY_ENVIRONMENT_VARIABLE, 'some value'); }); diff --git a/test/fixture/esm/package.json b/test/fixture/esm/package.json new file mode 100644 index 000000000..3dbc1ca59 --- /dev/null +++ b/test/fixture/esm/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/test/fixture/esm/test.js b/test/fixture/esm/test.js new file mode 100644 index 000000000..4d43b03a7 --- /dev/null +++ b/test/fixture/esm/test.js @@ -0,0 +1,5 @@ +import test from '../../..'; + +test('pass', t => { + t.pass(); +}); diff --git a/test/fixture/load-config/cjs/ava.config.cjs b/test/fixture/load-config/cjs/ava.config.cjs new file mode 100644 index 000000000..24a2383a5 --- /dev/null +++ b/test/fixture/load-config/cjs/ava.config.cjs @@ -0,0 +1,5 @@ +module.exports = ({projectDir}) => { + return { + files: projectDir + }; +}; diff --git a/test/fixture/load-config/cjs/package.json b/test/fixture/load-config/cjs/package.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/fixture/load-config/cjs/package.json @@ -0,0 +1 @@ +{} diff --git a/test/fixture/load-config/explicit-bad-extension/explicit.txt b/test/fixture/load-config/explicit-bad-extension/explicit.txt new file mode 100644 index 000000000..755aeb7b9 --- /dev/null +++ b/test/fixture/load-config/explicit-bad-extension/explicit.txt @@ -0,0 +1,5 @@ +const config = { + files: 'config-file-esm-test-value' +}; + +export default config; diff --git a/test/fixture/load-config/explicit-bad-extension/package.json b/test/fixture/load-config/explicit-bad-extension/package.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/fixture/load-config/explicit-bad-extension/package.json @@ -0,0 +1 @@ +{} diff --git a/test/fixture/load-config/file-yes-cjs-yes/ava.config.cjs b/test/fixture/load-config/file-yes-cjs-yes/ava.config.cjs new file mode 100644 index 000000000..358af79e4 --- /dev/null +++ b/test/fixture/load-config/file-yes-cjs-yes/ava.config.cjs @@ -0,0 +1,3 @@ +module.exports = { + files: 'package-yes-files-yes-test-value' +}; diff --git a/test/fixture/load-config/file-yes-cjs-yes/ava.config.js b/test/fixture/load-config/file-yes-cjs-yes/ava.config.js new file mode 100644 index 000000000..c6ddbbed4 --- /dev/null +++ b/test/fixture/load-config/file-yes-cjs-yes/ava.config.js @@ -0,0 +1,3 @@ +export default { + files: 'package-yes-files-yes-test-value' +}; diff --git a/test/fixture/load-config/file-yes-cjs-yes/package.json b/test/fixture/load-config/file-yes-cjs-yes/package.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/fixture/load-config/file-yes-cjs-yes/package.json @@ -0,0 +1 @@ +{} diff --git a/test/fixture/load-config/mjs/ava.config.mjs b/test/fixture/load-config/mjs/ava.config.mjs new file mode 100644 index 000000000..4715349f6 --- /dev/null +++ b/test/fixture/load-config/mjs/ava.config.mjs @@ -0,0 +1,5 @@ +export default ({projectDir}) => { + return { + files: projectDir + }; +}; diff --git a/test/fixture/load-config/mjs/package.json b/test/fixture/load-config/mjs/package.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/fixture/load-config/mjs/package.json @@ -0,0 +1 @@ +{} diff --git a/test/fixture/load-config/no-default-export/ava.config.js b/test/fixture/load-config/no-default-export/ava.config.js index c4470d209..e69de29bb 100644 --- a/test/fixture/load-config/no-default-export/ava.config.js +++ b/test/fixture/load-config/no-default-export/ava.config.js @@ -1 +0,0 @@ -export const config = {}; diff --git a/test/fixture/mjs.mjs b/test/fixture/mjs.mjs new file mode 100644 index 000000000..eb655cc68 --- /dev/null +++ b/test/fixture/mjs.mjs @@ -0,0 +1,5 @@ +import test from '../..'; + +test('pass', t => { + t.pass(); +}); diff --git a/test/integration/assorted.js b/test/integration/assorted.js index acc6e9d80..180ce3282 100644 --- a/test/integration/assorted.js +++ b/test/integration/assorted.js @@ -165,3 +165,27 @@ test('reset-cache resets cache', t => { t.end(); }); }); + +test('selects .cjs test files', t => { + execCli('cjs.cjs', (err, stdout) => { + t.ifError(err); + t.match(stdout, /1 test passed/); + t.end(); + }); +}); + +test('refuses to load .mjs test files', t => { + execCli('mjs.mjs', (err, stdout) => { + t.ok(err); + t.match(stdout, /AVA cannot yet load ESM files/); + t.end(); + }); +}); + +test('refuses to load .js test files as ESM modules', t => { + execCli('test.js', {dirname: 'fixture/esm'}, (err, stdout) => { + t.ok(err); + t.match(stdout, /AVA cannot yet load ESM files/); + t.end(); + }); +}); diff --git a/test/integration/environment-variables.js b/test/integration/environment-variables.js index 65fc27871..a6e0b3ba0 100644 --- a/test/integration/environment-variables.js +++ b/test/integration/environment-variables.js @@ -2,7 +2,6 @@ const {test} = require('tap'); const figures = require('figures'); const {execCli} = require('../helper/cli'); -const {name, value} = require('../fixture/environment-variables'); test('sets default environment variables from the config', t => { execCli(['test.js'], {dirname: 'fixture/environment-variables'}, (err, stdout) => { @@ -13,7 +12,7 @@ test('sets default environment variables from the config', t => { }); test('overrides environment variables provided through the CLI', t => { - const env = {[name]: `${value} (updated)`}; + const env = {MY_ENVIRONMENT_VARIABLE: 'some value (updated)'}; execCli(['test.js'], {dirname: 'fixture/environment-variables', env}, (err, stdout) => { t.ifError(err); diff --git a/test/load-config.js b/test/load-config.js index d3fe826ac..862fb75d0 100644 --- a/test/load-config.js +++ b/test/load-config.js @@ -28,7 +28,7 @@ test('loads config from a particular directory', t => { t.end(); }); -test('throws a warning if both configs are present', t => { +test('throws an error if both configs are present', t => { changeDir('package-yes-file-yes'); t.throws(loadConfig, /Conflicting configuration in ava.config.js and package.json/); t.end(); @@ -47,6 +47,12 @@ test('throws if configFile option is not in the same directory as the package.js t.end(); }); +test('throws if configFile option has an unsupported extension', t => { + changeDir('explicit-bad-extension'); + t.throws(() => loadConfig({configFile: 'explicit.txt'}), /Config files must have .js, .cjs or .mjs extensions/); + t.end(); +}); + test('merges in defaults passed with initial call', t => { changeDir('package-only'); const defaults = { @@ -72,10 +78,9 @@ test('loads config from factory function', t => { t.end(); }); -test('supports require() inside config file', t => { +test('does not support require() inside config.js files', t => { changeDir('require'); - const conf = loadConfig(); - t.is(conf.files, 'config-file-cjs-test-value'); + t.throws(loadConfig, /require\(\) is not available in ava\.config\.js\. Use a \.cjs file instead/); t.end(); }); @@ -120,7 +125,7 @@ test('rethrows wrapped module errors', t => { } }); -test('throws an error if a config file has no default export', t => { +test('throws an error if a .js config file has no default export', t => { changeDir('no-default-export'); t.throws(loadConfig, /ava.config.js must have a default export, using ES module syntax/); t.end(); @@ -143,3 +148,28 @@ test('throws an error if a config file enables an unsupported experiment', t => t.throws(loadConfig, /nonSemVerExperiments.unsupported from ava.config.js is not a supported experiment/); t.end(); }); + +test('loads .cjs config', t => { + changeDir('cjs'); + const conf = loadConfig(); + t.ok(conf.files.startsWith(__dirname)); + t.end(); +}); + +test('throws an error if both .js and .cjs configs are present', t => { + changeDir('file-yes-cjs-yes'); + t.throws(loadConfig, /Conflicting configuration in ava.config.js and ava.config.cjs/); + t.end(); +}); + +test('refuses to load .mjs config', t => { + changeDir('mjs'); + t.throws(loadConfig, /AVA cannot yet load ava.config.mjs files/); + t.end(); +}); + +test('throws an error if .js, .cjs and .mjs configs are present', t => { + changeDir('file-yes-cjs-yes'); + t.throws(loadConfig, /Conflicting configuration in ava.config.js and ava.config.cjs & ava.config.mjs/); + t.end(); +}, {todo: true}); diff --git a/test/watcher.js b/test/watcher.js index b21d630b2..e85e7f80f 100644 --- a/test/watcher.js +++ b/test/watcher.js @@ -188,7 +188,7 @@ group('chokidar', (beforeEach, test, group) => { ['**/*'], { cwd: process.cwd(), - ignored: [...defaultIgnore.map(dir => `${dir}/**/*`), '**/node_modules/**/*', '**/*.snap.md', 'ava.config.js'], + ignored: [...defaultIgnore.map(dir => `${dir}/**/*`), '**/node_modules/**/*', '**/*.snap.md', 'ava.config.js', 'ava.config.cjs'], ignoreInitial: true } ]); @@ -204,7 +204,7 @@ group('chokidar', (beforeEach, test, group) => { ['**/*'], { cwd: process.cwd(), - ignored: [...defaultIgnore.map(dir => `${dir}/**/*`), '**/node_modules/**/*', '**/*.snap.md', 'ava.config.js', 'bar.js', 'qux.js'], + ignored: [...defaultIgnore.map(dir => `${dir}/**/*`), '**/node_modules/**/*', '**/*.snap.md', 'ava.config.js', 'ava.config.cjs', 'bar.js', 'qux.js'], ignoreInitial: true } ]);