Skip to content

feat!: local types, supporting jest, @jest/globals, vitest #511

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
if: ${{ !contains(github.head_ref, 'all-contributors') }}
strategy:
matrix:
node: [10.14, 12, 14, 15, 16]
node: [14, 16, 18, 20]
runs-on: ubuntu-latest
steps:
- name: ⬇️ Checkout repo
Expand Down
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ clear to read and to maintain.

- [Installation](#installation)
- [Usage](#usage)
- [With `@jest/globals`](#with-jestglobals)
- [With Vitest](#with-vitest)
- [With TypeScript](#with-typescript)
- [With another Jest-compatible `expect`](#with-another-jest-compatible-expect)
- [Custom matchers](#custom-matchers)
- [`toBeDisabled`](#tobedisabled)
- [`toBeEnabled`](#tobeenabled)
Expand Down Expand Up @@ -128,6 +131,39 @@ import '@testing-library/jest-dom'
setupFilesAfterEnv: ['<rootDir>/jest-setup.js']
```

### With `@jest/globals`

If you are using [`@jest/globals`][jest-globals announcement] with
[`injectGlobals: false`][inject-globals docs], you will need to use a different
import in your tests setup file:

```javascript
// In your own jest-setup.js (or any other name)
import '@testing-library/jest-dom/jest-globals'
```

[jest-globals announcement]:
https://jestjs.io/blog/2020/05/05/jest-26#a-new-way-to-consume-jest---jestglobals
[inject-globals docs]:
https://jestjs.io/docs/configuration#injectglobals-boolean

### With Vitest

If you are using [vitest][], this module will work as-is, but you will need to
use a different import in your tests setup file. This file should be added to
the [`setupFiles`][vitest setupfiles] property in your vitest config:

```javascript
// In your own vitest-setup.js (or any other name)
import '@testing-library/jest-dom/vitest'

// In vitest.config.js add (if you haven't already)
setupFiles: ['./vitest-setup.js']
```

[vitest]: https://vitest.dev/
[vitest setupfiles]: https://vitest.dev/config/#setupfiles

### With TypeScript

If you're using TypeScript, make sure your setup file is a `.ts` and not a `.js`
Expand All @@ -144,6 +180,18 @@ haven't already:
],
```

### With another Jest-compatible `expect`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be the approach if you're not using vitest's globals.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% sure what you mean by vitest's globals. Vitest's default mode is globals: false, which requires explicit imports of describe, expect, etc., and the new vitest entrypoint is designed to work with that. I didn't actually think to test with globals: true and importing the vitest/globals types — I'll do that tomorrow.

This section was intended as a hedge against future testing libraries that might emerge that retain some level of compatibility with Jest. But if you think it might be more confusing than helpful, I'm happy to remove it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't actually think to test with globals: true and importing the vitest/globals types — I'll do that tomorrow.

Tested this and it works.


If you are using a different test runner that is compatible with Jest's `expect`
interface, it might be possible to use it with this library:

```javascript
import * as matchers from '@testing-library/jest-dom/matchers'
import {expect} from 'my-test-runner/expect'

expect.extend(matchers)
```

## Custom matchers

`@testing-library/jest-dom` can work with any library or framework that returns
Expand Down
2 changes: 0 additions & 2 deletions extend-expect.js

This file was deleted.

1 change: 1 addition & 0 deletions jest-globals.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference path="types/jest-globals.d.ts" />
4 changes: 4 additions & 0 deletions jest-globals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const globals = require('@jest/globals')
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my testing, @jest/globals had to use CommonJS

const extensions = require('./dist/matchers')

globals.expect.extend(extensions)
3 changes: 3 additions & 0 deletions matchers.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import * as matchers from './types/matchers'

export = matchers
57 changes: 50 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
"version": "0.0.0-semantically-released",
"description": "Custom jest matchers to test the state of the DOM",
"main": "dist/index.js",
"types": "types/index.d.ts",
"engines": {
"node": ">=8",
"node": ">=14",
"npm": ">=6",
"yarn": ">=1"
},
Expand All @@ -19,8 +20,11 @@
},
"files": [
"dist",
"extend-expect.js",
"matchers.js"
"types",
"*.d.ts",
"jest-globals.js",
"matchers.js",
"vitest.js"
],
"keywords": [
"testing",
Expand All @@ -32,7 +36,6 @@
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.9.2",
"@types/testing-library__jest-dom": "^5.9.1",
"aria-query": "^5.0.0",
"chalk": "^3.0.0",
"@adobe/css-tools": "^4.0.1",
Expand All @@ -42,16 +45,44 @@
"redent": "^3.0.0"
},
"devDependencies": {
"@jest/globals": "^29.6.2",
"expect": "^29.6.2",
"jest-environment-jsdom-sixteen": "^1.0.3",
"jest-watch-select-projects": "^2.0.0",
"jsdom": "^16.2.1",
"kcd-scripts": "^11.1.0",
"pretty-format": "^25.1.0"
"kcd-scripts": "^14.0.0",
"pretty-format": "^25.1.0",
"vitest": "^0.34.1",
"typescript": "^5.1.6"
},
"peerDependencies": {
"@jest/globals": ">= 28",
"@types/jest": ">= 28",
"jest": ">= 28",
"vitest": ">= 0.32"
},
"peerDependenciesMeta": {
"@jest/globals": {
"optional": true
},
"@types/jest": {
"optional": true
},
"jest": {
"optional": true
},
"vitest": {
"optional": true
}
},
"eslintConfig": {
"extends": "./node_modules/kcd-scripts/eslint.js",
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2020
},
"rules": {
"@babel/no-invalid-this": "off"
"no-invalid-this": "off"
},
"overrides": [
{
Expand All @@ -61,6 +92,18 @@
"rules": {
"max-lines-per-function": "off"
}
},
{
"files": [
"**/*.d.ts"
],
"rules": {
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-invalid-void-type": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/triple-slash-reference": "off"
}
}
]
},
Expand Down
3 changes: 0 additions & 3 deletions src/extend-expect.js

This file was deleted.

4 changes: 3 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
import './extend-expect'
import * as extensions from './matchers'

expect.extend(extensions)
2 changes: 1 addition & 1 deletion src/to-be-in-the-document.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function toBeInTheDocument(element) {
'',
),
'',
// eslint-disable-next-line @babel/new-cap
// eslint-disable-next-line new-cap
this.utils.RECEIVED_COLOR(this.isNot ? errorFound() : errorNotFound()),
].join('\n')
},
Expand Down
2 changes: 1 addition & 1 deletion src/to-contain-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function toContainElement(container, element) {
'element',
),
'',
// eslint-disable-next-line @babel/new-cap
// eslint-disable-next-line new-cap
this.utils.RECEIVED_COLOR(`${this.utils.stringify(
container.cloneNode(false),
)} ${
Expand Down
2 changes: 1 addition & 1 deletion src/to-contain-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function toContainHTML(container, htmlText) {
'',
),
'Expected:',
// eslint-disable-next-line @babel/new-cap
// eslint-disable-next-line new-cap
` ${this.utils.EXPECTED_COLOR(htmlText)}`,
'Received:',
` ${this.utils.printReceived(container.cloneNode(true))}`,
Expand Down
10 changes: 5 additions & 5 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class GenericTypeError extends Error {
'',
),
'',
// eslint-disable-next-line @babel/new-cap
// eslint-disable-next-line new-cap
`${context.utils.RECEIVED_COLOR(
'received',
)} value must ${expectedString}.`,
Expand Down Expand Up @@ -91,9 +91,9 @@ class InvalidCSSError extends Error {
this.message = [
received.message,
'',
// eslint-disable-next-line @babel/new-cap
// eslint-disable-next-line new-cap
context.utils.RECEIVED_COLOR(`Failing css:`),
// eslint-disable-next-line @babel/new-cap
// eslint-disable-next-line new-cap
context.utils.RECEIVED_COLOR(`${received.css}`),
].join('\n')
}
Expand Down Expand Up @@ -137,11 +137,11 @@ function getMessage(
) {
return [
`${matcher}\n`,
// eslint-disable-next-line @babel/new-cap
// eslint-disable-next-line new-cap
`${expectedLabel}:\n${context.utils.EXPECTED_COLOR(
redent(display(context, expectedValue), 2),
)}`,
// eslint-disable-next-line @babel/new-cap
// eslint-disable-next-line new-cap
`${receivedLabel}:\n${context.utils.RECEIVED_COLOR(
redent(display(context, receivedValue), 2),
)}`,
Expand Down
2 changes: 1 addition & 1 deletion tests/setup-env.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {plugins} from 'pretty-format'
import '../src/extend-expect'
import '../src/index'

expect.addSnapshotSerializer(plugins.ConvertAnsi)
7 changes: 7 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"compilerOptions": {
"strict": true,
"skipLibCheck": true
},
"include": ["*.d.ts", "types"]
}
1 change: 1 addition & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference path="jest.d.ts" />
8 changes: 8 additions & 0 deletions types/jest-globals.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {type expect} from '@jest/globals'
import {type TestingLibraryMatchers} from './matchers'

export {}
declare module '@jest/expect' {
export interface Matchers<R extends void | Promise<void>>
extends TestingLibraryMatchers<typeof expect.stringContaining, R> {}
}
10 changes: 10 additions & 0 deletions types/jest.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/// <reference types="jest" />

import {type TestingLibraryMatchers} from './matchers'

declare global {
namespace jest {
interface Matchers<R = void, T = {}>
extends TestingLibraryMatchers<typeof expect.stringContaining, R> {}
}
}
Loading