Skip to content

Commit

Permalink
Feat/no conditional tests (#370)
Browse files Browse the repository at this point in the history
* x

* fix(no-conditional-tests): fixed rule and added some test cases

* fix(minor fixes): minor fixes

* fix(minor fix): no-conditional-tests
  • Loading branch information
veritem committed Feb 6, 2024
1 parent 536d88e commit 82b1fe9
Show file tree
Hide file tree
Showing 10 changed files with 313 additions and 432 deletions.
5 changes: 3 additions & 2 deletions fixtures/.eslintrc
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"extends": [
"plugin:vitest/recommended"
"plugin:vitest/all"
],
"rules": {
"vitest/unbound-method": "off"
"vitest/unbound-method": "off",
"vitest/prefer-expect-assertions": "off"
}
}
82 changes: 43 additions & 39 deletions fixtures/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions fixtures/tests/conditional.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { expect, it, describe } from 'vitest'

describe('conditionals', () => {
it('should run only if condition is true', () => {
expect(true).toBeTruthy()
})

it('should error one errors only', () => {
if (true) {
function foo() {
console.log('foo')
}
foo()
}

expect(true).toBeTruthy()
})
})
2 changes: 0 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ import preferSpyOn, { RULE_NAME as preferSpyOnName } from './rules/prefer-spy-on
import preferComparisonMatcher, { RULE_NAME as preferComparisonMatcherName } from './rules/prefer-comparison-matcher'
import preferToContain, { RULE_NAME as preferToContainName } from './rules/prefer-to-contain'
import preferExpectAssertions, { RULE_NAME as preferExpectAssertionsName } from './rules/prefer-expect-assertions'
// import unboundMethod, { RULE_NAME as unboundMethodName } from './rules/unbound-method'

const createConfig = (rules: Record<string, string>) => ({
plugins: ['vitest'],
Expand Down Expand Up @@ -174,7 +173,6 @@ export default {
[preferComparisonMatcherName]: preferComparisonMatcher,
[preferToContainName]: preferToContain,
[preferExpectAssertionsName]: preferExpectAssertions
// [unboundMethodName]: unboundMethod
},
configs: {
all: createConfig(allRules),
Expand Down
27 changes: 6 additions & 21 deletions src/rules/no-conditional-in-test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { TSESTree } from '@typescript-eslint/utils'
import { createEslintRule } from '../utils'
import { isTypeOfVitestFnCall } from '../utils/parseVitestFnCall'

Expand All @@ -22,26 +21,12 @@ export default createEslintRule<Options, MESSAGE_IDS>({
},
defaultOptions: [],
create(context) {
let inTestCase = false

const reportCondional = (node: TSESTree.Node) => {
if (inTestCase)
context.report({ messageId: 'noConditionalInTest', node })
}

return {
CallExpression(node) {
if (isTypeOfVitestFnCall(node, context, ['test']))
inTestCase = true
},
'CallExpression:exit'(node) {
if (isTypeOfVitestFnCall(node, context, ['test']))
inTestCase = false
},
IfStatement: reportCondional,
SwitchStatement: reportCondional,
ConditionalExpression: reportCondional,
LogicalExpression: reportCondional
IfStatement(node) {
if(node.parent?.parent?.parent?.type === "CallExpression" && isTypeOfVitestFnCall(node.parent?.parent?.parent, context, ['test','it'])) {
context.report({ messageId: 'noConditionalInTest', node })
}
},
}
}
})
})
43 changes: 10 additions & 33 deletions src/rules/no-conditional-tests.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// Got inspirations from https://github.com/shokai/eslint-plugin-if-in-test

import { TSESTree } from '@typescript-eslint/utils/dist/ts-estree'
import { createEslintRule } from '../utils'

Expand All @@ -16,42 +14,21 @@ export default createEslintRule<[], MESSAGE_ID>({
},
schema: [],
messages: {
noConditionalTests: 'Avoid using conditionals in a test.'
noConditionalTests: 'Avoid using if conditions in a test.'
}
},
defaultOptions: [],
create(context) {
let isInTestBlock = false

function checkIfItsUnderTestOrItBlock(node: TSESTree.Node) {
if (
node.type === 'CallExpression' &&
node.callee.type === 'Identifier' &&
(node.callee.name === 'it' || node.callee.name === 'test')
)
return true
}

function reportConditional(node: TSESTree.Node) {
if (isInTestBlock) {
context.report({
node,
messageId: 'noConditionalTests'
})
}
}

return {
CallExpression: function (node: TSESTree.CallExpression) {
if (checkIfItsUnderTestOrItBlock(node)) isInTestBlock = true
},
'CallExpression:exit': function (node: TSESTree.CallExpression) {
if (checkIfItsUnderTestOrItBlock(node)) isInTestBlock = false
},
IfStatement: reportConditional,
SwitchStatement: reportConditional,
LogicalExpression: reportConditional,
ConditionalExpression: reportConditional
Identifier: function (node: TSESTree.Identifier) {
if(["test","it","describe"].includes(node.name))
if(node.parent?.parent?.parent?.parent?.type === "IfStatement") {
context.report({
node,
messageId: 'noConditionalTests'
})
}
},
}
}
})
Loading

0 comments on commit 82b1fe9

Please sign in to comment.