Remove built-in Babel support

This updates code and tests to remove built-in Babel support. In the
future, it needs to be opted in to, and @ava/babel needs to be installed
besides AVA itself.

Our tests have become quite muddled, and some of them require Babel to
still be enabled, but that's all OK for now.

* Remove outdated JSPM recipe

* Update documentation to reflect the removal of built-in Babel

* Move responsibility for power-assert to @ava/babel
This commit is contained in:
Mark Wubben 2019-12-24 17:46:45 +01:00 committed by GitHub
parent 4953457277
commit b4ea43529a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
227 changed files with 868 additions and 2377 deletions

View file

@ -28,7 +28,6 @@ The [`question` label](https://github.com/avajs/ava/labels/question) is a good p
You can use issue labels to discover issues you could help out with:
* [`babel` issues](https://github.com/avajs/ava/labels/babel) relate to our Babel infrastructure
* [`blocked` issues](https://github.com/avajs/ava/labels/blocked) need help getting unstuck
* [`bug` issues](https://github.com/avajs/ava/labels/bug) are known bugs we'd like to fix
* [`enhancement` issues](https://github.com/avajs/ava/labels/enhancement) are features we're open to including

View file

@ -12,7 +12,7 @@ AVA tries to run test files with their current working directory set to the dire
Each test file is run in a separate Node.js process. This allows you to change the global state or overriding a built-in in one test file, without affecting another. It's also great for performance on modern multi-core processors, allowing multiple test files to execute in parallel.
AVA will set `process.env.NODE_ENV` to `test`, unless the `NODE_ENV` environment variable has been set. This is useful if the code you're testing has test defaults (for example when picking what database to connect to, or environment-specific Babel options). It may cause your code or its dependencies to behave differently though. Note that `'NODE_ENV' in process.env` will always be `true`.
AVA will set `process.env.NODE_ENV` to `test`, unless the `NODE_ENV` environment variable has been set. This is useful if the code you're testing has test defaults (for example when picking what database to connect to). It may cause your code or its dependencies to behave differently though. Note that `'NODE_ENV' in process.env` will always be `true`.
## Declaring tests

View file

@ -84,7 +84,7 @@ test('skip assertion', t => {
## Enhanced assertion messages
AVA comes with [`power-assert`](https://github.com/power-assert-js/power-assert) built-in, giving you more descriptive assertion messages.
Enabling [Babel](./recipes/babel.md) will also enable [`power-assert`](https://github.com/power-assert-js/power-assert), giving you more descriptive assertion messages.
Let's take this example, using Node's standard [`assert` library](https://nodejs.org/api/assert.html):

View file

@ -133,7 +133,13 @@ test(function foo(t) {
## Resetting AVA's cache
AVA caches the compiled test and helper files. It automatically recompiles these files when you change them. AVA tries its best to detect changes to your Babel configuration files, plugins and presets. If it seems like your latest Babel configuration isn't being applied, however, you can run AVA with the `--reset-cache` flag to reset AVA's cache. If set, all files in the `node_modules/.cache/ava` directory are deleted. Run AVA as normal to apply your new Babel configuration.
AVA may cache certain files, especially when you use our [`@ava/babel`](https://github.com/avajs/babel) provider. If it seems like your latest changes aren't being picked up by AVA you can reset the cache by running:
```console
npx ava reset-cache
```
This deletes all files in the `node_modules/.cache/ava` directory.
## Reporters

View file

@ -26,25 +26,16 @@ To ignore files, prefix the pattern with an `!` (exclamation mark).
"*oo",
"!foo"
],
"cache": true,
"concurrency": 5,
"failFast": true,
"failWithoutAssertions": false,
"environmentVariables": {
"MY_ENVIRONMENT_VARIABLE": "some value"
},
"tap": true,
"verbose": true,
"compileEnhancements": false,
"require": [
"@babel/register"
],
"babel": {
"extensions": ["js", "jsx"],
"testOptions": {
"babelrc": false
}
}
"./my-helper-module.js"
]
}
}
```
@ -53,8 +44,8 @@ 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` and `babel.extensions` to allow other file extensions
- `helpers`: an array of glob patterns to select helper files. Files matched here are never considered as tests. By default only selects files with `js` extensions, even if the pattern matches other files. Specify `extensions` and `babel.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 `js` extensions, even if the pattern matches other files. Specify `extensions` to allow other file extensions
- `helpers`: an array of glob patterns to select helper files. Files matched here are never considered as tests. By default only selects files with `js` extensions, even if the pattern matches other files. Specify `extensions` to allow other file extensions
- `sources`: an array of glob patterns to match files that, when changed, cause tests to be re-run (when in watch mode). See the [watch mode recipe for details](https://github.com/avajs/ava/blob/master/docs/recipes/watch-mode.md#source-files-and-test-files)
- `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 test and helper files under `node_modules/.cache/ava`. If `false`, files are cached in a temporary directory instead
@ -64,15 +55,14 @@ 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
- `compileEnhancements`: if `false`, disables [`power-assert`](./03-assertions.md#enhanced-assertion-messages) — which otherwise helps provide more descriptive error messages — and detection of improper use of the `t.throws()` assertion
- `extensions`: extensions of test files that are not precompiled using AVA's Babel presets. Note that files are still compiled to enable `power-assert` and other features, so you may also need to set `compileEnhancements` to `false` if your files are not valid JavaScript. Setting this overrides the default `"js"` value, so make sure to include that extension in the list, as long as it's not included in `babel.extensions`
- `extensions`: extensions of test files. Setting this overrides the default `"js"` value, so make sure to include that extension 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)
- `babel`: test file specific Babel options. See our [Babel recipe](./recipes/babel.md#configuring-babel) for more details
- `babel.extensions`: extensions of test files that will be precompiled using AVA's Babel presets. Setting this overrides the default `"js"` value, so make sure to include that extension in the list
- `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.
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`
To use an `ava.config.js` file:

View file

@ -4,14 +4,6 @@ Translations: [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/do
If you use [ESLint](http://eslint.org/), you can install [eslint-plugin-ava](https://github.com/avajs/eslint-plugin-ava). It will help you use AVA correctly and avoid some common pitfalls.
## Transpiling imported modules
AVA currently only transpiles test and helper files. *It will not transpile modules you `import` from outside of the test.* This may be unexpected but there are workarounds.
If you use Babel you can use its [require hook](https://babeljs.io/docs/usage/require/) to transpile imported modules on-the-fly. To add it, [configure it in your `package.json`](./06-configuration.md).
You can also transpile your modules in a separate process and refer to the transpiled files rather than the sources from your tests.
## AVA in Docker
If you run AVA in Docker as part of your CI, you need to fix the appropriate environment variables. Specifically, adding `-e CI=true` in the `docker exec` command. See [#751](https://github.com/avajs/ava/issues/751).
@ -81,6 +73,8 @@ test('one is one', t => {
});
```
Also make sure to enable [Babel](./recipes/babel.md).
## Sharing variables between asynchronous tests
By default AVA executes tests concurrently. This can cause problems if your tests are asynchronous and share variables.

View file

@ -2,285 +2,18 @@
Translations: [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/docs/recipes/babel.md)
AVA uses [Babel 7](https://babeljs.io) so you can use the latest JavaScript syntax in your tests. We do this by compiling test and helper files using our [`@ava/stage-4`](https://github.com/avajs/babel-preset-stage-4) preset. We also use a [second preset, `@ava/transform-test-files`](https://github.com/avajs/babel-preset-transform-test-files) to enable [enhanced assertion messages](../03-assertions.md#enhanced-assertion-messages) and detect improper use of `t.throws()` assertions.
**The upcoming AVA 3 release removes built-in Babel support. See the [AVA 2](https://github.com/avajs/ava/blob/v2.4.0/docs/recipes/babel.md) documentation instead.**
By default our Babel pipeline is applied to test and helper files ending in `.js`. If your project uses Babel then we'll automatically compile these files using your project's Babel configuration. The `@ava/transform-helper-files` preset is applied first, and the `@ava/stage-4` last.
If you are using Babel for your source files then you must also [configure source compilation](#compile-sources).
## Customize how AVA compiles your test files
You can override the default Babel configuration AVA uses for test file compilation in `package.json` or `ava.config.js`. For example, the configuration below adds support for JSX syntax and stage 3 features.
You can enable Babel support by installing `@ava/babel`, and then in AVA's configuration setting `babel` to `true`:
**`package.json`:**
```json
{
"ava": {
"babel": {
"testOptions": {
"plugins": ["@babel/plugin-syntax-jsx"],
"presets": ["@babel/preset-stage-3"]
}
}
"babel": true
}
}
```
All [Babel options] are allowed inside the `testOptions` object.
## Reset AVA's cache
AVA caches the compiled test and helper files. It automatically recompiles these files when you change them. AVA tries its best to detect changes to your Babel configuration files, plugins and presets. If it seems like your latest Babel configuration isn't being applied, however, you can reset AVA's cache:
```console
$ npx ava --reset-cache
```
## Add additional extensions
You can configure AVA to recognize additional file extensions and compile those test & helper files using Babel.
**`package.json`:**
```json
{
"ava": {
"babel": {
"extensions": [
"js",
"jsx"
]
}
}
}
```
See also AVA's [`extensions` option](../06-configuration.md#options).
## Make AVA skip your project's Babel options
You may not want AVA to use your project's Babel options, for example if your project is relying on Babel 6. Set the `babelrc` and `configFile` options to `false`.
**`package.json`:**
```json
{
"ava": {
"babel": {
"testOptions": {
"babelrc": false,
"configFile": false
}
}
}
}
```
## Disable AVA's stage-4 preset
You can disable AVA's stage-4 preset.
**`package.json`:**
```json
{
"ava": {
"babel": {
"testOptions": {
"presets": [
["module:ava/stage-4", false]
]
}
}
}
}
```
Note that this *does not* stop AVA from compiling your test files using Babel.
If you want, you can disable the preset in your project's Babel configuration.
## Preserve ES module syntax
By default AVA's stage-4 preset will convert ES module syntax to CommonJS. This can be disabled.
**`package.json`:**
```json
{
"ava": {
"babel": {
"testOptions": {
"presets": [
["module:ava/stage-4", {"modules": false}]
]
}
}
}
}
```
You'll have to use the [`esm`](https://github.com/standard-things/esm) module so that AVA can still load your test files. [See our recipe for details](./es-modules.md).
## Disable AVA's Babel pipeline
You can completely disable AVA's use of Babel.
**`package.json`:**
```json
{
"ava": {
"babel": false,
"compileEnhancements": false
}
}
```
## Experimental feature: No Babel out of the box
A future release of AVA will not use Babel out of the box. You can opt in to this feature. **This feature may change or be removed at any time**:
**`package.json`:**
```js
{
"ava": {
"nonSemVerExperiments": {
"noBabelOutOfTheBox": true
}
}
}
```
This disables AVA's Babel pipeline, though you can still enable it by configuring it as described above.
`compileEnhancements` can no longer be configured on the top-level AVA configuration. It must be configured in AVA's `babel` configuration instead. It defaults to `true`.
**`package.json`:**
```json
{
"ava": {
"nonSemVerExperiments": {
"noBabelOutOfTheBox": true
},
"babel": {
"compileEnhancements": false
}
}
}
```
You can disable the non-enhancement compilation of your test files by setting `testOptions` to `false`.
```json
{
"ava": {
"nonSemVerExperiments": {
"noBabelOutOfTheBox": true
},
"babel": {
"testOptions": false
}
}
}
```
## Use Babel polyfills
AVA lets you write your tests using new JavaScript syntax, even on Node.js versions that otherwise wouldn't support it. However, it doesn't add or modify built-ins of your current environment. Using AVA would, for example, not provide modern features such as `Object.entries()` to an underlying Node.js 6 environment.
By loading [Babel's `polyfill` module](https://babeljs.io/docs/usage/polyfill/) you can opt in to these features. Note that this will modify the environment, which may influence how your program behaves.
You can enable the `polyfill` module by adding it to AVA's `require` option.
**`package.json`:**
```json
{
"ava": {
"require": [
"@babel/polyfill"
]
}
}
```
You'll need to install `@babel/polyfill` yourself.
## Compile sources
AVA does not currently compile source files. You'll have to load [Babel's `register` module](http://babeljs.io/docs/usage/require/), which will compile source files as needed.
You can enable the `register` module by adding it to AVA's `require` option.
**`package.json`:**
```json
{
"ava": {
"require": [
"@babel/register"
]
}
}
```
You'll need to install `@babel/register` yourself.
`@babel/register` will *also* process your test and helper files. For most use cases this is unnecessary. If you create a new file that requires `@babel/register` you can tell it which file paths to ignore. For instance in your `test` directory create `_register.js`:
```js
// test/_register.js:
require('@babel/register')({
// These patterns are relative to the project directory (where the `package.json` file lives):
ignore: ['node_modules/*', 'test/*']
});
```
Now instead of requiring `@babel/register`, require `./test/_register` instead.
**`package.json`:**
```json
{
"ava": {
"require": [
"./test/_register.js"
]
}
}
```
Note that loading `@babel/register` in every worker process has a non-trivial performance cost. If you have lots of test files, you may want to consider using a build step to compile your sources *before* running your tests. This isn't ideal, since it complicates using AVA's watch mode, so we recommend using `@babel/register` until the performance penalty becomes too great. Setting up a precompilation step is out of scope for this document, but we recommend you check out one of the many [build systems that support Babel](http://babeljs.io/docs/setup/). There is an [issue](https://github.com/avajs/ava/issues/577) discussing ways we could make this experience better.
## Webpack aliases
[Webpack aliases](https://webpack.js.org/configuration/resolve/#resolve-alias) can be used to provide a shortcut to deeply nested or otherwise inconvenient paths. If you already use aliases in your source files, you'll need to make sure you can use the same aliases in your test files.
Install `babel-plugin-webpack-alias-7` as a dev-dependency. Then add the plugin to AVA's Babel config:
`package.json`:
```json
{
"ava": {
"babel": {
"testOptions": {
"plugins": [
[
"babel-plugin-webpack-alias-7",
{
"config": "./path/to/webpack.config.test.js"
}
]
]
}
}
}
}
```
[Babel options]: https://babeljs.io/docs/en/options
Find out more in [`@ava/babel`](https://github.com/avajs/babel).

View file

@ -1,5 +0,0 @@
# Configuring Babel
Translations: [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/docs/recipes/babelrc.md)
This recipe has moved. Please see our [new Babel recipe](babel.md).

View file

@ -2,15 +2,15 @@
Translations: [Español](https://github.com/avajs/ava-docs/blob/master/es_ES/docs/recipes/code-coverage.md), [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/docs/recipes/code-coverage.md), [Italiano](https://github.com/avajs/ava-docs/blob/master/it_IT/docs/recipes/code-coverage.md), [日本語](https://github.com/avajs/ava-docs/blob/master/ja_JP/docs/recipes/code-coverage.md), [Português](https://github.com/avajs/ava-docs/blob/master/pt_BR/docs/recipes/code-coverage.md), [Русский](https://github.com/avajs/ava-docs/blob/master/ru_RU/docs/recipes/code-coverage.md), [简体中文](https://github.com/avajs/ava-docs/blob/master/zh_CN/docs/recipes/code-coverage.md)
Use the [nyc] command-line-client for [Istanbul] to compute the code coverage of your tests.
Use [`nyc`] to compute the code coverage of your tests.
First install [nyc]:
First install [`nyc`]:
```
$ npm install --save-dev nyc
```
At its simplest run AVA through [nyc]. In your `package.json` file:
At its simplest run AVA through [`nyc`]. In your `package.json` file:
```json
{
@ -27,7 +27,4 @@ You may want to exclude the `.nyc_output` and `coverage` directories from source
coverage
```
If you're compiling your source files using Babel you may want to apply Istanbul's instrumentation as part of the source file compilation. This will yield better results than instrumenting Babel's output. See Istanbul's [*Using Istanbul With ES2015+* tutorial](https://istanbul.js.org/docs/tutorials/es2015/). AVA sets `NODE_ENV=test` for you. Note that as of February 2018 this tutorial hasn't yet been updated for Babel 7.
[Istanbul]: https://istanbul.js.org/
[nyc]: https://github.com/istanbuljs/nyc
[`nyc`]: https://github.com/istanbuljs/nyc

View file

@ -26,8 +26,6 @@ Configure it in your `package.json` or `ava.config.js` file, and add it to AVA's
}
```
By default AVA converts ES module syntax to CommonJS. [You can disable this](./babel.md#preserve-es-module-syntax).
You can now use native ES modules with AVA:
```js
@ -47,29 +45,13 @@ test('2 + 2 = 4', t => {
});
```
You need to configure AVA to recognize `.mjs` extensions. If you want AVA to apply its Babel presets use the following.
You need to configure AVA to recognize `.mjs` extensions;
**`package.json`:**
```json
{
"ava": {
"babel": {
"extensions": [
"js",
"mjs"
]
}
}
}
```
Alternatively you can use:
```json
{
"ava": {
"babel": false,
"extensions": [
"js",
"mjs"
@ -77,15 +59,3 @@ Alternatively you can use:
}
}
```
Or leave Babel enabled (which means it's applied to `.js` files), but don't apply it to `.mjs` files:
```json
{
"ava": {
"extensions": [
"mjs"
]
}
}
```

View file

@ -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 built-in Babel pipeline 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.js` file) as follows.
**`package.json`:**
@ -26,7 +26,7 @@ We recommend you use AVA's built-in Babel pipeline to strip Flow type annotation
}
```
See our [Babel documentation](babel.md) for more details.
See our [`@ava/babel`](https://github.com/avajs/babel) for more details.
## Writing tests

View file

@ -1,67 +0,0 @@
# JSPM and SystemJS for ES2015
Translations: [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/docs/recipes/jspm-systemjs.md)
It requires a special loader helper to correctly resolve `import`s of JSPM packages when using AVA. The purpose of the loader is to allow you to run your tests without having to pre-build your JSPM project.
## Setup
This recipe has only been tested with JSPM v0.17.0-beta.22, but it should work with any version of JSPM v0.17 and may work with v0.16.
### Babel
Set up your Babel options to work with AVA if you have not already. NOTE: You can keep additional configuration in your JSPM config files to override these settings during bundling and building.
```
$ npm install --save-dev @babel/preset-env
```
```json
{
"presets": ["@babel/preset-env"]
}
```
You can find more information about setting up Babel with AVA in the [Babel recipe](babel.md).
### JSPM Loader Helper
You will need to install the [AVA JSPM loader](https://github.com/skorlir/ava-jspm-loader) as a dev dependency. You will also need to install [`@babel/register`](https://www.npmjs.com/package/@babel/register).
```
$ npm install --save-dev ava-jspm-loader @babel/register
```
You will also need to update your AVA config in the `package.json` or `ava.config.js` to use the JSPM loader.
**`package.json`:**
```json
{
"ava": {
"require": [
"@babel/register",
"ava-jspm-loader"
]
}
}
```
NOTE: If you use async/await in your source code (not in your test code), you will need to install [`@babel/polyfill`](https://www.npmjs.com/package/@babel/polyfill) and add it to your `require` array.
### Example test file
Note that you will need to use `System.import` paths for all of your project files. So, if you named your project `app` and you want to import your `main.js` into a test file, you will need to `import main from 'app/main'`.
```js
import test from 'ava';
import main from 'app/main'; // Maps to your JSPM config for "app/main.js"
import BigNumber from 'bignumber.js'; // In jspm_packages
function fn() {
return Promise.resolve(new BigNumber('1234567890.123456789'));
}
test('example test', async t => {
t.is((await fn()).toString(), '1234567890.123456789');
});
```

View file

@ -4,7 +4,7 @@ Translations: [Español](https://github.com/avajs/ava-docs/blob/master/es_ES/doc
## Setting up Babel
AVA automatically extends your regular (project-level) Babel configuration. You should be able to use React in your test files without any additional configuration.
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.
@ -22,7 +22,7 @@ However if you want to set it up explicitly, add the preset to the test options
}
```
You can find more information about setting up Babel with AVA in the [Babel recipe](babel.md).
You can find more information in [`@ava/babel`](https://github.com/avajs/babel).
## Using [Enzyme](https://github.com/airbnb/enzyme)

View file

@ -48,7 +48,7 @@ hooks(['vue', 'js']).exclude(({filename}) => filename.match(/\/node_modules\//))
**Note:** If you are using _babel-plugin-webpack-alias-7_, you must also exclude your webpack file - e.g. `filename.includes(/\/node_modules\//) || filename.includes('webpack.config.test.js')`
You can find more information about setting up Babel with AVA in the [Babel recipe](babel.md).
You can find more information about setting up Babel with AVA in [`@ava/babel`](https://github.com/avajs/babel).
## Sample snapshot test

View file

@ -19,11 +19,10 @@ function load(projectDir, overrides) {
({conf, babelProvider} = configCache.get(projectDir));
} else {
conf = loadConfig({resolveFrom: projectDir});
const {nonSemVerExperiments: experiments} = conf;
if (!experiments.noBabelOutOfTheBox || conf.babel !== undefined) {
babelProvider = babelManager({experiments, projectDir});
babelProvider.validateConfig(conf.babel, conf.compileEnhancements !== false);
if (Reflect.has(conf, 'babel')) {
babelProvider = babelManager({projectDir});
babelProvider.validateConfig(conf.babel);
}
configCache.set(projectDir, {conf, babelProvider});
@ -38,7 +37,7 @@ function load(projectDir, overrides) {
}
}
const extensions = normalizeExtensions(conf.extensions, babelProvider, {experiments: conf.nonSemVerExperiments});
const extensions = normalizeExtensions(conf.extensions, babelProvider);
const globs = {cwd: projectDir, ...normalizeGlobs(conf.files, conf.helpers, conf.sources, extensions.all)};
const helper = Object.freeze({

View file

@ -57,7 +57,7 @@ class Api extends Emittery {
}
}
async run(files = [], runtimeOptions = {}) { // eslint-disable-line complexity
async run(files = [], runtimeOptions = {}) {
let setupOrGlobError;
files = files.map(file => path.resolve(this.options.resolveTestsFrom, file));
@ -118,11 +118,7 @@ class Api extends Emittery {
let helpers;
const {babelProvider} = this.options;
const enabledBabelProvider = babelProvider !== undefined && (
babelProvider.isEnabled() || (babelProvider.legacy && babelProvider.compileEnhancements !== null)
) ?
babelProvider :
null;
const enabledBabelProvider = babelProvider !== undefined && babelProvider.isEnabled() ? babelProvider : null;
try {
cacheDir = this._createCacheDir();
@ -210,44 +206,13 @@ class Api extends Emittery {
const testFiles = files.map(file => fs.realpathSync(file));
const helperFiles = helpers.map(file => fs.realpathSync(file));
if (enabledBabelProvider.legacy) {
const full = {testFiles: [], helperFiles: []};
const enhancements = {testFiles: [], helperFiles: []};
for (const realpath of testFiles) {
if (this._regexpBabelExtensions.test(path.basename(realpath))) { // eslint-disable-line max-depth
full.testFiles.push(realpath);
} else {
enhancements.testFiles.push(realpath);
}
}
for (const realpath of helperFiles) {
if (this._regexpBabelExtensions.test(path.basename(realpath))) { // eslint-disable-line max-depth
full.helperFiles.push(realpath);
} else {
enhancements.helperFiles.push(realpath);
}
}
babelState = {
...enabledBabelProvider.isEnabled() && enabledBabelProvider.compile({
cacheDir,
...full
}),
...enabledBabelProvider.compileEnhancements !== null && enabledBabelProvider.compileEnhancements({
cacheDir,
...enhancements
})
};
} else {
babelState = {
...enabledBabelProvider.compile({
cacheDir,
testFiles: testFiles.filter(realpath => this._regexpBabelExtensions.test(path.basename(realpath))),
helperFiles: helperFiles.filter(realpath => this._regexpBabelExtensions.test(path.basename(realpath)))
})
};
}
babelState = {
...enabledBabelProvider.compile({
cacheDir,
testFiles: testFiles.filter(realpath => this._regexpBabelExtensions.test(path.basename(realpath))),
helperFiles: helperFiles.filter(realpath => this._regexpBabelExtensions.test(path.basename(realpath)))
})
};
}
// Resolve the correct concurrency value.

View file

@ -1,11 +1,9 @@
'use strict';
const concordance = require('concordance');
const empower = require('empower-core');
const isError = require('is-error');
const isPromise = require('is-promise');
const concordanceOptions = require('./concordance-options').default;
const concordanceDiffOptions = require('./concordance-options').diff;
const enhanceAssert = require('./enhance-assert');
const snapshotManager = require('./snapshot-manager');
function formatDescriptorDiff(actualDescriptor, expectedDescriptor, options) {
@ -27,6 +25,10 @@ function formatWithLabel(label, value) {
return formatDescriptorWithLabel(label, concordance.describe(value, concordanceOptions));
}
function formatPowerAssertValue(value) {
return concordance.format(value, concordanceOptions);
}
const hasOwnProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
const noop = () => {};
const notImplemented = () => {
@ -236,20 +238,20 @@ class Assertions {
pending = notImplemented,
fail = notImplemented,
skip = notImplemented,
compareWithSnapshot = notImplemented
compareWithSnapshot = notImplemented,
powerAssert
} = {}) {
const withSkip = assertionFn => {
assertionFn.skip = skip;
return assertionFn;
};
// When adding new enhanced functions with new patterns, don't forget to add to
// https://github.com/avajs/babel-preset-transform-test-files/blob/master/espower-patterns.json
// Then release a new version of that preset and bump the SemVer range here.
const withPowerAssert = (pattern, assertionFn) => empower(assertionFn, {
// When adding new enhanced functions with new patterns, don't forget to
// enable the pattern in the power-assert compilation step in @ava/babel.
const withPowerAssert = (pattern, assertionFn) => powerAssert.empower(assertionFn, {
onError: event => {
if (event.powerAssertContext) {
event.error.statements = enhanceAssert.formatter(event.powerAssertContext);
event.error.statements = powerAssert.format(event.powerAssertContext, formatPowerAssertValue);
}
fail(event.error);
@ -835,21 +837,38 @@ class Assertions {
pass();
});
this.assert = withSkip(withPowerAssert(
'assert(value, [message])',
(actual, message) => {
checkMessage('assert', message, true);
if (powerAssert === undefined) {
this.assert = withSkip((actual, message) => {
if (!checkMessage('assert', message)) {
return;
}
if (!actual) {
throw new AssertionError({
fail(new AssertionError({
assertion: 'assert',
message,
operator: '!!',
values: [formatWithLabel('Value is not truthy:', actual)]
});
}));
}
})
);
});
} else {
this.assert = withSkip(withPowerAssert(
'assert(value, [message])',
(actual, message) => {
checkMessage('assert', message, true);
if (!actual) {
throw new AssertionError({
assertion: 'assert',
message,
operator: '!!',
values: [formatWithLabel('Value is not truthy:', actual)]
});
}
})
);
}
}
}
exports.Assertions = Assertions;

View file

@ -1,63 +1,25 @@
const pkg = require('../package.json');
module.exports = ({experiments, projectDir}) => {
module.exports = ({projectDir}) => {
const ava = {version: pkg.version};
const makeProvider = require('@ava/babel');
if (experiments.noBabelOutOfTheBox) {
let fatal;
const provider = makeProvider({
negotiateProtocol(identifiers) {
if (!identifiers.includes('noBabelOutOfTheBox')) {
fatal = new Error('TODO: Throw error when @ava/babel does not negotiate the expected protocol');
return null;
}
return {identifier: 'noBabelOutOfTheBox', ava, projectDir};
}
});
if (fatal) {
throw fatal;
}
return {
legacy: false,
...provider,
// Don't pass the legacy compileEnhancements value.
validateConfig: babelConfig => provider.validateConfig(babelConfig)
};
}
let fatal;
const negotiateProtocol = identifiers => {
if (!identifiers.includes('legacy')) {
fatal = new Error('TODO: Throw error when @ava/babel does not negotiate the expected protocol');
return null;
const provider = makeProvider({
negotiateProtocol(identifiers) {
// TODO: Settle on a identifier before releasing AVA@3; fix error message.
if (!identifiers.includes('noBabelOutOfTheBox')) {
fatal = new Error('TODO: Throw error when @ava/babel does not negotiate the expected protocol');
return null;
}
return {identifier: 'noBabelOutOfTheBox', ava, projectDir};
}
return {identifier: 'legacy', ava, projectDir};
};
const [full, enhancementsOnly] = [makeProvider({negotiateProtocol}), makeProvider({negotiateProtocol})];
});
if (fatal) {
throw fatal;
}
return {
legacy: true,
...full,
validateConfig(babelConfig, compileEnhancements) {
full.validateConfig({babelConfig, compileEnhancements, enhancementsOnly: false});
enhancementsOnly.validateConfig({compileEnhancements, enhancementsOnly: true});
},
get compileEnhancements() {
if (enhancementsOnly.isEnabled()) {
return enhancementsOnly.compile;
}
return null;
}
};
return provider;
};

View file

@ -232,7 +232,7 @@ exports.run = async () => { // eslint-disable-line complexity
console.log(chalk.magenta(` ${figures.warning} Experiments are enabled. These are unsupported and may change or be removed at any time.`));
}
if (experiments.noBabelOutOfTheBox && typeof conf.compileEnhancements === 'boolean') {
if (typeof conf.compileEnhancements === 'boolean') {
exit('Enhancement compilation must be configured in AVA’s Babel options');
}
@ -248,10 +248,10 @@ exports.run = async () => { // eslint-disable-line complexity
const validateEnvironmentVariables = require('./environment-variables');
let babelProvider;
if (!experiments.noBabelOutOfTheBox || conf.babel !== undefined) {
if (Reflect.has(conf, 'babel')) {
try {
babelProvider = babelManager({experiments, projectDir});
babelProvider.validateConfig(conf.babel, conf.compileEnhancements !== false);
babelProvider = babelManager({projectDir});
babelProvider.validateConfig(conf.babel);
} catch (error) {
exit(error.message);
}
@ -266,7 +266,7 @@ exports.run = async () => { // eslint-disable-line complexity
let extensions;
try {
extensions = normalizeExtensions(conf.extensions, babelProvider, {experiments});
extensions = normalizeExtensions(conf.extensions, babelProvider);
} catch (error) {
exit(error.message);
}
@ -313,7 +313,6 @@ exports.run = async () => { // eslint-disable-line complexity
babelProvider,
cacheEnabled: combined.cache !== false,
color: combined.color,
compileEnhancements: combined.compileEnhancements !== false,
concurrency: combined.concurrency || 0,
debug,
experiments,

View file

@ -1,23 +0,0 @@
'use strict';
const concordance = require('concordance');
const dotProp = require('dot-prop');
const generate = require('@babel/generator').default;
const concordanceOptions = require('./concordance-options').default;
const computeStatement = node => generate(node).code;
const getNode = (ast, path) => dotProp.get(ast, path.replace(/\//g, '.'));
const formatter = context => {
const ast = JSON.parse(context.source.ast);
const args = context.args[0].events;
return args
.map(arg => {
const node = getNode(ast, arg.espath);
const statement = computeStatement(node);
const formatted = concordance.format(arg.value, concordanceOptions);
return [statement, formatted];
})
.reverse();
};
module.exports.formatter = formatter;

View file

@ -1,47 +1,10 @@
const legacy = (enhancementsOnly, babelIsEnabled, babelOnly) => {
module.exports = (configuredExtensions = [], babelProvider = null) => {
const babelExtensions = babelProvider !== null && babelProvider.isEnabled() ? babelProvider.getExtensions() : [];
// Combine all extensions possible for testing. Remove duplicate extensions.
const duplicates = [];
const seen = new Set();
for (const ext of [...enhancementsOnly, ...babelOnly]) {
if (seen.has(ext)) {
duplicates.push(ext);
} else {
seen.add(ext);
}
}
// Decide if and where to add the default `js` extension. Keep in mind it's not
// added if extensions have been explicitly given.
if (!seen.has('js')) {
if (babelIsEnabled && babelOnly.length === 0) {
seen.add('js');
babelOnly.push('js');
}
if (!babelIsEnabled && enhancementsOnly.length === 0) {
seen.add('js');
enhancementsOnly.push('js');
}
} else if (babelIsEnabled && babelOnly.length === 0) {
// If Babel is not disabled, and has the default extensions (or, explicitly,
// no configured extensions), then the `js` extension must have come from
// the `enhancementsOnly` value. That's not allowed since it'd be a
// roundabout way of disabling Babel.
throw new Error('Cannot specify generic \'js\' extension without disabling AVA\'s Babel usage.');
}
if (duplicates.length > 0) {
throw new Error(`Unexpected duplicate extensions in options: '${duplicates.join('\', \'')}'.`);
}
return {all: [...seen], enhancementsOnly, babelOnly};
};
const noBabelOutOfTheBox = (extensions = [], babelOnly = []) => {
// Combine all extensions possible for testing. Remove duplicate extensions.
const duplicates = [];
const seen = new Set();
for (const ext of [...extensions, ...babelOnly]) {
for (const ext of [...configuredExtensions, ...babelExtensions]) {
if (seen.has(ext)) {
duplicates.push(ext);
} else {
@ -54,21 +17,10 @@ const noBabelOutOfTheBox = (extensions = [], babelOnly = []) => {
}
// Assume `babelOnly` would contain the `js` extension, so if it was not seen
// and `extensions` has not been explicitly given, default it to `js`.
if (!seen.has('js') && extensions === undefined) {
// and `extensions` is empty, default it to `js`.
if (!seen.has('js') && configuredExtensions.length === 0) {
seen.add('js');
}
return {all: [...seen], babelOnly};
};
module.exports = (configuredExtensions, babelProvider, {experiments = {}} = {}) => {
const babelIsEnabled = babelProvider !== undefined && babelProvider.isEnabled();
const babelExtensions = babelIsEnabled ? babelProvider.getExtensions() : [];
if (experiments.noBabelOutOfTheBox) {
return noBabelOutOfTheBox(configuredExtensions, babelExtensions);
}
return legacy(configuredExtensions || [], babelIsEnabled, babelExtensions);
return {all: [...seen], babelOnly: babelExtensions};
};

View file

@ -6,7 +6,7 @@ const pkgConf = require('pkg-conf');
const NO_SUCH_FILE = Symbol('no ava.config.js file');
const MISSING_DEFAULT_EXPORT = Symbol('missing default export');
const EXPERIMENTS = new Set(['noBabelOutOfTheBox', 'tryAssertion']);
const EXPERIMENTS = new Set(['tryAssertion']);
function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) { // eslint-disable-line complexity
let packageConf = pkgConf.sync('ava', {cwd: resolveFrom});

View file

@ -17,6 +17,7 @@ class Runner extends Emittery {
this.failWithoutAssertions = options.failWithoutAssertions !== false;
this.file = options.file;
this.match = options.match || [];
this.powerAssert = undefined; // Assigned later.
this.projectDir = options.projectDir;
this.recordNewSnapshots = options.recordNewSnapshots === true;
this.runOnlyExclusive = options.runOnlyExclusive === true;
@ -276,6 +277,7 @@ class Runner extends Emittery {
compareTestSnapshot: this.boundCompareTestSnapshot,
updateSnapshots: this.updateSnapshots,
metadata: task.metadata,
powerAssert: this.powerAssert,
title: `${task.title}${titleSuffix || ''}`
}));
const outcome = await this.runMultiple(hooks, this.serial);
@ -317,6 +319,7 @@ class Runner extends Emittery {
compareTestSnapshot: this.boundCompareTestSnapshot,
updateSnapshots: this.updateSnapshots,
metadata: task.metadata,
powerAssert: this.powerAssert,
title: task.title,
registerUniqueTitle: this.registerUniqueTitle
});

View file

@ -40,7 +40,8 @@ class ExecutionContext extends assert.Assertions {
},
compareWithSnapshot: options => {
return test.compareWithSnapshot(options);
}
},
powerAssert: test.powerAssert
});
testMap.set(this, test);
@ -193,6 +194,7 @@ class Test {
this.failWithoutAssertions = options.failWithoutAssertions;
this.fn = options.fn;
this.metadata = options.metadata;
this.powerAssert = options.powerAssert;
this.title = options.title;
this.registerUniqueTitle = options.registerUniqueTitle;
this.logs = [];

View file

@ -104,11 +104,19 @@ ipc.options.then(options => {
// Store value in case to prevent required modules from modifying it.
const testPath = options.file;
// Install basic source map support.
const sourceMapSupport = require('source-map-support');
sourceMapSupport.install({
environment: 'node',
handleUncaughtExceptions: false
});
// Install before processing options.require, so if helpers are added to the
// require configuration the *compiled* helper will be loaded.
if (options.babelState !== null) {
const {experiments, projectDir} = options;
const babelProvider = babelManager({experiments, projectDir});
const {projectDir} = options;
const babelProvider = babelManager({projectDir});
runner.powerAssert = babelProvider.powerAssert;
babelProvider.installHook(options.babelState);
}

752
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -57,8 +57,6 @@
"typescript"
],
"dependencies": {
"@ava/babel": "^0.1.0",
"@babel/generator": "^7.7.7",
"@concordance/react": "^2.0.0",
"ansi-escapes": "^4.3.0",
"ansi-styles": "^4.2.0",
@ -80,9 +78,7 @@
"currently-unhandled": "^0.4.1",
"debug": "^4.1.1",
"del": "^5.1.0",
"dot-prop": "^5.2.0",
"emittery": "^0.5.1",
"empower-core": "^1.2.0",
"equal-length": "^1.0.0",
"escape-string-regexp": "^2.0.0",
"esm": "^3.2.25",
@ -111,6 +107,7 @@
"pretty-ms": "^5.1.0",
"resolve-cwd": "^3.0.0",
"slash": "^3.0.0",
"source-map-support": "^0.5.16",
"stack-utils": "^2.0.1",
"strip-ansi": "^6.0.0",
"supertap": "^1.0.0",
@ -123,6 +120,7 @@
"yargs": "^15.0.2"
},
"devDependencies": {
"@ava/babel": "^0.2.0",
"@babel/core": "^7.7.7",
"@types/node": "^10.17.11",
"cli-table3": "^0.5.1",
@ -139,7 +137,6 @@
"signal-exit": "^3.0.0",
"sinon": "^7.5.0",
"source-map-fixtures": "^2.1.0",
"source-map-support": "^0.5.16",
"tap": "^14.10.5",
"temp-write": "^4.0.0",
"touch": "^3.1.0",

View file

@ -25,7 +25,7 @@ Translations: [Español](https://github.com/avajs/ava-docs/blob/master/es_ES/rea
- Includes TypeScript definitions
- [Magic assert](#magic-assert)
- [Isolated environment for each test file](./docs/01-writing-tests.md#process-isolation)
- [Write your tests using the latest JavaScript syntax](#latest-javascript-support)
- [Write your tests using the latest JavaScript syntax](https://github.com/avajs/babel)
- [Promise support](./docs/01-writing-tests.md#promise-support)
- [Async function support](./docs/01-writing-tests.md#async-function-support)
- [Observable support](./docs/01-writing-tests.md#observable-support)
@ -121,16 +121,6 @@ AVA adds code excerpts and clean diffs for actual and expected values. If values
AVA automatically removes unrelated lines in stack traces, allowing you to find the source of an error much faster, as seen above.
### Latest JavaScript support
AVA uses [Babel 7](https://babeljs.io) so you can use the latest JavaScript syntax in your tests. There is no extra setup required. You don't need to be using Babel in your own project for this to work either.
We aim to support all [finished syntax proposals](https://github.com/tc39/proposals/blob/master/finished-proposals.md), as well as all syntax from ratified JavaScript versions (e.g. ES2017). See our [`@ava/stage-4`](https://github.com/avajs/babel-preset-stage-4) preset for the currently supported proposals.
Please note that we do not add or modify built-ins. For example, if you use [`Object.fromEntries()`](https://github.com/tc39/proposal-object-from-entries) in your tests, they will crash in Node.js 10 which does not implement this method.
You can disable this syntax support, or otherwise customize AVA's Babel pipeline. See our [Babel recipe] for more details.
### Parallel runs in CI
AVA automatically detects whether your CI environment supports parallel builds. Each build will run a subset of all test files, while still making sure all tests get executed. See the [`ci-parallel-vars`](https://www.npmjs.com/package/ci-parallel-vars) package for a list of supported CI environments.
@ -161,7 +151,7 @@ We have a growing list of [common pitfalls](docs/08-common-pitfalls.md) you may
- [Browser testing](docs/recipes/browser-testing.md)
- [TypeScript](docs/recipes/typescript.md)
- [Flow](docs/recipes/flow.md)
- [Configuring Babel][Babel recipe]
- [Configuring Babel](https://github.com/avajs/babel)
- [Using ES modules](docs/recipes/es-modules.md)
- [Passing arguments to your test files](docs/recipes/passing-arguments-to-your-test-files.md)
- [Testing React components](docs/recipes/react.md)
@ -243,5 +233,3 @@ It's the [Andromeda galaxy](https://simple.wikipedia.org/wiki/Andromeda_galaxy).
<br>
<br>
</div>
[Babel recipe]: docs/recipes/babel.md

View file

@ -1 +0,0 @@
module.exports = require('@ava/babel/stage-4');

View file

@ -1,7 +1,6 @@
'use strict';
require('../lib/chalk').set();
const assert = require('assert');
const path = require('path');
const fs = require('fs');
const del = require('del');
@ -10,71 +9,25 @@ const Api = require('../lib/api');
const babelManager = require('../lib/babel-manager');
const {normalizeGlobs} = require('../lib/globs');
const testCapitalizerPlugin = require.resolve('./fixture/babel-plugin-test-capitalizer');
const ROOT_DIR = path.join(__dirname, '..');
function withNodeEnv(value, run) {
assert(!('NODE_ENV' in process.env));
process.env.NODE_ENV = value;
const reset = () => {
delete process.env.NODE_ENV;
};
const promise = new Promise(resolve => {
resolve(run());
});
promise.then(reset, reset);
return promise;
}
function apiCreator(options = {}) {
options.projectDir = options.projectDir || ROOT_DIR;
options.babelProvider = babelManager({experiments: {}, projectDir: options.projectDir});
options.babelProvider.validateConfig(options.babelConfig, options.compileEnhancements !== false);
if (options.babelConfig !== undefined) {
options.babelProvider = babelManager({projectDir: options.projectDir});
options.babelProvider.validateConfig(options.babelConfig);
}
options.concurrency = 2;
options.extensions = options.extensions || {all: ['js'], enhancementsOnly: [], babelOnly: ['js']};
options.experiments = {};
options.globs = normalizeGlobs(options.files, options.helpers, options.sources, options.extensions.all);
options.resolveTestsFrom = options.resolveTestsFrom || options.projectDir;
const instance = new Api(options);
if (!options.precompileHelpers) {
instance._precompileHelpers = () => Promise.resolve();
}
return instance;
}
test('ES2015 support', t => {
const api = apiCreator();
return api.run([path.join(__dirname, 'fixture/es2015.js')])
.then(runStatus => {
t.is(runStatus.stats.passedTests, 1);
});
});
test('precompile helpers', t => {
const api = apiCreator({
precompileHelpers: true,
resolveTestsFrom: path.join(__dirname, 'fixture/precompile-helpers')
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 1);
});
});
test('async/await support', t => {
const api = apiCreator();
return api.run([path.join(__dirname, 'fixture/async-await.js')])
.then(runStatus => {
t.is(runStatus.stats.passedTests, 2);
});
});
test('test.meta.file', t => {
const api = apiCreator();
@ -367,7 +320,7 @@ test('stack traces for exceptions are corrected using a source map file', t => {
plan.status.on('stateChange', evt => {
if (evt.type === 'uncaught-exception') {
t.match(evt.err.message, /Thrown by source-map-fixtures/);
t.match(evt.err.stack, /^.*?Object\.run\b.*source-map-fixtures.src.throws.js:1.*$/m);
t.match(evt.err.stack, /^.*?\brun\b.*source-map-fixtures.src.throws.js:1.*$/m);
t.match(evt.err.stack, /^.*?Immediate\b.*source-map-file.js:4.*$/m);
}
});
@ -379,33 +332,6 @@ test('stack traces for exceptions are corrected using a source map file', t => {
});
});
test('babel.testOptions can disable sourceMaps', t => {
t.plan(3);
const api = apiCreator({
babelConfig: {
testOptions: {
sourceMaps: false
}
},
cacheEnabled: true
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'uncaught-exception') {
t.match(evt.err.message, /Thrown by source-map-fixtures/);
t.match(evt.err.stack, /^.*?Immediate\b.*source-map-file.js:7.*$/m);
}
});
});
return api.run([path.join(__dirname, 'fixture/source-map-file.js')])
.then(runStatus => {
t.is(runStatus.stats.passedTests, 1);
});
});
test('stack traces for exceptions are corrected using a source map file in what looks like a browser env', t => {
t.plan(4);
@ -417,7 +343,7 @@ test('stack traces for exceptions are corrected using a source map file in what
plan.status.on('stateChange', evt => {
if (evt.type === 'uncaught-exception') {
t.match(evt.err.message, /Thrown by source-map-fixtures/);
t.match(evt.err.stack, /^.*?Object\.run\b.*source-map-fixtures.src.throws.js:1.*$/m);
t.match(evt.err.stack, /^.*?\brun\b.*source-map-fixtures.src.throws.js:1.*$/m);
t.match(evt.err.stack, /^.*?Immediate\b.*source-map-file-browser-env.js:7.*$/m);
}
});
@ -453,7 +379,7 @@ test('enhanced assertion formatting necessary whitespace and empty strings', t =
];
t.plan(15);
const api = apiCreator();
const api = apiCreator({babelConfig: true});
const errors = [];
api.on('run', plan => {
plan.status.on('stateChange', evt => {
@ -486,7 +412,7 @@ test('stack traces for exceptions are corrected using a source map file (cache o
plan.status.on('stateChange', evt => {
if (evt.type === 'uncaught-exception') {
t.match(evt.err.message, /Thrown by source-map-fixtures/);
t.match(evt.err.stack, /^.*?Object\.run\b.*source-map-fixtures.src.throws.js:1.*$/m);
t.match(evt.err.stack, /^.*?\brun\b.*source-map-fixtures.src.throws.js:1.*$/m);
t.match(evt.err.stack, /^.*?Immediate\b.*source-map-file.js:4.*$/m);
}
});
@ -509,7 +435,7 @@ test('stack traces for exceptions are corrected using a source map, taking an in
plan.status.on('stateChange', evt => {
if (evt.type === 'uncaught-exception') {
t.match(evt.err.message, /Thrown by source-map-fixtures/);
t.match(evt.err.stack, /^.*?Object\.t.*?\[?as run\]?\b.*source-map-fixtures.src.throws.js:1.*$/m);
t.match(evt.err.stack, /^.*?\brun\b.*source-map-fixtures.src.throws.js:1.*$/m);
t.match(evt.err.stack, /^.*?Immediate\b.*source-map-initial-input.js:14.*$/m);
}
});
@ -532,7 +458,7 @@ test('stack traces for exceptions are corrected using a source map, taking an in
plan.status.on('stateChange', evt => {
if (evt.type === 'uncaught-exception') {
t.match(evt.err.message, /Thrown by source-map-fixtures/);
t.match(evt.err.stack, /^.*?Object\.t.*?\[?as run\]?\b.*source-map-fixtures.src.throws.js:1.*$/m);
t.match(evt.err.stack, /^.*?\brun\b.*source-map-fixtures.src.throws.js:1.*$/m);
t.match(evt.err.stack, /^.*?Immediate\b.*source-map-initial-input.js:14.*$/m);
}
});
@ -616,6 +542,7 @@ test('caching is enabled by default', t => {
del.sync(path.join(__dirname, 'fixture/caching/node_modules'));
const api = apiCreator({
babelConfig: true,
projectDir: path.join(__dirname, 'fixture/caching')
});
@ -716,442 +643,6 @@ test('verify test count', t => {
});
});
test('babel.testOptions with a custom plugin', t => {
t.plan(2);
const api = apiCreator({
babelConfig: {
testOptions: {
plugins: [testCapitalizerPlugin]
}
},
cacheEnabled: false,
projectDir: __dirname
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.is(evt.title, 'FOO');
}
});
});
return api.run([path.join(__dirname, 'fixture/babelrc/test.js')])
.then(runStatus => {
t.is(runStatus.stats.passedTests, 1);
}, t.threw);
});
test('babel.testOptions.babelrc effectively defaults to true', t => {
t.plan(3);
const api = apiCreator({
projectDir: path.join(__dirname, 'fixture/babelrc')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.ok((evt.title === 'foo') || (evt.title === 'repeated test: foo'));
}
});
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 2);
});
});
test('babel.testOptions.babelrc can explicitly be true', t => {
t.plan(3);
const api = apiCreator({
babelConfig: {
testOptions: {babelrc: true}
},
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/babelrc')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.ok(evt.title === 'foo' || evt.title === 'repeated test: foo');
}
});
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 2);
});
});
test('babel.testOptions.babelrc can explicitly be false', t => {
t.plan(2);
const api = apiCreator({
babelConfig: {
testOptions: {babelrc: false}
},
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/babelrc')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.is(evt.title, 'foo');
}
});
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 1);
});
});
test('babel.testOptions merges plugins with .babelrc', t => {
t.plan(3);
const api = apiCreator({
babelConfig: {
testOptions: {
babelrc: true,
plugins: [testCapitalizerPlugin]
}
},
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/babelrc')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.ok(evt.title === 'FOO' || evt.title === 'repeated test: foo');
}
});
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 2);
});
});
test('babel.testOptions.babelrc (when true) picks up .babelrc.js files', t => {
t.plan(3);
const api = apiCreator({
babelConfig: {
testOptions: {
babelrc: true
}
},
projectDir: path.join(__dirname, 'fixture/babelrc-js')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.ok((evt.title === 'foo') || (evt.title === 'repeated test: foo'));
}
});
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 2);
});
});
test('babel.testOptions.configFile effectively defaults to true', t => {
t.plan(3);
const api = apiCreator({
projectDir: path.join(__dirname, 'fixture/babel-config')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.ok((evt.title === 'foo') || (evt.title === 'repeated test: foo'));
}
});
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 2);
});
});
test('babel.testOptions.configFile can explicitly be true', t => {
t.plan(3);
const api = apiCreator({
babelConfig: {
testOptions: {configFile: true}
},
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/babel-config')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.ok(evt.title === 'foo' || evt.title === 'repeated test: foo');
}
});
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 2);
});
});
test('babel.testOptions.configFile can explicitly be false', t => {
t.plan(2);
const api = apiCreator({
babelConfig: {
testOptions: {configFile: false}
},
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/babel-config')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.is(evt.title, 'foo');
}
});
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 1);
});
});
test('babel.testOptions merges plugins with babel.config.js', t => {
t.plan(3);
const api = apiCreator({
babelConfig: {
testOptions: {
babelrc: true,
plugins: [testCapitalizerPlugin]
}
},
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/babel-config')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.ok(evt.title === 'FOO' || evt.title === 'repeated test: foo');
}
});
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 2);
});
});
test('babel.testOptions can disable ava/stage-4', t => {
t.plan(1);
const api = apiCreator({
babelConfig: {
testOptions: {
babelrc: false,
presets: [[require.resolve('../stage-4'), false]]
}
},
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/babelrc')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'uncaught-exception') {
t.is(evt.err.name, 'SyntaxError');
}
});
});
return api.run();
});
test('babel.testOptions with extends still merges plugins with .babelrc', t => {
t.plan(3);
const api = apiCreator({
babelConfig: {
testOptions: {
plugins: [testCapitalizerPlugin],
extends: path.join(__dirname, 'fixture/babelrc/.alt-babelrc')
}
},
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/babelrc')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.ok(evt.title === 'BAR' || evt.title === 'repeated test: bar');
}
});
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 2);
});
});
test('babel.testOptions with extends still merges plugins with babel.config.js', t => {
t.plan(3);
const api = apiCreator({
babelConfig: {
testOptions: {
plugins: [testCapitalizerPlugin],
extends: path.join(__dirname, 'fixture/babel-config/.alt-babelrc')
}
},
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/babel-config')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.ok(evt.title === 'BAR' || evt.title === 'repeated test: bar');
}
});
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 2);
});
});
test('extended config can disable ava/stage-4', t => {
t.plan(1);
const api = apiCreator({
babelConfig: {
testOptions: {
babelrc: false,
extends: path.join(__dirname, 'fixture/babelrc/disable-stage-4.babelrc')
}
},
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/babelrc')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'uncaught-exception') {
t.is(evt.err.name, 'SyntaxError');
}
});
});
return api.run();
});
test('babel can be disabled for particular files', t => {
t.plan(1);
const api = apiCreator({
babelConfig: {
testOptions: {
babelrc: false,
ignore: [path.join(__dirname, 'fixture/babelrc/test.js')]
}
},
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/babelrc')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'uncaught-exception') {
t.is(evt.err.name, 'SyntaxError');
}
});
});
return api.run();
});
test('uses "development" Babel environment if NODE_ENV is the empty string', t => {
t.plan(2);
const api = apiCreator({
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/babelrc')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.is(evt.title, 'FOO');
}
});
});
return withNodeEnv('', () => api.run())
.then(runStatus => {
t.is(runStatus.stats.passedTests, 1);
});
});
test('babelOnly extensions take precedence over enhancements-only', t => {
t.plan(2);
const api = apiCreator({
babelConfig: {
testOptions: {
plugins: [testCapitalizerPlugin]
}
},
extensions: {
all: ['foo.bar', 'bar'],
enhancementsOnly: ['bar'],
babelOnly: ['foo.bar']
},
cacheEnabled: false,
projectDir: path.join(__dirname, 'fixture/extensions')
});
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'test-passed') {
t.ok(evt.title === 'FOO');
}
});
});
return api.run()
.then(runStatus => {
t.is(runStatus.stats.passedTests, 1);
});
});
test('using --match with matching tests will only report those passing tests', t => {
t.plan(3);

View file

@ -1,13 +0,0 @@
import test from '../..';
test('async function', async t => {
t.plan(1);
const value = await Promise.resolve(1);
t.is(value, 1);
});
test('arrow async function', async t => {
t.plan(1);
const value = await Promise.resolve(1);
t.is(value, 1);
});

View file

@ -1,4 +1,4 @@
import test from 'ava';
const test = require('ava');
test('test', t => {
t.pass();

View file

@ -1,3 +0,0 @@
{
"plugins": ["../babel-plugin-foo-to-bar"]
}

View file

@ -1,11 +0,0 @@
module.exports = {
presets: ['@ava/stage-4'],
env: {
development: {
plugins: ['../babel-plugin-test-capitalizer']
},
test: {
plugins: ['../babel-plugin-test-doubler']
}
}
};

View file

@ -1,4 +0,0 @@
{
"name": "application-name",
"version": "0.0.1"
}

View file

@ -1,11 +0,0 @@
import test from '../../..';
test('foo', t => {
// Using optional catch-binding to ensure it transpiles on Node.js 8, since this
// is a Node.js 10 feature
try {
throw new Error('test');
} catch {
t.pass();
}
});

View file

@ -1 +0,0 @@
export default () => {};

View file

@ -1 +0,0 @@
import './babel-hook-imported'; // eslint-disable-line import/no-unassigned-import

View file

@ -1 +0,0 @@
module.exports = () => ({});

View file

@ -1,22 +0,0 @@
'use strict';
function isRequire(path) {
return path.isCallExpression() && path.get('callee').isIdentifier() && (path.get('callee').node.name === 'require');
}
module.exports = babel => {
const t = babel.types;
return {
visitor: {
CallExpression: path => {
// Skip require calls
const firstArg = path.get('arguments')[0];
if (!isRequire(path) && firstArg && firstArg.isStringLiteral() && /foo/i.test(firstArg.node.value)) {
firstArg.replaceWith(t.stringLiteral(firstArg.node.value.replace('foo', 'bar').replace('FOO', 'BAR')));
}
}
}
};
};

View file

@ -1,22 +0,0 @@
'use strict';
function isRequire(path) {
return path.isCallExpression() && path.get('callee').isIdentifier() && (path.get('callee').node.name === 'require');
}
module.exports = babel => {
const t = babel.types;
return {
visitor: {
CallExpression: path => {
// Skip require calls
const firstArg = path.get('arguments')[0];
if (!isRequire(path) && firstArg && firstArg.isStringLiteral() && !firstArg.node.value.includes('repeated test')) {
firstArg.replaceWith(t.stringLiteral(firstArg.node.value.toUpperCase()));
}
}
}
};
};

View file

@ -1,49 +0,0 @@
/* eslint-disable new-cap */
'use strict';
/*
A Babel plugin that causes each AVA test to be duplicated with a new title.
test('foo', t => {});
becomes
test('foo', t => {});
test('repeated test: foo', t => {});
This is used by some integration tests to validate correct handling of Babel config options.
*/
module.exports = babel => {
const t = babel.types;
let anonCount = 1;
return {
visitor: {
CallExpression: path => {
const {node} = path;
const {callee} = node;
let args = node.arguments;
if (callee.type === 'Identifier' && callee.name === 'test') {
if (args.length === 1) {
args = [t.StringLiteral(`repeated test: anonymous${anonCount++}`), args[0]];
} else if (args.length === 2 && args[0].type === 'StringLiteral') {
if (args[0].value.startsWith('repeated test')) {
return;
}
args = args.slice();
args[0] = t.StringLiteral(`repeated test: ${args[0].value}`);
} else {
throw new Error('The plugin does not know how to handle this call to test');
}
path.insertAfter(t.CallExpression(
t.Identifier('test'),
args
));
}
}
}
};
};

View file

@ -1,7 +0,0 @@
module.exports = api => {
api.cache.forever();
return {
'plugins': ['../babel-plugin-test-doubler'],
'presets': ['@ava/stage-4']
};
};

View file

@ -1,4 +0,0 @@
{
"name": "application-name",
"version": "0.0.1"
}

View file

@ -1,11 +0,0 @@
import test from '../../..';
test('foo', t => {
// Using optional catch-binding to ensure it transpiles on Node.js 8, since this
// is a Node.js 10 feature
try {
throw new Error('test');
} catch {
t.pass();
}
});

View file

@ -1,3 +0,0 @@
{
"plugins": ["../babel-plugin-foo-to-bar"]
}

View file

@ -1,11 +0,0 @@
{
"presets": ["@ava/stage-4"],
"env": {
"development": {
"plugins": ["../babel-plugin-test-capitalizer"]
},
"test": {
"plugins": ["../babel-plugin-test-doubler"],
}
}
}

View file

@ -1,3 +0,0 @@
{
"presets": [["../../../stage-4", false]]
}

View file

@ -1,4 +0,0 @@
{
"name": "application-name",
"version": "0.0.1"
}

View file

@ -1,11 +0,0 @@
import test from '../../..';
test('foo', t => {
// Using optional catch-binding to ensure it transpiles on Node.js 8, since this
// is a Node.js 10 feature
try {
throw new Error('test');
} catch {
t.pass();
}
});

View file

@ -1,4 +1,4 @@
import test from '../../..';
const test = require('../../..');
test('test', t => {
t.true(2 + 2 === 4);

View file

@ -1,4 +1,4 @@
import test from '../../..';
const test = require('../../..');
test('works', t => {
t.pass();

View file

@ -1,3 +0,0 @@
import test from '../../../../../..';
test('ok', t => t.pass());

View file

@ -1,4 +1,4 @@
import test from '../..';
const test = require('../..');
const foo = 'foo';

View file

@ -1,5 +1,5 @@
import test from '../../..';
import {name, value} from '.';
const test = require('../../..');
const {name, value} = require('.');
test('works', t => {
t.is(process.env[name], value);

View file

@ -1,4 +1,4 @@
import test from '../..';
const test = require('../..');
const getAnonymousFn = () => () => {
throw new Error(); // eslint-disable-line unicorn/error-message

View file

@ -1,8 +0,0 @@
import test from '../..';
test('test', t => {
t.pass();
});
// eslint-disable-next-line spaced-comment
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImVzMjAxNS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLElBQUksTUFBTSxRQUFRLENBQUM7O0FBRTFCLElBQUksQ0FBQyxDQUFDLElBQUk7QUFDVCxFQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7Q0FDVCxDQUFDLENBQUMiLCJmaWxlIjoiZXMyMDE1LXNvdXJjZS1tYXBzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHRlc3QgZnJvbSAnLi4vLi4vJztcblxudGVzdCh0ID0+IHtcblx0dC5wYXNzKCk7XG59KTtcbiJdfQ==

View file

@ -1,4 +1,4 @@
import test from '../..';
const test = require('../..');
test('test', t => {
t.pass();

View file

@ -1,5 +1,4 @@
export default {
babel: false,
extensions: ['foo'],
files: ['tests/**/*'],
helpers: ['helpers/*']

View file

@ -1,4 +1,4 @@
import test from '../../..';
const test = require('../../..');
const one = {one: 1};
const two = {two: 2};

View file

@ -1,3 +1,3 @@
import '../../../..'; // eslint-disable-line import/no-unassigned-import
require('../../../..'); // eslint-disable-line import/no-unassigned-import
process.exit(1); // eslint-disable-line unicorn/no-process-exit

View file

@ -1,4 +1,4 @@
import test from '../../../..';
const test = require('../../../..');
test('first pass', t => {
t.pass();

View file

@ -1,4 +1,4 @@
import test from '../../../..';
const test = require('../../../..');
test('first pass', t => {
t.pass();

View file

@ -1,4 +1,4 @@
import test from '../../../..';
const test = require('../../../..');
test.serial('first pass', t => {
t.pass();

View file

@ -1,4 +1,4 @@
import test from '../../../..';
const test = require('../../../..');
test('first pass', t => {
t.pass();

View file

@ -1,4 +1,4 @@
import test from '../../../..';
const test = require('../../../..');
test('first pass', t => {
t.pass();

View file

@ -1,4 +1,4 @@
import test from '../../../..';
const test = require('../../../..');
test.cb('slow pass', t => {
setTimeout(t.end, 1000);

View file

@ -1,4 +1,4 @@
import test from '../../../..';
const test = require('../../../..');
test('first pass', t => {
t.pass();

View file

@ -1,3 +1,3 @@
import test from '../../../..';
const test = require('../../../..');
test('pass', t => t.pass());

View file

@ -1,4 +1,4 @@
import test from '../../../..';
const test = require('../../../..');
setTimeout(() => {
test.serial('pass', t => t.pass());

View file

@ -1,4 +1,4 @@
import test from '../..';
const test = require('../..');
test('test', t => {
t.deepEqual({foo: 1}, {foo: 2});

View file

@ -1,336 +0,0 @@
import React from 'react';
import test from '../..';
import HelloMessage from './hello-message';
// Older AVA versions that do not use Concordance don't handle globals very
// well. Use this so formatting output can be contrasted between versions.
const formatGlobals = Boolean(require(process.env.AVA_PATH + '/package.json').dependencies.concordance);
test('date formatted', t => {
const date = new Date('1969-07-20T20:17:40.000Z');
t.true(date);
});
test('invalid date formatted', t => {
const date = new Date('🙀');
t.true(date);
});
test('date formatted, subclass', t => {
class Foo extends Date {}
const date = new Foo('1969-07-20T20:17:40.000Z');
t.true(date);
});
test('date diff', t => {
t.deepEqual(new Date('1969-07-20T20:17:40.000Z'), new Date());
});
test('date diff, extra properties', t => {
t.deepEqual(new Date('1969-07-20T20:17:40.000Z'), Object.assign(new Date('1969-07-20T20:17:40.000Z'), {
foo: 'bar'
}));
});
test('error formatted', t => {
const err = new Error('Houston, we have a problem');
t.true(err);
});
test('error formatted, constructor does not match name', t => {
const err = Object.assign(new Error('Houston, we have a problem'), {name: 'FamousWords'});
t.true(err);
});
test('error formatted, constructor does not match name, and string tag does not match constructor', t => {
class CustomError extends Error {
constructor(message) {
super(message);
this.name = 'FamousWords';
}
}
const err = new CustomError('Houston, we have a problem');
t.true(err);
});
test('error formatted, no name or constructor', t => {
class CustomError extends Error {
constructor(message) {
super(message);
this.name = '';
}
}
const err = new CustomError('Houston, we have a problem');
Object.defineProperty(err, 'constructor', {});
t.true(err);
});
test('error diff, message', t => {
t.deepEqual(new Error('Houston, we have a problem'), new Error('One small step'));
});
test('error diff, constructor', t => {
t.deepEqual(new Error('Houston, we have a problem'), new RangeError('One small step'));
});
test('error diff, extra properties', t => {
t.deepEqual(new Error('Houston, we have a problem'), Object.assign(new Error('Houston, we have a problem'), {
date: new Date('1969-07-20T20:17:40.000Z')
}));
});
test('error thrown in test', () => {
throw Object.assign(new Error('Houston, we have a problem'), {
date: new Date('1969-07-20T20:17:40.000Z')
});
});
test.cb('callback test ended with error', t => {
t.end(Object.assign(new Error('Houston, we have a problem'), {
date: new Date('1969-07-20T20:17:40.000Z')
}));
});
test('error thrown in test due to improper throws', t => {
const improper = () => {
throw Object.assign(new Error('Houston, we have a problem'), {
date: new Date('1969-07-20T20:17:40.000Z')
});
};
t.throws(improper());
});
test('test returned rejected promise', () => {
return Promise.reject(Object.assign(new Error('Houston, we have a problem'), {
date: new Date('1969-07-20T20:17:40.000Z')
}));
});
test('array of strings formatted', t => {
const arr = ['foo'];
t.true(arr);
});
test('array of strings diff', t => {
t.deepEqual(['foo'], ['bar']);
});
test('string formatted', t => {
t.true('foo');
});
test('string diff', t => {
t.is('foo', 'bar');
});
test('string diff, with overlap', t => {
t.is('foobar', 'bar');
});
test('multiline string diff, with overlap at start', t => {
t.is('foo\nbar', 'foo\nbaz');
});
test('multiline string diff, with overlap at end', t => {
t.is('bar\nbaz', 'foo\nbaz');
});
test('map formatted', t => {
const map = new Map([['foo', 'bar']]);
t.true(map);
});
test('map diff', t => {
t.deepEqual(new Map([['foo', 'bar']]), new Map([['baz', 'qux']]));
});
test('map diff, extra properties', t => {
t.deepEqual(new Map([['foo', 'bar']]), Object.assign(new Map([['foo', 'bar']]), {baz: 'qux'}));
});
test('function formatted', t => {
const fn = function foo() {}; // eslint-disable-line func-name-matching, func-names
t.true(fn);
});
test('function diff', t => {
function foo() {}
function bar() {}
t.deepEqual(foo, bar);
});
test('function diff, extra properties', t => {
function foo() {}
function bar() {}
t.deepEqual(foo, Object.assign(bar, {baz: 'qux'}));
});
test('anonymous function', t => {
t.true(() => {});
});
test('generator function', t => {
t.true(function * foo() {}); // eslint-disable-line func-names
});
/* eslint-disable prefer-rest-params */
test('arguments formatted', t => {
const args = (function () {
return arguments;
})('foo');
t.true(args);
});
test('arguments diff', t => {
const foo = (function () {
return arguments;
})('foo');
const bar = (function () {
return arguments;
})('bar');
t.deepEqual(foo, bar);
});
test('arguments diff with normal array', t => {
const foo = (function () {
return arguments;
})('foo');
t.deepEqual(foo, ['bar']);
});
/* eslint-enable prefer-rest-params */
if (formatGlobals) {
test('global formatted', t => {
t.true(global);
});
test('global diff', t => {
t.deepEqual(global, {});
});
}
test('object formatted', t => {
const obj = {
foo: 'bar'
};
t.true(obj);
});
test('object diff', t => {
t.deepEqual({
foo: 'bar'
}, {
baz: 'qux'
});
});
test('object formatted, custom class', t => {
class Foo {}
const obj = new Foo();
t.true(obj);
});
test('object formatted, no constructor', t => {
class Foo {}
const obj = new Foo();
Object.defineProperty(obj, 'constructor', {});
t.true(obj);
});
test('object formatted, non-Object string tag that does not match constructor', t => {
class Foo extends Array {}
const obj = new Foo();
t.true(obj);
});
test('promise formatted', t => {
const promise = Promise.resolve();
t.true(promise);
});
test('promise diff', t => {
t.deepEqual(Promise.resolve(), Promise.resolve());
});
test('promise diff, extra properties', t => {
t.deepEqual(Promise.resolve(), Object.assign(Promise.resolve(), {foo: 'bar'}));
});
test('regexp formatted', t => {
const regexp = /foo/gi;
t.true(regexp);
});
test('regexp diff', t => {
t.deepEqual(/foo/gi, /bar/gi);
});
test('regexp diff, extra properties', t => {
t.deepEqual(/foo/gi, Object.assign(/foo/gi, {baz: 'qux'}));
});
test('set formatted', t => {
const set = new Set([{foo: 'bar'}]);
t.true(set);
});
test('set diff, string values', t => {
t.deepEqual(new Set(['foo']), new Set(['bar']));
});
test('set diff, object values', t => {
t.deepEqual(new Set([{foo: 'bar'}]), new Set([{bar: 'baz'}]));
});
test('set diff, distinct values', t => {
t.deepEqual(new Set([{foo: 'bar'}]), new Set([null]));
});
test('set diff, extra properties', t => {
t.deepEqual(new Set([{foo: 'bar'}]), Object.assign(new Set([{foo: 'bar'}]), {baz: 'qux'}));
});
test('buffer formatted', t => {
const buffer = Buffer.from('decafba'.repeat(12), 'hex');
t.true(buffer);
});
test('buffer diff', t => {
t.deepEqual(Buffer.from('decafba'.repeat(12), 'hex'), Buffer.from('baddecaf', 'hex'));
});
test('buffer diff, extra properties', t => {
t.deepEqual(Buffer.from('decafba'.repeat(12), 'hex'), Object.assign(Buffer.from('decafba'.repeat(12), 'hex'), {foo: 'bar'}));
});
test('primitives', t => {
const primitives = [
true,
false,
null,
0,
-0,
42,
Infinity,
-Infinity,
NaN,
'foo',
'foo\nbar',
Symbol.iterator,
Symbol.for('foo'),
Symbol('bar'),
undefined
];
t.true(primitives);
});
test('circular references', t => {
const obj = {};
obj.circular = obj;
t.true(obj);
});
test('react element, formatted', t => {
const element = React.createElement(HelloMessage, {name: 'Sindre'});
t.true(element);
});
test('react element, complex attributes, formatted', t => {
const element = React.createElement('div', {
multiline: 'Hello\nworld',
object: {foo: ['bar']}
});
t.true(element);
});
test('react element, opaque children, formatted', t => {
const element = React.createElement('Foo', null, new Set(['foo']), true);
t.true(element);
});
test('react element, diff', t => {
const element = React.createElement(HelloMessage, {name: 'Sindre'});
const other = React.createElement(HelloMessage, {name: 'Vadim'});
t.deepEqual(element, other);
});
test('deep structure, formatted', t => {
const deep = {
foo: {
bar: {
baz: {
qux: 'quux'
}
}
}
};
t.true(deep);
});
test('deep structure, diff', t => {
const deep = {
foo: {
bar: {
baz: {
qux: 'quux'
}
}
}
};
t.deepEqual(deep, {corge: 'grault', ...deep});
});

View file

@ -1,4 +1,4 @@
import test from '../..';
const test = require('../..');
test.before(() => {
throw new Error('should not run');

View file

@ -1,4 +1,4 @@
import test from '../../../..';
const test = require('../../../..');
test('test', t => {
t.pass();

View file

@ -1,3 +1,3 @@
import test from '../../..';
const test = require('../../..');
test('pass', t => t.pass());

View file

@ -1,4 +1,4 @@
import test from '../../..';
const test = require('../../..');
test.cb('test', t => {
setTimeout(() => {

View file

@ -1,4 +1,4 @@
import test from '../../..';
const test = require('../../..');
test('test', t => {
try {

View file

@ -1,4 +1,4 @@
import test from '../../..';
const test = require('../../..');
test('test', t => {
try {

View file

@ -1,4 +1,4 @@
import test from '../../..';
const test = require('../../..');
test('test', t => {
try {

View file

@ -1,4 +1,4 @@
import test from '../../..';
const test = require('../../..');
test('test', t => {
try {

View file

@ -1,4 +1,4 @@
import test from '../../..';
const test = require('../../..');
test('test', t => {
try {

View file

@ -0,0 +1,5 @@
{
"ava": {
"babel": true
}
}

View file

@ -1,4 +1,4 @@
import test from '../../..';
const test = require('../../..');
test('test', t => {
return Promise.resolve().then(() => {

View file

@ -1,4 +1,4 @@
import test from '../../..';
const test = require('../../..');
test('test', t => {
t.throws(throwSync());

View file

@ -1,4 +1,4 @@
import test from '../../..';
const test = require('../../..');
test.cb('test', t => {
Promise.resolve().then(() => {

View file

@ -1,4 +1,4 @@
import test from '../..';
const test = require('../..');
Error.stackTraceLimit = 1;

View file

@ -1,5 +0,0 @@
import test from '../..';
test('test', t => {
t.true(process.execArgv[0].startsWith('--inspect'));
});

View file

@ -1,7 +0,0 @@
{
"ava": {
"babel": {
"extensions": ["js", "js", "jsx", "jsx"]
}
}
}

View file

@ -1,6 +1,5 @@
{
"ava": {
"babel": false,
"extensions": ["js", "js", "jsx", "jsx"]
}
}

View file

@ -1 +0,0 @@
import dependency from './dependency'; // eslint-disable-line no-unused-vars

View file

@ -1,5 +0,0 @@
{
"ava": {
"extensions": ["foo"]
}
}

View file

@ -1,8 +0,0 @@
'use strict';
const test = require('../../../..');
test('test', t => {
const bool = false;
t.assert(bool);
});

View file

@ -1 +0,0 @@
import dependency from './dependency'; // eslint-disable-line no-unused-vars

View file

@ -1,6 +0,0 @@
{
"ava": {
"babel": false,
"compileEnhancements": true
}
}

View file

@ -1,8 +0,0 @@
'use strict';
const test = require('../../..');
test('test', t => {
const bool = false;
t.assert(bool);
});

View file

@ -1,4 +1,4 @@
import test from '../..';
const test = require('../..');
test.cb('slow', t => {
setTimeout(t.end, 5000);

View file

@ -1,5 +1,5 @@
import test from '../../..';
import Bluebird from './_enable-trace';
const test = require('../../..');
const Bluebird = require('./_enable-trace');
// This promise throwing pattern was used in bluebird documentation for long stack traces
// http://bluebirdjs.com/docs/api/promise.longstacktraces.html

View file

@ -1,4 +1,4 @@
import test from '../..';
const test = require('../..');
test('this test will match', t => {
t.pass();

Some files were not shown because too many files have changed in this diff Show more