Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: avajs/ava
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v5.2.0
Choose a base ref
...
head repository: avajs/ava
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v5.3.0
Choose a head ref
  • 10 commits
  • 44 files changed
  • 8 contributors

Commits on Feb 7, 2023

  1. Properly end sentence

    novemberborn authored Feb 7, 2023
    Copy the full SHA
    38593a7 View commit details

Commits on Mar 1, 2023

  1. Copy the full SHA
    1c56764 View commit details

Commits on Mar 21, 2023

  1. Add t-node error handling section to TypeScript recipe

    Martynas Žilinskas authored Mar 21, 2023
    Copy the full SHA
    0574e5e View commit details

Commits on Apr 19, 2023

  1. Add Node.js 20 to test matrix

    Run tests against newly released node v20
    flovogt authored Apr 19, 2023
    Copy the full SHA
    5bf01a3 View commit details

Commits on May 21, 2023

  1. Update TypeScript recipe to remove ts-node recommendation (#3192)

    * Update typescript recipe to use the tsx loader;
    * Remove ts-node references; strongly advocate @ava/typescript; general instructions for setting up custom loaders
    
    ---------
    
    Co-authored-by: Mark Wubben <mark@novemberborn.net>
    ondreian and novemberborn authored May 21, 2023
    Copy the full SHA
    49e5582 View commit details

Commits on May 24, 2023

  1. Support arrays in t.like() assertion

    Co-authored-by: Mark Wubben <mark@novemberborn.net>
    tommy-mitchell and novemberborn authored May 24, 2023
    Copy the full SHA
    d7c6120 View commit details
  2. Replace 'del' dependency by built-in recursive fs.rm (#3198)

    Co-authored-by: Mark Wubben <mark@novemberborn.net>
    craigahobbs and novemberborn authored May 24, 2023
    Copy the full SHA
    faa9654 View commit details
  3. Recognize typical assertion errors and use their formatting

    Co-authored-by: Mark Wubben <mark@novemberborn.net>
    Irvenae and novemberborn authored May 24, 2023
    Copy the full SHA
    5558367 View commit details
  4. Dependency updates and so forth

    * Test against typescript@5.0
    
    * Default to Node.js 20
    
    * Upgrade XO
    
    * Add reporter logs for Node.js 20
    
    * Update dev dependencies
    
    * Reduce timeouts in reporter tests
    
    This may cause CI failures especially on Windows, but we do waste a lot of time with these tests.
    
    * Inline slash dependency
    
    We need it available in CJS but the package is now ESM only. It's more bothersome to remember to not upgrade the dependency than to inline it.
    
    * Update dependencies
    
    * Rebuild lockfile
    
    * Use latest Codecov action
    novemberborn authored May 24, 2023
    Copy the full SHA
    784ca4c View commit details

Commits on May 25, 2023

  1. 5.3.0

    novemberborn committed May 25, 2023
    Copy the full SHA
    568fe40 View commit details
Showing with 2,959 additions and 1,165 deletions.
  1. +3 −5 .github/workflows/ci.yml
  2. +10 −4 docs/03-assertions.md
  3. +1 −1 docs/07-test-timeouts.md
  4. +17 −101 docs/recipes/typescript.md
  5. +2 −2 lib/assert.js
  6. +16 −4 lib/cli.js
  7. +2 −1 lib/glob-helpers.cjs
  8. +12 −10 lib/like-selector.js
  9. +36 −0 lib/slash.cjs
  10. +1 −1 lib/snapshot-manager.js
  11. +42 −10 lib/test.js
  12. +1,649 −987 package-lock.json
  13. +18 −20 package.json
  14. +2 −3 test-tap/api.js
  15. +10 −0 test-tap/assert.js
  16. +2 −2 test-tap/fixture/report/timeoutcontextlogs/a.cjs
  17. +2 −2 test-tap/fixture/report/timeoutinmultiplefiles/a.cjs
  18. +3 −3 test-tap/fixture/report/timeoutinmultiplefiles/b.cjs
  19. +2 −2 test-tap/fixture/report/timeoutinsinglefile/a.cjs
  20. +3 −3 test-tap/fixture/report/timeoutwithmatch/a.cjs
  21. +2 −1 test-tap/fixture/snapshots/test-sourcemaps/tsconfig.json
  22. +1 −1 test-tap/helper/report.js
  23. +59 −0 test-tap/reporters/default.edgecases.v20.log
  24. +24 −0 test-tap/reporters/default.failfast.v20.log
  25. +24 −0 test-tap/reporters/default.failfast2.v20.log
  26. +10 −0 test-tap/reporters/default.only.v20.log
  27. +357 −0 test-tap/reporters/default.regular.v20.log
  28. +38 −0 test-tap/reporters/default.timeoutcontextlogs.v20.log
  29. +34 −0 test-tap/reporters/default.timeoutinmultiplefiles.v20.log
  30. +20 −0 test-tap/reporters/default.timeoutinsinglefile.v20.log
  31. +18 −0 test-tap/reporters/default.timeoutwithmatch.v20.log
  32. +32 −0 test-tap/reporters/default.watch.v20.log
  33. +46 −0 test-tap/reporters/tap.edgecases.v20.log
  34. +17 −0 test-tap/reporters/tap.failfast.v20.log
  35. +19 −0 test-tap/reporters/tap.failfast2.v20.log
  36. +13 −0 test-tap/reporters/tap.only.v20.log
  37. +268 −0 test-tap/reporters/tap.regular.v20.log
  38. +2 −2 test/builtin-nodejs-assert/test.js
  39. +11 −0 test/external-assertions/fixtures/assert-failure.js
  40. +10 −0 test/external-assertions/fixtures/expect-failure.js
  41. +11 −0 test/external-assertions/fixtures/package.json
  42. +97 −0 test/external-assertions/snapshots/test.js.md
  43. BIN test/external-assertions/snapshots/test.js.snap
  44. +13 −0 test/external-assertions/test.js
8 changes: 3 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: [^14.19, ^16.15, ^18]
node-version: [^14.19, ^16.15, ^18, ^20]
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v3
@@ -33,7 +33,7 @@ jobs:
run: npm install --global npm@^8
- run: npm install --no-audit
- run: npm run cover
- uses: codecov/codecov-action@v2
- uses: codecov/codecov-action@v3
with:
files: coverage/lcov.info
name: ${{ matrix.os }}/${{ matrix.node-version }}
@@ -43,7 +43,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
ts-version: [~4.7, ~4.8, ~4.9]
ts-version: [~4.7, ~4.8, ~4.9, ~5.0]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
@@ -66,8 +66,6 @@ jobs:
with:
node-version-file: package.json
cache: npm
- name: Pin npm
run: npm install --global npm@9.3.0
- run: npm install --no-audit
- name: Test package-lock for unexpected modifications
run: |
14 changes: 10 additions & 4 deletions docs/03-assertions.md
Original file line number Diff line number Diff line change
@@ -141,9 +141,9 @@ Assert that `actual` is not deeply equal to `expected`. The inverse of `.deepEqu

Assert that `actual` is like `selector`. This is a variant of `.deepEqual()`, however `selector` does not need to have the same enumerable properties as `actual` does.

Instead AVA derives a *comparable* object from `actual`, based on the deeply-nested properties of `selector`. This object is then compared to `selector` using `.deepEqual()`.
Instead AVA derives a *comparable* value from `actual`, recursively based on the shape of `selector`. This value is then compared to `selector` using `.deepEqual()`.

Any values in `selector` that are not regular objects should be deeply equal to the corresponding values in `actual`.
Any values in `selector` that are not arrays or regular objects should be deeply equal to the corresponding values in `actual`.

In the following example, the `map` property of `actual` must be deeply equal to that of `selector`. However `nested.qux` is ignored, because it's not in `selector`.

@@ -162,6 +162,12 @@ t.like({
})
```

You can also use arrays, but note that any indices in `actual` that are not in `selector` are ignored:

```js
t.like([1, 2, 3], [1, 2])
```

Finally, this returns a boolean indicating whether the assertion passed.

### `.throws(fn, expectation?, message?)`
@@ -172,7 +178,7 @@ Assert that an error is thrown. `fn` must be a function which should throw. The

* `instanceOf`: a constructor, the thrown error must be an instance of
* `is`: the thrown error must be strictly equal to `expectation.is`
* `message`: the following types are valid:
* `message`: the following types are valid:
* *string* - it is compared against the thrown error's message
* *regular expression* - it is matched against this message
* *function* - it is passed the thrown error message and must return a boolean for whether the assertion passed
@@ -207,7 +213,7 @@ The thrown value *must* be an error. It is returned so you can run more assertio

* `instanceOf`: a constructor, the thrown error must be an instance of
* `is`: the thrown error must be strictly equal to `expectation.is`
* `message`: the following types are valid:
* `message`: the following types are valid:
* *string* - it is compared against the thrown error's message
* *regular expression* - it is matched against this message
* *function* - it is passed the thrown error message and must return a boolean for whether the assertion passed
2 changes: 1 addition & 1 deletion docs/07-test-timeouts.md
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ npx ava --timeout=100 # 100 milliseconds

### `t.timeout(ms, message?)`

Timeouts can also be set individually for each test These timeouts are reset each time an assertion is made. The test fails if it takes more than `ms` for an assertion to be made or the test to complete.
Timeouts can also be set individually for each test. These timeouts are reset each time an assertion is made. The test fails if it takes more than `ms` for an assertion to be made or the test to complete.

```js
test('foo', t => {
118 changes: 17 additions & 101 deletions docs/recipes/typescript.md
Original file line number Diff line number Diff line change
@@ -8,76 +8,35 @@ This guide assumes you've already set up TypeScript for your project. Note that

## Enabling AVA's support for TypeScript test files

### With precompile step
Broadly speaking, there are two ways to run tests written in TypeScript:

Out of the box AVA does not load TypeScript test files. You can use our [`@ava/typescript`] package, which is designed to work for projects that precompile TypeScript using the `tsc` command. Please see [`@ava/typescript`] for setup instructions.
1. Build first, then test against the build output
2. Configure loaders which build test files as they're loaded

### Using `ts-node`
**The first option is the most reliable since it doesn't rely on experimental Node.js features.** You can use our [`@ava/typescript`] package, which is designed to work for projects that precompile TypeScript using the `tsc` command. Please see [`@ava/typescript`] for setup instructions. **This package also sets up the various TypeScript file extensions for you.**

You can use [`ts-node`] to do live testing without transpiling. This can be especially helpful when you're using a bundler. Be sure to install the required dev dependencies:
**You can use loaders, but you're largely on your own. [Please post questions to our Discussions forum if you're stuck](https://github.com/avajs/ava/discussions/categories/q-a).**

`npm install --save-dev typescript ts-node`
There are two components to a setup like this:

The required setup depends on the type of your package:
1. [Make sure AVA recognizes the extensions of your TypeScript files](../06-configuration.md#configuring-module-formats)
2. Install the loader [through `nodeArguments`](../06-configuration.md#node-arguments)

1. [for packages with type "module"](#for-packages-with-type-module)
2. [for packages without type "module"](#for-packages-without-type-module)

#### For packages with type `module`

If your `package.json` has `"type": "module"`, then this is the AVA configuration you need:

`package.json`:

```json
{
"ava": {
"extensions": {
"ts": "module"
},
"nodeArguments": [
"--loader=ts-node/esm"
]
}
}
```

You also need to have this in your `tsconfig.json`:

```json
{
"compilerOptions": {
"module": "ES2020",
"moduleResolution": "node"
}
}
```

Remember that, by default, ES modules require you to specify the file extension and TypeScript outputs `.js` files, so you have to write your imports to load from `.js` files not `.ts`.

If this is not to your liking there is an _experimental_ option in Node.js that you might want to use. You can add it to the `nodeArguments` array in the AVA configuration so it applies to your test runs: [`--experimental-specifier-resolution=node`](https://nodejs.org/api/esm.html#customizing-esm-specifier-resolution-algorithm).

#### For packages without type "module"

If your `package.json` does not have `"type": "module"`, then this is the AVA configuration you need:
[`tsx`](https://github.com/esbuild-kit/tsx) may be the best loader available. The setup, assuming your TypeScript config outputs ES modules, would look like this:

`package.json`:

```json
{
"ava": {
"extensions": [
"ts"
],
"require": [
"ts-node/register"
]
}
}
"ava": {
"extensions": {
"ts": "module"
},
"nodeArguments": [
"--loader=tsx"
]
}
```

It's worth noting that with this configuration, tests will fail if there are TypeScript build errors. If you want to test while ignoring these errors you can use `ts-node/register/transpile-only` instead of `ts-node/register`.

## Writing tests

[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/avajs/ava/tree/main/examples/typescript-basic?file=source%2Ftest.ts&terminal=test&view=editor)
@@ -218,47 +177,4 @@ test('throwsAsync', async t => {

Note that, despite the typing, the assertion returns `undefined` if it fails. Typing the assertions as returning `Error | undefined` didn't seem like the pragmatic choice.

### Using module path mapping

`ts-node` [does not support module path mapping](https://github.com/TypeStrong/ts-node/issues/138), however you can use [`tsconfig-paths`](https://github.com/dividab/tsconfig-paths#readme).

Once installed, add the `tsconfig-paths/register` entry to the `require` section of AVA's config:

`package.json`:

```json
{
"ava": {
"extensions": [
"ts"
],
"require": [
"ts-node/register",
"tsconfig-paths/register"
]
}
}
```

Then you can start using module aliases:

`tsconfig.json`:
```json
{
"baseUrl": ".",
"paths": {
"@helpers/*": ["helpers/*"]
}
}
```

Test:

```ts
import myHelper from '@helpers/myHelper';

// Rest of the file
```

[`@ava/typescript`]: https://github.com/avajs/typescript
[`ts-node`]: https://www.npmjs.com/package/ts-node
4 changes: 2 additions & 2 deletions lib/assert.js
Original file line number Diff line number Diff line change
@@ -55,7 +55,7 @@ export class AssertionError extends Error {
}

export function checkAssertionMessage(assertion, message) {
if (typeof message === 'undefined' || typeof message === 'string') {
if (message === undefined || typeof message === 'string') {
return true;
}

@@ -253,7 +253,7 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
});
}

if (typeof expectations.code !== 'undefined' && actual.code !== expectations.code) {
if (expectations.code !== undefined && actual.code !== expectations.code) {
throw new AssertionError({
assertion,
message,
20 changes: 16 additions & 4 deletions lib/cli.js
Original file line number Diff line number Diff line change
@@ -5,7 +5,6 @@ import process from 'node:process';

import arrify from 'arrify';
import ciParallelVars from 'ci-parallel-vars';
import {deleteAsync} from 'del';
import figures from 'figures';
import yargs from 'yargs';
import {hideBin} from 'yargs/helpers'; // eslint-disable-line n/file-extension-in-import
@@ -140,6 +139,7 @@ export default async function loadCli() { // eslint-disable-line complexity

let resetCache = false;
const {argv} = yargs(hideBin(process.argv))
.scriptName('ava')
.version(pkg.version)
.parserConfiguration({
'boolean-negation': true,
@@ -260,11 +260,23 @@ export default async function loadCli() { // eslint-disable-line complexity
const {nonSemVerExperiments: experiments, projectDir} = conf;
if (resetCache) {
const cacheDir = path.join(projectDir, 'node_modules', '.cache', 'ava');

try {
const deletedFilePaths = await deleteAsync('*', {cwd: cacheDir});
let entries;
try {
entries = fs.readdirSync(cacheDir);
} catch (error) {
if (error.code === 'ENOENT') {
entries = [];
} else {
throw error;
}
}

for (const entry of entries) {
fs.rmSync(path.join(cacheDir, entry), {recursive: true, force: true});
}

if (deletedFilePaths.length === 0) {
if (entries.length === 0) {
console.log(`\n${chalk.green(figures.tick)} No cache files to remove`);
} else {
console.log(`\n${chalk.green(figures.tick)} Removed AVA cache files in ${cacheDir}`);
3 changes: 2 additions & 1 deletion lib/glob-helpers.cjs
Original file line number Diff line number Diff line change
@@ -4,7 +4,8 @@ const process = require('node:process');

const ignoreByDefault = require('ignore-by-default');
const picomatch = require('picomatch');
const slash = require('slash');

const slash = require('./slash.cjs');

const defaultIgnorePatterns = [...ignoreByDefault.directories(), '**/node_modules'];
exports.defaultIgnorePatterns = defaultIgnorePatterns;
22 changes: 12 additions & 10 deletions lib/like-selector.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
const isObject = selector => Reflect.getPrototypeOf(selector) === Object.prototype;

export function isLikeSelector(selector) {
return selector !== null
&& typeof selector === 'object'
&& Reflect.getPrototypeOf(selector) === Object.prototype
&& Reflect.ownKeys(selector).length > 0;
if (selector === null || typeof selector !== 'object') {
return false;
}

const keyCount = Reflect.ownKeys(selector).length;
return (Array.isArray(selector) && keyCount > 1) || (isObject(selector) && keyCount > 0);
}

export const CIRCULAR_SELECTOR = new Error('Encountered a circular selector');
@@ -18,13 +22,11 @@ export function selectComparable(lhs, selector, circular = new Set()) {
return lhs;
}

const comparable = {};
const comparable = Array.isArray(selector) ? [] : {};
for (const [key, rhs] of Object.entries(selector)) {
if (isLikeSelector(rhs)) {
comparable[key] = selectComparable(Reflect.get(lhs, key), rhs, circular);
} else {
comparable[key] = Reflect.get(lhs, key);
}
comparable[key] = isLikeSelector(rhs)
? selectComparable(Reflect.get(lhs, key), rhs, circular)
: Reflect.get(lhs, key);
}

return comparable;
36 changes: 36 additions & 0 deletions lib/slash.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
Inlined from
<https://github.com/sindresorhus/slash/blob/98b618f5a3bfcb5dd374b204868818845b87bb2f/index.js>,
since we need a CJS version.
Copyright 2023 Sindre Sorhus
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the “Software”), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

function slash(path) {
const isExtendedLengthPath = path.startsWith('\\\\?\\');

if (isExtendedLengthPath) {
return path;
}

return path.replace(/\\/g, '/');
}

module.exports = slash;
2 changes: 1 addition & 1 deletion lib/snapshot-manager.js
Original file line number Diff line number Diff line change
@@ -10,10 +10,10 @@ import cbor from 'cbor';
import concordance from 'concordance';
import indentString from 'indent-string';
import mem from 'mem';
import slash from 'slash';
import writeFileAtomic from 'write-file-atomic';

import {snapshotManager as concordanceOptions} from './concordance-options.js';
import slash from './slash.cjs';

// Increment if encoding layout or Concordance serialization versions change. Previous AVA versions will not be able to
// decode buffers generated by a newer version, so changing this value will require a major version bump of AVA itself.
Loading