Skip to content

Commit

Permalink
Allow importing AVA as anyTest in TypeScript files
Browse files Browse the repository at this point in the history
  • Loading branch information
pvdlg authored Feb 16, 2020
1 parent 9fcec4d commit 524594d
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 24 deletions.
7 changes: 7 additions & 0 deletions docs/rules/use-test.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Translations: [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/related/eslint-plugin-ava/docs/rules/use-test.md)

The convention is to import AVA and assign it to a variable named `test`. Most rules in `eslint-plugin-ava` are based on that assumption.
In a TypeScript file (`.ts` or `.tsx`) AVA can be assigned to a variable named `anyTest` in order to define the types of `t.context` (see [Typing t.context](https://github.com/avajs/ava/blob/master/docs/recipes/typescript.md#typing-tcontext)).

### Fail

Expand All @@ -24,3 +25,9 @@ import test from 'ava';
var test = require('foo');
const test = require('foo');
```

```ts
import anyTest from 'ava';

const test = anyTest as TestInterface<{foo: string}>;
```
34 changes: 23 additions & 11 deletions rules/use-test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
const path = require('path');
const espurify = require('espurify');
const deepStrictEqual = require('deep-strict-equal');
const util = require('../util');
Expand All @@ -24,18 +25,29 @@ function report(context, node) {
});
}

const create = context => ({
ImportDeclaration: node => {
if (node.source.value === 'ava' && node.specifiers[0].local.name !== 'test') {
report(context, node);
}
},
VariableDeclarator: node => {
if (node.id.name !== 'test' && node.init && deepStrictEqual(espurify(node.init), avaVariableDeclaratorInitAst)) {
report(context, node);
const create = context => {
const ext = path.extname(context.getFilename());
const isTypeScript = ext === '.ts' || ext === '.tsx';

return {
ImportDeclaration: node => {
if (node.source.value === 'ava') {
const {name} = node.specifiers[0].local;
if (name !== 'test' && (!isTypeScript || name !== 'anyTest')) {
report(context, node);
}
}
},
VariableDeclarator: node => {
if (node.init && deepStrictEqual(espurify(node.init), avaVariableDeclaratorInitAst)) {
const {name} = node.id;
if (name !== 'test' && (!isTypeScript || name !== 'anyTest')) {
report(context, node);
}
}
}
}
});
};
};

module.exports = {
create,
Expand Down
102 changes: 89 additions & 13 deletions test/use-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,111 @@ const errors = [{ruleId: 'use-test'}];

ruleTester.run('use-test', rule, {
valid: [
'var test = require(\'ava\');',
'let test = require(\'ava\');',
'const test = require(\'ava\');',
'const a = 1, test = require(\'ava\'), b = 2;',
'const test = require(\'foo\');',
'import test from \'ava\';',
'import test, {} from \'ava\';',
'import test from \'foo\';'
{code: 'var test = require(\'ava\');', filename: 'file.js'},
{code: 'let test = require(\'ava\');', filename: 'file.js'},
{code: 'const test = require(\'ava\');', filename: 'file.js'},
{code: 'const a = 1, test = require(\'ava\'), b = 2;', filename: 'file.js'},
{code: 'const test = require(\'foo\');', filename: 'file.js'},
{code: 'import test from \'ava\';', filename: 'file.js'},
{code: 'import test, {} from \'ava\';', filename: 'file.js'},
{code: 'import test from \'foo\';', filename: 'file.js'},
{code: 'var anyTest = require(\'ava\');', filename: 'file.ts'},
{code: 'let anyTest = require(\'ava\');', filename: 'file.ts'},
{code: 'const anyTest = require(\'ava\');', filename: 'file.ts'},
{code: 'const a = 1, anyTest = require(\'ava\'), b = 2;', filename: 'file.ts'},
{code: 'const anyTest = require(\'foo\');', filename: 'file.ts'},
{code: 'import anyTest from \'ava\';', filename: 'file.ts'},
{code: 'import anyTest, {} from \'ava\';', filename: 'file.ts'},
{code: 'import anyTest from \'foo\';', filename: 'file.ts'},
{code: 'var anyTest = require(\'ava\');', filename: 'file.tsx'},
{code: 'let anyTest = require(\'ava\');', filename: 'file.tsx'},
{code: 'const anyTest = require(\'ava\');', filename: 'file.tsx'},
{code: 'const a = 1, anyTest = require(\'ava\'), b = 2;', filename: 'file.tsx'},
{code: 'const anyTest = require(\'foo\');', filename: 'file.tsx'},
{code: 'import anyTest from \'ava\';', filename: 'file.tsx'},
{code: 'import anyTest, {} from \'ava\';', filename: 'file.tsx'},
{code: 'import anyTest from \'foo\';', filename: 'file.tsx'}
],
invalid: [
{
code: 'var ava = require(\'ava\');',
errors
errors,
filename: 'file.ts'
},
{
code: 'let ava = require(\'ava\');',
errors
errors,
filename: 'file.ts'
},
{
code: 'const ava = require(\'ava\');',
errors
errors,
filename: 'file.ts'
},
{
code: 'const a = 1, ava = require(\'ava\'), b = 2;',
errors
errors,
filename: 'file.ts'
},
{
code: 'import ava from \'ava\';',
errors
errors,
filename: 'file.ts'
},
{
code: 'var anyTest = require(\'ava\');',
errors,
filename: 'file.js'
},
{
code: 'var ava = require(\'ava\');',
errors,
filename: 'file.ts'
},
{
code: 'let ava = require(\'ava\');',
errors,
filename: 'file.ts'
},
{
code: 'const ava = require(\'ava\');',
errors,
filename: 'file.ts'
},
{
code: 'const a = 1, ava = require(\'ava\'), b = 2;',
errors,
filename: 'file.ts'
},
{
code: 'import ava from \'ava\';',
errors,
filename: 'file.ts'
},
{
code: 'var ava = require(\'ava\');',
errors,
filename: 'file.tsx'
},
{
code: 'let ava = require(\'ava\');',
errors,
filename: 'file.tsx'
},
{
code: 'const ava = require(\'ava\');',
errors,
filename: 'file.tsx'
},
{
code: 'const a = 1, ava = require(\'ava\'), b = 2;',
errors,
filename: 'file.tsx'
},
{
code: 'import ava from \'ava\';',
errors,
filename: 'file.tsx'
}
]
});

0 comments on commit 524594d

Please sign in to comment.