UNPKG

eslint-plugin-sonarjs

Version:
85 lines (84 loc) • 4.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TESTING_LIBRARY_MODULES = void 0; exports.isDirectTestingLibraryBinding = isDirectTestingLibraryBinding; exports.importsTestingLibrary = importsTestingLibrary; exports.withStrictImportResolution = withStrictImportResolution; const ast_js_1 = require("./ast.js"); const module_js_1 = require("./module.js"); exports.TESTING_LIBRARY_MODULES = [ '@testing-library/dom', '@testing-library/react', '@testing-library/vue', '@testing-library/angular', '@testing-library/svelte', ]; function isDirectTestingLibraryBinding(context, node, importedName, options) { if ((0, ast_js_1.isIdentifier)(node)) { return isDirectNamedImport(context, node, importedName, options.allowSubpathImport); } return (options.allowNamespaceImport && node.type === 'MemberExpression' && !node.computed && (0, ast_js_1.isIdentifier)(node.object) && (0, ast_js_1.isIdentifier)(node.property, importedName) && isDirectNamespaceImport(context, node.object, options.allowSubpathImport)); } function isDirectNamedImport(context, node, importedName, allowSubpathImport) { const variable = (0, ast_js_1.getVariableFromName)(context, node.name, node); const definition = variable?.defs[0]; return (variable?.defs.length === 1 && definition?.type === 'ImportBinding' && definition.node.type === 'ImportSpecifier' && (0, ast_js_1.isIdentifier)(definition.node.imported, importedName) && definition.parent.type === 'ImportDeclaration' && typeof definition.parent.source.value === 'string' && isTestingLibraryModule(definition.parent.source.value, allowSubpathImport)); } function isDirectNamespaceImport(context, node, allowSubpathImport) { const variable = (0, ast_js_1.getVariableFromName)(context, node.name, node); const definition = variable?.defs[0]; return (variable?.defs.length === 1 && definition?.type === 'ImportBinding' && definition.node.type === 'ImportNamespaceSpecifier' && definition.parent.type === 'ImportDeclaration' && typeof definition.parent.source.value === 'string' && isTestingLibraryModule(definition.parent.source.value, allowSubpathImport)); } function isTestingLibraryModule(moduleName, allowSubpathImport) { return exports.TESTING_LIBRARY_MODULES.some((module) => moduleName === module || (allowSubpathImport && moduleName.startsWith(`${module}/`))); } function importsTestingLibrary(context) { return [...(0, module_js_1.getCurrentFileImports)(context.sourceCode)].some(moduleName => isTestingLibraryModule(moduleName, true)); } // Without any `testing-library/*` settings, the upstream `eslint-plugin-testing-library` // rules fall back to "aggressive" name-based heuristics for `waitFor`, `fireEvent`, // `userEvent`, `render`, and custom queries: they treat any call merely *named* like one // of these as a Testing Library util, regardless of where it's imported from. Forcing // these settings (the upstream plugin's own documented recipe for disabling aggressive // reporting) switches detection to import resolution instead. The official // `@testing-library/*` module check still runs unconditionally, so real Testing Library // imports are unaffected. Note this does not make *built-in* query detection // (`getBy*`/`queryBy*`/`findBy*`) import-resolution-based: upstream matches those purely // by name in all modes, so a same-named, unrelated helper (e.g. Playwright's // `page.getByRole`) can still be misidentified as a Testing Library query. Accepted as a // known v1 limitation inherited from the upstream plugin. const STRICT_IMPORT_RESOLUTION_SETTINGS = { 'testing-library/utils-module': 'off', 'testing-library/custom-renders': 'off', 'testing-library/custom-queries': 'off', }; function withStrictImportResolution(rule) { return { ...rule, create(context) { const overriddenContext = Object.create(context, { settings: { value: { ...context.settings, ...STRICT_IMPORT_RESOLUTION_SETTINGS }, enumerable: true, }, }); return rule.create(overriddenContext); }, }; }