Skip to content

Commit bdb34f1

Browse files
kryopsjgoz
andauthoredAug 18, 2023
fix: matchers type is making the global expect unsafe (#513)
* fix: matchers type is making the global expect unsafe * Add test file for TypeScript typings * Remove jest specifics from matchers.d.ts * Type tests for all test environments * Fix all AsymmetricMatcher interfaces * Ignore type tests from eslint --------- Co-authored-by: Michael Manzinger <michael.manzinger@mobilex.eu> Co-authored-by: John Gozde <john@gozde.ca>
1 parent 4b764b9 commit bdb34f1

15 files changed

+694
-8
lines changed
 

‎package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"setup": "npm install && npm run validate -s",
1717
"test": "kcd-scripts test",
1818
"test:update": "npm test -- --updateSnapshot --coverage",
19-
"validate": "kcd-scripts validate"
19+
"test:types": "tsc -p types/__tests__/jest && tsc -p types/__tests__/jest-globals && tsc -p types/__tests__/vitest",
20+
"validate": "kcd-scripts validate && npm run test:types"
2021
},
2122
"files": [
2223
"dist",
@@ -110,7 +111,8 @@
110111
"eslintIgnore": [
111112
"node_modules",
112113
"coverage",
113-
"dist"
114+
"dist",
115+
"types/__tests__"
114116
],
115117
"repository": {
116118
"type": "git",

‎tsconfig.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
{
22
"compilerOptions": {
3+
"noEmit": true,
34
"strict": true,
45
"skipLibCheck": true
56
},
6-
"include": ["*.d.ts", "types"]
7+
"include": ["*.d.ts", "types"],
8+
"exclude": ["types/__tests__"]
79
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* File that tests whether the TypeScript typings work as expected.
3+
*/
4+
5+
/* eslint-disable @typescript-eslint/no-unsafe-call */
6+
/* eslint-disable @typescript-eslint/no-floating-promises */
7+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
8+
9+
import {expect} from '@jest/globals'
10+
import * as matchers from '../../matchers'
11+
12+
expect.extend(matchers)
13+
14+
const element: HTMLElement = document.body
15+
16+
function customExpect(
17+
_actual: HTMLElement,
18+
):
19+
| matchers.TestingLibraryMatchers<unknown, void>
20+
| matchers.TestingLibraryMatchers<unknown, Promise<void>> {
21+
throw new Error('Method not implemented.')
22+
}
23+
24+
customExpect(element).toBeInTheDOM()
25+
customExpect(element).toBeInTheDOM(document.body)
26+
customExpect(element).toBeInTheDocument()
27+
customExpect(element).toBeVisible()
28+
customExpect(element).toBeEmpty()
29+
customExpect(element).toBeDisabled()
30+
customExpect(element).toBeEnabled()
31+
customExpect(element).toBeInvalid()
32+
customExpect(element).toBeRequired()
33+
customExpect(element).toBeValid()
34+
customExpect(element).toContainElement(document.body)
35+
customExpect(element).toContainElement(null)
36+
customExpect(element).toContainHTML('body')
37+
customExpect(element).toHaveAttribute('attr')
38+
customExpect(element).toHaveAttribute('attr', true)
39+
customExpect(element).toHaveAttribute('attr', 'yes')
40+
customExpect(element).toHaveClass()
41+
customExpect(element).toHaveClass('cls1')
42+
customExpect(element).toHaveClass('cls1', 'cls2', 'cls3', 'cls4')
43+
customExpect(element).toHaveClass('cls1', {exact: true})
44+
customExpect(element).toHaveDisplayValue('str')
45+
customExpect(element).toHaveDisplayValue(['str1', 'str2'])
46+
customExpect(element).toHaveDisplayValue(/str/)
47+
customExpect(element).toHaveDisplayValue([/str1/, 'str2'])
48+
customExpect(element).toHaveFocus()
49+
customExpect(element).toHaveFormValues({foo: 'bar', baz: 1})
50+
customExpect(element).toHaveStyle('display: block')
51+
customExpect(element).toHaveStyle({display: 'block', width: 100})
52+
customExpect(element).toHaveTextContent('Text')
53+
customExpect(element).toHaveTextContent(/Text/)
54+
customExpect(element).toHaveTextContent('Text', {normalizeWhitespace: true})
55+
customExpect(element).toHaveTextContent(/Text/, {normalizeWhitespace: true})
56+
customExpect(element).toHaveValue()
57+
customExpect(element).toHaveValue('str')
58+
customExpect(element).toHaveValue(['str1', 'str2'])
59+
customExpect(element).toHaveValue(1)
60+
customExpect(element).toHaveValue(null)
61+
customExpect(element).toBeChecked()
62+
customExpect(element).toHaveDescription('some description')
63+
customExpect(element).toHaveDescription(/some description/)
64+
customExpect(element).toHaveDescription(expect.stringContaining('partial'))
65+
customExpect(element).toHaveDescription()
66+
customExpect(element).toHaveAccessibleDescription('some description')
67+
customExpect(element).toHaveAccessibleDescription(/some description/)
68+
customExpect(element).toHaveAccessibleDescription(
69+
expect.stringContaining('partial'),
70+
)
71+
customExpect(element).toHaveAccessibleDescription()
72+
73+
customExpect(element).toHaveAccessibleErrorMessage()
74+
customExpect(element).toHaveAccessibleErrorMessage(
75+
'Invalid time: the time must be between 9:00 AM and 5:00 PM',
76+
)
77+
customExpect(element).toHaveAccessibleErrorMessage(/invalid time/i)
78+
customExpect(element).toHaveAccessibleErrorMessage(
79+
expect.stringContaining('Invalid time'),
80+
)
81+
82+
customExpect(element).toHaveAccessibleName('a label')
83+
customExpect(element).toHaveAccessibleName(/a label/)
84+
customExpect(element).toHaveAccessibleName(
85+
expect.stringContaining('partial label'),
86+
)
87+
customExpect(element).toHaveAccessibleName()
88+
customExpect(element).toHaveErrorMessage(
89+
'Invalid time: the time must be between 9:00 AM and 5:00 PM',
90+
)
91+
customExpect(element).toHaveErrorMessage(/invalid time/i)
92+
customExpect(element).toHaveErrorMessage(
93+
expect.stringContaining('Invalid time'),
94+
)
95+
96+
// @ts-expect-error The types accidentally allowed any property by falling back to "any"
97+
customExpect(element).nonExistentProperty()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/**
2+
* File that tests whether the TypeScript typings for @types/jest work as expected.
3+
*/
4+
5+
/* eslint-disable @typescript-eslint/no-unsafe-call */
6+
/* eslint-disable @typescript-eslint/no-floating-promises */
7+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
8+
9+
import {expect} from '@jest/globals'
10+
import '../../jest-globals'
11+
12+
const element: HTMLElement = document.body
13+
14+
expect(element).toBeInTheDOM()
15+
expect(element).toBeInTheDOM(document.body)
16+
expect(element).toBeInTheDocument()
17+
expect(element).toBeVisible()
18+
expect(element).toBeEmpty()
19+
expect(element).toBeDisabled()
20+
expect(element).toBeEnabled()
21+
expect(element).toBeInvalid()
22+
expect(element).toBeRequired()
23+
expect(element).toBeValid()
24+
expect(element).toContainElement(document.body)
25+
expect(element).toContainElement(null)
26+
expect(element).toContainHTML('body')
27+
expect(element).toHaveAttribute('attr')
28+
expect(element).toHaveAttribute('attr', true)
29+
expect(element).toHaveAttribute('attr', 'yes')
30+
expect(element).toHaveClass()
31+
expect(element).toHaveClass('cls1')
32+
expect(element).toHaveClass('cls1', 'cls2', 'cls3', 'cls4')
33+
expect(element).toHaveClass('cls1', {exact: true})
34+
expect(element).toHaveDisplayValue('str')
35+
expect(element).toHaveDisplayValue(['str1', 'str2'])
36+
expect(element).toHaveDisplayValue(/str/)
37+
expect(element).toHaveDisplayValue([/str1/, 'str2'])
38+
expect(element).toHaveFocus()
39+
expect(element).toHaveFormValues({foo: 'bar', baz: 1})
40+
expect(element).toHaveStyle('display: block')
41+
expect(element).toHaveStyle({display: 'block', width: 100})
42+
expect(element).toHaveTextContent('Text')
43+
expect(element).toHaveTextContent(/Text/)
44+
expect(element).toHaveTextContent('Text', {normalizeWhitespace: true})
45+
expect(element).toHaveTextContent(/Text/, {normalizeWhitespace: true})
46+
expect(element).toHaveValue()
47+
expect(element).toHaveValue('str')
48+
expect(element).toHaveValue(['str1', 'str2'])
49+
expect(element).toHaveValue(1)
50+
expect(element).toHaveValue(null)
51+
expect(element).toBeChecked()
52+
expect(element).toHaveDescription('some description')
53+
expect(element).toHaveDescription(/some description/)
54+
expect(element).toHaveDescription(expect.stringContaining('partial'))
55+
expect(element).toHaveDescription()
56+
expect(element).toHaveAccessibleDescription('some description')
57+
expect(element).toHaveAccessibleDescription(/some description/)
58+
expect(element).toHaveAccessibleDescription(expect.stringContaining('partial'))
59+
expect(element).toHaveAccessibleDescription()
60+
expect(element).toHaveAccessibleName('a label')
61+
expect(element).toHaveAccessibleName(/a label/)
62+
expect(element).toHaveAccessibleName(expect.stringContaining('partial label'))
63+
expect(element).toHaveAccessibleName()
64+
expect(element).toHaveErrorMessage(
65+
'Invalid time: the time must be between 9:00 AM and 5:00 PM',
66+
)
67+
expect(element).toHaveErrorMessage(/invalid time/i)
68+
expect(element).toHaveErrorMessage(expect.stringContaining('Invalid time'))
69+
70+
expect(element).not.toBeInTheDOM()
71+
expect(element).not.toBeInTheDOM(document.body)
72+
expect(element).not.toBeInTheDocument()
73+
expect(element).not.toBeVisible()
74+
expect(element).not.toBeEmpty()
75+
expect(element).not.toBeEmptyDOMElement()
76+
expect(element).not.toBeDisabled()
77+
expect(element).not.toBeEnabled()
78+
expect(element).not.toBeInvalid()
79+
expect(element).not.toBeRequired()
80+
expect(element).not.toBeValid()
81+
expect(element).not.toContainElement(document.body)
82+
expect(element).not.toContainElement(null)
83+
expect(element).not.toContainHTML('body')
84+
expect(element).not.toHaveAttribute('attr')
85+
expect(element).not.toHaveAttribute('attr', true)
86+
expect(element).not.toHaveAttribute('attr', 'yes')
87+
expect(element).not.toHaveClass()
88+
expect(element).not.toHaveClass('cls1')
89+
expect(element).not.toHaveClass('cls1', 'cls2', 'cls3', 'cls4')
90+
expect(element).not.toHaveClass('cls1', {exact: true})
91+
expect(element).not.toHaveDisplayValue('str')
92+
expect(element).not.toHaveDisplayValue(['str1', 'str2'])
93+
expect(element).not.toHaveDisplayValue(/str/)
94+
expect(element).not.toHaveDisplayValue([/str1/, 'str2'])
95+
expect(element).not.toHaveFocus()
96+
expect(element).not.toHaveFormValues({foo: 'bar', baz: 1})
97+
expect(element).not.toHaveStyle('display: block')
98+
expect(element).not.toHaveTextContent('Text')
99+
expect(element).not.toHaveTextContent(/Text/)
100+
expect(element).not.toHaveTextContent('Text', {normalizeWhitespace: true})
101+
expect(element).not.toHaveTextContent(/Text/, {normalizeWhitespace: true})
102+
expect(element).not.toHaveValue()
103+
expect(element).not.toHaveValue('str')
104+
expect(element).not.toHaveValue(['str1', 'str2'])
105+
expect(element).not.toHaveValue(1)
106+
expect(element).not.toBeChecked()
107+
expect(element).not.toHaveDescription('some description')
108+
expect(element).not.toHaveDescription()
109+
expect(element).not.toHaveAccessibleDescription('some description')
110+
expect(element).not.toHaveAccessibleDescription()
111+
expect(element).not.toHaveAccessibleName('a label')
112+
expect(element).not.toHaveAccessibleName()
113+
expect(element).not.toBePartiallyChecked()
114+
expect(element).not.toHaveErrorMessage()
115+
expect(element).not.toHaveErrorMessage('Pikachu!')
116+
117+
// @ts-expect-error The types accidentally allowed any property by falling back to "any"
118+
expect(element).nonExistentProperty()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"compilerOptions": {
3+
"noEmit": true,
4+
"strict": true,
5+
"skipLibCheck": true,
6+
"types": []
7+
},
8+
"include": ["*.ts"]
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* File that tests whether the TypeScript typings work as expected.
3+
*/
4+
5+
/* eslint-disable @typescript-eslint/no-unsafe-call */
6+
/* eslint-disable @typescript-eslint/no-floating-promises */
7+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
8+
9+
import * as matchers from '../../matchers'
10+
11+
expect.extend(matchers)
12+
13+
const element: HTMLElement = document.body
14+
15+
function customExpect(
16+
_actual: HTMLElement,
17+
):
18+
| matchers.TestingLibraryMatchers<unknown, void>
19+
| matchers.TestingLibraryMatchers<unknown, Promise<void>> {
20+
throw new Error('Method not implemented.')
21+
}
22+
23+
customExpect(element).toBeInTheDOM()
24+
customExpect(element).toBeInTheDOM(document.body)
25+
customExpect(element).toBeInTheDocument()
26+
customExpect(element).toBeVisible()
27+
customExpect(element).toBeEmpty()
28+
customExpect(element).toBeDisabled()
29+
customExpect(element).toBeEnabled()
30+
customExpect(element).toBeInvalid()
31+
customExpect(element).toBeRequired()
32+
customExpect(element).toBeValid()
33+
customExpect(element).toContainElement(document.body)
34+
customExpect(element).toContainElement(null)
35+
customExpect(element).toContainHTML('body')
36+
customExpect(element).toHaveAttribute('attr')
37+
customExpect(element).toHaveAttribute('attr', true)
38+
customExpect(element).toHaveAttribute('attr', 'yes')
39+
customExpect(element).toHaveClass()
40+
customExpect(element).toHaveClass('cls1')
41+
customExpect(element).toHaveClass('cls1', 'cls2', 'cls3', 'cls4')
42+
customExpect(element).toHaveClass('cls1', {exact: true})
43+
customExpect(element).toHaveDisplayValue('str')
44+
customExpect(element).toHaveDisplayValue(['str1', 'str2'])
45+
customExpect(element).toHaveDisplayValue(/str/)
46+
customExpect(element).toHaveDisplayValue([/str1/, 'str2'])
47+
customExpect(element).toHaveFocus()
48+
customExpect(element).toHaveFormValues({foo: 'bar', baz: 1})
49+
customExpect(element).toHaveStyle('display: block')
50+
customExpect(element).toHaveStyle({display: 'block', width: 100})
51+
customExpect(element).toHaveTextContent('Text')
52+
customExpect(element).toHaveTextContent(/Text/)
53+
customExpect(element).toHaveTextContent('Text', {normalizeWhitespace: true})
54+
customExpect(element).toHaveTextContent(/Text/, {normalizeWhitespace: true})
55+
customExpect(element).toHaveValue()
56+
customExpect(element).toHaveValue('str')
57+
customExpect(element).toHaveValue(['str1', 'str2'])
58+
customExpect(element).toHaveValue(1)
59+
customExpect(element).toHaveValue(null)
60+
customExpect(element).toBeChecked()
61+
customExpect(element).toHaveDescription('some description')
62+
customExpect(element).toHaveDescription(/some description/)
63+
customExpect(element).toHaveDescription(expect.stringContaining('partial'))
64+
customExpect(element).toHaveDescription()
65+
customExpect(element).toHaveAccessibleDescription('some description')
66+
customExpect(element).toHaveAccessibleDescription(/some description/)
67+
customExpect(element).toHaveAccessibleDescription(
68+
expect.stringContaining('partial'),
69+
)
70+
customExpect(element).toHaveAccessibleDescription()
71+
72+
customExpect(element).toHaveAccessibleErrorMessage()
73+
customExpect(element).toHaveAccessibleErrorMessage(
74+
'Invalid time: the time must be between 9:00 AM and 5:00 PM',
75+
)
76+
customExpect(element).toHaveAccessibleErrorMessage(/invalid time/i)
77+
customExpect(element).toHaveAccessibleErrorMessage(
78+
expect.stringContaining('Invalid time'),
79+
)
80+
81+
customExpect(element).toHaveAccessibleName('a label')
82+
customExpect(element).toHaveAccessibleName(/a label/)
83+
customExpect(element).toHaveAccessibleName(
84+
expect.stringContaining('partial label'),
85+
)
86+
customExpect(element).toHaveAccessibleName()
87+
customExpect(element).toHaveErrorMessage(
88+
'Invalid time: the time must be between 9:00 AM and 5:00 PM',
89+
)
90+
customExpect(element).toHaveErrorMessage(/invalid time/i)
91+
customExpect(element).toHaveErrorMessage(
92+
expect.stringContaining('Invalid time'),
93+
)
94+
95+
// @ts-expect-error The types accidentally allowed any property by falling back to "any"
96+
customExpect(element).nonExistentProperty()
+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/**
2+
* File that tests whether the TypeScript typings for @types/jest work as expected.
3+
*/
4+
5+
/* eslint-disable @typescript-eslint/no-unsafe-call */
6+
/* eslint-disable @typescript-eslint/no-floating-promises */
7+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
8+
9+
import '../../jest'
10+
11+
const element: HTMLElement = document.body
12+
13+
expect(element).toBeInTheDOM()
14+
expect(element).toBeInTheDOM(document.body)
15+
expect(element).toBeInTheDocument()
16+
expect(element).toBeVisible()
17+
expect(element).toBeEmpty()
18+
expect(element).toBeDisabled()
19+
expect(element).toBeEnabled()
20+
expect(element).toBeInvalid()
21+
expect(element).toBeRequired()
22+
expect(element).toBeValid()
23+
expect(element).toContainElement(document.body)
24+
expect(element).toContainElement(null)
25+
expect(element).toContainHTML('body')
26+
expect(element).toHaveAttribute('attr')
27+
expect(element).toHaveAttribute('attr', true)
28+
expect(element).toHaveAttribute('attr', 'yes')
29+
expect(element).toHaveClass()
30+
expect(element).toHaveClass('cls1')
31+
expect(element).toHaveClass('cls1', 'cls2', 'cls3', 'cls4')
32+
expect(element).toHaveClass('cls1', {exact: true})
33+
expect(element).toHaveDisplayValue('str')
34+
expect(element).toHaveDisplayValue(['str1', 'str2'])
35+
expect(element).toHaveDisplayValue(/str/)
36+
expect(element).toHaveDisplayValue([/str1/, 'str2'])
37+
expect(element).toHaveFocus()
38+
expect(element).toHaveFormValues({foo: 'bar', baz: 1})
39+
expect(element).toHaveStyle('display: block')
40+
expect(element).toHaveStyle({display: 'block', width: 100})
41+
expect(element).toHaveTextContent('Text')
42+
expect(element).toHaveTextContent(/Text/)
43+
expect(element).toHaveTextContent('Text', {normalizeWhitespace: true})
44+
expect(element).toHaveTextContent(/Text/, {normalizeWhitespace: true})
45+
expect(element).toHaveValue()
46+
expect(element).toHaveValue('str')
47+
expect(element).toHaveValue(['str1', 'str2'])
48+
expect(element).toHaveValue(1)
49+
expect(element).toHaveValue(null)
50+
expect(element).toBeChecked()
51+
expect(element).toHaveDescription('some description')
52+
expect(element).toHaveDescription(/some description/)
53+
expect(element).toHaveDescription(expect.stringContaining('partial'))
54+
expect(element).toHaveDescription()
55+
expect(element).toHaveAccessibleDescription('some description')
56+
expect(element).toHaveAccessibleDescription(/some description/)
57+
expect(element).toHaveAccessibleDescription(expect.stringContaining('partial'))
58+
expect(element).toHaveAccessibleDescription()
59+
expect(element).toHaveAccessibleName('a label')
60+
expect(element).toHaveAccessibleName(/a label/)
61+
expect(element).toHaveAccessibleName(expect.stringContaining('partial label'))
62+
expect(element).toHaveAccessibleName()
63+
expect(element).toHaveErrorMessage(
64+
'Invalid time: the time must be between 9:00 AM and 5:00 PM',
65+
)
66+
expect(element).toHaveErrorMessage(/invalid time/i)
67+
expect(element).toHaveErrorMessage(expect.stringContaining('Invalid time'))
68+
69+
expect(element).not.toBeInTheDOM()
70+
expect(element).not.toBeInTheDOM(document.body)
71+
expect(element).not.toBeInTheDocument()
72+
expect(element).not.toBeVisible()
73+
expect(element).not.toBeEmpty()
74+
expect(element).not.toBeEmptyDOMElement()
75+
expect(element).not.toBeDisabled()
76+
expect(element).not.toBeEnabled()
77+
expect(element).not.toBeInvalid()
78+
expect(element).not.toBeRequired()
79+
expect(element).not.toBeValid()
80+
expect(element).not.toContainElement(document.body)
81+
expect(element).not.toContainElement(null)
82+
expect(element).not.toContainHTML('body')
83+
expect(element).not.toHaveAttribute('attr')
84+
expect(element).not.toHaveAttribute('attr', true)
85+
expect(element).not.toHaveAttribute('attr', 'yes')
86+
expect(element).not.toHaveClass()
87+
expect(element).not.toHaveClass('cls1')
88+
expect(element).not.toHaveClass('cls1', 'cls2', 'cls3', 'cls4')
89+
expect(element).not.toHaveClass('cls1', {exact: true})
90+
expect(element).not.toHaveDisplayValue('str')
91+
expect(element).not.toHaveDisplayValue(['str1', 'str2'])
92+
expect(element).not.toHaveDisplayValue(/str/)
93+
expect(element).not.toHaveDisplayValue([/str1/, 'str2'])
94+
expect(element).not.toHaveFocus()
95+
expect(element).not.toHaveFormValues({foo: 'bar', baz: 1})
96+
expect(element).not.toHaveStyle('display: block')
97+
expect(element).not.toHaveTextContent('Text')
98+
expect(element).not.toHaveTextContent(/Text/)
99+
expect(element).not.toHaveTextContent('Text', {normalizeWhitespace: true})
100+
expect(element).not.toHaveTextContent(/Text/, {normalizeWhitespace: true})
101+
expect(element).not.toHaveValue()
102+
expect(element).not.toHaveValue('str')
103+
expect(element).not.toHaveValue(['str1', 'str2'])
104+
expect(element).not.toHaveValue(1)
105+
expect(element).not.toBeChecked()
106+
expect(element).not.toHaveDescription('some description')
107+
expect(element).not.toHaveDescription()
108+
expect(element).not.toHaveAccessibleDescription('some description')
109+
expect(element).not.toHaveAccessibleDescription()
110+
expect(element).not.toHaveAccessibleName('a label')
111+
expect(element).not.toHaveAccessibleName()
112+
expect(element).not.toBePartiallyChecked()
113+
expect(element).not.toHaveErrorMessage()
114+
expect(element).not.toHaveErrorMessage('Pikachu!')
115+
116+
// @ts-expect-error The types accidentally allowed any property by falling back to "any"
117+
expect(element).nonExistentProperty()

‎types/__tests__/jest/tsconfig.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"compilerOptions": {
3+
"noEmit": true,
4+
"strict": true,
5+
"skipLibCheck": true,
6+
"types": ["jest"]
7+
},
8+
"include": ["*.ts"]
9+
}

‎types/__tests__/vitest/tsconfig.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"compilerOptions": {
3+
"noEmit": true,
4+
"strict": true,
5+
"skipLibCheck": true,
6+
"types": []
7+
},
8+
"include": ["*.ts"]
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* File that tests whether the TypeScript typings work as expected.
3+
*/
4+
5+
/* eslint-disable @typescript-eslint/no-unsafe-call */
6+
/* eslint-disable @typescript-eslint/no-floating-promises */
7+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
8+
9+
import {expect} from 'vitest'
10+
import * as matchers from '../../matchers'
11+
12+
expect.extend(matchers)
13+
14+
const element: HTMLElement = document.body
15+
16+
function customExpect(
17+
_actual: HTMLElement,
18+
):
19+
| matchers.TestingLibraryMatchers<unknown, void>
20+
| matchers.TestingLibraryMatchers<unknown, Promise<void>> {
21+
throw new Error('Method not implemented.')
22+
}
23+
24+
customExpect(element).toBeInTheDOM()
25+
customExpect(element).toBeInTheDOM(document.body)
26+
customExpect(element).toBeInTheDocument()
27+
customExpect(element).toBeVisible()
28+
customExpect(element).toBeEmpty()
29+
customExpect(element).toBeDisabled()
30+
customExpect(element).toBeEnabled()
31+
customExpect(element).toBeInvalid()
32+
customExpect(element).toBeRequired()
33+
customExpect(element).toBeValid()
34+
customExpect(element).toContainElement(document.body)
35+
customExpect(element).toContainElement(null)
36+
customExpect(element).toContainHTML('body')
37+
customExpect(element).toHaveAttribute('attr')
38+
customExpect(element).toHaveAttribute('attr', true)
39+
customExpect(element).toHaveAttribute('attr', 'yes')
40+
customExpect(element).toHaveClass()
41+
customExpect(element).toHaveClass('cls1')
42+
customExpect(element).toHaveClass('cls1', 'cls2', 'cls3', 'cls4')
43+
customExpect(element).toHaveClass('cls1', {exact: true})
44+
customExpect(element).toHaveDisplayValue('str')
45+
customExpect(element).toHaveDisplayValue(['str1', 'str2'])
46+
customExpect(element).toHaveDisplayValue(/str/)
47+
customExpect(element).toHaveDisplayValue([/str1/, 'str2'])
48+
customExpect(element).toHaveFocus()
49+
customExpect(element).toHaveFormValues({foo: 'bar', baz: 1})
50+
customExpect(element).toHaveStyle('display: block')
51+
customExpect(element).toHaveStyle({display: 'block', width: 100})
52+
customExpect(element).toHaveTextContent('Text')
53+
customExpect(element).toHaveTextContent(/Text/)
54+
customExpect(element).toHaveTextContent('Text', {normalizeWhitespace: true})
55+
customExpect(element).toHaveTextContent(/Text/, {normalizeWhitespace: true})
56+
customExpect(element).toHaveValue()
57+
customExpect(element).toHaveValue('str')
58+
customExpect(element).toHaveValue(['str1', 'str2'])
59+
customExpect(element).toHaveValue(1)
60+
customExpect(element).toHaveValue(null)
61+
customExpect(element).toBeChecked()
62+
customExpect(element).toHaveDescription('some description')
63+
customExpect(element).toHaveDescription(/some description/)
64+
customExpect(element).toHaveDescription(expect.stringContaining('partial'))
65+
customExpect(element).toHaveDescription()
66+
customExpect(element).toHaveAccessibleDescription('some description')
67+
customExpect(element).toHaveAccessibleDescription(/some description/)
68+
customExpect(element).toHaveAccessibleDescription(
69+
expect.stringContaining('partial'),
70+
)
71+
customExpect(element).toHaveAccessibleDescription()
72+
73+
customExpect(element).toHaveAccessibleErrorMessage()
74+
customExpect(element).toHaveAccessibleErrorMessage(
75+
'Invalid time: the time must be between 9:00 AM and 5:00 PM',
76+
)
77+
customExpect(element).toHaveAccessibleErrorMessage(/invalid time/i)
78+
customExpect(element).toHaveAccessibleErrorMessage(
79+
expect.stringContaining('Invalid time'),
80+
)
81+
82+
customExpect(element).toHaveAccessibleName('a label')
83+
customExpect(element).toHaveAccessibleName(/a label/)
84+
customExpect(element).toHaveAccessibleName(
85+
expect.stringContaining('partial label'),
86+
)
87+
customExpect(element).toHaveAccessibleName()
88+
customExpect(element).toHaveErrorMessage(
89+
'Invalid time: the time must be between 9:00 AM and 5:00 PM',
90+
)
91+
customExpect(element).toHaveErrorMessage(/invalid time/i)
92+
customExpect(element).toHaveErrorMessage(
93+
expect.stringContaining('Invalid time'),
94+
)
95+
96+
// @ts-expect-error The types accidentally allowed any property by falling back to "any"
97+
customExpect(element).nonExistentProperty()
+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/**
2+
* File that tests whether the TypeScript typings for @types/jest work as expected.
3+
*/
4+
5+
/* eslint-disable @typescript-eslint/no-unsafe-call */
6+
/* eslint-disable @typescript-eslint/no-floating-promises */
7+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
8+
9+
import {expect} from 'vitest'
10+
import '../../vitest'
11+
12+
const element: HTMLElement = document.body
13+
14+
expect(element).toBeInTheDOM()
15+
expect(element).toBeInTheDOM(document.body)
16+
expect(element).toBeInTheDocument()
17+
expect(element).toBeVisible()
18+
expect(element).toBeEmpty()
19+
expect(element).toBeDisabled()
20+
expect(element).toBeEnabled()
21+
expect(element).toBeInvalid()
22+
expect(element).toBeRequired()
23+
expect(element).toBeValid()
24+
expect(element).toContainElement(document.body)
25+
expect(element).toContainElement(null)
26+
expect(element).toContainHTML('body')
27+
expect(element).toHaveAttribute('attr')
28+
expect(element).toHaveAttribute('attr', true)
29+
expect(element).toHaveAttribute('attr', 'yes')
30+
expect(element).toHaveClass()
31+
expect(element).toHaveClass('cls1')
32+
expect(element).toHaveClass('cls1', 'cls2', 'cls3', 'cls4')
33+
expect(element).toHaveClass('cls1', {exact: true})
34+
expect(element).toHaveDisplayValue('str')
35+
expect(element).toHaveDisplayValue(['str1', 'str2'])
36+
expect(element).toHaveDisplayValue(/str/)
37+
expect(element).toHaveDisplayValue([/str1/, 'str2'])
38+
expect(element).toHaveFocus()
39+
expect(element).toHaveFormValues({foo: 'bar', baz: 1})
40+
expect(element).toHaveStyle('display: block')
41+
expect(element).toHaveStyle({display: 'block', width: 100})
42+
expect(element).toHaveTextContent('Text')
43+
expect(element).toHaveTextContent(/Text/)
44+
expect(element).toHaveTextContent('Text', {normalizeWhitespace: true})
45+
expect(element).toHaveTextContent(/Text/, {normalizeWhitespace: true})
46+
expect(element).toHaveValue()
47+
expect(element).toHaveValue('str')
48+
expect(element).toHaveValue(['str1', 'str2'])
49+
expect(element).toHaveValue(1)
50+
expect(element).toHaveValue(null)
51+
expect(element).toBeChecked()
52+
expect(element).toHaveDescription('some description')
53+
expect(element).toHaveDescription(/some description/)
54+
expect(element).toHaveDescription(expect.stringContaining('partial'))
55+
expect(element).toHaveDescription()
56+
expect(element).toHaveAccessibleDescription('some description')
57+
expect(element).toHaveAccessibleDescription(/some description/)
58+
expect(element).toHaveAccessibleDescription(expect.stringContaining('partial'))
59+
expect(element).toHaveAccessibleDescription()
60+
expect(element).toHaveAccessibleName('a label')
61+
expect(element).toHaveAccessibleName(/a label/)
62+
expect(element).toHaveAccessibleName(expect.stringContaining('partial label'))
63+
expect(element).toHaveAccessibleName()
64+
expect(element).toHaveErrorMessage(
65+
'Invalid time: the time must be between 9:00 AM and 5:00 PM',
66+
)
67+
expect(element).toHaveErrorMessage(/invalid time/i)
68+
expect(element).toHaveErrorMessage(expect.stringContaining('Invalid time'))
69+
70+
expect(element).not.toBeInTheDOM()
71+
expect(element).not.toBeInTheDOM(document.body)
72+
expect(element).not.toBeInTheDocument()
73+
expect(element).not.toBeVisible()
74+
expect(element).not.toBeEmpty()
75+
expect(element).not.toBeEmptyDOMElement()
76+
expect(element).not.toBeDisabled()
77+
expect(element).not.toBeEnabled()
78+
expect(element).not.toBeInvalid()
79+
expect(element).not.toBeRequired()
80+
expect(element).not.toBeValid()
81+
expect(element).not.toContainElement(document.body)
82+
expect(element).not.toContainElement(null)
83+
expect(element).not.toContainHTML('body')
84+
expect(element).not.toHaveAttribute('attr')
85+
expect(element).not.toHaveAttribute('attr', true)
86+
expect(element).not.toHaveAttribute('attr', 'yes')
87+
expect(element).not.toHaveClass()
88+
expect(element).not.toHaveClass('cls1')
89+
expect(element).not.toHaveClass('cls1', 'cls2', 'cls3', 'cls4')
90+
expect(element).not.toHaveClass('cls1', {exact: true})
91+
expect(element).not.toHaveDisplayValue('str')
92+
expect(element).not.toHaveDisplayValue(['str1', 'str2'])
93+
expect(element).not.toHaveDisplayValue(/str/)
94+
expect(element).not.toHaveDisplayValue([/str1/, 'str2'])
95+
expect(element).not.toHaveFocus()
96+
expect(element).not.toHaveFormValues({foo: 'bar', baz: 1})
97+
expect(element).not.toHaveStyle('display: block')
98+
expect(element).not.toHaveTextContent('Text')
99+
expect(element).not.toHaveTextContent(/Text/)
100+
expect(element).not.toHaveTextContent('Text', {normalizeWhitespace: true})
101+
expect(element).not.toHaveTextContent(/Text/, {normalizeWhitespace: true})
102+
expect(element).not.toHaveValue()
103+
expect(element).not.toHaveValue('str')
104+
expect(element).not.toHaveValue(['str1', 'str2'])
105+
expect(element).not.toHaveValue(1)
106+
expect(element).not.toBeChecked()
107+
expect(element).not.toHaveDescription('some description')
108+
expect(element).not.toHaveDescription()
109+
expect(element).not.toHaveAccessibleDescription('some description')
110+
expect(element).not.toHaveAccessibleDescription()
111+
expect(element).not.toHaveAccessibleName('a label')
112+
expect(element).not.toHaveAccessibleName()
113+
expect(element).not.toBePartiallyChecked()
114+
expect(element).not.toHaveErrorMessage()
115+
expect(element).not.toHaveErrorMessage('Pikachu!')
116+
117+
// @ts-expect-error The types accidentally allowed any property by falling back to "any"
118+
expect(element).nonExistentProperty()

‎types/jest-globals.d.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@ import {type TestingLibraryMatchers} from './matchers'
44
export {}
55
declare module '@jest/expect' {
66
export interface Matchers<R extends void | Promise<void>>
7-
extends TestingLibraryMatchers<typeof expect.stringContaining, R> {}
7+
extends TestingLibraryMatchers<
8+
ReturnType<typeof expect.stringContaining>,
9+
R
10+
> {}
811
}

‎types/jest.d.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import {type TestingLibraryMatchers} from './matchers'
55
declare global {
66
namespace jest {
77
interface Matchers<R = void, T = {}>
8-
extends TestingLibraryMatchers<typeof expect.stringContaining, R> {}
8+
extends TestingLibraryMatchers<
9+
ReturnType<typeof expect.stringContaining>,
10+
R
11+
> {}
912
}
1013
}

‎types/matchers.d.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
declare namespace matchers {
2-
interface TestingLibraryMatchers<E, R> extends Record<string, any> {
2+
interface TestingLibraryMatchers<E, R> {
33
/**
44
* @deprecated
55
* since v1.9.0
@@ -662,5 +662,8 @@ declare namespace matchers {
662662
}
663663
}
664664

665-
declare const matchers: matchers.TestingLibraryMatchers<any, void>
665+
// Needs to extend Record<string, any> to be accepted by expect.extend()
666+
// as it requires a string index signature.
667+
declare const matchers: matchers.TestingLibraryMatchers<any, void> &
668+
Record<string, any>
666669
export = matchers

‎types/vitest.d.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@ import {type TestingLibraryMatchers} from './matchers'
44
export {}
55
declare module '@vitest/expect' {
66
interface JestAssertion<T = any>
7-
extends TestingLibraryMatchers<typeof expect.stringContaining, T> {}
7+
extends TestingLibraryMatchers<
8+
ReturnType<typeof expect.stringContaining>,
9+
T
10+
> {}
811
}

0 commit comments

Comments
 (0)
Please sign in to comment.