From aa7bb657e8de87a169840f7671be97e7cdefffe3 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Fri, 29 Apr 2022 11:28:04 +1200 Subject: [PATCH] chore: clean up code & tests more --- src/rules/__tests__/expect-expect.test.ts | 267 ---------------------- src/rules/__tests__/utils.test.ts | 149 ++++++++++++ src/rules/utils.ts | 47 +--- 3 files changed, 155 insertions(+), 308 deletions(-) diff --git a/src/rules/__tests__/expect-expect.test.ts b/src/rules/__tests__/expect-expect.test.ts index 1b11686b6..88617888f 100644 --- a/src/rules/__tests__/expect-expect.test.ts +++ b/src/rules/__tests__/expect-expect.test.ts @@ -273,270 +273,3 @@ ruleTester.run('wildcards', rule, { }, ], }); - -ruleTester.run('non-jest functions (commonjs)', rule, { - valid: [ - { - code: dedent` - const { test } = require('./test-fn'); - - describe(test, () => { - it('should do something good', () => { - expect(test({})).toBeDefined(); - }); - }); - `, - }, - { - code: dedent` - const { test: testWithJest } = require('@jest/globals'); - const { test } = require('./test-fn'); - - describe(test, () => { - testWithJest('should do something good', () => { - expect(test({})).toBeDefined(); - }); - }); - `, - }, - ], - invalid: [ - { - code: dedent` - const { test: testWithJest } = require('@jest/globals'); - - it('should do something good', () => { - expect(testWithJest({})).toBeDefined(); - }); - `, - parserOptions: { sourceType: 'module' }, - errors: [ - { - messageId: 'noAssertions', - type: AST_NODE_TYPES.CallExpression, - }, - ], - }, - { - code: dedent` - const { test: testWithJest } = require('@jest/globals'); - - describe(test, () => { - it('should do something good', () => { - expect(testWithJest({})).toBeDefined(); - }); - }); - `, - parserOptions: { sourceType: 'module' }, - errors: [ - { - messageId: 'noAssertions', - type: AST_NODE_TYPES.CallExpression, - }, - ], - }, - { - code: dedent` - const { test: testWithJest } = require('@jest/globals'); - const { test } = require('./test-fn'); - - describe(test, () => { - testWithJest('should do something good', () => { - // - }); - }); - `, - errors: [ - { - messageId: 'noAssertions', - type: AST_NODE_TYPES.CallExpression, - }, - ], - }, - ], -}); - -ruleTester.run('non-jest functions (esm)', rule, { - valid: [ - { - code: dedent` - it('should do something good', () => { - const test = obj => {}; - - expect(test({})).toBeDefined(); - }); - `, - parserOptions: { sourceType: 'module' }, - }, - { - code: dedent` - const test = obj => {}; - - it('should do something good', () => { - expect(test({})).toBeDefined(); - }); - `, - parserOptions: { sourceType: 'module' }, - }, - { - code: dedent` - const test = obj => {}; - - describe(test, () => { - it('should do something good', () => { - expect(test({})).toBeDefined(); - }); - }); - `, - parserOptions: { sourceType: 'module' }, - }, - { - code: dedent` - import { test } from './test-fn'; - - describe(test, () => { - it('should do something good', () => { - expect(test({})).toBeDefined(); - }); - }); - `, - parserOptions: { sourceType: 'module' }, - }, - { - code: dedent` - import { test as testWithJest } from '@jest/globals'; - import { test } from './test-fn'; - - describe(test, () => { - testWithJest('should do something good', () => { - expect(test({})).toBeDefined(); - }); - }); - `, - parserOptions: { sourceType: 'module' }, - }, - ], - invalid: [ - { - code: dedent` - import { it } from '@jest/globals'; - - it('should do something good', () => { - // - }); - `, - parserOptions: { sourceType: 'module' }, - errors: [ - { - messageId: 'noAssertions', - type: AST_NODE_TYPES.CallExpression, - }, - ], - }, - { - code: dedent` - import { test } from '@jest/globals'; - - it('should do something good', () => { - expect(test({})).toBeDefined(); - }); - `, - parserOptions: { sourceType: 'module' }, - errors: [ - { - messageId: 'noAssertions', - type: AST_NODE_TYPES.CallExpression, - }, - ], - }, - { - code: dedent` - import { test } from '@jest/globals'; - - describe('value', () => { - it('should do something good', () => { - expect(test({})).toBeDefined(); - }); - }); - `, - parserOptions: { sourceType: 'module' }, - errors: [ - { - messageId: 'noAssertions', - type: AST_NODE_TYPES.CallExpression, - }, - ], - }, - { - code: dedent` - import { describe, it } from '@jest/globals'; - - describe('my tests', () => { - it('should do something good', () => { - // - }); - }); - `, - parserOptions: { sourceType: 'module' }, - errors: [ - { - messageId: 'noAssertions', - type: AST_NODE_TYPES.CallExpression, - }, - ], - }, - { - code: dedent` - import { test as testWithJest } from '@jest/globals'; - - describe(test, () => { - it('should do something good', () => { - expect(testWithJest({})).toBeDefined(); - }); - }); - `, - parserOptions: { sourceType: 'module' }, - errors: [ - { - messageId: 'noAssertions', - type: AST_NODE_TYPES.CallExpression, - }, - ], - }, - { - code: dedent` - import { test as testWithJest } from '@jest/globals'; - import { test } from './test-fn'; - - describe(test, () => { - testWithJest('should do something good', () => { - // - }); - }); - `, - parserOptions: { sourceType: 'module' }, - errors: [ - { - messageId: 'noAssertions', - type: AST_NODE_TYPES.CallExpression, - }, - ], - }, - { - code: dedent` - const { test: testWithJest } = import('@jest/globals'); - - it('should do something good', () => { - expect(testWithJest({})).toBeDefined(); - }); - `, - parserOptions: { sourceType: 'module' }, - errors: [ - { - messageId: 'noAssertions', - type: AST_NODE_TYPES.CallExpression, - }, - ], - }, - ], -}); diff --git a/src/rules/__tests__/utils.test.ts b/src/rules/__tests__/utils.test.ts index aee8de7e8..e4269ad2f 100644 --- a/src/rules/__tests__/utils.test.ts +++ b/src/rules/__tests__/utils.test.ts @@ -350,6 +350,18 @@ describe('reference checking', () => { `, parserOptions: { sourceType: 'module' }, }, + { + code: dedent` + import { defineFeature, loadFeature } from "jest-cucumber"; + + const feature = loadFeature("some/feature"); + + defineFeature(feature, (test) => { + test("A scenario", ({ given, when, then }) => {}); + }); + `, + parserOptions: { sourceType: 'module' }, + }, { code: dedent` import { describe } from './test-utils'; @@ -366,6 +378,15 @@ describe('reference checking', () => { `, parserOptions: { sourceType: 'module' }, }, + { + code: dedent` + import * as jest from '@jest/globals'; + const { it } = jest; + + it('is not supported', () => {}); + `, + parserOptions: { sourceType: 'module' }, + }, ], invalid: [ { @@ -470,6 +491,41 @@ describe('reference checking', () => { }, ], }, + { + code: dedent` + import { test as testWithJest } from '@jest/globals'; + const test = () => {}; + + describe(test, () => { + testWithJest('should do something good', () => { + expect(test({})).toBeDefined(); + }); + }); + `, + parserOptions: { sourceType: 'module' }, + errors: [ + { + messageId: 'details' as const, + data: { + callType: 'describe', + numOfArgs: 2, + nodeName: 'describe', + }, + column: 1, + line: 4, + }, + { + messageId: 'details' as const, + data: { + callType: 'test', + numOfArgs: 2, + nodeName: 'testWithJest', + }, + column: 3, + line: 5, + }, + ], + }, ], }); @@ -483,6 +539,14 @@ describe('reference checking', () => { `, parserOptions: { sourceType: 'script' }, }, + { + code: dedent` + const { it } = require(\`./test-utils\`); + + it('is not a jest function', () => {}); + `, + parserOptions: { sourceType: 'script' }, + }, { code: dedent` const { describe } = require('./test-utils'); @@ -499,6 +563,46 @@ describe('reference checking', () => { `, parserOptions: { sourceType: 'script' }, }, + { + code: dedent` + const { fn: it } = require('@jest/globals'); + + it('is not considered a test function', () => {}); + `, + parserOptions: { sourceType: 'script' }, + }, + { + code: dedent` + const { it } = aliasedRequire('@jest/globals'); + + it('is not considered a jest function', () => {}); + `, + parserOptions: { sourceType: 'script' }, + }, + { + code: dedent` + const { it } = require(); + + it('is not a jest function', () => {}); + `, + parserOptions: { sourceType: 'script' }, + }, + { + code: dedent` + const { it } = require(pathToMyPackage); + + it('is not a jest function', () => {}); + `, + parserOptions: { sourceType: 'script' }, + }, + { + code: dedent` + const { it } = require(pathToMyPackage); + + it('is not a jest function', () => {}); + `, + parserOptions: { sourceType: 'script' }, + }, ], invalid: [ { @@ -521,6 +625,26 @@ describe('reference checking', () => { }, ], }, + { + code: dedent` + const { describe } = require(\`@jest/globals\`); + + describe('is a jest function', () => {}); + `, + parserOptions: { sourceType: 'script' }, + errors: [ + { + messageId: 'details' as const, + data: { + callType: 'describe', + numOfArgs: 2, + nodeName: 'describe', + }, + column: 1, + line: 3, + }, + ], + }, { code: dedent` const { it } = require('@jest/globals'); @@ -605,4 +729,29 @@ describe('reference checking', () => { }, ], }); + + ruleTester.run('typescript', rule, { + valid: [ + { + code: dedent` + import type { it } from '@jest/globals'; + + it('is not a jest function', () => {}); + `, + parser: require.resolve('@typescript-eslint/parser'), + parserOptions: { sourceType: 'module' }, + }, + { + code: dedent` + import jest = require('@jest/globals'); + const { it } = jest; + + it('is not a jest function', () => {}); + `, + parser: require.resolve('@typescript-eslint/parser'), + parserOptions: { sourceType: 'module' }, + }, + ], + invalid: [], + }); }); diff --git a/src/rules/utils.ts b/src/rules/utils.ts index 333adba78..7b7ab4203 100644 --- a/src/rules/utils.ts +++ b/src/rules/utils.ts @@ -676,40 +676,6 @@ export const getTestCallExpressionsFromDeclaredVariables = ( ); }; -const isTestCaseName = (node: TSESTree.LeftHandSideExpression) => - node.type === AST_NODE_TYPES.Identifier && - TestCaseName.hasOwnProperty(node.name); - -const isTestCaseProperty = ( - node: TSESTree.Expression | TSESTree.PrivateIdentifier, -): node is AccessorNode => - isSupportedAccessor(node) && - TestCaseProperty.hasOwnProperty(getAccessorValue(node)); - -/** - * Checks if the given `node` is a *call* to a test case function that would - * result in tests being run by `jest`. - * - * Note that `.each()` does not count as a call in this context, as it will not - * result in `jest` running any tests. - */ -export const isTestCaseCall2 = ( - node: TSESTree.CallExpression, - scope?: TSESLint.Scope.Scope, -): node is JestFunctionCallExpression => { - const name = findFirstCallPropertyName(node, Object.keys(TestCaseProperty)); - - if (!!name && TestCaseName.hasOwnProperty(name)) { - if (!scope) { - return true; - } - - return !scopeHasLocalReference(scope, name); - } - - return false; -}; - /** * Checks if the given `node` is a *call* to a test case function that would * result in tests being run by `jest`. @@ -817,6 +783,11 @@ const describeImportDefAsImport = ( return null; } + // we only care about value imports + if (def.parent.importKind === 'type') { + return null; + } + return { source: def.parent.source.value, imported: def.node.imported.name, @@ -872,7 +843,7 @@ const describeVariableDefAsImport = ( if ( def.node.init.type !== AST_NODE_TYPES.ImportExpression && (def.node.init.type !== AST_NODE_TYPES.CallExpression || - isStringNode(def.node.init.callee, 'require')) + !isIdentifier(def.node.init.callee, 'require')) ) { return null; } @@ -1001,11 +972,5 @@ export const resolveToJestFn = ( return null; } - // the identifier was not found as an unresolved reference, - // meaning it's unlikely to be an implicit global variable - if (!references.unresolved.has(identifier)) { - return null; - } - return identifier; };