diff --git a/.eslintrc.json b/.eslintrc.json
index 5e07a699..56f12605 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -21,6 +21,7 @@
"react-hooks",
"import",
"vitest",
+ "testing-library",
"eslint-plugin-react-compiler"
],
"parser": "@typescript-eslint/parser",
@@ -109,6 +110,7 @@
},
"overrides": [
{
+ "extends": ["plugin:testing-library/react"],
"files": ["tests/**/*.ts", "tests/**/*.tsx"],
"rules": {
"import/extensions": ["error", "never"],
diff --git a/package.json b/package.json
index 3ee875fb..8cb0bd35 100644
--- a/package.json
+++ b/package.json
@@ -128,6 +128,7 @@
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-compiler": "19.0.0-beta-8a03594-20241020",
"eslint-plugin-react-hooks": "^5.0.0",
+ "eslint-plugin-testing-library": "^6.4.0",
"eslint-plugin-vitest": "^0.5.4",
"jest-leak-detector": "^29.7.0",
"jsdom": "^25.0.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 50ce475b..f092b900 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -78,6 +78,9 @@ importers:
eslint-plugin-react-hooks:
specifier: ^5.0.0
version: 5.0.0(eslint@8.57.0)
+ eslint-plugin-testing-library:
+ specifier: ^6.4.0
+ version: 6.4.0(eslint@8.57.0)(typescript@5.6.3)
eslint-plugin-vitest:
specifier: ^0.5.4
version: 0.5.4(@typescript-eslint/eslint-plugin@8.13.0)(eslint@8.57.0)(typescript@5.6.3)(vitest@2.1.4)
@@ -4566,6 +4569,10 @@ packages:
/@types/scheduler@0.23.0:
resolution: {integrity: sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==}
+ /@types/semver@7.5.8:
+ resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
+ dev: true
+
/@types/source-list-map@0.1.6:
resolution: {integrity: sha512-5JcVt1u5HDmlXkwOD2nslZVllBBc7HDuOICfiZah2Z0is8M8g+ddAEawbmd3VjedfDHBzxCaXLs07QEmb7y54g==}
@@ -4741,6 +4748,14 @@ packages:
'@typescript-eslint/types': 4.33.0
'@typescript-eslint/visitor-keys': 4.33.0
+ /@typescript-eslint/scope-manager@5.62.0:
+ resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ '@typescript-eslint/types': 5.62.0
+ '@typescript-eslint/visitor-keys': 5.62.0
+ dev: true
+
/@typescript-eslint/scope-manager@7.18.0:
resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==}
engines: {node: ^18.18.0 || >=20.0.0}
@@ -4784,6 +4799,11 @@ packages:
resolution: {integrity: sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==}
engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
+ /@typescript-eslint/types@5.62.0:
+ resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
/@typescript-eslint/types@7.18.0:
resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==}
engines: {node: ^18.18.0 || >=20.0.0}
@@ -4835,6 +4855,27 @@ packages:
transitivePeerDependencies:
- supports-color
+ /@typescript-eslint/typescript-estree@5.62.0(typescript@5.6.3):
+ resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/types': 5.62.0
+ '@typescript-eslint/visitor-keys': 5.62.0
+ debug: 4.3.7
+ globby: 11.1.0
+ is-glob: 4.0.3
+ semver: 7.6.3
+ tsutils: 3.21.0(typescript@5.6.3)
+ typescript: 5.6.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/@typescript-eslint/typescript-estree@7.18.0(typescript@5.6.3):
resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==}
engines: {node: ^18.18.0 || >=20.0.0}
@@ -4879,6 +4920,26 @@ packages:
- supports-color
dev: true
+ /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.6.3):
+ resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.0)
+ '@types/json-schema': 7.0.15
+ '@types/semver': 7.5.8
+ '@typescript-eslint/scope-manager': 5.62.0
+ '@typescript-eslint/types': 5.62.0
+ '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.6.3)
+ eslint: 8.57.0
+ eslint-scope: 5.1.1
+ semver: 7.6.3
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+ dev: true
+
/@typescript-eslint/utils@7.18.0(eslint@8.57.0)(typescript@5.6.3):
resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==}
engines: {node: ^18.18.0 || >=20.0.0}
@@ -4924,6 +4985,14 @@ packages:
'@typescript-eslint/types': 4.33.0
eslint-visitor-keys: 2.1.0
+ /@typescript-eslint/visitor-keys@5.62.0:
+ resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ '@typescript-eslint/types': 5.62.0
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
/@typescript-eslint/visitor-keys@7.18.0:
resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==}
engines: {node: ^18.18.0 || >=20.0.0}
@@ -8220,6 +8289,19 @@ packages:
- supports-color
- typescript
+ /eslint-plugin-testing-library@6.4.0(eslint@8.57.0)(typescript@5.6.3):
+ resolution: {integrity: sha512-yeWF+YgCgvNyPNI9UKnG0FjeE2sk93N/3lsKqcmR8dSfeXJwFT5irnWo7NjLf152HkRzfoFjh3LsBUrhvFz4eA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'}
+ peerDependencies:
+ eslint: ^7.5.0 || ^8.0.0 || ^9.0.0
+ dependencies:
+ '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.6.3)
+ eslint: 8.57.0
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+ dev: true
+
/eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@8.13.0)(eslint@8.57.0)(typescript@5.6.3)(vitest@2.1.4):
resolution: {integrity: sha512-um+odCkccAHU53WdKAw39MY61+1x990uXjSPguUCq3VcEHdqJrOb8OTMrbYlY6f9jAKx7x98kLVlIe3RJeJqoQ==}
engines: {node: ^18.0.0 || >= 20.0.0}
@@ -14535,6 +14617,16 @@ packages:
tslib: 1.14.1
typescript: 4.4.2
+ /tsutils@3.21.0(typescript@5.6.3):
+ resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
+ engines: {node: '>= 6'}
+ peerDependencies:
+ typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
+ dependencies:
+ tslib: 1.14.1
+ typescript: 5.6.3
+ dev: true
+
/tty-browserify@0.0.0:
resolution: {integrity: sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==}
diff --git a/tests/basic.test.tsx b/tests/basic.test.tsx
index 970f031b..5f76f849 100644
--- a/tests/basic.test.tsx
+++ b/tests/basic.test.tsx
@@ -516,16 +516,16 @@ it('stable snapshot object (#985)', async () => {
)
}
- const { getByText, findByText } = render()
+ render()
- await findByText('count: 0')
+ await screen.findByText('count: 0')
expect(effectCount).toBe(1)
- fireEvent.click(getByText('button'))
- await findByText('count: 1')
+ fireEvent.click(screen.getByText('button'))
+ await screen.findByText('count: 1')
expect(effectCount).toBe(1)
- fireEvent.click(getByText('button'))
- await findByText('count: 2')
+ fireEvent.click(screen.getByText('button'))
+ await screen.findByText('count: 2')
expect(effectCount).toBe(1)
})
diff --git a/tests/proxySet.test.tsx b/tests/proxySet.test.tsx
index ea7338eb..744c43b6 100644
--- a/tests/proxySet.test.tsx
+++ b/tests/proxySet.test.tsx
@@ -641,16 +641,15 @@ describe('ui updates - useSnapshot', async () => {
)
}
- const { getByText } = render(
+ render(
,
)
- fireEvent.click(getByText('Add Item'))
- await waitFor(() => {
- getByText('1')
- })
+ fireEvent.click(screen.getByText('Add Item'))
+
+ expect(await screen.findByText('1')).toBeDefined()
})
it('should be reactive to changes when using keys method', async () => {
@@ -676,16 +675,14 @@ describe('ui updates - useSnapshot', async () => {
)
}
- const { getByText } = render(
+ render(
,
)
- fireEvent.click(getByText('Add Item'))
- await waitFor(() => {
- getByText('item key: 1')
- })
+ fireEvent.click(screen.getByText('Add Item'))
+ expect(await screen.findByText('item key: 1')).toBeDefined()
})
it('should be reactive to changes when using entries method', async () => {
@@ -711,16 +708,14 @@ describe('ui updates - useSnapshot', async () => {
)
}
- const { getByText } = render(
+ render(
,
)
- fireEvent.click(getByText('Add Item'))
- await waitFor(() => {
- getByText('key: 1; value: 1')
- })
+ fireEvent.click(screen.getByText('Add Item'))
+ expect(await screen.findByText('key: 1; value: 1')).toBeDefined()
})
})
diff --git a/tests/setup.ts b/tests/setup.ts
deleted file mode 100644
index 384ea297..00000000
--- a/tests/setup.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { cleanup } from '@testing-library/react'
-import { afterEach } from 'vitest'
-
-afterEach(cleanup)
diff --git a/vitest.config.ts b/vitest.config.ts
index 32841e8b..a2d3239e 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -11,7 +11,9 @@ export default defineConfig({
},
test: {
name: 'valtio',
- setupFiles: './tests/setup.ts',
+ // Keeping globals to true triggers React Testing Library's auto cleanup
+ // https://vitest.dev/guide/migration.html
+ globals: true,
coverage: {
include: ['src/**/'],
reporter: ['text', 'json', 'html', 'text-summary'],