Skip to content

Commit b383620

Browse files
committed
Merge branch 'master' into chores/enhance-get-text-error
2 parents aca8814 + 90d420d commit b383620

File tree

12 files changed

+121
-38
lines changed

12 files changed

+121
-38
lines changed

.all-contributorsrc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,33 @@
14971497
"contributions": [
14981498
"bug"
14991499
]
1500+
},
1501+
{
1502+
"login": "robcaldecott",
1503+
"name": "Rob Caldecott",
1504+
"avatar_url": "https://avatars.githubusercontent.com/u/796702?v=4",
1505+
"profile": "https://github.com/robcaldecott",
1506+
"contributions": [
1507+
"bug"
1508+
]
1509+
},
1510+
{
1511+
"login": "Dennis273",
1512+
"name": "Dennis273",
1513+
"avatar_url": "https://avatars.githubusercontent.com/u/19815164?v=4",
1514+
"profile": "https://github.com/Dennis273",
1515+
"contributions": [
1516+
"code"
1517+
]
1518+
},
1519+
{
1520+
"login": "jacksonhardaker",
1521+
"name": "Jackson Hardaker",
1522+
"avatar_url": "https://avatars.githubusercontent.com/u/7596320?v=4",
1523+
"profile": "https://www.jacksonhardaker.dev",
1524+
"contributions": [
1525+
"test"
1526+
]
15001527
}
15011528
],
15021529
"repoHost": "https://github.com"

.codesandbox/ci.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"installCommand": "install:csb",
23
"sandboxes": ["github/kentcdodds/react-testing-library-examples"],
34
"node": "12"
45
}

.github/workflows/validate.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,20 @@ jobs:
1818
# Otherwise we would not know if the problem is tied to the Node.js version
1919
fail-fast: false
2020
matrix:
21-
# TODO: relax `'16.9.1'` to `16` once GitHub has 16.9.1 cached. 16.9.0 is broken due to https://github.com/nodejs/node/issues/40030
22-
node: [12, 14, '16.9.1']
21+
node: [12, 14, 16]
2322
runs-on: ubuntu-latest
2423
steps:
2524
- name: 🛑 Cancel Previous Runs
2625
uses: styfle/[email protected]
2726

2827
- name: ⬇️ Checkout repo
29-
uses: actions/checkout@v2
28+
uses: actions/checkout@v3
3029
with:
3130
# required by codecov/codecov-action
3231
fetch-depth: 0
3332

3433
- name: ⎔ Setup node
35-
uses: actions/setup-node@v2
34+
uses: actions/setup-node@v3
3635
with:
3736
node-version: ${{ matrix.node }}
3837

@@ -66,10 +65,10 @@ jobs:
6665
uses: styfle/[email protected]
6766

6867
- name: ⬇️ Checkout repo
69-
uses: actions/checkout@v2
68+
uses: actions/checkout@v3
7069

7170
- name: ⎔ Setup node
72-
uses: actions/setup-node@v2
71+
uses: actions/setup-node@v3
7372
with:
7473
node-version: 14
7574

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,11 @@ Thanks goes to these people ([emoji key][emojis]):
327327
<td align="center"><a href="https://github.com/IanVS"><img src="https://avatars.githubusercontent.com/u/4616705?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ian VanSchooten</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=IanVS" title="Code">💻</a></td>
328328
<td align="center"><a href="http://supervanya.com"><img src="https://avatars.githubusercontent.com/u/12336038?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vanya Prokopovich</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Asupervanya" title="Bug reports">🐛</a></td>
329329
<td align="center"><a href="https://github.com/jrnail23"><img src="https://avatars.githubusercontent.com/u/392612?v=4?s=100" width="100px;" alt=""/><br /><sub><b>James Nail</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Ajrnail23" title="Bug reports">🐛</a></td>
330+
<td align="center"><a href="https://github.com/robcaldecott"><img src="https://avatars.githubusercontent.com/u/796702?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rob Caldecott</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Arobcaldecott" title="Bug reports">🐛</a></td>
331+
</tr>
332+
<tr>
333+
<td align="center"><a href="https://github.com/Dennis273"><img src="https://avatars.githubusercontent.com/u/19815164?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dennis273</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=Dennis273" title="Code">💻</a></td>
334+
<td align="center"><a href="https://www.jacksonhardaker.dev"><img src="https://avatars.githubusercontent.com/u/7596320?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jackson Hardaker</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=jacksonhardaker" title="Tests">⚠️</a></td>
330335
</tr>
331336
</table>
332337

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"scripts": {
2727
"build": "kcd-scripts build --no-ts-defs --ignore \"**/__tests__/**,**/__node_tests__/**,**/__mocks__/**\" && kcd-scripts build --no-ts-defs --bundle --no-clean",
2828
"format": "kcd-scripts format",
29+
"install:csb": "npm install",
2930
"lint": "kcd-scripts lint",
3031
"setup": "npm install && npm run validate -s",
3132
"test": "kcd-scripts test",

src/__tests__/events.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,17 +172,17 @@ eventTypes.forEach(({type, events, elementType}) => {
172172
expect(spy).toHaveBeenCalledTimes(1)
173173
})
174174
})
175-
176-
it('fires resize', () => {
177-
const node = document.defaultView
178-
const spy = jest.fn()
179-
node.addEventListener('resize', spy, {once: true})
180-
fireEvent.resize(node)
181-
expect(spy).toHaveBeenCalledTimes(1)
182-
})
183175
})
184176
})
185177

