diff --git a/src/__tests__/__fixtures__/createBannedAttributeTestCases.js b/src/__tests__/__fixtures__/createBannedAttributeTestCases.js index 957b70d..3a3adb8 100644 --- a/src/__tests__/__fixtures__/createBannedAttributeTestCases.js +++ b/src/__tests__/__fixtures__/createBannedAttributeTestCases.js @@ -39,6 +39,15 @@ export default ({ preferred, negatedPreferred, attribute }) => { ], output: `const el = screen.getByText("foo"); expect(el).${negatedPreferred}`, }, + { + code: `const el = screen.getByRole("button"); expect(el).not.${preferred}`, + errors: [ + { + message: `Use ${negatedPreferred} instead of not.${preferred}`, + }, + ], + output: `const el = screen.getByRole("button"); expect(el).${negatedPreferred}`, + }, ] : []; const directChecks = /-/.test(attribute) @@ -63,13 +72,22 @@ export default ({ preferred, negatedPreferred, attribute }) => { output: `expect(getByText('foo')).${[negatedPreferred]}`, }, { - code: `expect(getByText('foo').${attribute}).toBe(true)`, + code: `const el = getByText('foo'); expect(el.${attribute}).toBe(true)`, errors: [ { message: `Use ${preferred} instead of checking .${attribute} directly`, }, ], - output: `expect(getByText('foo')).${[preferred]}`, + output: `const el = getByText('foo'); expect(el).${[preferred]}`, + }, + { + code: `const el = getByRole('button'); expect(el.${attribute}).toBe(true)`, + errors: [ + { + message: `Use ${preferred} instead of checking .${attribute} directly`, + }, + ], + output: `const el = getByRole('button'); expect(el).${[preferred]}`, }, ]; @@ -203,6 +221,14 @@ export default ({ preferred, negatedPreferred, attribute }) => { }, ], }, + { + code: `const el = getByRole("button", { name: 'My Button' }); expect(el).toHaveProperty('${attribute}', foo)`, + errors: [ + { + message: `Use ${preferred} instead of toHaveProperty('${attribute}', foo)`, + }, + ], + }, ], }; }; diff --git a/src/assignment-ast.js b/src/assignment-ast.js index 4f5e987..e923af2 100644 --- a/src/assignment-ast.js +++ b/src/assignment-ast.js @@ -5,17 +5,20 @@ import { queries } from "./queries"; * await someAsyncFunc() => someAsyncFunc() * someElement as HTMLDivElement => someElement * + * @param {Object} context - Context for a rule * @param {Object} expression - An expression node * @returns {Object} - A node */ -export function getInnerNodeFrom(expression) { +export function getInnerNodeFrom(context, expression) { switch (expression.type) { + case "Identifier": + return getAssignmentForIdentifier(context, expression.name); case "TSAsExpression": - return getInnerNodeFrom(expression.expression); + return getInnerNodeFrom(context, expression.expression); case "AwaitExpression": - return getInnerNodeFrom(expression.argument); + return getInnerNodeFrom(context, expression.argument); case "MemberExpression": - return getInnerNodeFrom(expression.object); + return getInnerNodeFrom(context, expression.object); default: return expression; } @@ -37,7 +40,7 @@ export function getAssignmentForIdentifier(context, identifierName) { let assignmentNode; if (init) { // let foo = bar; - assignmentNode = getInnerNodeFrom(init); + assignmentNode = getInnerNodeFrom(context, init); } else { // let foo; // foo = bar; @@ -47,7 +50,7 @@ export function getAssignmentForIdentifier(context, identifierName) { if (!assignmentRef) { return; } - assignmentNode = getInnerNodeFrom(assignmentRef.writeExpr); + assignmentNode = getInnerNodeFrom(context, assignmentRef.writeExpr); } return assignmentNode; } @@ -61,10 +64,7 @@ export function getAssignmentForIdentifier(context, identifierName) { * @returns {Object} - Object with query, queryArg & isDTLQuery */ export function getQueryNodeFrom(context, nodeWithValueProp) { - const queryNode = - nodeWithValueProp.type === "Identifier" - ? getAssignmentForIdentifier(context, nodeWithValueProp.name) - : getInnerNodeFrom(nodeWithValueProp); + const queryNode = getInnerNodeFrom(context, nodeWithValueProp); if (!queryNode || !queryNode.callee) { return {