89 lines
4.8 KiB
JavaScript
89 lines
4.8 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.meta = exports.create = void 0;
|
||
|
/**
|
||
|
* @fileoverview prefer toHaveAttribute over checking getAttribute/hasAttribute
|
||
|
* @author Ben Monro
|
||
|
*/
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Rule Definition
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
const meta = {
|
||
|
docs: {
|
||
|
category: "Best Practices",
|
||
|
description: "prefer toHaveAttribute over checking getAttribute/hasAttribute ",
|
||
|
url: "prefer-to-have-attribute",
|
||
|
recommended: true
|
||
|
},
|
||
|
fixable: "code"
|
||
|
};
|
||
|
exports.meta = meta;
|
||
|
const create = context => ({
|
||
|
[`CallExpression[callee.property.name='getAttribute'][parent.callee.name='expect'][parent.parent.property.name=/toBeNull/]`](node) {
|
||
|
context.report({
|
||
|
node: node.parent,
|
||
|
message: `Use toHaveAttribute instead of asserting on getAttribute`,
|
||
|
fix: fixer => [fixer.removeRange([node.callee.object.range[1], node.range[1]]), fixer.replaceTextRange([node.parent.parent.property.range[0], node.parent.parent.parent.range[1]], `not.toHaveAttribute(${context.getSourceCode().getText(node.arguments[0])})`)]
|
||
|
});
|
||
|
},
|
||
|
[`CallExpression[callee.property.name='getAttribute'][parent.callee.name='expect'][parent.parent.property.name=/toContain$|toMatch$/]`](node) {
|
||
|
const sourceCode = context.getSourceCode();
|
||
|
context.report({
|
||
|
node: node.parent,
|
||
|
message: `Use toHaveAttribute instead of asserting on getAttribute`,
|
||
|
fix: fixer => [fixer.removeRange([node.callee.object.range[1], node.range[1]]), fixer.replaceText(node.parent.parent.property, "toHaveAttribute"), fixer.replaceText(node.parent.parent.parent.arguments[0], `${sourceCode.getText(node.arguments[0])}, expect.string${node.parent.parent.property.name.slice(2)}ing(${sourceCode.getText(node.parent.parent.parent.arguments[0])})`)]
|
||
|
});
|
||
|
},
|
||
|
[`CallExpression[callee.property.name='getAttribute'][parent.callee.name='expect'][parent.parent.property.name=/toBe$|to(Strict)?Equal/]`](node) {
|
||
|
const arg = node.parent.parent.parent.arguments;
|
||
|
const isNull = arg.length > 0 && arg[0].value === null;
|
||
|
const sourceCode = context.getSourceCode();
|
||
|
context.report({
|
||
|
node: node.parent,
|
||
|
message: `Use toHaveAttribute instead of asserting on getAttribute`,
|
||
|
fix: fixer => {
|
||
|
const lastFixer = isNull ? fixer.replaceText(node.parent.parent.parent.arguments[0], sourceCode.getText(node.arguments[0])) : fixer.insertTextBefore(node.parent.parent.parent.arguments[0], `${sourceCode.getText(node.arguments[0])}, `);
|
||
|
return [fixer.removeRange([node.callee.object.range[1], node.range[1]]), fixer.replaceText(node.parent.parent.property, `${isNull ? "not." : ""}toHaveAttribute`), lastFixer];
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
[`CallExpression[callee.property.name='hasAttribute'][parent.callee.name='expect'][parent.parent.property.name=/toBeNull|toBeUndefined|toBeDefined/]`](node) {
|
||
|
context.report({
|
||
|
node: node.parent.parent.property,
|
||
|
message: "Invalid matcher for hasAttribute"
|
||
|
});
|
||
|
},
|
||
|
[`CallExpression[callee.property.name='getAttribute'][parent.callee.name='expect'][parent.parent.property.name=/toBeUndefined|toBeDefined/]`](node) {
|
||
|
context.report({
|
||
|
node: node.parent.parent.property,
|
||
|
message: "Invalid matcher for getAttribute"
|
||
|
});
|
||
|
},
|
||
|
[`CallExpression[callee.property.name='hasAttribute'][parent.callee.name='expect'][parent.parent.property.name=/toBe$|to(Strict)?Equal/]`](node) {
|
||
|
if (typeof node.parent.parent.parent.arguments[0].value === "boolean") {
|
||
|
context.report({
|
||
|
node: node.parent,
|
||
|
message: `Use toHaveAttribute instead of asserting on hasAttribute`,
|
||
|
fix: fixer => [fixer.removeRange([node.callee.object.range[1], node.range[1]]), fixer.replaceText(node.parent.parent.property, `${node.parent.parent.parent.arguments[0].value === false ? "not." : ""}toHaveAttribute`), fixer.replaceText(node.parent.parent.parent.arguments[0], context.getSourceCode().getText(node.arguments[0]))]
|
||
|
});
|
||
|
} else {
|
||
|
context.report({
|
||
|
node: node.parent.parent.property,
|
||
|
message: "Invalid matcher for hasAttribute"
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
[`CallExpression[callee.property.name='hasAttribute'][parent.callee.name='expect'][parent.parent.property.name=/toBeTruthy|toBeFalsy/]`](node) {
|
||
|
context.report({
|
||
|
node: node.parent,
|
||
|
message: `Use toHaveAttribute instead of asserting on hasAttribute`,
|
||
|
fix: fixer => [fixer.removeRange([node.callee.object.range[1], node.range[1]]), fixer.replaceTextRange([node.parent.parent.property.range[0], node.parent.parent.parent.range[1]], `${node.parent.parent.property.name === "toBeFalsy" ? "not." : ""}toHaveAttribute(${context.getSourceCode().getText(node.arguments[0])})`)]
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
exports.create = create;
|