178+
it('fires resize', () => {
179+
const node = document.defaultView
180+
const spy = jest.fn()
181+
node.addEventListener('resize', spy, {once: true})
182+
fireEvent.resize(node)
183+
expect(spy).toHaveBeenCalledTimes(1)
184+
})
185+
186186
describe(`Bubbling Events`, () => {
187187
bubblingEvents.forEach(event =>
188188
it(`bubbles ${event}`, () => {

src/__tests__/helpers.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,22 @@ describe('window retrieval throws when given something other than a node', () =>
2525
`It looks like you passed an Array instead of a DOM node. Did you do something like \`fireEvent.click(screen.getAllBy...\` when you meant to use a \`getBy\` query \`fireEvent.click(screen.getBy...\`?`,
2626
)
2727
})
28+
test('window is not available for node', () => {
29+
const elem = document.createElement('div')
30+
Object.defineProperty(elem.ownerDocument, 'defaultView', {
31+
get: function get() {
32+
return null
33+
},
34+
})
35+
36+
expect(() => getWindowFromNode(elem)).toThrowErrorMatchingInlineSnapshot(
37+
`It looks like the window object is not available for the provided node.`,
38+
)
39+
})
40+
2841
test('unknown as node', () => {
2942
expect(() => getWindowFromNode({})).toThrowErrorMatchingInlineSnapshot(
30-
`Unable to find the "window" object for the given node. Please file an issue with the code that's causing you to see this error: https://github.com/testing-library/dom-testing-library/issues/new`,
43+
`The given node is not an Element, the node type is: object.`,
3144
)
3245
})
3346
})

src/__tests__/matches.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,22 @@ test('matchers accept regex', () => {
1515
expect(fuzzyMatches('ABC', node, /ABC/, normalizer)).toBe(true)
1616
})
1717

18+
// https://stackoverflow.com/questions/1520800/why-does-a-regexp-with-global-flag-give-wrong-results
19+
test('a regex with the global flag consistently (re-)finds a match', () => {
20+
const regex = /ABC/g
21+
const spy = jest.spyOn(console, 'warn').mockImplementation()
22+
23+
expect(matches('ABC', node, regex, normalizer)).toBe(true)
24+
expect(fuzzyMatches('ABC', node, regex, normalizer)).toBe(true)
25+
26+
expect(spy).toBeCalledTimes(2)
27+
expect(spy).toHaveBeenCalledWith(
28+
`To match all elements we had to reset the lastIndex of the RegExp because the global flag is enabled. We encourage to remove the global flag from the RegExp.`,
29+
)
30+
31+
console.warn.mockClear()
32+
})
33+
1834
test('matchers accept functions', () => {
1935
expect(matches('ABC', node, text => text === 'ABC', normalizer)).toBe(true)
2036
expect(fuzzyMatches('ABC', node, text => text === 'ABC', normalizer)).toBe(

src/helpers.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ function getWindowFromNode(node) {
3333
} else if (node.window) {
3434
// node is window
3535
return node.window
36+
} else if (node.ownerDocument && node.ownerDocument.defaultView === null) {
37+
throw new Error(
38+
`It looks like the window object is not available for the provided node.`,
39+
)
3640
} else if (node.then instanceof Function) {
3741
throw new Error(
3842
`It looks like you passed a Promise object instead of a DOM node. Did you do something like \`fireEvent.click(screen.findBy...\` when you meant to use a \`getBy\` query \`fireEvent.click(screen.getBy...\`, or await the findBy query \`fireEvent.click(await screen.findBy...\`?`,
@@ -51,7 +55,7 @@ function getWindowFromNode(node) {
5155
} else {
5256
// The user passed something unusual to a calling function
5357
throw new Error(
54-
`Unable to find the "window" object for the given node. Please file an issue with the code that's causing you to see this error: https://github.com/testing-library/dom-testing-library/issues/new`,
58+
`The given node is not an Element, the node type is: ${typeof node}.`,
5559
)
5660
}
5761
}

src/matches.ts

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function fuzzyMatches(
3636
} else if (typeof matcher === 'function') {
3737
return matcher(normalizedText, node)
3838
} else {
39-
return matcher.test(normalizedText)
39+
return matchRegExp(matcher, normalizedText)
4040
}
4141
}
4242

@@ -56,7 +56,7 @@ function matches(
5656
if (matcher instanceof Function) {
5757
return matcher(normalizedText, node)
5858
} else if (matcher instanceof RegExp) {
59-
return matcher.test(normalizedText)
59+
return matchRegExp(matcher, normalizedText)
6060
} else {
6161
return normalizedText === String(matcher)
6262
}
@@ -91,25 +91,35 @@ function makeNormalizer({
9191
collapseWhitespace,
9292
normalizer,
9393
}: NormalizerOptions) {
94-
if (normalizer) {
95-
// User has specified a custom normalizer
96-
if (
97-
typeof trim !== 'undefined' ||
98-
typeof collapseWhitespace !== 'undefined'
99-
) {
100-
// They've also specified a value for trim or collapseWhitespace
101-
throw new Error(
102-
'trim and collapseWhitespace are not supported with a normalizer. ' +
103-
'If you want to use the default trim and collapseWhitespace logic in your normalizer, ' +
104-
'use "getDefaultNormalizer({trim, collapseWhitespace})" and compose that into your normalizer',
105-
)
106-
}
107-
108-
return normalizer
109-
} else {
94+
if (!normalizer) {
11095
// No custom normalizer specified. Just use default.
11196
return getDefaultNormalizer({trim, collapseWhitespace})
11297
}
98+
99+
if (
100+
typeof trim !== 'undefined' ||
101+
typeof collapseWhitespace !== 'undefined'
102+
) {
103+
// They've also specified a value for trim or collapseWhitespace
104+
throw new Error(
105+
'trim and collapseWhitespace are not supported with a normalizer. ' +
106+
'If you want to use the default trim and collapseWhitespace logic in your normalizer, ' +
107+
'use "getDefaultNormalizer({trim, collapseWhitespace})" and compose that into your normalizer',
108+
)
109+
}
110+
111+
return normalizer
112+
}
113+
114+
function matchRegExp(matcher: RegExp, text: string) {
115+
const match = matcher.test(text)
116+
if (matcher.global && matcher.lastIndex !== 0) {
117+
console.warn(
118+
`To match all elements we had to reset the lastIndex of the RegExp because the global flag is enabled. We encourage to remove the global flag from the RegExp.`,
119+
)
120+
matcher.lastIndex = 0
121+
}
122+
return match
113123
}
114124

115125
export {fuzzyMatches, matches, getDefaultNormalizer, makeNormalizer}

types/__tests__/type-tests.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,12 @@ export async function testWithin() {
254254

255255
await container.findByRole('button', {name: /click me/i})
256256
container.getByRole<HTMLButtonElement>('button', {name: /click me/i})
257+
258+
let withinQueries = within(document.body)
259+
withinQueries = within(document.body)
260+
withinQueries.getByRole<HTMLButtonElement>('button', {name: /click me/i})
261+
withinQueries = within(document.body)
262+
withinQueries.getByRole<HTMLButtonElement>('button', {name: /click me/i})
257263
}
258264

259265
/*

types/get-queries-for-element.d.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ export interface Queries {
175175
[T: string]: Query
176176
}
177177

178-
export function getQueriesForElement<T extends Queries = typeof queries>(
179-
element: HTMLElement,
180-
queriesToBind?: T,
181-
): BoundFunctions<T>
178+
export function getQueriesForElement<
179+
QueriesToBind extends Queries = typeof queries,
180+
// Extra type parameter required for reassignment.
181+
T extends QueriesToBind = QueriesToBind,
182+
>(element: HTMLElement, queriesToBind?: T): BoundFunctions<T>

0 commit comments

Comments
 (0)