Skip to content

Commit 43a14a2

Browse files
authored
fix(no-debug): allow console.debug() (#349)
* fix: allow console.debug() in no-debug * refactor: check for built-in console in isDebugUtil * fix: support destructuring from console object * fix: no-debug check correctly for declared variable * refactor: simplify code Closes #327
1 parent 91b6dca commit 43a14a2

File tree

3 files changed

+78
-10
lines changed

3 files changed

+78
-10
lines changed

lib/detect-testing-library-utils.ts

+17-9
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ type IsRenderUtilFn = (node: TSESTree.Identifier) => boolean;
7878
type IsRenderVariableDeclaratorFn = (
7979
node: TSESTree.VariableDeclarator
8080
) => boolean;
81-
type IsDebugUtilFn = (node: TSESTree.Identifier) => boolean;
81+
type IsDebugUtilFn = (identifierNode: TSESTree.Identifier) => boolean;
8282
type IsPresenceAssertFn = (node: TSESTree.MemberExpression) => boolean;
8383
type IsAbsenceAssertFn = (node: TSESTree.MemberExpression) => boolean;
8484
type CanReportErrorsFn = () => boolean;
@@ -580,14 +580,22 @@ export function detectTestingLibraryUtils<
580580
return isRenderUtil(initIdentifierNode);
581581
};
582582

583-
const isDebugUtil: IsDebugUtilFn = (node) => {
584-
return isTestingLibraryUtil(
585-
node,
586-
(identifierNodeName, originalNodeName) => {
587-
return [identifierNodeName, originalNodeName]
588-
.filter(Boolean)
589-
.includes('debug');
590-
}
583+
const isDebugUtil: IsDebugUtilFn = (identifierNode) => {
584+
const isBuiltInConsole =
585+
isMemberExpression(identifierNode.parent) &&
586+
ASTUtils.isIdentifier(identifierNode.parent.object) &&
587+
identifierNode.parent.object.name === 'console';
588+
589+
return (
590+
!isBuiltInConsole &&
591+
isTestingLibraryUtil(
592+
identifierNode,
593+
(identifierNodeName, originalNodeName) => {
594+
return [identifierNodeName, originalNodeName]
595+
.filter(Boolean)
596+
.includes('debug');
597+
}
598+
)
591599
);
592600
};
593601

lib/rules/no-debug.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
getInnermostReturningFunction,
55
getPropertyIdentifierNode,
66
getReferenceNode,
7+
isCallExpression,
78
isObjectPattern,
89
isProperty,
910
} from '../node-utils';
@@ -34,6 +35,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
3435
const suspiciousDebugVariableNames: string[] = [];
3536
const suspiciousReferenceNodes: TSESTree.Identifier[] = [];
3637
const renderWrapperNames: string[] = [];
38+
const builtInConsoleNodes: TSESTree.VariableDeclarator[] = [];
3739

3840
function detectRenderWrapper(node: TSESTree.Identifier): void {
3941
const innerFunction = getInnermostReturningFunction(context, node);
@@ -54,6 +56,11 @@ export default createTestingLibraryRule<Options, MessageIds>({
5456
return;
5557
}
5658

59+
if (initIdentifierNode.name === 'console') {
60+
builtInConsoleNodes.push(node);
61+
return;
62+
}
63+
5764
const isRenderWrapperVariableDeclarator = initIdentifierNode
5865
? renderWrapperNames.includes(initIdentifierNode.name)
5966
: false;
@@ -120,7 +127,21 @@ export default createTestingLibraryRule<Options, MessageIds>({
120127
}
121128
);
122129

123-
if (isDebugUtil || isDeclaredDebugVariable || isChainedReferenceDebug) {
130+
const isVariableFromBuiltInConsole = builtInConsoleNodes.some(
131+
(variableDeclarator) => {
132+
const variables = context.getDeclaredVariables(variableDeclarator);
133+
return variables.some(
134+
({ name }) =>
135+
name === callExpressionIdentifier.name &&
136+
isCallExpression(callExpressionIdentifier.parent)
137+
);
138+
}
139+
);
140+
141+
if (
142+
!isVariableFromBuiltInConsole &&
143+
(isDebugUtil || isDeclaredDebugVariable || isChainedReferenceDebug)
144+
) {
124145
context.report({
125146
node: callExpressionIdentifier,
126147
messageId: 'noDebug',

tests/lib/rules/no-debug.test.ts

+39
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,27 @@ ruleTester.run(RULE_NAME, rule, {
5454
settings: { 'testing-library/utils-module': 'test-utils' },
5555
code: `screen.debug()`,
5656
},
57+
{
58+
code: `console.debug()`,
59+
},
60+
{
61+
code: `
62+
const consoleDebug = console.debug
63+
consoleDebug()
64+
`,
65+
},
66+
{
67+
code: `
68+
const { debug } = console
69+
debug()
70+
`,
71+
},
72+
{
73+
code: `
74+
const { debug: consoleDebug } = console
75+
consoleDebug()
76+
`,
77+
},
5778
{
5879
code: `
5980
const { screen } = require('@testing-library/dom')
@@ -516,5 +537,23 @@ ruleTester.run(RULE_NAME, rule, {
516537
`,
517538
errors: [{ line: 7, column: 7, messageId: 'noDebug' }],
518539
},
540+
{
541+
settings: { 'testing-library/utils-module': 'test-utils' },
542+
code: `
543+
import { render } from '@testing-library/react'
544+
545+
const utils = render(element)
546+
const { debug: renamedDestructuredDebug } = console
547+
const { debug } = console
548+
const assignedDebug = console.debug
549+
console.debug('debugging')
550+
debug('destructured')
551+
assignedDebug('foo')
552+
// the following line is the one that fails
553+
utils.debug()
554+
renamedDestructuredDebug('foo')
555+
`,
556+
errors: [{ line: 12, column: 13, messageId: 'noDebug' }],
557+
},
519558
],
520559
});

0 commit comments

Comments
 (0)