Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: prefer importing jest globals for specific types #1568

Merged
merged 2 commits into from
Apr 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions docs/rules/prefer-importing-jest-globals.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,42 @@ describe('foo', () => {
});
```

## Options

This rule can be configured as follows

```json
{
"type": "object",
"properties": {
"types": {
"type": "array",
"items": {
"type": "string",
"enum": ["hook", "describe", "test", "expect", "jest", "unknown"]
}
}
},
"additionalProperties": false
}
```

#### types

A list of Jest global types to enforce explicit imports for. By default, all
Jest globals are enforced.

This option is useful when you only want to enforce explicit imports for a
subset of Jest globals. For instance, when migrating to ESM, you might want to
enforce explicit imports only for the `jest` global, as of
[Jest's ESM documentation](https://jestjs.io/docs/ecmascript-modules#differences-between-esm-and-commonjs).

```json5
{
'jest/prefer-importing-jest-globals': ['error', { types: ['jest'] }],
}
```

## Further Reading

- [Documentation](https://jestjs.io/docs/api)
46 changes: 46 additions & 0 deletions src/rules/__tests__/prefer-importing-jest-globals.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,25 @@ ruleTester.run('prefer-importing-jest-globals', rule, {
`,
parserOptions: { sourceType: 'module' },
},
{
code: dedent`
test('should pass', () => {
expect(true).toBeDefined();
});
`,
options: [{ types: ['jest'] }],
parserOptions: { sourceType: 'module' },
},
{
code: dedent`
const { it } = require('@jest/globals');
it('should pass', () => {
expect(true).toBeDefined();
});
`,
options: [{ types: ['test'] }],
parserOptions: { sourceType: 'module' },
},
{
code: dedent`
// with require
Expand Down Expand Up @@ -85,6 +104,33 @@ ruleTester.run('prefer-importing-jest-globals', rule, {
},
],
},
{
code: dedent`
jest.useFakeTimers();
describe("suite", () => {
test("foo");
expect(true).toBeDefined();
})
`,
output: dedent`
import { jest } from '@jest/globals';
jest.useFakeTimers();
describe("suite", () => {
test("foo");
expect(true).toBeDefined();
})
`,
options: [{ types: ['jest'] }],
parserOptions: { sourceType: 'module' },
errors: [
{
endColumn: 5,
column: 1,
line: 1,
messageId: 'preferImportingJestGlobal',
},
],
},
{
code: dedent`
import React from 'react';
Expand Down
38 changes: 35 additions & 3 deletions src/rules/prefer-importing-jest-globals.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { AST_NODE_TYPES, type TSESTree } from '@typescript-eslint/utils';
import {
type JestFnType,
createRule,
getAccessorValue,
getSourceCode,
Expand All @@ -20,6 +21,15 @@ const createFixerImports = (
: `const { ${allImportsFormatted} } = require('@jest/globals');`;
};

const allJestFnTypes: JestFnType[] = [
'hook',
'describe',
'test',
'expect',
'jest',
'unknown',
];

export default createRule({
name: __filename,
meta: {
Expand All @@ -31,10 +41,29 @@ export default createRule({
},
fixable: 'code',
type: 'problem',
schema: [],
schema: [
{
type: 'object',
properties: {
types: {
type: 'array',
items: {
type: 'string',
enum: allJestFnTypes,
},
},
},
additionalProperties: false,
},
],
},
defaultOptions: [],
defaultOptions: [
{
types: allJestFnTypes as JestFnType[],
},
],
G-Rath marked this conversation as resolved.
Show resolved Hide resolved
create(context) {
const { types = allJestFnTypes } = context.options[0] || {};
const importedFunctionsWithSource: Record<string, string> = {};
const functionsToImport = new Set<string>();
let reportingNode: TSESTree.Node;
Expand All @@ -55,7 +84,10 @@ export default createRule({
return;
}

if (jestFnCall.head.type !== 'import') {
if (
jestFnCall.head.type !== 'import' &&
types.includes(jestFnCall.type)
) {
functionsToImport.add(jestFnCall.name);
reportingNode ||= jestFnCall.head.node;
}
Expand Down
Loading