Restrict compatibility to AVA 6
This commit is contained in:
parent
41d8c6b4de
commit
1ae15b27c2
7 changed files with 101 additions and 340 deletions
225
index.js
225
index.js
|
|
@ -75,7 +75,7 @@ const changeInterpretations = Object.freeze(Object.assign(Object.create(null), {
|
|||
}));
|
||||
|
||||
export default function typescriptProvider({negotiateProtocol}) {
|
||||
const protocol = negotiateProtocol(['ava-6', 'ava-3.2'], {version: pkg.version});
|
||||
const protocol = negotiateProtocol(['ava-6'], {version: pkg.version});
|
||||
if (protocol === null) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -100,141 +100,110 @@ export default function typescriptProvider({negotiateProtocol}) {
|
|||
]);
|
||||
const testFileExtension = new RegExp(`\\.(${extensions.map(ext => escapeStringRegexp(ext)).join('|')})$`);
|
||||
|
||||
const watchMode = protocol.identifier === 'ava-3.2'
|
||||
? {
|
||||
ignoreChange(filePath) {
|
||||
if (!testFileExtension.test(filePath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return rewritePaths.some(([from]) => filePath.startsWith(from));
|
||||
},
|
||||
|
||||
resolveTestFile(testfile) { // Used under AVA 3.2 protocol by legacy watcher implementation.
|
||||
if (!testFileExtension.test(testfile)) {
|
||||
return testfile;
|
||||
}
|
||||
|
||||
const rewrite = rewritePaths.find(([from]) => testfile.startsWith(from));
|
||||
if (rewrite === undefined) {
|
||||
return testfile;
|
||||
}
|
||||
|
||||
const [from, to] = rewrite;
|
||||
let newExtension = '.js';
|
||||
if (testfile.endsWith('.cts')) {
|
||||
newExtension = '.cjs';
|
||||
} else if (testfile.endsWith('.mts')) {
|
||||
newExtension = '.mjs';
|
||||
}
|
||||
|
||||
return `${to}${testfile.slice(from.length)}`.replace(testFileExtension, newExtension);
|
||||
},
|
||||
}
|
||||
: {
|
||||
changeInterpretations,
|
||||
interpretChange(filePath) {
|
||||
if (config.compile === false) {
|
||||
for (const [from] of rewritePaths) {
|
||||
if (testFileExtension.test(filePath) && filePath.startsWith(from)) {
|
||||
return changeInterpretations.waitForOutOfBandCompilation;
|
||||
}
|
||||
const watchMode = {
|
||||
changeInterpretations,
|
||||
interpretChange(filePath) {
|
||||
if (config.compile === false) {
|
||||
for (const [from] of rewritePaths) {
|
||||
if (testFileExtension.test(filePath) && filePath.startsWith(from)) {
|
||||
return changeInterpretations.waitForOutOfBandCompilation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.compile === 'tsc') {
|
||||
for (const [, to] of rewritePaths) {
|
||||
if (filePath.startsWith(to)) {
|
||||
return changeInterpretations.ignoreCompiled;
|
||||
}
|
||||
if (config.compile === 'tsc') {
|
||||
for (const [, to] of rewritePaths) {
|
||||
if (filePath.startsWith(to)) {
|
||||
return changeInterpretations.ignoreCompiled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changeInterpretations.unspecified;
|
||||
},
|
||||
|
||||
resolvePossibleOutOfBandCompilationSources(filePath) {
|
||||
if (config.compile !== false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Only recognize .cjs, .mjs and .js files.
|
||||
if (!/\.(c|m)?js$/.test(filePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (const [from, to] of rewritePaths) {
|
||||
if (!filePath.startsWith(to)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const rewritten = `${from}${filePath.slice(to.length)}`;
|
||||
const possibleExtensions = [];
|
||||
|
||||
if (filePath.endsWith('.cjs')) {
|
||||
if (extensions.includes('cjs')) {
|
||||
possibleExtensions.push({replace: /\.cjs$/, extension: 'cjs'});
|
||||
}
|
||||
|
||||
if (extensions.includes('cts')) {
|
||||
possibleExtensions.push({replace: /\.cjs$/, extension: 'cts'});
|
||||
}
|
||||
|
||||
if (possibleExtensions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (filePath.endsWith('.mjs')) {
|
||||
if (extensions.includes('mjs')) {
|
||||
possibleExtensions.push({replace: /\.mjs$/, extension: 'mjs'});
|
||||
}
|
||||
|
||||
if (extensions.includes('mts')) {
|
||||
possibleExtensions.push({replace: /\.mjs$/, extension: 'mts'});
|
||||
}
|
||||
|
||||
if (possibleExtensions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (filePath.endsWith('.js')) {
|
||||
if (extensions.includes('js')) {
|
||||
possibleExtensions.push({replace: /\.js$/, extension: 'js'});
|
||||
}
|
||||
|
||||
if (extensions.includes('ts')) {
|
||||
possibleExtensions.push({replace: /\.js$/, extension: 'ts'});
|
||||
}
|
||||
|
||||
if (extensions.includes('tsx')) {
|
||||
possibleExtensions.push({replace: /\.js$/, extension: 'tsx'});
|
||||
}
|
||||
|
||||
if (possibleExtensions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const possibleDeletedFiles = [];
|
||||
for (const {replace, extension} of possibleExtensions) {
|
||||
const possibleFilePath = rewritten.replace(replace, `.${extension}`);
|
||||
|
||||
// Pick the first file path that exists.
|
||||
if (fs.existsSync(possibleFilePath)) {
|
||||
return [possibleFilePath];
|
||||
}
|
||||
|
||||
possibleDeletedFiles.push(possibleFilePath);
|
||||
}
|
||||
|
||||
return possibleDeletedFiles;
|
||||
}
|
||||
return changeInterpretations.unspecified;
|
||||
},
|
||||
|
||||
resolvePossibleOutOfBandCompilationSources(filePath) {
|
||||
if (config.compile !== false) {
|
||||
return null;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Only recognize .cjs, .mjs and .js files.
|
||||
if (!/\.(c|m)?js$/.test(filePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (const [from, to] of rewritePaths) {
|
||||
if (!filePath.startsWith(to)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const rewritten = `${from}${filePath.slice(to.length)}`;
|
||||
const possibleExtensions = [];
|
||||
|
||||
if (filePath.endsWith('.cjs')) {
|
||||
if (extensions.includes('cjs')) {
|
||||
possibleExtensions.push({replace: /\.cjs$/, extension: 'cjs'});
|
||||
}
|
||||
|
||||
if (extensions.includes('cts')) {
|
||||
possibleExtensions.push({replace: /\.cjs$/, extension: 'cts'});
|
||||
}
|
||||
|
||||
if (possibleExtensions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (filePath.endsWith('.mjs')) {
|
||||
if (extensions.includes('mjs')) {
|
||||
possibleExtensions.push({replace: /\.mjs$/, extension: 'mjs'});
|
||||
}
|
||||
|
||||
if (extensions.includes('mts')) {
|
||||
possibleExtensions.push({replace: /\.mjs$/, extension: 'mts'});
|
||||
}
|
||||
|
||||
if (possibleExtensions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (filePath.endsWith('.js')) {
|
||||
if (extensions.includes('js')) {
|
||||
possibleExtensions.push({replace: /\.js$/, extension: 'js'});
|
||||
}
|
||||
|
||||
if (extensions.includes('ts')) {
|
||||
possibleExtensions.push({replace: /\.js$/, extension: 'ts'});
|
||||
}
|
||||
|
||||
if (extensions.includes('tsx')) {
|
||||
possibleExtensions.push({replace: /\.js$/, extension: 'tsx'});
|
||||
}
|
||||
|
||||
if (possibleExtensions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const possibleDeletedFiles = [];
|
||||
for (const {replace, extension} of possibleExtensions) {
|
||||
const possibleFilePath = rewritten.replace(replace, `.${extension}`);
|
||||
|
||||
// Pick the first file path that exists.
|
||||
if (fs.existsSync(possibleFilePath)) {
|
||||
return [possibleFilePath];
|
||||
}
|
||||
|
||||
possibleDeletedFiles.push(possibleFilePath);
|
||||
}
|
||||
|
||||
return possibleDeletedFiles;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
...watchMode,
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import {execaNode} 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 withAltProvider = createProviderMacro('ava-3.2', '3.2.0', path.join(__dirname, 'broken-fixtures'));
|
||||
const withProvider = createProviderMacro('ava-6', '6.0.0', path.join(__dirname, 'fixtures'));
|
||||
const withAltProvider = createProviderMacro('ava-6', '6.0.0', path.join(__dirname, 'broken-fixtures'));
|
||||
|
||||
test.before('deleting compiled files', async t => {
|
||||
t.log(await deleteAsync('test/fixtures/typescript/compiled'));
|
||||
|
|
|
|||
2
test/fixtures/install-and-load.js
vendored
2
test/fixtures/install-and-load.js
vendored
|
|
@ -8,7 +8,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|||
|
||||
const provider = makeProvider({
|
||||
negotiateProtocol() {
|
||||
return {identifier: 'ava-3.2', ava: {version: '3.15.0'}, projectDir: __dirname};
|
||||
return {identifier: 'ava-6', ava: {version: '6.0.0'}, projectDir: __dirname};
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {execaNode} 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 withProvider = createProviderMacro('ava-6', '6.0.0', path.join(__dirname, 'fixtures'));
|
||||
|
||||
const setup = async provider => ({
|
||||
state: await provider.main({
|
||||
|
|
|
|||
|
|
@ -1,91 +0,0 @@
|
|||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
import test from 'ava';
|
||||
import createProviderMacro from './_with-provider.js';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const pkg = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url)));
|
||||
const withProvider = createProviderMacro('ava-3.2', '3.15.0');
|
||||
|
||||
const validateConfig = (t, provider, config) => {
|
||||
const error = t.throws(() => provider.main({config}));
|
||||
error.message = error.message.replace(`v${pkg.version}`, 'v${pkg.version}'); // eslint-disable-line no-template-curly-in-string
|
||||
t.snapshot(error);
|
||||
};
|
||||
|
||||
test('negotiates ava-3.2 protocol', withProvider, t => t.plan(2));
|
||||
|
||||
test('main() config validation: throw when config is not a plain object', withProvider, (t, provider) => {
|
||||
validateConfig(t, provider, false);
|
||||
validateConfig(t, provider, true);
|
||||
validateConfig(t, provider, null);
|
||||
validateConfig(t, provider, []);
|
||||
});
|
||||
|
||||
test('main() config validation: throw when config contains keys other than \'extensions\', \'rewritePaths\' or \'compile\'', withProvider, (t, provider) => {
|
||||
validateConfig(t, provider, {compile: false, foo: 1, rewritePaths: {'src/': 'build/'}});
|
||||
});
|
||||
|
||||
test('main() config validation: throw when config.extensions contains empty strings', withProvider, (t, provider) => {
|
||||
validateConfig(t, provider, {extensions: ['']});
|
||||
});
|
||||
|
||||
test('main() config validation: throw when config.extensions contains non-strings', withProvider, (t, provider) => {
|
||||
validateConfig(t, provider, {extensions: [1]});
|
||||
});
|
||||
|
||||
test('main() config validation: throw when config.extensions contains duplicates', withProvider, (t, provider) => {
|
||||
validateConfig(t, provider, {extensions: ['ts', 'ts']});
|
||||
});
|
||||
|
||||
test('main() config validation: config may not be an empty object', withProvider, (t, provider) => {
|
||||
validateConfig(t, provider, {});
|
||||
});
|
||||
|
||||
test('main() config validation: throw when config.compile is invalid', withProvider, (t, provider) => {
|
||||
validateConfig(t, provider, {rewritePaths: {'src/': 'build/'}, compile: 1});
|
||||
validateConfig(t, provider, {rewritePaths: {'src/': 'build/'}, compile: undefined});
|
||||
});
|
||||
|
||||
test('main() config validation: rewrite paths must end in a /', withProvider, (t, provider) => {
|
||||
validateConfig(t, provider, {rewritePaths: {src: 'build/', compile: false}});
|
||||
validateConfig(t, provider, {rewritePaths: {'src/': 'build', compile: false}});
|
||||
});
|
||||
|
||||
test('main() extensions: defaults to [\'ts\', \'cts\', \'mts\']', withProvider, (t, provider) => {
|
||||
t.deepEqual(provider.main({config: {rewritePaths: {'src/': 'build/'}, compile: false}}).extensions, ['ts', 'cts', 'mts']);
|
||||
});
|
||||
|
||||
test('main() extensions: returns configured extensions', withProvider, (t, provider) => {
|
||||
const extensions = ['tsx'];
|
||||
t.deepEqual(provider.main({config: {extensions, rewritePaths: {'src/': 'build/'}, compile: false}}).extensions, extensions);
|
||||
});
|
||||
|
||||
test('main() extensions: always returns new arrays', withProvider, (t, provider) => {
|
||||
const main = provider.main({config: {rewritePaths: {'src/': 'build/'}, compile: false}});
|
||||
t.not(main.extensions, main.extensions);
|
||||
});
|
||||
|
||||
test('main() ignoreChange()', withProvider, (t, provider) => {
|
||||
const main = provider.main({config: {rewritePaths: {'src/': 'build/'}, compile: false}});
|
||||
t.true(main.ignoreChange(path.join(__dirname, 'src/foo.ts')));
|
||||
t.false(main.ignoreChange(path.join(__dirname, 'build/foo.js')));
|
||||
});
|
||||
|
||||
test('main() resolveTestfile()', withProvider, (t, provider) => {
|
||||
const main = provider.main({config: {rewritePaths: {'src/': 'build/'}, compile: false}});
|
||||
t.is(main.resolveTestFile(path.join(__dirname, 'src/foo.ts')), path.join(__dirname, 'build/foo.js'));
|
||||
t.is(main.resolveTestFile(path.join(__dirname, 'src/foo.cts')), path.join(__dirname, 'build/foo.cjs'));
|
||||
t.is(main.resolveTestFile(path.join(__dirname, 'src/foo.mts')), path.join(__dirname, 'build/foo.mjs'));
|
||||
t.is(main.resolveTestFile(path.join(__dirname, 'build/foo.js')), path.join(__dirname, 'build/foo.js'));
|
||||
t.is(main.resolveTestFile(path.join(__dirname, 'foo/bar.ts')), path.join(__dirname, 'foo/bar.ts'));
|
||||
});
|
||||
|
||||
test('main() updateGlobs()', withProvider, (t, provider) => {
|
||||
const main = provider.main({config: {rewritePaths: {'src/': 'build/'}, compile: false}});
|
||||
t.snapshot(main.updateGlobs({
|
||||
filePatterns: ['src/test.ts'],
|
||||
ignoredByWatcherPatterns: ['assets/**'],
|
||||
}));
|
||||
});
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
# Snapshot report for `test/protocol-ava-3.2.js`
|
||||
|
||||
The actual snapshot is saved in `protocol-ava-3.2.js.snap`.
|
||||
|
||||
Generated by [AVA](https://avajs.dev).
|
||||
|
||||
## main() config validation: throw when config is not a plain object
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
Error {
|
||||
message: 'Unexpected Typescript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
> Snapshot 2
|
||||
|
||||
Error {
|
||||
message: 'Unexpected Typescript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
> Snapshot 3
|
||||
|
||||
Error {
|
||||
message: 'Unexpected Typescript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
> Snapshot 4
|
||||
|
||||
Error {
|
||||
message: 'Unexpected Typescript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
## main() config validation: throw when config contains keys other than 'extensions', 'rewritePaths' or 'compile'
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
Error {
|
||||
message: 'Unexpected \'foo\' property in TypeScript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
## main() config validation: throw when config.extensions contains empty strings
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
Error {
|
||||
message: 'Missing \'compile\' property in TypeScript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
## main() config validation: throw when config.extensions contains non-strings
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
Error {
|
||||
message: 'Missing \'compile\' property in TypeScript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
## main() config validation: throw when config.extensions contains duplicates
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
Error {
|
||||
message: 'Missing \'compile\' property in TypeScript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
## main() config validation: config may not be an empty object
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
Error {
|
||||
message: 'Missing \'compile\' property in TypeScript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
## main() config validation: throw when config.compile is invalid
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
Error {
|
||||
message: 'Invalid \'compile\' property in TypeScript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
> Snapshot 2
|
||||
|
||||
Error {
|
||||
message: 'Invalid \'compile\' property in TypeScript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
## main() config validation: rewrite paths must end in a /
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
Error {
|
||||
message: 'Missing \'compile\' property in TypeScript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
> Snapshot 2
|
||||
|
||||
Error {
|
||||
message: 'Missing \'compile\' property in TypeScript configuration for AVA. See https://github.com/avajs/typescript/blob/v${pkg.version}/README.md',
|
||||
}
|
||||
|
||||
## main() updateGlobs()
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
{
|
||||
filePatterns: [
|
||||
'src/test.ts',
|
||||
'!**/*.d.ts',
|
||||
'!build/**',
|
||||
],
|
||||
ignoredByWatcherPatterns: [
|
||||
'assets/**',
|
||||
'build/**/*.js.map',
|
||||
'build/**/*.cjs.map',
|
||||
'build/**/*.mjs.map',
|
||||
],
|
||||
}
|
||||
Binary file not shown.
Loading…
Reference in a new issue