Skip to content

Commit

Permalink
feat: support providing aliases for @jest/globals package (#1543)
Browse files Browse the repository at this point in the history
  • Loading branch information
G-Rath committed Apr 6, 2024
1 parent 8f59e2b commit 744d4f6
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 3 deletions.
21 changes: 21 additions & 0 deletions README.md
Expand Up @@ -87,6 +87,27 @@ You can tell this plugin about any global Jests you have aliased using the
}
```

#### Aliased `@jest/globals`

You can tell this plugin to treat a different package as the source of Jest
globals using the `globalPackage` setting:

```json
{
"settings": {
"jest": {
"globalPackage": "bun:test"
}
}
}
```

> [!WARNING]
>
> While this can be used to apply rules when using alternative testing libraries
> and frameworks like `bun`, `vitest` and `node`, there's no guarantee the
> semantics this plugin assumes will hold outside of Jest
### Running rules only on test-related files

The rules provided by this plugin assume that the files they are checking are
Expand Down
192 changes: 192 additions & 0 deletions src/rules/utils/__tests__/parseJestFnCall.test.ts
Expand Up @@ -737,6 +737,198 @@ ruleTester.run('global aliases', rule, {
],
});

ruleTester.run('global package source', rule, {
valid: [
{
code: dedent`
import { expect } from 'bun:test'
expect(x).toBe(y);
`,
parserOptions: { sourceType: 'module' },
settings: { jest: { globalPackage: '@jest/globals' } },
},
{
code: dedent`
const { it } = require('@jest/globals');
it('is not considered a test function', () => {});
`,
parserOptions: { sourceType: 'script' },
settings: { jest: { globalPackage: 'bun:test' } },
},
{
code: dedent`
const { fn: it } = require('bun:test');
it('is not considered a test function', () => {});
`,
parserOptions: { sourceType: 'script' },
settings: { jest: { globalPackage: 'bun:test' } },
},
{
code: dedent`
import { it } from '@jest/globals';
it('is not considered a test function', () => {});
`,
parserOptions: { sourceType: 'module' },
settings: { jest: { globalPackage: 'bun:test' } },
},
{
code: dedent`
import { fn as it } from 'bun:test';
it('is not considered a test function', () => {});
`,
parserOptions: { sourceType: 'module' },
settings: { jest: { globalPackage: 'bun:test' } },
},
],
invalid: [
{
code: 'expect(x).toBe(y);',
parserOptions: { sourceType: 'script' },
errors: [
{
messageId: 'details' as const,
data: expectedParsedJestFnCallResultData({
name: 'expect',
type: 'expect',
head: {
original: null,
local: 'expect',
type: 'global',
node: 'expect',
},
members: ['toBe'],
}),
column: 1,
line: 1,
},
],
settings: { jest: { globalPackage: 'bun:test' } },
},
{
code: dedent`
import { describe, expect, it } from 'bun:test'
describe('some tests', () => {
it('ensures something', () => {
expect.assertions();
});
});
`,
parserOptions: { sourceType: 'module' },
errors: [
{
messageId: 'details' as const,
data: expectedParsedJestFnCallResultData({
name: 'describe',
type: 'describe',
head: {
original: 'describe',
local: 'describe',
type: 'import',
node: 'describe',
},
members: [],
}),
column: 1,
line: 3,
},
{
messageId: 'details' as const,
data: expectedParsedJestFnCallResultData({
name: 'it',
type: 'test',
head: {
original: 'it',
local: 'it',
type: 'import',
node: 'it',
},
members: [],
}),
column: 3,
line: 4,
},
{
messageId: 'details' as const,
data: expectedParsedJestFnCallResultData({
name: 'expect',
type: 'expect',
head: {
original: 'expect',
local: 'expect',
type: 'import',
node: 'expect',
},
members: ['assertions'],
}),
column: 5,
line: 5,
},
],
settings: { jest: { globalPackage: 'bun:test' } },
},
{
code: dedent`
import { expect } from 'bun:test'
expect(x).not.toBe(y);
`,
parserOptions: { sourceType: 'module' },
errors: [
{
messageId: 'details' as const,
data: expectedParsedJestFnCallResultData({
name: 'expect',
type: 'expect',
head: {
original: 'expect',
local: 'expect',
type: 'import',
node: 'expect',
},
members: ['not', 'toBe'],
}),
column: 1,
line: 3,
},
],
settings: { jest: { globalPackage: 'bun:test' } },
},
{
code: 'context("when there is an error", () => {})',
errors: [
{
messageId: 'details' as const,
data: expectedParsedJestFnCallResultData({
name: 'describe',
type: 'describe',
head: {
original: 'describe',
local: 'context',
type: 'global',
node: 'context',
},
members: [],
}),
column: 1,
line: 1,
},
],
settings: {
jest: {
globalPackage: 'bun:test',
globalAliases: { describe: ['context'] },
},
},
},
],
});

ruleTester.run('typescript', rule, {
valid: [
{
Expand Down
10 changes: 7 additions & 3 deletions src/rules/utils/parseJestFnCall.ts
Expand Up @@ -188,6 +188,7 @@ const ValidJestFnCallChains = [
interface SharedConfigurationSettings {
jest?: {
globalAliases?: Record<string, string[]>;
globalPackage?: string;
version?: number | string;
};
}
Expand Down Expand Up @@ -584,9 +585,12 @@ const resolveToJestFn = (
}

if (maybeImport) {
// the identifier is imported from @jest/globals,
// so return the original import name
if (maybeImport.source === '@jest/globals') {
const globalPackage =
(context.settings as SharedConfigurationSettings).jest?.globalPackage ??
'@jest/globals';

// the identifier is imported from our global package so return the original import name
if (maybeImport.source === globalPackage) {
return {
original: maybeImport.imported,
local: maybeImport.local,
Expand Down

0 comments on commit 744d4f6

Please sign in to comment.