From 5c83d70ded937fcc83cbbdd65c6061d9b001a5d0 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Thu, 15 Aug 2024 07:06:58 +1200
Subject: [PATCH 1/8] fix: introduce utilities for v9 compatability

---
 lib/utils/compat.ts | 84 +++++++++++++++++++++++++++++++++++++++++++++
 lib/utils/index.ts  |  1 +
 2 files changed, 85 insertions(+)
 create mode 100644 lib/utils/compat.ts

diff --git a/lib/utils/compat.ts b/lib/utils/compat.ts
new file mode 100644
index 00000000..8fb34608
--- /dev/null
+++ b/lib/utils/compat.ts
@@ -0,0 +1,84 @@
+import { type TSESLint, type TSESTree } from '@typescript-eslint/utils';
+
+declare module '@typescript-eslint/utils/dist/ts-eslint/Rule' {
+  // eslint-disable-next-line @typescript-eslint/no-unused-vars
+  export interface RuleContext<TMessageIds extends string, TOptions extends readonly unknown[]> {
+    /**
+     * The filename associated with the source.
+     */
+    filename: string;
+
+    /**
+     * A SourceCode object that you can use to work with the source that
+     * was passed to ESLint.
+     */
+    sourceCode: Readonly<TSESLint.SourceCode>;
+  }
+}
+
+declare module '@typescript-eslint/utils/dist/ts-eslint/SourceCode' {
+  export interface SourceCode {
+    /**
+     * Returns the scope of the given node.
+     * This information can be used track references to variables.
+     * @since 8.37.0
+     */
+    getScope(node: TSESTree.Node): TSESLint.Scope.Scope;
+    /**
+     * Returns an array of the ancestors of the given node, starting at
+     * the root of the AST and continuing through the direct parent of the current node.
+     * This array does not include the currently-traversed node itself.
+     * @since 8.38.0
+     */
+    getAncestors(node: TSESTree.Node): TSESTree.Node[];
+    /**
+     * Returns a list of variables declared by the given node.
+     * This information can be used to track references to variables.
+     * @since 8.38.0
+     */
+    getDeclaredVariables(
+      node: TSESTree.Node,
+    ): readonly TSESLint.Scope.Variable[];
+  }
+}
+
+/* istanbul ignore next */
+export const getFilename = (
+  context: TSESLint.RuleContext<string, unknown[]>,
+) => {
+  return context.filename ?? context.getFilename();
+};
+
+/* istanbul ignore next */
+export const getSourceCode = (
+  context: TSESLint.RuleContext<string, unknown[]>,
+) => {
+  return context.sourceCode ?? context.getSourceCode();
+};
+
+/* istanbul ignore next */
+export const getScope = (
+  context: TSESLint.RuleContext<string, unknown[]>,
+  node: TSESTree.Node,
+) => {
+  return getSourceCode(context).getScope?.(node) ?? context.getScope();
+};
+
+/* istanbul ignore next */
+export const getAncestors = (
+  context: TSESLint.RuleContext<string, unknown[]>,
+  node: TSESTree.Node,
+) => {
+  return getSourceCode(context).getAncestors?.(node) ?? context.getAncestors();
+};
+
+/* istanbul ignore next */
+export const getDeclaredVariables = (
+  context: TSESLint.RuleContext<string, unknown[]>,
+  node: TSESTree.Node,
+) => {
+  return (
+    getSourceCode(context).getDeclaredVariables?.(node) ??
+    context.getDeclaredVariables(node)
+  );
+};
diff --git a/lib/utils/index.ts b/lib/utils/index.ts
index b0ed31f7..cb0e8e03 100644
--- a/lib/utils/index.ts
+++ b/lib/utils/index.ts
@@ -1,3 +1,4 @@
+export * from './compat';
 export * from './file-import';
 export * from './types';
 

From 15e4f44bdb27137e2250db2f36a2d3d4477c7a0d Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Thu, 15 Aug 2024 07:12:01 +1200
Subject: [PATCH 2/8] fix: replace uses of `context.getFilename`

---
 lib/rules/consistent-data-testid.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/rules/consistent-data-testid.ts b/lib/rules/consistent-data-testid.ts
index 2536706e..f8b7ff6e 100644
--- a/lib/rules/consistent-data-testid.ts
+++ b/lib/rules/consistent-data-testid.ts
@@ -1,5 +1,6 @@
 import { createTestingLibraryRule } from '../create-testing-library-rule';
 import { isJSXAttribute, isLiteral } from '../node-utils';
+import { getFilename } from '../utils';
 
 export const RULE_NAME = 'consistent-data-testid';
 export type MessageIds =
