eslint-plugin-sonarjs
Version:
104 lines (103 loc) • 4.49 kB
JavaScript
;
/*
* SonarQube JavaScript Plugin
* Copyright (C) SonarSource Sàrl
* mailto:info AT sonarsource DOT com
*
* You can redistribute and/or modify this program under the terms of
* the Sonar Source-Available License Version 1, as published by SonarSource Sàrl.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the Sonar Source-Available License for more details.
*
* You should have received a copy of the Sonar Source-Available License
* along with this program; if not, see https://sonarsource.com/license/ssal/
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPlaywrightLocatorSuggestion = getPlaywrightLocatorSuggestion;
const ast_js_1 = require("../helpers/ast.js");
const module_js_1 = require("../helpers/module.js");
const assertion_utils_js_1 = require("./assertion-utils.js");
const expect_chain_js_1 = require("./expect-chain.js");
const PLAYWRIGHT_BOOLEAN_GETTERS = new Map([
['isVisible', { truthy: 'toBeVisible', falsy: 'toBeHidden' }],
['isHidden', { truthy: 'toBeHidden', falsy: 'toBeVisible' }],
['isEnabled', { truthy: 'toBeEnabled', falsy: 'toBeDisabled' }],
['isDisabled', { truthy: 'toBeDisabled', falsy: 'toBeEnabled' }],
['isChecked', { truthy: 'toBeChecked', falsy: 'not.toBeChecked' }],
]);
const PLAYWRIGHT_VALUE_GETTERS = new Map([
['count', 'toHaveCount'],
['inputValue', 'toHaveValue'],
]);
function getPlaywrightLocatorSuggestion(context, node, sourceCode, locatorVariables) {
const chain = getPlaywrightAssertionChain(context, node);
if (!chain) {
return null;
}
const { getter, locator, negated } = chain;
if (!(0, assertion_utils_js_1.isPlaywrightLocatorExpression)(context, locator, locatorVariables)) {
return null;
}
return (getBooleanGetterSuggestion(getter, locator, node.arguments[0], negated, sourceCode) ??
getValueGetterSuggestion(getter, locator, node.arguments[0], negated, sourceCode));
}
function getPlaywrightAssertionChain(context, node) {
if (!(0, ast_js_1.isMethodCall)(node) ||
!['toBe', 'toEqual', 'toStrictEqual'].includes(node.callee.property.name) ||
node.arguments.length !== 1) {
return null;
}
if (!isPlaywrightExpect(context, node.callee.object)) {
return null;
}
const chain = (0, expect_chain_js_1.getExpectChain)(node.callee.object);
const awaited = chain?.actual.type === 'AwaitExpression' ? chain.actual.argument : undefined;
if (!chain || awaited?.type !== 'CallExpression' || !(0, ast_js_1.isMethodCall)(awaited)) {
return null;
}
if (awaited.arguments.length !== 0) {
return null;
}
return { getter: awaited, locator: awaited.callee.object, negated: chain.negated };
}
function isPlaywrightExpect(context, node) {
const expectCall = getExpectCall(node);
return (expectCall !== null &&
(0, module_js_1.getFullyQualifiedName)(context, expectCall.callee) === '@playwright.test.expect');
}
function getExpectCall(node) {
if (node.type === 'MemberExpression' && !node.computed && (0, ast_js_1.isIdentifier)(node.property, 'not')) {
return getExpectCall(node.object);
}
if (node.type === 'CallExpression' && (0, ast_js_1.isIdentifier)(node.callee, 'expect')) {
return node;
}
return null;
}
function getBooleanGetterSuggestion(getter, locator, expected, negated, sourceCode) {
if (!(0, ast_js_1.isMethodCall)(getter)) {
return null;
}
const matcher = PLAYWRIGHT_BOOLEAN_GETTERS.get(getter.callee.property.name);
const expectedBoolean = (0, assertion_utils_js_1.getBooleanValue)(expected);
if (!matcher || expectedBoolean === undefined) {
return null;
}
const method = expectedBoolean === negated ? matcher.falsy : matcher.truthy;
return { assertion: `await expect(${sourceCode.getText(locator)}).${method}()` };
}
function getValueGetterSuggestion(getter, locator, expected, negated, sourceCode) {
if (!(0, ast_js_1.isMethodCall)(getter)) {
return null;
}
const matcher = PLAYWRIGHT_VALUE_GETTERS.get(getter.callee.property.name);
if (!matcher) {
return null;
}
return {
assertion: `await expect(${sourceCode.getText(locator)}).${negated ? 'not.' : ''}${matcher}(${sourceCode.getText(expected)})`,
};
}