diff --git a/lib/createBannedAttributeRule.js b/lib/createBannedAttributeRule.js index 5939327..394671b 100644 --- a/lib/createBannedAttributeRule.js +++ b/lib/createBannedAttributeRule.js @@ -32,6 +32,39 @@ module.exports = ({ preferred, negatedPreferred, attributes }) => context => { }); } }, + + "CallExpression[callee.property.name=/toBe(Truthy|Falsy)?|toEqual/][callee.object.callee.name='expect']"( + node + ) { + const { + arguments: [{ property, property: { name } = {} }], + } = node.callee.object; + const matcher = node.callee.property.name; + const matcherArg = node.arguments.length && node.arguments[0].value; + if (attributes.some(attr => attr === name)) { + const isNegated = + matcher.endsWith('Falsy') || + ((matcher === 'toBe' || matcher === 'toEqual') && + matcherArg !== true); + const correctFunction = getCorrectFunctionFor( + node.callee.object, + isNegated + ); + context.report({ + node, + message: `Use ${correctFunction}() instead of checking .${name} directly`, + fix(fixer) { + return [ + fixer.removeRange([property.start - 1, property.end]), + fixer.replaceTextRange( + [node.callee.property.start, node.end], + `${correctFunction}()` + ), + ]; + }, + }); + } + }, "CallExpression[callee.property.name=/toHaveProperty|toHaveAttribute/][callee.object.property.name='not'][callee.object.object.callee.name='expect']"( node ) { diff --git a/tests/fixtures/createBannedAttributeTestCases.js b/tests/fixtures/createBannedAttributeTestCases.js index 13b3886..32d07e6 100644 --- a/tests/fixtures/createBannedAttributeTestCases.js +++ b/tests/fixtures/createBannedAttributeTestCases.js @@ -22,6 +22,38 @@ module.exports = ({ preferred, negatedPreferred, attribute }) => { }, ]; } + let directChecks = []; + if (!/-/.test(attribute)) { + directChecks = [ + { + code: `expect(getByText('foo').${attribute}).toBeTruthy()`, + errors: [ + { + message: `Use ${preferred} instead of checking .${attribute} directly`, + }, + ], + output: `expect(getByText('foo')).${[preferred]}`, + }, + { + code: `expect(getByText('foo').${attribute}).toBeFalsy()`, + errors: [ + { + message: `Use ${negatedPreferred} instead of checking .${attribute} directly`, + }, + ], + output: `expect(getByText('foo')).${[negatedPreferred]}`, + }, + { + code: `expect(getByText('foo').${attribute}).toBe(true)`, + errors: [ + { + message: `Use ${preferred} instead of checking .${attribute} directly`, + }, + ], + output: `expect(getByText('foo')).${[preferred]}`, + }, + ]; + } return { valid: [ `expect(element).not.toHaveProperty('value', 'foo')`, @@ -31,6 +63,7 @@ module.exports = ({ preferred, negatedPreferred, attribute }) => { ], invalid: [ ...doubleNegativeCases, + ...directChecks, { code: `expect(element).toHaveProperty('${attribute}', true)`, errors: [