@@ -77,11 +78,10 @@ export default createTestingLibraryRule<Options, MessageIds>({
 	},
 
 	create: (context, [options]) => {
-		const { getFilename } = context;
 		const { testIdPattern, testIdAttribute: attr, customMessage } = options;
 
 		function getFileNameData() {
-			const splitPath = getFilename().split('/');
+			const splitPath = getFilename(context).split('/');
 			const fileNameWithExtension = splitPath.pop() ?? '';
 			if (
 				fileNameWithExtension.includes('[') ||

From 142bb23be3e62822f8fbc4c129ee94195409fdd9 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Thu, 15 Aug 2024 07:12:23 +1200
Subject: [PATCH 3/8] fix: replace uses of `context.getSourceCode`

---
 lib/rules/prefer-find-by.ts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/rules/prefer-find-by.ts b/lib/rules/prefer-find-by.ts
index f9d951e0..632790a2 100644
--- a/lib/rules/prefer-find-by.ts
+++ b/lib/rules/prefer-find-by.ts
@@ -9,6 +9,7 @@ import {
 	isObjectPattern,
 	isProperty,
 } from '../node-utils';
+import { getSourceCode } from '../utils';
 
 export const RULE_NAME = 'prefer-find-by';
 export type MessageIds = 'preferFindBy';
@@ -69,7 +70,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
 	defaultOptions: [],
 
 	create(context, _, helpers) {
-		const sourceCode = context.getSourceCode();
+		const sourceCode = getSourceCode(context);
 
 		/**
 		 * Reports the invalid usage of wait* plus getBy/QueryBy methods and automatically fixes the scenario

From 49449033a90ac5a70b218106511abcba3c95e798 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Thu, 15 Aug 2024 07:15:46 +1200
Subject: [PATCH 4/8] fix: replace uses of `context.getScope`

---
 lib/node-utils/index.ts               |  4 +++-
 lib/rules/no-promise-in-fire-event.ts |  3 ++-
 lib/rules/prefer-find-by.ts           | 28 +++++++++++++++------------
 3 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/lib/node-utils/index.ts b/lib/node-utils/index.ts
index 0f748c5c..a47dd642 100644
--- a/lib/node-utils/index.ts
+++ b/lib/node-utils/index.ts
@@ -6,6 +6,8 @@ import {
 	TSESTree,
 } from '@typescript-eslint/utils';
 
+import { getScope } from '../utils';
+
 import {
 	isArrayExpression,
 	isArrowFunctionExpression,
@@ -305,7 +307,7 @@ export function getInnermostFunctionScope(
 	asyncQueryNode: TSESTree.Identifier
 ): InnermostFunctionScope | null {
 	const innermostScope = ASTUtils.getInnermostScope(
-		context.getScope(),
+		getScope(context, asyncQueryNode),
 		asyncQueryNode
 	);
 
diff --git a/lib/rules/no-promise-in-fire-event.ts b/lib/rules/no-promise-in-fire-event.ts
index c3c7eb4d..f10bfc77 100644
--- a/lib/rules/no-promise-in-fire-event.ts
+++ b/lib/rules/no-promise-in-fire-event.ts
@@ -8,6 +8,7 @@ import {
 	isNewExpression,
 	isPromiseIdentifier,
 } from '../node-utils';
+import { getScope } from '../utils';
 
 export const RULE_NAME = 'no-promise-in-fire-event';
 export type MessageIds = 'noPromiseInFireEvent';
@@ -76,7 +77,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
 
 			if (ASTUtils.isIdentifier(node)) {
 				const nodeVariable = ASTUtils.findVariable(
-					context.getScope(),
+					getScope(context, node),
 					node.name
 				);
 				if (!nodeVariable) {
diff --git a/lib/rules/prefer-find-by.ts b/lib/rules/prefer-find-by.ts
index 632790a2..7e48993b 100644
--- a/lib/rules/prefer-find-by.ts
+++ b/lib/rules/prefer-find-by.ts
@@ -9,7 +9,7 @@ import {
 	isObjectPattern,
 	isProperty,
 } from '../node-utils';
-import { getSourceCode } from '../utils';
+import { getScope, getSourceCode } from '../utils';
 
 export const RULE_NAME = 'prefer-find-by';
 export type MessageIds = 'preferFindBy';
@@ -119,7 +119,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
 				isCallExpression(node.body.callee.object.arguments[0]) &&
 				ASTUtils.isIdentifier(node.body.callee.object.arguments[0].callee)
 			) {
-				return node.body.callee.object.arguments[0].callee.name;
+				return node.body.callee.object.arguments[0].callee;
 			}
 
 			if (!ASTUtils.isIdentifier(node.body.callee.property)) {
@@ -135,7 +135,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
 					node.body.callee.object.arguments[0].callee.property
 				)
 			) {
-				return node.body.callee.object.arguments[0].callee.property.name;
+				return node.body.callee.object.arguments[0].callee.property;
 			}
 
 			// expect(screen.getByText).not shape
@@ -150,7 +150,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
 					node.body.callee.object.object.arguments[0].callee.property
 				)
 			) {
-				return node.body.callee.object.object.arguments[0].callee.property.name;
+				return node.body.callee.object.object.arguments[0].callee.property;
 			}
 
 			// expect(getByText).not shape
@@ -162,10 +162,10 @@ export default createTestingLibraryRule<Options, MessageIds>({
 					node.body.callee.object.object.arguments[0].callee
 				)
 			) {
-				return node.body.callee.object.object.arguments[0].callee.name;
+				return node.body.callee.object.object.arguments[0].callee;
 			}
 
-			return node.body.callee.property.name;
+			return node.body.callee.property;
 		}
 
 		function getWrongQueryName(node: TSESTree.ArrowFunctionExpression) {
@@ -178,7 +178,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
 				ASTUtils.isIdentifier(node.body.callee) &&
 				helpers.isSyncQuery(node.body.callee)
 			) {
-				return node.body.callee.name;
+				return node.body.callee;
 			}
 
 			return getWrongQueryNameInAssertion(node);
@@ -354,12 +354,14 @@ export default createTestingLibraryRule<Options, MessageIds>({
 					}
 
 					// shape of () => screen.getByText
-					const fullQueryMethod = getWrongQueryName(argument);
+					const fullQueryMethodNode = getWrongQueryName(argument);
 
-					if (!fullQueryMethod) {
+					if (!fullQueryMethodNode) {
 						return;
 					}
 
+					const fullQueryMethod = fullQueryMethodNode.name;
+
 					// if there is a second argument to AwaitExpression, it is the options
 					const waitOptions = node.arguments[1];
 					let waitOptionsSourceCode = '';
@@ -401,12 +403,14 @@ export default createTestingLibraryRule<Options, MessageIds>({
 				}
 
 				// shape of () => getByText
-				const fullQueryMethod = getWrongQueryName(argument);
+				const fullQueryMethodNode = getWrongQueryName(argument);
 
-				if (!fullQueryMethod) {
+				if (!fullQueryMethodNode) {
 					return;
 				}
 
+				const fullQueryMethod = fullQueryMethodNode.name;
+
 				const queryMethod = fullQueryMethod.split('By')[1];
 				const queryVariant = getFindByQueryVariant(fullQueryMethod);
 				const callArguments = getQueryArguments(argument.body);
@@ -435,7 +439,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
 
 						// this adds the findBy* declaration - adding it to the list of destructured variables { findBy* } = render()
 						const definition = findRenderDefinitionDeclaration(
-							context.getScope(),
+							getScope(context, fullQueryMethodNode),
 							fullQueryMethod
 						);
 						// I think it should always find it, otherwise code should not be valid (it'd be using undeclared variables)

From 8cc367621d46a7d4bdba2217cedf780f6091f113 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Thu, 15 Aug 2024 07:17:28 +1200
Subject: [PATCH 5/8] fix: replace uses of `context.getDeclaredVariables`

---
 lib/node-utils/index.ts         | 4 ++--
 lib/rules/no-debugging-utils.ts | 4 ++--
 lib/rules/no-manual-cleanup.ts  | 3 ++-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/lib/node-utils/index.ts b/lib/node-utils/index.ts
index a47dd642..9e9e9b04 100644
--- a/lib/node-utils/index.ts
+++ b/lib/node-utils/index.ts
@@ -6,7 +6,7 @@ import {
 	TSESTree,
 } from '@typescript-eslint/utils';
 
-import { getScope } from '../utils';
+import { getDeclaredVariables, getScope } from '../utils';
 
 import {
 	isArrayExpression,
@@ -289,7 +289,7 @@ export function getVariableReferences(
 ): TSESLint.Scope.Reference[] {
 	if (ASTUtils.isVariableDeclarator(node)) {
 		// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
-		return context.getDeclaredVariables(node)[0]?.references?.slice(1) ?? [];
+		return getDeclaredVariables(context, node)[0]?.references?.slice(1) ?? [];
 	}
 
 	return [];
diff --git a/lib/rules/no-debugging-utils.ts b/lib/rules/no-debugging-utils.ts
index d9ed3040..3978fbde 100644
--- a/lib/rules/no-debugging-utils.ts
+++ b/lib/rules/no-debugging-utils.ts
@@ -11,7 +11,7 @@ import {
 	isObjectPattern,
 	isProperty,
 } from '../node-utils';
-import { DEBUG_UTILS } from '../utils';
+import { DEBUG_UTILS, getDeclaredVariables } from '../utils';
 
 type DebugUtilsToCheckForConfig = Record<(typeof DEBUG_UTILS)[number], boolean>;
 type DebugUtilsToCheckFor = Partial<DebugUtilsToCheckForConfig>;
@@ -175,7 +175,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
 
 				const isVariableFromBuiltInConsole = builtInConsoleNodes.some(
 					(variableDeclarator) => {
-						const variables = context.getDeclaredVariables(variableDeclarator);
+						const variables = getDeclaredVariables(context, variableDeclarator);
 						return variables.some(
 							({ name }) =>
 								name === callExpressionIdentifier.name &&
diff --git a/lib/rules/no-manual-cleanup.ts b/lib/rules/no-manual-cleanup.ts
index 9074d669..ee65ee71 100644
--- a/lib/rules/no-manual-cleanup.ts
+++ b/lib/rules/no-manual-cleanup.ts
@@ -12,6 +12,7 @@ import {
 	isObjectPattern,
 	isProperty,
 } from '../node-utils';
+import { getDeclaredVariables } from '../utils';
 
 export const RULE_NAME = 'no-manual-cleanup';
 export type MessageIds = 'noManualCleanup';
@@ -65,7 +66,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
 			if (isImportDeclaration(moduleNode)) {
 				// case: import utils from 'testing-library-module'
 				if (isImportDefaultSpecifier(moduleNode.specifiers[0])) {
-					const { references } = context.getDeclaredVariables(moduleNode)[0];
+					const { references } = getDeclaredVariables(context, moduleNode)[0];
 
 					reportImportReferences(references);
 				}

From 83538d31ea5dcac482ee528852a8ef1bdcee3dd5 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Thu, 15 Aug 2024 07:37:59 +1200
Subject: [PATCH 6/8] refactor: remove unneeded compat utility

---
 lib/utils/compat.ts | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/lib/utils/compat.ts b/lib/utils/compat.ts
index 8fb34608..a8068cea 100644
--- a/lib/utils/compat.ts
+++ b/lib/utils/compat.ts
@@ -64,14 +64,6 @@ export const getScope = (
   return getSourceCode(context).getScope?.(node) ?? context.getScope();
 };
 
-/* istanbul ignore next */
-export const getAncestors = (
-  context: TSESLint.RuleContext<string, unknown[]>,
-  node: TSESTree.Node,
-) => {
-  return getSourceCode(context).getAncestors?.(node) ?? context.getAncestors();
-};
-
 /* istanbul ignore next */
 export const getDeclaredVariables = (
   context: TSESLint.RuleContext<string, unknown[]>,

From 10705729e8322fd19d5cbeec2b2e0bf6140425a8 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Thu, 15 Aug 2024 07:38:22 +1200
Subject: [PATCH 7/8] refactor: apply prettier

---
 lib/utils/compat.ts | 99 +++++++++++++++++++++++----------------------
 1 file changed, 51 insertions(+), 48 deletions(-)

diff --git a/lib/utils/compat.ts b/lib/utils/compat.ts
index a8068cea..0520d843 100644
--- a/lib/utils/compat.ts
+++ b/lib/utils/compat.ts
@@ -1,76 +1,79 @@
 import { type TSESLint, type TSESTree } from '@typescript-eslint/utils';
 
 declare module '@typescript-eslint/utils/dist/ts-eslint/Rule' {
-  // eslint-disable-next-line @typescript-eslint/no-unused-vars
-  export interface RuleContext<TMessageIds extends string, TOptions extends readonly unknown[]> {
-    /**
-     * The filename associated with the source.
-     */
-    filename: string;
+	// eslint-disable-next-line @typescript-eslint/no-unused-vars
+	export interface RuleContext<
+		TMessageIds extends string,
+		TOptions extends readonly unknown[],
+	> {
+		/**
+		 * The filename associated with the source.
+		 */
+		filename: string;
 
-    /**
-     * A SourceCode object that you can use to work with the source that
-     * was passed to ESLint.
-     */
-    sourceCode: Readonly<TSESLint.SourceCode>;
-  }
+		/**
+		 * A SourceCode object that you can use to work with the source that
+		 * was passed to ESLint.
+		 */
+		sourceCode: Readonly<TSESLint.SourceCode>;
+	}
 }
 
 declare module '@typescript-eslint/utils/dist/ts-eslint/SourceCode' {
-  export interface SourceCode {
-    /**
-     * Returns the scope of the given node.
-     * This information can be used track references to variables.
-     * @since 8.37.0
-     */
-    getScope(node: TSESTree.Node): TSESLint.Scope.Scope;
-    /**
-     * Returns an array of the ancestors of the given node, starting at
-     * the root of the AST and continuing through the direct parent of the current node.
-     * This array does not include the currently-traversed node itself.
-     * @since 8.38.0
-     */
-    getAncestors(node: TSESTree.Node): TSESTree.Node[];
-    /**
-     * Returns a list of variables declared by the given node.
-     * This information can be used to track references to variables.
-     * @since 8.38.0
-     */
-    getDeclaredVariables(
-      node: TSESTree.Node,
-    ): readonly TSESLint.Scope.Variable[];
-  }
+	export interface SourceCode {
+		/**
+		 * Returns the scope of the given node.
+		 * This information can be used track references to variables.
+		 * @since 8.37.0
+		 */
+		getScope(node: TSESTree.Node): TSESLint.Scope.Scope;
+		/**
+		 * Returns an array of the ancestors of the given node, starting at
+		 * the root of the AST and continuing through the direct parent of the current node.
+		 * This array does not include the currently-traversed node itself.
+		 * @since 8.38.0
+		 */
+		getAncestors(node: TSESTree.Node): TSESTree.Node[];
+		/**
+		 * Returns a list of variables declared by the given node.
+		 * This information can be used to track references to variables.
+		 * @since 8.38.0
+		 */
+		getDeclaredVariables(
+			node: TSESTree.Node
+		): readonly TSESLint.Scope.Variable[];
+	}
 }
 
 /* istanbul ignore next */
 export const getFilename = (
-  context: TSESLint.RuleContext<string, unknown[]>,
+	context: TSESLint.RuleContext<string, unknown[]>
 ) => {
-  return context.filename ?? context.getFilename();
+	return context.filename ?? context.getFilename();
 };
 
 /* istanbul ignore next */
 export const getSourceCode = (
-  context: TSESLint.RuleContext<string, unknown[]>,
+	context: TSESLint.RuleContext<string, unknown[]>
 ) => {
-  return context.sourceCode ?? context.getSourceCode();
+	return context.sourceCode ?? context.getSourceCode();
 };
 
 /* istanbul ignore next */
 export const getScope = (
-  context: TSESLint.RuleContext<string, unknown[]>,
-  node: TSESTree.Node,
+	context: TSESLint.RuleContext<string, unknown[]>,
+	node: TSESTree.Node
 ) => {
-  return getSourceCode(context).getScope?.(node) ?? context.getScope();
+	return getSourceCode(context).getScope?.(node) ?? context.getScope();
 };
 
 /* istanbul ignore next */
 export const getDeclaredVariables = (
-  context: TSESLint.RuleContext<string, unknown[]>,
-  node: TSESTree.Node,
+	context: TSESLint.RuleContext<string, unknown[]>,
+	node: TSESTree.Node
 ) => {
-  return (
-    getSourceCode(context).getDeclaredVariables?.(node) ??
-    context.getDeclaredVariables(node)
-  );
+	return (
+		getSourceCode(context).getDeclaredVariables?.(node) ??
+		context.getDeclaredVariables(node)
+	);
 };

From 88ecc281b31a1773608082200c88a78c758ab368 Mon Sep 17 00:00:00 2001
From: Gareth Jones <jones258@gmail.com>
Date: Thu, 15 Aug 2024 08:47:32 +1200
Subject: [PATCH 8/8] chore: adjust eslint inline disables

---
 lib/utils/compat.ts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/utils/compat.ts b/lib/utils/compat.ts
index 0520d843..2216dd8d 100644
--- a/lib/utils/compat.ts
+++ b/lib/utils/compat.ts
@@ -1,9 +1,10 @@
 import { type TSESLint, type TSESTree } from '@typescript-eslint/utils';
 
 declare module '@typescript-eslint/utils/dist/ts-eslint/Rule' {
-	// eslint-disable-next-line @typescript-eslint/no-unused-vars
 	export interface RuleContext<
+		// eslint-disable-next-line @typescript-eslint/no-unused-vars
 		TMessageIds extends string,
+		// eslint-disable-next-line @typescript-eslint/no-unused-vars
 		TOptions extends readonly unknown[],
 	> {
 		/**