Skip to content

Commit

Permalink
Support ESM files
Browse files Browse the repository at this point in the history
Fixes #5.
  • Loading branch information
novemberborn committed Nov 1, 2021
1 parent 3debd9d commit 26b5caa
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 10 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ Output files are expected to have the `.js` extension.

AVA searches your entire project for `*.js`, `*.cjs`, `*.mjs` and `*.ts` files (or other extensions you've configured). It will ignore such files found in the `rewritePaths` targets (e.g. `build/`). If you use more specific paths, for instance `build/main/`, you may need to change AVA's `files` configuration to ignore other directories.

## ES Modules

When used with AVA 4, if your `package.json` has configured `"type": "module"`, or you've configured AVA to treat the `js` extension as `module`, then `@ava/typescript` will import the output file as an ES module. Note that this is based on the *output file*, not the `ts` extension.

## Add additional extensions

You can configure AVA to recognize additional file extensions. To add (partial†) JSX support:
Expand Down
10 changes: 3 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'node:fs';
import path from 'node:path';
import {pathToFileURL} from 'node:url';
import escapeStringRegexp from 'escape-string-regexp';
import execa from 'execa';

Expand Down Expand Up @@ -149,6 +150,7 @@ export default function typescriptProvider({negotiateProtocol}) {
},

worker({extensionsToLoadAsModules, state: {extensions, rewritePaths}}) {
const useImport = extensionsToLoadAsModules.includes('js');
const testFileExtension = new RegExp(`\\.(${extensions.map(ext => escapeStringRegexp(ext)).join('|')})$`);

return {
Expand All @@ -157,16 +159,10 @@ export default function typescriptProvider({negotiateProtocol}) {
},

async load(ref, {requireFn}) {
for (const extension of extensionsToLoadAsModules) {
if (ref.endsWith(`.${extension}`)) {
throw new Error('@ava/typescript cannot yet load ESM files');
}
}

const [from, to] = rewritePaths.find(([from]) => ref.startsWith(from));
// TODO: Support JSX preserve mode — https://www.typescriptlang.org/docs/handbook/jsx.html
const rewritten = `${to}${ref.slice(from.length)}`.replace(testFileExtension, '.js');
return requireFn(rewritten);
return useImport ? import(pathToFileURL(rewritten)) : requireFn(rewritten); // eslint-disable-line node/no-unsupported-features/es-syntax
},
};
},
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"files": [
"!test/broken-fixtures/**"
],
"ignoredByWatcher": ["test/fixtures/**", "test/broken-fixtures/**"],
"timeout": "60s"
},
"xo": {
Expand Down
4 changes: 2 additions & 2 deletions test/compilation.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ test('worker(): load rewritten paths files', withProvider, async (t, provider) =
const {state} = await compile(provider);
const {stdout, stderr} = await execa.node(
path.join(__dirname, 'fixtures/install-and-load'),
[JSON.stringify(state), path.join(__dirname, 'fixtures/ts', 'file.ts')],
[JSON.stringify({state}), path.join(__dirname, 'fixtures/ts', 'file.ts')],
{cwd: path.join(__dirname, 'fixtures')},
);
if (stderr.length > 0) {
Expand All @@ -44,7 +44,7 @@ test('worker(): runs compiled files', withProvider, async (t, provider) => {
const {state} = await compile(provider);
const {stdout, stderr} = await execa.node(
path.join(__dirname, 'fixtures/install-and-load'),
[JSON.stringify(state), path.join(__dirname, 'fixtures/compiled', 'index.ts')],
[JSON.stringify({state}), path.join(__dirname, 'fixtures/compiled', 'index.ts')],
{cwd: path.join(__dirname, 'fixtures')},
);
if (stderr.length > 0) {
Expand Down
33 changes: 33 additions & 0 deletions test/esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import path from 'node:path';
import {fileURLToPath} from 'node:url';
import test from 'ava';
import execa from 'execa';
import createProviderMacro from './_with-provider.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const withProvider = createProviderMacro('ava-3.2', '3.2.0', path.join(__dirname, 'fixtures'));

const setup = async provider => ({
state: await provider.main({
config: {
rewritePaths: {
'esm/': 'esm/',
},
compile: false,
},
}).compile(),
});

test('worker(): import ESM', withProvider, async (t, provider) => {
const {state} = await setup(provider);
const {stdout, stderr} = await execa.node(
path.join(__dirname, 'fixtures/install-and-load'),
[JSON.stringify({extensionsToLoadAsModules: ['js'], state}), path.join(__dirname, 'fixtures/esm', 'index.ts')],
{cwd: path.join(__dirname, 'fixtures')},
);
if (stderr.length > 0) {
t.log(stderr);
}

t.snapshot(stdout);
});
1 change: 1 addition & 0 deletions test/fixtures/esm/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('logged in fixtures/esm/index.js');
1 change: 1 addition & 0 deletions test/fixtures/esm/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('logged in fixtures/esm/index.ts');
8 changes: 8 additions & 0 deletions test/fixtures/esm/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"outDir": "compiled"
},
"include": [
"."
]
}
3 changes: 2 additions & 1 deletion test/fixtures/install-and-load.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ const provider = makeProvider({

const worker = provider.worker({
extensionsToLoadAsModules: [],
state: JSON.parse(process.argv[2]),
state: {},
...JSON.parse(process.argv[2]),
});

const ref = path.resolve(process.argv[3]);
Expand Down
11 changes: 11 additions & 0 deletions test/snapshots/esm.js.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Snapshot report for `test/esm.js`

The actual snapshot is saved in `esm.js.snap`.

Generated by [AVA](https://avajs.dev).

## worker(): import ESM

> Snapshot 1
'logged in fixtures/esm/index.js'
Binary file added test/snapshots/esm.js.snap
Binary file not shown.

0 comments on commit 26b5caa

Please sign in to comment.