diff --git a/.all-contributorsrc b/.all-contributorsrc
index 515ea578..ccff7e6e 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -718,6 +718,16 @@
"test",
"doc"
]
+ },
+ {
+ "login": "y-hsgw",
+ "name": "Yukihiro Hasegawa",
+ "avatar_url": "https://avatars.githubusercontent.com/u/49516827?v=4",
+ "profile": "https://github.com/y-hsgw",
+ "contributions": [
+ "code",
+ "test"
+ ]
}
],
"contributorsPerLine": 7,
diff --git a/.github/workflows/main-coverage.yml b/.github/workflows/main-coverage.yml
new file mode 100644
index 00000000..8eb4854e
--- /dev/null
+++ b/.github/workflows/main-coverage.yml
@@ -0,0 +1,38 @@
+name: Code Coverage (main)
+on:
+ push:
+ branches:
+ - 'main'
+
+permissions:
+ contents: read
+ statuses: write
+
+jobs:
+ coverage:
+ name: Code Coverage
+ runs-on: ubuntu-latest
+ timeout-minutes: 3
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@v4
+
+ - name: Set up Node
+ uses: actions/setup-node@v4
+ with:
+ cache: 'pnpm'
+ node-version-file: '.nvmrc'
+
+ - name: Install dependencies
+ run: pnpm install
+
+ - name: Run tests with coverage
+ run: pnpm run test:ci
+
+ - name: Upload coverage report
+ uses: codecov/codecov-action@v5
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/README.md b/README.md
index 981ae6fc..18e61661 100644
--- a/README.md
+++ b/README.md
@@ -346,7 +346,7 @@ module.exports = [
| [prefer-explicit-assert](docs/rules/prefer-explicit-assert.md) | Suggest using explicit assertions rather than standalone queries | | | |
| [prefer-find-by](docs/rules/prefer-find-by.md) | Suggest using `find(All)By*` query instead of `waitFor` + `get(All)By*` to wait for elements | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | π§ |
| [prefer-implicit-assert](docs/rules/prefer-implicit-assert.md) | Suggest using implicit assertions for getBy* & findBy* queries | | | |
-| [prefer-presence-queries](docs/rules/prefer-presence-queries.md) | Ensure appropriate `get*`/`query*` queries are used with their respective matchers | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | |
+| [prefer-presence-queries](docs/rules/prefer-presence-queries.md) | Ensure appropriate `get*`/`query*` queries are used with their respective matchers | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | π§ |
| [prefer-query-by-disappearance](docs/rules/prefer-query-by-disappearance.md) | Suggest using `queryBy*` queries when waiting for disappearance | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | |
| [prefer-query-matchers](docs/rules/prefer-query-matchers.md) | Ensure the configured `get*`/`query*` query is used with the corresponding matchers | | | |
| [prefer-screen-queries](docs/rules/prefer-screen-queries.md) | Suggest using `screen` while querying | ![badge-angular][] ![badge-dom][] ![badge-marko][] ![badge-react][] ![badge-svelte][] ![badge-vue][] | | |
@@ -552,6 +552,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 nostro π» |
 Daniel Rentz π |
 StyleShit π» β οΈ π |
+  Yukihiro Hasegawa π» β οΈ |
diff --git a/docs/rules/no-node-access.md b/docs/rules/no-node-access.md
index 7290cec3..3ae667b7 100644
--- a/docs/rules/no-node-access.md
+++ b/docs/rules/no-node-access.md
@@ -4,11 +4,15 @@
-The Testing Library already provides methods for querying DOM elements.
+Disallow direct access or manipulation of DOM nodes in favor of Testing Library's user-centric APIs.
## Rule Details
-This rule aims to disallow DOM traversal using native HTML methods and properties, such as `closest`, `lastChild` and all that returns another Node element from an HTML tree.
+This rule aims to disallow direct access and manipulation of DOM nodes using native HTML properties and methods β including traversal (e.g. `closest`, `lastChild`) as well as direct actions (e.g. `click()`, `select()`). Use Testing Libraryβs queries and userEvent APIs instead.
+
+> [!NOTE]
+> This rule does not report usage of `focus()` or `blur()`, because imperative usage (e.g. `getByText('focus me').focus()` or .`blur()`) is recommended over `fireEvent.focus()` or `fireEvent.blur()`.
+> If an element is not focusable, related assertions will fail, leading to more robust tests. See [Testing Library Events Guide](https://testing-library.com/docs/guide-events/) for more details.
Examples of **incorrect** code for this rule:
@@ -21,6 +25,12 @@ screen.getByText('Submit').closest('button'); // chaining with Testing Library m
```js
import { screen } from '@testing-library/react';
+screen.getByText('Submit').click();
+```
+
+```js
+import { screen } from '@testing-library/react';
+
const buttons = screen.getAllByRole('button');
expect(buttons[1].lastChild).toBeInTheDocument();
```
@@ -41,6 +51,12 @@ const button = screen.getByRole('button');
expect(button).toHaveTextContent('submit');
```
+```js
+import { screen } from '@testing-library/react';
+
+userEvent.click(screen.getByText('Submit'));
+```
+
```js
import { render, within } from '@testing-library/react';
@@ -92,3 +108,7 @@ expect(container.firstChild).toMatchSnapshot();
- [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document)
- [`Element`](https://developer.mozilla.org/en-US/docs/Web/API/Element)
- [`Node`](https://developer.mozilla.org/en-US/docs/Web/API/Node)
+
+### Testing Library Guides
+
+- [Testing Library Events Guide](https://testing-library.com/docs/guide-events/)
diff --git a/docs/rules/prefer-find-by.md b/docs/rules/prefer-find-by.md
index 2a39b131..0431e27b 100644
--- a/docs/rules/prefer-find-by.md
+++ b/docs/rules/prefer-find-by.md
@@ -41,6 +41,12 @@ const submitButton = await waitFor(() =>
const submitButton = await waitFor(() =>
expect(queryByLabel('button', { name: /submit/i })).not.toBeFalsy()
);
+
+// unnecessary usage of waitFor with findBy*, which already includes waiting logic
+await waitFor(async () => {
+ const button = await findByRole('button', { name: 'Submit' });
+ expect(button).toBeInTheDocument();
+});
```
Examples of **correct** code for this rule:
diff --git a/docs/rules/prefer-presence-queries.md b/docs/rules/prefer-presence-queries.md
index 2bb3174a..b7e40121 100644
--- a/docs/rules/prefer-presence-queries.md
+++ b/docs/rules/prefer-presence-queries.md
@@ -2,6 +2,8 @@
πΌ This rule is enabled in the following configs: `angular`, `dom`, `marko`, `react`, `svelte`, `vue`.
+π§ This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
The (DOM) Testing Library allows to query DOM elements using different types of queries such as `get*` and `query*`. Using `get*` throws an error in case the element is not found, while `query*` returns null instead of throwing (or empty array for `queryAllBy*` ones). These differences are useful in some situations:
diff --git a/lib/create-testing-library-rule/detect-testing-library-utils.ts b/lib/create-testing-library-rule/detect-testing-library-utils.ts
index 001dc532..09688bef 100644
--- a/lib/create-testing-library-rule/detect-testing-library-utils.ts
+++ b/lib/create-testing-library-rule/detect-testing-library-utils.ts
@@ -802,8 +802,10 @@ export function detectTestingLibraryUtils<
}
return isNegated
- ? ABSENCE_MATCHERS.includes(matcher)
- : PRESENCE_MATCHERS.includes(matcher);
+ ? ABSENCE_MATCHERS.some((absenceMather) => absenceMather === matcher)
+ : PRESENCE_MATCHERS.some(
+ (presenceMather) => presenceMather === matcher
+ );
};
/**
@@ -821,8 +823,8 @@ export function detectTestingLibraryUtils<
}
return isNegated
- ? PRESENCE_MATCHERS.includes(matcher)
- : ABSENCE_MATCHERS.includes(matcher);
+ ? PRESENCE_MATCHERS.some((presenceMather) => presenceMather === matcher)
+ : ABSENCE_MATCHERS.some((absenceMather) => absenceMather === matcher);
};
const isMatchingAssert: IsMatchingAssertFn = (node, matcherName) => {
diff --git a/lib/create-testing-library-rule/index.ts b/lib/create-testing-library-rule/index.ts
index 82e28403..8ce3b334 100644
--- a/lib/create-testing-library-rule/index.ts
+++ b/lib/create-testing-library-rule/index.ts
@@ -1,6 +1,10 @@
import { ESLintUtils } from '@typescript-eslint/utils';
-import { getDocsUrl, TestingLibraryPluginDocs } from '../utils';
+import {
+ getDocsUrl,
+ TestingLibraryPluginDocs,
+ TestingLibraryPluginRuleModule,
+} from '../utils';
import {
DetectionOptions,
@@ -27,11 +31,20 @@ export const createTestingLibraryRule = <
create: EnhancedRuleCreate;
detectionOptions?: Partial;
}
->) =>
- ESLintUtils.RuleCreator>(getDocsUrl)({
+>): TestingLibraryPluginRuleModule => {
+ const rule = ESLintUtils.RuleCreator>(
+ getDocsUrl
+ )({
...remainingConfig,
create: detectTestingLibraryUtils(
create,
detectionOptions
),
});
+ const { docs } = rule.meta;
+ if (docs === undefined) {
+ throw new Error('Rule metadata must contain `docs` property');
+ }
+
+ return { ...rule, meta: { ...rule.meta, docs } };
+};
diff --git a/lib/rules/no-node-access.ts b/lib/rules/no-node-access.ts
index 0fcd78ac..bfbbc346 100644
--- a/lib/rules/no-node-access.ts
+++ b/lib/rules/no-node-access.ts
@@ -1,12 +1,21 @@
import { TSESTree, ASTUtils } from '@typescript-eslint/utils';
import { createTestingLibraryRule } from '../create-testing-library-rule';
-import { ALL_RETURNING_NODES } from '../utils';
+import {
+ ALL_RETURNING_NODES,
+ EVENT_HANDLER_METHODS,
+ EVENTS_SIMULATORS,
+} from '../utils';
export const RULE_NAME = 'no-node-access';
export type MessageIds = 'noNodeAccess';
export type Options = [{ allowContainerFirstChild: boolean }];
+const ALL_PROHIBITED_MEMBERS = [
+ ...ALL_RETURNING_NODES,
+ ...EVENT_HANDLER_METHODS,
+] as const;
+
export default createTestingLibraryRule({
name: RULE_NAME,
meta: {
@@ -52,11 +61,26 @@ export default createTestingLibraryRule({
return;
}
+ const propertyName = ASTUtils.isIdentifier(node.property)
+ ? node.property.name
+ : null;
+
+ const objectName = ASTUtils.isIdentifier(node.object)
+ ? node.object.name
+ : null;
if (
- ASTUtils.isIdentifier(node.property) &&
- ALL_RETURNING_NODES.includes(node.property.name)
+ propertyName &&
+ ALL_PROHIBITED_MEMBERS.some(
+ (allReturningNode) => allReturningNode === propertyName
+ ) &&
+ ![
+ ...EVENTS_SIMULATORS,
+ // TODO: As discussed in https://github.com/testing-library/eslint-plugin-testing-library/issues/1024, this is just a temporary workaround.
+ // We should address the root cause and implement a proper solution instead of explicitly excluding 'user' here.
+ 'user',
+ ].some((simulator) => simulator === objectName)
) {
- if (allowContainerFirstChild && node.property.name === 'firstChild') {
+ if (allowContainerFirstChild && propertyName === 'firstChild') {
return;
}
diff --git a/lib/rules/no-render-in-lifecycle.ts b/lib/rules/no-render-in-lifecycle.ts
index c15fcd19..1e1aee24 100644
--- a/lib/rules/no-render-in-lifecycle.ts
+++ b/lib/rules/no-render-in-lifecycle.ts
@@ -68,7 +68,7 @@ export default createTestingLibraryRule({
type: 'object',
properties: {
allowTestingFrameworkSetupHook: {
- enum: TESTING_FRAMEWORK_SETUP_HOOKS,
+ enum: [...TESTING_FRAMEWORK_SETUP_HOOKS],
type: 'string',
},
},
diff --git a/lib/rules/prefer-explicit-assert.ts b/lib/rules/prefer-explicit-assert.ts
index 7dc78f2c..ed0ffc8c 100644
--- a/lib/rules/prefer-explicit-assert.ts
+++ b/lib/rules/prefer-explicit-assert.ts
@@ -92,7 +92,7 @@ export default createTestingLibraryRule({
properties: {
assertion: {
type: 'string',
- enum: PRESENCE_MATCHERS,
+ enum: [...PRESENCE_MATCHERS],
},
includeFindQueries: { type: 'boolean' },
},
@@ -182,8 +182,14 @@ export default createTestingLibraryRule({
}
const shouldEnforceAssertion =
- (!isNegatedMatcher && PRESENCE_MATCHERS.includes(matcher)) ||
- (isNegatedMatcher && ABSENCE_MATCHERS.includes(matcher));
+ (!isNegatedMatcher &&
+ PRESENCE_MATCHERS.some(
+ (presenceMather) => presenceMather === matcher
+ )) ||
+ (isNegatedMatcher &&
+ ABSENCE_MATCHERS.some(
+ (absenceMather) => absenceMather === matcher
+ ));
if (shouldEnforceAssertion && matcher !== assertion) {
context.report({
diff --git a/lib/rules/prefer-find-by.ts b/lib/rules/prefer-find-by.ts
index 1fc26ebd..5e3f35a7 100644
--- a/lib/rules/prefer-find-by.ts
+++ b/lib/rules/prefer-find-by.ts
@@ -2,12 +2,15 @@ import { TSESTree, ASTUtils, TSESLint } from '@typescript-eslint/utils';
import { createTestingLibraryRule } from '../create-testing-library-rule';
import {
+ getDeepestIdentifierNode,
isArrowFunctionExpression,
+ isBlockStatement,
isCallExpression,
isMemberExpression,
isObjectExpression,
isObjectPattern,
isProperty,
+ isVariableDeclaration,
} from '../node-utils';
import { getScope, getSourceCode } from '../utils';
@@ -329,20 +332,82 @@ export default createTestingLibraryRule({
}
return {
- 'AwaitExpression > CallExpression'(node: TSESTree.CallExpression) {
+ 'AwaitExpression > CallExpression'(
+ node: TSESTree.CallExpression & { parent: TSESTree.AwaitExpression }
+ ) {
if (
!ASTUtils.isIdentifier(node.callee) ||
!helpers.isAsyncUtil(node.callee, ['waitFor'])
) {
return;
}
- // ensure the only argument is an arrow function expression - if the arrow function is a block
- // we skip it
+ // ensure the only argument is an arrow function expression
const argument = node.arguments[0];
- if (
- !isArrowFunctionExpression(argument) ||
- !isCallExpression(argument.body)
- ) {
+
+ if (!isArrowFunctionExpression(argument)) {
+ return;
+ }
+
+ if (isBlockStatement(argument.body) && argument.async) {
+ const { body } = argument.body;
+ const declarations = body
+ .filter(isVariableDeclaration)
+ ?.flatMap((declaration) => declaration.declarations);
+
+ const findByDeclarator = declarations.find((declaration) => {
+ if (
+ !ASTUtils.isAwaitExpression(declaration.init) ||
+ !isCallExpression(declaration.init.argument)
+ ) {
+ return false;
+ }
+
+ const { callee } = declaration.init.argument;
+ const node = getDeepestIdentifierNode(callee);
+ return node ? helpers.isFindQueryVariant(node) : false;
+ });
+
+ const init = ASTUtils.isAwaitExpression(findByDeclarator?.init)
+ ? findByDeclarator.init.argument
+ : null;
+
+ if (!isCallExpression(init)) {
+ return;
+ }
+ const queryIdentifier = getDeepestIdentifierNode(init.callee);
+
+ // ensure the query is a supported async query like findBy*
+ if (!queryIdentifier || !helpers.isAsyncQuery(queryIdentifier)) {
+ return;
+ }
+
+ const fullQueryMethod = queryIdentifier.name;
+ const queryMethod = fullQueryMethod.split('By')[1];
+ const queryVariant = getFindByQueryVariant(fullQueryMethod);
+
+ reportInvalidUsage(node, {
+ queryMethod,
+ queryVariant,
+ prevQuery: fullQueryMethod,
+ fix(fixer) {
+ const { parent: expressionStatement } = node.parent;
+ const bodyText = sourceCode
+ .getText(argument.body)
+ .slice(1, -1)
+ .trim();
+ const { line, column } = expressionStatement.loc.start;
+ const indent = sourceCode.getLines()[line - 1].slice(0, column);
+ const newText = bodyText
+ .split('\n')
+ .map((line) => line.trim())
+ .join(`\n${indent}`);
+ return fixer.replaceText(expressionStatement, newText);
+ },
+ });
+ return;
+ }
+
+ if (!isCallExpression(argument.body)) {
return;
}
diff --git a/lib/rules/prefer-presence-queries.ts b/lib/rules/prefer-presence-queries.ts
index a810f869..504633c3 100644
--- a/lib/rules/prefer-presence-queries.ts
+++ b/lib/rules/prefer-presence-queries.ts
@@ -33,6 +33,7 @@ export default createTestingLibraryRule({
wrongAbsenceQuery:
'Use `queryBy*` queries rather than `getBy*` for checking element is NOT present',
},
+ fixable: 'code',
schema: [
{
type: 'object',
@@ -62,7 +63,7 @@ export default createTestingLibraryRule({
const expectCallNode = findClosestCallNode(node, 'expect');
const withinCallNode = findClosestCallNode(node, 'within');
- if (!expectCallNode || !isMemberExpression(expectCallNode.parent)) {
+ if (!isMemberExpression(expectCallNode?.parent)) {
return;
}
@@ -86,14 +87,25 @@ export default createTestingLibraryRule({
(withinCallNode || isPresenceAssert) &&
!isPresenceQuery
) {
- context.report({ node, messageId: 'wrongPresenceQuery' });
+ const newQueryName = node.name.replace(/^query/, 'get');
+
+ context.report({
+ node,
+ messageId: 'wrongPresenceQuery',
+ fix: (fixer) => fixer.replaceText(node, newQueryName),
+ });
} else if (
!withinCallNode &&
absence &&
isAbsenceAssert &&
isPresenceQuery
) {
- context.report({ node, messageId: 'wrongAbsenceQuery' });
+ const newQueryName = node.name.replace(/^get/, 'query');
+ context.report({
+ node,
+ messageId: 'wrongAbsenceQuery',
+ fix: (fixer) => fixer.replaceText(node, newQueryName),
+ });
}
},
};
diff --git a/lib/utils/index.ts b/lib/utils/index.ts
index cb0e8e03..299d4c36 100644
--- a/lib/utils/index.ts
+++ b/lib/utils/index.ts
@@ -2,7 +2,10 @@ export * from './compat';
export * from './file-import';
export * from './types';
-const combineQueries = (variants: string[], methods: string[]): string[] => {
+const combineQueries = (
+ variants: readonly string[],
+ methods: readonly string[]
+): string[] => {
const combinedQueries: string[] = [];
variants.forEach((variant) => {
const variantPrefix = variant.replace('By', '');
@@ -25,14 +28,19 @@ const LIBRARY_MODULES = [
'@testing-library/vue',
'@testing-library/svelte',
'@marko/testing-library',
-];
+] as const;
-const SYNC_QUERIES_VARIANTS = ['getBy', 'getAllBy', 'queryBy', 'queryAllBy'];
-const ASYNC_QUERIES_VARIANTS = ['findBy', 'findAllBy'];
+const SYNC_QUERIES_VARIANTS = [
+ 'getBy',
+ 'getAllBy',
+ 'queryBy',
+ 'queryAllBy',
+] as const;
+const ASYNC_QUERIES_VARIANTS = ['findBy', 'findAllBy'] as const;
const ALL_QUERIES_VARIANTS = [
...SYNC_QUERIES_VARIANTS,
...ASYNC_QUERIES_VARIANTS,
-];
+] as const;
const ALL_QUERIES_METHODS = [
'ByLabelText',
@@ -43,7 +51,7 @@ const ALL_QUERIES_METHODS = [
'ByDisplayValue',
'ByRole',
'ByTestId',
-];
+] as const;
const SYNC_QUERIES_COMBINATIONS = combineQueries(
SYNC_QUERIES_VARIANTS,
@@ -58,7 +66,7 @@ const ASYNC_QUERIES_COMBINATIONS = combineQueries(
const ALL_QUERIES_COMBINATIONS = [
...SYNC_QUERIES_COMBINATIONS,
...ASYNC_QUERIES_COMBINATIONS,
-];
+] as const;
const ASYNC_UTILS = ['waitFor', 'waitForElementToBeRemoved'] as const;
@@ -73,7 +81,7 @@ const DEBUG_UTILS = [
const EVENTS_SIMULATORS = ['fireEvent', 'userEvent'] as const;
-const TESTING_FRAMEWORK_SETUP_HOOKS = ['beforeEach', 'beforeAll'];
+const TESTING_FRAMEWORK_SETUP_HOOKS = ['beforeEach', 'beforeAll'] as const;
const PROPERTIES_RETURNING_NODES = [
'activeElement',
@@ -93,7 +101,7 @@ const PROPERTIES_RETURNING_NODES = [
'previousSibling',
'rootNode',
'scripts',
-];
+] as const;
const METHODS_RETURNING_NODES = [
'closest',
@@ -104,20 +112,22 @@ const METHODS_RETURNING_NODES = [
'getElementsByTagNameNS',
'querySelector',
'querySelectorAll',
-];
+] as const;
+
+const EVENT_HANDLER_METHODS = ['click', 'select', 'submit'] as const;
const ALL_RETURNING_NODES = [
...PROPERTIES_RETURNING_NODES,
...METHODS_RETURNING_NODES,
-];
+] as const;
const PRESENCE_MATCHERS = [
'toBeOnTheScreen',
'toBeInTheDocument',
'toBeTruthy',
'toBeDefined',
-];
-const ABSENCE_MATCHERS = ['toBeNull', 'toBeFalsy'];
+] as const;
+const ABSENCE_MATCHERS = ['toBeNull', 'toBeFalsy'] as const;
export {
combineQueries,
@@ -139,4 +149,5 @@ export {
ALL_RETURNING_NODES,
PRESENCE_MATCHERS,
ABSENCE_MATCHERS,
+ EVENT_HANDLER_METHODS,
};
diff --git a/package.json b/package.json
index 4ba0d923..639769de 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
"types": "index.d.ts",
"scripts": {
"prebuild": "del-cli dist",
- "build": "tsc",
+ "build": "tsc -p ./tsconfig.build.json",
"generate-all": "pnpm run --parallel \"/^generate:.*/\"",
"generate-all:check": "pnpm run generate-all && git diff --exit-code",
"generate:configs": "ts-node tools/generate-configs",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 72f8abd0..985b9771 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -17,7 +17,7 @@ importers:
devDependencies:
'@commitlint/cli':
specifier: ^19.6.0
- version: 19.8.0(@types/node@22.10.1)(typescript@5.7.2)
+ version: 19.8.0(@types/node@22.15.29)(typescript@5.7.2)
'@commitlint/config-conventional':
specifier: ^19.6.0
version: 19.8.0
@@ -32,7 +32,7 @@ importers:
version: 29.5.14
'@types/node':
specifier: ^22.9.3
- version: 22.10.1
+ version: 22.15.29
'@typescript-eslint/eslint-plugin':
specifier: ^8.15.0
version: 8.15.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)
@@ -62,7 +62,7 @@ importers:
version: 2.31.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
eslint-plugin-jest:
specifier: ^28.9.0
- version: 28.9.0(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(jest@29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2)))(typescript@5.7.2)
+ version: 28.12.0(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2)))(typescript@5.7.2)
eslint-plugin-jest-formatting:
specifier: ^3.1.0
version: 3.1.0(eslint@8.57.1)
@@ -74,7 +74,7 @@ importers:
version: 7.2.1(eslint@8.57.1)
eslint-remote-tester:
specifier: ^3.0.1
- version: 3.0.1(eslint@8.57.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2))
+ version: 3.0.1(eslint@8.57.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2))
eslint-remote-tester-repositories:
specifier: ^1.0.1
version: 1.0.1
@@ -86,7 +86,7 @@ importers:
version: 3.0.1
jest:
specifier: ^29.7.0
- version: 29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2))
+ version: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2))
lint-staged:
specifier: ^15.2.10
version: 15.4.3
@@ -101,7 +101,7 @@ importers:
version: 7.7.1
ts-node:
specifier: ^10.9.2
- version: 10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2)
+ version: 10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2)
typescript:
specifier: ^5.7.2
version: 5.7.2
@@ -777,8 +777,8 @@ packages:
'@types/json5@0.0.29':
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
- '@types/node@22.10.1':
- resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==}
+ '@types/node@22.15.29':
+ resolution: {integrity: sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==}
'@types/normalize-package-data@2.4.4':
resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
@@ -1060,11 +1060,11 @@ packages:
bottleneck@2.19.5:
resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==}
- brace-expansion@1.1.11:
- resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ brace-expansion@1.1.12:
+ resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
- brace-expansion@2.0.1:
- resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+ brace-expansion@2.0.2:
+ resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
@@ -1564,8 +1564,8 @@ packages:
peerDependencies:
eslint: '>=0.8.0'
- eslint-plugin-jest@28.9.0:
- resolution: {integrity: sha512-rLu1s1Wf96TgUUxSw6loVIkNtUjq1Re7A9QdCCHSohnvXEBAjuL420h0T/fMmkQlNsQP2GhQzEUpYHPfxBkvYQ==}
+ eslint-plugin-jest@28.12.0:
+ resolution: {integrity: sha512-J6zmDp8WiQ9tyvYXE+3RFy7/+l4hraWLzmsabYXyehkmmDd36qV4VQFc7XzcsD8C1PTNt646MSx25bO1mdd9Yw==}
engines: {node: ^16.10.0 || ^18.12.0 || >=20.0.0}
peerDependencies:
'@typescript-eslint/eslint-plugin': ^6.0.0 || ^7.0.0 || ^8.0.0
@@ -3470,8 +3470,8 @@ packages:
unbox-primitive@1.0.2:
resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
- undici-types@6.20.0:
- resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
+ undici-types@6.21.0:
+ resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
unicode-emoji-modifier-base@1.0.0:
resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==}
@@ -3861,11 +3861,11 @@ snapshots:
'@colors/colors@1.5.0':
optional: true
- '@commitlint/cli@19.8.0(@types/node@22.10.1)(typescript@5.7.2)':
+ '@commitlint/cli@19.8.0(@types/node@22.15.29)(typescript@5.7.2)':
dependencies:
'@commitlint/format': 19.8.0
'@commitlint/lint': 19.8.0
- '@commitlint/load': 19.8.0(@types/node@22.10.1)(typescript@5.7.2)
+ '@commitlint/load': 19.8.0(@types/node@22.15.29)(typescript@5.7.2)
'@commitlint/read': 19.8.0
'@commitlint/types': 19.8.0
tinyexec: 0.3.2
@@ -3912,7 +3912,7 @@ snapshots:
'@commitlint/rules': 19.8.0
'@commitlint/types': 19.8.0
- '@commitlint/load@19.8.0(@types/node@22.10.1)(typescript@5.7.2)':
+ '@commitlint/load@19.8.0(@types/node@22.15.29)(typescript@5.7.2)':
dependencies:
'@commitlint/config-validator': 19.8.0
'@commitlint/execute-rule': 19.8.0
@@ -3920,7 +3920,7 @@ snapshots:
'@commitlint/types': 19.8.0
chalk: 5.4.1
cosmiconfig: 9.0.0(typescript@5.7.2)
- cosmiconfig-typescript-loader: 6.1.0(@types/node@22.10.1)(cosmiconfig@9.0.0(typescript@5.7.2))(typescript@5.7.2)
+ cosmiconfig-typescript-loader: 6.1.0(@types/node@22.15.29)(cosmiconfig@9.0.0(typescript@5.7.2))(typescript@5.7.2)
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
lodash.uniq: 4.5.0
@@ -4023,27 +4023,27 @@ snapshots:
'@jest/console@29.7.0':
dependencies:
'@jest/types': 29.6.3
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
chalk: 4.1.2
jest-message-util: 29.7.0
jest-util: 29.7.0
slash: 3.0.0
- '@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2))':
+ '@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2))':
dependencies:
'@jest/console': 29.7.0
'@jest/reporters': 29.7.0
'@jest/test-result': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
ansi-escapes: 4.3.2
chalk: 4.1.2
ci-info: 3.9.0
exit: 0.1.2
graceful-fs: 4.2.11
jest-changed-files: 29.7.0
- jest-config: 29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2))
+ jest-config: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2))
jest-haste-map: 29.7.0
jest-message-util: 29.7.0
jest-regex-util: 29.6.3
@@ -4072,7 +4072,7 @@ snapshots:
dependencies:
'@jest/fake-timers': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
jest-mock: 29.7.0
'@jest/expect-utils@29.7.0':
@@ -4090,7 +4090,7 @@ snapshots:
dependencies:
'@jest/types': 29.6.3
'@sinonjs/fake-timers': 10.3.0
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
jest-message-util: 29.7.0
jest-mock: 29.7.0
jest-util: 29.7.0
@@ -4112,7 +4112,7 @@ snapshots:
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
'@jridgewell/trace-mapping': 0.3.25
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
chalk: 4.1.2
collect-v8-coverage: 1.0.2
exit: 0.1.2
@@ -4182,7 +4182,7 @@ snapshots:
'@jest/schemas': 29.6.3
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
'@types/yargs': 17.0.33
chalk: 4.1.2
@@ -4488,11 +4488,11 @@ snapshots:
'@types/conventional-commits-parser@5.0.1':
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
'@types/graceful-fs@4.1.9':
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
'@types/istanbul-lib-coverage@2.0.6': {}
@@ -4513,9 +4513,9 @@ snapshots:
'@types/json5@0.0.29': {}
- '@types/node@22.10.1':
+ '@types/node@22.15.29':
dependencies:
- undici-types: 6.20.0
+ undici-types: 6.21.0
'@types/normalize-package-data@2.4.4': {}
@@ -4873,12 +4873,12 @@ snapshots:
bottleneck@2.19.5: {}
- brace-expansion@1.1.11:
+ brace-expansion@1.1.12:
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
- brace-expansion@2.0.1:
+ brace-expansion@2.0.2:
dependencies:
balanced-match: 1.0.2
@@ -5066,9 +5066,9 @@ snapshots:
core-util-is@1.0.3: {}
- cosmiconfig-typescript-loader@6.1.0(@types/node@22.10.1)(cosmiconfig@9.0.0(typescript@5.7.2))(typescript@5.7.2):
+ cosmiconfig-typescript-loader@6.1.0(@types/node@22.15.29)(cosmiconfig@9.0.0(typescript@5.7.2))(typescript@5.7.2):
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
cosmiconfig: 9.0.0(typescript@5.7.2)
jiti: 2.4.2
typescript: 5.7.2
@@ -5091,13 +5091,13 @@ snapshots:
optionalDependencies:
typescript: 5.7.2
- create-jest@29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2)):
+ create-jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2)):
dependencies:
'@jest/types': 29.6.3
chalk: 4.1.2
exit: 0.1.2
graceful-fs: 4.2.11
- jest-config: 29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2))
+ jest-config: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2))
jest-util: 29.7.0
prompts: 2.4.2
transitivePeerDependencies:
@@ -5427,13 +5427,13 @@ snapshots:
dependencies:
eslint: 8.57.1
- eslint-plugin-jest@28.9.0(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(jest@29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2)))(typescript@5.7.2):
+ eslint-plugin-jest@28.12.0(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2)))(typescript@5.7.2):
dependencies:
'@typescript-eslint/utils': 8.15.0(eslint@8.57.1)(typescript@5.7.2)
eslint: 8.57.1
optionalDependencies:
'@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)
- jest: 29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2))
+ jest: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2))
transitivePeerDependencies:
- supports-color
- typescript
@@ -5455,7 +5455,7 @@ snapshots:
eslint-remote-tester-repositories@1.0.1: {}
- eslint-remote-tester@3.0.1(eslint@8.57.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2)):
+ eslint-remote-tester@3.0.1(eslint@8.57.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2)):
dependencies:
'@babel/code-frame': 7.26.2
JSONStream: 1.3.5
@@ -5466,7 +5466,7 @@ snapshots:
react: 17.0.2
simple-git: 3.27.0
optionalDependencies:
- ts-node: 10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2)
+ ts-node: 10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2)
transitivePeerDependencies:
- '@types/react'
- bufferutil
@@ -6184,7 +6184,7 @@ snapshots:
'@jest/expect': 29.7.0
'@jest/test-result': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
chalk: 4.1.2
co: 4.6.0
dedent: 1.5.3
@@ -6204,16 +6204,16 @@ snapshots:
- babel-plugin-macros
- supports-color
- jest-cli@29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2)):
+ jest-cli@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2)):
dependencies:
- '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2))
+ '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2))
'@jest/test-result': 29.7.0
'@jest/types': 29.6.3
chalk: 4.1.2
- create-jest: 29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2))
+ create-jest: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2))
exit: 0.1.2
import-local: 3.2.0
- jest-config: 29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2))
+ jest-config: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2))
jest-util: 29.7.0
jest-validate: 29.7.0
yargs: 17.7.2
@@ -6223,7 +6223,7 @@ snapshots:
- supports-color
- ts-node
- jest-config@29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2)):
+ jest-config@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2)):
dependencies:
'@babel/core': 7.26.0
'@jest/test-sequencer': 29.7.0
@@ -6248,8 +6248,8 @@ snapshots:
slash: 3.0.0
strip-json-comments: 3.1.1
optionalDependencies:
- '@types/node': 22.10.1
- ts-node: 10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2)
+ '@types/node': 22.15.29
+ ts-node: 10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2)
transitivePeerDependencies:
- babel-plugin-macros
- supports-color
@@ -6278,7 +6278,7 @@ snapshots:
'@jest/environment': 29.7.0
'@jest/fake-timers': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
jest-mock: 29.7.0
jest-util: 29.7.0
@@ -6288,7 +6288,7 @@ snapshots:
dependencies:
'@jest/types': 29.6.3
'@types/graceful-fs': 4.1.9
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
anymatch: 3.1.3
fb-watchman: 2.0.2
graceful-fs: 4.2.11
@@ -6327,7 +6327,7 @@ snapshots:
jest-mock@29.7.0:
dependencies:
'@jest/types': 29.6.3
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
jest-util: 29.7.0
jest-pnp-resolver@1.2.3(jest-resolve@29.7.0):
@@ -6362,7 +6362,7 @@ snapshots:
'@jest/test-result': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
chalk: 4.1.2
emittery: 0.13.1
graceful-fs: 4.2.11
@@ -6390,7 +6390,7 @@ snapshots:
'@jest/test-result': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
chalk: 4.1.2
cjs-module-lexer: 1.4.1
collect-v8-coverage: 1.0.2
@@ -6436,7 +6436,7 @@ snapshots:
jest-util@29.7.0:
dependencies:
'@jest/types': 29.6.3
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
chalk: 4.1.2
ci-info: 3.9.0
graceful-fs: 4.2.11
@@ -6455,7 +6455,7 @@ snapshots:
dependencies:
'@jest/test-result': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
ansi-escapes: 4.3.2
chalk: 4.1.2
emittery: 0.13.1
@@ -6464,17 +6464,17 @@ snapshots:
jest-worker@29.7.0:
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
jest-util: 29.7.0
merge-stream: 2.0.0
supports-color: 8.1.1
- jest@29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2)):
+ jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2)):
dependencies:
- '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2))
+ '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2))
'@jest/types': 29.6.3
import-local: 3.2.0
- jest-cli: 29.7.0(@types/node@22.10.1)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2))
+ jest-cli: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2))
transitivePeerDependencies:
- '@types/node'
- babel-plugin-macros
@@ -6689,11 +6689,11 @@ snapshots:
minimatch@3.1.2:
dependencies:
- brace-expansion: 1.1.11
+ brace-expansion: 1.1.12
minimatch@9.0.5:
dependencies:
- brace-expansion: 2.0.1
+ brace-expansion: 2.0.2
minimist@1.2.8: {}
@@ -7403,14 +7403,14 @@ snapshots:
dependencies:
typescript: 5.7.2
- ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.10.1)(typescript@5.7.2):
+ ts-node@10.9.2(@swc/core@1.9.3)(@types/node@22.15.29)(typescript@5.7.2):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.11
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
- '@types/node': 22.10.1
+ '@types/node': 22.15.29
acorn: 8.14.0
acorn-walk: 8.3.4
arg: 4.1.3
@@ -7504,7 +7504,7 @@ snapshots:
has-symbols: 1.0.3
which-boxed-primitive: 1.0.2
- undici-types@6.20.0: {}
+ undici-types@6.21.0: {}
unicode-emoji-modifier-base@1.0.0: {}
diff --git a/tests/index.test.ts b/tests/index.test.ts
index 03cdbe2b..0d3ab20d 100644
--- a/tests/index.test.ts
+++ b/tests/index.test.ts
@@ -61,7 +61,7 @@ it('should export configs that refer to actual rules', () => {
'flat/marko',
]);
const allConfigRules = Object.values(allConfigs)
- .map((config) => Object.keys(config.rules))
+ .map((config) => Object.keys(config.rules ?? {}))
.reduce((previousValue, currentValue) => [
...previousValue,
...currentValue,
diff --git a/tests/lib/rules/consistent-data-testid.test.ts b/tests/lib/rules/consistent-data-testid.test.ts
index b0f5874a..a2cdc46c 100644
--- a/tests/lib/rules/consistent-data-testid.test.ts
+++ b/tests/lib/rules/consistent-data-testid.test.ts
@@ -1,4 +1,7 @@
-import { type TSESLint } from '@typescript-eslint/utils';
+import {
+ type InvalidTestCase,
+ type ValidTestCase,
+} from '@typescript-eslint/rule-tester';
import rule, {
MessageIds,
@@ -9,9 +12,9 @@ import { createRuleTester } from '../test-utils';
const ruleTester = createRuleTester();
-type ValidTestCase = TSESLint.ValidTestCase;
-type InvalidTestCase = TSESLint.InvalidTestCase;
-type TestCase = InvalidTestCase | ValidTestCase;
+type RuleValidTestCase = ValidTestCase;
+type RuleInvalidTestCase = InvalidTestCase;
+type TestCase = RuleValidTestCase | RuleInvalidTestCase;
const disableAggressiveReporting = (array: T[]): T[] =>
array.map((testCase) => ({
...testCase,
@@ -22,11 +25,11 @@ const disableAggressiveReporting = (array: T[]): T[] =>
},
}));
-const validTestCases: ValidTestCase[] = [
+const validTestCases: RuleValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -40,7 +43,7 @@ const validTestCases: ValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -54,7 +57,7 @@ const validTestCases: ValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -73,7 +76,7 @@ const validTestCases: ValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -92,7 +95,7 @@ const validTestCases: ValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -111,7 +114,7 @@ const validTestCases: ValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -130,7 +133,7 @@ const validTestCases: ValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -149,7 +152,7 @@ const validTestCases: ValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -168,7 +171,7 @@ const validTestCases: ValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -188,7 +191,7 @@ const validTestCases: ValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
const dynamicTestId = 'somethingDynamic';
return (
@@ -205,7 +208,7 @@ const validTestCases: ValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -224,7 +227,7 @@ const validTestCases: ValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -244,7 +247,7 @@ const validTestCases: ValidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -262,11 +265,11 @@ const validTestCases: ValidTestCase[] = [
filename: '/my/cool/file/path/[...wildcard].js',
},
];
-const invalidTestCases: InvalidTestCase[] = [
+const invalidTestCases: RuleInvalidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -291,7 +294,7 @@ const invalidTestCases: InvalidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -321,7 +324,7 @@ const invalidTestCases: InvalidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -352,7 +355,7 @@ const invalidTestCases: InvalidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -391,7 +394,7 @@ const invalidTestCases: InvalidTestCase[] = [
{
code: `
import React from 'react';
-
+
const TestComponent = props => {
return (
@@ -421,7 +424,7 @@ const invalidTestCases: InvalidTestCase[] = [
{
code: ` // test for custom message
import React from 'react';
-
+
const TestComponent = props => {
return (
diff --git a/tests/lib/rules/no-node-access.test.ts b/tests/lib/rules/no-node-access.test.ts
index cdecd5a9..32960944 100644
--- a/tests/lib/rules/no-node-access.test.ts
+++ b/tests/lib/rules/no-node-access.test.ts
@@ -1,11 +1,17 @@
-import { type TSESLint } from '@typescript-eslint/utils';
+import { InvalidTestCase, ValidTestCase } from '@typescript-eslint/rule-tester';
-import rule, { RULE_NAME, Options } from '../../../lib/rules/no-node-access';
+import rule, {
+ RULE_NAME,
+ Options,
+ MessageIds,
+} from '../../../lib/rules/no-node-access';
+import { EVENT_HANDLER_METHODS, EVENTS_SIMULATORS } from '../../../lib/utils';
import { createRuleTester } from '../test-utils';
const ruleTester = createRuleTester();
-type ValidTestCase = TSESLint.ValidTestCase
;
+type RuleValidTestCase = ValidTestCase;
+type RuleInvalidTestCase = InvalidTestCase;
const SUPPORTED_TESTING_FRAMEWORKS = [
'@testing-library/angular',
@@ -15,7 +21,7 @@ const SUPPORTED_TESTING_FRAMEWORKS = [
];
ruleTester.run(RULE_NAME, rule, {
- valid: SUPPORTED_TESTING_FRAMEWORKS.flatMap(
+ valid: SUPPORTED_TESTING_FRAMEWORKS.flatMap(
(testingFramework) => [
{
code: `
@@ -100,7 +106,7 @@ ruleTester.run(RULE_NAME, rule, {
code: `/* related to issue #386 fix
* now all node accessing properties (listed in lib/utils/index.ts, in PROPERTIES_RETURNING_NODES)
* will not be reported by this rule because anything props.something won't be reported.
- */
+ */
import { screen } from '${testingFramework}';
function ComponentA(props) {
if (props.firstChild) {
@@ -142,21 +148,39 @@ ruleTester.run(RULE_NAME, rule, {
// Example from discussions in issue #386
code: `
import { render } from '${testingFramework}';
-
+
function Wrapper({ children }) {
// this should NOT be reported
if (children) {
// ...
}
-
+
// this should NOT be reported
return {children}
};
-
+
render();
expect(screen.getByText('SomeComponent')).toBeInTheDocument();
`,
},
+ {
+ code: `
+ import userEvent from '@testing-library/user-event';
+ import { screen } from '${testingFramework}';
+
+ const buttonText = screen.getByText('submit');
+ const user = userEvent.setup();
+ user.click(buttonText);
+ `,
+ },
+ ...EVENTS_SIMULATORS.map((simulator) => ({
+ code: `
+ import { screen } from '${testingFramework}';
+
+ const buttonText = screen.getByText('submit');
+ ${simulator}.click(buttonText);
+ `,
+ })),
]
),
invalid: SUPPORTED_TESTING_FRAMEWORKS.flatMap((testingFramework) => [
@@ -395,5 +419,24 @@ ruleTester.run(RULE_NAME, rule, {
},
],
},
+ ...EVENT_HANDLER_METHODS.map((method) => ({
+ code: `
+ import { screen } from '${testingFramework}';
+
+ const button = document.getElementById('submit-btn').${method}();
+ `,
+ errors: [
+ {
+ line: 4,
+ column: 33,
+ messageId: 'noNodeAccess',
+ },
+ {
+ line: 4,
+ column: 62,
+ messageId: 'noNodeAccess',
+ },
+ ],
+ })),
]),
});
diff --git a/tests/lib/rules/no-unnecessary-act.test.ts b/tests/lib/rules/no-unnecessary-act.test.ts
index 3dcac3d8..26305961 100644
--- a/tests/lib/rules/no-unnecessary-act.test.ts
+++ b/tests/lib/rules/no-unnecessary-act.test.ts
@@ -1,4 +1,7 @@
-import { type TSESLint } from '@typescript-eslint/utils';
+import {
+ type InvalidTestCase,
+ type ValidTestCase,
+} from '@typescript-eslint/rule-tester';
import rule, {
MessageIds,
@@ -9,9 +12,9 @@ import { createRuleTester } from '../test-utils';
const ruleTester = createRuleTester();
-type ValidTestCase = TSESLint.ValidTestCase;
-type InvalidTestCase = TSESLint.InvalidTestCase;
-type TestCase = InvalidTestCase | ValidTestCase;
+type RuleValidTestCase = ValidTestCase;
+type RuleInvalidTestCase = InvalidTestCase;
+type TestCase = RuleInvalidTestCase | RuleValidTestCase;
const addOptions = (
array: T[],
@@ -37,7 +40,7 @@ const SUPPORTED_TESTING_FRAMEWORKS = [
['@marko/testing-library', 'Marko TL'],
];
-const validNonStrictTestCases: ValidTestCase[] = [
+const validNonStrictTestCases: RuleValidTestCase[] = [
{
code: `// case: RTL act wrapping both RTL and non-RTL calls
import { act, render, waitFor } from '@testing-library/react'
@@ -62,7 +65,7 @@ const validNonStrictTestCases: ValidTestCase[] = [
},
];
-const validTestCases: ValidTestCase[] = [
+const validTestCases: RuleValidTestCase[] = [
...SUPPORTED_TESTING_FRAMEWORKS.map(([testingFramework, shortName]) => ({
code: `// case: ${shortName} act wrapping non-${shortName} calls
import { act } from '${testingFramework}'
@@ -214,7 +217,7 @@ const validTestCases: ValidTestCase[] = [
})),
];
-const invalidStrictTestCases: InvalidTestCase[] =
+const invalidStrictTestCases: RuleInvalidTestCase[] =
SUPPORTED_TESTING_FRAMEWORKS.flatMap(([testingFramework, shortName]) => [
{
code: `// case: ${shortName} act wrapping both ${shortName} and non-${shortName} calls with strict option
@@ -244,7 +247,7 @@ const invalidStrictTestCases: InvalidTestCase[] =
},
]);
-const invalidTestCases: InvalidTestCase[] = [
+const invalidTestCases: RuleInvalidTestCase[] = [
...SUPPORTED_TESTING_FRAMEWORKS.map(
([testingFramework, shortName]) =>
({
diff --git a/tests/lib/rules/no-wait-for-side-effects.test.ts b/tests/lib/rules/no-wait-for-side-effects.test.ts
index 2cdbe093..c7eed01a 100644
--- a/tests/lib/rules/no-wait-for-side-effects.test.ts
+++ b/tests/lib/rules/no-wait-for-side-effects.test.ts
@@ -1,4 +1,9 @@
-import rule, { RULE_NAME } from '../../../lib/rules/no-wait-for-side-effects';
+import { InvalidTestCase } from '@typescript-eslint/rule-tester';
+
+import rule, {
+ RULE_NAME,
+ type MessageIds,
+} from '../../../lib/rules/no-wait-for-side-effects';
import { createRuleTester } from '../test-utils';
const ruleTester = createRuleTester();
@@ -118,7 +123,7 @@ ruleTester.run(RULE_NAME, rule, {
code: `
import { waitFor } from '${testingFramework}';
import { notUserEvent } from 'somewhere-else';
-
+
waitFor(() => {
await notUserEvent.click(button)
})
@@ -736,7 +741,7 @@ ruleTester.run(RULE_NAME, rule, {
expect(b).toEqual('b')
}).then(() => {
userEvent.click(button) // Side effects are allowed inside .then()
- expect(b).toEqual('b')
+ expect(b).toEqual('b')
})
`,
errors: [{ line: 4, column: 11, messageId: 'noSideEffectsWaitFor' }],
@@ -808,9 +813,10 @@ ruleTester.run(RULE_NAME, rule, {
} as const,
]),
- ...SUPPORTED_TESTING_FRAMEWORKS.flatMap((testingFramework) => [
- {
- code: `
+ ...SUPPORTED_TESTING_FRAMEWORKS.flatMap>(
+ (testingFramework) => [
+ {
+ code: `
import { waitFor } from '${testingFramework}';
import userEvent from '@testing-library/user-event'
@@ -820,8 +826,9 @@ ruleTester.run(RULE_NAME, rule, {
});
});
`,
- errors: [{ line: 7, column: 13, messageId: 'noSideEffectsWaitFor' }],
- },
- ]),
+ errors: [{ line: 7, column: 13, messageId: 'noSideEffectsWaitFor' }],
+ },
+ ]
+ ),
],
});
diff --git a/tests/lib/rules/prefer-find-by.test.ts b/tests/lib/rules/prefer-find-by.test.ts
index 2f27043e..b4728c15 100644
--- a/tests/lib/rules/prefer-find-by.test.ts
+++ b/tests/lib/rules/prefer-find-by.test.ts
@@ -1,4 +1,7 @@
-import { TSESLint } from '@typescript-eslint/utils';
+import {
+ type InvalidTestCase,
+ type ValidTestCase,
+} from '@typescript-eslint/rule-tester';
import rule, {
RULE_NAME,
@@ -26,9 +29,7 @@ function buildFindByMethod(queryMethod: string) {
}
function createScenario<
- T extends
- | TSESLint.InvalidTestCase
- | TSESLint.ValidTestCase<[]>,
+ T extends InvalidTestCase | ValidTestCase<[]>,
>(callback: (waitMethod: string, queryMethod: string) => T) {
return SYNC_QUERIES_COMBINATIONS.map((queryMethod) =>
callback('waitFor', queryMethod)
@@ -51,6 +52,17 @@ ruleTester.run(RULE_NAME, rule, {
it('tests', async () => {
const submitButton = await screen.${queryMethod}('foo')
})
+ `,
+ })),
+ ...ASYNC_QUERIES_COMBINATIONS.map((queryMethod) => ({
+ code: `
+ import {waitFor} from '${testingFramework}';
+ it('tests', async () => {
+ await waitFor(async () => {
+ const button = screen.${queryMethod}("button", { name: "Submit" })
+ expect(button).toBeInTheDocument()
+ })
+ })
`,
})),
...SYNC_QUERIES_COMBINATIONS.map((queryMethod) => ({
@@ -164,11 +176,22 @@ ruleTester.run(RULE_NAME, rule, {
const { container } = render()
await waitFor(() => expect(container.querySelector('baz')).toBeInTheDocument());
})
+ `,
+ },
+ {
+ code: `
+ import {waitFor} from '${testingFramework}';
+ it('tests', async () => {
+ await waitFor(async () => {
+ const button = await foo("button", { name: "Submit" })
+ expect(button).toBeInTheDocument()
+ })
+ })
`,
},
]),
invalid: SUPPORTED_TESTING_FRAMEWORKS.flatMap((testingFramework) => [
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}, screen} from '${testingFramework}';
it('tests', async () => {
@@ -330,7 +353,7 @@ ruleTester.run(RULE_NAME, rule, {
output: null,
},
// presence matchers
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}} from '${testingFramework}';
it('tests', async () => {
@@ -359,7 +382,7 @@ ruleTester.run(RULE_NAME, rule, {
})
`,
})),
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}} from '${testingFramework}';
it('tests', async () => {
@@ -388,7 +411,7 @@ ruleTester.run(RULE_NAME, rule, {
})
`,
})),
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}} from '${testingFramework}';
it('tests', async () => {
@@ -417,7 +440,7 @@ ruleTester.run(RULE_NAME, rule, {
})
`,
})),
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}} from '${testingFramework}';
it('tests', async () => {
@@ -446,7 +469,7 @@ ruleTester.run(RULE_NAME, rule, {
})
`,
})),
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}} from '${testingFramework}';
it('tests', async () => {
@@ -475,7 +498,7 @@ ruleTester.run(RULE_NAME, rule, {
})
`,
})),
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}} from '${testingFramework}';
it('tests', async () => {
@@ -504,7 +527,7 @@ ruleTester.run(RULE_NAME, rule, {
})
`,
})),
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}} from '${testingFramework}';
it('tests', async () => {
@@ -533,7 +556,7 @@ ruleTester.run(RULE_NAME, rule, {
})
`,
})),
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}} from '${testingFramework}';
it('tests', async () => {
@@ -560,7 +583,7 @@ ruleTester.run(RULE_NAME, rule, {
})
`,
})),
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}} from '${testingFramework}';
it('tests', async () => {
@@ -587,7 +610,7 @@ ruleTester.run(RULE_NAME, rule, {
})
`,
})),
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}} from '${testingFramework}';
it('tests', async () => {
@@ -614,7 +637,7 @@ ruleTester.run(RULE_NAME, rule, {
})
`,
})),
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}} from '${testingFramework}';
it('tests', async () => {
@@ -641,7 +664,7 @@ ruleTester.run(RULE_NAME, rule, {
})
`,
})),
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `
import {${waitMethod}} from '${testingFramework}';
it('tests', async () => {
@@ -670,7 +693,7 @@ ruleTester.run(RULE_NAME, rule, {
})),
// Issue #579, https://github.com/testing-library/eslint-plugin-testing-library/issues/579
// findBy can have two sets of options: await screen.findByText('text', queryOptions, waitForOptions)
- ...createScenario((waitMethod: string, queryMethod: string) => ({
+ ...createScenario((waitMethod, queryMethod) => ({
code: `import {${waitMethod}} from '${testingFramework}';
const button = await ${waitMethod}(() => screen.${queryMethod}('Count is: 0'), { timeout: 100, interval: 200 })
`,
@@ -691,5 +714,36 @@ ruleTester.run(RULE_NAME, rule, {
)}('Count is: 0', { timeout: 100, interval: 200 })
`,
})),
+ ...ASYNC_QUERIES_COMBINATIONS.map>(
+ (queryMethod) => ({
+ code: `
+ import {waitFor} from '${testingFramework}';
+ it('tests', async () => {
+ await waitFor(async () => {
+ const button = await screen.${queryMethod}("button", { name: "Submit" })
+ expect(button).toBeInTheDocument()
+ })
+ })
+ `,
+ errors: [
+ {
+ messageId: 'preferFindBy',
+ data: {
+ queryVariant: getFindByQueryVariant(queryMethod),
+ queryMethod: queryMethod.split('By')[1],
+ prevQuery: queryMethod,
+ waitForMethodName: 'waitFor',
+ },
+ },
+ ],
+ output: `
+ import {waitFor} from '${testingFramework}';
+ it('tests', async () => {
+ const button = await screen.${queryMethod}("button", { name: "Submit" })
+ expect(button).toBeInTheDocument()
+ })
+ `,
+ })
+ ),
]),
});
diff --git a/tests/lib/rules/prefer-presence-queries.test.ts b/tests/lib/rules/prefer-presence-queries.test.ts
index 488534c7..72cbe4d5 100644
--- a/tests/lib/rules/prefer-presence-queries.test.ts
+++ b/tests/lib/rules/prefer-presence-queries.test.ts
@@ -1,4 +1,7 @@
-import { TSESLint } from '@typescript-eslint/utils';
+import {
+ type InvalidTestCase,
+ type ValidTestCase,
+} from '@typescript-eslint/rule-tester';
import rule, {
RULE_NAME,
@@ -17,8 +20,8 @@ const queryAllByQueries = ALL_QUERIES_METHODS.map(
(method) => `queryAll${method}`
);
-type RuleValidTestCase = TSESLint.ValidTestCase;
-type RuleInvalidTestCase = TSESLint.InvalidTestCase;
+type RuleValidTestCase = ValidTestCase;
+type RuleInvalidTestCase = InvalidTestCase;
type AssertionFnParams = {
query: string;
@@ -79,6 +82,15 @@ const getDisabledValidAssertion = ({
};
};
+const toggleQueryPrefix = (query: string): string => {
+ if (query.startsWith('get')) return query.replace(/^get/, 'query');
+ if (query.startsWith('query')) return query.replace(/^query/, 'get');
+ return query;
+};
+
+const applyScreenPrefix = (query: string, shouldUseScreen: boolean): string =>
+ shouldUseScreen ? `screen.${query}` : query;
+
const getInvalidAssertions = ({
query,
matcher,
@@ -86,12 +98,18 @@ const getInvalidAssertions = ({
shouldUseScreen = false,
assertionType,
}: AssertionFnParams): RuleInvalidTestCase[] => {
- const finalQuery = shouldUseScreen ? `screen.${query}` : query;
+ const finalQuery = applyScreenPrefix(query, shouldUseScreen);
const code = `expect(${finalQuery}('Hello'))${matcher}`;
+
+ const outputQuery = toggleQueryPrefix(query);
+ const finalOutputQuery = applyScreenPrefix(outputQuery, shouldUseScreen);
+ const output = `expect(${finalOutputQuery}('Hello'))${matcher}`;
+
return [
{
code,
errors: [{ messageId, line: 1, column: shouldUseScreen ? 15 : 8 }],
+ output,
},
{
code,
@@ -102,6 +120,7 @@ const getInvalidAssertions = ({
},
],
errors: [{ messageId, line: 1, column: shouldUseScreen ? 15 : 8 }],
+ output,
},
];
};
@@ -921,7 +940,7 @@ ruleTester.run(RULE_NAME, rule, {
// submit button exists
const submitButton = screen.getByRole('button')
fireEvent.click(submitButton)
-
+
// right after clicking submit button it disappears
expect(submitButton).not.toBeInTheDocument()
`,
@@ -1304,18 +1323,24 @@ ruleTester.run(RULE_NAME, rule, {
{
code: 'expect(screen.getAllByText("button")[1]).not.toBeInTheDocument()',
errors: [{ messageId: 'wrongAbsenceQuery', line: 1, column: 15 }],
+ output:
+ 'expect(screen.queryAllByText("button")[1]).not.toBeInTheDocument()',
},
{
code: 'expect(screen.getAllByText("button")[1]).not.toBeOnTheScreen()',
errors: [{ messageId: 'wrongAbsenceQuery', line: 1, column: 15 }],
+ output:
+ 'expect(screen.queryAllByText("button")[1]).not.toBeOnTheScreen()',
},
{
code: 'expect(screen.queryAllByText("button")[1]).toBeInTheDocument()',
errors: [{ messageId: 'wrongPresenceQuery', line: 1, column: 15 }],
+ output: 'expect(screen.getAllByText("button")[1]).toBeInTheDocument()',
},
{
code: 'expect(screen.queryAllByText("button")[1]).toBeOnTheScreen()',
errors: [{ messageId: 'wrongPresenceQuery', line: 1, column: 15 }],
+ output: 'expect(screen.getAllByText("button")[1]).toBeOnTheScreen()',
},
{
code: `
@@ -1323,6 +1348,10 @@ ruleTester.run(RULE_NAME, rule, {
expect(queryByCustomQuery("button")).toBeInTheDocument()
`,
errors: [{ messageId: 'wrongPresenceQuery', line: 3, column: 16 }],
+ output: `
+ // case: asserting presence incorrectly with custom queryBy* query
+ expect(getByCustomQuery("button")).toBeInTheDocument()
+ `,
},
{
code: `
@@ -1330,6 +1359,10 @@ ruleTester.run(RULE_NAME, rule, {
expect(queryByCustomQuery("button")).toBeOnTheScreen()
`,
errors: [{ messageId: 'wrongPresenceQuery', line: 3, column: 16 }],
+ output: `
+ // case: asserting presence incorrectly with custom queryBy* query
+ expect(getByCustomQuery("button")).toBeOnTheScreen()
+ `,
},
{
code: `
@@ -1337,6 +1370,10 @@ ruleTester.run(RULE_NAME, rule, {
expect(getByCustomQuery("button")).not.toBeInTheDocument()
`,
errors: [{ messageId: 'wrongAbsenceQuery', line: 3, column: 16 }],
+ output: `
+ // case: asserting absence incorrectly with custom getBy* query
+ expect(queryByCustomQuery("button")).not.toBeInTheDocument()
+ `,
},
{
code: `
@@ -1344,6 +1381,10 @@ ruleTester.run(RULE_NAME, rule, {
expect(getByCustomQuery("button")).not.toBeOnTheScreen()
`,
errors: [{ messageId: 'wrongAbsenceQuery', line: 3, column: 16 }],
+ output: `
+ // case: asserting absence incorrectly with custom getBy* query
+ expect(queryByCustomQuery("button")).not.toBeOnTheScreen()
+ `,
},
{
settings: {
@@ -1355,6 +1396,11 @@ ruleTester.run(RULE_NAME, rule, {
expect(queryByRole("button")).toBeInTheDocument()
`,
errors: [{ line: 4, column: 14, messageId: 'wrongPresenceQuery' }],
+ output: `
+ // case: asserting presence incorrectly importing custom module
+ import 'test-utils'
+ expect(getByRole("button")).toBeInTheDocument()
+ `,
},
{
settings: {
@@ -1366,6 +1412,11 @@ ruleTester.run(RULE_NAME, rule, {
expect(queryByRole("button")).toBeOnTheScreen()
`,
errors: [{ line: 4, column: 14, messageId: 'wrongPresenceQuery' }],
+ output: `
+ // case: asserting presence incorrectly importing custom module
+ import 'test-utils'
+ expect(getByRole("button")).toBeOnTheScreen()
+ `,
},
{
settings: {
@@ -1377,6 +1428,11 @@ ruleTester.run(RULE_NAME, rule, {
expect(getByRole("button")).not.toBeInTheDocument()
`,
errors: [{ line: 4, column: 14, messageId: 'wrongAbsenceQuery' }],
+ output: `
+ // case: asserting absence incorrectly importing custom module
+ import 'test-utils'
+ expect(queryByRole("button")).not.toBeInTheDocument()
+ `,
},
{
settings: {
@@ -1388,18 +1444,29 @@ ruleTester.run(RULE_NAME, rule, {
expect(getByRole("button")).not.toBeOnTheScreen()
`,
errors: [{ line: 4, column: 14, messageId: 'wrongAbsenceQuery' }],
+ output: `
+ // case: asserting absence incorrectly importing custom module
+ import 'test-utils'
+ expect(queryByRole("button")).not.toBeOnTheScreen()
+ `,
},
{
code: `
// case: asserting within check does still work with improper outer clause
expect(within(screen.getByRole("button")).getByText("Hello")).not.toBeInTheDocument()`,
errors: [{ line: 3, column: 46, messageId: 'wrongAbsenceQuery' }],
+ output: `
+ // case: asserting within check does still work with improper outer clause
+ expect(within(screen.getByRole("button")).queryByText("Hello")).not.toBeInTheDocument()`,
},
{
code: `
// case: asserting within check does still work with improper outer clause
expect(within(screen.getByRole("button")).queryByText("Hello")).toBeInTheDocument()`,
errors: [{ line: 3, column: 46, messageId: 'wrongPresenceQuery' }],
+ output: `
+ // case: asserting within check does still work with improper outer clause
+ expect(within(screen.getByRole("button")).getByText("Hello")).toBeInTheDocument()`,
},
{
code: `
@@ -1409,18 +1476,27 @@ ruleTester.run(RULE_NAME, rule, {
{ line: 3, column: 25, messageId: 'wrongPresenceQuery' },
{ line: 3, column: 48, messageId: 'wrongAbsenceQuery' },
],
+ output: `
+ // case: asserting within check does still work with improper outer clause and improper inner clause
+ expect(within(screen.getByRole("button")).queryByText("Hello")).not.toBeInTheDocument()`,
},
{
code: `
// case: asserting within check does still work with proper outer clause and improper inner clause
expect(within(screen.queryByRole("button")).queryByText("Hello")).not.toBeInTheDocument()`,
errors: [{ line: 3, column: 25, messageId: 'wrongPresenceQuery' }],
+ output: `
+ // case: asserting within check does still work with proper outer clause and improper inner clause
+ expect(within(screen.getByRole("button")).queryByText("Hello")).not.toBeInTheDocument()`,
},
{
code: `
// case: asserting within check does still work with proper outer clause and improper inner clause
expect(within(screen.queryByRole("button")).getByText("Hello")).toBeInTheDocument()`,
errors: [{ line: 3, column: 25, messageId: 'wrongPresenceQuery' }],
+ output: `
+ // case: asserting within check does still work with proper outer clause and improper inner clause
+ expect(within(screen.getByRole("button")).getByText("Hello")).toBeInTheDocument()`,
},
{
code: `
@@ -1430,18 +1506,27 @@ ruleTester.run(RULE_NAME, rule, {
{ line: 3, column: 25, messageId: 'wrongPresenceQuery' },
{ line: 3, column: 48, messageId: 'wrongPresenceQuery' },
],
+ output: `
+ // case: asserting within check does still work with improper outer clause and improper inner clause
+ expect(within(screen.getByRole("button")).getByText("Hello")).toBeInTheDocument()`,
},
{
code: `
// case: asserting within check does still work with improper outer clause
expect(within(screen.getByRole("button")).getByText("Hello")).not.toBeOnTheScreen()`,
errors: [{ line: 3, column: 46, messageId: 'wrongAbsenceQuery' }],
+ output: `
+ // case: asserting within check does still work with improper outer clause
+ expect(within(screen.getByRole("button")).queryByText("Hello")).not.toBeOnTheScreen()`,
},
{
code: `
// case: asserting within check does still work with improper outer clause
expect(within(screen.getByRole("button")).queryByText("Hello")).toBeOnTheScreen()`,
errors: [{ line: 3, column: 46, messageId: 'wrongPresenceQuery' }],
+ output: `
+ // case: asserting within check does still work with improper outer clause
+ expect(within(screen.getByRole("button")).getByText("Hello")).toBeOnTheScreen()`,
},
{
code: `
@@ -1451,18 +1536,27 @@ ruleTester.run(RULE_NAME, rule, {
{ line: 3, column: 25, messageId: 'wrongPresenceQuery' },
{ line: 3, column: 48, messageId: 'wrongAbsenceQuery' },
],
+ output: `
+ // case: asserting within check does still work with improper outer clause and improper inner clause
+ expect(within(screen.getByRole("button")).queryByText("Hello")).not.toBeOnTheScreen()`,
},
{
code: `
// case: asserting within check does still work with proper outer clause and improper inner clause
expect(within(screen.queryByRole("button")).queryByText("Hello")).not.toBeOnTheScreen()`,
errors: [{ line: 3, column: 25, messageId: 'wrongPresenceQuery' }],
+ output: `
+ // case: asserting within check does still work with proper outer clause and improper inner clause
+ expect(within(screen.getByRole("button")).queryByText("Hello")).not.toBeOnTheScreen()`,
},
{
code: `
// case: asserting within check does still work with proper outer clause and improper inner clause
expect(within(screen.queryByRole("button")).getByText("Hello")).toBeOnTheScreen()`,
errors: [{ line: 3, column: 25, messageId: 'wrongPresenceQuery' }],
+ output: `
+ // case: asserting within check does still work with proper outer clause and improper inner clause
+ expect(within(screen.getByRole("button")).getByText("Hello")).toBeOnTheScreen()`,
},
{
code: `
@@ -1472,6 +1566,9 @@ ruleTester.run(RULE_NAME, rule, {
{ line: 3, column: 25, messageId: 'wrongPresenceQuery' },
{ line: 3, column: 48, messageId: 'wrongPresenceQuery' },
],
+ output: `
+ // case: asserting within check does still work with improper outer clause and improper inner clause
+ expect(within(screen.getByRole("button")).getByText("Hello")).toBeOnTheScreen()`,
},
],
});
diff --git a/tests/lib/rules/prefer-query-matchers.test.ts b/tests/lib/rules/prefer-query-matchers.test.ts
index 908f1b27..66f03644 100644
--- a/tests/lib/rules/prefer-query-matchers.test.ts
+++ b/tests/lib/rules/prefer-query-matchers.test.ts
@@ -1,4 +1,7 @@
-import { TSESLint } from '@typescript-eslint/utils';
+import {
+ type InvalidTestCase,
+ type ValidTestCase,
+} from '@typescript-eslint/rule-tester';
import rule, {
RULE_NAME,
@@ -17,8 +20,8 @@ const queryAllByQueries = ALL_QUERIES_METHODS.map(
(method) => `queryAll${method}`
);
-type RuleValidTestCase = TSESLint.ValidTestCase;
-type RuleInvalidTestCase = TSESLint.InvalidTestCase;
+type RuleValidTestCase = ValidTestCase;
+type RuleInvalidTestCase = InvalidTestCase;
type AssertionFnParams = {
query: string;
diff --git a/tests/lib/rules/prefer-user-event.test.ts b/tests/lib/rules/prefer-user-event.test.ts
index aae52d9b..299a65dc 100644
--- a/tests/lib/rules/prefer-user-event.test.ts
+++ b/tests/lib/rules/prefer-user-event.test.ts
@@ -1,4 +1,7 @@
-import { TSESLint } from '@typescript-eslint/utils';
+import {
+ type InvalidTestCase,
+ type ValidTestCase,
+} from '@typescript-eslint/rule-tester';
import rule, {
MAPPING_TO_USER_EVENT,
@@ -11,9 +14,7 @@ import { LIBRARY_MODULES } from '../../../lib/utils';
import { createRuleTester } from '../test-utils';
function createScenarioWithImport<
- T extends
- | TSESLint.InvalidTestCase
- | TSESLint.ValidTestCase,
+ T extends InvalidTestCase | ValidTestCase,
>(callback: (libraryModule: string, fireEventMethod: string) => T) {
return LIBRARY_MODULES.reduce(
(acc: Array, libraryModule) =>
@@ -69,7 +70,7 @@ ruleTester.run(RULE_NAME, rule, {
userEvent.${userEventMethod}(foo)
`,
})),
- ...createScenarioWithImport>(
+ ...createScenarioWithImport>(
(libraryModule: string, fireEventMethod: string) => ({
code: `
import { fireEvent } from '${libraryModule}'
@@ -79,7 +80,7 @@ ruleTester.run(RULE_NAME, rule, {
options: [{ allowedMethods: [fireEventMethod] }],
})
),
- ...createScenarioWithImport>(
+ ...createScenarioWithImport>(
(libraryModule: string, fireEventMethod: string) => ({
code: `
import { fireEvent as fireEventAliased } from '${libraryModule}'
@@ -89,7 +90,7 @@ ruleTester.run(RULE_NAME, rule, {
options: [{ allowedMethods: [fireEventMethod] }],
})
),
- ...createScenarioWithImport>(
+ ...createScenarioWithImport>(
(libraryModule: string, fireEventMethod: string) => ({
code: `
import * as dom from '${libraryModule}'
@@ -273,7 +274,7 @@ ruleTester.run(RULE_NAME, rule, {
},
],
invalid: [
- ...createScenarioWithImport>(
+ ...createScenarioWithImport>(
(libraryModule: string, fireEventMethod: string) => ({
code: `
import { fireEvent } from '${libraryModule}'
@@ -293,7 +294,7 @@ ruleTester.run(RULE_NAME, rule, {
],
})
),
- ...createScenarioWithImport>(
+ ...createScenarioWithImport>(
(libraryModule: string, fireEventMethod: string) => ({
code: `
import * as dom from '${libraryModule}'
@@ -312,7 +313,7 @@ ruleTester.run(RULE_NAME, rule, {
],
})
),
- ...createScenarioWithImport>(
+ ...createScenarioWithImport>(
(libraryModule: string, fireEventMethod: string) => ({
code: `
const { fireEvent } = require('${libraryModule}')
@@ -331,7 +332,7 @@ ruleTester.run(RULE_NAME, rule, {
],
})
),
- ...createScenarioWithImport>(
+ ...createScenarioWithImport>(
(libraryModule: string, fireEventMethod: string) => ({
code: `
const rtl = require('${libraryModule}')
@@ -484,7 +485,7 @@ ruleTester.run(RULE_NAME, rule, {
},
code: `
import { fireEvent, createEvent } from 'test-utils'
-
+
fireEvent(node, createEvent('${fireEventMethod}', node))
`,
errors: [
diff --git a/tsconfig.build.json b/tsconfig.build.json
new file mode 100644
index 00000000..f46aafbc
--- /dev/null
+++ b/tsconfig.build.json
@@ -0,0 +1,4 @@
+{
+ "extends": "./tsconfig.json",
+ "exclude": ["./tests/**/*.ts"]
+}
diff --git a/tsconfig.json b/tsconfig.json
index b4fb3559..c52787a0 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -16,5 +16,5 @@
"outDir": "dist",
"sourceMap": false
},
- "include": ["./lib/**/*.ts"]
+ "include": ["./lib/**/*.ts", "./tests/**/*.ts"]
}