diff --git a/.c8rc.json b/.c8rc.json index af0d00eac..3409cc347 100644 --- a/.c8rc.json +++ b/.c8rc.json @@ -3,7 +3,7 @@ "exclude": [ "{coverage,examples,media,test,test-d,test-tap,types}/**", "*.config.cjs", - "*.d.ts" + "*.d.*(c|m)ts" ], "reporter": [ "html", diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 21cf3ab30..31320044b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ts-version: [~4.4, ~4.5, ~4.6] + ts-version: [~4.4, ~4.5, ~4.6, ~4.7] steps: - uses: actions/checkout@v2 - run: rm .npmrc diff --git a/.xo-config.cjs b/.xo-config.cjs index 97c38e53d..74b2df577 100644 --- a/.xo-config.cjs +++ b/.xo-config.cjs @@ -28,7 +28,7 @@ module.exports = { }, overrides: [ { - files: '**/*.d.ts', + files: '**/*.d.*(c|m)ts', rules: { 'import/extensions': 'off', }, diff --git a/docs/recipes/typescript.md b/docs/recipes/typescript.md index 38fe1d729..6127efc7f 100644 --- a/docs/recipes/typescript.md +++ b/docs/recipes/typescript.md @@ -82,7 +82,7 @@ It's worth noting that with this configuration, tests will fail if there are Typ [![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) -Create a `test.ts` file. +Create a `test.ts` file. ESM syntax works best, even if you're targeting CommonJS. ```ts import test from 'ava'; @@ -94,6 +94,22 @@ test('fn() returns foo', t => { }); ``` +You can use CommonJS syntax as well: + +```ts +const test = require('ava'); +``` + +This works whether `esModuleInterop` is enabled or not. + +`import … = require()` syntax is less elegant. It's best like this: + +```ts +import ava = require('ava') + +const test = ava.default; +``` + ## Using [macros](../01-writing-tests.md#reusing-test-logic-through-macros) Macros can receive additional arguments. AVA can infer these to ensure you're using the macro correctly: diff --git a/entrypoints/index.d.cts b/entrypoints/index.d.cts new file mode 100644 index 000000000..91c40063f --- /dev/null +++ b/entrypoints/index.d.cts @@ -0,0 +1,2 @@ +export {default} from '../index.js'; +export * from '../index.js'; diff --git a/entrypoints/plugin.d.cts b/entrypoints/plugin.d.cts new file mode 100644 index 000000000..b66e07dcb --- /dev/null +++ b/entrypoints/plugin.d.cts @@ -0,0 +1 @@ +export * from '../plugin.js' diff --git a/index.d.ts b/index.d.ts index 24b722040..50f1570d7 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,9 +1,9 @@ -import type {TestFn} from './types/test-fn'; +import type {TestFn} from './types/test-fn.js'; -export * from './types/assertions'; -export * from './types/try-fn'; -export * from './types/test-fn'; -export * from './types/subscribable'; +export * from './types/assertions.js'; +export * from './types/try-fn.js'; +export * from './types/test-fn.js'; +export * from './types/subscribable.js'; /** Call to declare a test, or chain to declare hooks or test modifiers */ declare const test: TestFn; diff --git a/lib/create-chain.js b/lib/create-chain.js index 525fa96d1..2140d85bb 100644 --- a/lib/create-chain.js +++ b/lib/create-chain.js @@ -101,11 +101,13 @@ export default function createChain(fn, defaults, meta) { root.meta = meta; - // Our type definition uses ESM syntax; when using CJS with VSCode, the - // auto-completion assumes the root is accessed through `require('ava').default`. - // Placate VSCode by adding a mostly hidden default property on the root. - // This is available through both CJS and ESM imports. We use a proxy so that - // we don't end up with root.default.default.default chains. + // The ESM and CJS type definitions export the chain (`test()` function) as + // the default. TypeScript's CJS output (when `esModuleInterop` is disabled) + // assume `require('ava').default` is available. The same goes for `import ava + // = require('ava')` syntax. + // + // Add `test.default` to make this work. Use a proxy to avoid + // `test.default.default` chains. Object.defineProperty(root, 'default', { configurable: false, enumerable: false, diff --git a/package.json b/package.json index e2f7efdd2..ad36940d3 100644 --- a/package.json +++ b/package.json @@ -10,13 +10,25 @@ }, "exports": { ".": { - "import": "./entrypoints/main.mjs", - "require": "./entrypoints/main.cjs" + "import": { + "types": "./index.d.ts", + "default": "./entrypoints/main.mjs" + }, + "require": { + "types": "./entrypoints/index.d.cts", + "default": "./entrypoints/main.cjs" + } }, "./eslint-plugin-helper": "./entrypoints/eslint-plugin-helper.cjs", "./plugin": { - "import": "./entrypoints/plugin.mjs", - "require": "./entrypoints/plugin.cjs" + "import": { + "types": "./plugin.d.ts", + "default": "./entrypoints/plugin.mjs" + }, + "require": { + "types": "./entrypoints/plugin.d.cts", + "default": "./entrypoints/plugin.cjs" + } } }, "type": "module", diff --git a/types/subscribable.ts b/types/subscribable.d.ts similarity index 100% rename from types/subscribable.ts rename to types/subscribable.d.ts diff --git a/types/test-fn.d.ts b/types/test-fn.d.ts index ff9d13fb7..2b206cdb6 100644 --- a/types/test-fn.d.ts +++ b/types/test-fn.d.ts @@ -1,6 +1,6 @@ -import type {Assertions} from './assertions'; -import type {Subscribable} from './subscribable'; -import type {TryFn} from './try-fn'; +import type {Assertions} from './assertions.js'; +import type {Subscribable} from './subscribable.js'; +import type {TryFn} from './try-fn.js'; /** The `t` value passed to test & hook implementations. */ export interface ExecutionContext extends Assertions { diff --git a/types/try-fn.d.ts b/types/try-fn.d.ts index 41a1664d5..8009df0c9 100644 --- a/types/try-fn.d.ts +++ b/types/try-fn.d.ts @@ -1,4 +1,4 @@ -import type {Implementation} from './test-fn'; +import type {Implementation} from './test-fn.js'; export type CommitDiscardOptions = { /**