From d41366594f55b49cb5ced38d42195af2ac5eddaa Mon Sep 17 00:00:00 2001 From: mohamedmagdy17593 <40938625+mohamedmagdy17593@users.noreply.github.com> Date: Sun, 17 Feb 2019 16:46:18 +0200 Subject: [PATCH 001/327] refactor: remove duplication of act (#304) --- .all-contributorsrc | 9 +++++++++ README.md | 5 +++-- src/index.js | 12 +++++------- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 2a0be067..48b07d8e 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -680,6 +680,15 @@ "ideas", "test" ] + }, + { + "login": "mohamedmagdy17593", + "name": "mohamedmagdy17593", + "avatar_url": "https://avatars0.githubusercontent.com/u/40938625?v=4", + "profile": "https://github.com/mohamedmagdy17593", + "contributions": [ + "code" + ] } ] } diff --git a/README.md b/README.md index 7ae254f6..fe43640c 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-69-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-70-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -216,7 +216,8 @@ Thanks goes to these people ([emoji key][emojis]): | [dadamssg
dadamssg](https://github.com/dadamssg)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=dadamssg "Documentation") | [Yazan Aabed
Yazan Aabed](https://www.yaabed.com/)
[πŸ“](#blog-YazanAabeed "Blogposts") | [Tim
Tim](https://github.com/timbonicus)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Atimbonicus "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=timbonicus "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=timbonicus "Documentation") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=timbonicus "Tests") | [Divyanshu Maithani
Divyanshu Maithani](http://divyanshu.xyz)
[βœ…](#tutorial-divyanshu013 "Tutorials") [πŸ“Ή](#video-divyanshu013 "Videos") | [Deepak Grover
Deepak Grover](https://www.linkedin.com/in/metagrover)
[βœ…](#tutorial-metagrover "Tutorials") [πŸ“Ή](#video-metagrover "Videos") | [Eyal Cohen
Eyal Cohen](https://github.com/eyalcohen4)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=eyalcohen4 "Documentation") | [Peter Makowski
Peter Makowski](https://github.com/petermakowski)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=petermakowski "Documentation") | | [Michiel Nuyts
Michiel Nuyts](https://github.com/Michielnuyts)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=Michielnuyts "Documentation") | [Joe Ng'ethe
Joe Ng'ethe](https://github.com/joeynimu)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=joeynimu "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=joeynimu "Documentation") | [Kate
Kate](https://github.com/Enikol)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=Enikol "Documentation") | [Sean
Sean](http://www.seanrparker.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=SeanRParker "Documentation") | [James Long
James Long](http://jlongster.com)
[πŸ€”](#ideas-jlongster "Ideas, Planning, & Feedback") [πŸ“¦](#platform-jlongster "Packaging/porting to new platform") | [Herb Hagely
Herb Hagely](https://github.com/hhagely)
[πŸ’‘](#example-hhagely "Examples") | [Alex Wendte
Alex Wendte](http://www.wendtedesigns.com/)
[πŸ’‘](#example-themostcolm "Examples") | | [Monica Powell
Monica Powell](http://www.aboutmonica.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=M0nica "Documentation") | [Vitaly Sivkov
Vitaly Sivkov](http://sivkoff.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=sivkoff "Code") | [Weyert de Boer
Weyert de Boer](https://github.com/weyert)
[πŸ€”](#ideas-weyert "Ideas, Planning, & Feedback") [πŸ‘€](#review-weyert "Reviewed Pull Requests") | [EstebanMarin
EstebanMarin](https://github.com/EstebanMarin)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=EstebanMarin "Documentation") | [Victor Martins
Victor Martins](https://github.com/vctormb)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=vctormb "Documentation") | [Royston Shufflebotham
Royston Shufflebotham](https://github.com/RoystonS)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3ARoystonS "Bug reports") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=RoystonS "Documentation") [πŸ’‘](#example-RoystonS "Examples") | [chrbala
chrbala](https://github.com/chrbala)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=chrbala "Code") | -| [Donavon West
Donavon West](http://donavon.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Documentation") [πŸ€”](#ideas-donavon "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Tests") | [Richard Maisano
Richard Maisano](https://github.com/maisano)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=maisano "Code") | [Marco Biedermann
Marco Biedermann](https://www.marcobiedermann.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Code") [🚧](#maintenance-marcobiedermann "Maintenance") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Tests") | [Alex Zherdev
Alex Zherdev](https://github.com/alexzherdev)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Aalexzherdev "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=alexzherdev "Code") | [AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos](https://twitter.com/Andrewmat)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Code") [πŸ’‘](#example-Andrewmat "Examples") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Tests") | [Daniel K.
Daniel K.](https://github.com/FredyC)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3AFredyC "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=FredyC "Code") [πŸ€”](#ideas-FredyC "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=FredyC "Tests") | +| [Donavon West
Donavon West](http://donavon.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Documentation") [πŸ€”](#ideas-donavon "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Tests") | [Richard Maisano
Richard Maisano](https://github.com/maisano)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=maisano "Code") | [Marco Biedermann
Marco Biedermann](https://www.marcobiedermann.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Code") [🚧](#maintenance-marcobiedermann "Maintenance") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Tests") | [Alex Zherdev
Alex Zherdev](https://github.com/alexzherdev)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Aalexzherdev "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=alexzherdev "Code") | [AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos](https://twitter.com/Andrewmat)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Code") [πŸ’‘](#example-Andrewmat "Examples") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Tests") | [Daniel K.
Daniel K.](https://github.com/FredyC)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3AFredyC "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=FredyC "Code") [πŸ€”](#ideas-FredyC "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=FredyC "Tests") | [mohamedmagdy17593
mohamedmagdy17593](https://github.com/mohamedmagdy17593)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=mohamedmagdy17593 "Code") | + This project follows the [all-contributors][all-contributors] specification. diff --git a/src/index.js b/src/index.js index 31f99339..89a31e2c 100644 --- a/src/index.js +++ b/src/index.js @@ -25,15 +25,13 @@ function render( // they're passing us a custom container or not. mountedContainers.add(container) - if (hydrate) { - act(() => { + act(() => { + if (hydrate) { ReactDOM.hydrate(ui, container) - }) - } else { - act(() => { + } else { ReactDOM.render(ui, container) - }) - } + } + }) return { container, baseElement, From e49a23fe9739becd6fb5f24f9c58cbcab004345a Mon Sep 17 00:00:00 2001 From: Alex Krolick Date: Mon, 18 Feb 2019 17:10:47 -0800 Subject: [PATCH 002/327] feat(render): add wrapper component option (#303) * feat(render): add wrapper component option * feat(render): update types * fix(types): remove unreferenced type * fix(render): optional type for wrapper option --- package.json | 3 ++- src/__tests__/render.js | 21 +++++++++++++++++++ src/index.js | 46 ++++++++++++++++++++++++----------------- typings/index.d.ts | 7 +++---- 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 67bde194..54f531f1 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,8 @@ }, "devDependencies": { "@reach/router": "^1.2.1", - "@types/react-dom": "^16.0.9", + "@types/react": "^16.8.3", + "@types/react-dom": "^16.8.2", "axios": "^0.18.0", "eslint-import-resolver-jest": "^2.1.1", "history": "^4.7.2", diff --git a/src/__tests__/render.js b/src/__tests__/render.js index 5ee0dc6f..0ffe1322 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -90,3 +90,24 @@ it('supports fragments', () => { cleanup() expect(document.body.innerHTML).toBe('') }) + +test('renders options.wrapper around node', () => { + const WrapperComponent = ({children}) => ( +
{children}
+ ) + + const {container, getByTestId} = render(
, { + wrapper: WrapperComponent, + }) + + expect(getByTestId('wrapper')).toBeInTheDocument() + expect(container.firstChild).toMatchInlineSnapshot(` +
+
+
+`) +}) diff --git a/src/index.js b/src/index.js index 89a31e2c..70bf83c2 100644 --- a/src/index.js +++ b/src/index.js @@ -11,7 +11,13 @@ const mountedContainers = new Set() function render( ui, - {container, baseElement = container, queries, hydrate = false} = {}, + { + container, + baseElement = container, + queries, + hydrate = false, + wrapper: WrapperComponent, + } = {}, ) { if (!container) { // default to document.body instead of documentElement to avoid output of potentially-large @@ -25,13 +31,20 @@ function render( // they're passing us a custom container or not. mountedContainers.add(container) + + const wrapUiIfNeeded = innerElement => + WrapperComponent + ? React.createElement(WrapperComponent, null, innerElement) + : innerElement + act(() => { if (hydrate) { - ReactDOM.hydrate(ui, container) + ReactDOM.hydrate(wrapUiIfNeeded(ui), container) } else { - ReactDOM.render(ui, container) + ReactDOM.render(wrapUiIfNeeded(ui), container) } }) + return { container, baseElement, @@ -39,7 +52,7 @@ function render( debug: (el = baseElement) => console.log(prettyDOM(el)), unmount: () => ReactDOM.unmountComponentAtNode(container), rerender: rerenderUi => { - render(rerenderUi, {container, baseElement}) + render(wrapUiIfNeeded(rerenderUi), {container, baseElement}) // Intentionally do not return anything to avoid unnecessarily complicating the API. // folks can use all the same utilities we return in the first place that are bound to the container }, @@ -68,25 +81,20 @@ function testHook(callback, options = {}) { const result = { current: null, } - const toRender = () => { - const hookRender = ( - - {res => { - result.current = res - }} - - ) - if (options.wrapper) { - return React.createElement(options.wrapper, null, hookRender) - } - return hookRender - } - const {unmount, rerender: rerenderComponent} = render(toRender()) + const toRender = () => ( + + {res => { + result.current = res + }} + + ) + + const {unmount, rerender: rerenderComponent} = render(toRender(), options) return { result, unmount, rerender: () => { - rerenderComponent(toRender()) + rerenderComponent(toRender(), options) }, } } diff --git a/typings/index.d.ts b/typings/index.d.ts index 16594936..af09f778 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -25,17 +25,16 @@ export type HookResult = { unmount: () => boolean } -export type HookOptions = { - wrapper: React.FunctionComponent -} - export interface RenderOptions { container?: HTMLElement baseElement?: HTMLElement hydrate?: boolean queries?: Q + wrapper?: React.ComponentType } +export type HookOptions = RenderOptions + type Omit = Pick> /** From 912841077297b0e929111fe974cf2c2fac9c0753 Mon Sep 17 00:00:00 2001 From: Christopher Tran Date: Thu, 21 Feb 2019 16:41:02 -0800 Subject: [PATCH 003/327] docs: fixed plural typo (#305) --- examples/__tests__/react-context.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/__tests__/react-context.js b/examples/__tests__/react-context.js index 4c709429..b87c61c9 100644 --- a/examples/__tests__/react-context.js +++ b/examples/__tests__/react-context.js @@ -45,7 +45,7 @@ test('NameProvider composes full name from first, last', () => { }) /** - * A tree containing both a providers and consumer can be rendered normally + * A tree containing both a provider and consumer can be rendered normally */ test('NameProvider/Consumer shows name of character', () => { const tree = ( From 12d934abd14990d0164c83f1574b13f6d386ce3f Mon Sep 17 00:00:00 2001 From: Matheus Schettino Date: Sun, 24 Feb 2019 00:25:27 -0600 Subject: [PATCH 004/327] fix: move testHook to its own pacakge (#307) This removes testHook in favor of http://npm.im/react-hook-testing-library Closes #302 BREAKING CHANGE: move testHook to another library. Use http://npm.im/react-hook-testing-library instead --- README.md | 9 ++- examples/__tests__/react-hooks.js | 119 ------------------------------ src/__tests__/test-hook.js | 77 ------------------- src/index.js | 30 +------- typings/index.d.ts | 16 ---- 5 files changed, 8 insertions(+), 243 deletions(-) delete mode 100644 examples/__tests__/react-hooks.js delete mode 100644 src/__tests__/test-hook.js diff --git a/README.md b/README.md index fe43640c..16aba65d 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ practices.

- [Example](#example) - [Installation](#installation) - [Examples](#examples) +- [Hooks](#hooks) - [Other Solutions](#other-solutions) - [Guiding Principles](#guiding-principles) - [Contributors](#contributors) @@ -162,12 +163,15 @@ Some included are: - [`react-redux`](https://github.com/kentcdodds/react-testing-library/blob/master/examples/__tests__/react-redux.js) - [`react-router`](https://github.com/kentcdodds/react-testing-library/blob/master/examples/__tests__/react-router.js) - [`react-context`](https://github.com/kentcdodds/react-testing-library/blob/master/examples/__tests__/react-context.js) -- [`react-hooks`](https://github.com/kentcdodds/react-testing-library/blob/master/examples/__tests__/react-hooks.js) - - Use react-testing-library to test a custom React Hook. You can also find react-testing-library examples at [react-testing-examples.com](https://react-testing-examples.com/jest-rtl/). +## Hooks + +If you are interested in testing a custom hook, check out +[react-hooks-testing-library][react-hooks-testing-library] + ## Other Solutions In preparing this project, @@ -296,5 +300,6 @@ Links: [good-first-issue]: https://github.com/kentcdodds/react-testing-library/issues?utf8=βœ“&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3A"good+first+issue"+ [reactiflux]: https://www.reactiflux.com/ [stackoverflow]: https://stackoverflow.com/questions/tagged/react-testing-library +[react-hooks-testing-library]: https://github.com/mpeyper/react-hooks-testing-library diff --git a/examples/__tests__/react-hooks.js b/examples/__tests__/react-hooks.js deleted file mode 100644 index fe616eb7..00000000 --- a/examples/__tests__/react-hooks.js +++ /dev/null @@ -1,119 +0,0 @@ -/* - * This is the recommended way to test reusable custom react hooks. - * It is not however recommended to use the testHook utility to test - * single-use custom hooks. Typically those are better tested by testing - * the component that is using it. - */ -import {testHook, act, cleanup} from 'react-testing-library' - -import {useCounter, useDocumentTitle, useCall} from '../react-hooks' - -afterEach(cleanup) - -describe('useCounter', () => { - test('accepts default initial values', () => { - let count - testHook(() => ({count} = useCounter())) - - expect(count).toBe(0) - }) - - test('accepts a default initial value for `count`', () => { - let count - testHook(() => ({count} = useCounter({}))) - - expect(count).toBe(0) - }) - - test('provides an `increment` function', () => { - let count, increment - testHook(() => ({count, increment} = useCounter({step: 2}))) - - expect(count).toBe(0) - act(() => { - increment() - }) - expect(count).toBe(2) - }) - - test('provides an `decrement` function', () => { - let count, decrement - testHook(() => ({count, decrement} = useCounter({step: 2}))) - - expect(count).toBe(0) - act(() => { - decrement() - }) - expect(count).toBe(-2) - }) - - test('accepts a default initial value for `step`', () => { - let count, increment - testHook(() => ({count, increment} = useCounter({}))) - - expect(count).toBe(0) - act(() => { - increment() - }) - expect(count).toBe(1) - }) -}) - -// using unmount function to check useEffect behavior when unmounting -describe('useDocumentTitle', () => { - test('sets a title', () => { - document.title = 'original title' - testHook(() => { - useDocumentTitle('modified title') - }) - - expect(document.title).toBe('modified title') - }) - - test('returns to original title when component is unmounted', () => { - document.title = 'original title' - const {unmount} = testHook(() => { - useDocumentTitle('modified title') - }) - - unmount() - expect(document.title).toBe('original title') - }) -}) - -// using rerender function to test calling useEffect multiple times -describe('useCall', () => { - test('calls once on render', () => { - const spy = jest.fn() - testHook(() => { - useCall(spy, []) - }) - expect(spy).toHaveBeenCalledTimes(1) - }) - - test('calls again if deps change', () => { - let deps = [false] - const spy = jest.fn() - const {rerender} = testHook(() => { - useCall(spy, deps) - }) - expect(spy).toHaveBeenCalledTimes(1) - - deps = [true] - rerender() - expect(spy).toHaveBeenCalledTimes(2) - }) - - test('does not call again if deps are the same', () => { - let deps = [false] - const spy = jest.fn() - const {rerender} = testHook(() => { - useCall(spy, deps) - }) - expect(spy).toHaveBeenCalledTimes(1) - - deps = [false] - rerender() - expect(spy).toHaveBeenCalledTimes(1) - }) -}) diff --git a/src/__tests__/test-hook.js b/src/__tests__/test-hook.js deleted file mode 100644 index 4b54bfb8..00000000 --- a/src/__tests__/test-hook.js +++ /dev/null @@ -1,77 +0,0 @@ -import React, {useState, useEffect} from 'react' -import 'jest-dom/extend-expect' -import {testHook, cleanup, act} from '../' - -afterEach(cleanup) - -test('testHook calls the callback', () => { - const spy = jest.fn() - testHook(spy) - expect(spy).toHaveBeenCalledTimes(1) -}) -test('confirm we can safely call a React Hook from within the callback', () => { - testHook(() => useState()) -}) -test('returns a function to unmount component', () => { - let isMounted - const {unmount} = testHook(() => { - useEffect(() => { - isMounted = true - return () => { - isMounted = false - } - }) - }) - expect(isMounted).toBe(true) - unmount() - expect(isMounted).toBe(false) -}) -test('returns a function to rerender component', () => { - let renderCount = 0 - const {rerender} = testHook(() => { - useEffect(() => { - renderCount++ - }) - }) - - expect(renderCount).toBe(1) - rerender() - expect(renderCount).toBe(2) -}) -test('accepts wrapper option to wrap rendered hook with', () => { - const ctxA = React.createContext() - const ctxB = React.createContext() - const useHook = () => { - return React.useContext(ctxA) * React.useContext(ctxB) - } - let actual - testHook( - () => { - actual = useHook() - }, - { - // eslint-disable-next-line react/display-name - wrapper: props => ( - - - - ), - }, - ) - expect(actual).toBe(12) -}) -test('returns result ref with latest result from hook execution', () => { - function useCounter({initialCount = 0, step = 1} = {}) { - const [count, setCount] = React.useState(initialCount) - const increment = () => setCount(c => c + step) - const decrement = () => setCount(c => c - step) - return {count, increment, decrement} - } - - const {result} = testHook(useCounter) - expect(result.current.count).toBe(0) - act(() => { - result.current.increment() - }) - expect(result.current.count).toBe(1) -}) diff --git a/src/index.js b/src/index.js index 70bf83c2..d2661920 100644 --- a/src/index.js +++ b/src/index.js @@ -31,7 +31,6 @@ function render( // they're passing us a custom container or not. mountedContainers.add(container) - const wrapUiIfNeeded = innerElement => WrapperComponent ? React.createElement(WrapperComponent, null, innerElement) @@ -72,33 +71,6 @@ function render( } } -function TestHook({callback, children}) { - children(callback()) - return null -} - -function testHook(callback, options = {}) { - const result = { - current: null, - } - const toRender = () => ( - - {res => { - result.current = res - }} - - ) - - const {unmount, rerender: rerenderComponent} = render(toRender(), options) - return { - result, - unmount, - rerender: () => { - rerenderComponent(toRender(), options) - }, - } -} - function cleanup() { mountedContainers.forEach(cleanupAtContainer) } @@ -159,6 +131,6 @@ fireEvent.select = (node, init) => { // just re-export everything from dom-testing-library export * from 'dom-testing-library' -export {render, testHook, cleanup, fireEvent, act} +export {render, cleanup, fireEvent, act} /* eslint func-name-matching:0 */ diff --git a/typings/index.d.ts b/typings/index.d.ts index af09f778..06eaeeaf 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -19,12 +19,6 @@ export type RenderResult = { asFragment: () => DocumentFragment } & {[P in keyof Q]: BoundFunction} -export type HookResult = { - result: React.MutableRefObject - rerender: () => void - unmount: () => boolean -} - export interface RenderOptions { container?: HTMLElement baseElement?: HTMLElement @@ -33,8 +27,6 @@ export interface RenderOptions { wrapper?: React.ComponentType } -export type HookOptions = RenderOptions - type Omit = Pick> /** @@ -49,14 +41,6 @@ export function render( options: RenderOptions, ): RenderResult -/** - * Renders a test component that calls back to the test. - */ -export function testHook( - callback: () => T, - options?: Partial, -): HookResult - /** * Unmounts React trees that were mounted with render. */ From 8055fb52ded420178ab15729e26cc1184ffc24fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Loren=20=E2=98=BA=EF=B8=8F?= <251288+lorensr@users.noreply.github.com> Date: Mon, 25 Feb 2019 21:30:52 -0500 Subject: [PATCH 005/327] docs: fix README typo (#310) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 16aba65d..2374b9dd 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ your team down. ## This solution -The `react-testing-library` is a very light-weight solution for testing React +The `react-testing-library` is a very lightweight solution for testing React components. It provides light utility functions on top of `react-dom` and `react-dom/test-utils`, in a way that encourages better testing practices. Its primary guiding principle is: From a06a6ecb434db03d89273fc3252812f912cd4bdc Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" Date: Mon, 25 Feb 2019 19:31:26 -0700 Subject: [PATCH 006/327] docs: add lorensr as a contributor (#311) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 12 +++++++++++- README.md | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 48b07d8e..076f4205 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -689,6 +689,16 @@ "contributions": [ "code" ] + }, + { + "login": "lorensr", + "name": "Loren ☺️", + "avatar_url": "https://avatars2.githubusercontent.com/u/251288?v=4", + "profile": "http://lorensr.me", + "contributions": [ + "doc" + ] } - ] + ], + "contributorsPerLine": 7 } diff --git a/README.md b/README.md index 2374b9dd..890fa52b 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-70-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-71-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -221,7 +221,7 @@ Thanks goes to these people ([emoji key][emojis]): | [Michiel Nuyts
Michiel Nuyts](https://github.com/Michielnuyts)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=Michielnuyts "Documentation") | [Joe Ng'ethe
Joe Ng'ethe](https://github.com/joeynimu)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=joeynimu "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=joeynimu "Documentation") | [Kate
Kate](https://github.com/Enikol)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=Enikol "Documentation") | [Sean
Sean](http://www.seanrparker.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=SeanRParker "Documentation") | [James Long
James Long](http://jlongster.com)
[πŸ€”](#ideas-jlongster "Ideas, Planning, & Feedback") [πŸ“¦](#platform-jlongster "Packaging/porting to new platform") | [Herb Hagely
Herb Hagely](https://github.com/hhagely)
[πŸ’‘](#example-hhagely "Examples") | [Alex Wendte
Alex Wendte](http://www.wendtedesigns.com/)
[πŸ’‘](#example-themostcolm "Examples") | | [Monica Powell
Monica Powell](http://www.aboutmonica.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=M0nica "Documentation") | [Vitaly Sivkov
Vitaly Sivkov](http://sivkoff.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=sivkoff "Code") | [Weyert de Boer
Weyert de Boer](https://github.com/weyert)
[πŸ€”](#ideas-weyert "Ideas, Planning, & Feedback") [πŸ‘€](#review-weyert "Reviewed Pull Requests") | [EstebanMarin
EstebanMarin](https://github.com/EstebanMarin)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=EstebanMarin "Documentation") | [Victor Martins
Victor Martins](https://github.com/vctormb)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=vctormb "Documentation") | [Royston Shufflebotham
Royston Shufflebotham](https://github.com/RoystonS)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3ARoystonS "Bug reports") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=RoystonS "Documentation") [πŸ’‘](#example-RoystonS "Examples") | [chrbala
chrbala](https://github.com/chrbala)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=chrbala "Code") | | [Donavon West
Donavon West](http://donavon.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Documentation") [πŸ€”](#ideas-donavon "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Tests") | [Richard Maisano
Richard Maisano](https://github.com/maisano)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=maisano "Code") | [Marco Biedermann
Marco Biedermann](https://www.marcobiedermann.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Code") [🚧](#maintenance-marcobiedermann "Maintenance") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Tests") | [Alex Zherdev
Alex Zherdev](https://github.com/alexzherdev)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Aalexzherdev "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=alexzherdev "Code") | [AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos](https://twitter.com/Andrewmat)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Code") [πŸ’‘](#example-Andrewmat "Examples") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Tests") | [Daniel K.
Daniel K.](https://github.com/FredyC)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3AFredyC "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=FredyC "Code") [πŸ€”](#ideas-FredyC "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=FredyC "Tests") | [mohamedmagdy17593
mohamedmagdy17593](https://github.com/mohamedmagdy17593)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=mohamedmagdy17593 "Code") | - +| [Loren ☺️
Loren ☺️](http://lorensr.me)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=lorensr "Documentation") | This project follows the [all-contributors][all-contributors] specification. From 75a98b5cc47d0e40e40486b30f87d4cd0085dd59 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 7 Mar 2019 22:57:26 -0700 Subject: [PATCH 007/327] docs: funding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mostly just trying this out πŸ€·β€β™‚οΈ --- .github/FUNDING.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..87ac4edc --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,5 @@ +# You can add one username per supported platform and one custom link +patreon: kentcdodds +# open_collective: +# ko_fi: +custom: https://kcd.im/donate From ca313f2ea36724561eb56d8f336e36b2a59ced4a Mon Sep 17 00:00:00 2001 From: MarkFalconbridge Date: Tue, 19 Mar 2019 15:42:28 +0000 Subject: [PATCH 008/327] fix: reorder cleanupAtContainer code (#327) Closes https://github.com/kentcdodds/react-testing-library/issues/326 --- .all-contributorsrc | 10 ++++++++++ README.md | 4 ++-- src/__tests__/render.js | 4 +++- src/index.js | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 076f4205..de679507 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -698,6 +698,16 @@ "contributions": [ "doc" ] + }, + { + "login": "MarkFalconbridge", + "name": "MarkFalconbridge", + "avatar_url": "https://avatars1.githubusercontent.com/u/20678943?v=4", + "profile": "https://github.com/MarkFalconbridge", + "contributions": [ + "bug", + "code" + ] } ], "contributorsPerLine": 7 diff --git a/README.md b/README.md index 890fa52b..d6c46844 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-71-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-72-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -221,7 +221,7 @@ Thanks goes to these people ([emoji key][emojis]): | [Michiel Nuyts
Michiel Nuyts](https://github.com/Michielnuyts)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=Michielnuyts "Documentation") | [Joe Ng'ethe
Joe Ng'ethe](https://github.com/joeynimu)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=joeynimu "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=joeynimu "Documentation") | [Kate
Kate](https://github.com/Enikol)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=Enikol "Documentation") | [Sean
Sean](http://www.seanrparker.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=SeanRParker "Documentation") | [James Long
James Long](http://jlongster.com)
[πŸ€”](#ideas-jlongster "Ideas, Planning, & Feedback") [πŸ“¦](#platform-jlongster "Packaging/porting to new platform") | [Herb Hagely
Herb Hagely](https://github.com/hhagely)
[πŸ’‘](#example-hhagely "Examples") | [Alex Wendte
Alex Wendte](http://www.wendtedesigns.com/)
[πŸ’‘](#example-themostcolm "Examples") | | [Monica Powell
Monica Powell](http://www.aboutmonica.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=M0nica "Documentation") | [Vitaly Sivkov
Vitaly Sivkov](http://sivkoff.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=sivkoff "Code") | [Weyert de Boer
Weyert de Boer](https://github.com/weyert)
[πŸ€”](#ideas-weyert "Ideas, Planning, & Feedback") [πŸ‘€](#review-weyert "Reviewed Pull Requests") | [EstebanMarin
EstebanMarin](https://github.com/EstebanMarin)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=EstebanMarin "Documentation") | [Victor Martins
Victor Martins](https://github.com/vctormb)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=vctormb "Documentation") | [Royston Shufflebotham
Royston Shufflebotham](https://github.com/RoystonS)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3ARoystonS "Bug reports") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=RoystonS "Documentation") [πŸ’‘](#example-RoystonS "Examples") | [chrbala
chrbala](https://github.com/chrbala)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=chrbala "Code") | | [Donavon West
Donavon West](http://donavon.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Documentation") [πŸ€”](#ideas-donavon "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Tests") | [Richard Maisano
Richard Maisano](https://github.com/maisano)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=maisano "Code") | [Marco Biedermann
Marco Biedermann](https://www.marcobiedermann.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Code") [🚧](#maintenance-marcobiedermann "Maintenance") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Tests") | [Alex Zherdev
Alex Zherdev](https://github.com/alexzherdev)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Aalexzherdev "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=alexzherdev "Code") | [AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos](https://twitter.com/Andrewmat)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Code") [πŸ’‘](#example-Andrewmat "Examples") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Tests") | [Daniel K.
Daniel K.](https://github.com/FredyC)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3AFredyC "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=FredyC "Code") [πŸ€”](#ideas-FredyC "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=FredyC "Tests") | [mohamedmagdy17593
mohamedmagdy17593](https://github.com/mohamedmagdy17593)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=mohamedmagdy17593 "Code") | -| [Loren ☺️
Loren ☺️](http://lorensr.me)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=lorensr "Documentation") | +| [Loren ☺️
Loren ☺️](http://lorensr.me)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=lorensr "Documentation") | [MarkFalconbridge
MarkFalconbridge](https://github.com/MarkFalconbridge)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3AMarkFalconbridge "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=MarkFalconbridge "Code") | This project follows the [all-contributors][all-contributors] specification. diff --git a/src/__tests__/render.js b/src/__tests__/render.js index 0ffe1322..74adf5ea 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -57,14 +57,16 @@ test('returns baseElement which defaults to document.body', () => { it('cleansup document', () => { const spy = jest.fn() + const divId = 'my-div'; class Test extends React.Component { componentWillUnmount() { + expect(document.getElementById(divId)).toBeInTheDocument() spy() } render() { - return
+ return
} } diff --git a/src/index.js b/src/index.js index d2661920..c07bd000 100644 --- a/src/index.js +++ b/src/index.js @@ -78,10 +78,10 @@ function cleanup() { // maybe one day we'll expose this (perhaps even as a utility returned by render). // but let's wait until someone asks for it. function cleanupAtContainer(container) { + ReactDOM.unmountComponentAtNode(container) if (container.parentNode === document.body) { document.body.removeChild(container) } - ReactDOM.unmountComponentAtNode(container) mountedContainers.delete(container) } From 4302cdd591039b274aabdee9f716c65c524db1c8 Mon Sep 17 00:00:00 2001 From: Vinicius Date: Wed, 20 Mar 2019 11:56:16 -0300 Subject: [PATCH 009/327] docs: add example for react intl (#329) * Example: react-intl example on examples folder. * Contributors add. --- .all-contributorsrc | 10 +++++++ README.md | 5 ++-- examples/__tests__/react-intl.js | 45 ++++++++++++++++++++++++++++++++ package.json | 2 ++ 4 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 examples/__tests__/react-intl.js diff --git a/.all-contributorsrc b/.all-contributorsrc index de679507..027204fd 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -708,6 +708,16 @@ "bug", "code" ] + }, + { + "login": "viniciusavieira", + "name": "Vinicius", + "avatar_url": "https://avatars0.githubusercontent.com/u/2073019?v=4", + "profile": "https://github.com/viniciusavieira", + "contributions": [ + "doc", + "example" + ] } ], "contributorsPerLine": 7 diff --git a/README.md b/README.md index d6c46844..234eb7cc 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-72-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-73-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -221,7 +221,8 @@ Thanks goes to these people ([emoji key][emojis]): | [Michiel Nuyts
Michiel Nuyts](https://github.com/Michielnuyts)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=Michielnuyts "Documentation") | [Joe Ng'ethe
Joe Ng'ethe](https://github.com/joeynimu)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=joeynimu "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=joeynimu "Documentation") | [Kate
Kate](https://github.com/Enikol)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=Enikol "Documentation") | [Sean
Sean](http://www.seanrparker.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=SeanRParker "Documentation") | [James Long
James Long](http://jlongster.com)
[πŸ€”](#ideas-jlongster "Ideas, Planning, & Feedback") [πŸ“¦](#platform-jlongster "Packaging/porting to new platform") | [Herb Hagely
Herb Hagely](https://github.com/hhagely)
[πŸ’‘](#example-hhagely "Examples") | [Alex Wendte
Alex Wendte](http://www.wendtedesigns.com/)
[πŸ’‘](#example-themostcolm "Examples") | | [Monica Powell
Monica Powell](http://www.aboutmonica.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=M0nica "Documentation") | [Vitaly Sivkov
Vitaly Sivkov](http://sivkoff.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=sivkoff "Code") | [Weyert de Boer
Weyert de Boer](https://github.com/weyert)
[πŸ€”](#ideas-weyert "Ideas, Planning, & Feedback") [πŸ‘€](#review-weyert "Reviewed Pull Requests") | [EstebanMarin
EstebanMarin](https://github.com/EstebanMarin)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=EstebanMarin "Documentation") | [Victor Martins
Victor Martins](https://github.com/vctormb)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=vctormb "Documentation") | [Royston Shufflebotham
Royston Shufflebotham](https://github.com/RoystonS)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3ARoystonS "Bug reports") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=RoystonS "Documentation") [πŸ’‘](#example-RoystonS "Examples") | [chrbala
chrbala](https://github.com/chrbala)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=chrbala "Code") | | [Donavon West
Donavon West](http://donavon.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Documentation") [πŸ€”](#ideas-donavon "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Tests") | [Richard Maisano
Richard Maisano](https://github.com/maisano)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=maisano "Code") | [Marco Biedermann
Marco Biedermann](https://www.marcobiedermann.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Code") [🚧](#maintenance-marcobiedermann "Maintenance") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Tests") | [Alex Zherdev
Alex Zherdev](https://github.com/alexzherdev)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Aalexzherdev "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=alexzherdev "Code") | [AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos](https://twitter.com/Andrewmat)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Code") [πŸ’‘](#example-Andrewmat "Examples") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Tests") | [Daniel K.
Daniel K.](https://github.com/FredyC)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3AFredyC "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=FredyC "Code") [πŸ€”](#ideas-FredyC "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=FredyC "Tests") | [mohamedmagdy17593
mohamedmagdy17593](https://github.com/mohamedmagdy17593)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=mohamedmagdy17593 "Code") | -| [Loren ☺️
Loren ☺️](http://lorensr.me)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=lorensr "Documentation") | [MarkFalconbridge
MarkFalconbridge](https://github.com/MarkFalconbridge)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3AMarkFalconbridge "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=MarkFalconbridge "Code") | +| [Loren ☺️
Loren ☺️](http://lorensr.me)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=lorensr "Documentation") | [MarkFalconbridge
MarkFalconbridge](https://github.com/MarkFalconbridge)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3AMarkFalconbridge "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=MarkFalconbridge "Code") | [Vinicius
Vinicius](https://github.com/viniciusavieira)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=viniciusavieira "Documentation") [πŸ’‘](#example-viniciusavieira "Examples") | + This project follows the [all-contributors][all-contributors] specification. diff --git a/examples/__tests__/react-intl.js b/examples/__tests__/react-intl.js new file mode 100644 index 00000000..48fe0e0f --- /dev/null +++ b/examples/__tests__/react-intl.js @@ -0,0 +1,45 @@ +import React from 'react' +import 'jest-dom/extend-expect' +import {render, cleanup, getByTestId} from 'react-testing-library' +import {IntlProvider, FormattedDate} from 'react-intl' +import IntlPolyfill from 'intl' +import 'intl/locale-data/jsonp/pt' + +const setupTests = () => { + // Test enviroment run as server enviroment and should have polyfill to locale + // https://formatjs.io/guides/runtime-environments/#server + if (global.Intl) { + Intl.NumberFormat = IntlPolyfill.NumberFormat + Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat + } else { + global.Intl = require('intl') + } +} + +const FormatDateView = () => { + return ( +
+ +
+ ) +} + +const renderWithReactIntl = component => { + return { + ...render({component}), + } +} + +setupTests() +afterEach(cleanup) + +test('it should render FormattedDate and have a formated pt date', () => { + const {container} = renderWithReactIntl() + expect(getByTestId(container, 'date-display')).toHaveTextContent('11/03/2019') +}) diff --git a/package.json b/package.json index 54f531f1..8220dcbe 100644 --- a/package.json +++ b/package.json @@ -52,11 +52,13 @@ "axios": "^0.18.0", "eslint-import-resolver-jest": "^2.1.1", "history": "^4.7.2", + "intl": "^1.2.5", "jest-dom": "3.0.1", "jest-in-case": "^1.0.2", "kcd-scripts": "0.49.0", "react": "^16.8.0", "react-dom": "^16.8.0", + "react-intl": "^2.8.0", "react-redux": "6.0.0", "react-router": "^4.3.1", "react-router-dom": "^4.3.1", From aed35f4ca085eebd968212343f8dfa8a68096796 Mon Sep 17 00:00:00 2001 From: Peter Schyma Date: Thu, 21 Mar 2019 16:22:35 +0100 Subject: [PATCH 010/327] fix(TS): update Typings (#331) Extend the typings of Query interface to match those from dom-testing-library. --- typings/index.d.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 06eaeeaf..53e8caf5 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -3,7 +3,13 @@ import {queries, BoundFunction} from 'dom-testing-library' export * from 'dom-testing-library' interface Query extends Function { - (container: HTMLElement, ...args: any[]): HTMLElement[] | HTMLElement | null + (container: HTMLElement, ...args: any[]): + | Error + | Promise + | Promise + | HTMLElement[] + | HTMLElement + | null } interface Queries { From ea3ef2f88959085cb97a3e76c096cdb2ecd7842c Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" Date: Thu, 21 Mar 2019 09:23:08 -0600 Subject: [PATCH 011/327] docs: add pschyma as a contributor (#332) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null --- .all-contributorsrc | 9 +++++++++ README.md | 15 ++------------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 027204fd..a3aa85b1 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -718,6 +718,15 @@ "doc", "example" ] + }, + { + "login": "pschyma", + "name": "Peter Schyma", + "avatar_url": "https://avatars2.githubusercontent.com/u/2489928?v=4", + "profile": "https://github.com/pschyma", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7 diff --git a/README.md b/README.md index 234eb7cc..0326734f 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-73-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-74-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -210,18 +210,7 @@ Thanks goes to these people ([emoji key][emojis]): -| [Kent C. Dodds
Kent C. Dodds](https://kentcdodds.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Documentation") [πŸš‡](#infra-kentcdodds "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Tests") | [Ryan Castner
Ryan Castner](http://audiolion.github.io)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=audiolion "Documentation") | [Daniel Sandiego
Daniel Sandiego](https://www.dnlsandiego.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=dnlsandiego "Code") | [PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk](https://github.com/Miklet)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=Miklet "Code") | [Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz](http://co.linkedin.com/in/alejandronanez/)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=alejandronanez "Documentation") | [Matt Parrish
Matt Parrish](https://github.com/pbomb)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Apbomb "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Documentation") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Tests") | [Justin Hall
Justin Hall](https://github.com/wKovacs64)
[πŸ“¦](#platform-wKovacs64 "Packaging/porting to new platform") | -| :---: | :---: | :---: | :---: | :---: | :---: | :---: | -| [Anto Aravinth
Anto Aravinth](https://github.com/antoaravinth)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=antoaravinth "Code") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=antoaravinth "Tests") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=antoaravinth "Documentation") | [Jonah Moses
Jonah Moses](https://github.com/JonahMoses)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=JonahMoses "Documentation") | [Łukasz Gandecki
Łukasz Gandecki](http://team.thebrain.pro)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=lgandecki "Code") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=lgandecki "Tests") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=lgandecki "Documentation") | [Ivan Babak
Ivan Babak](https://sompylasar.github.io)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Asompylasar "Bug reports") [πŸ€”](#ideas-sompylasar "Ideas, Planning, & Feedback") | [Jesse Day
Jesse Day](https://github.com/jday3)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=jday3 "Code") | [Ernesto GarcΓ­a
Ernesto GarcΓ­a](http://gnapse.github.io)
[πŸ’¬](#question-gnapse "Answering Questions") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=gnapse "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=gnapse "Documentation") | [Josef Maxx Blake
Josef Maxx Blake](http://jomaxx.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=jomaxx "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=jomaxx "Documentation") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=jomaxx "Tests") | -| [Michal Baranowski
Michal Baranowski](https://twitter.com/baranovskim)
[πŸ“](#blog-mbaranovski "Blogposts") [βœ…](#tutorial-mbaranovski "Tutorials") | [Arthur Puthin
Arthur Puthin](https://github.com/aputhin)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=aputhin "Documentation") | [Thomas Chia
Thomas Chia](https://github.com/thchia)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=thchia "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=thchia "Documentation") | [Thiago Galvani
Thiago Galvani](http://ilegra.com/)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=thiagopaiva99 "Documentation") | [Christian
Christian](http://Chriswcs.github.io)
[⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=ChrisWcs "Tests") | [Alex Krolick
Alex Krolick](https://alexkrolick.com)
[πŸ’¬](#question-alexkrolick "Answering Questions") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=alexkrolick "Documentation") [πŸ’‘](#example-alexkrolick "Examples") [πŸ€”](#ideas-alexkrolick "Ideas, Planning, & Feedback") | [Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer](https://github.com/johann-sonntagbauer)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=johann-sonntagbauer "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=johann-sonntagbauer "Documentation") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=johann-sonntagbauer "Tests") | -| [Maddi Joyce
Maddi Joyce](http://www.maddijoyce.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=maddijoyce "Code") | [Ryan Vice
Ryan Vice](http://www.vicesoftware.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=RyanAtViceSoftware "Documentation") | [Ian Wilson
Ian Wilson](https://ianwilson.io)
[πŸ“](#blog-iwilsonq "Blogposts") [βœ…](#tutorial-iwilsonq "Tutorials") | [Daniel
Daniel](https://github.com/InExtremaRes)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3AInExtremaRes "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=InExtremaRes "Code") | [Giorgio Polvara
Giorgio Polvara](https://twitter.com/Gpx)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3AGpx "Bug reports") [πŸ€”](#ideas-Gpx "Ideas, Planning, & Feedback") | [John Gozde
John Gozde](https://github.com/jgoz)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=jgoz "Code") | [Sam Horton
Sam Horton](https://twitter.com/SavePointSam)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=SavePointSam "Documentation") [πŸ’‘](#example-SavePointSam "Examples") [πŸ€”](#ideas-SavePointSam "Ideas, Planning, & Feedback") | -| [Richard Kotze (mobile)
Richard Kotze (mobile)](http://www.richardkotze.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=rkotze "Documentation") | [Brahian E. Soto Mercedes
Brahian E. Soto Mercedes](https://github.com/sotobuild)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=sotobuild "Documentation") | [Benoit de La Forest
Benoit de La Forest](https://github.com/bdelaforest)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=bdelaforest "Documentation") | [Salah
Salah](https://github.com/thesalah)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=thesalah "Code") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=thesalah "Tests") | [Adam Gordon
Adam Gordon](http://gordonizer.com)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Aicfantv "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=icfantv "Code") | [Matija MarohniΔ‡
Matija Marohnić](https://silvenon.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=silvenon "Documentation") | [Justice Mba
Justice Mba](https://github.com/Dajust)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=Dajust "Documentation") | -| [Mark Pollmann
Mark Pollmann](https://markpollmann.com/)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=MarkPollmann "Documentation") | [Ehtesham Kafeel
Ehtesham Kafeel](https://github.com/ehteshamkafeel)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=ehteshamkafeel "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=ehteshamkafeel "Documentation") | [Julio PavΓ³n
Julio PavΓ³n](http://jpavon.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=jpavon "Code") | [Duncan L
Duncan L](http://www.duncanleung.com/)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=duncanleung "Documentation") [πŸ’‘](#example-duncanleung "Examples") | [Tiago Almeida
Tiago Almeida](https://www.linkedin.com/in/tyagow/?locale=en_US)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=tyagow "Documentation") | [Robert Smith
Robert Smith](http://rbrtsmith.com/)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Arbrtsmith "Bug reports") | [Zach Green
Zach Green](https://offbyone.tech)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=zgreen "Documentation") | -| [dadamssg
dadamssg](https://github.com/dadamssg)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=dadamssg "Documentation") | [Yazan Aabed
Yazan Aabed](https://www.yaabed.com/)
[πŸ“](#blog-YazanAabeed "Blogposts") | [Tim
Tim](https://github.com/timbonicus)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Atimbonicus "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=timbonicus "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=timbonicus "Documentation") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=timbonicus "Tests") | [Divyanshu Maithani
Divyanshu Maithani](http://divyanshu.xyz)
[βœ…](#tutorial-divyanshu013 "Tutorials") [πŸ“Ή](#video-divyanshu013 "Videos") | [Deepak Grover
Deepak Grover](https://www.linkedin.com/in/metagrover)
[βœ…](#tutorial-metagrover "Tutorials") [πŸ“Ή](#video-metagrover "Videos") | [Eyal Cohen
Eyal Cohen](https://github.com/eyalcohen4)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=eyalcohen4 "Documentation") | [Peter Makowski
Peter Makowski](https://github.com/petermakowski)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=petermakowski "Documentation") | -| [Michiel Nuyts
Michiel Nuyts](https://github.com/Michielnuyts)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=Michielnuyts "Documentation") | [Joe Ng'ethe
Joe Ng'ethe](https://github.com/joeynimu)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=joeynimu "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=joeynimu "Documentation") | [Kate
Kate](https://github.com/Enikol)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=Enikol "Documentation") | [Sean
Sean](http://www.seanrparker.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=SeanRParker "Documentation") | [James Long
James Long](http://jlongster.com)
[πŸ€”](#ideas-jlongster "Ideas, Planning, & Feedback") [πŸ“¦](#platform-jlongster "Packaging/porting to new platform") | [Herb Hagely
Herb Hagely](https://github.com/hhagely)
[πŸ’‘](#example-hhagely "Examples") | [Alex Wendte
Alex Wendte](http://www.wendtedesigns.com/)
[πŸ’‘](#example-themostcolm "Examples") | -| [Monica Powell
Monica Powell](http://www.aboutmonica.com)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=M0nica "Documentation") | [Vitaly Sivkov
Vitaly Sivkov](http://sivkoff.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=sivkoff "Code") | [Weyert de Boer
Weyert de Boer](https://github.com/weyert)
[πŸ€”](#ideas-weyert "Ideas, Planning, & Feedback") [πŸ‘€](#review-weyert "Reviewed Pull Requests") | [EstebanMarin
EstebanMarin](https://github.com/EstebanMarin)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=EstebanMarin "Documentation") | [Victor Martins
Victor Martins](https://github.com/vctormb)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=vctormb "Documentation") | [Royston Shufflebotham
Royston Shufflebotham](https://github.com/RoystonS)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3ARoystonS "Bug reports") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=RoystonS "Documentation") [πŸ’‘](#example-RoystonS "Examples") | [chrbala
chrbala](https://github.com/chrbala)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=chrbala "Code") | -| [Donavon West
Donavon West](http://donavon.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Code") [πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Documentation") [πŸ€”](#ideas-donavon "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Tests") | [Richard Maisano
Richard Maisano](https://github.com/maisano)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=maisano "Code") | [Marco Biedermann
Marco Biedermann](https://www.marcobiedermann.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Code") [🚧](#maintenance-marcobiedermann "Maintenance") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Tests") | [Alex Zherdev
Alex Zherdev](https://github.com/alexzherdev)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Aalexzherdev "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=alexzherdev "Code") | [AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos](https://twitter.com/Andrewmat)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Code") [πŸ’‘](#example-Andrewmat "Examples") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Tests") | [Daniel K.
Daniel K.](https://github.com/FredyC)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3AFredyC "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=FredyC "Code") [πŸ€”](#ideas-FredyC "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=FredyC "Tests") | [mohamedmagdy17593
mohamedmagdy17593](https://github.com/mohamedmagdy17593)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=mohamedmagdy17593 "Code") | -| [Loren ☺️
Loren ☺️](http://lorensr.me)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=lorensr "Documentation") | [MarkFalconbridge
MarkFalconbridge](https://github.com/MarkFalconbridge)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3AMarkFalconbridge "Bug reports") [πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=MarkFalconbridge "Code") | [Vinicius
Vinicius](https://github.com/viniciusavieira)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=viniciusavieira "Documentation") [πŸ’‘](#example-viniciusavieira "Examples") | +
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
From a33ccf8f52ecffd46a7ee2438454949794270f67 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Tue, 26 Mar 2019 11:08:43 -0600 Subject: [PATCH 012/327] fix(deps): upgrade all dependencies --- package.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 8220dcbe..6bcb30cd 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,8 @@ "author": "Kent C. Dodds (http://kentcdodds.com/)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.3.1", - "dom-testing-library": "^3.13.1" + "@babel/runtime": "^7.4.2", + "dom-testing-library": "^3.18.2" }, "devDependencies": { "@reach/router": "^1.2.1", @@ -51,18 +51,18 @@ "@types/react-dom": "^16.8.2", "axios": "^0.18.0", "eslint-import-resolver-jest": "^2.1.1", - "history": "^4.7.2", + "history": "^4.9.0", "intl": "^1.2.5", - "jest-dom": "3.0.1", + "jest-dom": "3.1.3", "jest-in-case": "^1.0.2", - "kcd-scripts": "0.49.0", - "react": "^16.8.0", - "react-dom": "^16.8.0", + "kcd-scripts": "1.1.2", + "react": "^16.8.5", + "react-dom": "^16.8.5", "react-intl": "^2.8.0", - "react-redux": "6.0.0", - "react-router": "^4.3.1", - "react-router-dom": "^4.3.1", - "react-transition-group": "^2.5.0", + "react-redux": "6.0.1", + "react-router": "^5.0.0", + "react-router-dom": "^5.0.0", + "react-transition-group": "^2.7.1", "redux": "^4.0.0" }, "peerDependencies": { From c0d2d6e08d88de092f73cd0f688e4e0b0fc0fc5d Mon Sep 17 00:00:00 2001 From: Ian Schmitz Date: Thu, 28 Mar 2019 15:15:44 -0700 Subject: [PATCH 013/327] docs: fix README.md typo (#334) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just fixing a small typo πŸ˜ƒ. Thanks for the great lib! --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0326734f..d148af95 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ test('Fetch makes an API call and displays the greeting when load-greeting is cl expect(getByTestId('ok-button')).toHaveAttribute('disabled') // snapshots work great with regular DOM nodes! expect(container.firstChild).toMatchSnapshot() - // you can also use get a `DocumentFragment`, which is useful if you want to compare nodes across render + // you can also get a `DocumentFragment`, which is useful if you want to compare nodes across renders expect(asFragment()).toMatchSnapshot() }) ``` From d2479428271a6b6baff6d67e8e576fa30398239c Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" Date: Thu, 28 Mar 2019 16:16:19 -0600 Subject: [PATCH 014/327] docs: add ianschmitz as a contributor (#335) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 12 +++++++++++- README.md | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index a3aa85b1..d4301b17 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -727,7 +727,17 @@ "contributions": [ "code" ] + }, + { + "login": "ianschmitz", + "name": "Ian Schmitz", + "avatar_url": "https://avatars1.githubusercontent.com/u/6355370?v=4", + "profile": "https://github.com/ianschmitz", + "contributions": [ + "doc" + ] } ], - "contributorsPerLine": 7 + "contributorsPerLine": 7, + "repoHost": "https://github.com" } diff --git a/README.md b/README.md index d148af95..2b127f7e 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-74-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-75-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -210,7 +210,7 @@ Thanks goes to these people ([emoji key][emojis]): -
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
+
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
From 6890f4f7c187c8302561cc043a6aa99180218717 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Mon, 1 Apr 2019 10:20:11 -0600 Subject: [PATCH 015/327] chore: remove lint warning --- examples/react-hooks.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/react-hooks.js b/examples/react-hooks.js index 251644cd..2ef92b7d 100644 --- a/examples/react-hooks.js +++ b/examples/react-hooks.js @@ -23,3 +23,5 @@ export function useCall(callback, deps) { callback() }, deps) } + +/* eslint react-hooks/exhaustive-deps:0 */ From 89299e90542091b5c9227b6083f82ba6b98fd816 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Mon, 1 Apr 2019 11:33:06 -0600 Subject: [PATCH 016/327] fix(act): add try/catch around react-dom/test-utils require (#340) Closes #315 --- src/act-compat.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/act-compat.js b/src/act-compat.js index 8b76d157..f6e4a680 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -1,6 +1,12 @@ import React from 'react' import ReactDOM from 'react-dom' -import {act as reactAct} from 'react-dom/test-utils' + +let reactAct +try { + reactAct = require('react-dom/test-utils').act +} catch (error) { + // ignore, this is to support old versions of react +} // act is supported react-dom@16.8.0 // so for versions that don't have act from test utils From 7e6031f40c572b0a2cf5d285d84487d4e562a36d Mon Sep 17 00:00:00 2001 From: Alex Krolick Date: Mon, 1 Apr 2019 11:28:56 -0700 Subject: [PATCH 017/327] docs: link issue templates to docs repo (#325) --- .github/ISSUE_TEMPLATE.md | 4 ++-- .github/ISSUE_TEMPLATE/Bug_Report.md | 5 +++++ .github/ISSUE_TEMPLATE/Question.md | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 724a7df6..b43b3471 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -60,11 +60,11 @@ What happened: Reproduction repository: -https://github.com/alexkrolick/dom-testing-library-template + ### What you did: diff --git a/.github/ISSUE_TEMPLATE/Question.md b/.github/ISSUE_TEMPLATE/Question.md index 52790875..efd0d846 100644 --- a/.github/ISSUE_TEMPLATE/Question.md +++ b/.github/ISSUE_TEMPLATE/Question.md @@ -16,5 +16,6 @@ and feature requests so we recommend not using this medium to ask them here 😁 - Reactiflux on Discord https://www.reactiflux.com - Stack Overflow https://stackoverflow.com/questions/tagged/react-testing-library +- Documentation: https://github.com/alexkrolick/testing-library-docs **ISSUES WHICH ARE QUESTIONS WILL BE CLOSED** From 5a88da27a87de869e40fc8abdf5a9483066e5ec2 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 5 Apr 2019 10:32:44 -0600 Subject: [PATCH 018/327] =?UTF-8?q?feat(act):=20Support=20async=20act=20?= =?UTF-8?q?=F0=9F=8E=89=20(#343)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #281 --- .github/PULL_REQUEST_TEMPLATE.md | 5 ++-- package.json | 7 +++-- src/__tests__/old-act.js | 45 ++++++++++++++++++++++++++++++++ src/act-compat.js | 41 ++++++++++++++++++++++++++--- src/index.js | 11 +++++++- 5 files changed, 98 insertions(+), 11 deletions(-) create mode 100644 src/__tests__/old-act.js diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index df54e83c..e3b54b33 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -34,12 +34,11 @@ merge of your pull request! -- [ ] Documentation added to the [docs site](https://github.com/alexkrolick/testing-library-docs) +- [ ] Documentation added to the + [docs site](https://github.com/alexkrolick/testing-library-docs) - [ ] Tests - [ ] Typescript definitions updated - [ ] Ready to be merged -- [ ] Added myself to contributors table - diff --git a/package.json b/package.json index 6bcb30cd..f226d339 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "node": ">=8" }, "scripts": { - "add-contributor": "kcd-scripts contributors add", "build": "kcd-scripts build && kcd-scripts build --bundle --no-clean", "lint": "kcd-scripts lint", "test": "kcd-scripts test --config=other/jest.config.js", @@ -43,7 +42,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.4.2", - "dom-testing-library": "^3.18.2" + "dom-testing-library": "^3.19.0" }, "devDependencies": { "@reach/router": "^1.2.1", @@ -56,8 +55,8 @@ "jest-dom": "3.1.3", "jest-in-case": "^1.0.2", "kcd-scripts": "1.1.2", - "react": "^16.8.5", - "react-dom": "^16.8.5", + "react": "16.9.0-alpha.0", + "react-dom": "16.9.0-alpha.0", "react-intl": "^2.8.0", "react-redux": "6.0.1", "react-router": "^5.0.0", diff --git a/src/__tests__/old-act.js b/src/__tests__/old-act.js new file mode 100644 index 00000000..5fee7fe7 --- /dev/null +++ b/src/__tests__/old-act.js @@ -0,0 +1,45 @@ +import {asyncAct} from '../act-compat' + +jest.mock('react-dom/test-utils', () => ({ + act: cb => { + const promise = cb() + return { + then() { + console.error('blah, do not do this') + return promise + }, + } + }, +})) + +test('async act works even when the act is an old one', async () => { + jest.spyOn(console, 'error').mockImplementation(() => {}) + const callback = jest.fn() + await asyncAct(async () => { + await Promise.resolve() + await callback() + }) + expect(console.error.mock.calls).toMatchInlineSnapshot(` +Array [ + Array [ + "It looks like you're using a version of react-dom that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.", + ], +] +`) + expect(callback).toHaveBeenCalledTimes(1) + + // and it doesn't warn you twice + callback.mockClear() + console.error.mockClear() + + await asyncAct(async () => { + await Promise.resolve() + await callback() + }) + expect(console.error).toHaveBeenCalledTimes(0) + expect(callback).toHaveBeenCalledTimes(1) + + console.error.mockRestore() +}) + +/* eslint no-console:0 */ diff --git a/src/act-compat.js b/src/act-compat.js index f6e4a680..7e4fbb9a 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -2,8 +2,23 @@ import React from 'react' import ReactDOM from 'react-dom' let reactAct +let actSupported = false +let asyncActSupported = false try { reactAct = require('react-dom/test-utils').act + actSupported = reactAct !== undefined + + const originalError = console.error + let errorCalled = false + console.error = () => { + errorCalled = true + } + console.error.calls = [] + reactAct(() => ({then: () => {}})).then(/* istanbul ignore next */ () => {}) + if (!errorCalled) { + asyncActSupported = true + } + console.error = originalError } catch (error) { // ignore, this is to support old versions of react } @@ -19,8 +34,28 @@ function actPolyfill(cb) { const act = reactAct || actPolyfill -function rtlAct(...args) { - return act(...args) +let youHaveBeenWarned = false +// this will not avoid warnings that react-dom 16.8.0 logs for triggering +// state updates asynchronously, but at least we can tell people they need +// to upgrade to avoid the warnings. +async function asyncActPolyfill(cb) { + if (!youHaveBeenWarned && actSupported) { + // if act is supported and async act isn't and they're trying to use async + // act, then they need to upgrade from 16.8 to 16.9. + // This is a seemless upgrade, so we'll add a warning + console.error( + `It looks like you're using a version of react-dom that supports the "act" function, but not an awaitable version of "act" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.`, + ) + youHaveBeenWarned = true + } + await cb() + // make all effects resolve after + act(() => {}) } -export default rtlAct +const asyncAct = asyncActSupported ? reactAct : asyncActPolyfill + +export default act +export {asyncAct} + +/* eslint no-console:0 */ diff --git a/src/index.js b/src/index.js index c07bd000..fe6b259b 100644 --- a/src/index.js +++ b/src/index.js @@ -4,8 +4,13 @@ import { getQueriesForElement, prettyDOM, fireEvent as dtlFireEvent, + configure as configureDTL, } from 'dom-testing-library' -import act from './act-compat' +import act, {asyncAct} from './act-compat' + +configureDTL({ + asyncWrapper: asyncAct, +}) const mountedContainers = new Set() @@ -133,4 +138,8 @@ fireEvent.select = (node, init) => { export * from 'dom-testing-library' export {render, cleanup, fireEvent, act} +// NOTE: we're not going to export asyncAct because that's our own compatibility +// thing for people using react-dom@16.8.0. Anyone else doesn't need it and +// people should just upgrade anyway. + /* eslint func-name-matching:0 */ From 180179e12239d7de7ec5bf5f572291cd9ec48d33 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 5 Apr 2019 10:49:08 -0600 Subject: [PATCH 019/327] fix(act): wait until react-dom-16.9.0 is released (#344) --- package.json | 4 ++-- src/__tests__/old-act.js | 4 ++++ src/act-compat.js | 13 +++++++++++-- src/react-dom-16.9.0-is-released.js | 2 ++ 4 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 src/react-dom-16.9.0-is-released.js diff --git a/package.json b/package.json index f226d339..ba558b87 100644 --- a/package.json +++ b/package.json @@ -55,8 +55,8 @@ "jest-dom": "3.1.3", "jest-in-case": "^1.0.2", "kcd-scripts": "1.1.2", - "react": "16.9.0-alpha.0", - "react-dom": "16.9.0-alpha.0", + "react": "^16.8.6", + "react-dom": "^16.8.6", "react-intl": "^2.8.0", "react-redux": "6.0.1", "react-router": "^5.0.0", diff --git a/src/__tests__/old-act.js b/src/__tests__/old-act.js index 5fee7fe7..d21c2bae 100644 --- a/src/__tests__/old-act.js +++ b/src/__tests__/old-act.js @@ -1,5 +1,9 @@ import {asyncAct} from '../act-compat' +jest.mock('../react-dom-16.9.0-is-released', () => ({ + reactDomSixteenPointNineIsReleased: true, +})) + jest.mock('react-dom/test-utils', () => ({ act: cb => { const promise = cb() diff --git a/src/act-compat.js b/src/act-compat.js index 7e4fbb9a..a87ee4d7 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -1,5 +1,6 @@ import React from 'react' import ReactDOM from 'react-dom' +import {reactDomSixteenPointNineIsReleased} from './react-dom-16.9.0-is-released' let reactAct let actSupported = false @@ -14,7 +15,9 @@ try { errorCalled = true } console.error.calls = [] - reactAct(() => ({then: () => {}})).then(/* istanbul ignore next */ () => {}) + /* istanbul ignore next */ + reactAct(() => ({then: () => {}})).then(() => {}) + /* istanbul ignore next */ if (!errorCalled) { asyncActSupported = true } @@ -39,7 +42,12 @@ let youHaveBeenWarned = false // state updates asynchronously, but at least we can tell people they need // to upgrade to avoid the warnings. async function asyncActPolyfill(cb) { - if (!youHaveBeenWarned && actSupported) { + // istanbul-ignore-next + if ( + !youHaveBeenWarned && + actSupported && + reactDomSixteenPointNineIsReleased + ) { // if act is supported and async act isn't and they're trying to use async // act, then they need to upgrade from 16.8 to 16.9. // This is a seemless upgrade, so we'll add a warning @@ -53,6 +61,7 @@ async function asyncActPolyfill(cb) { act(() => {}) } +// istanbul ignore next const asyncAct = asyncActSupported ? reactAct : asyncActPolyfill export default act diff --git a/src/react-dom-16.9.0-is-released.js b/src/react-dom-16.9.0-is-released.js new file mode 100644 index 00000000..33053dfa --- /dev/null +++ b/src/react-dom-16.9.0-is-released.js @@ -0,0 +1,2 @@ +// we don't want to warn until react-dom@16.9.0 is actually released +export const reactDomSixteenPointNineIsReleased = false From 30bf1c6e0e024c0dff8201f848f2c73209e1bdf6 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" Date: Fri, 5 Apr 2019 13:42:03 -0600 Subject: [PATCH 020/327] docs: add joual as a contributor (#348) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null --- .all-contributorsrc | 11 +++++++++++ README.md | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index d4301b17..6d741407 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -736,6 +736,17 @@ "contributions": [ "doc" ] + }, + { + "login": "joual", + "name": "Joel Marcotte", + "avatar_url": "https://avatars0.githubusercontent.com/u/157877?v=4", + "profile": "https://github.com/joual", + "contributions": [ + "bug", + "test", + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 2b127f7e..eb92d5d9 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-75-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-76-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -210,7 +210,7 @@ Thanks goes to these people ([emoji key][emojis]): -
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
+
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
From 021ef9d6bce13d6bf7d71a4a8ecdd6aafb4cd660 Mon Sep 17 00:00:00 2001 From: Joel Marcotte Date: Fri, 5 Apr 2019 15:44:08 -0400 Subject: [PATCH 021/327] fix(act): ensure that the result is returned from our wrapper (#346) * failing test * act-compat change * fix(act): ensure that the result is returned from our wrapper Closes #345 Closes #347 --- src/__tests__/act.js | 6 ++++++ src/index.js | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/__tests__/act.js b/src/__tests__/act.js index 49729f3b..5f3cbfb5 100644 --- a/src/__tests__/act.js +++ b/src/__tests__/act.js @@ -14,6 +14,12 @@ test('render calls useEffect immediately', () => { expect(effectCb).toHaveBeenCalledTimes(1) }) +test('findByTestId returns the element', async () => { + const ref = React.createRef() + const {findByTestId} = render(
) + expect(await findByTestId('foo')).toBe(ref.current) +}) + test('fireEvent triggers useEffect calls', () => { const effectCb = jest.fn() function Counter() { diff --git a/src/index.js b/src/index.js index fe6b259b..379fccbc 100644 --- a/src/index.js +++ b/src/index.js @@ -9,7 +9,13 @@ import { import act, {asyncAct} from './act-compat' configureDTL({ - asyncWrapper: asyncAct, + asyncWrapper: async cb => { + let result + await asyncAct(async () => { + result = await cb() + }) + return result + }, }) const mountedContainers = new Set() From 1d00c79408a77a88c620d214da4465369c1a51ad Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" Date: Fri, 5 Apr 2019 13:44:52 -0600 Subject: [PATCH 022/327] docs: add aledustet as a contributor (#349) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null --- .all-contributorsrc | 9 +++++++++ README.md | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 6d741407..282ef160 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -747,6 +747,15 @@ "test", "code" ] + }, + { + "login": "aledustet", + "name": "Alejandro Dustet", + "avatar_url": "https://avatars3.githubusercontent.com/u/2413802?v=4", + "profile": "http://aledustet.com", + "contributions": [ + "bug" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index eb92d5d9..83916bb9 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-76-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-77-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -210,7 +210,7 @@ Thanks goes to these people ([emoji key][emojis]): -
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
+
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
From 1a57361cd55aa63b76615bad2343c1763668b3d8 Mon Sep 17 00:00:00 2001 From: Brandon Carroll Date: Sat, 13 Apr 2019 19:31:17 -0400 Subject: [PATCH 023/327] docs: add cheat sheet (#354) --- other/cheat-sheet.pdf | Bin 0 -> 54406 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 other/cheat-sheet.pdf diff --git a/other/cheat-sheet.pdf b/other/cheat-sheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3cafbc3a2c9fa9b7dd9a7b206fdb6c8288165b91 GIT binary patch literal 54406 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

FeDN)({>EHLQv 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 ak(``?uh`#SY%I)-0CpHMG7&jZnEwTHsC={l literal 0 HcmV?d00001 From 480b3e584ac51a4af84ec9756603fc298e4a0ca5 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" Date: Sat, 13 Apr 2019 17:32:13 -0600 Subject: [PATCH 024/327] docs: add bcarroll22 as a contributor (#355) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 282ef160..5859504a 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -756,6 +756,15 @@ "contributions": [ "bug" ] + }, + { + "login": "bcarroll22", + "name": "Brandon Carroll", + "avatar_url": "https://avatars2.githubusercontent.com/u/11020406?v=4", + "profile": "https://github.com/bcarroll22", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 83916bb9..e5998abe 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-77-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-78-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -210,7 +210,7 @@ Thanks goes to these people ([emoji key][emojis]): -
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
+
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
From f5b1b23dfdb615e2a1f995c9861b99ffd9276419 Mon Sep 17 00:00:00 2001 From: Alex Krolick Date: Wed, 17 Apr 2019 17:17:16 -0700 Subject: [PATCH 025/327] docs: update README.md (#358) --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index e5998abe..f1ee4cb0 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,12 @@

Simple and complete React DOM testing utilities that encourage good testing practices.

+
+ [**Read The Docs**](https://testing-library.com/react) | [Edit the docs](https://github.com/alexkrolick/testing-library-docs) +

@@ -59,6 +62,7 @@ practices.

- [Other Solutions](#other-solutions) - [Guiding Principles](#guiding-principles) - [Contributors](#contributors) +- [Docs](#docs) - [Issues](#issues) - [πŸ› Bugs](#-bugs) - [πŸ’‘ Feature Requests](#-feature-requests) @@ -217,6 +221,10 @@ Thanks goes to these people ([emoji key][emojis]): This project follows the [all-contributors][all-contributors] specification. Contributions of any kind welcome! +## Docs + +[**Read The Docs**](https://testing-library.com/react) | [Edit the docs](https://github.com/alexkrolick/testing-library-docs) + ## Issues _Looking to contribute? Look for the [Good First Issue][good-first-issue] From cf606f570636df6a2b876ae8f12a6f087d9b3054 Mon Sep 17 00:00:00 2001 From: Lucas Machado Date: Mon, 22 Apr 2019 18:27:47 -0300 Subject: [PATCH 026/327] docs: add a dot to end of section about Hooks (#360) Added a dot to end of section about Hooks. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f1ee4cb0..5c28286f 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ You can also find react-testing-library examples at ## Hooks If you are interested in testing a custom hook, check out -[react-hooks-testing-library][react-hooks-testing-library] +[react-hooks-testing-library][react-hooks-testing-library]. ## Other Solutions From 5ce6c19ea31a3fcc0d277a2f544d426ecbc945bb Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" Date: Mon, 22 Apr 2019 15:28:23 -0600 Subject: [PATCH 027/327] docs: add lucas0707 as a contributor (#361) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 5859504a..bf8d25f1 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -765,6 +765,15 @@ "contributions": [ "doc" ] + }, + { + "login": "lucas0707", + "name": "Lucas Machado", + "avatar_url": "https://avatars1.githubusercontent.com/u/26284338?v=4", + "profile": "https://github.com/lucas0707", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 5c28286f..9144145f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-78-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-79-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -214,7 +214,7 @@ Thanks goes to these people ([emoji key][emojis]): -
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
+
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
From d232c0063d80fe0cf5e79bf00bc53c228981a3f0 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 25 Apr 2019 15:14:27 -0600 Subject: [PATCH 028/327] feat: update to the latest dom-testing-library@4.0.0 (#365) BREAKING CHANGE: This upgrades to the latest dom-testing-library which has a few breaking changes: https://github.com/testing-library/dom-testing-library/releases/tag/v4.0.0 --- .all-contributorsrc | 2 +- .github/FUNDING.yml | 6 +---- CONTRIBUTING.md | 6 ++--- README.md | 53 +++++++++++++++++++++--------------------- examples/README.md | 2 +- package.json | 20 ++++++++-------- src/__mocks__/axios.js | 2 +- 7 files changed, 43 insertions(+), 48 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index bf8d25f1..39f5a7e4 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1,6 +1,6 @@ { "projectName": "react-testing-library", - "projectOwner": "kentcdodds", + "projectOwner": "testing-library", "repoType": "github", "files": [ "README.md" diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 87ac4edc..9bf52665 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,5 +1 @@ -# You can add one username per supported platform and one custom link -patreon: kentcdodds -# open_collective: -# ko_fi: -custom: https://kcd.im/donate +open_collective: testing-library diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 89f9e343..7cc35e72 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,7 +15,7 @@ series [How to Contribute to an Open Source Project on GitHub][egghead] > pull requests from branches on your fork. To do this, run: > > ``` -> git remote add upstream https://github.com/kentcdodds/react-testing-library.git +> git remote add upstream https://github.com/testing-library/react-testing-library.git > git fetch upstream > git branch --set-upstream-to=upstream/master master > ``` @@ -75,5 +75,5 @@ requests! Thanks! [egghead]: https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github -[all-contributors]: https://github.com/kentcdodds/all-contributors -[issues]: https://github.com/kentcdodds/react-testing-library/issues +[all-contributors]: https://github.com/all-contributors/all-contributors +[issues]: https://github.com/testing-library/react-testing-library/issues diff --git a/README.md b/README.md index 9144145f..05b243e5 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ height="80" width="80" alt="goat" - src="https://raw.githubusercontent.com/kentcdodds/react-testing-library/master/other/goat.png" + src="https://raw.githubusercontent.com/testing-library/react-testing-library/master/other/goat.png" />
@@ -43,7 +43,7 @@ practices.

TestingJavaScript.com Learn the smart, efficient way to test any JavaScript application.
@@ -161,12 +161,12 @@ You may also be interested in installing `jest-dom` so you can use > [docs site](https://testing-library.com/docs/example-codesandbox) You'll find runnable examples of testing with different libraries in -[the `examples` directory](https://github.com/kentcdodds/react-testing-library/blob/master/examples). +[the `examples` directory](https://github.com/testing-library/react-testing-library/blob/master/examples). Some included are: -- [`react-redux`](https://github.com/kentcdodds/react-testing-library/blob/master/examples/__tests__/react-redux.js) -- [`react-router`](https://github.com/kentcdodds/react-testing-library/blob/master/examples/__tests__/react-router.js) -- [`react-context`](https://github.com/kentcdodds/react-testing-library/blob/master/examples/__tests__/react-context.js) +- [`react-redux`](https://github.com/testing-library/react-testing-library/blob/master/examples/__tests__/react-redux.js) +- [`react-router`](https://github.com/testing-library/react-testing-library/blob/master/examples/__tests__/react-router.js) +- [`react-context`](https://github.com/testing-library/react-testing-library/blob/master/examples/__tests__/react-context.js) You can also find react-testing-library examples at [react-testing-examples.com](https://react-testing-examples.com/jest-rtl/). @@ -214,7 +214,7 @@ Thanks goes to these people ([emoji key][emojis]): -
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
+
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
@@ -223,7 +223,8 @@ Contributions of any kind welcome! ## Docs -[**Read The Docs**](https://testing-library.com/react) | [Edit the docs](https://github.com/alexkrolick/testing-library-docs) +[**Read The Docs**](https://testing-library.com/react) | +[Edit the docs](https://github.com/alexkrolick/testing-library-docs) ## Issues @@ -264,10 +265,10 @@ Links: [npm]: https://www.npmjs.com/ [node]: https://nodejs.org -[build-badge]: https://img.shields.io/travis/kentcdodds/react-testing-library.svg?style=flat-square -[build]: https://travis-ci.org/kentcdodds/react-testing-library -[coverage-badge]: https://img.shields.io/codecov/c/github/kentcdodds/react-testing-library.svg?style=flat-square -[coverage]: https://codecov.io/github/kentcdodds/react-testing-library +[build-badge]: https://img.shields.io/travis/testing-library/react-testing-library.svg?style=flat-square +[build]: https://travis-ci.org/testing-library/react-testing-library +[coverage-badge]: https://img.shields.io/codecov/c/github/testing-library/react-testing-library.svg?style=flat-square +[coverage]: https://codecov.io/github/testing-library/react-testing-library [version-badge]: https://img.shields.io/npm/v/react-testing-library.svg?style=flat-square [package]: https://www.npmjs.com/package/react-testing-library [downloads-badge]: https://img.shields.io/npm/dm/react-testing-library.svg?style=flat-square @@ -275,27 +276,25 @@ Links: [spectrum-badge]: https://withspectrum.github.io/badge/badge.svg [spectrum]: https://spectrum.chat/react-testing-library [license-badge]: https://img.shields.io/npm/l/react-testing-library.svg?style=flat-square -[license]: https://github.com/kentcdodds/react-testing-library/blob/master/LICENSE +[license]: https://github.com/testing-library/react-testing-library/blob/master/LICENSE [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square [prs]: http://makeapullrequest.com [donate-badge]: https://img.shields.io/badge/$-support-green.svg?style=flat-square [coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square -[coc]: https://github.com/kentcdodds/react-testing-library/blob/master/CODE_OF_CONDUCT.md -[github-watch-badge]: https://img.shields.io/github/watchers/kentcdodds/react-testing-library.svg?style=social -[github-watch]: https://github.com/kentcdodds/react-testing-library/watchers -[github-star-badge]: https://img.shields.io/github/stars/kentcdodds/react-testing-library.svg?style=social -[github-star]: https://github.com/kentcdodds/react-testing-library/stargazers -[twitter]: https://twitter.com/intent/tweet?text=Check%20out%20react-testing-library%20by%20%40kentcdodds%20https%3A%2F%2Fgithub.com%2Fkentcdodds%2Freact-testing-library%20%F0%9F%91%8D -[twitter-badge]: https://img.shields.io/twitter/url/https/github.com/kentcdodds/react-testing-library.svg?style=social -[emojis]: https://github.com/kentcdodds/all-contributors#emoji-key -[all-contributors]: https://github.com/kentcdodds/all-contributors +[coc]: https://github.com/testing-library/react-testing-library/blob/master/CODE_OF_CONDUCT.md +[github-watch-badge]: https://img.shields.io/github/watchers/testing-library/react-testing-library.svg?style=social +[github-watch]: https://github.com/testing-library/react-testing-library/watchers +[github-star-badge]: https://img.shields.io/github/stars/testing-library/react-testing-library.svg?style=social +[github-star]: https://github.com/testing-library/react-testing-library/stargazers +[twitter]: https://twitter.com/intent/tweet?text=Check%20out%20react-testing-library%20by%20%40@TestingLib%20https%3A%2F%2Fgithub.com%2Ftesting-library%2Freact-testing-library%20%F0%9F%91%8D +[twitter-badge]: https://img.shields.io/twitter/url/https/github.com/testing-library/react-testing-library.svg?style=social +[emojis]: https://github.com/all-contributors/all-contributors#emoji-key +[all-contributors]: https://github.com/all-contributors/all-contributors [set-immediate]: https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate [guiding-principle]: https://twitter.com/kentcdodds/status/977018512689455106 -[data-testid-blog-post]: https://blog.kentcdodds.com/making-your-ui-tests-resilient-to-change-d37a6ee37269 -[dom-testing-lib-textmatch]: https://github.com/kentcdodds/dom-testing-library#textmatch -[bugs]: https://github.com/kentcdodds/react-testing-library/issues?q=is%3Aissue+is%3Aopen+label%3Abug+sort%3Acreated-desc -[requests]: https://github.com/kentcdodds/react-testing-library/issues?q=is%3Aissue+sort%3Areactions-%2B1-desc+label%3Aenhancement+is%3Aopen -[good-first-issue]: https://github.com/kentcdodds/react-testing-library/issues?utf8=βœ“&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3A"good+first+issue"+ +[bugs]: https://github.com/testing-library/react-testing-library/issues?q=is%3Aissue+is%3Aopen+label%3Abug+sort%3Acreated-desc +[requests]: https://github.com/testing-library/react-testing-library/issues?q=is%3Aissue+sort%3Areactions-%2B1-desc+label%3Aenhancement+is%3Aopen +[good-first-issue]: https://github.com/testing-library/react-testing-library/issues?utf8=βœ“&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3A"good+first+issue"+ [reactiflux]: https://www.reactiflux.com/ [stackoverflow]: https://stackoverflow.com/questions/tagged/react-testing-library [react-hooks-testing-library]: https://github.com/mpeyper/react-hooks-testing-library diff --git a/examples/README.md b/examples/README.md index 9c89757e..44e36304 100644 --- a/examples/README.md +++ b/examples/README.md @@ -27,5 +27,5 @@ specific example, you can run `npm test name-of-your-file`. This will put you into Jest's interactive watch mode with a filter based on the name you provided. [contributing]: - https://github.com/kentcdodds/react-testing-library/blob/master/CONTRIBUTING.md + https://github.com/testing-library/react-testing-library/blob/master/CONTRIBUTING.md [jest-dom]: https://github.com/gnapse/jest-dom diff --git a/package.json b/package.json index ba558b87..7be1db97 100644 --- a/package.json +++ b/package.json @@ -41,27 +41,27 @@ "author": "Kent C. Dodds (http://kentcdodds.com/)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.4.2", - "dom-testing-library": "^3.19.0" + "@babel/runtime": "^7.4.3", + "dom-testing-library": "^4.0.0" }, "devDependencies": { "@reach/router": "^1.2.1", - "@types/react": "^16.8.3", - "@types/react-dom": "^16.8.2", + "@types/react": "^16.8.14", + "@types/react-dom": "^16.8.4", "axios": "^0.18.0", "eslint-import-resolver-jest": "^2.1.1", "history": "^4.9.0", "intl": "^1.2.5", "jest-dom": "3.1.3", "jest-in-case": "^1.0.2", - "kcd-scripts": "1.1.2", + "kcd-scripts": "1.2.2", "react": "^16.8.6", "react-dom": "^16.8.6", "react-intl": "^2.8.0", - "react-redux": "6.0.1", + "react-redux": "7.0.2", "react-router": "^5.0.0", "react-router-dom": "^5.0.0", - "react-transition-group": "^2.7.1", + "react-transition-group": "^4.0.0", "redux": "^4.0.0" }, "peerDependencies": { @@ -83,10 +83,10 @@ ], "repository": { "type": "git", - "url": "https://github.com/kentcdodds/react-testing-library.git" + "url": "https://github.com/testing-library/react-testing-library.git" }, "bugs": { - "url": "https://github.com/kentcdodds/react-testing-library/issues" + "url": "https://github.com/testing-library/react-testing-library/issues" }, - "homepage": "https://github.com/kentcdodds/react-testing-library#readme" + "homepage": "https://github.com/testing-library/react-testing-library#readme" } diff --git a/src/__mocks__/axios.js b/src/__mocks__/axios.js index 9d70d624..30970385 100644 --- a/src/__mocks__/axios.js +++ b/src/__mocks__/axios.js @@ -5,4 +5,4 @@ module.exports = { // Note: // For now we don't need any other method (POST/PUT/PATCH), what we have already works fine. // We will add more methods only if we need to. -// For reference please read: https://github.com/kentcdodds/react-testing-library/issues/2 +// For reference please read: https://github.com/testing-library/react-testing-library/issues/2 From 960451b00196352fc3085a3d1bb233b5b85f454b Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 26 Apr 2019 11:39:33 -0600 Subject: [PATCH 029/327] docs: fix spectrum link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 05b243e5..aa9ed015 100644 --- a/README.md +++ b/README.md @@ -274,7 +274,7 @@ Links: [downloads-badge]: https://img.shields.io/npm/dm/react-testing-library.svg?style=flat-square [npmtrends]: http://www.npmtrends.com/react-testing-library [spectrum-badge]: https://withspectrum.github.io/badge/badge.svg -[spectrum]: https://spectrum.chat/react-testing-library +[spectrum]: https://spectrum.chat/testing-library [license-badge]: https://img.shields.io/npm/l/react-testing-library.svg?style=flat-square [license]: https://github.com/testing-library/react-testing-library/blob/master/LICENSE [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square From e66230598b46d7b6b6ac718e9a1e421624798681 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Sun, 19 May 2019 13:53:04 -0600 Subject: [PATCH 030/327] fix: bump dom-testing-library range Closes #373 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7be1db97..2eaee0fa 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.4.3", - "dom-testing-library": "^4.0.0" + "dom-testing-library": "^4.1.0" }, "devDependencies": { "@reach/router": "^1.2.1", From f539213acf8e2d9d0a2c8e652e67f064aab644e0 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 30 May 2019 11:33:51 -0600 Subject: [PATCH 031/327] chore(deps): upgrade all deps --- package.json | 16 ++++++++-------- src/__tests__/render.js | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 2eaee0fa..743023b3 100644 --- a/package.json +++ b/package.json @@ -41,27 +41,27 @@ "author": "Kent C. Dodds (http://kentcdodds.com/)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.4.3", + "@babel/runtime": "^7.4.5", "dom-testing-library": "^4.1.0" }, "devDependencies": { "@reach/router": "^1.2.1", - "@types/react": "^16.8.14", + "@types/react": "^16.8.19", "@types/react-dom": "^16.8.4", - "axios": "^0.18.0", + "axios": "^0.19.0", "eslint-import-resolver-jest": "^2.1.1", "history": "^4.9.0", "intl": "^1.2.5", - "jest-dom": "3.1.3", + "jest-dom": "3.4.0", "jest-in-case": "^1.0.2", - "kcd-scripts": "1.2.2", + "kcd-scripts": "1.4.0", "react": "^16.8.6", "react-dom": "^16.8.6", - "react-intl": "^2.8.0", - "react-redux": "7.0.2", + "react-intl": "^2.9.0", + "react-redux": "7.0.3", "react-router": "^5.0.0", "react-router-dom": "^5.0.0", - "react-transition-group": "^4.0.0", + "react-transition-group": "^4.1.0", "redux": "^4.0.0" }, "peerDependencies": { diff --git a/src/__tests__/render.js b/src/__tests__/render.js index 74adf5ea..f8bed704 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -57,7 +57,7 @@ test('returns baseElement which defaults to document.body', () => { it('cleansup document', () => { const spy = jest.fn() - const divId = 'my-div'; + const divId = 'my-div' class Test extends React.Component { componentWillUnmount() { @@ -66,7 +66,7 @@ it('cleansup document', () => { } render() { - return
+ return
} } From 23da68cf1428d2f0a51ad9581ffca2c77e1498a0 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 30 May 2019 11:37:14 -0600 Subject: [PATCH 032/327] feat: initial release of scoped package Reference: https://github.com/testing-library/dom-testing-library/issues/260 BREAKING CHANGE: You must update all imports from 'react-testing-library' to '@testing-library/react' --- package.json | 11 ++++++----- src/index.js | 4 ++-- typings/index.d.ts | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 743023b3..1889c416 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { - "name": "react-testing-library", - "version": "0.0.0-semantically-released", + "name": "@testing-library/react", + "version": "0.0.0", "description": "Simple and complete React DOM testing utilities that encourage good testing practices.", "main": "dist/index.js", - "module": "dist/react-testing-library.esm.js", + "module": "dist/@testing-library/react.esm.js", "typings": "typings/index.d.ts", "engines": { "node": ">=8" @@ -42,7 +42,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.4.5", - "dom-testing-library": "^4.1.0" + "@testing-library/dom": "^5.0.0" }, "devDependencies": { "@reach/router": "^1.2.1", @@ -79,7 +79,8 @@ "eslintIgnore": [ "node_modules", "coverage", - "dist" + "dist", + "*.d.ts" ], "repository": { "type": "git", diff --git a/src/index.js b/src/index.js index 379fccbc..8192e169 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,7 @@ import { prettyDOM, fireEvent as dtlFireEvent, configure as configureDTL, -} from 'dom-testing-library' +} from '@testing-library/dom' import act, {asyncAct} from './act-compat' configureDTL({ @@ -141,7 +141,7 @@ fireEvent.select = (node, init) => { } // just re-export everything from dom-testing-library -export * from 'dom-testing-library' +export * from '@testing-library/dom' export {render, cleanup, fireEvent, act} // NOTE: we're not going to export asyncAct because that's our own compatibility diff --git a/typings/index.d.ts b/typings/index.d.ts index 53e8caf5..6c51d23c 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1,6 +1,6 @@ -import {queries, BoundFunction} from 'dom-testing-library' +import {queries, BoundFunction} from '@testing-library/dom' -export * from 'dom-testing-library' +export * from '@testing-library/dom' interface Query extends Function { (container: HTMLElement, ...args: any[]): From 7a794ad5824d65819898a991cc608677f73e67f1 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 30 May 2019 11:43:13 -0600 Subject: [PATCH 033/327] chore: fix version for semantic release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1889c416..db896df1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@testing-library/react", - "version": "0.0.0", + "version": "0.0.0-semantically-released", "description": "Simple and complete React DOM testing utilities that encourage good testing practices.", "main": "dist/index.js", "module": "dist/@testing-library/react.esm.js", From 76d112cff16823be1874f1baa265dad5753c127c Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 30 May 2019 11:52:16 -0600 Subject: [PATCH 034/327] fix: docs pointed to old package --- README.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index aa9ed015..92b68b60 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,12 @@ primary guiding principle is: ```javascript // __tests__/fetch.js import React from 'react' -import {render, fireEvent, cleanup, waitForElement} from 'react-testing-library' +import { + render, + fireEvent, + cleanup, + waitForElement, +} from '@testing-library/react' // this adds custom jest matchers from jest-dom import 'jest-dom/extend-expect' @@ -145,7 +150,7 @@ This module is distributed via [npm][npm] which is bundled with [node][node] and should be installed as one of your project's `devDependencies`: ``` -npm install --save-dev react-testing-library +npm install --save-dev @testing-library/react ``` This library has `peerDependencies` listings for `react` and `react-dom`. @@ -269,17 +274,16 @@ Links: [build]: https://travis-ci.org/testing-library/react-testing-library [coverage-badge]: https://img.shields.io/codecov/c/github/testing-library/react-testing-library.svg?style=flat-square [coverage]: https://codecov.io/github/testing-library/react-testing-library -[version-badge]: https://img.shields.io/npm/v/react-testing-library.svg?style=flat-square -[package]: https://www.npmjs.com/package/react-testing-library -[downloads-badge]: https://img.shields.io/npm/dm/react-testing-library.svg?style=flat-square -[npmtrends]: http://www.npmtrends.com/react-testing-library +[version-badge]: https://img.shields.io/npm/v/@testing-library/react.svg?style=flat-square +[package]: https://www.npmjs.com/package/@testing-library/react +[downloads-badge]: https://img.shields.io/npm/dm/@testing-library/react.svg?style=flat-square +[npmtrends]: http://www.npmtrends.com/@testing-library/react [spectrum-badge]: https://withspectrum.github.io/badge/badge.svg [spectrum]: https://spectrum.chat/testing-library -[license-badge]: https://img.shields.io/npm/l/react-testing-library.svg?style=flat-square +[license-badge]: https://img.shields.io/npm/l/@testing-library/react.svg?style=flat-square [license]: https://github.com/testing-library/react-testing-library/blob/master/LICENSE [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square [prs]: http://makeapullrequest.com -[donate-badge]: https://img.shields.io/badge/$-support-green.svg?style=flat-square [coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square [coc]: https://github.com/testing-library/react-testing-library/blob/master/CODE_OF_CONDUCT.md [github-watch-badge]: https://img.shields.io/github/watchers/testing-library/react-testing-library.svg?style=social @@ -290,7 +294,6 @@ Links: [twitter-badge]: https://img.shields.io/twitter/url/https/github.com/testing-library/react-testing-library.svg?style=social [emojis]: https://github.com/all-contributors/all-contributors#emoji-key [all-contributors]: https://github.com/all-contributors/all-contributors -[set-immediate]: https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate [guiding-principle]: https://twitter.com/kentcdodds/status/977018512689455106 [bugs]: https://github.com/testing-library/react-testing-library/issues?q=is%3Aissue+is%3Aopen+label%3Abug+sort%3Acreated-desc [requests]: https://github.com/testing-library/react-testing-library/issues?q=is%3Aissue+sort%3Areactions-%2B1-desc+label%3Aenhancement+is%3Aopen From 3076b119172b8b7188603509bfe576b7d2914de3 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" Date: Mon, 10 Jun 2019 23:43:58 -0700 Subject: [PATCH 035/327] docs: add pascalduez as a contributor (#383) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 39f5a7e4..ea42809e 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -774,6 +774,15 @@ "contributions": [ "doc" ] + }, + { + "login": "pascalduez", + "name": "Pascal Duez", + "avatar_url": "https://avatars3.githubusercontent.com/u/335467?v=4", + "profile": "http://pascalduez.me", + "contributions": [ + "platform" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 92b68b60..12199fc4 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-79-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-80-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -219,7 +219,7 @@ Thanks goes to these people ([emoji key][emojis]): -
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
+
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
Pascal Duez
Pascal Duez

πŸ“¦
From 8e99f3cf99b76afbf2b20993745b802def3bb6c9 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 24 Jun 2019 20:46:02 +0200 Subject: [PATCH 036/327] fix: Specify baseElement without container (#394) * Add expected behavior of base element * Fix expected behavior of baseElement * Improve tests --- src/__tests__/multi-base.js | 41 +++++++++++++++++++++++++++++++++++++ src/__tests__/render.js | 2 -- src/index.js | 6 ++++-- 3 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 src/__tests__/multi-base.js diff --git a/src/__tests__/multi-base.js b/src/__tests__/multi-base.js new file mode 100644 index 00000000..03f0d93e --- /dev/null +++ b/src/__tests__/multi-base.js @@ -0,0 +1,41 @@ +import React from 'react' +import {render, cleanup} from '../' + +// these are created once per test suite and reused for each case +let treeA, treeB +beforeAll(() => { + treeA = document.createElement('div') + treeB = document.createElement('div') + document.body.appendChild(treeA) + document.body.appendChild(treeB) +}) + +afterAll(() => { + treeA.parentNode.removeChild(treeA) + treeB.parentNode.removeChild(treeB) +}) + +afterEach(cleanup) + +test('baseElement isolates trees from one another', () => { + const {getByText: getByTextInA} = render(
Jekyll
, { + baseElement: treeA, + }) + const {getByText: getByTextInB} = render(
Hyde
, { + baseElement: treeB, + }) + + expect(() => getByTextInA('Jekyll')).not.toThrow( + 'Unable to find an element with the text: Jekyll.', + ) + expect(() => getByTextInB('Jekyll')).toThrow( + 'Unable to find an element with the text: Jekyll.', + ) + + expect(() => getByTextInA('Hyde')).toThrow( + 'Unable to find an element with the text: Hyde.', + ) + expect(() => getByTextInB('Hyde')).not.toThrow( + 'Unable to find an element with the text: Hyde.', + ) +}) diff --git a/src/__tests__/render.js b/src/__tests__/render.js index f8bed704..4fdf8dc0 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -3,8 +3,6 @@ import React from 'react' import ReactDOM from 'react-dom' import {render, cleanup} from '../' -afterEach(cleanup) - test('renders div into document', () => { const ref = React.createRef() const {container} = render(
) diff --git a/src/index.js b/src/index.js index 8192e169..4565074b 100644 --- a/src/index.js +++ b/src/index.js @@ -30,11 +30,13 @@ function render( wrapper: WrapperComponent, } = {}, ) { - if (!container) { + if (!baseElement) { // default to document.body instead of documentElement to avoid output of potentially-large // head elements (such as JSS style blocks) in debug output baseElement = document.body - container = document.body.appendChild(document.createElement('div')) + } + if (!container) { + container = baseElement.appendChild(document.createElement('div')) } // we'll add it to the mounted containers regardless of whether it's actually From 566dd156af5598eda4cd9a8f05a546a649ddf8cc Mon Sep 17 00:00:00 2001 From: Minh Nguyen Date: Tue, 25 Jun 2019 13:53:55 +0100 Subject: [PATCH 037/327] fix(TS): export `Queries` interface (#396) --- typings/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 6c51d23c..e6573abe 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -12,7 +12,7 @@ interface Query extends Function { | null } -interface Queries { +export interface Queries { [T: string]: Query } From 5f260bc323a9314a458f475f371da88cebaaabf4 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2019 06:54:37 -0600 Subject: [PATCH 038/327] docs: add NMinhNguyen as a contributor (#397) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index ea42809e..d588d9c3 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -783,6 +783,15 @@ "contributions": [ "platform" ] + }, + { + "login": "NMinhNguyen", + "name": "Minh Nguyen", + "avatar_url": "https://avatars3.githubusercontent.com/u/2852660?v=4", + "profile": "https://twitter.com/minh_ngvyen", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 12199fc4..6d40ef24 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-80-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-81-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -219,7 +219,7 @@ Thanks goes to these people ([emoji key][emojis]): -
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
Pascal Duez
Pascal Duez

πŸ“¦
+
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
Pascal Duez
Pascal Duez

πŸ“¦
Minh Nguyen
Minh Nguyen

πŸ’»
From a51a86b3347ca55fe9944c48834fcf761ea55212 Mon Sep 17 00:00:00 2001 From: Minh Nguyen Date: Tue, 25 Jun 2019 15:19:45 +0100 Subject: [PATCH 039/327] fix(TS): use `Queries` from @testing-library/dom (#398) --- typings/index.d.ts | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index e6573abe..ddc5512a 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1,21 +1,7 @@ -import {queries, BoundFunction} from '@testing-library/dom' +import {queries, Queries, BoundFunction} from '@testing-library/dom' export * from '@testing-library/dom' -interface Query extends Function { - (container: HTMLElement, ...args: any[]): - | Error - | Promise - | Promise - | HTMLElement[] - | HTMLElement - | null -} - -export interface Queries { - [T: string]: Query -} - export type RenderResult = { container: HTMLElement baseElement: HTMLElement From 7dc3120ddb6c505ffb238beaec848eef27bd4b40 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 12 Jul 2019 10:57:24 -0600 Subject: [PATCH 040/327] chore: improve docs and simplify project. Also update deps --- README.md | 379 ++++++++++++++---- examples/.eslintrc.js | 15 - examples/README.md | 31 -- examples/__tests__/input-event.js | 65 --- .../__tests__/mock.react-transition-group.js | 49 --- examples/__tests__/reach-router.js | 70 ---- examples/__tests__/react-context.js | 58 --- examples/__tests__/react-intl.js | 45 --- examples/__tests__/react-redux.js | 106 ----- examples/__tests__/react-router.js | 71 ---- .../shallow.react-transition-group.js | 51 --- examples/__tests__/update-props.js | 33 -- examples/jest.config.js | 11 - examples/react-context.js | 18 - examples/react-hooks.js | 27 -- jest.config.js | 5 - other/jest.config.js | 9 - package.json | 25 +- src/__tests__/__snapshots__/fetch.js.snap | 12 - src/__tests__/act.js | 1 - src/__tests__/fetch.js | 50 --- src/__tests__/forms.js | 53 --- src/__tests__/render.js | 1 - src/__tests__/rerender.js | 5 +- tests/setup-env.js | 6 + 25 files changed, 306 insertions(+), 890 deletions(-) delete mode 100644 examples/.eslintrc.js delete mode 100644 examples/README.md delete mode 100644 examples/__tests__/input-event.js delete mode 100644 examples/__tests__/mock.react-transition-group.js delete mode 100644 examples/__tests__/reach-router.js delete mode 100644 examples/__tests__/react-context.js delete mode 100644 examples/__tests__/react-intl.js delete mode 100644 examples/__tests__/react-redux.js delete mode 100644 examples/__tests__/react-router.js delete mode 100644 examples/__tests__/shallow.react-transition-group.js delete mode 100644 examples/__tests__/update-props.js delete mode 100644 examples/jest.config.js delete mode 100644 examples/react-context.js delete mode 100644 examples/react-hooks.js delete mode 100644 jest.config.js delete mode 100644 other/jest.config.js delete mode 100644 src/__tests__/__snapshots__/fetch.js.snap delete mode 100644 src/__tests__/fetch.js delete mode 100644 src/__tests__/forms.js create mode 100644 tests/setup-env.js diff --git a/README.md b/README.md index 6d40ef24..28443956 100644 --- a/README.md +++ b/README.md @@ -55,18 +55,19 @@ practices.

- [The problem](#the-problem) - [This solution](#this-solution) -- [Example](#example) - [Installation](#installation) - [Examples](#examples) + - [Basic Example](#basic-example) + - [Complex Example](#complex-example) + - [More Examples](#more-examples) - [Hooks](#hooks) -- [Other Solutions](#other-solutions) - [Guiding Principles](#guiding-principles) -- [Contributors](#contributors) - [Docs](#docs) - [Issues](#issues) - [πŸ› Bugs](#-bugs) - [πŸ’‘ Feature Requests](#-feature-requests) - [❓ Questions](#-questions) +- [Contributors](#contributors) - [LICENSE](#license) @@ -91,87 +92,193 @@ primary guiding principle is: > [The more your tests resemble the way your software is used, the more > confidence they can give you.][guiding-principle] -## Example +## Installation + +This module is distributed via [npm][npm] which is bundled with [node][node] and +should be installed as one of your project's `devDependencies`: + +``` +npm install --save-dev @testing-library/react +``` + +This library has `peerDependencies` listings for `react` and `react-dom`. + +You may also be interested in installing `@testing-library/jest-dom` so you can +use [the custom jest matchers](https://github.com/testing-library/jest-dom). + +> [**Docs**](https://testing-library.com/react) + +## Examples + +### Basic Example -```javascript -// __tests__/fetch.js +```jsx +// hidden-message.js import React from 'react' -import { - render, - fireEvent, - cleanup, - waitForElement, -} from '@testing-library/react' -// this adds custom jest matchers from jest-dom -import 'jest-dom/extend-expect' - -// the mock lives in a __mocks__ directory -// to know more about manual mocks, access: https://jestjs.io/docs/en/manual-mocks -import axiosMock from 'axios' -import Fetch from '../fetch' // see the tests for a full implementation - -// automatically unmount and cleanup DOM after the test is finished. -afterEach(cleanup) - -test('Fetch makes an API call and displays the greeting when load-greeting is clicked', async () => { - // Arrange - axiosMock.get.mockResolvedValueOnce({data: {greeting: 'hello there'}}) - const url = '/greeting' - const {getByText, getByTestId, container, asFragment} = render( - , + +// NOTE: React Testing Library works with React Hooks _and_ classes just as well +// and your tests will be the same however you write your components. +function HiddenMessage({children}) { + const [showMessage, setShowMessage] = React.useState(false) + return ( +
+ + setShowMessage(e.target.checked)} + checked={showMessage} + /> + {showMessage ? children : null} +
) +} + +export default HiddenMessage + +// __tests__/hidden-message.js +// these imports are something you'd normally configure Jest to import for you +// automatically. Learn more in the setup docs: https://testing-library.com/docs/react-testing-library/setup#cleanup +import '@testing-library/react/cleanup-after-each' +import '@testing-library/jest-dom/extend-expect' +// NOTE: jest-dom adds handy assertions to Jest and is recommended, but not required - // Act - fireEvent.click(getByText(/load greeting/i)) +import React from 'react' +import {render, fireEvent} from '@testing-library/react' +import HiddenMessage from '../hidden-message' - // Let's wait until our mocked `get` request promise resolves and - // the component calls setState and re-renders. - // getByTestId throws an error if it cannot find an element with the given ID - // and waitForElement will wait until the callback doesn't throw an error - const greetingTextNode = await waitForElement(() => - getByTestId('greeting-text'), +test('shows the children when the checkbox is checked', () => { + const testMessage = 'Test Message' + const {queryByText, getByLabelText, getByText} = render( + {testMessage}, ) - // Assert - expect(axiosMock.get).toHaveBeenCalledTimes(1) - expect(axiosMock.get).toHaveBeenCalledWith(url) - expect(getByTestId('greeting-text')).toHaveTextContent('hello there') - expect(getByTestId('ok-button')).toHaveAttribute('disabled') - // snapshots work great with regular DOM nodes! - expect(container.firstChild).toMatchSnapshot() - // you can also get a `DocumentFragment`, which is useful if you want to compare nodes across renders - expect(asFragment()).toMatchSnapshot() + // query* functions will return the element or null if it cannot be found + // get* functions will return the element or throw an error if it cannot be found + expect(queryByText(testMessage)).toBeNull() + + // the queries can accept a regex to make your selectors more resilient to content tweaks and changes. + fireEvent.click(getByLabelText(/show/i)) + + // .toBeInTheDocument() is an assertion that comes from jest-dom + // otherwise you could use .toBeDefined() + expect(getByText(testMessage)).toBeInTheDocument() }) ``` -## Installation - -This module is distributed via [npm][npm] which is bundled with [node][node] and -should be installed as one of your project's `devDependencies`: +### Complex Example -``` -npm install --save-dev @testing-library/react -``` +```jsx +// login.js +import React from 'react' -This library has `peerDependencies` listings for `react` and `react-dom`. +function Login() { + const [state, setState] = React.useReducer((s, a) => ({...s, ...a}), { + resolved: false, + loading: false, + error: null, + }) + + function handleSubmit(event) { + event.preventDefault() + const {usernameInput, passwordInput} = event.target.elements + + setState({loading: true, resolved: false, error: null}) + + window + .fetch('/api/login', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ + username: usernameInput.value, + password: passwordInput.value, + }), + }) + .then(r => r.json()) + .then( + user => { + setState({loading: false, resolved: true, error: null}) + window.localStorage.setItem('token', user.token) + }, + error => { + setState({loading: false, resolved: false, error: error.message}) + }, + ) + } + + return ( +
+
+
+ + +
+
+ + +
+ +
+ {state.error ?
{state.error.message}
: null} + {state.success ? ( +
Congrats! You're signed in!
+ ) : null} +
+ ) +} -You may also be interested in installing `jest-dom` so you can use -[the custom jest matchers](https://github.com/gnapse/jest-dom#readme). +export default Login -> [**Docs**](https://testing-library.com/docs/react-testing-library/intro) +// __tests__/login.js +// again, these first two imports are something you'd normally handle in +// your testing framework configuration rather than importing them in every file. +import '@testing-library/react/cleanup-after-each' +import '@testing-library/jest-dom/extend-expect' +import React from 'react' +import {render, fireEvent} from '@testing-library/react' +import Login from '../login' + +test('allows the user to login successfully', async () => { + // mock out window.fetch for the test + const fakeUserResponse = {token: 'fake_user_token'} + jest.spyOn(window, 'fetch').mockImplementationOnce(() => { + return Promise.resolve({ + json: () => Promise.resolve(fakeUserResponse), + }) + }) + + const {getByLabelText, getByText, findByRole} = render() + + // fill out the form + fireEvent.change(getByLabelText(/username/i), {target: {value: 'chuck'}}) + fireEvent.change(getBylabelText(/password/i), {target: {value: 'norris'}}) + + fireEvent.click(getByText(/submit/i)) + + // just like a manual tester, we'll instruct our test to wait for the alert + // to show up before continuing with our assertions. + const alert = await findByRole('alert') + + // .toHaveTextContent() comes from jest-dom's assertions + // otherwise you could use expect(alert.textContent).toMatch(/congrats/i) + // but jest-dom will give you better error messages which is why it's recommended + expect(alert).toHaveTextContent(/congrats/i) + expect(window.localStorage.getItem('token')).toEqual(fakeUserReponse.token) +}) +``` -## Examples +### More Examples > We're in the process of moving examples to the > [docs site](https://testing-library.com/docs/example-codesandbox) You'll find runnable examples of testing with different libraries in -[the `examples` directory](https://github.com/testing-library/react-testing-library/blob/master/examples). +[the `react-testing-library-examples` codesandbox](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples). Some included are: -- [`react-redux`](https://github.com/testing-library/react-testing-library/blob/master/examples/__tests__/react-redux.js) -- [`react-router`](https://github.com/testing-library/react-testing-library/blob/master/examples/__tests__/react-router.js) -- [`react-context`](https://github.com/testing-library/react-testing-library/blob/master/examples/__tests__/react-context.js) +- [`react-redux`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-redux.js&previewwindow=tests) +- [`react-router`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-router.js&previewwindow=tests) +- [`react-context`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-context.js&previewwindow=tests) You can also find react-testing-library examples at [react-testing-examples.com](https://react-testing-examples.com/jest-rtl/). @@ -181,14 +288,10 @@ You can also find react-testing-library examples at If you are interested in testing a custom hook, check out [react-hooks-testing-library][react-hooks-testing-library]. -## Other Solutions - -In preparing this project, -[I tweeted about it](https://twitter.com/kentcdodds/status/974278185540964352) -and [Sune Simonsen](https://github.com/sunesimonsen) -[took up the challenge](https://twitter.com/sunesimonsen/status/974784783908818944). -We had different ideas of what to include in the library, so I decided to create -this one instead. +> NOTE it is not recommended to test single-use custom hooks in isolation from +> the components where it's being used. It's better to test the component that's +> using the hook rather than the hook itself. The react-hooks-testing-library is +> intended to be used for reusable hooks/libraries. ## Guiding Principles @@ -213,19 +316,6 @@ principles: At the end of the day, what we want is for this library to be pretty light-weight, simple, and understandable. -## Contributors - -Thanks goes to these people ([emoji key][emojis]): - - - -
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
Pascal Duez
Pascal Duez

πŸ“¦
Minh Nguyen
Minh Nguyen

πŸ’»
- - - -This project follows the [all-contributors][all-contributors] specification. -Contributions of any kind welcome! - ## Docs [**Read The Docs**](https://testing-library.com/react) | @@ -258,14 +348,129 @@ instead of filing an issue on GitHub. - [Reactiflux on Discord][reactiflux] - [Stack Overflow][stackoverflow] +## Contributors + +Thanks goes to these people ([emoji key][emojis]): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
Pascal Duez
Pascal Duez

πŸ“¦
Minh Nguyen
Minh Nguyen

πŸ’»
+ + + +This project follows the [all-contributors][all-contributors] specification. +Contributions of any kind welcome! + ## LICENSE MIT - - [npm]: https://www.npmjs.com/ diff --git a/examples/.eslintrc.js b/examples/.eslintrc.js deleted file mode 100644 index 67ff778c..00000000 --- a/examples/.eslintrc.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = { - // we have to do this so our tests can reference 'react-testing-library' - overrides: [ - { - files: ['**/__tests__/**'], - settings: { - 'import/resolver': { - jest: { - jestConfigFile: require.resolve('./jest.config.js'), - }, - }, - }, - }, - ], -} diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index 44e36304..00000000 --- a/examples/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Examples - -Here we have some examples for you to know how to not only use -`react-testing-library` but also in general how to test common scenarios that -pop up with React. Check out the `__tests__` directory for the different -examples. - -## Setup - -The examples have a unique jest/eslint set up so the test files will resemble -how they might appear in your project. (You'll see in the tests that we can -`import {render} from 'react-testing-library'`). - -## Contribute - -We're always happy to accept contributions to the examples. Can't have too many -of these as there are TONs of different ways to test React. Examples of testing -components that use different and common libraries is always welcome. Try to -keep examples simple enough for people to understand the main thing we're trying -to demonstrate from the example. - -Please follow the guidelines found in [CONTRIBUTING.md][contributing] to set up -the project. - -To run the tests, you can run `npm test examples`, or if you're working on a -specific example, you can run `npm test name-of-your-file`. This will put you -into Jest's interactive watch mode with a filter based on the name you provided. - -[contributing]: - https://github.com/testing-library/react-testing-library/blob/master/CONTRIBUTING.md -[jest-dom]: https://github.com/gnapse/jest-dom diff --git a/examples/__tests__/input-event.js b/examples/__tests__/input-event.js deleted file mode 100644 index 0e1c5305..00000000 --- a/examples/__tests__/input-event.js +++ /dev/null @@ -1,65 +0,0 @@ -import React from 'react' -import {render, fireEvent, cleanup} from 'react-testing-library' - -class CostInput extends React.Component { - state = { - value: '', - } - - removeDollarSign = value => (value[0] === '$' ? value.slice(1) : value) - getReturnValue = value => (value === '' ? '' : `$${value}`) - handleChange = ev => { - ev.preventDefault() - const inputtedValue = ev.currentTarget.value - const noDollarSign = this.removeDollarSign(inputtedValue) - if (isNaN(noDollarSign)) return - this.setState({value: this.getReturnValue(noDollarSign)}) - } - - render() { - return ( - - ) - } -} - -const setup = () => { - const utils = render() - const input = utils.getByLabelText('cost-input') - return { - input, - ...utils, - } -} - -afterEach(cleanup) - -test('It should keep a $ in front of the input', () => { - const {input} = setup() - fireEvent.change(input, {target: {value: '23'}}) - expect(input.value).toBe('$23') -}) -test('It should allow a $ to be in the input when the value is changed', () => { - const {input} = setup() - fireEvent.change(input, {target: {value: '$23.0'}}) - expect(input.value).toBe('$23.0') -}) - -test('It should not allow letters to be inputted', () => { - const {input} = setup() - expect(input.value).toBe('') // empty before - fireEvent.change(input, {target: {value: 'Good Day'}}) - expect(input.value).toBe('') //empty after -}) - -test('It should allow the $ to be deleted', () => { - const {input} = setup() - fireEvent.change(input, {target: {value: '23'}}) - expect(input.value).toBe('$23') // need to make a change so React registers "" as a change - fireEvent.change(input, {target: {value: ''}}) - expect(input.value).toBe('') -}) diff --git a/examples/__tests__/mock.react-transition-group.js b/examples/__tests__/mock.react-transition-group.js deleted file mode 100644 index 83894534..00000000 --- a/examples/__tests__/mock.react-transition-group.js +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react' -import {CSSTransition} from 'react-transition-group' -import {render, fireEvent, cleanup} from 'react-testing-library' - -function Fade({children, ...props}) { - return ( - - {children} - - ) -} - -class HiddenMessage extends React.Component { - state = {show: this.props.initialShow || false} - toggle = () => { - this.setState(({show}) => ({show: !show})) - } - render() { - return ( -
- - -
Hello world
-
-
- ) - } -} - -afterEach(cleanup) - -jest.mock('react-transition-group', () => { - const FakeTransition = jest.fn(({children}) => children) - const FakeCSSTransition = jest.fn(props => - props.in ? {props.children} : null, - ) - return {CSSTransition: FakeCSSTransition, Transition: FakeTransition} -}) - -test('you can mock things with jest.mock', () => { - const {getByText, queryByText} = render() - expect(getByText('Hello world')).toBeTruthy() // we just care it exists - // hide the message - fireEvent.click(getByText('Toggle')) - // in the real world, the CSSTransition component would take some time - // before finishing the animation which would actually hide the message. - // So we've mocked it out for our tests to make it happen instantly - expect(queryByText('Hello World')).toBeNull() // we just care it doesn't exist -}) diff --git a/examples/__tests__/reach-router.js b/examples/__tests__/reach-router.js deleted file mode 100644 index 61aae97d..00000000 --- a/examples/__tests__/reach-router.js +++ /dev/null @@ -1,70 +0,0 @@ -import React from 'react' -import {render, cleanup} from 'react-testing-library' -import { - Router, - Link, - createHistory, - createMemorySource, - LocationProvider, -} from '@reach/router' -import 'jest-dom/extend-expect' - -const About = () =>
You are on the about page
-const Home = () =>
You are home
-const NoMatch = () =>
No match
- -function App() { - return ( -
- Home - About - - - - - -
- ) -} - -// Ok, so here's what your tests might look like - -afterEach(cleanup) - -// this is a handy function that I would utilize for any component -// that relies on the router being in context -function renderWithRouter( - ui, - {route = '/', history = createHistory(createMemorySource(route))} = {}, -) { - return { - ...render({ui}), - // adding `history` to the returned utilities to allow us - // to reference it in our tests (just try to avoid using - // this to test implementation details). - history, - } -} - -test('full app rendering/navigating', async () => { - const { - container, - history: {navigate}, - } = renderWithRouter() - const appContainer = container - // normally I'd use a data-testid, but just wanted to show this is also possible - expect(appContainer.innerHTML).toMatch('You are home') - - // with reach-router we don't need to simulate a click event, we can just transition - // to the page using the navigate function returned from the history object. - await navigate('/about') - expect(container.innerHTML).toMatch('You are on the about page') -}) - -test('landing on a bad page', () => { - const {container} = renderWithRouter(, { - route: '/something-that-does-not-match', - }) - // normally I'd use a data-testid, but just wanted to show this is also possible - expect(container.innerHTML).toMatch('No match') -}) diff --git a/examples/__tests__/react-context.js b/examples/__tests__/react-context.js deleted file mode 100644 index b87c61c9..00000000 --- a/examples/__tests__/react-context.js +++ /dev/null @@ -1,58 +0,0 @@ -import React from 'react' -import {render, cleanup} from 'react-testing-library' -import 'jest-dom/extend-expect' -import {NameContext, NameProvider, NameConsumer} from '../react-context' - -afterEach(cleanup) - -/** - * Test default values by rendering a context consumer without a - * matching provider - */ -test('NameConsumer shows default value', () => { - const {getByText} = render() - expect(getByText(/^My Name Is:/)).toHaveTextContent('My Name Is: Unknown') -}) - -/** - * To test a component tree that uses a context consumer but not the provider, - * wrap the tree with a matching provider - */ -test('NameConsumer shows value from provider', () => { - const tree = ( - - - - ) - const {getByText} = render(tree) - expect(getByText(/^My Name Is:/)).toHaveTextContent('My Name Is: C3P0') -}) - -/** - * To test a component that provides a context value, render a matching - * consumer as the child - */ -test('NameProvider composes full name from first, last', () => { - const tree = ( - - - {value => Received: {value}} - - - ) - const {getByText} = render(tree) - expect(getByText(/^Received:/).textContent).toBe('Received: Boba Fett') -}) - -/** - * A tree containing both a provider and consumer can be rendered normally - */ -test('NameProvider/Consumer shows name of character', () => { - const tree = ( - - - - ) - const {getByText} = render(tree) - expect(getByText(/^My Name Is:/).textContent).toBe('My Name Is: Leia Organa') -}) diff --git a/examples/__tests__/react-intl.js b/examples/__tests__/react-intl.js deleted file mode 100644 index 48fe0e0f..00000000 --- a/examples/__tests__/react-intl.js +++ /dev/null @@ -1,45 +0,0 @@ -import React from 'react' -import 'jest-dom/extend-expect' -import {render, cleanup, getByTestId} from 'react-testing-library' -import {IntlProvider, FormattedDate} from 'react-intl' -import IntlPolyfill from 'intl' -import 'intl/locale-data/jsonp/pt' - -const setupTests = () => { - // Test enviroment run as server enviroment and should have polyfill to locale - // https://formatjs.io/guides/runtime-environments/#server - if (global.Intl) { - Intl.NumberFormat = IntlPolyfill.NumberFormat - Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat - } else { - global.Intl = require('intl') - } -} - -const FormatDateView = () => { - return ( -
- -
- ) -} - -const renderWithReactIntl = component => { - return { - ...render({component}), - } -} - -setupTests() -afterEach(cleanup) - -test('it should render FormattedDate and have a formated pt date', () => { - const {container} = renderWithReactIntl() - expect(getByTestId(container, 'date-display')).toHaveTextContent('11/03/2019') -}) diff --git a/examples/__tests__/react-redux.js b/examples/__tests__/react-redux.js deleted file mode 100644 index acfb3369..00000000 --- a/examples/__tests__/react-redux.js +++ /dev/null @@ -1,106 +0,0 @@ -import React from 'react' -import {createStore} from 'redux' -import {Provider, connect} from 'react-redux' -import {render, fireEvent, cleanup} from 'react-testing-library' - -// counter.js -class Counter extends React.Component { - increment = () => { - this.props.dispatch({type: 'INCREMENT'}) - } - - decrement = () => { - this.props.dispatch({type: 'DECREMENT'}) - } - - render() { - return ( -
-

Counter

-
- - {this.props.count} - -
-
- ) - } -} - -// normally this would be: -// export default connect(state => ({count: state.count}))(Counter) -// but for this test we'll give it a variable name -// because we're doing this all in one file -const ConnectedCounter = connect(state => ({count: state.count}))(Counter) - -// app.js -function reducer(state = {count: 0}, action) { - switch (action.type) { - case 'INCREMENT': - return { - count: state.count + 1, - } - case 'DECREMENT': - return { - count: state.count - 1, - } - default: - return state - } -} - -// normally here you'd do: -// const store = createStore(reducer) -// ReactDOM.render( -// -// -// , -// document.getElementById('root'), -// ) -// but for this test we'll umm... not do that :) - -// Now here's what your test will look like: - -afterEach(cleanup) - -// this is a handy function that I normally make available for all my tests -// that deal with connected components. -// you can provide initialState or the entire store that the ui is rendered with -function renderWithRedux( - ui, - {initialState, store = createStore(reducer, initialState)} = {}, -) { - return { - ...render({ui}), - // adding `store` to the returned utilities to allow us - // to reference it in our tests (just try to avoid using - // this to test implementation details). - store, - } -} - -test('can render with redux with defaults', () => { - const {getByTestId, getByText} = renderWithRedux() - fireEvent.click(getByText('+')) - expect(getByTestId('count-value').textContent).toBe('1') -}) - -test('can render with redux with custom initial state', () => { - const {getByTestId, getByText} = renderWithRedux(, { - initialState: {count: 3}, - }) - fireEvent.click(getByText('-')) - expect(getByTestId('count-value').textContent).toBe('2') -}) - -test('can render with redux with custom store', () => { - // this is a silly store that can never be changed - const store = createStore(() => ({count: 1000})) - const {getByTestId, getByText} = renderWithRedux(, { - store, - }) - fireEvent.click(getByText('+')) - expect(getByTestId('count-value').textContent).toBe('1000') - fireEvent.click(getByText('-')) - expect(getByTestId('count-value').textContent).toBe('1000') -}) diff --git a/examples/__tests__/react-router.js b/examples/__tests__/react-router.js deleted file mode 100644 index 02f4c7d2..00000000 --- a/examples/__tests__/react-router.js +++ /dev/null @@ -1,71 +0,0 @@ -import React from 'react' -import {withRouter} from 'react-router' -import {Link, Route, Router, Switch} from 'react-router-dom' -import {createMemoryHistory} from 'history' -import {render, fireEvent, cleanup} from 'react-testing-library' - -const About = () =>
You are on the about page
-const Home = () =>
You are home
-const NoMatch = () =>
No match
- -const LocationDisplay = withRouter(({location}) => ( -
{location.pathname}
-)) - -function App() { - return ( -
- Home - About - - - - - - -
- ) -} - -// Ok, so here's what your tests might look like - -afterEach(cleanup) - -// this is a handy function that I would utilize for any component -// that relies on the router being in context -function renderWithRouter( - ui, - {route = '/', history = createMemoryHistory({initialEntries: [route]})} = {}, -) { - return { - ...render({ui}), - // adding `history` to the returned utilities to allow us - // to reference it in our tests (just try to avoid using - // this to test implementation details). - history, - } -} - -test('full app rendering/navigating', () => { - const {container, getByText} = renderWithRouter() - // normally I'd use a data-testid, but just wanted to show this is also possible - expect(container.innerHTML).toMatch('You are home') - const leftClick = {button: 0} - fireEvent.click(getByText(/about/i), leftClick) - // normally I'd use a data-testid, but just wanted to show this is also possible - expect(container.innerHTML).toMatch('You are on the about page') -}) - -test('landing on a bad page', () => { - const {container} = renderWithRouter(, { - route: '/something-that-does-not-match', - }) - // normally I'd use a data-testid, but just wanted to show this is also possible - expect(container.innerHTML).toMatch('No match') -}) - -test('rendering a component that uses withRouter', () => { - const route = '/some-route' - const {getByTestId} = renderWithRouter(, {route}) - expect(getByTestId('location-display').textContent).toBe(route) -}) diff --git a/examples/__tests__/shallow.react-transition-group.js b/examples/__tests__/shallow.react-transition-group.js deleted file mode 100644 index fe7ddead..00000000 --- a/examples/__tests__/shallow.react-transition-group.js +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react' -import {CSSTransition} from 'react-transition-group' -import {render, fireEvent, cleanup} from 'react-testing-library' - -function Fade({children, ...props}) { - return ( - - {children} - - ) -} - -class HiddenMessage extends React.Component { - state = {show: this.props.initialShow || false} - toggle = () => { - this.setState(({show}) => ({show: !show})) - } - render() { - return ( -
- - -
Hello world
-
-
- ) - } -} - -afterEach(cleanup) - -jest.mock('react-transition-group', () => { - const FakeCSSTransition = jest.fn(() => null) - return {CSSTransition: FakeCSSTransition} -}) - -test('you can mock things with jest.mock', () => { - const {getByText} = render() - const context = expect.any(Object) - const children = expect.any(Object) - const defaultProps = {children, timeout: 1000, className: 'fade'} - expect(CSSTransition).toHaveBeenCalledWith( - {in: true, ...defaultProps}, - context, - ) - fireEvent.click(getByText(/toggle/i)) - expect(CSSTransition).toHaveBeenCalledWith( - {in: true, ...defaultProps}, - expect.any(Object), - ) -}) diff --git a/examples/__tests__/update-props.js b/examples/__tests__/update-props.js deleted file mode 100644 index c245b9ff..00000000 --- a/examples/__tests__/update-props.js +++ /dev/null @@ -1,33 +0,0 @@ -// This is an example of how to update the props of a rendered component. -// the basic idea is to simply call `render` again and provide the same container -// that your first call created for you. - -import React from 'react' -import {render, cleanup} from 'react-testing-library' - -let idCounter = 1 - -class NumberDisplay extends React.Component { - id = idCounter++ // to ensure we don't remount a different instance - render() { - return ( -
- {this.props.number} - {this.id} -
- ) - } -} - -afterEach(cleanup) - -test('calling render with the same component on the same container does not remount', () => { - const {getByTestId, rerender} = render() - expect(getByTestId('number-display').textContent).toBe('1') - - // re-render the same component with different props - rerender() - expect(getByTestId('number-display').textContent).toBe('2') - - expect(getByTestId('instance-id').textContent).toBe('1') -}) diff --git a/examples/jest.config.js b/examples/jest.config.js deleted file mode 100644 index 8dc4330d..00000000 --- a/examples/jest.config.js +++ /dev/null @@ -1,11 +0,0 @@ -const jestConfig = require('kcd-scripts/jest') - -module.exports = Object.assign(jestConfig, { - rootDir: __dirname, - roots: [__dirname], - displayName: 'example', - moduleNameMapper: { - // this is just here so our examples look like they would in a real project - 'react-testing-library': require.resolve('../src'), - }, -}) diff --git a/examples/react-context.js b/examples/react-context.js deleted file mode 100644 index 4ec24f6c..00000000 --- a/examples/react-context.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react' - -const NameContext = React.createContext('Unknown') - -const NameProvider = ({children, first, last}) => { - const fullName = `${first} ${last}` - return ( - {children} - ) -} - -const NameConsumer = () => ( - - {value =>
My Name Is: {value}
} -
-) - -export {NameContext, NameConsumer, NameProvider} diff --git a/examples/react-hooks.js b/examples/react-hooks.js deleted file mode 100644 index 2ef92b7d..00000000 --- a/examples/react-hooks.js +++ /dev/null @@ -1,27 +0,0 @@ -import {useState, useEffect} from 'react' - -export function useCounter({initialCount = 0, step = 1} = {}) { - const [count, setCount] = useState(initialCount) - const increment = () => setCount(c => c + step) - const decrement = () => setCount(c => c - step) - return {count, increment, decrement} -} - -export function useDocumentTitle(title) { - const [originalTitle, setOriginalTitle] = useState(document.title) - useEffect(() => { - setOriginalTitle(document.title) - document.title = title - return () => { - document.title = originalTitle - } - }, [title]) -} - -export function useCall(callback, deps) { - useEffect(() => { - callback() - }, deps) -} - -/* eslint react-hooks/exhaustive-deps:0 */ diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index 23133e67..00000000 --- a/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const jestConfig = require('kcd-scripts/jest') - -module.exports = Object.assign(jestConfig, { - displayName: 'library', -}) diff --git a/other/jest.config.js b/other/jest.config.js deleted file mode 100644 index 3efec572..00000000 --- a/other/jest.config.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - coverageDirectory: '../coverage', - collectCoverageFrom: [ - '**/src/**/*.js', - '!**/__tests__/**', - '!**/node_modules/**', - ], - projects: ['./', './examples'], -} diff --git a/package.json b/package.json index db896df1..c30e9282 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "scripts": { "build": "kcd-scripts build && kcd-scripts build --bundle --no-clean", "lint": "kcd-scripts lint", - "test": "kcd-scripts test --config=other/jest.config.js", + "test": "kcd-scripts test", "test:update": "npm test -- --updateSnapshot --coverage", "validate": "kcd-scripts validate", "setup": "npm install && npm run validate -s" @@ -41,28 +41,17 @@ "author": "Kent C. Dodds (http://kentcdodds.com/)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.4.5", - "@testing-library/dom": "^5.0.0" + "@babel/runtime": "^7.5.4", + "@testing-library/dom": "^5.5.4" }, "devDependencies": { "@reach/router": "^1.2.1", - "@types/react": "^16.8.19", + "@testing-library/jest-dom": "^4.0.0", + "@types/react": "^16.8.23", "@types/react-dom": "^16.8.4", - "axios": "^0.19.0", - "eslint-import-resolver-jest": "^2.1.1", - "history": "^4.9.0", - "intl": "^1.2.5", - "jest-dom": "3.4.0", - "jest-in-case": "^1.0.2", - "kcd-scripts": "1.4.0", + "kcd-scripts": "1.5.2", "react": "^16.8.6", - "react-dom": "^16.8.6", - "react-intl": "^2.9.0", - "react-redux": "7.0.3", - "react-router": "^5.0.0", - "react-router-dom": "^5.0.0", - "react-transition-group": "^4.1.0", - "redux": "^4.0.0" + "react-dom": "^16.8.6" }, "peerDependencies": { "react": "*", diff --git a/src/__tests__/__snapshots__/fetch.js.snap b/src/__tests__/__snapshots__/fetch.js.snap deleted file mode 100644 index 69e0e57b..00000000 --- a/src/__tests__/__snapshots__/fetch.js.snap +++ /dev/null @@ -1,12 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Fetch makes an API call and displays the greeting when load-greeting is clicked 1`] = ` -
- - - hello there - -
-`; diff --git a/src/__tests__/act.js b/src/__tests__/act.js index 5f3cbfb5..00be96f7 100644 --- a/src/__tests__/act.js +++ b/src/__tests__/act.js @@ -1,4 +1,3 @@ -import 'jest-dom/extend-expect' import React from 'react' import {render, cleanup, fireEvent} from '../' diff --git a/src/__tests__/fetch.js b/src/__tests__/fetch.js deleted file mode 100644 index c607508c..00000000 --- a/src/__tests__/fetch.js +++ /dev/null @@ -1,50 +0,0 @@ -import React from 'react' -import axiosMock from 'axios' -import {render, fireEvent, cleanup, wait} from '../' - -afterEach(cleanup) - -// instead of importing it, we'll define it inline here -// import Fetch from '../fetch' - -class Fetch extends React.Component { - state = {} - componentDidUpdate(prevProps) { - if (this.props.url !== prevProps.url) { - this.fetch() - } - } - fetch = async () => { - const response = await axiosMock.get(this.props.url) - this.setState({data: response.data}) - } - render() { - const {data} = this.state - return ( -
- - {data ? {data.greeting} : null} -
- ) - } -} - -test('Fetch makes an API call and displays the greeting when load-greeting is clicked', async () => { - // Arrange - axiosMock.get.mockResolvedValueOnce({data: {greeting: 'hello there'}}) - const url = '/greeting' - const {container, getByText} = render() - - // Act - fireEvent.click(getByText('Fetch')) - - await wait() - - // Assert - expect(axiosMock.get).toHaveBeenCalledTimes(1) - expect(axiosMock.get).toHaveBeenCalledWith(url) - // this assertion is funny because if the textContent were not "hello there" - // then the `getByText` would throw anyway... πŸ€” - expect(getByText('hello there').textContent).toBe('hello there') - expect(container.firstChild).toMatchSnapshot() -}) diff --git a/src/__tests__/forms.js b/src/__tests__/forms.js deleted file mode 100644 index f3b7ebe9..00000000 --- a/src/__tests__/forms.js +++ /dev/null @@ -1,53 +0,0 @@ -import React from 'react' -import {render, fireEvent, cleanup} from '../' - -afterEach(cleanup) - -function Login({onSubmit}) { - return ( -
-
{ - e.preventDefault() - const {username, password} = e.target.elements - onSubmit({ - username: username.value, - password: password.value, - }) - }} - > - - - - - -
-
- ) -} - -test('login form submits', () => { - const fakeUser = {username: 'jackiechan', password: 'hiya! πŸ₯‹'} - const handleSubmit = jest.fn() - const {getByLabelText, getByText} = render() - - const usernameNode = getByLabelText(/username/i) - const passwordNode = getByLabelText(/password/i) - const submitButtonNode = getByText(/submit/i) - - // Act - usernameNode.value = fakeUser.username - passwordNode.value = fakeUser.password - fireEvent.click(submitButtonNode) - - // Assert - expect(handleSubmit).toHaveBeenCalledTimes(1) - expect(handleSubmit).toHaveBeenCalledWith(fakeUser) -}) - -/* eslint jsx-a11y/label-has-for:0, jsx-a11y/aria-proptypes:0 */ diff --git a/src/__tests__/render.js b/src/__tests__/render.js index 4fdf8dc0..e8f25d3f 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -1,4 +1,3 @@ -import 'jest-dom/extend-expect' import React from 'react' import ReactDOM from 'react-dom' import {render, cleanup} from '../' diff --git a/src/__tests__/rerender.js b/src/__tests__/rerender.js index a35144b5..ff30ffd5 100644 --- a/src/__tests__/rerender.js +++ b/src/__tests__/rerender.js @@ -1,8 +1,5 @@ import React from 'react' -import {render, cleanup} from '../' -import 'jest-dom/extend-expect' - -afterEach(cleanup) +import {render} from '../' test('rerender will re-render the element', () => { const Greeting = props =>
{props.message}
diff --git a/tests/setup-env.js b/tests/setup-env.js new file mode 100644 index 00000000..d1d6d891 --- /dev/null +++ b/tests/setup-env.js @@ -0,0 +1,6 @@ +import '@testing-library/jest-dom/extend-expect' + +afterEach(() => { + // have to do a dynamic import so we don't mess up jest mocking for old-act.js + require('../src').cleanup() +}) From 94b4e8b3ede2f25fde90fe5e8eb6da983ec85425 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 12 Jul 2019 10:58:36 -0600 Subject: [PATCH 041/327] chore: version range kcd-scripts --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c30e9282..8280be55 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@testing-library/jest-dom": "^4.0.0", "@types/react": "^16.8.23", "@types/react-dom": "^16.8.4", - "kcd-scripts": "1.5.2", + "kcd-scripts": "^1.5.2", "react": "^16.8.6", "react-dom": "^16.8.6" }, From 4ada26bcb9ae7dfc6ce22f380a7459ace40494f7 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 12 Jul 2019 11:04:44 -0600 Subject: [PATCH 042/327] fix(build output): the dist directory no longer includes tests This happened when I updated kcd-scripts, but I forgot to make a release commit message for it. --- other/manual-releases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/manual-releases.md b/other/manual-releases.md index 1e9a7365..e19f34cf 100644 --- a/other/manual-releases.md +++ b/other/manual-releases.md @@ -41,4 +41,4 @@ change is to release a new patch version. Reference: # ``` -The number of times we've had to do a manual release is: 2 +The number of times we've had to do a manual release is: 3 From b1e5b3a72ec339cf2d86a235518f1d814fea14cb Mon Sep 17 00:00:00 2001 From: LiaoJimmy Date: Sun, 14 Jul 2019 16:05:39 +0800 Subject: [PATCH 043/327] docs: Add missing characters in complex example (#404) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 28443956..b71f3172 100644 --- a/README.md +++ b/README.md @@ -251,7 +251,7 @@ test('allows the user to login successfully', async () => { // fill out the form fireEvent.change(getByLabelText(/username/i), {target: {value: 'chuck'}}) - fireEvent.change(getBylabelText(/password/i), {target: {value: 'norris'}}) + fireEvent.change(getByLabelText(/password/i), {target: {value: 'norris'}}) fireEvent.click(getByText(/submit/i)) @@ -263,7 +263,7 @@ test('allows the user to login successfully', async () => { // otherwise you could use expect(alert.textContent).toMatch(/congrats/i) // but jest-dom will give you better error messages which is why it's recommended expect(alert).toHaveTextContent(/congrats/i) - expect(window.localStorage.getItem('token')).toEqual(fakeUserReponse.token) + expect(window.localStorage.getItem('token')).toEqual(fakeUserResponse.token) }) ``` From 4aa0c56c60ac99f331ac8267428fb92fd89dcd2f Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 14 Jul 2019 02:06:17 -0600 Subject: [PATCH 044/327] docs: add LiaoJimmy as a contributor (#405) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index d588d9c3..de28339c 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -792,6 +792,15 @@ "contributions": [ "code" ] + }, + { + "login": "LiaoJimmy", + "name": "LiaoJimmy", + "avatar_url": "https://avatars0.githubusercontent.com/u/11155585?v=4", + "profile": "http://iababy46.blogspot.tw/", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index b71f3172..8d16e148 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-81-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-82-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -459,6 +459,7 @@ Thanks goes to these people ([emoji key][emojis]): Lucas Machado
Lucas Machado

πŸ“– Pascal Duez
Pascal Duez

πŸ“¦ Minh Nguyen
Minh Nguyen

πŸ’» + LiaoJimmy
LiaoJimmy

πŸ“– From ffe2b7918874c88f990534314f2f124db52038ed Mon Sep 17 00:00:00 2001 From: Sunil Pai Date: Tue, 23 Jul 2019 12:49:14 +0100 Subject: [PATCH 045/327] fix: async act detection (#407) The previous version of async act detection left an open hanging act scope, which broke tests and expectations. This PR delays the detection until it's been called at least once. --- src/__tests__/new-act.js | 76 +++++++++++++++++++ src/__tests__/no-act.js | 73 ++++++++++++++++++- src/__tests__/old-act.js | 82 ++++++++++++++++++--- src/act-compat.js | 153 +++++++++++++++++++++++++++------------ 4 files changed, 325 insertions(+), 59 deletions(-) create mode 100644 src/__tests__/new-act.js diff --git a/src/__tests__/new-act.js b/src/__tests__/new-act.js new file mode 100644 index 00000000..56ce4970 --- /dev/null +++ b/src/__tests__/new-act.js @@ -0,0 +1,76 @@ +let asyncAct + +jest.mock('react-dom/test-utils', () => ({ + act: cb => { + return cb() + }, +})) + +beforeEach(() => { + jest.resetModules() + asyncAct = require('../act-compat').asyncAct + jest.spyOn(console, 'error').mockImplementation(() => {}) +}) + +afterEach(() => { + console.error.mockRestore() +}) + +test('async act works when it does not exist (older versions of react)', async () => { + const callback = jest.fn() + await asyncAct(async () => { + await Promise.resolve() + await callback() + }) + expect(console.error).toHaveBeenCalledTimes(0) + expect(callback).toHaveBeenCalledTimes(1) + + callback.mockClear() + console.error.mockClear() + + await asyncAct(async () => { + await Promise.resolve() + await callback() + }) + expect(console.error).toHaveBeenCalledTimes(0) + expect(callback).toHaveBeenCalledTimes(1) +}) + +test('async act recovers from errors', async () => { + try { + await asyncAct(async () => { + await null + throw new Error('test error') + }) + } catch (err) { + console.error('call console.error') + } + expect(console.error).toHaveBeenCalledTimes(1) + expect(console.error.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "call console.error", + ], + ] + `) +}) + +test('async act recovers from sync errors', async () => { + try { + await asyncAct(() => { + throw new Error('test error') + }) + } catch (err) { + console.error('call console.error') + } + expect(console.error).toHaveBeenCalledTimes(1) + expect(console.error.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "call console.error", + ], + ] + `) +}) + +/* eslint no-console:0 */ diff --git a/src/__tests__/no-act.js b/src/__tests__/no-act.js index 7bf6cd6a..039a79ae 100644 --- a/src/__tests__/no-act.js +++ b/src/__tests__/no-act.js @@ -1,4 +1,15 @@ -import {act} from '..' +let act, asyncAct + +beforeEach(() => { + jest.resetModules() + act = require('..').act + asyncAct = require('../act-compat').asyncAct + jest.spyOn(console, 'error').mockImplementation(() => {}) +}) + +afterEach(() => { + console.error.mockRestore() +}) jest.mock('react-dom/test-utils', () => ({})) @@ -6,4 +17,64 @@ test('act works even when there is no act from test utils', () => { const callback = jest.fn() act(callback) expect(callback).toHaveBeenCalledTimes(1) + expect(console.error).toHaveBeenCalledTimes(0) +}) + +test('async act works when it does not exist (older versions of react)', async () => { + const callback = jest.fn() + await asyncAct(async () => { + await Promise.resolve() + await callback() + }) + expect(console.error).toHaveBeenCalledTimes(0) + expect(callback).toHaveBeenCalledTimes(1) + + callback.mockClear() + console.error.mockClear() + + await asyncAct(async () => { + await Promise.resolve() + await callback() + }) + expect(console.error).toHaveBeenCalledTimes(0) + expect(callback).toHaveBeenCalledTimes(1) +}) + +test('async act recovers from errors', async () => { + try { + await asyncAct(async () => { + await null + throw new Error('test error') + }) + } catch (err) { + console.error('call console.error') + } + expect(console.error).toHaveBeenCalledTimes(1) + expect(console.error.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "call console.error", + ], + ] + `) +}) + +test('async act recovers from sync errors', async () => { + try { + await asyncAct(() => { + throw new Error('test error') + }) + } catch (err) { + console.error('call console.error') + } + expect(console.error).toHaveBeenCalledTimes(1) + expect(console.error.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "call console.error", + ], + ] + `) }) + +/* eslint no-console:0 */ diff --git a/src/__tests__/old-act.js b/src/__tests__/old-act.js index d21c2bae..1b7760eb 100644 --- a/src/__tests__/old-act.js +++ b/src/__tests__/old-act.js @@ -1,4 +1,14 @@ -import {asyncAct} from '../act-compat' +let asyncAct + +beforeEach(() => { + jest.resetModules() + asyncAct = require('../act-compat').asyncAct + jest.spyOn(console, 'error').mockImplementation(() => {}) +}) + +afterEach(() => { + console.error.mockRestore() +}) jest.mock('../react-dom-16.9.0-is-released', () => ({ reactDomSixteenPointNineIsReleased: true, @@ -6,30 +16,40 @@ jest.mock('../react-dom-16.9.0-is-released', () => ({ jest.mock('react-dom/test-utils', () => ({ act: cb => { - const promise = cb() + cb() return { then() { - console.error('blah, do not do this') - return promise + console.error( + 'Warning: Do not await the result of calling ReactTestUtils.act(...), it is not a Promise.', + ) }, } }, })) test('async act works even when the act is an old one', async () => { - jest.spyOn(console, 'error').mockImplementation(() => {}) const callback = jest.fn() await asyncAct(async () => { + console.error('sigil') await Promise.resolve() await callback() + console.error('sigil') }) expect(console.error.mock.calls).toMatchInlineSnapshot(` -Array [ - Array [ - "It looks like you're using a version of react-dom that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.", - ], -] -`) + Array [ + Array [ + Array [ + "sigil", + ], + ], + Array [ + "It looks like you're using a version of react-dom that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.", + ], + Array [ + "sigil", + ], + ] + `) expect(callback).toHaveBeenCalledTimes(1) // and it doesn't warn you twice @@ -42,8 +62,46 @@ Array [ }) expect(console.error).toHaveBeenCalledTimes(0) expect(callback).toHaveBeenCalledTimes(1) +}) - console.error.mockRestore() +test('async act recovers from async errors', async () => { + try { + await asyncAct(async () => { + await null + throw new Error('test error') + }) + } catch (err) { + console.error('call console.error') + } + expect(console.error).toHaveBeenCalledTimes(2) + expect(console.error.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "It looks like you're using a version of react-dom that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.", + ], + Array [ + "call console.error", + ], + ] + `) +}) + +test('async act recovers from sync errors', async () => { + try { + await asyncAct(() => { + throw new Error('test error') + }) + } catch (err) { + console.error('call console.error') + } + expect(console.error).toHaveBeenCalledTimes(1) + expect(console.error.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "call console.error", + ], + ] + `) }) /* eslint no-console:0 */ diff --git a/src/act-compat.js b/src/act-compat.js index a87ee4d7..2c1a53c5 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -2,29 +2,8 @@ import React from 'react' import ReactDOM from 'react-dom' import {reactDomSixteenPointNineIsReleased} from './react-dom-16.9.0-is-released' -let reactAct -let actSupported = false -let asyncActSupported = false -try { - reactAct = require('react-dom/test-utils').act - actSupported = reactAct !== undefined - - const originalError = console.error - let errorCalled = false - console.error = () => { - errorCalled = true - } - console.error.calls = [] - /* istanbul ignore next */ - reactAct(() => ({then: () => {}})).then(() => {}) - /* istanbul ignore next */ - if (!errorCalled) { - asyncActSupported = true - } - console.error = originalError -} catch (error) { - // ignore, this is to support old versions of react -} +const reactAct = require('react-dom/test-utils').act +const actSupported = reactAct !== undefined // act is supported react-dom@16.8.0 // so for versions that don't have act from test utils @@ -38,32 +17,114 @@ function actPolyfill(cb) { const act = reactAct || actPolyfill let youHaveBeenWarned = false -// this will not avoid warnings that react-dom 16.8.0 logs for triggering -// state updates asynchronously, but at least we can tell people they need -// to upgrade to avoid the warnings. -async function asyncActPolyfill(cb) { - // istanbul-ignore-next - if ( - !youHaveBeenWarned && - actSupported && - reactDomSixteenPointNineIsReleased - ) { - // if act is supported and async act isn't and they're trying to use async - // act, then they need to upgrade from 16.8 to 16.9. - // This is a seemless upgrade, so we'll add a warning - console.error( - `It looks like you're using a version of react-dom that supports the "act" function, but not an awaitable version of "act" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.`, - ) - youHaveBeenWarned = true +let isAsyncActSupported = null + +function asyncAct(cb) { + if (actSupported === true) { + if (isAsyncActSupported === null) { + return new Promise((resolve, reject) => { + // patch console.error here + const originalConsoleError = console.error + console.error = function error(...args) { + /* if console.error fired *with that specific message* */ + if ( + args[0].indexOf( + 'Warning: Do not await the result of calling ReactTestUtils.act', + ) === 0 + ) { + // v16.8.6 + isAsyncActSupported = false + } else if ( + args[0].indexOf( + 'Warning: The callback passed to ReactTestUtils.act(...) function must not return anything', + ) === 0 + ) { + // no-op + } else { + originalConsoleError.call(console, args) + } + } + let cbReturn, result + try { + result = reactAct(() => { + cbReturn = cb() + return cbReturn + }) + } catch (err) { + console.error = originalConsoleError + reject(err) + return + } + + result.then( + () => { + console.error = originalConsoleError + // if it got here, it means async act is supported + isAsyncActSupported = true + resolve() + }, + err => { + console.error = originalConsoleError + isAsyncActSupported = true + reject(err) + }, + ) + + // 16.8.6's act().then() doesn't call a resolve handler, so we need to manually flush here, sigh + + if (isAsyncActSupported === false) { + console.error = originalConsoleError + /* istanbul-ignore-next */ + if (!youHaveBeenWarned && reactDomSixteenPointNineIsReleased) { + // if act is supported and async act isn't and they're trying to use async + // act, then they need to upgrade from 16.8 to 16.9. + // This is a seemless upgrade, so we'll add a warning + console.error( + `It looks like you're using a version of react-dom that supports the "act" function, but not an awaitable version of "act" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.`, + ) + youHaveBeenWarned = true + } + + cbReturn.then(() => { + // a faux-version. + // todo - copy https://github.com/facebook/react/blob/master/packages/shared/enqueueTask.js + Promise.resolve().then(() => { + // use sync act to flush effects + act(() => {}) + resolve() + }) + }, reject) + } + }) + } else if (isAsyncActSupported === false) { + // use the polyfill directly + let result + act(() => { + result = cb() + }) + return result.then(() => { + return Promise.resolve().then(() => { + // use sync act to flush effects + act(() => {}) + }) + }) + } + // all good! regular act + return act(cb) } - await cb() - // make all effects resolve after - act(() => {}) + // use the polyfill + let result + act(() => { + result = cb() + }) + return result.then(() => { + return Promise.resolve().then(() => { + // use sync act to flush effects + act(() => {}) + }) + }) } -// istanbul ignore next -const asyncAct = asyncActSupported ? reactAct : asyncActPolyfill - export default act export {asyncAct} From 2774d7b4975d42a18c88c037bbc2676f405c37df Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2019 07:51:00 -0400 Subject: [PATCH 046/327] docs: add threepointone as a contributor (#408) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 10 ++++++++++ README.md | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index de28339c..9424ac71 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -801,6 +801,16 @@ "contributions": [ "doc" ] + }, + { + "login": "threepointone", + "name": "Sunil Pai", + "avatar_url": "https://avatars2.githubusercontent.com/u/18808?v=4", + "profile": "https://github.com/threepointone", + "contributions": [ + "code", + "test" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 8d16e148..e6cde207 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-82-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-83-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -460,6 +460,7 @@ Thanks goes to these people ([emoji key][emojis]): Pascal Duez
Pascal Duez

πŸ“¦ Minh Nguyen
Minh Nguyen

πŸ’» LiaoJimmy
LiaoJimmy

πŸ“– + Sunil Pai
Sunil Pai

πŸ’» ⚠️ From 98bc29a623c6c3f59bc5ee9f269e791ead8fb65a Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2019 07:52:14 -0400 Subject: [PATCH 047/327] docs: add gaearon as a contributor (#409) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 9424ac71..f9a8ee31 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -811,6 +811,15 @@ "code", "test" ] + }, + { + "login": "gaearon", + "name": "Dan Abramov", + "avatar_url": "https://avatars0.githubusercontent.com/u/810438?v=4", + "profile": "http://twitter.com/dan_abramov", + "contributions": [ + "review" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index e6cde207..2409f735 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-83-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-84-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -461,6 +461,7 @@ Thanks goes to these people ([emoji key][emojis]): Minh Nguyen
Minh Nguyen

πŸ’» LiaoJimmy
LiaoJimmy

πŸ“– Sunil Pai
Sunil Pai

πŸ’» ⚠️ + Dan Abramov
Dan Abramov

πŸ‘€ From 06ce496de0bdd75a164d2a1713c056bcad9b28b2 Mon Sep 17 00:00:00 2001 From: Christian Murphy Date: Tue, 23 Jul 2019 09:42:07 -0700 Subject: [PATCH 048/327] ci: test with node 8, 10, and 12 (#410) --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 08be7ec0..ed2d9bca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,10 @@ cache: - ~/.npm notifications: email: false -node_js: '8' +node_js: + - '8' + - '10' + - '12' install: npm install script: npm run validate after_success: kcd-scripts travis-after-success From 00f8b229013c80504c424cda15d4a8d060a10648 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2019 12:42:58 -0400 Subject: [PATCH 049/327] docs: add ChristianMurphy as a contributor (#411) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index f9a8ee31..16b87cc5 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -820,6 +820,15 @@ "contributions": [ "review" ] + }, + { + "login": "ChristianMurphy", + "name": "Christian Murphy", + "avatar_url": "https://avatars3.githubusercontent.com/u/3107513?v=4", + "profile": "https://github.com/ChristianMurphy", + "contributions": [ + "infra" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 2409f735..98d2043e 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-84-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-85-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -463,6 +463,9 @@ Thanks goes to these people ([emoji key][emojis]): Sunil Pai
Sunil Pai

πŸ’» ⚠️ Dan Abramov
Dan Abramov

πŸ‘€ + + Christian Murphy
Christian Murphy

πŸš‡ + From 34d69cf51dd81f4179df8bc1b5d783888bd664fa Mon Sep 17 00:00:00 2001 From: Ivakhnenko Dmitry Date: Fri, 26 Jul 2019 17:15:17 +0300 Subject: [PATCH 050/327] don't mix require and import (#415) --- src/act-compat.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/act-compat.js b/src/act-compat.js index 2c1a53c5..981e6fcd 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -1,8 +1,9 @@ import React from 'react' import ReactDOM from 'react-dom' import {reactDomSixteenPointNineIsReleased} from './react-dom-16.9.0-is-released' +import * as testUtils from 'react-dom/test-utils' -const reactAct = require('react-dom/test-utils').act +const reactAct = testUtils.act const actSupported = reactAct !== undefined // act is supported react-dom@16.8.0 From 7e9f03c337772f833d1595a74863d491a2432df5 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 26 Jul 2019 08:16:09 -0600 Subject: [PATCH 051/327] fix(release): manually release a patch version There was an issue with a patch release, so this manual-releases.md change is to release a new patch version. Reference: #415 --- other/manual-releases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/manual-releases.md b/other/manual-releases.md index e19f34cf..0ae36c3f 100644 --- a/other/manual-releases.md +++ b/other/manual-releases.md @@ -41,4 +41,4 @@ change is to release a new patch version. Reference: # ``` -The number of times we've had to do a manual release is: 3 +The number of times we've had to do a manual release is: 4 From 929748f092013b4045f65866edea5df9680f1f3a Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 26 Jul 2019 08:17:19 -0600 Subject: [PATCH 052/327] docs: add jeetiss as a contributor (#416) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 16b87cc5..d05c067b 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -829,6 +829,15 @@ "contributions": [ "infra" ] + }, + { + "login": "jeetiss", + "name": "Ivakhnenko Dmitry", + "avatar_url": "https://avatars1.githubusercontent.com/u/6726016?v=4", + "profile": "https://jeetiss.github.io/", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 98d2043e..d606a25f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-85-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-86-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -465,6 +465,7 @@ Thanks goes to these people ([emoji key][emojis]): Christian Murphy
Christian Murphy

πŸš‡ + Ivakhnenko Dmitry
Ivakhnenko Dmitry

πŸ’» From 709eb75546e4256e64f834bfb3b2936b66f48f65 Mon Sep 17 00:00:00 2001 From: James George Date: Thu, 1 Aug 2019 23:50:21 +0530 Subject: [PATCH 053/327] docs: make the license text point to the respective file (#420) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d606a25f..bf897ba8 100644 --- a/README.md +++ b/README.md @@ -476,7 +476,7 @@ Contributions of any kind welcome! ## LICENSE -MIT +[MIT](LICENSE) From edd3eaaa9d40b7fbc4e56f71a0dbe9b6eb29073c Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2019 12:21:30 -0600 Subject: [PATCH 054/327] docs: add jamesgeorge007 as a contributor (#421) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index d05c067b..dc1342d7 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -838,6 +838,15 @@ "contributions": [ "code" ] + }, + { + "login": "jamesgeorge007", + "name": "James George", + "avatar_url": "https://avatars2.githubusercontent.com/u/25279263?v=4", + "profile": "https://ghuser.io/jamesgeorge007", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index bf897ba8..ac962d1b 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-86-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-87-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -466,6 +466,7 @@ Thanks goes to these people ([emoji key][emojis]): Christian Murphy
Christian Murphy

πŸš‡ Ivakhnenko Dmitry
Ivakhnenko Dmitry

πŸ’» + James George
James George

πŸ“– From 54d060be1e485004a69ed88ddc135df58f0d9ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Fernandes?= Date: Mon, 5 Aug 2019 16:06:41 +0200 Subject: [PATCH 055/327] docs: Document known issue with React 16.8 (#423) * docs: Document known issue with React 16.8 These warnings will be common among users with React 16.8. By adding this to the README we can address a common concern until React 16.9 becomes common. * Update README.md Co-authored-by: Kent C. Dodds --- README.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/README.md b/README.md index ac962d1b..e8a1342f 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ practices.

- [The problem](#the-problem) - [This solution](#this-solution) - [Installation](#installation) + - [Suppressing unnecessary warnings on React DOM 16.8](#suppressing-unnecessary-warnings-on-react-dom-168) - [Examples](#examples) - [Basic Example](#basic-example) - [Complex Example](#complex-example) @@ -108,6 +109,37 @@ use [the custom jest matchers](https://github.com/testing-library/jest-dom). > [**Docs**](https://testing-library.com/react) +### Suppressing unnecessary warnings on React DOM 16.8 + +There is a known compatibility issue with React DOM 16.8 where you will see the +following warning: + +``` +Warning: An update to ComponentName inside a test was not wrapped in act(...). +``` + +If you cannot upgrade to React DOM 16.9, you may suppress the warnings by adding +the following snippet to your test configuration +([learn more](https://github.com/testing-library/react-testing-library/issues/281)): + +```js +// this is just a little hack to silence a warning that we'll get until we +// upgrade to 16.9: https://github.com/facebook/react/pull/14853 +const originalError = console.error +beforeAll(() => { + console.error = (...args) => { + if (/Warning.*not wrapped in act/.test(args[0])) { + return + } + originalError.call(console, ...args) + } +}) + +afterAll(() => { + console.error = originalError +}) +``` + ## Examples ### Basic Example From 3ef5361bd792d1c51c9a7d4cd6c73c41df441963 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2019 08:23:49 -0600 Subject: [PATCH 056/327] docs: add JSFernandes as a contributor (#424) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index dc1342d7..56f8ab9f 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -847,6 +847,15 @@ "contributions": [ "doc" ] + }, + { + "login": "JSFernandes", + "name": "JoΓ£o Fernandes", + "avatar_url": "https://avatars1.githubusercontent.com/u/1075053?v=4", + "profile": "https://joaofernandes.me/", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index e8a1342f..af475f90 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-87-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-88-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -499,6 +499,7 @@ Thanks goes to these people ([emoji key][emojis]): Christian Murphy
Christian Murphy

πŸš‡ Ivakhnenko Dmitry
Ivakhnenko Dmitry

πŸ’» James George
James George

πŸ“– + JoΓ£o Fernandes
JoΓ£o Fernandes

πŸ“– From 4c8ca23ca68c110f1ca31c552573dfe8f5ba4e95 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2019 08:24:37 -0600 Subject: [PATCH 057/327] docs: add alejandroperea as a contributor (#425) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 56f8ab9f..24dbb2ee 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -856,6 +856,15 @@ "contributions": [ "doc" ] + }, + { + "login": "alejandroperea", + "name": "Alejandro Perea", + "avatar_url": "https://avatars3.githubusercontent.com/u/6084749?v=4", + "profile": "https://github.com/alejandroperea", + "contributions": [ + "review" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index af475f90..8008d6b7 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-88-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-89-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -500,6 +500,7 @@ Thanks goes to these people ([emoji key][emojis]): Ivakhnenko Dmitry
Ivakhnenko Dmitry

πŸ’» James George
James George

πŸ“– JoΓ£o Fernandes
JoΓ£o Fernandes

πŸ“– + Alejandro Perea
Alejandro Perea

πŸ‘€ From 1eae36176315bf0449575252c1d0498e632c3d67 Mon Sep 17 00:00:00 2001 From: Sunil Pai Date: Tue, 6 Aug 2019 21:13:04 +0100 Subject: [PATCH 058/327] fix: make cleanup use async act (#427) - awaits an `act(async () => {})` inside `cleanup-after-each` Some possible Q&A: - why not do the same in sync cleanup()?: if peeps are using react-testing-library already, it's suuuper unlikely they'll have hanging sync effects/updates. Decided not to add code without a good reason. (bonus: fixes a lint violation in act-compat.js) --- cleanup-after-each.js | 4 +++- src/__tests__/cleanup-after-each.js | 32 +++++++++++++++++++++++++++++ src/act-compat.js | 2 +- src/cleanup-async.js | 10 +++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/__tests__/cleanup-after-each.js create mode 100644 src/cleanup-async.js diff --git a/cleanup-after-each.js b/cleanup-after-each.js index f0a17c95..9bbba5ce 100644 --- a/cleanup-after-each.js +++ b/cleanup-after-each.js @@ -1 +1,3 @@ -afterEach(require('./dist').cleanup) +afterEach(() => { + return require('./dist/cleanup-async')() +}) diff --git a/src/__tests__/cleanup-after-each.js b/src/__tests__/cleanup-after-each.js new file mode 100644 index 00000000..f59dac9c --- /dev/null +++ b/src/__tests__/cleanup-after-each.js @@ -0,0 +1,32 @@ +import React from 'react' +import {render} from '../index' +import cleanupAsync from '../cleanup-async' + +afterEach(() => { + return cleanupAsync() +}) + +const log = [] +let ctr = 0 + +function App() { + async function somethingAsync() { + await null + log.push(ctr++) + } + React.useEffect(() => { + somethingAsync() + }, []) + return 123 +} + +it('cleanup-after-each does not leave any hanging microtasks: part 1', () => { + render() + expect(document.body.textContent).toBe('123') + expect(log).toEqual([]) +}) + +it('cleanup-after-each does not leave any hanging microtasks: part 2', () => { + expect(log).toEqual([0]) + expect(document.body.innerHTML).toBe('') +}) diff --git a/src/act-compat.js b/src/act-compat.js index 981e6fcd..f812f8a2 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -1,7 +1,7 @@ import React from 'react' import ReactDOM from 'react-dom' -import {reactDomSixteenPointNineIsReleased} from './react-dom-16.9.0-is-released' import * as testUtils from 'react-dom/test-utils' +import {reactDomSixteenPointNineIsReleased} from './react-dom-16.9.0-is-released' const reactAct = testUtils.act const actSupported = reactAct !== undefined diff --git a/src/cleanup-async.js b/src/cleanup-async.js new file mode 100644 index 00000000..0031db56 --- /dev/null +++ b/src/cleanup-async.js @@ -0,0 +1,10 @@ +// This file is for use by the top-level export +// @testing-library/react/cleanup-after-each +// It is not meant to be used directly + +module.exports = async function cleanupAsync() { + const {asyncAct} = require('./act-compat') + const {cleanup} = require('./index') + await asyncAct(async () => {}) + cleanup() +} From 98b9605cb0b6c5f7e1c91e0e65ca88e1989ed5ea Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Tue, 6 Aug 2019 14:14:20 -0600 Subject: [PATCH 059/327] Update FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 9bf52665..e9dc1c69 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ open_collective: testing-library +github: [kentcdodds] From c0266503bfff4cd24de4039c2e0a624bb4fdb3d0 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 8 Aug 2019 16:54:48 -0600 Subject: [PATCH 060/327] fix: improve warning so people know they can upgrade to 16.9.0 now (#431) Closes #281 --- package.json | 12 ++++++------ src/__tests__/old-act.js | 4 ---- src/act-compat.js | 6 +++--- src/react-dom-16.9.0-is-released.js | 2 -- 4 files changed, 9 insertions(+), 15 deletions(-) delete mode 100644 src/react-dom-16.9.0-is-released.js diff --git a/package.json b/package.json index 8280be55..b326a1a6 100644 --- a/package.json +++ b/package.json @@ -41,17 +41,17 @@ "author": "Kent C. Dodds (http://kentcdodds.com/)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.5.4", - "@testing-library/dom": "^5.5.4" + "@babel/runtime": "^7.5.5", + "@testing-library/dom": "^5.6.1" }, "devDependencies": { "@reach/router": "^1.2.1", "@testing-library/jest-dom": "^4.0.0", - "@types/react": "^16.8.23", - "@types/react-dom": "^16.8.4", + "@types/react": "^16.8.25", + "@types/react-dom": "^16.8.5", "kcd-scripts": "^1.5.2", - "react": "^16.8.6", - "react-dom": "^16.8.6" + "react": "^16.9.0", + "react-dom": "^16.9.0" }, "peerDependencies": { "react": "*", diff --git a/src/__tests__/old-act.js b/src/__tests__/old-act.js index 1b7760eb..0098ed08 100644 --- a/src/__tests__/old-act.js +++ b/src/__tests__/old-act.js @@ -10,10 +10,6 @@ afterEach(() => { console.error.mockRestore() }) -jest.mock('../react-dom-16.9.0-is-released', () => ({ - reactDomSixteenPointNineIsReleased: true, -})) - jest.mock('react-dom/test-utils', () => ({ act: cb => { cb() diff --git a/src/act-compat.js b/src/act-compat.js index f812f8a2..e16b135f 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -1,7 +1,6 @@ import React from 'react' import ReactDOM from 'react-dom' import * as testUtils from 'react-dom/test-utils' -import {reactDomSixteenPointNineIsReleased} from './react-dom-16.9.0-is-released' const reactAct = testUtils.act const actSupported = reactAct !== undefined @@ -28,6 +27,7 @@ function asyncAct(cb) { const originalConsoleError = console.error console.error = function error(...args) { /* if console.error fired *with that specific message* */ + /* istanbul ignore next */ if ( args[0].indexOf( 'Warning: Do not await the result of calling ReactTestUtils.act', @@ -75,8 +75,8 @@ function asyncAct(cb) { if (isAsyncActSupported === false) { console.error = originalConsoleError - /* istanbul-ignore-next */ - if (!youHaveBeenWarned && reactDomSixteenPointNineIsReleased) { + /* istanbul ignore next */ + if (!youHaveBeenWarned) { // if act is supported and async act isn't and they're trying to use async // act, then they need to upgrade from 16.8 to 16.9. // This is a seemless upgrade, so we'll add a warning diff --git a/src/react-dom-16.9.0-is-released.js b/src/react-dom-16.9.0-is-released.js deleted file mode 100644 index 33053dfa..00000000 --- a/src/react-dom-16.9.0-is-released.js +++ /dev/null @@ -1,2 +0,0 @@ -// we don't want to warn until react-dom@16.9.0 is actually released -export const reactDomSixteenPointNineIsReleased = false From f77012ec3326509c6055b92801de55db74506ee0 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 8 Aug 2019 17:09:34 -0600 Subject: [PATCH 061/327] chore: cleanup some tests --- src/__tests__/act.js | 4 +--- src/__tests__/bugs.js | 10 ---------- src/__tests__/cleanup-after-each.js | 4 ++-- src/__tests__/cleanup.js | 28 ++++++++++++++++++++++++++++ src/__tests__/debug.js | 3 +-- src/__tests__/end-to-end.js | 4 +--- src/__tests__/events.js | 4 +--- src/__tests__/multi-base.js | 4 +--- src/__tests__/render.js | 27 ++------------------------- src/__tests__/stopwatch.js | 4 +--- 10 files changed, 38 insertions(+), 54 deletions(-) delete mode 100644 src/__tests__/bugs.js create mode 100644 src/__tests__/cleanup.js diff --git a/src/__tests__/act.js b/src/__tests__/act.js index 00be96f7..2adcee94 100644 --- a/src/__tests__/act.js +++ b/src/__tests__/act.js @@ -1,7 +1,5 @@ import React from 'react' -import {render, cleanup, fireEvent} from '../' - -afterEach(cleanup) +import {render, fireEvent} from '../' test('render calls useEffect immediately', () => { const effectCb = jest.fn() diff --git a/src/__tests__/bugs.js b/src/__tests__/bugs.js deleted file mode 100644 index 05146cf7..00000000 --- a/src/__tests__/bugs.js +++ /dev/null @@ -1,10 +0,0 @@ -// this is where we'll put bug reproductions/regressions -// to make sure we never see them again - -import React from 'react' -import {render, cleanup} from '../' - -test('cleanup does not error when an element is not a child', () => { - render(
, {container: document.createElement('div')}) - cleanup() -}) diff --git a/src/__tests__/cleanup-after-each.js b/src/__tests__/cleanup-after-each.js index f59dac9c..4a38a74d 100644 --- a/src/__tests__/cleanup-after-each.js +++ b/src/__tests__/cleanup-after-each.js @@ -20,13 +20,13 @@ function App() { return 123 } -it('cleanup-after-each does not leave any hanging microtasks: part 1', () => { +test('does not leave any hanging microtasks: part 1', () => { render() expect(document.body.textContent).toBe('123') expect(log).toEqual([]) }) -it('cleanup-after-each does not leave any hanging microtasks: part 2', () => { +test('does not leave any hanging microtasks: part 2', () => { expect(log).toEqual([0]) expect(document.body.innerHTML).toBe('') }) diff --git a/src/__tests__/cleanup.js b/src/__tests__/cleanup.js new file mode 100644 index 00000000..ec2a057c --- /dev/null +++ b/src/__tests__/cleanup.js @@ -0,0 +1,28 @@ +import React from 'react' +import {render, cleanup} from '../' + +test('cleans up the document', () => { + const spy = jest.fn() + const divId = 'my-div' + + class Test extends React.Component { + componentWillUnmount() { + expect(document.getElementById(divId)).toBeInTheDocument() + spy() + } + + render() { + return
+ } + } + + render() + cleanup() + expect(document.body.innerHTML).toBe('') + expect(spy).toHaveBeenCalledTimes(1) +}) + +test('cleanup does not error when an element is not a child', () => { + render(
, {container: document.createElement('div')}) + cleanup() +}) diff --git a/src/__tests__/debug.js b/src/__tests__/debug.js index f7c0a927..4cab1ea9 100644 --- a/src/__tests__/debug.js +++ b/src/__tests__/debug.js @@ -1,12 +1,11 @@ import React from 'react' -import {render, cleanup} from '../' +import {render} from '../' beforeEach(() => { jest.spyOn(console, 'log').mockImplementation(() => {}) }) afterEach(() => { - cleanup() console.log.mockRestore() }) diff --git a/src/__tests__/end-to-end.js b/src/__tests__/end-to-end.js index 78087e58..4cdfc328 100644 --- a/src/__tests__/end-to-end.js +++ b/src/__tests__/end-to-end.js @@ -1,7 +1,5 @@ import React from 'react' -import {render, wait, cleanup} from '../' - -afterEach(cleanup) +import {render, wait} from '../' const fetchAMessage = () => new Promise(resolve => { diff --git a/src/__tests__/events.js b/src/__tests__/events.js index c091a366..afe2193f 100644 --- a/src/__tests__/events.js +++ b/src/__tests__/events.js @@ -1,5 +1,5 @@ import React from 'react' -import {render, cleanup, fireEvent} from '../' +import {render, fireEvent} from '../' const eventTypes = [ { @@ -128,8 +128,6 @@ const eventTypes = [ }, ] -afterEach(cleanup) - eventTypes.forEach(({type, events, elementType, init}) => { describe(`${type} Events`, () => { events.forEach(eventName => { diff --git a/src/__tests__/multi-base.js b/src/__tests__/multi-base.js index 03f0d93e..c45bcd37 100644 --- a/src/__tests__/multi-base.js +++ b/src/__tests__/multi-base.js @@ -1,5 +1,5 @@ import React from 'react' -import {render, cleanup} from '../' +import {render} from '../' // these are created once per test suite and reused for each case let treeA, treeB @@ -15,8 +15,6 @@ afterAll(() => { treeB.parentNode.removeChild(treeB) }) -afterEach(cleanup) - test('baseElement isolates trees from one another', () => { const {getByText: getByTextInA} = render(
Jekyll
, { baseElement: treeA, diff --git a/src/__tests__/render.js b/src/__tests__/render.js index e8f25d3f..28d7f9e7 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -1,6 +1,6 @@ import React from 'react' import ReactDOM from 'react-dom' -import {render, cleanup} from '../' +import {render} from '../' test('renders div into document', () => { const ref = React.createRef() @@ -52,28 +52,7 @@ test('returns baseElement which defaults to document.body', () => { expect(baseElement).toBe(document.body) }) -it('cleansup document', () => { - const spy = jest.fn() - const divId = 'my-div' - - class Test extends React.Component { - componentWillUnmount() { - expect(document.getElementById(divId)).toBeInTheDocument() - spy() - } - - render() { - return
- } - } - - render() - cleanup() - expect(document.body.innerHTML).toBe('') - expect(spy).toHaveBeenCalledTimes(1) -}) - -it('supports fragments', () => { +test('supports fragments', () => { class Test extends React.Component { render() { return ( @@ -86,8 +65,6 @@ it('supports fragments', () => { const {asFragment} = render() expect(asFragment()).toMatchSnapshot() - cleanup() - expect(document.body.innerHTML).toBe('') }) test('renders options.wrapper around node', () => { diff --git a/src/__tests__/stopwatch.js b/src/__tests__/stopwatch.js index 34f58561..d4cd606c 100644 --- a/src/__tests__/stopwatch.js +++ b/src/__tests__/stopwatch.js @@ -1,7 +1,5 @@ import React from 'react' -import {render, cleanup, fireEvent} from '../' - -afterEach(cleanup) +import {render, fireEvent} from '../' class StopWatch extends React.Component { state = {lapse: 0, running: false} From 2f17920c8a37abcb855e4dac720c881332abda47 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 9 Aug 2019 09:00:16 -0600 Subject: [PATCH 062/327] chore: meh --- src/__tests__/cleanup-after-each.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/cleanup-after-each.js b/src/__tests__/cleanup-after-each.js index 4a38a74d..3f7e139b 100644 --- a/src/__tests__/cleanup-after-each.js +++ b/src/__tests__/cleanup-after-each.js @@ -1,5 +1,5 @@ import React from 'react' -import {render} from '../index' +import {render} from '../' import cleanupAsync from '../cleanup-async' afterEach(() => { From 605a8b16f4b5a8bb3fb5457119877807bba6306a Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 8 Aug 2019 15:50:51 -0600 Subject: [PATCH 063/327] feat(cleanup): automatically cleanup if afterEach is detected You can disable this with the RTL_SKIP_CLEANUP environment variable if you so choose, but it's recommended to have cleanup work this way. Closes #428 --- src/__tests__/auto-cleanup-skip.js | 18 ++++++++++++++++++ src/__tests__/auto-cleanup.js | 13 +++++++++++++ src/index.js | 10 ++++++++++ tests/setup-env.js | 5 ----- 4 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 src/__tests__/auto-cleanup-skip.js create mode 100644 src/__tests__/auto-cleanup.js diff --git a/src/__tests__/auto-cleanup-skip.js b/src/__tests__/auto-cleanup-skip.js new file mode 100644 index 00000000..4e58d6c5 --- /dev/null +++ b/src/__tests__/auto-cleanup-skip.js @@ -0,0 +1,18 @@ +import React from 'react' + +let render +beforeAll(() => { + process.env.RTL_SKIP_CLEANUP = 'true' + const rtl = require('../') + render = rtl.render +}) + +// This one verifies that if RTL_SKIP_CLEANUP is set +// that we DON'T auto-wire up the afterEach for folks +test('first', () => { + render(
hi
) +}) + +test('second', () => { + expect(document.body.innerHTML).toEqual('
hi
') +}) diff --git a/src/__tests__/auto-cleanup.js b/src/__tests__/auto-cleanup.js new file mode 100644 index 00000000..1d0a7954 --- /dev/null +++ b/src/__tests__/auto-cleanup.js @@ -0,0 +1,13 @@ +import React from 'react' +import {render} from '../' + +// This just verifies that by importing RTL in an +// environment which supports afterEach (like jest) +// we'll get automatic cleanup between tests. +test('first', () => { + render(
hi
) +}) + +test('second', () => { + expect(document.body.innerHTML).toEqual('') +}) diff --git a/src/index.js b/src/index.js index 4565074b..f6e1c1ef 100644 --- a/src/index.js +++ b/src/index.js @@ -142,6 +142,16 @@ fireEvent.select = (node, init) => { fireEvent.keyUp(node, init) } +// if we're running in a test runner that supports afterEach +// then we'll automatically run cleanup afterEach test +// this ensures that tests run in isolation from each other +if (typeof afterEach === 'function' && !process.env.RTL_SKIP_CLEANUP) { + afterEach(async () => { + await asyncAct(async () => {}) + cleanup() + }) +} + // just re-export everything from dom-testing-library export * from '@testing-library/dom' export {render, cleanup, fireEvent, act} diff --git a/tests/setup-env.js b/tests/setup-env.js index d1d6d891..264828a9 100644 --- a/tests/setup-env.js +++ b/tests/setup-env.js @@ -1,6 +1 @@ import '@testing-library/jest-dom/extend-expect' - -afterEach(() => { - // have to do a dynamic import so we don't mess up jest mocking for old-act.js - require('../src').cleanup() -}) From f8a88e779ceb65720d5d60a5166c96df1026db12 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 9 Aug 2019 12:20:07 -0600 Subject: [PATCH 064/327] Update src/__tests__/auto-cleanup-skip.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: AdriΓ  Fontcuberta --- src/__tests__/auto-cleanup-skip.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/auto-cleanup-skip.js b/src/__tests__/auto-cleanup-skip.js index 4e58d6c5..c52d741b 100644 --- a/src/__tests__/auto-cleanup-skip.js +++ b/src/__tests__/auto-cleanup-skip.js @@ -8,7 +8,7 @@ beforeAll(() => { }) // This one verifies that if RTL_SKIP_CLEANUP is set -// that we DON'T auto-wire up the afterEach for folks +// then we DON'T auto-wire up the afterEach for folks test('first', () => { render(
hi
) }) From e2d25724dc5b0f9b29655a75c8a58ae24780a307 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 8 Aug 2019 15:50:51 -0600 Subject: [PATCH 065/327] feat(cleanup): automatically cleanup if afterEach is detected You can disable this with the RTL_SKIP_CLEANUP environment variable if you so choose, but it's recommended to have cleanup work this way. Closes #428 BREAKING CHANGE: If your tests were not isolated before (and you referenced the same component between tests) then this change will break your tests. You should [keep your tests isolated](https://kentcdodds.com/blog/test-isolation-with-react), but if you're unable/unwilling to do that right away, then you can either run your tests with the environment variable `RTL_SKIP_AUTO_CLEANUP` set to `true` or import `@testing-library/react/pure` instead of `@testing-library/react`. --- package.json | 3 +- pure.js | 2 + src/__tests__/auto-cleanup-skip.js | 4 +- src/index.js | 159 ++--------------------------- src/pure.js | 153 +++++++++++++++++++++++++++ 5 files changed, 165 insertions(+), 156 deletions(-) create mode 100644 pure.js create mode 100644 src/pure.js diff --git a/package.json b/package.json index b326a1a6..d27b209a 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "files": [ "dist", "typings", - "cleanup-after-each.js" + "cleanup-after-each.js", + "pure.js" ], "keywords": [ "testing", diff --git a/pure.js b/pure.js new file mode 100644 index 00000000..75dc0452 --- /dev/null +++ b/pure.js @@ -0,0 +1,2 @@ +// makes it so people can import from '@testing-library/react/pure' +module.exports = require('./dist/pure') diff --git a/src/__tests__/auto-cleanup-skip.js b/src/__tests__/auto-cleanup-skip.js index c52d741b..e5ef35ae 100644 --- a/src/__tests__/auto-cleanup-skip.js +++ b/src/__tests__/auto-cleanup-skip.js @@ -2,12 +2,12 @@ import React from 'react' let render beforeAll(() => { - process.env.RTL_SKIP_CLEANUP = 'true' + process.env.RTL_SKIP_AUTO_CLEANUP = 'true' const rtl = require('../') render = rtl.render }) -// This one verifies that if RTL_SKIP_CLEANUP is set +// This one verifies that if RTL_SKIP_AUTO_CLEANUP is set // then we DON'T auto-wire up the afterEach for folks test('first', () => { render(
hi
) diff --git a/src/index.js b/src/index.js index f6e1c1ef..5e05b725 100644 --- a/src/index.js +++ b/src/index.js @@ -1,163 +1,16 @@ -import React from 'react' -import ReactDOM from 'react-dom' -import { - getQueriesForElement, - prettyDOM, - fireEvent as dtlFireEvent, - configure as configureDTL, -} from '@testing-library/dom' -import act, {asyncAct} from './act-compat' - -configureDTL({ - asyncWrapper: async cb => { - let result - await asyncAct(async () => { - result = await cb() - }) - return result - }, -}) - -const mountedContainers = new Set() - -function render( - ui, - { - container, - baseElement = container, - queries, - hydrate = false, - wrapper: WrapperComponent, - } = {}, -) { - if (!baseElement) { - // default to document.body instead of documentElement to avoid output of potentially-large - // head elements (such as JSS style blocks) in debug output - baseElement = document.body - } - if (!container) { - container = baseElement.appendChild(document.createElement('div')) - } - - // we'll add it to the mounted containers regardless of whether it's actually - // added to document.body so the cleanup method works regardless of whether - // they're passing us a custom container or not. - mountedContainers.add(container) - - const wrapUiIfNeeded = innerElement => - WrapperComponent - ? React.createElement(WrapperComponent, null, innerElement) - : innerElement - - act(() => { - if (hydrate) { - ReactDOM.hydrate(wrapUiIfNeeded(ui), container) - } else { - ReactDOM.render(wrapUiIfNeeded(ui), container) - } - }) - - return { - container, - baseElement, - // eslint-disable-next-line no-console - debug: (el = baseElement) => console.log(prettyDOM(el)), - unmount: () => ReactDOM.unmountComponentAtNode(container), - rerender: rerenderUi => { - render(wrapUiIfNeeded(rerenderUi), {container, baseElement}) - // Intentionally do not return anything to avoid unnecessarily complicating the API. - // folks can use all the same utilities we return in the first place that are bound to the container - }, - asFragment: () => { - /* istanbul ignore if (jsdom limitation) */ - if (typeof document.createRange === 'function') { - return document - .createRange() - .createContextualFragment(container.innerHTML) - } - - const template = document.createElement('template') - template.innerHTML = container.innerHTML - return template.content - }, - ...getQueriesForElement(baseElement, queries), - } -} - -function cleanup() { - mountedContainers.forEach(cleanupAtContainer) -} - -// maybe one day we'll expose this (perhaps even as a utility returned by render). -// but let's wait until someone asks for it. -function cleanupAtContainer(container) { - ReactDOM.unmountComponentAtNode(container) - if (container.parentNode === document.body) { - document.body.removeChild(container) - } - mountedContainers.delete(container) -} - -// react-testing-library's version of fireEvent will call -// dom-testing-library's version of fireEvent wrapped inside -// an "act" call so that after all event callbacks have been -// been called, the resulting useEffect callbacks will also -// be called. -function fireEvent(...args) { - let returnValue - act(() => { - returnValue = dtlFireEvent(...args) - }) - return returnValue -} - -Object.keys(dtlFireEvent).forEach(key => { - fireEvent[key] = (...args) => { - let returnValue - act(() => { - returnValue = dtlFireEvent[key](...args) - }) - return returnValue - } -}) - -// React event system tracks native mouseOver/mouseOut events for -// running onMouseEnter/onMouseLeave handlers -// @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/EnterLeaveEventPlugin.js#L24-L31 -fireEvent.mouseEnter = fireEvent.mouseOver -fireEvent.mouseLeave = fireEvent.mouseOut - -fireEvent.select = (node, init) => { - // React tracks this event only on focused inputs - node.focus() - - // React creates this event when one of the following native events happens - // - contextMenu - // - mouseUp - // - dragEnd - // - keyUp - // - keyDown - // so we can use any here - // @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/SelectEventPlugin.js#L203-L224 - fireEvent.keyUp(node, init) -} +import {asyncAct} from './act-compat' +import {cleanup} from './pure' // if we're running in a test runner that supports afterEach // then we'll automatically run cleanup afterEach test // this ensures that tests run in isolation from each other -if (typeof afterEach === 'function' && !process.env.RTL_SKIP_CLEANUP) { +// if you don't like this then either import the `pure` module +// or set the RTL_SKIP_AUTO_CLEANUP env variable to 'true'. +if (typeof afterEach === 'function' && !process.env.RTL_SKIP_AUTO_CLEANUP) { afterEach(async () => { await asyncAct(async () => {}) cleanup() }) } -// just re-export everything from dom-testing-library -export * from '@testing-library/dom' -export {render, cleanup, fireEvent, act} - -// NOTE: we're not going to export asyncAct because that's our own compatibility -// thing for people using react-dom@16.8.0. Anyone else doesn't need it and -// people should just upgrade anyway. - -/* eslint func-name-matching:0 */ +export * from './pure' diff --git a/src/pure.js b/src/pure.js new file mode 100644 index 00000000..4565074b --- /dev/null +++ b/src/pure.js @@ -0,0 +1,153 @@ +import React from 'react' +import ReactDOM from 'react-dom' +import { + getQueriesForElement, + prettyDOM, + fireEvent as dtlFireEvent, + configure as configureDTL, +} from '@testing-library/dom' +import act, {asyncAct} from './act-compat' + +configureDTL({ + asyncWrapper: async cb => { + let result + await asyncAct(async () => { + result = await cb() + }) + return result + }, +}) + +const mountedContainers = new Set() + +function render( + ui, + { + container, + baseElement = container, + queries, + hydrate = false, + wrapper: WrapperComponent, + } = {}, +) { + if (!baseElement) { + // default to document.body instead of documentElement to avoid output of potentially-large + // head elements (such as JSS style blocks) in debug output + baseElement = document.body + } + if (!container) { + container = baseElement.appendChild(document.createElement('div')) + } + + // we'll add it to the mounted containers regardless of whether it's actually + // added to document.body so the cleanup method works regardless of whether + // they're passing us a custom container or not. + mountedContainers.add(container) + + const wrapUiIfNeeded = innerElement => + WrapperComponent + ? React.createElement(WrapperComponent, null, innerElement) + : innerElement + + act(() => { + if (hydrate) { + ReactDOM.hydrate(wrapUiIfNeeded(ui), container) + } else { + ReactDOM.render(wrapUiIfNeeded(ui), container) + } + }) + + return { + container, + baseElement, + // eslint-disable-next-line no-console + debug: (el = baseElement) => console.log(prettyDOM(el)), + unmount: () => ReactDOM.unmountComponentAtNode(container), + rerender: rerenderUi => { + render(wrapUiIfNeeded(rerenderUi), {container, baseElement}) + // Intentionally do not return anything to avoid unnecessarily complicating the API. + // folks can use all the same utilities we return in the first place that are bound to the container + }, + asFragment: () => { + /* istanbul ignore if (jsdom limitation) */ + if (typeof document.createRange === 'function') { + return document + .createRange() + .createContextualFragment(container.innerHTML) + } + + const template = document.createElement('template') + template.innerHTML = container.innerHTML + return template.content + }, + ...getQueriesForElement(baseElement, queries), + } +} + +function cleanup() { + mountedContainers.forEach(cleanupAtContainer) +} + +// maybe one day we'll expose this (perhaps even as a utility returned by render). +// but let's wait until someone asks for it. +function cleanupAtContainer(container) { + ReactDOM.unmountComponentAtNode(container) + if (container.parentNode === document.body) { + document.body.removeChild(container) + } + mountedContainers.delete(container) +} + +// react-testing-library's version of fireEvent will call +// dom-testing-library's version of fireEvent wrapped inside +// an "act" call so that after all event callbacks have been +// been called, the resulting useEffect callbacks will also +// be called. +function fireEvent(...args) { + let returnValue + act(() => { + returnValue = dtlFireEvent(...args) + }) + return returnValue +} + +Object.keys(dtlFireEvent).forEach(key => { + fireEvent[key] = (...args) => { + let returnValue + act(() => { + returnValue = dtlFireEvent[key](...args) + }) + return returnValue + } +}) + +// React event system tracks native mouseOver/mouseOut events for +// running onMouseEnter/onMouseLeave handlers +// @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/EnterLeaveEventPlugin.js#L24-L31 +fireEvent.mouseEnter = fireEvent.mouseOver +fireEvent.mouseLeave = fireEvent.mouseOut + +fireEvent.select = (node, init) => { + // React tracks this event only on focused inputs + node.focus() + + // React creates this event when one of the following native events happens + // - contextMenu + // - mouseUp + // - dragEnd + // - keyUp + // - keyDown + // so we can use any here + // @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/SelectEventPlugin.js#L203-L224 + fireEvent.keyUp(node, init) +} + +// just re-export everything from dom-testing-library +export * from '@testing-library/dom' +export {render, cleanup, fireEvent, act} + +// NOTE: we're not going to export asyncAct because that's our own compatibility +// thing for people using react-dom@16.8.0. Anyone else doesn't need it and +// people should just upgrade anyway. + +/* eslint func-name-matching:0 */ From 1dd65446fb4f67364966e4b856f1ae729af72dc9 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 9 Aug 2019 13:45:48 -0600 Subject: [PATCH 066/327] feat(deps): update @testing-library/dom to 6.0.0 BREAKING CHANGE: If you were using `debugDOM` before, use `prettyDOM` instead. Note that `debugDOM` is different from `debug` which you get back from `render`. That is unchanged. --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d27b209a..84e734d3 100644 --- a/package.json +++ b/package.json @@ -43,12 +43,12 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.5.5", - "@testing-library/dom": "^5.6.1" + "@testing-library/dom": "^6.0.0" }, "devDependencies": { "@reach/router": "^1.2.1", "@testing-library/jest-dom": "^4.0.0", - "@types/react": "^16.8.25", + "@types/react": "^16.9.1", "@types/react-dom": "^16.8.5", "kcd-scripts": "^1.5.2", "react": "^16.9.0", From 0b83ca5720b40ab1731e0c1ed924833d8728eeea Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 9 Aug 2019 14:12:57 -0600 Subject: [PATCH 067/327] fix(cleanup-after-each): remove cleanup-after-each file. (#433) This is automatic now, so there is no reason to have it Closes #433 --- cleanup-after-each.js | 3 --- package.json | 1 - src/__tests__/cleanup-after-each.js | 32 ----------------------------- src/cleanup-async.js | 10 --------- 4 files changed, 46 deletions(-) delete mode 100644 cleanup-after-each.js delete mode 100644 src/__tests__/cleanup-after-each.js delete mode 100644 src/cleanup-async.js diff --git a/cleanup-after-each.js b/cleanup-after-each.js deleted file mode 100644 index 9bbba5ce..00000000 --- a/cleanup-after-each.js +++ /dev/null @@ -1,3 +0,0 @@ -afterEach(() => { - return require('./dist/cleanup-async')() -}) diff --git a/package.json b/package.json index 84e734d3..78b89545 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "files": [ "dist", "typings", - "cleanup-after-each.js", "pure.js" ], "keywords": [ diff --git a/src/__tests__/cleanup-after-each.js b/src/__tests__/cleanup-after-each.js deleted file mode 100644 index 3f7e139b..00000000 --- a/src/__tests__/cleanup-after-each.js +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react' -import {render} from '../' -import cleanupAsync from '../cleanup-async' - -afterEach(() => { - return cleanupAsync() -}) - -const log = [] -let ctr = 0 - -function App() { - async function somethingAsync() { - await null - log.push(ctr++) - } - React.useEffect(() => { - somethingAsync() - }, []) - return 123 -} - -test('does not leave any hanging microtasks: part 1', () => { - render() - expect(document.body.textContent).toBe('123') - expect(log).toEqual([]) -}) - -test('does not leave any hanging microtasks: part 2', () => { - expect(log).toEqual([0]) - expect(document.body.innerHTML).toBe('') -}) diff --git a/src/cleanup-async.js b/src/cleanup-async.js deleted file mode 100644 index 0031db56..00000000 --- a/src/cleanup-async.js +++ /dev/null @@ -1,10 +0,0 @@ -// This file is for use by the top-level export -// @testing-library/react/cleanup-after-each -// It is not meant to be used directly - -module.exports = async function cleanupAsync() { - const {asyncAct} = require('./act-compat') - const {cleanup} = require('./index') - await asyncAct(async () => {}) - cleanup() -} From 8277b06c199cacb0e81597aa506151de7a71b439 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 9 Aug 2019 14:35:16 -0600 Subject: [PATCH 068/327] fix: restore cleanup-after-each and include a deprecation warning ref: #433 --- cleanup-after-each.js | 4 ++++ package.json | 1 + 2 files changed, 5 insertions(+) create mode 100644 cleanup-after-each.js diff --git a/cleanup-after-each.js b/cleanup-after-each.js new file mode 100644 index 00000000..ace739eb --- /dev/null +++ b/cleanup-after-each.js @@ -0,0 +1,4 @@ +console.warn( + 'The module `@testing-library/react/cleanup-after-each` has been deprecated and no longer does anything (it is not needed). You no longer need to import this module and can safely remove any import or configuration which imports this module', +) +/* eslint no-console:0 */ diff --git a/package.json b/package.json index 78b89545..84e734d3 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "files": [ "dist", "typings", + "cleanup-after-each.js", "pure.js" ], "keywords": [ From f4b813e60390501e5db825e1270cc0294fa440b7 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Sat, 10 Aug 2019 11:36:08 -0600 Subject: [PATCH 069/327] feat: add dont-cleanup-after-each.js (#435) This is just a simple file that sets the RTL_SKIP_AUTO_CLEANUP environment variable so that RTL doesn't setup automatic cleanup. This makes it easier for folks who don't want to write their tests in an isolated way. It's totally not recommended, but it will hopefully reduce pain while people migrate from one testing style to another. --- dont-cleanup-after-each.js | 1 + package.json | 1 + 2 files changed, 2 insertions(+) create mode 100644 dont-cleanup-after-each.js diff --git a/dont-cleanup-after-each.js b/dont-cleanup-after-each.js new file mode 100644 index 00000000..083a8188 --- /dev/null +++ b/dont-cleanup-after-each.js @@ -0,0 +1 @@ +process.env.RTL_SKIP_AUTO_CLEANUP = true diff --git a/package.json b/package.json index 84e734d3..279e065e 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "dist", "typings", "cleanup-after-each.js", + "dont-cleanup-after-each.js", "pure.js" ], "keywords": [ From b5584ebb301f1a0c2cf09236528d1a79656d5e6e Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 13 Aug 2019 01:41:16 +0200 Subject: [PATCH 070/327] fix(TS): act type (#438) * fix(types): Use act types from react-dom * Fix unary not extending binary --- package.json | 3 ++- typings/index.d.ts | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 279e065e..ff29c1af 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,8 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.5.5", - "@testing-library/dom": "^6.0.0" + "@testing-library/dom": "^6.0.0", + "@types/react-dom": "*" }, "devDependencies": { "@reach/router": "^1.2.1", diff --git a/typings/index.d.ts b/typings/index.d.ts index ddc5512a..ab4528e2 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1,4 +1,5 @@ import {queries, Queries, BoundFunction} from '@testing-library/dom' +import {act as reactAct} from 'react-dom/test-utils' export * from '@testing-library/dom' @@ -43,4 +44,6 @@ export function cleanup(): void * If that's not available (older version of react) then it * simply calls the given callback immediately */ -export function act(callback: () => void): void +export const act: typeof reactAct extends undefined + ? (callback: () => void) => void + : typeof reactAct From 29aad25c7576670bbbe5096fd39bda7c282e702e Mon Sep 17 00:00:00 2001 From: Alex Krolick Date: Thu, 15 Aug 2019 12:21:48 -0700 Subject: [PATCH 071/327] fix(typescript): move typings to DefinitelyTyped (#437) You should not need to make any changes to upgrade to this version. We're just doing this to improve TypeScript maintenance. Co-authored-by: Kent C. Dodds --- CONTRIBUTING.md | 35 +++------------------------------ package.json | 6 +----- typings/index.d.ts | 49 ---------------------------------------------- 3 files changed, 4 insertions(+), 86 deletions(-) delete mode 100644 typings/index.d.ts diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7cc35e72..de766c7a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,45 +26,16 @@ series [How to Contribute to an Open Source Project on GitHub][egghead] > can make all of your pull request branches based on this `master` branch. > Whenever you want to update your version of `master`, do a regular `git pull`. -## Add yourself as a contributor - -This project follows the [all contributors][all-contributors] specification. To -add yourself to the table of contributors on the `README.md`, please use the -automated script as part of your PR: - -```console -npm run add-contributor -``` - -Follow the prompt and commit `.all-contributorsrc` and `README.md` in the PR. If -you've already added yourself to the list and are making a new type of -contribution, you can run it again and select the added contribution type. - ## Committing and Pushing changes Please make sure to run the tests before you commit your changes. You can run `npm run test:update` which will update any snapshots that need updating. Make sure to include those changes (if they exist) in your commit. -### opt into git hooks - -There are git hooks set up with this project that are automatically installed -when you install dependencies. They're really handy, but are turned off by -default (so as to not hinder new contributors). You can opt into these by -creating a file called `.opt-in` at the root of the project and putting this -inside: - -``` -pre-commit -``` - -### Add typings +### Update Typings -If your PR introduced some changes in the API, you are more than welcome to -modify the Typescript type definition to reflect those changes. Just modify the -`/typings/index.d.ts` file accordingly. If you have never seen Typescript -definitions before, you can read more about it in its -[documentation pages](https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html) +The TypeScript type definitions are in the +[DefinitelyTyped repo](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/testing-library__react) ## Help needed diff --git a/package.json b/package.json index ff29c1af..56aa7346 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,6 @@ "description": "Simple and complete React DOM testing utilities that encourage good testing practices.", "main": "dist/index.js", "module": "dist/@testing-library/react.esm.js", - "typings": "typings/index.d.ts", "engines": { "node": ">=8" }, @@ -23,7 +22,6 @@ }, "files": [ "dist", - "typings", "cleanup-after-each.js", "dont-cleanup-after-each.js", "pure.js" @@ -45,13 +43,11 @@ "dependencies": { "@babel/runtime": "^7.5.5", "@testing-library/dom": "^6.0.0", - "@types/react-dom": "*" + "@types/testing-library__react": "^9.1.0" }, "devDependencies": { "@reach/router": "^1.2.1", "@testing-library/jest-dom": "^4.0.0", - "@types/react": "^16.9.1", - "@types/react-dom": "^16.8.5", "kcd-scripts": "^1.5.2", "react": "^16.9.0", "react-dom": "^16.9.0" diff --git a/typings/index.d.ts b/typings/index.d.ts deleted file mode 100644 index ab4528e2..00000000 --- a/typings/index.d.ts +++ /dev/null @@ -1,49 +0,0 @@ -import {queries, Queries, BoundFunction} from '@testing-library/dom' -import {act as reactAct} from 'react-dom/test-utils' - -export * from '@testing-library/dom' - -export type RenderResult = { - container: HTMLElement - baseElement: HTMLElement - debug: (baseElement?: HTMLElement | DocumentFragment) => void - rerender: (ui: React.ReactElement) => void - unmount: () => boolean - asFragment: () => DocumentFragment -} & {[P in keyof Q]: BoundFunction} - -export interface RenderOptions { - container?: HTMLElement - baseElement?: HTMLElement - hydrate?: boolean - queries?: Q - wrapper?: React.ComponentType -} - -type Omit = Pick> - -/** - * Render into a container which is appended to document.body. It should be used with cleanup. - */ -export function render( - ui: React.ReactElement, - options?: Omit, -): RenderResult -export function render( - ui: React.ReactElement, - options: RenderOptions, -): RenderResult - -/** - * Unmounts React trees that were mounted with render. - */ -export function cleanup(): void - -/** - * Simply calls ReactDOMTestUtils.act(cb) - * If that's not available (older version of react) then it - * simply calls the given callback immediately - */ -export const act: typeof reactAct extends undefined - ? (callback: () => void) => void - : typeof reactAct From a4fa8413bbab8b08518994e96322622fc0008f72 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2019 13:23:07 -0600 Subject: [PATCH 072/327] docs: add nickmccurdy as a contributor (#444) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 24dbb2ee..03ea3c9a 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -865,6 +865,15 @@ "contributions": [ "review" ] + }, + { + "login": "nickmccurdy", + "name": "Nick McCurdy", + "avatar_url": "https://avatars0.githubusercontent.com/u/927220?v=4", + "profile": "https://nickmccurdy.com/", + "contributions": [ + "review" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 8008d6b7..81424e6f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-89-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-90-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -501,6 +501,7 @@ Thanks goes to these people ([emoji key][emojis]): James George
James George

πŸ“– JoΓ£o Fernandes
JoΓ£o Fernandes

πŸ“– Alejandro Perea
Alejandro Perea

πŸ‘€ + Nick McCurdy
Nick McCurdy

πŸ‘€ From e92ace801b6e374186f762e47a6483e3715b106f Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2019 13:23:39 -0600 Subject: [PATCH 073/327] docs: add eps1lon as a contributor (#445) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 03ea3c9a..72c045fb 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -874,6 +874,15 @@ "contributions": [ "review" ] + }, + { + "login": "eps1lon", + "name": "Sebastian Silbermann", + "avatar_url": "https://avatars3.githubusercontent.com/u/12292047?v=4", + "profile": "https://twitter.com/sebsilbermann", + "contributions": [ + "review" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 81424e6f..5c5bfeb2 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-90-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-91-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -502,6 +502,7 @@ Thanks goes to these people ([emoji key][emojis]): JoΓ£o Fernandes
JoΓ£o Fernandes

πŸ“– Alejandro Perea
Alejandro Perea

πŸ‘€ Nick McCurdy
Nick McCurdy

πŸ‘€ + Sebastian Silbermann
Sebastian Silbermann

πŸ‘€ From d8a843d4fb7928e1f19285fd8a0fe30015d3737c Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2019 13:24:20 -0600 Subject: [PATCH 074/327] docs: add weyert as a contributor (#447) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> From aea79db2e1fdf4076bc457fba4bdd651ae4b6583 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2019 13:25:16 -0600 Subject: [PATCH 075/327] docs: add afontcu as a contributor (#448) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 72c045fb..2bc1ae63 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -883,6 +883,15 @@ "contributions": [ "review" ] + }, + { + "login": "afontcu", + "name": "AdriΓ  Fontcuberta", + "avatar_url": "https://avatars0.githubusercontent.com/u/9197791?v=4", + "profile": "https://afontcu.dev", + "contributions": [ + "review" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 5c5bfeb2..926c8295 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-91-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-92-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -504,6 +504,9 @@ Thanks goes to these people ([emoji key][emojis]): Nick McCurdy
Nick McCurdy

πŸ‘€ Sebastian Silbermann
Sebastian Silbermann

πŸ‘€ + + AdriΓ  Fontcuberta
AdriΓ  Fontcuberta

πŸ‘€ + From 23e50ac3c926c4e5ae52507ca7c375999cc700e2 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2019 13:25:48 -0600 Subject: [PATCH 076/327] docs: add johnnyreilly as a contributor (#449) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 2bc1ae63..096682c1 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -892,6 +892,15 @@ "contributions": [ "review" ] + }, + { + "login": "johnnyreilly", + "name": "John Reilly", + "avatar_url": "https://avatars0.githubusercontent.com/u/1010525?v=4", + "profile": "https://blog.johnnyreilly.com/", + "contributions": [ + "review" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 926c8295..c6cccd1d 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-92-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-93-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -506,6 +506,7 @@ Thanks goes to these people ([emoji key][emojis]): AdriΓ  Fontcuberta
AdriΓ  Fontcuberta

πŸ‘€ + John Reilly
John Reilly

πŸ‘€ From 9c9e518929a7fc7bd72dac71eb2967f5b1929386 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2019 13:26:30 -0600 Subject: [PATCH 077/327] docs: add MichaelDeBoey as a contributor (#450) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 096682c1..92e497ec 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -901,6 +901,15 @@ "contributions": [ "review" ] + }, + { + "login": "MichaelDeBoey", + "name": "MichaΓ«l De Boey", + "avatar_url": "https://avatars3.githubusercontent.com/u/6643991?v=4", + "profile": "https://michaeldeboey.be", + "contributions": [ + "review" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index c6cccd1d..7e949b46 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-93-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-94-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -507,6 +507,7 @@ Thanks goes to these people ([emoji key][emojis]): AdriΓ  Fontcuberta
AdriΓ  Fontcuberta

πŸ‘€ John Reilly
John Reilly

πŸ‘€ + MichaΓ«l De Boey
MichaΓ«l De Boey

πŸ‘€ From 4ed01c374b9e3e10c29b979499181aa325d0c526 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2019 13:27:07 -0600 Subject: [PATCH 078/327] docs: add cimbul as a contributor (#451) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 92e497ec..d8323946 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -910,6 +910,15 @@ "contributions": [ "review" ] + }, + { + "login": "cimbul", + "name": "Tim Yates", + "avatar_url": "https://avatars2.githubusercontent.com/u/927923?v=4", + "profile": "https://cimbul.com", + "contributions": [ + "review" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 7e949b46..5137cd09 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-94-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-95-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -508,6 +508,7 @@ Thanks goes to these people ([emoji key][emojis]): AdriΓ  Fontcuberta
AdriΓ  Fontcuberta

πŸ‘€ John Reilly
John Reilly

πŸ‘€ MichaΓ«l De Boey
MichaΓ«l De Boey

πŸ‘€ + Tim Yates
Tim Yates

πŸ‘€ From 2bbfff3710ce96ca01e7a36f0c12e6ae645c35db Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2019 13:27:27 -0600 Subject: [PATCH 079/327] docs: add FredyC as a contributor (#452) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 3 ++- README.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index d8323946..bdc785ef 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -678,7 +678,8 @@ "bug", "code", "ideas", - "test" + "test", + "review" ] }, { diff --git a/README.md b/README.md index 5137cd09..555ffbb0 100644 --- a/README.md +++ b/README.md @@ -474,7 +474,7 @@ Thanks goes to these people ([emoji key][emojis]): Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️ Alex Zherdev
Alex Zherdev

πŸ› πŸ’» AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️ - Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️ + Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️ πŸ‘€ mohamedmagdy17593
mohamedmagdy17593

πŸ’» From f4f3ea566eef3f61090ef93d7da0229d2e67a160 Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Fri, 16 Aug 2019 14:08:04 -0700 Subject: [PATCH 080/327] fix: use apply for console error args when proxying (#454) * fix: spread console error args when proxying Without this the proxied errors are logged as an array, which is not very helpful. * Update act-compat.js * Update old-act.js Co-authored-by: Kent C. Dodds --- src/__tests__/old-act.js | 4 +--- src/act-compat.js | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/__tests__/old-act.js b/src/__tests__/old-act.js index 0098ed08..fcd531b4 100644 --- a/src/__tests__/old-act.js +++ b/src/__tests__/old-act.js @@ -34,9 +34,7 @@ test('async act works even when the act is an old one', async () => { expect(console.error.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - Array [ - "sigil", - ], + "sigil", ], Array [ "It looks like you're using a version of react-dom that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.", diff --git a/src/act-compat.js b/src/act-compat.js index e16b135f..dd5f1d96 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -42,7 +42,7 @@ function asyncAct(cb) { ) { // no-op } else { - originalConsoleError.call(console, args) + originalConsoleError.apply(console, args) } } let cbReturn, result From 21869777362172e6ec44c164a7f7944aa43a17c1 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 16 Aug 2019 15:08:35 -0600 Subject: [PATCH 081/327] docs: add eventualbuddha as a contributor (#455) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index bdc785ef..5ae31ec3 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -920,6 +920,15 @@ "contributions": [ "review" ] + }, + { + "login": "eventualbuddha", + "name": "Brian Donovan", + "avatar_url": "https://avatars3.githubusercontent.com/u/1938?v=4", + "profile": "https://github.com/eventualbuddha", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 555ffbb0..f39c90a8 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-95-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-96-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -509,6 +509,7 @@ Thanks goes to these people ([emoji key][emojis]): John Reilly
John Reilly

πŸ‘€ MichaΓ«l De Boey
MichaΓ«l De Boey

πŸ‘€ Tim Yates
Tim Yates

πŸ‘€ + Brian Donovan
Brian Donovan

πŸ’» From f4f1b7526eac32f9ba744593dc91e6991d5fc0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Fontcuberta?= Date: Sat, 17 Aug 2019 22:01:38 +0200 Subject: [PATCH 082/327] Update names and links (#457) --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index f39c90a8..5810a414 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ @@ -85,7 +85,7 @@ your team down. ## This solution -The `react-testing-library` is a very lightweight solution for testing React +The `React Testing Library` is a very lightweight solution for testing React components. It provides light utility functions on top of `react-dom` and `react-dom/test-utils`, in a way that encourages better testing practices. Its primary guiding principle is: @@ -312,18 +312,18 @@ Some included are: - [`react-router`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-router.js&previewwindow=tests) - [`react-context`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-context.js&previewwindow=tests) -You can also find react-testing-library examples at +You can also find React Testing Library examples at [react-testing-examples.com](https://react-testing-examples.com/jest-rtl/). ## Hooks If you are interested in testing a custom hook, check out -[react-hooks-testing-library][react-hooks-testing-library]. +[React Hooks Testing Library][react-hooks-testing-library]. > NOTE it is not recommended to test single-use custom hooks in isolation from > the components where it's being used. It's better to test the component that's -> using the hook rather than the hook itself. The react-hooks-testing-library is -> intended to be used for reusable hooks/libraries. +> using the hook rather than the hook itself. The `React Hooks Testing Library` +> is intended to be used for reusable hooks/libraries. ## Guiding Principles @@ -351,7 +351,7 @@ light-weight, simple, and understandable. ## Docs [**Read The Docs**](https://testing-library.com/react) | -[Edit the docs](https://github.com/alexkrolick/testing-library-docs) +[Edit the docs](https://github.com/testing-library/testing-library-docs) ## Issues @@ -556,6 +556,6 @@ Contributions of any kind welcome! [good-first-issue]: https://github.com/testing-library/react-testing-library/issues?utf8=βœ“&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3A"good+first+issue"+ [reactiflux]: https://www.reactiflux.com/ [stackoverflow]: https://stackoverflow.com/questions/tagged/react-testing-library -[react-hooks-testing-library]: https://github.com/mpeyper/react-hooks-testing-library +[react-hooks-testing-library]: https://github.com/testing-library/react-hooks-testing-library From c4ba755e42938018ec67dbc716037cfafca15e03 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 17 Aug 2019 14:02:15 -0600 Subject: [PATCH 083/327] docs: add afontcu as a contributor (#458) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 3 ++- README.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 5ae31ec3..71618a32 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -891,7 +891,8 @@ "avatar_url": "https://avatars0.githubusercontent.com/u/9197791?v=4", "profile": "https://afontcu.dev", "contributions": [ - "review" + "review", + "doc" ] }, { diff --git a/README.md b/README.md index 5810a414..57171e77 100644 --- a/README.md +++ b/README.md @@ -505,7 +505,7 @@ Thanks goes to these people ([emoji key][emojis]): Sebastian Silbermann
Sebastian Silbermann

πŸ‘€ - AdriΓ  Fontcuberta
AdriΓ  Fontcuberta

πŸ‘€ + AdriΓ  Fontcuberta
AdriΓ  Fontcuberta

πŸ‘€ πŸ“– John Reilly
John Reilly

πŸ‘€ MichaΓ«l De Boey
MichaΓ«l De Boey

πŸ‘€ Tim Yates
Tim Yates

πŸ‘€ From e0ab0a8103407bb846723c3c3ed9c3a1b629dfec Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Tue, 20 Aug 2019 14:08:22 -0600 Subject: [PATCH 084/327] chore: delete funding.yml We don't want people's money. We want their support. https://testing-library.com/support --- .github/FUNDING.yml | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index e9dc1c69..00000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -open_collective: testing-library -github: [kentcdodds] From dca5d9a7d744b66e5f937aadb819fc5ceed5c19a Mon Sep 17 00:00:00 2001 From: Noam Gabriel Jacobson Date: Tue, 20 Aug 2019 22:30:38 -0400 Subject: [PATCH 085/327] docs: update README.md (#461) Removing `import '@testing-library/react/cleanup-after-each'; ` due to deprecation. --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 57171e77..1ac6e455 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,6 @@ export default HiddenMessage // __tests__/hidden-message.js // these imports are something you'd normally configure Jest to import for you // automatically. Learn more in the setup docs: https://testing-library.com/docs/react-testing-library/setup#cleanup -import '@testing-library/react/cleanup-after-each' import '@testing-library/jest-dom/extend-expect' // NOTE: jest-dom adds handy assertions to Jest and is recommended, but not required @@ -264,7 +263,6 @@ export default Login // __tests__/login.js // again, these first two imports are something you'd normally handle in // your testing framework configuration rather than importing them in every file. -import '@testing-library/react/cleanup-after-each' import '@testing-library/jest-dom/extend-expect' import React from 'react' import {render, fireEvent} from '@testing-library/react' From 67d943d24aa23850f534a1353bb58354b8fdb510 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2019 20:31:10 -0600 Subject: [PATCH 086/327] docs: add JaysQubeXon as a contributor (#462) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 71618a32..4d743bae 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -930,6 +930,15 @@ "contributions": [ "code" ] + }, + { + "login": "JaysQubeXon", + "name": "Noam Gabriel Jacobson", + "avatar_url": "https://avatars1.githubusercontent.com/u/18309230?v=4", + "profile": "https://github.com/JaysQubeXon", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 1ac6e455..cafb1b9f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-96-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-97-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -508,6 +508,7 @@ Thanks goes to these people ([emoji key][emojis]): MichaΓ«l De Boey
MichaΓ«l De Boey

πŸ‘€ Tim Yates
Tim Yates

πŸ‘€ Brian Donovan
Brian Donovan

πŸ’» + Noam Gabriel Jacobson
Noam Gabriel Jacobson

πŸ“– From c4e51fbbc8895669a5159e5655b7b6d9bc7f8659 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 21 Aug 2019 11:34:58 -0600 Subject: [PATCH 087/327] chore: update all deps --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 56aa7346..7f164c11 100644 --- a/package.json +++ b/package.json @@ -42,13 +42,13 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.5.5", - "@testing-library/dom": "^6.0.0", + "@testing-library/dom": "^6.1.0", "@types/testing-library__react": "^9.1.0" }, "devDependencies": { "@reach/router": "^1.2.1", - "@testing-library/jest-dom": "^4.0.0", - "kcd-scripts": "^1.5.2", + "@testing-library/jest-dom": "^4.1.0", + "kcd-scripts": "^1.7.0", "react": "^16.9.0", "react-dom": "^16.9.0" }, From 7a7647f6b31b69b73d1b247d93df76803485ffe1 Mon Sep 17 00:00:00 2001 From: Ronald van der Kooij Date: Sun, 25 Aug 2019 00:21:14 +0200 Subject: [PATCH 088/327] chore: fixed the eslint jest/no-if error by not needing the if statement anymore (#465) --- src/__tests__/rerender.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/__tests__/rerender.js b/src/__tests__/rerender.js index ff30ffd5..7cb9156d 100644 --- a/src/__tests__/rerender.js +++ b/src/__tests__/rerender.js @@ -10,23 +10,22 @@ test('rerender will re-render the element', () => { }) test('hydrate will not update props until next render', () => { - const initial = '' + const initialInputElement = document.createElement('input') + const container = document.createElement('div') + container.appendChild(initialInputElement) + document.body.appendChild(container) - const container = document.body.appendChild(document.createElement('div')) - container.innerHTML = initial - const input = container.querySelector('input') const firstValue = 'hello' + initialInputElement.value = firstValue - if (!input) throw new Error('No element') - input.value = firstValue const {rerender} = render( null} />, { container, hydrate: true, }) - const secondValue = 'goodbye' + expect(initialInputElement.value).toBe(firstValue) - expect(input.value).toBe(firstValue) + const secondValue = 'goodbye' rerender( null} />) - expect(input.value).toBe(secondValue) + expect(initialInputElement.value).toBe(secondValue) }) From 8881803ea50f773cf909764299e68f35e22478d1 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 24 Aug 2019 16:21:45 -0600 Subject: [PATCH 089/327] docs: add rvdkooy as a contributor (#466) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 4d743bae..08949c27 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -939,6 +939,15 @@ "contributions": [ "doc" ] + }, + { + "login": "rvdkooy", + "name": "Ronald van der Kooij", + "avatar_url": "https://avatars1.githubusercontent.com/u/4119960?v=4", + "profile": "https://github.com/rvdkooy", + "contributions": [ + "test" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index cafb1b9f..8bc8738c 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-97-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-98-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -509,6 +509,7 @@ Thanks goes to these people ([emoji key][emojis]): Tim Yates
Tim Yates

πŸ‘€ Brian Donovan
Brian Donovan

πŸ’» Noam Gabriel Jacobson
Noam Gabriel Jacobson

πŸ“– + Ronald van der Kooij
Ronald van der Kooij

⚠️ From 59e20f8dbcb11e09947b55da81056c2f18c470ac Mon Sep 17 00:00:00 2001 From: Aayush Rajvanshi Date: Tue, 3 Sep 2019 18:26:29 +0530 Subject: [PATCH 090/327] docs: pdate README.md example (#474) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8bc8738c..f1677e32 100644 --- a/README.md +++ b/README.md @@ -251,7 +251,7 @@ function Login() { {state.error ?
{state.error.message}
: null} - {state.success ? ( + {state.resolved ? (
Congrats! You're signed in!
) : null}
From 7db67b38188fcbc33e05b73d85c1c3654200d496 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2019 06:57:09 -0600 Subject: [PATCH 091/327] docs: add aayushrajvanshi as a contributor (#475) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 08949c27..1ff0fd54 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -948,6 +948,15 @@ "contributions": [ "test" ] + }, + { + "login": "aayushrajvanshi", + "name": "Aayush Rajvanshi", + "avatar_url": "https://avatars0.githubusercontent.com/u/14968551?v=4", + "profile": "https://github.com/aayushrajvanshi", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index f1677e32..75e81f0d 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-98-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-99-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -511,6 +511,9 @@ Thanks goes to these people ([emoji key][emojis]): Noam Gabriel Jacobson
Noam Gabriel Jacobson

πŸ“– Ronald van der Kooij
Ronald van der Kooij

⚠️ + + Aayush Rajvanshi
Aayush Rajvanshi

πŸ“– + From 139df628291511a9ce0c3a559c2c245f7ce64747 Mon Sep 17 00:00:00 2001 From: Ronald van der Kooij Date: Tue, 3 Sep 2019 23:39:31 +0200 Subject: [PATCH 092/327] fix: console.error doesn't have to be a string in act.compat.js (#476) * checking the type of args in act-compat before doing an indexOf * removed unused code * noop scenario for console.error was not tested in act-compat --- src/__tests__/old-act.js | 41 ++++++++++++++++++++++++++++++++++++++++ src/act-compat.js | 3 +++ 2 files changed, 44 insertions(+) diff --git a/src/__tests__/old-act.js b/src/__tests__/old-act.js index fcd531b4..b3de9377 100644 --- a/src/__tests__/old-act.js +++ b/src/__tests__/old-act.js @@ -98,4 +98,45 @@ test('async act recovers from sync errors', async () => { `) }) +test('async act can handle any sort of console.error', async () => { + await asyncAct(async () => { + console.error({error: 'some error'}) + await null + }) + + expect(console.error).toHaveBeenCalledTimes(2) + expect(console.error.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "error": "some error", + }, + ], + Array [ + "It looks like you're using a version of react-dom that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.", + ], + ] + `) +}) + +test('async act should not show an error when ReactTestUtils.act returns something', async () => { + jest.resetModules() + jest.mock('react-dom/test-utils', () => ({ + act: () => { + return new Promise(resolve => { + console.error( + 'Warning: The callback passed to ReactTestUtils.act(...) function must not return anything', + ) + resolve() + }) + }, + })) + asyncAct = require('../act-compat').asyncAct + await asyncAct(async () => { + await null + }) + + expect(console.error).toHaveBeenCalledTimes(0) +}) + /* eslint no-console:0 */ diff --git a/src/act-compat.js b/src/act-compat.js index dd5f1d96..d758a97c 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -28,7 +28,9 @@ function asyncAct(cb) { console.error = function error(...args) { /* if console.error fired *with that specific message* */ /* istanbul ignore next */ + const firstArgIsString = typeof args[0] === 'string' if ( + firstArgIsString && args[0].indexOf( 'Warning: Do not await the result of calling ReactTestUtils.act', ) === 0 @@ -36,6 +38,7 @@ function asyncAct(cb) { // v16.8.6 isAsyncActSupported = false } else if ( + firstArgIsString && args[0].indexOf( 'Warning: The callback passed to ReactTestUtils.act(...) function must not return anything', ) === 0 From fa9260e43c06fd311d3af5d1e0d0a42862ea870f Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2019 15:40:31 -0600 Subject: [PATCH 093/327] docs: add rvdkooy as a contributor (#477) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 3 ++- README.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 1ff0fd54..d3c5da47 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -946,7 +946,8 @@ "avatar_url": "https://avatars1.githubusercontent.com/u/4119960?v=4", "profile": "https://github.com/rvdkooy", "contributions": [ - "test" + "test", + "code" ] }, { diff --git a/README.md b/README.md index 75e81f0d..1c7493fc 100644 --- a/README.md +++ b/README.md @@ -509,7 +509,7 @@ Thanks goes to these people ([emoji key][emojis]): Tim Yates
Tim Yates

πŸ‘€ Brian Donovan
Brian Donovan

πŸ’» Noam Gabriel Jacobson
Noam Gabriel Jacobson

πŸ“– - Ronald van der Kooij
Ronald van der Kooij

⚠️ + Ronald van der Kooij
Ronald van der Kooij

⚠️ πŸ’» Aayush Rajvanshi
Aayush Rajvanshi

πŸ“– From 8feb318b68d778c7fdd07337b66bf34e8e201f2b Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2019 15:40:58 -0600 Subject: [PATCH 094/327] docs: add ely-alamillo as a contributor (#478) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 10 ++++++++++ README.md | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index d3c5da47..d37c915b 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -958,6 +958,16 @@ "contributions": [ "doc" ] + }, + { + "login": "ely-alamillo", + "name": "Ely Alamillo", + "avatar_url": "https://avatars2.githubusercontent.com/u/24350492?v=4", + "profile": "https://elyalamillo.com", + "contributions": [ + "code", + "test" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 1c7493fc..20b3a962 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-99-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-100-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -513,6 +513,7 @@ Thanks goes to these people ([emoji key][emojis]): Aayush Rajvanshi
Aayush Rajvanshi

πŸ“– + Ely Alamillo
Ely Alamillo

πŸ’» ⚠️ From a67553521808a884b869d461d56a38048ef63c30 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2019 09:45:06 -0600 Subject: [PATCH 095/327] docs: add nickmccurdy as a contributor (#485) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 3 ++- README.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index d37c915b..a337c335 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -873,7 +873,8 @@ "avatar_url": "https://avatars0.githubusercontent.com/u/927220?v=4", "profile": "https://nickmccurdy.com/", "contributions": [ - "review" + "review", + "question" ] }, { diff --git a/README.md b/README.md index 20b3a962..1e9754c5 100644 --- a/README.md +++ b/README.md @@ -499,7 +499,7 @@ Thanks goes to these people ([emoji key][emojis]): James George
James George

πŸ“– JoΓ£o Fernandes
JoΓ£o Fernandes

πŸ“– Alejandro Perea
Alejandro Perea

πŸ‘€ - Nick McCurdy
Nick McCurdy

πŸ‘€ + Nick McCurdy
Nick McCurdy

πŸ‘€ πŸ’¬ Sebastian Silbermann
Sebastian Silbermann

πŸ‘€ From d0149e8ae498bdc02ee88d86546d76d6b7772ba1 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Mon, 23 Sep 2019 12:05:19 -0600 Subject: [PATCH 096/327] chore: upgrade deps --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7f164c11..d393710f 100644 --- a/package.json +++ b/package.json @@ -41,8 +41,8 @@ "author": "Kent C. Dodds (http://kentcdodds.com/)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.5.5", - "@testing-library/dom": "^6.1.0", + "@babel/runtime": "^7.6.0", + "@testing-library/dom": "^6.3.0", "@types/testing-library__react": "^9.1.0" }, "devDependencies": { From 594f85801e817e446f732511de6a804a6f9cf9b6 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 26 Sep 2019 17:02:57 -0600 Subject: [PATCH 097/327] feat: add pure bundle build (#489) Closes #486 --- package.json | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d393710f..53a43cb5 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,11 @@ "node": ">=8" }, "scripts": { - "build": "kcd-scripts build && kcd-scripts build --bundle --no-clean", + "prebuild": "rimraf dist", + "build": "npm-run-all --parallel build:main build:bundle:main build:bundle:pure", + "build:main": "kcd-scripts build --no-clean", + "build:bundle:main": "kcd-scripts build --bundle --no-clean", + "build:bundle:pure": "cross-env BUILD_FILENAME_SUFFIX=.pure BUILD_INPUT=src/pure.js kcd-scripts build --bundle --no-clean", "lint": "kcd-scripts lint", "test": "kcd-scripts test", "test:update": "npm test -- --updateSnapshot --coverage", @@ -48,9 +52,12 @@ "devDependencies": { "@reach/router": "^1.2.1", "@testing-library/jest-dom": "^4.1.0", + "cross-env": "^6.0.0", "kcd-scripts": "^1.7.0", + "npm-run-all": "^4.1.5", "react": "^16.9.0", - "react-dom": "^16.9.0" + "react-dom": "^16.9.0", + "rimraf": "^3.0.0" }, "peerDependencies": { "react": "*", From f2805d47bf2a9d5490dcbc0dd5b934d67d1e48a4 Mon Sep 17 00:00:00 2001 From: Daniel Afonso <35337607+danieljcafonso@users.noreply.github.com> Date: Thu, 3 Oct 2019 20:16:53 +0100 Subject: [PATCH 098/327] feat(debug): allow debugging an array of containers (#495) --- src/__tests__/debug.js | 17 +++++++++++++++++ src/pure.js | 8 ++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/__tests__/debug.js b/src/__tests__/debug.js index 4cab1ea9..ad3b8591 100644 --- a/src/__tests__/debug.js +++ b/src/__tests__/debug.js @@ -19,4 +19,21 @@ test('debug pretty prints the container', () => { ) }) +test('debug pretty prints multiple containers', () => { + const HelloWorld = () => ( + <> +

Hello World

+

Hello World

+ + ) + const {getAllByTestId, debug} = render() + const multipleElements = getAllByTestId('testId') + debug(multipleElements) + + expect(console.log).toHaveBeenCalledTimes(2) + expect(console.log).toHaveBeenCalledWith( + expect.stringContaining('Hello World'), + ) +}) + /* eslint no-console:0 */ diff --git a/src/pure.js b/src/pure.js index 4565074b..1b1838bf 100644 --- a/src/pure.js +++ b/src/pure.js @@ -60,8 +60,12 @@ function render( return { container, baseElement, - // eslint-disable-next-line no-console - debug: (el = baseElement) => console.log(prettyDOM(el)), + debug: (el = baseElement) => + Array.isArray(el) + ? // eslint-disable-next-line no-console + el.forEach(e => console.log(prettyDOM(e))) + : // eslint-disable-next-line no-console, + console.log(prettyDOM(el)), unmount: () => ReactDOM.unmountComponentAtNode(container), rerender: rerenderUi => { render(wrapUiIfNeeded(rerenderUi), {container, baseElement}) From 89d11b08c61f3cf5af770c61a03d564b3fdc301c Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2019 13:17:37 -0600 Subject: [PATCH 099/327] docs: add danieljcafonso as a contributor (#496) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 10 ++++++++++ README.md | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index a337c335..28b9d4e8 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -969,6 +969,16 @@ "code", "test" ] + }, + { + "login": "danieljcafonso", + "name": "Daniel Afonso", + "avatar_url": "https://avatars3.githubusercontent.com/u/35337607?v=4", + "profile": "https://github.com/danieljcafonso", + "contributions": [ + "code", + "test" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 1e9754c5..b2b0ae2d 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-100-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-101-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -514,6 +514,7 @@ Thanks goes to these people ([emoji key][emojis]): Aayush Rajvanshi
Aayush Rajvanshi

πŸ“– Ely Alamillo
Ely Alamillo

πŸ’» ⚠️ + Daniel Afonso
Daniel Afonso

πŸ’» ⚠️ From 10a515e6aa46f4c0546dffada488d89105f531d5 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 23 Oct 2019 11:08:51 -0600 Subject: [PATCH 100/327] chore(ci): add cron job install script for smoke testing next (#505) https://reactjs.org/blog/2019/10/22/react-release-channels.html#using-the-next-channel-for-integration-testing --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ed2d9bca..2195419d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,12 @@ node_js: - '8' - '10' - '12' -install: npm install +install: + - npm install + # as requested by the React team :) + # https://reactjs.org/blog/2019/10/22/react-release-channels.html#using-the-next-channel-for-integration-testing + - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then npm install react@next + react-dom@next; fi script: npm run validate after_success: kcd-scripts travis-after-success branches: From 646f8c05d65d45636ec6e23e0d189ea9998f0777 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 23 Oct 2019 11:09:51 -0600 Subject: [PATCH 101/327] chore(ci): make install script be on one line --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2195419d..66796ac9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,8 +13,7 @@ install: - npm install # as requested by the React team :) # https://reactjs.org/blog/2019/10/22/react-release-channels.html#using-the-next-channel-for-integration-testing - - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then npm install react@next - react-dom@next; fi + - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then npm install react@next react-dom@next; fi script: npm run validate after_success: kcd-scripts travis-after-success branches: From 4ba3617f0de0255f155c3da5902046e10b670a5e Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 23 Oct 2019 11:30:15 -0600 Subject: [PATCH 102/327] chore: run prettier --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b2b0ae2d..6aff8b27 100644 --- a/README.md +++ b/README.md @@ -315,8 +315,8 @@ You can also find React Testing Library examples at ## Hooks -If you are interested in testing a custom hook, check out -[React Hooks Testing Library][react-hooks-testing-library]. +If you are interested in testing a custom hook, check out [React Hooks Testing +Library][react-hooks-testing-library]. > NOTE it is not recommended to test single-use custom hooks in isolation from > the components where it's being used. It's better to test the component that's From 991dbfac94ad8612b335386212440a4160a33a56 Mon Sep 17 00:00:00 2001 From: "imgbot[bot]" <31301654+imgbot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2019 15:28:34 -0600 Subject: [PATCH 103/327] chore: [ImgBot] Optimize images (#512) /other/testingjavascript.jpg -- 228.22kb -> 196.34kb (13.97%) Signed-off-by: ImgBotApp Co-authored-by: Imgbot --- other/testingjavascript.jpg | Bin 233694 -> 201050 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/other/testingjavascript.jpg b/other/testingjavascript.jpg index 737ed4e2687cb433cebc1c889d4c191ef9fd6e47..e59e5ed9dd8036c2e2f5828ebe8ad1f3d52ce4a2 100644 GIT binary patch literal 201050 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

Cr~j$@1K)comjKd(D6B9X6ih`I;41Dft^dUttt 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 literal 233694 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�rlRvlB3zi z@cvX&zMsXzDM6>rQCdqHs0l49oc`~t#;|``Y5!{aA0=_D zj}G_k4yrpd&5s>ja(nx6zxO#zYl~k_t{Pr^ZLQsgK$j511-RVz`d+I95ltq~Qu!%1 zv1@9G*UsY}DQ@vUPnag?IDx|39S`i-q9g!-0$>w8ePl{My53Dl=au)8X8-B*mgsDjqOWDK*3+ z6H9Tuf{Na;o74VgsQFAC6D*Rpp+%XBk)oh-j8 zgfsS>$S-r>|DH0~EUdU%qdiear3-g_cKMOocmBT2n`zB~XZU42#J{$h8bBoU|$1xaoV*Ap*#PzzLpKpEL=@fl=c~IBE)2t`&lativ zH-!B{4cL*4=DRRHFQ@*!#8$?rA?_WXb+3K6;ne3_JM3mh9WYoXk6pwy%Y69Llf%Y` z&{KAH^$~)@lsA0)KDU(#KJz($pGn{|d-=?E|DznwZ&9$kN%xlQ2t9&*8bi}bTxs#! zrO8L~Zm2y)&g`w&__LYTeYG%+xJleyJ$Lz@^d}kG!n2>7(gc+LU!dc!@Ww)&xN4a6 zM!o(>*R+UquW5bzdaL|2{j(BlE;yL!9(s4*+(!Ls#OOxkiDaz5aanC%P@xTz9deEGoMEG|X({E+{u# znQ)$coNND0+uW%CTp;{MTlzHo-xn@?AB9Vn()a>8D(0g}*QZ#lWz2-az6&dwO;0)| z1Y;NhHgjwHj-*(8IrzV+&X435#uHZzqq}eLuYLHsKfyA=Y~MYCG?FMgua`W-+1X{{ zy8WMTD){?i_`7G)*KNf;pOx^z^A0Clq#lk3OTwV89*3{O!M|%&zZwFL5p|e&+;t1Q zGvr7LGqvvuo*x=Uw)`R-eL|vtpPnODJ? zCa!dRRgnMaM|l7_Umi8G%_V_*ygJvpKE-Y=>rVaMEFGy+Wgm3A;em9^Cjosn&%bWo zNxGt#D3&aUYec^~23$(xcTd%ORGVBAXA!-%-z`|0_$q)X>5?jM5*Ss`qT8&`W6^K) z{%axWH%~wB2(K2Iysg5<_JS1NI3l3gZ|NZUemryN=!h8oGkz1XGzx1!1QIxR`l0pM zUuebUvKRr?{SH>xuxN~-{S~?XDU17x=zp92f9Z`sUH`yd3x{z``U;1 znJH_&zq8r5(a_&LEUape@#5?$^ru22&}-(O2>X|HD?y%+snkDwv~&KoE!*SG&Uz(# zEm%QyZi)z6cWKqr=kFhZCYs>+&M#BX54irJA(Ybmzd3IH9xyKI4OO<%Tz~xjkn!@5 zb0i#2Hp}s-*-kw^vg%^|-iTdMgZO2T;mhBz_zh(yEJOY8rH^=E7+J2o$U=M&*T`zV{xG<|>FmI!Q>XtQ&rU+#mQ03_4;3# zv9suXI-$7X$kKG9Lqu7UV#~RvoqvWJCVJZq$$q}Zm z3%wv>TvQ5K`3)sJW@VU?5@?|lK}9JkYxfmd>w4enS?H5@jha3B6QOp|^2@rmrUBn~ zv@8qZdlVjPbzi+JEq#T}+PP2CF+z$!pmeU3=K@u_fv6kfh-&jvt;I#5ihhH`I$#0V zE26Mg1J-mL5hYS@2C7TTAFxv~8RH0b=;T}JGikO4)7Ab5@qy8ZK+{gTbMAy*Q&n_5ToP`>3T-+y6q0>dcm2tk+w0n`)AU-#AJD` zo2DD9LFujE>`ukOyV_3Q##zud7m4A0YGXhwS#b*BMpjs#%nz@?@Jw^u8Z1#fhprXJ zeANWVQu5IlT!Rjaag~;aHhM}d=mD$mK#t>x2ZqASRGbvcIUuZ5YJji6ZV{bXO#Z-J zGA)B%z3I4^AQ2~0$%}xP5_YhaG(bx3NDB1p7)PiOek7do#Z@2$8iM$jfR!T$zUol2 zLPdGrezDlN4txvWVQ43O-o8nUmoxeUPDj;8vEqc%Shp^UB6bvZ^>d_(sbYr z^%1<%xb-lTHLkX&it+MB;j01>nxzv$%p4J>W6}zUY2M^C^b#E5gm26XfH$W^rdz7D zsO=P+y1fM^pzb9R5ex86bj9m2dGb=2EFWxHoKB-cI~Nb{5;>tqbw%+`cnINjg@ffB z_0&q*3i3-Wq{v5J(>$nAOqVy}*OY*Cm=Fw7c9&Dm=9!;9>(wcgP>M!N;(c232lC}F z*R0BmJbPo1sUJaS>+fwZj){F!+iUa0tpz_O0Ksv@{bx!yoMb;+{?=D1ER8`j0p<;X zG@6Qo50Qc!P81K=F9WG!+~q)8pY{~xL&81Snb`?JzM|2`5 z12Lp)qi#Zht)guNt?p~fN0(XIYk_aU5fOPfn=jy7m1AnKX>M%Kye9ADo>s-_F1Jv} z(3iAt+m(sRLh8PfqriQ7P-M2OxHO6g-;~S5T+J{rm-wzq+Nl|_`U^IJJQK#*@}QJ0$oubxFH;wMoK}?@m291N9X|y@wU8Rpc<)k zW;1d1EV1;SGKH3M9LyjIbd}B;OcO;NE*&XP8b=%%M{wcWpKo~6mjL(sx9VG6q&gJ% zBFl~RM5s_&&Im3IH>=6lw1RGlgU{<=f9s2KY#tafd<1#=a&ePk70w!FyMf?Sh?99%(k8>>!)`~P;}&rBJ5m}&o&;E6BnPNoX{gfKDoF^s0(X{uxr2l4FB>Y!yk%W&BOr1TAwZU(wW3LnJPVKE3da$f?_(vG!IWU1 z7?WVCOD=S391-IaGLG2OZ_DI`<^vLPoGBxfBC)f02v#`T9Ink-4MP}8!K6z(cFmC< zR%X$;j|fMAsx4qGtbuSTG1XZ1t*qQKTbXkF8jKl^l8xBn*8%7oI6UG z`bRJUcuS>zK3xnX;TXX|h_P&efvagi*^>wPLl?Y;;;ko?5W!ke{zW*RG>p8U$vpWjN@q2Xko+n#cw&1TRjQzUUb70ld6}9*b%v3v>ZY9Q& z%=?zm(G~?8hn^R`zg`Mv_X`j@`tAnfo*}(Sb&gp>S1=i8c09t6m?dgp8D9pfei+azZf^i_ zCz~-<)&Z7%^a0@Mh+&L^*^o2H5IFGbAtzV11;#7|%w{V*q(SgLywsN6=z7%#OZf@- z`4JZOS~%8IDA$)%3Bc%@UzHD85RMbfWmv&tU9x08#3DdRY{ z0#)m=z9PIlOJ;h4d=j>^6|P2Wh?_(ult+rJJ=FRJCNVd=fc)FS+Tnd^-VvnhNMn715}wb(W~H` zWUEN4NqIK3-2l}=QkTthCGHTZh7vRLVn~wxg?f5%3tC1o(`6=#Mptj-JbD@`nXF1U zu?8#IPvt>4!fu)V^C)yc;|OWaK=C+2p5*4q$OP_(G))=PD$SO;xQgi^^ru?$MWOO+ z%FFieiMp^5jAb!pv{|CjVRQH?4z~0oDPXM$6IIWrrDg#43kySP=L=^Kac*o24G@a8 zD@#?^#d|)x^-}2EKA4w%y34Mp@0yQ&r_0h-{ZJ~5IAayWIn4@>PWEEROvZkmfBu*( z+!M>puSZ@pup+p);7_|LDc~Cs`)YL@&om!O@ zQJu#hq3SAYDS3he75ePy49&Z%zl(es^WYlpEL7pQYhc}zaYW##ZE$Whq@RzeEB5@~ z`gTy5^H3SvLhfrT{J-HX0=VD07E-oz&Sn?nPrf9}n!3+nNos_rFKuPBhtc9N4>vuZ zu`~^RjjQo-hf3!^ydsNHbWzQHj5yL@4xuT7 z&o@6@er$DWUc`y!LEEaJXJC`Kx|Wzu^@MgbRVp&GCWnkVtZJZ+{^*_L{c8Rpgq?90sAXP;sLvl$J7=sBLQ=RRd8Mkiat*QGqu z?%0ddZZNi|p{B}G0?_Fwgu5;8s)7L5d*2)zjN2lLd!6q}wnbUlFQ*O=3XZyYe@N!i zL(8=`fEnO>kvb&^s18t`O_Zmyt=&?`5l%R!6SbwarTs^RF-JH}w$E0T70QGk#5AZc z3o4IWEK0M*ve-1M|XnviXyg%Fi<%e!z$SzL=RyivNS(R~CnyPvo+2TpCm z4K{V28NsJhQX`a78L6@zDY{cF;m}oO#FwZv{N$=^p{BB_fZ*I7(YoBqm>0_;nNu5wdXp zn1XF!T%fJs(Yg11F)!P-#Tk7ZjD#qz4BCp9oDoY0o4W86Od6Ab^TofwSjKGznN+c` zo)lq3aizoM-VQ-|j03I6IO5g{woz`N9|s3tWfGch^cZ`?Ef6hDTni^THkufD30z2r zm$Gc1j&-KOy@NJlrVm9OIx5Td6lvTDJW;~vWXyDnn+{fhwPHLATTi*FOi!a%Wmk?W zzi-4;)0IC6zmXv;G1l33gdcsgeL-4&6St5}OQOZ=2~+6{#u0R^ZG>1SkmScQpE@ zDmcWrAxfj70>KdU@z_T8ZUvaorsDDxGhbd)4z6MQQo^_wno#sHN)_Ah=;3SHke-wCV`A+;JYTHJb;@p@cQQffOYvWDb3~7 zQ+<5e#pPhR*yoxzW2($wB4`l!RK`$ljF2eX0u7aC>Ed7D%oR|aW^>v2`4|hVGfY#Y z5(28V%ULl``xXT(>?n!yZPp7gPdKoZ@A?k7GoSfD)Lq8Fmjrc!sbb>lC#>r4M5yT)G8L zqjw7={A&DCnGatmz?WkzYGKXv1p3fTq|4l-VMf)XF1FzVsqSDiSS?b$PRu7#2Z+x` zFcJ$<1?NOA9YN6poCyUFon)GK}QDxTeh7ibh;V1 zk5`<+d`>T5T|AA~flI?D3n^;sv{;@XO3+e9n<4hO6nMzMsS`EYSvXkiSant!q&yec z+kM}<=W2meOBH6*3xXke#lw|Tp)fAW{5PdJBox%RVE`iBS1!eZjTh-YoR?-rsTc7 z%GvW%8|?`#&8O=1^qX2KuU3sGF2y zRID_-6FHqU4|s4#!3hv+jdhvE)kIBh{c-io+10rw^%^0uwUhT_%5;Q*naQYZATXUw9aGl2zd^^T{G$>*DIJ<~fF%m!S_OtAQQ`vbsS65wiJE zGmCl55k`>=c!7K8yIaw}w0$jDMk}ZEM10huyA`+IHQ^fey<` zNN_Vk^AKd_3$2ALe4$ym$-dPpUfJ$>>SnjI76+jfO{2kX?4$9}5abLzFwVb%uTh@I z*jz0D<3Y(Yurx-&G0N716=~Xun%Cy52Z;6LVVJ1j`EU$IL+ojYvl#|)wCiJTV5>_xKl+y_y}%^D{u_3)6y3?-B73%+v92KU_D%% zhvTQS;}zY++&Lan6DiL@8mh;F(Y!#0drm~bQpe0~a+3fLqF4{|G3IRhLxd9tq(UjZ zi;lo+p~SOzov}i`szAS-d{l!WpqJ6sihQmZJ*4I4)6=FBynKg*{Bgt!@*%c$Kq5=) ztyC<9J;L4HLOD7K)|89PGEgm8V7P%e&B$ zI5C&w)rpfl7P|#Egyuu3<(m578!-%+LDV@M(o!M&s6OK&t(Z!1@bdD)JGgO3lK9qc zD!fwQAXs0)<8uV4)8OkSVm_^4EiG*z>Vs}>VWoyr5ou{V6i7HH%Rj@WF5@hfJa5Ub zN0SVUIpYZA2>1@hZwuG4J7oDA=!|VU!J2S-0An41ZfIcTUpG+cQkN+D6vjsEEZ_ly zwJsQL^E>3ogr)69U?0d7VI#IK$&dv+E&9Z-MN z44v~mq>sx0rk-|@R(5QO0pLWfTn#R`RqXU}b7bzKR@Y*!UO48Yuo3Q9IO)@)Ol~)P zt7vlnu}ztv%rY>dC!y2VwUoi290=IZRu+m#%yGoUbj9idSqiWaF4U)1v=z1;m6=zN zZ3D2Of%~KmN_>kJqYIUWOed$3CcB}maNN<%{`TeKQPwDvacL`%3P|kWh`Aag!t`u|%k-2K@jAv8po;z6QaQgh&;k<gLZMQr5F#9k~tp&D)5+Of|KNirWK(A!Os}+GR*{-8ws`cgR=|Yw_JF9=p zjJU3Gx!5Gc=!xFzz?ITO<%KwH%bqTF($aRp3$_iJx3LRT2PYdx+7~OsAe?VD--k~r zwWWkBvyC2(;?*G&dxnEFQOfH?_4&X(!ffB{VIBCkz-n^27Sx560HUa29DiU?b8lU- zde$NfY3S)rDAYAZ!8I`VD}uY&E_|PtF-})#bXpR1lSVL5Wm~Ry6Mv9j%L0*-;AdGa zv}~gk>XyzXA_X2bs$4I|DunjbT#7yG!8yQDv;q;8zOX zJ}-tJX*X4RLb?SAkhWy?4-sG)$9S_(6hbGDx&=5gHEH>FZFhJ~r+NyLCXvQV!=>mh zx*8Cp-ai7bQ+~>h2O2TsWUdel+2ATIEcnnr@q`?s&t{Pg>*XcX-io` zfv&)`bZi|ZbSnmK^i@0dYQK2f>U!clp4I2V&M>tfAm*hOClp1F2JPN$YC0)Yo!ORl zH_k{*YfnYPNwbSaKJXx~N3$8eR^z!9`KS5T@vYbA&C!>XTP2xF+X#ly(2 z2c!v+sBa(#!g*iZ^8hENPJ@;}N-hE(01Bopd6u0oMbS#tbn6Tt%{7%SkS?7X92JVG zsyyFnl;3~6S@{&G@=-ePj!`;eudeGZZX_n_*)EL|Xl*|kZAdFoV05l1bBri8ey}ua zq+_|qeDwtmFTC|I)^wY(k*@T32T@5xB@53&g((wgiGd3`G0Aj!$`lLec)t%|30TK$ zDG{bm?9QlR=9Ox zXARivHo;NQRk1k{Uo;{8@0I$nk47BdJ z4TsBZ*i=Jdr8kNzm0ES7r@-F!K!aH!;j~35*hb0JeH|suz9$PqD{$NFC*L|E9v<+hRr4f9ZdQcgT z%a-2EIVQ7GG#mI8xB22q^|3)CMr=FOk=5XvXCkM1faT5L#EfYksC`?Bf@^hCwGz09 zG|JJ_C#9lO)uZ@zXTcsYiX>Q~%hwk?W@60Yp6zHrXH`4DxgA~%V{@6Db(9bAFP!ch z{(`6$F!I)+%PqeSh}PE0C0 zLpT#3hZZ5>V%FBT;dx6bD9>#gAm$i7rmldI)<^je_RFPZ_Jq@LS9LM`TIBG|+1c6u ziA?vLCgqB%;%d7gy>%;nsvA)gECrk4W!S*&4xK0@KtoEdiqT=zjh(0zbjrH13Z-_Z z@)6k6O5YDTeHv`g=6-WDa45eWl3HTA1McoA*AfPn)Ojh-Y5~dR9H0{8Zu3 z>)B614H-fw-7${?rvVSt;n&QKjj&;Ef!F3*J^lxK?;aP^_CF3ssE!!Pp`->Ojz}&g zWi~?Yb8Llr+X-7^)X(WU&2q77TO1F_NQ&NL;q03a$by73aG|hc`-g_qJ z`}zHz-}Ahlf1lUuV|6++d$09g@AbZ|_hs!JRChwbOdWF=3#+nX97mti3{YDx8JHF{ zrnFbtmu85-9#~fwp$zbsV3}x@_DO-&MJ2Iqg9D|No}HU|wjvsZKb`hH9;@s&CWSd2Daq+l}_WzJYTZTMa zz#62~LUAON-ZdKH_9$f?+WC+g8kABTW+tGAW67aj+`2ZtUQh}zvBYF{J7phdCuL{D zAU0ZFB^)pEZf%MI2ioH;WL-YUB|@j@Jo{Fw5vui4Hj7cxJW)ulvARflu5=6aZ(%Tq z&n|J_gPxwlw^3G@VMHO)W!OUdebbuQ0{sqiRw0AN!w@4v@lv;W+Zg+Wi*LO?^+7s$V(v{pQLOjIW#H_xxNg7?9pD+NLhX} zNdK*$TD6uYfi+RJV}#=UZR{6MA7slP*8i}r>>ub-)?w)f8Va71UfR;0@h4LQw*Jnl zvG}!{+mnY9v11hBKj>|p+Wf9)NoADsJN7aw|CybGKZFZJLJ<7j8IpceCjU7jjbI**`DVo zuH=s6E5Bhchc3P1P3heudY{CXvC+z<0$OC=R_>*uQnXXWrHwhk>8uu?rDjSKasKC? zO(;&0y~Axxk!i(_9XlF)+Fv%_zh+pBa0nMd_qVcj8iG7ZvET8e)ADsA#Otu*;q>R= ziKiVWrkcKB_Y#yXVHvaJWeuc^)4gmFh~X^?=2tKYi&Gs?9Z`8n;xplWlnGPGgTx74%TYTkLn&>r@RMF1V#6jY_b9x0Y&A3@VY-4Wm z4+?6_nE-=aJLRIp*U%g3BG^WOOeSN;qUv05PXq9}byaBxcIzDwitU6I3q_& zPzh84(y3h5T^)fF&4CPAXsFHx1TlK2vX%81gP$2g7BRkA{nXk--AP6J%ti@l;LeTd z5GOEkZ|DoujN{-$P81I_2o7P44)P)D2JKMx4sHIa^@YBRNKrVQbubqviO;^J9^!-C zfIVRLCiD3I0wgAr2ytrIx6GiTQpi}<3JG61H9zi-5!lwE;h+YLDSOa6F0uE)0@5IN zz2D46-q7G}xvr&AA7w^2j;!)7<-`qVZgo^_z+1B1QK4N(*5s=0CjP<2Jms-x&_!eFllm?ygInVC&}VjHR( zgp}BGYNBGWXQcGs#W!2|MQ4rS__I;*_^x*X6}X6=a+qMcQ9~ z{P;0Nmg_@#NJ@=Tw1H)fI_uzNQ!bt%_ISBJzsToh)AJfUJbjkkSnyn_mwUo(s-U2x zMfHOBeQbkwDp*dYXXD-0tld7fkVCfRJlnO;hw@k0sHRLfv_&~62&v98kuo3y&FnyGdmSx^0KOO2#rnBIW}7v#YryzV9)YKx8#>gX}lPosHEYA zEOR%UDuP#1d}i6!K7yQwMa{NW|5na#LH_UmqJ`Gm_)hG@Oy#%bd4k8{h7!aDe6xGs zNRX5~JvOa@m%x*RatiX0&TDAW{!7=pxZlu9{I%zM?<9GAQ?B$B!_K`lRr&qLi7dpd z0`r9<3ImNlAbfA_T_8I2UAgg15QUfe&TVXC-rg4Ex1dg|--4`)+;lUtv(EL8l;)`~z9OBe8w&s8aRU>NTBa zjz*JS)U_}tq06{d`XyYVzG^RZ9f+{m^uGW70u=h_dla;8M(RPf=;_g;N8RH(Kt@vF zM9sySLM?dVY?rb_V(1~>=8SI?(KfAn=V^mCbzjF0CkTdndXy}Ms2TaLQp z0y@6q`U}p^hQuD)BGB- zvG_bwpN|gA0mD_m9rV18-qBz5rAVLprNXKZ5~dH72NNigLUBZ!b}K`-G;gOTPq1R4 zO>SRm@06ogBqas&>QA=^)%m~NcV>HK6|c~WS5*8#=ylHiTM+;KURreESjB>86-977 zF)NmNOE{(0<*b7R5*2!;g)`Zzpi9gY`@ZrqL2BtWohpBc*WLL?9F}kiDWd#rXCF1>m%rUQGK*LViD0AIES@8%|kfvkf8+BwP1b|mYui1 zg`?YNrc>{*mCMu(S{~%Z3Y#E==qN^M+ak4Pq_I;`0_B9Fwz_RBk%6XB6Ay!NuOZfY zMFuwgqY6_U-Y1=ZP!2JUjVjukxd-_(_i*8B6*;I`#Bw9_Wd@NC2~%Y6gHn`rN>i!_ z#K95ydwmVr<6a{_!0nZkSwwc4_J(~6wez&Ct*fcKV8a(}gXrJ4*lmG;bG}bW72j;3 z7*Y43NfhOmK2dKVk6VBSPQ$zRoBqF;@)Z8o5KTSN9(RbnnfuY=$Y^5h0;VXp+&7tNAO$z;+e}wJI+Exe_e9x;}pX- z8zD}^PE3>{^7(D!YD^}Vi2aG-p&q%agN0(h*7-~kt;xASwO2Y8in*g0y41f`2a1o2 zd$5yXx`O;HNUf1x|6(YnAAoEf>pqLbfbNYSsk_vXq%K;Gi}q68R?P`o17O@zwLj4CS%g+L%xH&$3A= zF8J1-#yrPBI4&0#=1YptL`9xXD{Ky$EF9l^s42}DvL)`3MjkH}mtEcV=Tb)d1}?0A zS39|Le$WDEu~i^j@HbFKb*AsP#?T301M023G8!N0HlE0O>+P_d+cd7WYw68tZ)QVo zC$co3!ILn<(Y`s@o4j#()ZNkq58<2&aUmo%0*{N2zVykh?ZA95_cOb!vl_f9F4*tD zzJp}NX1XZ0;YA?f86WZ!ET-qfocgG@r2;b>w+L!j?iX#@6`Ij?BYLRR3N%ed%p z>`pED3Ht@x6uoV6_Jo5ib}W7-Iu??SPl?V@LFdW`1^?8Y4|~A(&Ez~aW%Q2adG*>< zD4QnVz|v99HvXxk1<%$Q&*HDVbgi2H-d?}TSF4YAQbpNk=P)jRHlq-mzL^pk*uLyU zZjNz7)&x~m-+)Evh5B=+lQutET2Fb(dgW8$C-o?vn5~@B=9yiUw5oikJ{M=%}J(*YEYYZZ@mlDs)M~wd1cAcoipga+uSl5#GYT zWN)Qe2i84q$lQO==}+an)?B_(P}DK-)VyEiN7Zm5GMR?tQMP{ux$x==!}M~&$&f^Z z9#Jk3d$v$USGKW7Nj+GTGc!NA?xCmt)Y7F-**wXgl>ukO^F+a;Y1syZK4i+2UnlkMw=HNqdhsphIg_JI^$|Nqch*w7fMx zs>H_L>T6cb^+L229UbIR=m$sk!zK%_njl}la`Nu%ceTWQg|-FX z3`)d7PYt*X89X;qMK9X%xZTpyyCJ{!dm1w|9palm#~2-Wxqm;Ld3qw4-Bjs&_)=YQ z#nrh`Y8lUNBR?n0rb(I-e1vA7#dPs5uw6cDTHD9IYL=Kx@#gC8?31Lu=s8CaosAr; zA9(-Z;?BEY>h}eu96Q@2P4Ub2_n*CF(^ckgL5^Xij}(D~Neh_!F1Rj42~|2z+atVjYfz8i;4N zQuMAmt&a!Ss4fHpcw@^| zsid^F_LFM^ytG+QUIjUW=+nn(lY)|p&E_RSm#jZFTx%gSI8&tVVZRFxS8x|3W4n<$ zV)SD{U5)(KyFd5+;nZY$ZlmA#4JngGEr&XW-sli@L}r9 zt!)@u%wt!wiL6yUsZ{ru+Uyn(-a!2#1GThN^jz_lYi9E{R8OEe?^mOZMzr!uIro2e-PR=4b)p2xZH1>cJHEda_63hL3KSQ-Oz5%3frnnBJRPC1-7#v9NoO_`RUy!b;Rq$XDwCSw~wF1o@RwCKpn2Zr_KfEGeb-U>23}|7CTMM>2Pj zeeqqg?ttqL^!94MdG}tPnfIYqX@H-En}U`puz(3O|GCSOz2o|&f7|v~N^7)%e;ZkB ztA4T){#-aR0v^jUw|1|*yLVAr`K?o)uO`j5^QN_3ufH%=yIe4J(1BRaTj7)Zi2mkl zOGR~iTEpV^yE|S>FHaoVMxA9zBulqDtG@LPD1&5XSE#moqgRpVEKHn7caGi_?{L`K zzO_m^_Qt@dD63*I(?mabg;l(iUF+n)%KCb$Gw0*>Yfe6hkoA0q2Y*g+;eDEg3pn8m zs0J0|Qyy2jU$mRPvRsc^(7ez2D%U?Yv%OTW{nPXqG?<$tuFnv!Txdp1<*hgooO9b~ z@tN>Lb5@ZpzK>d5HQjiXama?M^=p|{iS3J(R*(}4IVEIW8O6HKwhRw2&e+M&^fAi{} z@{$%QZA9mP_3YV(df4`4wD%NzTE9>5!1_a3gQ010*-5R;RmC^x*0YF$ID&jpo@(z; zEvT*rP5ms-@DN|nd{O@n?ItK#>c;J!5Z8t_BhA1G=0ejx5@B)w)NGm z8;CptvAd|lY#CERlY|3H>U}gEiwVSpKeZsO0sJ}00j|A6_{1N!Xdark4)1$Wb7w1D zVB%~Y1Ak8sX&#e^2{FM^HL!jSpz(a@eKzf<7L3#hgr3F20%Cf_1Cmz%UOhF3*^IQ{ zlZ?QJxBPE2n=m9aDL&CS4xh+3@KteDEd&W|XvMg>IFNVbe{ryaTaoyr(OEb$I&fpM z8aZtgMvhP;%87tZm(;V5!~3_`;$8m-d^KF-vi}9C1DO&)l=6R={ujA&VMN;sHKB;G zhQNOb6^;N=)z{V62x*3|Bi8I(-C#A5;kb4xX`BH@ta#k}HzqjT6E-~*DLF;zyAZJ7 zMtho+8#67#@I3#L@rh?Q%f_jiEkn`$NL25V_Si8SWA~G{ka!LAv`1Wdhnx>Tu5gT7 z$hv!mt0)?f%8f!#FHHT`GsAG)4QuxzyR|aI3Yt;H{8!mG8yWn@LCUxR(@{CdjS4e* zeb2xF-beC|=q+s*;x=gqav`zc8BrijtJR^*3uS#2@96d;&*)w8JZj8x7XLPNJZE!k z;0HL>WZUv^!UhL}LL&HA>*#ZZ_g4Yaq&TfjnLy=4fS(X6Wx1}FGl=yWxi?Kv60inD9y zES%8L3QRQMb$}250J)Xg@FAw70cH^5lGTi}Ih=eIWJYoh0hZLjASOP`xK)~w=FlOI z1Gghm;3|s-!ZjNQ(!!%G#4lf1hQmT(B_sa?0L^3Z6^x$Rrx|@c97ki4MlHheb-X0* z3=_nEVsV9`z9oYK>o|uyPCfZQQZ8jw1V6GWSkp1nx4+Y5xprrWzk(^c>G8?)>KJqV zCQJUQWSWijf`>_sV|pBun#Pl_Cd@n(JPS^mAx@LlZ@D34&+=QdBi8f!nON&{N2=Bs zT#cqBWX{4?_gD|2x%3%dly{M9-C;W>FAo^GJH*w+IoE1)(ljJ-!8@nM+pDj)PIo9C zJJYT6=;6xO^z8Nz9)_7_?Mk|E_0=a71`&M0bwpriaB#5Gc_4x0+`t4B7OV4l?xv+A z{1db~Gm|e{wjWnN5p`|=~a?Ko%EKSwU9^~s^z!S+6Iov*Vd4$KSb!T@dRb!2Vu zC)t-RVJW2n^xwZYF3sUzN-XnoaBreF6pe6uX)voIa8||N)=!F8HPW2FwD7Pw6st(1 zmxoz(n+eWeS{tp4ChsmD>@B&UfU7v)lQbJQ$ZkMm+hMt_|n@{B2j$h2N z+U@=i?WCh(eX$1`O@C8@wepKgkxF*0XJS{u1Y)N_$vb!!18E%$`KcutFI1dNWCbJ` zuZxd*W^i@3%&F3)ZZIGy+v&C`p?k%1=>|A4~@0Xh<9@?OU^wk5})u2yVAin}4NVy3Um^$;@mkN+= zzP3vEbU+R}*kf8v6nHm}+gwY`td z0$2jjwIN)q@YWfc%sPSq7%jDKFhR7!FX0-Dw~v5^3>-u5lW6w+jgDGt`htL(t9a7(0Jq46| zCAI7SWZCWWKVUc0GiuhxF^h$rS*t!}8{Hbk?4Nl`H7k8^j9hV_ht<`NoAr=Zo9(oMV0V zJ`8$RHvI_kZiP@r+B{d9=g0c&9_L^b>u`AJpUt)ocLta_`#z2^FTamnU;q~)zEObO zqrjM@Yi#Fh{Hn&Rd1L_-+VCx3vlZHC%=IRX?yqnGP8NPrU-JVoDF*gS&VgjqJ4}uO zIRd!@qc~Sk{Xb9)pVE>A@-HT%|7YrmM`}pAxUjX!Ejdf#R6%Ogg)9fFcPdGF-i4^u=4R!s#n<+*tqwB68PELq2 z_@^wvdD@5`?yI)S(8N__t$;g-1(s1_rX$r>@C^vf`o$qFJrB{M3?_&0KJ+p1x>RZU zmtDk?ICF;)U6T*YpQQ`Q3*zl#Zo167s&Cz4r`7}q9^j?3POP{ckn7$2G2Y=&c*a4! z3!{XK^mN*pCkwppaUA|MJ*_LsO~Iy*WH0yJ5wC@2NPcR)-WsvKaMU@%WopnMayJ_z zzNi$6WR{EK+!77UZL_Xe%=tsa{Qbh8M8ErgT$s2F9Pu`tjlz|-WdX*SVpAW8yf*(u z-ZG-;mRA{882!xpc5s1?JnXf$>c=*^t#j1$#H|SnEi=YwwO&oWd_izP{|~3YixA}< zkC{>#x}H+UW!0Q|8xkDNwkcA+^$ahYajTH{ku_t%+tsm!Q##7+Jj)#tI)g3dm4(mL zf4t?y}-O;9An}Ehf@F>CevX@HOAy6lUlSF{#hfwMs6{4NjcLO1!!>l?G( z0cUQs+qQntdAxy0dNX6kr8^mfQZ)OYFP#mvcDetTj{^VJyc>GTk9HNYloZjb0nhHg zy^3lMMur;CNE*L7$9VeM`!iGoMM;P#P@xjsaHkPJo~kdkQ^Xh5M2DMOuWWAi$GRq( zHPVKP?{kmlub}X^C8m_uouWT2srFgEmGjs1Wket{I_+Nv^19;$j4lu{w) zE%p8Hg#RV!e}(41YVrSQX*N7qJunVU8!RwyXXba6Vjg2z`Z+0l zORPush(g8lO|wR>fQT@@TV9a*ylMPB@k5M3a5j}LX%fyIIseEU>w1sfM}v?P?U>(gNVdSYC6m1VYdm2JeN zvN7g;S7SZR=h8F(+SoX5027CGc_liVy=o2F=QXL#Jn2!%D}%@lP%w8l-ef)VVAlFM z#gTolHxi*Z{(EgGxn$Z(Z>NPm4}wb$%PB&nKS3i zJRWAJM;Oz#VI}!vfT`2!>d-^xw3Kf7-^jI#d>hK*%3Et2AI&pd@Zi45w232#-JvTf zyQ=lZ)1R=zH$=>cu@v^3m-Nl#Ng;Irb2Zav|I{*2d8w2gu+`A{%07XcwMLAUzX*o71vy#$!5q_7I@(^S^ zLlc!wV!A|>h%H9*Nt-cqIa?uvLomk3e<%DeN&hP}|5c0sS4+c2HYZ0;yF=MZdrE&( z%_hz5D#zxSFIv1=`8lIgRz-U(bKpGa&Ve(e1{tQyd;AYx@?_~=_FupKLb-mV|LtVE zeM2{5udjN+uplQstxS0IF2v`qe^bne^8VY-NWDb&!sRi%lA7_y1`Fv{Ta(N}4X-=Y zKeUMR6B!dIk{ggreW`SUr#IFmOtKDr?N#j+ZE!vGZ@Wd?vKu|dee)}m7q4+1SR4L? z+4oJ6pM^>un=-FA=7Qf%&-B8we`--GL>QIg)8> z1qU}a`Wa5}{OCEZx_~YzlAL)Go+vs0_lM_P-i(Av$tp|kH**Zz<|wCcOO;f#tT=Jl zxz}mO3WeV(!QG9UvEQsCm&3!pJBWR&WIwg&ys$IRj8D>zr<7!$YFch%UApUJJoog* zPfb?ScCIoz)r0MrB5`pRnjT*8$!<&-?a9c2Q#Z4m(C?n6^#f}+5S_CHCybPIS0VDK z=#$cA6h zUq895wfkkj;*w7ROL`ZrC3LZgZwf-2%f8ubz1Zqn@CQ`H{uyVPaMj&-+xECc>z996 zTdI{XbGqJ>h?yIoy<#ipL9&phZe5V#z#9ZrLBD>&(C?NMxb}_+d1%yAUCdBt*U@Ik zy!_j3Z=K2_gyY#ujdE;_@yJm4c5{3gaxZm8t>vfI!x)$0>dtXY#lW*WVR-6AotlIE z#`Zcz3Cg5QJ&Pw{P>%jB4P?m1RMe&d3^^oqkkwGO#pip4)u|X-Xr7BgOj@c=*r4Cl zNk2^MIs;O~BjCP*!v7spA%L=`;0NQvdb`xva0l?DKU@f<57GJW=nL?aivdhrqK2iR z1Wl5#&Ro^TR=z<<^3=(@4h;D zI3?kU=wW;-$%uD~WYq2OsH5Xo?j8{9gTNogLmqO72&1QslJ&n*lL)^32tHVDwiGfF zh@A3^f_Zof2`@oZsAgnilpmGm|V)8%Z zONP=46$=anetwp07LV_!p^JV;mDL)#&aDzbO3#I)ohmfhBhVz zoG3lM8i5ltKMzhFH*Q|qk!6plQ-7q*d+~khU)LTTrL6j?^%!3*)c5FoVhafHY#fCy z6+@1}1$8sWugK8bcQhRlj^@T_HLKk5n_O%XWn5&Dd-|~G1t}{$Q~(Ufj;5yr-|!E4 zQ#4Yc>Qoa)0vSaOd}5y+%&UjOWO%ObJzg^!PC2VY*udnlsK*7jLU0KXV!o0aILDzW zdk`3)g~N`D!Rt2z2;b~(glY;72hTJXThO6yrCn+Mn)V34rad%Yjd2ihl}75r01tL` zw>l$E1U{fXB;x86TrXkZkZvq3Iswx{Ia6>_26LqtbHSPYQ(UenPxK6c=ehcZTAkjc_1^gLwnK6uO9e`>W8`Bp=TRuTeC z>p}5dXN5#PMfkVQ!DV`<``1&0 zNTp@?Pp!1KkjUZRGz&4N2|D12F<-$}R*_?6`s-6Zi_PV++b{pr8q?iRQ|^aH-;>}K zR{Mv-~@lWFQiqPZx9GgM{COb2(gyMXD7NC_6M6RaXbk z!)J-QQVLX+TtxUZNut{JvE*R=AlnS`4k{lc0+tmGE7}tTBtePuWIqQuhnIv|3bu+X z8r%pynHZeBf_yXn8Gdld{|8`0maFw&Em+8h$uw1Bb&+d6bh?1xQlJ`G`m0w(4Soeq z>jAKTuc=|@Ipg{XKic>>T)LFd^@k21UP6Gi{ZcZJR;Z&u&;~s|Y08vg>icz&6~{q_ zZ^8>9xJgfZM#ewkVAOilq6>?Jlq3znEx=L8b5e2T^5LR$+#}8Wpj=ofD1_BdtvBi` z9*_Bwn4emGK-}*jxim?k`tkvF{=5i!{|7?85F;38huA2wDd&{2Tb1`90!NDEBC{)8*HA6#M$jZfmr`*Wf; zfAM0s`@|A5k)q4dTw)i9)N!h9KjlMb1D~z432FRdcNi(s1=*dFNa&w4!s$ux09zDi z=?wDewj=(h);{#j-&nVDj#Wv-98_L;7apj>&8o@r0+Y6v5NLAct0`RfIP#DkwFuuA zjuoF$A=BLmzwMqeRDmWBxh%%UGHM`}i}a|Hero9`*k$GV zuA|A*=8S0Bpr?htLqRq|+4s9M{_3X_l@o1(!K%RaT!6k~w}#lc(%urv*6%}08kn5% z_c?8GLz4L0!VzaepFA!VD zFpJa7qlNs^;W5iHs^nXw}@z}EF71g>c&~H=+&nwKr zzDu`JM@-2>!a|Jvst23adtgg5+oBXEi3)8@RH+aR7-Bk`zqA4qs{cW!tugp}p5leO*Rw35jJ2b^>_u$vynIcYzh>o#jdv@Hus?7|{e0JcD~@Yl!^V7xEbnCMSOCPoYk!lymserml# z)kkwKP?z3U`#49!ykHmSfP-d`!jKJ`ogpNalX2_ASCB;{+*pc$iw9*0u(|Y{Lr)9N zIwsDoVEhtWLKDXoFuOhtiwe?wKx5EQroq!SzeI2V=E4Nd6uL&RI#663q1{OaS8k+1 z*Xk~q18-C(94L`bm)snokGqmRt;CmCj-Lw_sbI=xB;_7er+Uz|Wa`GjpIVEN=9Ne@ zrF%Qv7(T(`u?{z?>N2M;_%Zi}|AR6kkOhVOvDBm{kfopnGxfyYzay~5qpAICRoru-k5+#JU~5;yiNMTdGRJruqf(v0F} zM|~A`;7te^e?tKB9y%)3m1J#I+m{Jf#}TfEy+?sH1!o6|jQB;~4Xv22-3z7uCaBtWsq0t$>;e zY-Y{G3|;*s=lj3m_io*Y6oyT9DZ4#ah9irX_s)8L6f2jD@?E3 zTOPBwJiYrXP9q$PYFuKV4dv|qk*+|xFrp->o49&VHHJA%w~+48WJkac8dv2zyfX6n z*_t>IA4&qcw*VJ^IN+eVK)%`?G|b9FpQ}}k4SIFqI3AHDa%&HBGqpB2sN3& z;{;D?&3-2T_n%q~!!S8LJs|aPEJ!6Ve8IsZ&ptYQSD!;M12VP1mmiyOSt>-}(^8N< zcadOQ-1);6TIl-q(N)0sE%2N^?jAjv@K((XhtKTzx7DcKhH0wIDPjbC@7S zdg|K;2*X0!f-ekblA3OQ@L@dO+s+DX%mBD$io(?zcvRU|V&^b`j z_gjH;%&}g${J^JMGN;I*jX0G?so4*<1SC}Rv&ihsn5flVYiN3+dRz{Q$qI_3YsDo( zBFy1vkAnOEsS5u>gb%^Egq2;SO5`$s?7?B4_-f4)zOXfEDpxi<4h13q+D8w zvQuz2j@2Nv6CSs^H-J0IYI!84%cK4mtMH2nK`X}Lv}eJxdPm&X_yBntrt50BE5x$o zw&&B2``;Y%f{&bb@mzNA$g!!WgUeog`10m{10@5abo~N&0Q(P1K*1#oS|=UI ziMK+SLc=aZ!8+T69STyLtZiyJmBWUC32=1AshuZS?GUm1a}O5ypQvjf)kXryUXZZ7 zpsDx_pnbrV0`FhoVUoRdYT1QlNa{iE?Egc!$s!)kY-o6l(52oll=;7~ZBcKr=^%hK zU66e~l|~jZ>0tSM)qCPkEz-ZssVBm5J0PD@3l~}e?f*ELh6p`gt8u17!;>KD#?jo7 zv@QL01yKtv!2e(8R5Gh@v4NliC;?gq?VUl_j$wG{Fycd3QT3v96dh`K0)j{mX@sy1 z0vaJj!SSe8^8d$%BJ3xiu>cA7Y9Q9KVfaE7guHlLi4>*aD}y$u*;(L*!i?U9A_C~k zStTc=^kArZ1>x$!fD}_FQLSPvM*^(y(LytWRv`VF*hBEzTXomOPHO^Xh^f--a?2Ff z5E3aBk6Z1c9o<$@U}v$%LB!U~?E@n0RVw(5zVy+209|uk58t4M33!M^??x;S>PS%pM{;O(tf!qW>k7IM2vNvuQ#JIC zACWkH!s7NdYxU~xUz36t3t=nLLvN9PT&^l(HELH?q2F;$JRKx*6ml;!Y$xIYI9GH? z{Xb>TCET#$#;2nf8wylY6{pUBQuDcn?#OpILyR*R5_s`W3Kj$JOrvPTOhFmm?XUqL z>tYAv{~f4}}fG4*p7js2OI9_u>Wpc}3KC63=<;@3JUG7cNk0k)q=5j-@{ zEusP^TNj?4&=9$66^{B`G#yn-4)Ps0xLi6A(oF4=P>I8G-X$M7Q$4tfKH?&EvgMUB z+wrM7WV+Em&5cQA7xI~Zzc}9aQ_G*YRm59tV1yBuS^Ar+FoSq=>^Cj+jmPa%9;Y`y zo%-a$MD*hb+{Y=2V?Hl(Kz&*-Uq0r1bsJ~fZ1RqTFxLdkRzVQMO6ve4D@ecWP|u1D zFvO}2$%+Me=wqk_mPh}KVAYrr-Mo)$!UQ#HdV_H7h7W>U(;+16SXB;<|NEJDSXY-_LTgLk_- zC!1efq&0EepG|Y)=U*5lyI`Rb4Xm^vR}Vfct}1I9VR!RHwCH0NF;~gqlOC88w^^!W zC;1G?+yXKKT;P4uVYL7Ol!8yLHY7UAkq4b8J%*7onT@7zfq-1o zzGatuRXl+gcvDyZ%(mqbE^8L&Xe*pR$8X56$9o?xe{yyRV#AXHv}yy?f#eZaPL?nD z@>6TkV6-wyISND7$roHbAeh5>qo1$gmV^8_&p8EmPod4jGXgjbN>YmO73!$kpF0ezGWz1zhcq5#SQ*;X4vGeOgfkt7t_>&4sj#>NVD~?jAVX1<|wBLlAk`gdtjZa{$wfFyafwj>BJpD*Q_W= zo=N z;3M8-kp)k2dkbh)Vn75TI4~M}3BQ33u+;h#avy9e8wC;fai>I+gU9yYO;ayX8}O33Am_Z=4i2!iQ~{h z?D-9kjlgd{G0dnS?6zAqj#uAO=nbyDP0YFnBF4SytG~E0^e?S(UlcZ_J--+UYtY8U zf!GV%5fArb@p6mESxtQC`5Lty<}ye)NTFus$B<8}n(0JIXyWSV;KUtz#GYwrD07g= z>xj+pkMn~pwz%XRA&5VK z|Eu7|4ovlTrKSAl$(c4-V3(=`s$Y*z-Pt1dNzvIk>XD`ED4y)Ha0dF-u&3yYINxf& zfu-GnZA~mw+Uehm&$k|2Ln9_S5GQ*Xm2O{b5Ig$A_O|KcgX3{|5hz&|VY!PU?Ntj6 zmFX=V^oZ+@1B2ltou>9%O^4{OZKnw^|j2lNZk#$Kk}G@Q3NFT-L4@jl6Lhs*R_sg;86jlQ4lk2>Bh6S_$5L zu$xihCu0@j$*MY)myWZ8>-ybgT*c|;#Rrd9mzW(_aqF!1)&?B>lkR+dxAF$rGM3zt zTgG(rVODybU|Nad(C^l)naF(P2l5><+U_HWJn%8HnHpX-<2$gr;SmBnjQ~0ZHUJY2 z?>n#-gpWX|rs~9p-;$x4aU6zbSx~VXo1yd3NzTF1|6#)#Aa=qS{PXEzNagp>_ysl` zQ7_P9SiF5HYJq|@<1dIz^?e-`uB3Ql{+eQ&rUyY`#)b`@&NrjCl9>E6VU(7CDUH1R zmmwS+E}UD!#TD0cHT4;Bzv{qZ+{Xs=Km*l%$`SquENR)5{B2@wAVBoGx&)y+g8T`0tgFwKt>4(dng(03GdR1HzQT0|iis8r(N zDc&H!)bO2=s7|*q@ugh{WP`^2TGJcyaNmk*d=7xzdo~5Xq|{dNpW&hCXhhdA8vIoeiYIL|4C=l`cj`FzP$Cvj84q2qNYVN9)67lbve zFG^<7!$q5@q)_ot>-D)DSZfYEN25UMpmu8@;8>{YYTI}=#>HFo-|f0RYLlHgQDWOT zXQh66v6)>MSwhjNa8$5cGTKP0_QY-58iQwBks6ub>?~FF13P^cf7%dSJ_k_ss}?d+ zD$bn_D%UpY`bciQOp2TpAsf)^!)}H7g10wvw7||jZ#-Gvm`{8kK;1a;1A%-|wuB~{ zjbU6RrRy3&APplw>B-sWENxD_5o7mp0}?P{6m2LaC&fy5Y^Dlnb;M;PouCj);cp)F zVt<^GTXvbX*>aaTxFVb%CqcLx-#@}S&GL!-ES5M3@`L+zwPd$vm?e)OS+#~nb2H1DC)curXe;L>T2H_g{sht-W_!xuA6e7a!A3Oduq#@Ug`vB#R^aRq z%PB_0`MTlOPpwglDwO7`CmxCmUs=lJ7exj<>w{O>vPbirR8(eX=XvI7Y<{vy&fN#W zHZr@DEPWk$14tKwR2NxYmik2W^|lW>IOeL~akE4EQjg zztb7=3$VLSlwRHJD`U2p6ZnaI8#D8Pn}-q0?3`fCEoCydjX9;OcU_bsnx6NP(K#4A zmm^x?Mjo{HGJ`kG*1?8x_NJmj7D`dcAivs?Vx<5@$-9YkaelM?yJt3Nl~*Eob&Z?? zW}YiUA~8_3+KGtEU$`1cZvhCh5THb$}1BUS_RX4pD9CXp)-% z|CdD#hn_dhn60X0_1hjs{(9TPinx@No*DgOSHWO?)_Swf(3d6Jc0!~6n+8qh#ZFg( z#+|dAux>x?cUiv0-p^ubJ{I+?N1kWn-aq)w{gz4Fu|F4|y=-`)&3W0}ySh3oIf>Se z*1ty0v65sNacBXt47@LS?wrwmc)k}J>+6Hh%7T2umWiLuRuea@IXQXehF>TKaaD#^ z97bdhytY&n&{EA#?~9=)LYG9;cWe zO$?L~LlpzakA3x-s?S0mBt~F&?HQc0{KT}gYogV9rRunRVM{#3ZqVA;J`VQWGpV

mYqgY;B2O7JqEf(3EB|8l%+zL@YUg^{?L`$A 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 A2><{9 From c48b501bf683faae6fcf9cadb7ee96fc0da319ba Mon Sep 17 00:00:00 2001 From: Laurens Bosscher Date: Wed, 30 Oct 2019 18:52:52 +0100 Subject: [PATCH 104/327] fix: manually flush microtasks in afterEach (#514) This PR replaces calling async act() in afterEach, with a version that still flushes microtasks, but doesn't wrap with act(). Explanation: If there are any hanging microtasks, that means a test ran without asserting on a valid state. Any async portion that causes updates should be asserted on, or atleast resolved within the scope of a test. This PR should still fire missing act warnings for a test, but won't let it leak to the next one. Co-authored-by: Sunil Pai --- src/flush-microtasks.js | 47 +++++++++++++++++++++++++++++++++++++++++ src/index.js | 4 ++-- 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/flush-microtasks.js diff --git a/src/flush-microtasks.js b/src/flush-microtasks.js new file mode 100644 index 00000000..a34b5e85 --- /dev/null +++ b/src/flush-microtasks.js @@ -0,0 +1,47 @@ +/* istanbul ignore file */ +// the part of this file that we need tested is definitely being run +// and the part that is not cannot easily have useful tests written +// anyway. So we're just going to ignore coverage for this file +/** + * copied from React's enqueueTask.js + */ + +let didWarnAboutMessageChannel = false +let enqueueTask +try { + // read require off the module object to get around the bundlers. + // we don't want them to detect a require and bundle a Node polyfill. + const requireString = `require${Math.random()}`.slice(0, 7) + const nodeRequire = module && module[requireString] + // assuming we're in node, let's try to get node's + // version of setImmediate, bypassing fake timers if any. + enqueueTask = nodeRequire('timers').setImmediate +} catch (_err) { + // we're in a browser + // we can't use regular timers because they may still be faked + // so we try MessageChannel+postMessage instead + enqueueTask = callback => { + if (didWarnAboutMessageChannel === false) { + didWarnAboutMessageChannel = true + // eslint-disable-next-line no-console + console.error( + typeof MessageChannel !== 'undefined', + 'This browser does not have a MessageChannel implementation, ' + + 'so enqueuing tasks via await act(async () => ...) will fail. ' + + 'Please file an issue at https://github.com/facebook/react/issues ' + + 'if you encounter this warning.', + ) + } + const channel = new MessageChannel() + channel.port1.onmessage = callback + channel.port2.postMessage(undefined) + } +} + +export default function flushMicroTasks() { + return { + then(resolve) { + enqueueTask(resolve) + }, + } +} diff --git a/src/index.js b/src/index.js index 5e05b725..5e942670 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,4 @@ -import {asyncAct} from './act-compat' +import flush from './flush-microtasks' import {cleanup} from './pure' // if we're running in a test runner that supports afterEach @@ -8,7 +8,7 @@ import {cleanup} from './pure' // or set the RTL_SKIP_AUTO_CLEANUP env variable to 'true'. if (typeof afterEach === 'function' && !process.env.RTL_SKIP_AUTO_CLEANUP) { afterEach(async () => { - await asyncAct(async () => {}) + await flush() cleanup() }) } From 2cac7b97d16eeecb8be3a8d8b20b1232ddf83ea9 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2019 11:54:46 -0600 Subject: [PATCH 105/327] docs: add LaurensBosscher as a contributor (#516) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 28b9d4e8..bbf012fc 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -979,6 +979,15 @@ "code", "test" ] + }, + { + "login": "LaurensBosscher", + "name": "Laurens Bosscher", + "avatar_url": "https://avatars0.githubusercontent.com/u/13363196?v=4", + "profile": "http://www.laurensbosscher.nl", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 6aff8b27..f309091b 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ practices.

[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-101-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-102-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Join the community on Spectrum][spectrum-badge]][spectrum] @@ -515,6 +515,7 @@ Thanks goes to these people ([emoji key][emojis]): Aayush Rajvanshi
Aayush Rajvanshi

πŸ“– Ely Alamillo
Ely Alamillo

πŸ’» ⚠️ Daniel Afonso
Daniel Afonso

πŸ’» ⚠️ + Laurens Bosscher
Laurens Bosscher

πŸ’» From 11460a3b31d3826d59a8920a25ba2e3fb7e17495 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 4 Nov 2019 15:58:33 +0100 Subject: [PATCH 106/327] fix: False positive warning about MessageChannel (#522) --- src/flush-microtasks.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/flush-microtasks.js b/src/flush-microtasks.js index a34b5e85..4863b72e 100644 --- a/src/flush-microtasks.js +++ b/src/flush-microtasks.js @@ -21,20 +21,22 @@ try { // we can't use regular timers because they may still be faked // so we try MessageChannel+postMessage instead enqueueTask = callback => { - if (didWarnAboutMessageChannel === false) { + const supportsMessageChannel = typeof MessageChannel === 'function' + if (supportsMessageChannel) { + const channel = new MessageChannel() + channel.port1.onmessage = callback + channel.port2.postMessage(undefined) + } else if (didWarnAboutMessageChannel === false) { didWarnAboutMessageChannel = true + // eslint-disable-next-line no-console console.error( - typeof MessageChannel !== 'undefined', 'This browser does not have a MessageChannel implementation, ' + 'so enqueuing tasks via await act(async () => ...) will fail. ' + 'Please file an issue at https://github.com/facebook/react/issues ' + 'if you encounter this warning.', ) } - const channel = new MessageChannel() - channel.port1.onmessage = callback - channel.port2.postMessage(undefined) } } From 14670debd45236d2c5d0a61a83dadc72af1bef7c Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Sun, 17 Nov 2019 17:29:13 +0100 Subject: [PATCH 107/327] test: Build in CodeSandbox CI (#513) * test: Build in codesandbox ci * poke csb --- .codesandbox/ci.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .codesandbox/ci.json diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json new file mode 100644 index 00000000..f9286936 --- /dev/null +++ b/.codesandbox/ci.json @@ -0,0 +1,3 @@ +{ + "sandboxes": ["new", "github/kentcdodds/react-testing-library-examples"] +} From 965db571cd14203c8ae246c481c5bbf345364dee Mon Sep 17 00:00:00 2001 From: Alec Larson <1925840+aleclarson@users.noreply.github.com> Date: Wed, 11 Dec 2019 00:52:59 -0500 Subject: [PATCH 108/327] fix: support automatic types in pnpm installs (#540) * fix: support automatic types in pnpm installs When installed with pnpm, the @types/testing-library__react package cannot be used by packages that don't directly depend on it, so we need to re-export them. * poke --- index.d.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 index.d.ts diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 00000000..e50a1e7c --- /dev/null +++ b/index.d.ts @@ -0,0 +1 @@ +export * from 'testing-library__react' From ad5598fe7abeaa0bae01d96d5dc931e6bc61b88f Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Tue, 10 Dec 2019 22:59:21 -0700 Subject: [PATCH 109/327] chore: update all packages --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 53a43cb5..25e3adbc 100644 --- a/package.json +++ b/package.json @@ -45,15 +45,15 @@ "author": "Kent C. Dodds (http://kentcdodds.com/)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.6.0", - "@testing-library/dom": "^6.3.0", - "@types/testing-library__react": "^9.1.0" + "@babel/runtime": "^7.7.6", + "@testing-library/dom": "^6.10.1", + "@types/testing-library__react": "^9.1.2" }, "devDependencies": { "@reach/router": "^1.2.1", - "@testing-library/jest-dom": "^4.1.0", - "cross-env": "^6.0.0", - "kcd-scripts": "^1.7.0", + "@testing-library/jest-dom": "^4.2.4", + "cross-env": "^6.0.3", + "kcd-scripts": "^1.12.1", "npm-run-all": "^4.1.5", "react": "^16.9.0", "react-dom": "^16.9.0", From e35c21344b21c310e8a23023de1aea88fb786c96 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 13 Dec 2019 08:36:29 -0700 Subject: [PATCH 110/327] feat(screen): add screen export --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 25e3adbc..be5f4942 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.6", - "@testing-library/dom": "^6.10.1", + "@testing-library/dom": "^6.11.0", "@types/testing-library__react": "^9.1.2" }, "devDependencies": { From e6ff3b878e4fca1bc93476c4a398a15a250cd452 Mon Sep 17 00:00:00 2001 From: Sakito Mukai Date: Wed, 18 Dec 2019 02:26:00 +0900 Subject: [PATCH 111/327] docs: use screen (#553) --- README.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index f309091b..ef63ddb3 100644 --- a/README.md +++ b/README.md @@ -175,25 +175,23 @@ import '@testing-library/jest-dom/extend-expect' // NOTE: jest-dom adds handy assertions to Jest and is recommended, but not required import React from 'react' -import {render, fireEvent} from '@testing-library/react' +import {render, fireEvent, screen} from '@testing-library/react' import HiddenMessage from '../hidden-message' test('shows the children when the checkbox is checked', () => { const testMessage = 'Test Message' - const {queryByText, getByLabelText, getByText} = render( - {testMessage}, - ) + render({testMessage}) // query* functions will return the element or null if it cannot be found // get* functions will return the element or throw an error if it cannot be found - expect(queryByText(testMessage)).toBeNull() + expect(screen.queryByText(testMessage)).toBeNull() // the queries can accept a regex to make your selectors more resilient to content tweaks and changes. - fireEvent.click(getByLabelText(/show/i)) + fireEvent.click(screen.getByLabelText(/show/i)) // .toBeInTheDocument() is an assertion that comes from jest-dom // otherwise you could use .toBeDefined() - expect(getByText(testMessage)).toBeInTheDocument() + expect(screen.getByText(testMessage)).toBeInTheDocument() }) ``` @@ -265,7 +263,7 @@ export default Login // your testing framework configuration rather than importing them in every file. import '@testing-library/jest-dom/extend-expect' import React from 'react' -import {render, fireEvent} from '@testing-library/react' +import {render, fireEvent, screen} from '@testing-library/react' import Login from '../login' test('allows the user to login successfully', async () => { @@ -277,17 +275,21 @@ test('allows the user to login successfully', async () => { }) }) - const {getByLabelText, getByText, findByRole} = render() + render() // fill out the form - fireEvent.change(getByLabelText(/username/i), {target: {value: 'chuck'}}) - fireEvent.change(getByLabelText(/password/i), {target: {value: 'norris'}}) + fireEvent.change(screen.getByLabelText(/username/i), { + target: {value: 'chuck'}, + }) + fireEvent.change(screen.getByLabelText(/password/i), { + target: {value: 'norris'}, + }) - fireEvent.click(getByText(/submit/i)) + fireEvent.click(screen.getByText(/submit/i)) // just like a manual tester, we'll instruct our test to wait for the alert // to show up before continuing with our assertions. - const alert = await findByRole('alert') + const alert = await screen.findByRole('alert') // .toHaveTextContent() comes from jest-dom's assertions // otherwise you could use expect(alert.textContent).toMatch(/congrats/i) From 8db62fee6303d16e0d5c933ec1fab5841dd2109b Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2019 10:27:59 -0700 Subject: [PATCH 112/327] docs: add sakito21 as a contributor (#554) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: null <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 12 ++- README.md | 210 ++++++++++++++++++++++---------------------- 2 files changed, 118 insertions(+), 104 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index bbf012fc..86c68a68 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -988,8 +988,18 @@ "contributions": [ "code" ] + }, + { + "login": "sakito21", + "name": "Sakito Mukai", + "avatar_url": "https://avatars1.githubusercontent.com/u/15010907?v=4", + "profile": "https://twitter.com/__sakito__", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, - "repoHost": "https://github.com" + "repoHost": "https://github.com", + "skipCi": true } diff --git a/README.md b/README.md index ef63ddb3..b7033f96 100644 --- a/README.md +++ b/README.md @@ -385,142 +385,146 @@ instead of filing an issue on GitHub. Thanks goes to these people ([emoji key][emojis]): - + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - + + + + +
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦

Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️

Ryan Castner

πŸ“–

Daniel Sandiego

πŸ’»

PaweΕ‚ MikoΕ‚ajczyk

πŸ’»

Alejandro ÑÑñez Ortiz

πŸ“–

Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️

Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️

Anto Aravinth

πŸ’» ⚠️ πŸ“–

Jonah Moses

πŸ“–

Łukasz Gandecki

πŸ’» ⚠️ πŸ“–

Ivan Babak

πŸ› πŸ€”

Jesse Day

πŸ’»

Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–

Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️

Michal Baranowski

πŸ“ βœ…

Arthur Puthin

πŸ“–

Thomas Chia

πŸ’» πŸ“–

Thiago Galvani

πŸ“–

Christian

⚠️

Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”

Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”

Maddi Joyce

πŸ’»

Ryan Vice

πŸ“–

Ian Wilson

πŸ“ βœ…

Daniel

πŸ› πŸ’»

Giorgio Polvara

πŸ› πŸ€”

John Gozde

πŸ’»

Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–

Richard Kotze (mobile)

πŸ“–

Brahian E. Soto Mercedes

πŸ“–

Benoit de La Forest

πŸ“–

Salah

πŸ’» ⚠️

Adam Gordon

πŸ› πŸ’»

Matija Marohnić

πŸ“–

Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–

Mark Pollmann

πŸ“–

Ehtesham Kafeel

πŸ’» πŸ“–

Julio PavΓ³n

πŸ’»

Duncan L

πŸ“– πŸ’‘

Tiago Almeida

πŸ“–

Robert Smith

πŸ›

Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–

dadamssg

πŸ“–

Yazan Aabed

πŸ“

Tim

πŸ› πŸ’» πŸ“– ⚠️

Divyanshu Maithani

βœ… πŸ“Ή

Deepak Grover

βœ… πŸ“Ή

Eyal Cohen

πŸ“–

Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘

Michiel Nuyts

πŸ“–

Joe Ng'ethe

πŸ’» πŸ“–

Kate

πŸ“–

Sean

πŸ“–

James Long

πŸ€” πŸ“¦

Herb Hagely

πŸ’‘

Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»

Monica Powell

πŸ“–

Vitaly Sivkov

πŸ’»

Weyert de Boer

πŸ€” πŸ‘€

EstebanMarin

πŸ“–

Victor Martins

πŸ“–

Royston Shufflebotham

πŸ› πŸ“– πŸ’‘

chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️ πŸ‘€
mohamedmagdy17593
mohamedmagdy17593

πŸ’»

Donavon West

πŸ’» πŸ“– πŸ€” ⚠️

Richard Maisano

πŸ’»

Marco Biedermann

πŸ’» 🚧 ⚠️

Alex Zherdev

πŸ› πŸ’»

AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️

Daniel K.

πŸ› πŸ’» πŸ€” ⚠️ πŸ‘€

mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›

Loren ☺️

πŸ“–

MarkFalconbridge

πŸ› πŸ’»

Vinicius

πŸ“– πŸ’‘

Peter Schyma

πŸ’»

Ian Schmitz

πŸ“–

Joel Marcotte

πŸ› ⚠️ πŸ’»

Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
Pascal Duez
Pascal Duez

πŸ“¦
Minh Nguyen
Minh Nguyen

πŸ’»
LiaoJimmy
LiaoJimmy

πŸ“–
Sunil Pai
Sunil Pai

πŸ’» ⚠️
Dan Abramov
Dan Abramov

πŸ‘€

Brandon Carroll

πŸ“–

Lucas Machado

πŸ“–

Pascal Duez

πŸ“¦

Minh Nguyen

πŸ’»

LiaoJimmy

πŸ“–

Sunil Pai

πŸ’» ⚠️

Dan Abramov

πŸ‘€
Christian Murphy
Christian Murphy

πŸš‡
Ivakhnenko Dmitry
Ivakhnenko Dmitry

πŸ’»
James George
James George

πŸ“–
JoΓ£o Fernandes
JoΓ£o Fernandes

πŸ“–
Alejandro Perea
Alejandro Perea

πŸ‘€
Nick McCurdy
Nick McCurdy

πŸ‘€ πŸ’¬
Sebastian Silbermann
Sebastian Silbermann

πŸ‘€

Christian Murphy

πŸš‡

Ivakhnenko Dmitry

πŸ’»

James George

πŸ“–

JoΓ£o Fernandes

πŸ“–

Alejandro Perea

πŸ‘€

Nick McCurdy

πŸ‘€ πŸ’¬

Sebastian Silbermann

πŸ‘€
AdriΓ  Fontcuberta
AdriΓ  Fontcuberta

πŸ‘€ πŸ“–
John Reilly
John Reilly

πŸ‘€
MichaΓ«l De Boey
MichaΓ«l De Boey

πŸ‘€
Tim Yates
Tim Yates

πŸ‘€
Brian Donovan
Brian Donovan

πŸ’»
Noam Gabriel Jacobson
Noam Gabriel Jacobson

πŸ“–
Ronald van der Kooij
Ronald van der Kooij

⚠️ πŸ’»

AdriΓ  Fontcuberta

πŸ‘€ πŸ“–

John Reilly

πŸ‘€

MichaΓ«l De Boey

πŸ‘€

Tim Yates

πŸ‘€

Brian Donovan

πŸ’»

Noam Gabriel Jacobson

πŸ“–

Ronald van der Kooij

⚠️ πŸ’»
Aayush Rajvanshi
Aayush Rajvanshi

πŸ“–
Ely Alamillo
Ely Alamillo

πŸ’» ⚠️
Daniel Afonso
Daniel Afonso

πŸ’» ⚠️
Laurens Bosscher
Laurens Bosscher

πŸ’»

Aayush Rajvanshi

πŸ“–

Ely Alamillo

πŸ’» ⚠️

Daniel Afonso

πŸ’» ⚠️

Laurens Bosscher

πŸ’»

Sakito Mukai

πŸ“–
+ + This project follows the [all-contributors][all-contributors] specification. From cd3edf44ab2f96f0852fbe833644af6bed25eaae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrker=20Teke?= Date: Tue, 21 Jan 2020 21:34:30 +0300 Subject: [PATCH 113/327] docs: fix error on complex example (#560) Catch already sets error to error.message. So in render it should just show state.error. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b7033f96..565e4feb 100644 --- a/README.md +++ b/README.md @@ -248,7 +248,7 @@ function Login() {

JOF;m3i=B2=NAuvzC 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

- {state.error ?
{state.error.message}
: null} + {state.error ?
{state.error}
: null} {state.resolved ? (
Congrats! You're signed in!
) : null} From 7e2dac4a8273718a935bdf25c66719e1cceb2bf7 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2020 11:35:04 -0700 Subject: [PATCH 114/327] docs: add tteke as a contributor (#574) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 86c68a68..ac909615 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -997,6 +997,15 @@ "contributions": [ "doc" ] + }, + { + "login": "tteke", + "name": "TΓΌrker Teke", + "avatar_url": "https://avatars3.githubusercontent.com/u/12457162?v=4", + "profile": "http://turkerteke.com", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 565e4feb..fbe77b90 100644 --- a/README.md +++ b/README.md @@ -520,6 +520,7 @@ Thanks goes to these people ([emoji key][emojis]):
Daniel Afonso

πŸ’» ⚠️
Laurens Bosscher

πŸ’»
Sakito Mukai

πŸ“– +
TΓΌrker Teke

πŸ“– From d6fac0584cd06d39123301c8c2ed33ca5425a2f3 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Tue, 21 Jan 2020 16:29:49 -0700 Subject: [PATCH 115/327] chore: update all the deps --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index be5f4942..2797b540 100644 --- a/package.json +++ b/package.json @@ -45,15 +45,15 @@ "author": "Kent C. Dodds (http://kentcdodds.com/)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.7.6", + "@babel/runtime": "^7.8.3", "@testing-library/dom": "^6.11.0", "@types/testing-library__react": "^9.1.2" }, "devDependencies": { "@reach/router": "^1.2.1", - "@testing-library/jest-dom": "^4.2.4", + "@testing-library/jest-dom": "^5.0.0", "cross-env": "^6.0.3", - "kcd-scripts": "^1.12.1", + "kcd-scripts": "^4.0.0", "npm-run-all": "^4.1.5", "react": "^16.9.0", "react-dom": "^16.9.0", From b8855b5cdac97a6885a79802a8606fd5c65c7865 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Tue, 28 Jan 2020 14:56:50 -0700 Subject: [PATCH 116/327] chore: fix all contributors config --- .all-contributorsrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index ac909615..b6c2310f 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -7,6 +7,7 @@ ], "imageSize": 100, "commit": false, + "skipCi": false, "contributors": [ { "login": "kentcdodds", From 24fc9b0f60fcfb3169a62bbe41240bbf9cdcc50d Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Tue, 4 Feb 2020 08:51:04 -0700 Subject: [PATCH 117/327] chore: update issue templates --- .github/ISSUE_TEMPLATE.md | 7 ++++--- .github/ISSUE_TEMPLATE/Bug_Report.md | 2 +- .github/ISSUE_TEMPLATE/Question.md | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index b43b3471..e228ee1f 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -20,9 +20,10 @@ Thanks for your interest in the project. We appreciate bugs filed and PRs submit ❓ Questions: For questions related to using the library, please visit a support community - instead of filing an issue on GitHub. + instead of filing an issue on GitHub. You can follow the instructions in this + codesandbox to make a reproduction of your issue: https://kcd.im/rtl-help * React Spectrum - https://spectrum.chat/react-testing-library + https://spectrum.chat/testing-library * Reactiflux on Discord https://www.reactiflux.com * Stack Overflow @@ -43,7 +44,7 @@ tutorial to learn how: http://kcd.im/pull-request --> -- `react-testing-library` version: +- `@testing-library/react` version: - `react` version: - `node` version: - `npm` (or `yarn`) version: diff --git a/.github/ISSUE_TEMPLATE/Bug_Report.md b/.github/ISSUE_TEMPLATE/Bug_Report.md index dea2dde4..ba5ada35 100644 --- a/.github/ISSUE_TEMPLATE/Bug_Report.md +++ b/.github/ISSUE_TEMPLATE/Bug_Report.md @@ -22,7 +22,7 @@ tutorial to learn how: http://kcd.im/pull-request --> -- `react-testing-library` version: +- `@testing-library/react` version: - `react` version: - `node` version: - `npm` (or `yarn`) version: diff --git a/.github/ISSUE_TEMPLATE/Question.md b/.github/ISSUE_TEMPLATE/Question.md index efd0d846..3fd359af 100644 --- a/.github/ISSUE_TEMPLATE/Question.md +++ b/.github/ISSUE_TEMPLATE/Question.md @@ -12,6 +12,10 @@ and feature requests so we recommend not using this medium to ask them here 😁 ## ❓ Support Forums +For questions related to using the library, please visit a support community +instead of filing an issue on GitHub. You can follow the instructions in this +codesandbox to make a reproduction of your issue: https://kcd.im/rtl-help + - React Spectrum https://spectrum.chat/react-testing-library - Reactiflux on Discord https://www.reactiflux.com - Stack Overflow From c5a7206733191bf9d8b17c8c6112d3776f8b875a Mon Sep 17 00:00:00 2001 From: Zach Brogan Date: Sat, 22 Feb 2020 08:39:11 -0700 Subject: [PATCH 118/327] fix: make fireEvent mouseEnter/mouseLeave work with addEventListener (#588) * fix: make fireEvent mouseEnter/mouseLeave work with addEventListener (#577) * Add tests for native events * fix: make fireEvent select work with addEventListener. Improve organization of native events test. Closes #577 --- src/__tests__/events.js | 35 +++++++++++++++++++++++++++++++++++ src/pure.js | 14 ++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/__tests__/events.js b/src/__tests__/events.js index afe2193f..dc529344 100644 --- a/src/__tests__/events.js +++ b/src/__tests__/events.js @@ -153,6 +153,41 @@ eventTypes.forEach(({type, events, elementType, init}) => { }) }) +eventTypes.forEach(({type, events, elementType, init}) => { + describe(`Native ${type} Events`, () => { + events.forEach(eventName => { + let nativeEventName = eventName.toLowerCase() + + // The doubleClick synthetic event maps to the dblclick native event + if (nativeEventName === 'doubleclick') { + nativeEventName = 'dblclick' + } + + it(`triggers native ${nativeEventName}`, () => { + const ref = React.createRef() + const spy = jest.fn() + const Element = elementType + + const NativeEventElement = () => { + React.useEffect(() => { + const element = ref.current + element.addEventListener(nativeEventName, spy) + return () => { + element.removeEventListener(nativeEventName, spy) + } + }) + return + } + + render() + + fireEvent[eventName](ref.current, init) + expect(spy).toHaveBeenCalledTimes(1) + }) + }) + }) +}) + test('onChange works', () => { const handleChange = jest.fn() const { diff --git a/src/pure.js b/src/pure.js index 1b1838bf..40588797 100644 --- a/src/pure.js +++ b/src/pure.js @@ -128,10 +128,20 @@ Object.keys(dtlFireEvent).forEach(key => { // React event system tracks native mouseOver/mouseOut events for // running onMouseEnter/onMouseLeave handlers // @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/EnterLeaveEventPlugin.js#L24-L31 -fireEvent.mouseEnter = fireEvent.mouseOver -fireEvent.mouseLeave = fireEvent.mouseOut +const mouseEnter = fireEvent.mouseEnter +const mouseLeave = fireEvent.mouseLeave +fireEvent.mouseEnter = (...args) => { + mouseEnter(...args) + return fireEvent.mouseOver(...args) +} +fireEvent.mouseLeave = (...args) => { + mouseLeave(...args) + return fireEvent.mouseOut(...args) +} +const select = fireEvent.select fireEvent.select = (node, init) => { + select(node, init) // React tracks this event only on focused inputs node.focus() From 41c01c81a169e928287c227c240aeb29045e5ef8 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 22 Feb 2020 08:41:19 -0700 Subject: [PATCH 119/327] docs: add zbrogz as a contributor (#592) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] * Update .all-contributorsrc Co-authored-by: Kent C. Dodds --- .all-contributorsrc | 13 +++++++++++-- README.md | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index b6c2310f..3cd8e61d 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1007,9 +1007,18 @@ "contributions": [ "doc" ] + }, + { + "login": "zbrogz", + "name": "Zach Brogan", + "avatar_url": "https://avatars1.githubusercontent.com/u/319162?v=4", + "profile": "http://linkedin.com/in/zachbrogan", + "contributions": [ + "code", + "test" + ] } ], "contributorsPerLine": 7, - "repoHost": "https://github.com", - "skipCi": true + "repoHost": "https://github.com" } diff --git a/README.md b/README.md index fbe77b90..015ae8f1 100644 --- a/README.md +++ b/README.md @@ -521,6 +521,7 @@ Thanks goes to these people ([emoji key][emojis]):
Laurens Bosscher

πŸ’»
Sakito Mukai

πŸ“–
TΓΌrker Teke

πŸ“– +
Zach Brogan

πŸ’» ⚠️ From c4cae936af96b689982e08b2cabd1ca7f58a3cd9 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Sat, 22 Feb 2020 08:43:31 -0700 Subject: [PATCH 120/327] fix(release): manually release a patch version There was an issue with a patch release, so this manual-releases.md change is to release a new patch version. --- other/manual-releases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/manual-releases.md b/other/manual-releases.md index 0ae36c3f..3bceb32e 100644 --- a/other/manual-releases.md +++ b/other/manual-releases.md @@ -41,4 +41,4 @@ change is to release a new patch version. Reference: # ``` -The number of times we've had to do a manual release is: 4 +The number of times we've had to do a manual release is: 5 From c8a869442c94f1bf01b6638b2ce149be3f156bd9 Mon Sep 17 00:00:00 2001 From: Ryota Murakami Date: Tue, 25 Feb 2020 19:09:28 +0900 Subject: [PATCH 121/327] README: update @testing-library/jest-dom's old syntax (#590) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [@testing-library/jest-dom v5.0.0](https://github.com/testing-library/jest-dom/releases/tag/v5.0.0) later, import statement had BreakingChange. So update to latest that in the README example. Thank you πŸ˜€ Co-authored-by: Sebastian Silbermann --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 015ae8f1..4e2f1448 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,7 @@ export default HiddenMessage // __tests__/hidden-message.js // these imports are something you'd normally configure Jest to import for you // automatically. Learn more in the setup docs: https://testing-library.com/docs/react-testing-library/setup#cleanup -import '@testing-library/jest-dom/extend-expect' +import '@testing-library/jest-dom' // NOTE: jest-dom adds handy assertions to Jest and is recommended, but not required import React from 'react' @@ -261,7 +261,7 @@ export default Login // __tests__/login.js // again, these first two imports are something you'd normally handle in // your testing framework configuration rather than importing them in every file. -import '@testing-library/jest-dom/extend-expect' +import '@testing-library/jest-dom' import React from 'react' import {render, fireEvent, screen} from '@testing-library/react' import Login from '../login' From 6214d92744c0c59e1ae30ded2c860151f18f24c1 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2020 11:15:28 +0100 Subject: [PATCH 122/327] docs: add ryota-murakami as a contributor (#593) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 3 +++ 2 files changed, 12 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 3cd8e61d..f7f8d3ac 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1017,6 +1017,15 @@ "code", "test" ] + }, + { + "login": "ryota-murakami", + "name": "Ryota Murakami", + "avatar_url": "https://avatars2.githubusercontent.com/u/5501268?v=4", + "profile": "https://ryota-murakami.github.io/", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 4e2f1448..ffd75ed8 100644 --- a/README.md +++ b/README.md @@ -523,6 +523,9 @@ Thanks goes to these people ([emoji key][emojis]):
TΓΌrker Teke

πŸ“–
Zach Brogan

πŸ’» ⚠️ + +
Ryota Murakami

πŸ“– + From ea67b170fccfaf15b799d5aff5579f638b095892 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 4 Mar 2020 11:56:02 -0700 Subject: [PATCH 123/327] chore: update deps --- .travis.yml | 29 ++++++++++++++++++----------- package.json | 15 ++++++++------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 66796ac9..b670635e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,27 @@ -sudo: false language: node_js -cache: - directories: - - ~/.npm +cache: npm notifications: email: false node_js: - - '8' - - '10' - - '12' + - 10.14 + - 12 + - node install: - npm install # as requested by the React team :) # https://reactjs.org/blog/2019/10/22/react-release-channels.html#using-the-next-channel-for-integration-testing - - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then npm install react@next react-dom@next; fi -script: npm run validate -after_success: kcd-scripts travis-after-success + - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then npm install react@next + react-dom@next; fi +script: + - npm run validate + - npx codecov@3 branches: - only: master + only: + - master + - beta + +jobs: + include: + - stage: release + node_js: 12 + script: kcd-scripts travis-release diff --git a/package.json b/package.json index 2797b540..85ad3086 100644 --- a/package.json +++ b/package.json @@ -45,19 +45,19 @@ "author": "Kent C. Dodds (http://kentcdodds.com/)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.8.3", - "@testing-library/dom": "^6.11.0", + "@babel/runtime": "^7.8.4", + "@testing-library/dom": "^6.15.0", "@types/testing-library__react": "^9.1.2" }, "devDependencies": { - "@reach/router": "^1.2.1", - "@testing-library/jest-dom": "^5.0.0", - "cross-env": "^6.0.3", - "kcd-scripts": "^4.0.0", + "@reach/router": "^1.3.3", + "@testing-library/jest-dom": "^5.1.1", + "cross-env": "^7.0.1", + "kcd-scripts": "^5.4.0", "npm-run-all": "^4.1.5", "react": "^16.9.0", "react-dom": "^16.9.0", - "rimraf": "^3.0.0" + "rimraf": "^3.0.2" }, "peerDependencies": { "react": "*", @@ -67,6 +67,7 @@ "extends": "./node_modules/kcd-scripts/eslint.js", "rules": { "react/prop-types": "off", + "react/no-adjacent-inline-elements": "off", "import/no-unassigned-import": "off", "import/named": "off" } From 107e013bba95ebdfb550c7e3116deab9501abbec Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 4 Mar 2020 12:02:15 -0700 Subject: [PATCH 124/327] docs: add hottmanmichael as a contributor (#595) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index f7f8d3ac..19d0eaa6 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1026,6 +1026,15 @@ "contributions": [ "doc" ] + }, + { + "login": "hottmanmichael", + "name": "Michael Hottman", + "avatar_url": "https://avatars3.githubusercontent.com/u/10534502?v=4", + "profile": "https://github.com/hottmanmichael", + "contributions": [ + "ideas" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index ffd75ed8..5886c92e 100644 --- a/README.md +++ b/README.md @@ -525,6 +525,7 @@ Thanks goes to these people ([emoji key][emojis]):
Ryota Murakami

πŸ“– +
Michael Hottman

πŸ€” From 35522b1af7b72f771157d591387e84090fcf78f4 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 4 Mar 2020 12:13:32 -0700 Subject: [PATCH 125/327] feat(debug): accept the same arguments as prettyDOM (#596) Closes #580 --- src/__tests__/debug.js | 13 +++++++++++++ src/pure.js | 6 +++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/__tests__/debug.js b/src/__tests__/debug.js index ad3b8591..48411d88 100644 --- a/src/__tests__/debug.js +++ b/src/__tests__/debug.js @@ -36,4 +36,17 @@ test('debug pretty prints multiple containers', () => { ) }) +test('allows same arguments as prettyDOM', () => { + const HelloWorld = () =>

Hello World

+ const {debug, container} = render() + debug(container, 6, {highlight: false}) + expect(console.log).toHaveBeenCalledTimes(1) + expect(console.log.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "
+ ...", + ] + `) +}) + /* eslint no-console:0 */ diff --git a/src/pure.js b/src/pure.js index 40588797..9ed80e1e 100644 --- a/src/pure.js +++ b/src/pure.js @@ -60,12 +60,12 @@ function render( return { container, baseElement, - debug: (el = baseElement) => + debug: (el = baseElement, maxLength, options) => Array.isArray(el) ? // eslint-disable-next-line no-console - el.forEach(e => console.log(prettyDOM(e))) + el.forEach(e => console.log(prettyDOM(e, maxLength, options))) : // eslint-disable-next-line no-console, - console.log(prettyDOM(el)), + console.log(prettyDOM(el, maxLength, options)), unmount: () => ReactDOM.unmountComponentAtNode(container), rerender: rerenderUi => { render(wrapUiIfNeeded(rerenderUi), {container, baseElement}) From 04e64bb73063ae718b7fc819cdfb43e484f4ff6b Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 4 Mar 2020 12:54:35 -0700 Subject: [PATCH 126/327] docs: add MichaelDeBoey as a contributor (#599) * docs: update README.md * docs: update .all-contributorsrc --- .all-contributorsrc | 3 ++- README.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 19d0eaa6..9df4c976 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -912,7 +912,8 @@ "avatar_url": "https://avatars3.githubusercontent.com/u/6643991?v=4", "profile": "https://michaeldeboey.be", "contributions": [ - "review" + "review", + "code" ] }, { diff --git a/README.md b/README.md index 5886c92e..61fabd3e 100644 --- a/README.md +++ b/README.md @@ -508,7 +508,7 @@ Thanks goes to these people ([emoji key][emojis]):
AdriΓ  Fontcuberta

πŸ‘€ πŸ“–
John Reilly

πŸ‘€ -
MichaΓ«l De Boey

πŸ‘€ +
MichaΓ«l De Boey

πŸ‘€ πŸ’»
Tim Yates

πŸ‘€
Brian Donovan

πŸ’»
Noam Gabriel Jacobson

πŸ“– From 2613d668888a7e072f43e104e70869b9ec6d20c9 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 7 Mar 2020 07:47:22 -0700 Subject: [PATCH 127/327] docs: add stevenfitzpatrick as a contributor (#604) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 9df4c976..15254a50 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1036,6 +1036,15 @@ "contributions": [ "ideas" ] + }, + { + "login": "stevenfitzpatrick", + "name": "Steven Fitzpatrick", + "avatar_url": "https://avatars0.githubusercontent.com/u/23268855?v=4", + "profile": "https://github.com/stevenfitzpatrick", + "contributions": [ + "bug" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 61fabd3e..6224885b 100644 --- a/README.md +++ b/README.md @@ -526,6 +526,7 @@ Thanks goes to these people ([emoji key][emojis]):
Ryota Murakami

πŸ“–
Michael Hottman

πŸ€” +
Steven Fitzpatrick

πŸ› From 3d48019806d33897e89303836cd8fc5465df6516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Je=20Garc=C3=ADa?= Date: Wed, 11 Mar 2020 16:54:09 -0600 Subject: [PATCH 128/327] chore: fix typo (#608) remove extra `been`. --- src/pure.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pure.js b/src/pure.js index 9ed80e1e..03a53788 100644 --- a/src/pure.js +++ b/src/pure.js @@ -105,8 +105,8 @@ function cleanupAtContainer(container) { // react-testing-library's version of fireEvent will call // dom-testing-library's version of fireEvent wrapped inside // an "act" call so that after all event callbacks have been -// been called, the resulting useEffect callbacks will also -// be called. +// called, the resulting useEffect callbacks will also be +// called. function fireEvent(...args) { let returnValue act(() => { From 0890ccc461b4219e0d682cd5e5b75282ecb2e37f Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2020 16:57:37 -0600 Subject: [PATCH 129/327] docs: add juangl as a contributor (#609) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 15254a50..0ef0e46a 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1045,6 +1045,15 @@ "contributions": [ "bug" ] + }, + { + "login": "juangl", + "name": "Juan Je GarcΓ­a", + "avatar_url": "https://avatars0.githubusercontent.com/u/1887029?v=4", + "profile": "https://github.com/juangl", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 6224885b..da6120d4 100644 --- a/README.md +++ b/README.md @@ -527,6 +527,7 @@ Thanks goes to these people ([emoji key][emojis]):
Ryota Murakami

πŸ“–
Michael Hottman

πŸ€”
Steven Fitzpatrick

πŸ› +
Juan Je GarcΓ­a

πŸ“– From 435098c3a05ca4e9cadc0c8f2ef50c0e1dcc2ebd Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 4 Mar 2020 12:16:45 -0700 Subject: [PATCH 130/327] feat: update @testing-library/dom BREAKING CHANGE: The latest version of DOM Testing Library has several breaking changes you will want to review the changelog of DOM Testing Library to ensure you are uneffected. --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 85ad3086..47fbf096 100644 --- a/package.json +++ b/package.json @@ -45,9 +45,9 @@ "author": "Kent C. Dodds (http://kentcdodds.com/)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.8.4", - "@testing-library/dom": "^6.15.0", - "@types/testing-library__react": "^9.1.2" + "@babel/runtime": "^7.8.7", + "@testing-library/dom": "^7.0.2", + "@types/testing-library__react": "^9.1.3" }, "devDependencies": { "@reach/router": "^1.3.3", From fccc2cf302c1af2281712baa0bdad5a2b93c3212 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 4 Mar 2020 12:19:58 -0700 Subject: [PATCH 131/327] fix(node): drop Node 8 support (#576) Closes #575 BREAKING CHANGE: This release drops support for Node 8. Upgrade to Node 10 or greater. --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 47fbf096..3b5f3797 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "dist/index.js", "module": "dist/@testing-library/react.esm.js", "engines": { - "node": ">=8" + "node": ">=10" }, "scripts": { "prebuild": "rimraf dist", @@ -86,4 +86,4 @@ "url": "https://github.com/testing-library/react-testing-library/issues" }, "homepage": "https://github.com/testing-library/react-testing-library#readme" -} +} \ No newline at end of file From 9fc8581713d03972f935132b5cfab316d6b93abe Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 4 Mar 2020 12:23:33 -0700 Subject: [PATCH 132/327] feat: Flush microtasks in cleanup (#519) --- src/__tests__/cleanup.js | 8 ++++---- src/index.js | 4 +--- src/pure.js | 4 +++- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/__tests__/cleanup.js b/src/__tests__/cleanup.js index ec2a057c..a870a42d 100644 --- a/src/__tests__/cleanup.js +++ b/src/__tests__/cleanup.js @@ -1,7 +1,7 @@ import React from 'react' import {render, cleanup} from '../' -test('cleans up the document', () => { +test('cleans up the document', async () => { const spy = jest.fn() const divId = 'my-div' @@ -17,12 +17,12 @@ test('cleans up the document', () => { } render() - cleanup() + await cleanup() expect(document.body.innerHTML).toBe('') expect(spy).toHaveBeenCalledTimes(1) }) -test('cleanup does not error when an element is not a child', () => { +test('cleanup does not error when an element is not a child', async () => { render(
, {container: document.createElement('div')}) - cleanup() + await cleanup() }) diff --git a/src/index.js b/src/index.js index 5e942670..38aa9076 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,3 @@ -import flush from './flush-microtasks' import {cleanup} from './pure' // if we're running in a test runner that supports afterEach @@ -8,8 +7,7 @@ import {cleanup} from './pure' // or set the RTL_SKIP_AUTO_CLEANUP env variable to 'true'. if (typeof afterEach === 'function' && !process.env.RTL_SKIP_AUTO_CLEANUP) { afterEach(async () => { - await flush() - cleanup() + await cleanup() }) } diff --git a/src/pure.js b/src/pure.js index 03a53788..9060c941 100644 --- a/src/pure.js +++ b/src/pure.js @@ -7,6 +7,7 @@ import { configure as configureDTL, } from '@testing-library/dom' import act, {asyncAct} from './act-compat' +import flush from './flush-microtasks' configureDTL({ asyncWrapper: async cb => { @@ -88,7 +89,8 @@ function render( } } -function cleanup() { +async function cleanup() { + await flush() mountedContainers.forEach(cleanupAtContainer) } From 7942f684509831afcdd4d88b191e9193fab576ff Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 4 Mar 2020 12:52:19 -0700 Subject: [PATCH 133/327] fix: remove deprecated cleanup-after-each (#598) BREAKING CHANGE: This removes `@testing-library/react/cleanup-after-each` which is deprecated and hasn't done anything for many versions. --- cleanup-after-each.js | 4 ---- package.json | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) delete mode 100644 cleanup-after-each.js diff --git a/cleanup-after-each.js b/cleanup-after-each.js deleted file mode 100644 index ace739eb..00000000 --- a/cleanup-after-each.js +++ /dev/null @@ -1,4 +0,0 @@ -console.warn( - 'The module `@testing-library/react/cleanup-after-each` has been deprecated and no longer does anything (it is not needed). You no longer need to import this module and can safely remove any import or configuration which imports this module', -) -/* eslint no-console:0 */ diff --git a/package.json b/package.json index 3b5f3797..cb29c210 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ }, "files": [ "dist", - "cleanup-after-each.js", "dont-cleanup-after-each.js", "pure.js" ], @@ -86,4 +85,4 @@ "url": "https://github.com/testing-library/react-testing-library/issues" }, "homepage": "https://github.com/testing-library/react-testing-library#readme" -} \ No newline at end of file +} From f26b8df20369ab4bb41a462d6123819d526e53b9 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 4 Mar 2020 13:23:10 -0700 Subject: [PATCH 134/327] chore: cleanup repo (#600) --- .gitattributes | 3 +-- .gitignore | 6 ------ .prettierignore | 3 +-- .prettierrc | 11 ----------- .prettierrc.js | 1 + .travis.yml | 2 +- package.json | 14 +++++++------- src/__tests__/act.js | 6 +++--- src/__tests__/debug.js | 6 +++--- src/__tests__/end-to-end.js | 12 +++++------- src/__tests__/render.js | 12 ++++++------ src/__tests__/stopwatch.js | 11 ++++++----- 12 files changed, 34 insertions(+), 53 deletions(-) delete mode 100644 .prettierrc create mode 100644 .prettierrc.js diff --git a/.gitattributes b/.gitattributes index 391f0a4e..6313b56c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1 @@ -* text=auto -*.js text eol=lf +* text=auto eol=lf diff --git a/.gitignore b/.gitignore index 5bb9facf..8e0c70cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,9 @@ node_modules coverage dist -.opt-in -.opt-out .DS_Store -.eslintcache - -yarn-error.log # these cause more harm than good # when working with contributors package-lock.json yarn.lock - diff --git a/.prettierignore b/.prettierignore index 30117ea2..9c628283 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,3 @@ -package.json node_modules -dist coverage +dist diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index f3685197..00000000 --- a/.prettierrc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "printWidth": 80, - "tabWidth": 2, - "useTabs": false, - "semi": false, - "singleQuote": true, - "trailingComma": "all", - "bracketSpacing": false, - "jsxBracketSameLine": false, - "proseWrap": "always" -} diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000..4679d9bf --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1 @@ +module.exports = require('kcd-scripts/prettier') diff --git a/.travis.yml b/.travis.yml index b670635e..2da1648c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ cache: npm notifications: email: false node_js: - - 10.14 + - 10.18 - 12 - node install: diff --git a/package.json b/package.json index cb29c210..6ec8284a 100644 --- a/package.json +++ b/package.json @@ -5,19 +5,19 @@ "main": "dist/index.js", "module": "dist/@testing-library/react.esm.js", "engines": { - "node": ">=10" + "node": ">=10.18" }, "scripts": { "prebuild": "rimraf dist", "build": "npm-run-all --parallel build:main build:bundle:main build:bundle:pure", - "build:main": "kcd-scripts build --no-clean", "build:bundle:main": "kcd-scripts build --bundle --no-clean", "build:bundle:pure": "cross-env BUILD_FILENAME_SUFFIX=.pure BUILD_INPUT=src/pure.js kcd-scripts build --bundle --no-clean", + "build:main": "kcd-scripts build --no-clean", "lint": "kcd-scripts lint", + "setup": "npm install && npm run validate -s", "test": "kcd-scripts test", "test:update": "npm test -- --updateSnapshot --coverage", - "validate": "kcd-scripts validate", - "setup": "npm install && npm run validate -s" + "validate": "kcd-scripts validate" }, "husky": { "hooks": { @@ -41,7 +41,7 @@ "end-to-end", "e2e" ], - "author": "Kent C. Dodds (http://kentcdodds.com/)", + "author": "Kent C. Dodds (https://kentcdodds.com)", "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.7", @@ -51,7 +51,7 @@ "devDependencies": { "@reach/router": "^1.3.3", "@testing-library/jest-dom": "^5.1.1", - "cross-env": "^7.0.1", + "cross-env": "^7.0.2", "kcd-scripts": "^5.4.0", "npm-run-all": "^4.1.5", "react": "^16.9.0", @@ -79,7 +79,7 @@ ], "repository": { "type": "git", - "url": "https://github.com/testing-library/react-testing-library.git" + "url": "https://github.com/testing-library/react-testing-library" }, "bugs": { "url": "https://github.com/testing-library/react-testing-library/issues" diff --git a/src/__tests__/act.js b/src/__tests__/act.js index 2adcee94..97438d77 100644 --- a/src/__tests__/act.js +++ b/src/__tests__/act.js @@ -1,5 +1,5 @@ import React from 'react' -import {render, fireEvent} from '../' +import {render, fireEvent, screen} from '../' test('render calls useEffect immediately', () => { const effectCb = jest.fn() @@ -13,8 +13,8 @@ test('render calls useEffect immediately', () => { test('findByTestId returns the element', async () => { const ref = React.createRef() - const {findByTestId} = render(
) - expect(await findByTestId('foo')).toBe(ref.current) + render(
) + expect(await screen.findByTestId('foo')).toBe(ref.current) }) test('fireEvent triggers useEffect calls', () => { diff --git a/src/__tests__/debug.js b/src/__tests__/debug.js index 48411d88..088385b7 100644 --- a/src/__tests__/debug.js +++ b/src/__tests__/debug.js @@ -1,5 +1,5 @@ import React from 'react' -import {render} from '../' +import {render, screen} from '../' beforeEach(() => { jest.spyOn(console, 'log').mockImplementation(() => {}) @@ -26,8 +26,8 @@ test('debug pretty prints multiple containers', () => {

Hello World

) - const {getAllByTestId, debug} = render() - const multipleElements = getAllByTestId('testId') + const {debug} = render() + const multipleElements = screen.getAllByTestId('testId') debug(multipleElements) expect(console.log).toHaveBeenCalledTimes(2) diff --git a/src/__tests__/end-to-end.js b/src/__tests__/end-to-end.js index 4cdfc328..cbbf0973 100644 --- a/src/__tests__/end-to-end.js +++ b/src/__tests__/end-to-end.js @@ -1,5 +1,5 @@ import React from 'react' -import {render, wait} from '../' +import {render, waitForElementToBeRemoved, screen} from '../' const fetchAMessage = () => new Promise(resolve => { @@ -30,10 +30,8 @@ class ComponentWithLoader extends React.Component { } test('it waits for the data to be loaded', async () => { - const {queryByText, queryByTestId} = render() - - expect(queryByText('Loading...')).toBeTruthy() - - await wait(() => expect(queryByText('Loading...')).toBeNull()) - expect(queryByTestId('message').textContent).toMatch(/Hello World/) + render() + const loading = () => screen.getByText('Loading...') + await waitForElementToBeRemoved(loading) + expect(screen.getByTestId('message')).toHaveTextContent(/Hello World/) }) diff --git a/src/__tests__/render.js b/src/__tests__/render.js index 28d7f9e7..54916ba4 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -1,6 +1,6 @@ import React from 'react' import ReactDOM from 'react-dom' -import {render} from '../' +import {render, screen} from '../' test('renders div into document', () => { const ref = React.createRef() @@ -39,9 +39,9 @@ test('works great with react portals', () => { ) } - const {unmount, getByTestId, getByText} = render() - expect(getByText('Hello World')).toBeInTheDocument() - const portalNode = getByTestId('my-portal') + const {unmount} = render() + expect(screen.getByText('Hello World')).toBeInTheDocument() + const portalNode = screen.getByTestId('my-portal') expect(portalNode).toBeInTheDocument() unmount() expect(portalNode).not.toBeInTheDocument() @@ -72,11 +72,11 @@ test('renders options.wrapper around node', () => {
{children}
) - const {container, getByTestId} = render(
, { + const {container} = render(
, { wrapper: WrapperComponent, }) - expect(getByTestId('wrapper')).toBeInTheDocument() + expect(screen.getByTestId('wrapper')).toBeInTheDocument() expect(container.firstChild).toMatchInlineSnapshot(`
new Promise(resolve => setTimeout(resolve, time)) +const sleep = t => new Promise(resolve => setTimeout(resolve, t)) test('unmounts a component', async () => { jest.spyOn(console, 'error').mockImplementation(() => {}) - const {unmount, getByText, container} = render() - fireEvent.click(getByText('Start')) + const {unmount, container} = render() + fireEvent.click(screen.getByText('Start')) unmount() // hey there reader! You don't need to have an assertion like this one // this is just me making sure that the unmount function works. @@ -51,6 +51,7 @@ test('unmounts a component', async () => { // just wait to see if the interval is cleared or not // if it's not, then we'll call setState on an unmounted component // and get an error. + await sleep(5) // eslint-disable-next-line no-console - await wait(() => expect(console.error).not.toHaveBeenCalled()) + expect(console.error).not.toHaveBeenCalled() }) From 3bc13d94c05df06ae4cff5bf98ac1fd0cddb4783 Mon Sep 17 00:00:00 2001 From: Minh Nguyen Date: Fri, 13 Mar 2020 13:25:27 +0000 Subject: [PATCH 135/327] fix: support Node >=10 (#611) --- .travis.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2da1648c..4ce343e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ cache: npm notifications: email: false node_js: - - 10.18 + - 10.0.0 - 12 - node install: diff --git a/package.json b/package.json index 6ec8284a..0232006a 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "dist/index.js", "module": "dist/@testing-library/react.esm.js", "engines": { - "node": ">=10.18" + "node": ">=10" }, "scripts": { "prebuild": "rimraf dist", From 77186febd26b8c4fac7ac8f49566bd82c7e7d516 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 18 Mar 2020 12:46:44 +0100 Subject: [PATCH 136/327] Update package.json (#617) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0232006a..184ef500 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.7", - "@testing-library/dom": "^7.0.2", + "@testing-library/dom": "^7.0.3", "@types/testing-library__react": "^9.1.3" }, "devDependencies": { From eceffb1e1c5583db58b2e4833f7cfc698f871910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20De=20Boey?= Date: Sun, 22 Mar 2020 14:49:28 +0100 Subject: [PATCH 137/327] chore: update dependencies + use kcd-scripts' husky (#619) * Update dependencies + use kcd-scripts' husky * Update package.json --- .huskyrc.js | 1 + package.json | 15 +++++---------- 2 files changed, 6 insertions(+), 10 deletions(-) create mode 100644 .huskyrc.js diff --git a/.huskyrc.js b/.huskyrc.js new file mode 100644 index 00000000..5e45c45d --- /dev/null +++ b/.huskyrc.js @@ -0,0 +1 @@ +module.exports = require('kcd-scripts/husky') diff --git a/package.json b/package.json index 184ef500..3fd88257 100644 --- a/package.json +++ b/package.json @@ -19,11 +19,6 @@ "test:update": "npm test -- --updateSnapshot --coverage", "validate": "kcd-scripts validate" }, - "husky": { - "hooks": { - "pre-commit": "kcd-scripts pre-commit" - } - }, "files": [ "dist", "dont-cleanup-after-each.js", @@ -44,18 +39,18 @@ "author": "Kent C. Dodds (https://kentcdodds.com)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.8.7", - "@testing-library/dom": "^7.0.3", + "@babel/runtime": "^7.9.2", + "@testing-library/dom": "^7.1.0", "@types/testing-library__react": "^9.1.3" }, "devDependencies": { "@reach/router": "^1.3.3", "@testing-library/jest-dom": "^5.1.1", "cross-env": "^7.0.2", - "kcd-scripts": "^5.4.0", + "kcd-scripts": "^5.6.0", "npm-run-all": "^4.1.5", - "react": "^16.9.0", - "react-dom": "^16.9.0", + "react": "^16.13.1", + "react-dom": "^16.13.1", "rimraf": "^3.0.2" }, "peerDependencies": { From afce94fec01d18f654d919e8e091a814afd63da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jastrz=C4=99bski?= Date: Mon, 30 Mar 2020 18:22:34 +0200 Subject: [PATCH 138/327] fix: Bump types dependency (#625) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3fd88257..3075b39a 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "dependencies": { "@babel/runtime": "^7.9.2", "@testing-library/dom": "^7.1.0", - "@types/testing-library__react": "^9.1.3" + "@types/testing-library__react": "^10.0.0" }, "devDependencies": { "@reach/router": "^1.3.3", From 91f0c75d3bd950390783fe0ce390da64cbe9b0b4 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Fri, 3 Apr 2020 21:54:43 +1100 Subject: [PATCH 139/327] docs: Fix typo, seemless -> seamless (#628) There is a small typo in src/act-compat.js. Should read `seamless` rather than `seemless`. --- src/act-compat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/act-compat.js b/src/act-compat.js index d758a97c..e999ecfe 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -82,7 +82,7 @@ function asyncAct(cb) { if (!youHaveBeenWarned) { // if act is supported and async act isn't and they're trying to use async // act, then they need to upgrade from 16.8 to 16.9. - // This is a seemless upgrade, so we'll add a warning + // This is a seamless upgrade, so we'll add a warning console.error( `It looks like you're using a version of react-dom that supports the "act" function, but not an awaitable version of "act" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.`, ) From 59a2de1e689be718f0931656b518509d43f5ac29 Mon Sep 17 00:00:00 2001 From: Boris Serdiuk Date: Mon, 20 Apr 2020 20:00:30 +0200 Subject: [PATCH 140/327] fix: restore this when requiring timers (#644) closes #614 --- src/flush-microtasks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flush-microtasks.js b/src/flush-microtasks.js index 4863b72e..e309fe6a 100644 --- a/src/flush-microtasks.js +++ b/src/flush-microtasks.js @@ -15,7 +15,7 @@ try { const nodeRequire = module && module[requireString] // assuming we're in node, let's try to get node's // version of setImmediate, bypassing fake timers if any. - enqueueTask = nodeRequire('timers').setImmediate + enqueueTask = nodeRequire.call(module, 'timers').setImmediate } catch (_err) { // we're in a browser // we can't use regular timers because they may still be faked From 32c5b9f137b6a6526d5fde71102a758c9a0f5a0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20De=20Boey?= Date: Thu, 23 Apr 2020 20:38:58 +0200 Subject: [PATCH 141/327] chore: Test on Node 14 (#648) --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4ce343e2..c25d0af6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ notifications: node_js: - 10.0.0 - 12 + - 14 - node install: - npm install @@ -23,5 +24,5 @@ branches: jobs: include: - stage: release - node_js: 12 + node_js: 14 script: kcd-scripts travis-release From 1232e1fb12755d526a3d13ffee85f08c607b22ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20De=20Boey?= Date: Thu, 23 Apr 2020 20:58:26 +0200 Subject: [PATCH 142/327] chore: Only release on original repo (#647) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c25d0af6..fbb41880 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,3 +26,4 @@ jobs: - stage: release node_js: 14 script: kcd-scripts travis-release + if: fork = false From d6310a2bbfa2f9622765fb833053094c651c9953 Mon Sep 17 00:00:00 2001 From: Championrunner Date: Fri, 24 Apr 2020 14:58:06 +0530 Subject: [PATCH 143/327] docs(readme): Add install command for yarn (#645) --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index da6120d4..f6d9219a 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,12 @@ should be installed as one of your project's `devDependencies`: ``` npm install --save-dev @testing-library/react ``` +or + +for installation via [yarn](https://classic.yarnpkg.com/en/) +``` +yarn add --dev @testing-library/react +``` This library has `peerDependencies` listings for `react` and `react-dom`. From 644673975a1c2c375518c5ad804e65e651aeedca Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2020 11:39:28 +0200 Subject: [PATCH 144/327] docs: add Ishaan28malik as a contributor (#649) --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 0ef0e46a..2add43b4 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1054,6 +1054,15 @@ "contributions": [ "doc" ] + }, + { + "login": "Ishaan28malik", + "name": "Championrunner", + "avatar_url": "https://avatars3.githubusercontent.com/u/27343592?v=4", + "profile": "https://ghuser.io/Ishaan28malik", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index f6d9219a..13ab8d80 100644 --- a/README.md +++ b/README.md @@ -534,6 +534,7 @@ Thanks goes to these people ([emoji key][emojis]):
Michael Hottman

πŸ€”
Steven Fitzpatrick

πŸ›
Juan Je GarcΓ­a

πŸ“– +
Championrunner

πŸ“– From a75fa350399857cd889ee0b878b08a79c2101206 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 30 Apr 2020 10:08:05 -0600 Subject: [PATCH 145/327] fix: upgrade all dependencies (and fix UMD build) (#653) --- .bundle.main.env | 2 ++ .bundle.pure.env | 3 +++ package.json | 16 ++++++++-------- 3 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 .bundle.main.env create mode 100644 .bundle.pure.env diff --git a/.bundle.main.env b/.bundle.main.env new file mode 100644 index 00000000..669fe7e4 --- /dev/null +++ b/.bundle.main.env @@ -0,0 +1,2 @@ +BUILD_GLOBALS={"react-dom/test-utils":"ReactTestUtils","react":"React","react-dom":"ReactDOM"} + diff --git a/.bundle.pure.env b/.bundle.pure.env new file mode 100644 index 00000000..fed4df2e --- /dev/null +++ b/.bundle.pure.env @@ -0,0 +1,3 @@ +BUILD_FILENAME_SUFFIX=.pure +BUILD_INPUT=src/pure.js + diff --git a/package.json b/package.json index 3075b39a..2e6e668b 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "scripts": { "prebuild": "rimraf dist", "build": "npm-run-all --parallel build:main build:bundle:main build:bundle:pure", - "build:bundle:main": "kcd-scripts build --bundle --no-clean", - "build:bundle:pure": "cross-env BUILD_FILENAME_SUFFIX=.pure BUILD_INPUT=src/pure.js kcd-scripts build --bundle --no-clean", + "build:bundle:main": "dotenv -e .bundle.main.env kcd-scripts build -- --bundle --no-clean", + "build:bundle:pure": "dotenv -e .bundle.main.env -e .bundle.pure.env kcd-scripts build -- --bundle --no-clean", "build:main": "kcd-scripts build --no-clean", "lint": "kcd-scripts lint", "setup": "npm install && npm run validate -s", @@ -39,15 +39,15 @@ "author": "Kent C. Dodds (https://kentcdodds.com)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.9.2", - "@testing-library/dom": "^7.1.0", - "@types/testing-library__react": "^10.0.0" + "@babel/runtime": "^7.9.6", + "@testing-library/dom": "^7.2.2", + "@types/testing-library__react": "^10.0.1" }, "devDependencies": { "@reach/router": "^1.3.3", - "@testing-library/jest-dom": "^5.1.1", - "cross-env": "^7.0.2", - "kcd-scripts": "^5.6.0", + "@testing-library/jest-dom": "^5.5.0", + "dotenv-cli": "^3.1.0", + "kcd-scripts": "^5.11.1", "npm-run-all": "^4.1.5", "react": "^16.13.1", "react-dom": "^16.13.1", From 0afcbea3c3d1ddce218a36d963d39fa83f9a7cf6 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 7 May 2020 15:22:30 -0600 Subject: [PATCH 146/327] chore: update issue templates --- .github/ISSUE_TEMPLATE.md | 17 ++++++++++++++--- .github/ISSUE_TEMPLATE/Bug_Report.md | 17 ++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index e228ee1f..abcfc35e 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -45,9 +45,20 @@ tutorial to learn how: http://kcd.im/pull-request --> - `@testing-library/react` version: -- `react` version: -- `node` version: -- `npm` (or `yarn`) version: +- Testing Framework and version: + +- DOM Environment: + + + Relevant code or config diff --git a/.github/ISSUE_TEMPLATE/Bug_Report.md b/.github/ISSUE_TEMPLATE/Bug_Report.md index ba5ada35..6e22b369 100644 --- a/.github/ISSUE_TEMPLATE/Bug_Report.md +++ b/.github/ISSUE_TEMPLATE/Bug_Report.md @@ -23,9 +23,20 @@ tutorial to learn how: http://kcd.im/pull-request --> - `@testing-library/react` version: -- `react` version: -- `node` version: -- `npm` (or `yarn`) version: +- Testing Framework and version: + +- DOM Environment: + + + ### Relevant code or config: From 7b7460a61a0067f190947216c496ab7b5e30301f Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Mon, 1 Jun 2020 16:43:47 -0600 Subject: [PATCH 147/327] chore: update all the things Fun note that it looks like more recent versions of jsdom now support document.createRange --- package.json | 8 ++++---- src/pure.js | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 2e6e668b..5d8cd91b 100644 --- a/package.json +++ b/package.json @@ -39,15 +39,15 @@ "author": "Kent C. Dodds (https://kentcdodds.com)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.9.6", - "@testing-library/dom": "^7.2.2", + "@babel/runtime": "^7.10.2", + "@testing-library/dom": "^7.8.0", "@types/testing-library__react": "^10.0.1" }, "devDependencies": { "@reach/router": "^1.3.3", - "@testing-library/jest-dom": "^5.5.0", + "@testing-library/jest-dom": "^5.9.0", "dotenv-cli": "^3.1.0", - "kcd-scripts": "^5.11.1", + "kcd-scripts": "^6.2.0", "npm-run-all": "^4.1.5", "react": "^16.13.1", "react-dom": "^16.13.1", diff --git a/src/pure.js b/src/pure.js index 9060c941..0e693926 100644 --- a/src/pure.js +++ b/src/pure.js @@ -74,16 +74,16 @@ function render( // folks can use all the same utilities we return in the first place that are bound to the container }, asFragment: () => { - /* istanbul ignore if (jsdom limitation) */ + /* istanbul ignore else (old jsdom limitation) */ if (typeof document.createRange === 'function') { return document .createRange() .createContextualFragment(container.innerHTML) + } else { + const template = document.createElement('template') + template.innerHTML = container.innerHTML + return template.content } - - const template = document.createElement('template') - template.innerHTML = container.innerHTML - return template.content }, ...getQueriesForElement(baseElement, queries), } From 6147830b0ea61341d02f520d2a26b817996e3a4a Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Mon, 1 Jun 2020 17:33:40 -0600 Subject: [PATCH 148/327] fix(fireEvent): automatically configure `fireEvent` to be wrapped in act (#685) --- .travis.yml | 3 ++- src/fire-event.js | 44 ++++++++++++++++++++++++++++++++ src/pure.js | 65 +++++++---------------------------------------- 3 files changed, 55 insertions(+), 57 deletions(-) create mode 100644 src/fire-event.js diff --git a/.travis.yml b/.travis.yml index fbb41880..ac04499f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,8 @@ cache: npm notifications: email: false node_js: - - 10.0.0 + # technically we support 10.0.0, but some of our tooling doesn't + - 10.14.2 - 12 - 14 - node diff --git a/src/fire-event.js b/src/fire-event.js new file mode 100644 index 00000000..071aff8a --- /dev/null +++ b/src/fire-event.js @@ -0,0 +1,44 @@ +import {fireEvent as dtlFireEvent} from '@testing-library/dom' + +// react-testing-library's version of fireEvent will call +// dom-testing-library's version of fireEvent. The reason +// we make this distinction however is because we have +// a few extra events that work a bit differently +const fireEvent = (...args) => dtlFireEvent(...args) + +Object.keys(dtlFireEvent).forEach(key => { + fireEvent[key] = (...args) => dtlFireEvent[key](...args) +}) + +// React event system tracks native mouseOver/mouseOut events for +// running onMouseEnter/onMouseLeave handlers +// @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/EnterLeaveEventPlugin.js#L24-L31 +const mouseEnter = fireEvent.mouseEnter +const mouseLeave = fireEvent.mouseLeave +fireEvent.mouseEnter = (...args) => { + mouseEnter(...args) + return fireEvent.mouseOver(...args) +} +fireEvent.mouseLeave = (...args) => { + mouseLeave(...args) + return fireEvent.mouseOut(...args) +} + +const select = fireEvent.select +fireEvent.select = (node, init) => { + select(node, init) + // React tracks this event only on focused inputs + node.focus() + + // React creates this event when one of the following native events happens + // - contextMenu + // - mouseUp + // - dragEnd + // - keyUp + // - keyDown + // so we can use any here + // @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/SelectEventPlugin.js#L203-L224 + fireEvent.keyUp(node, init) +} + +export {fireEvent} diff --git a/src/pure.js b/src/pure.js index 0e693926..fe7e6cf9 100644 --- a/src/pure.js +++ b/src/pure.js @@ -3,10 +3,10 @@ import ReactDOM from 'react-dom' import { getQueriesForElement, prettyDOM, - fireEvent as dtlFireEvent, configure as configureDTL, } from '@testing-library/dom' import act, {asyncAct} from './act-compat' +import {fireEvent} from './fire-event' import flush from './flush-microtasks' configureDTL({ @@ -17,6 +17,13 @@ configureDTL({ }) return result }, + eventWrapper: cb => { + let result + act(() => { + result = cb() + }) + return result + }, }) const mountedContainers = new Set() @@ -104,63 +111,9 @@ function cleanupAtContainer(container) { mountedContainers.delete(container) } -// react-testing-library's version of fireEvent will call -// dom-testing-library's version of fireEvent wrapped inside -// an "act" call so that after all event callbacks have been -// called, the resulting useEffect callbacks will also be -// called. -function fireEvent(...args) { - let returnValue - act(() => { - returnValue = dtlFireEvent(...args) - }) - return returnValue -} - -Object.keys(dtlFireEvent).forEach(key => { - fireEvent[key] = (...args) => { - let returnValue - act(() => { - returnValue = dtlFireEvent[key](...args) - }) - return returnValue - } -}) - -// React event system tracks native mouseOver/mouseOut events for -// running onMouseEnter/onMouseLeave handlers -// @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/EnterLeaveEventPlugin.js#L24-L31 -const mouseEnter = fireEvent.mouseEnter -const mouseLeave = fireEvent.mouseLeave -fireEvent.mouseEnter = (...args) => { - mouseEnter(...args) - return fireEvent.mouseOver(...args) -} -fireEvent.mouseLeave = (...args) => { - mouseLeave(...args) - return fireEvent.mouseOut(...args) -} - -const select = fireEvent.select -fireEvent.select = (node, init) => { - select(node, init) - // React tracks this event only on focused inputs - node.focus() - - // React creates this event when one of the following native events happens - // - contextMenu - // - mouseUp - // - dragEnd - // - keyUp - // - keyDown - // so we can use any here - // @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/SelectEventPlugin.js#L203-L224 - fireEvent.keyUp(node, init) -} - // just re-export everything from dom-testing-library export * from '@testing-library/dom' -export {render, cleanup, fireEvent, act} +export {render, cleanup, act, fireEvent} // NOTE: we're not going to export asyncAct because that's our own compatibility // thing for people using react-dom@16.8.0. Anyone else doesn't need it and From c3008bec842373de24c56bc871b1d9010894aa2f Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Tue, 2 Jun 2020 16:10:52 -0600 Subject: [PATCH 149/327] fix: force update version of @testing-library/dom (#687) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5d8cd91b..cb9f9324 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.2", - "@testing-library/dom": "^7.8.0", + "@testing-library/dom": "^7.9.0", "@types/testing-library__react": "^10.0.1" }, "devDependencies": { From 16f2f564bcd00df158a4922c9bc2893d7e49d14d Mon Sep 17 00:00:00 2001 From: Sam Tsai Date: Wed, 3 Jun 2020 20:46:19 -0400 Subject: [PATCH 150/327] feat(TS): move typings from DefinitelyTyped into this repo (#690) * Bring typings from DefinitelyTyped into this repo Closes #688 * Add missing types and configs Add `pure.d.ts` that re-exports everything from `index.d.ts` Turn off `whitespace` rule Co-authored-by: Sam Tsai --- index.d.ts | 1 - package.json | 10 +++++-- types/index.d.ts | 59 ++++++++++++++++++++++++++++++++++++++ types/pure.d.ts | 1 + types/test.tsx | 70 +++++++++++++++++++++++++++++++++++++++++++++ types/tsconfig.json | 19 ++++++++++++ types/tslint.json | 9 ++++++ 7 files changed, 165 insertions(+), 4 deletions(-) delete mode 100644 index.d.ts create mode 100644 types/index.d.ts create mode 100644 types/pure.d.ts create mode 100644 types/test.tsx create mode 100644 types/tsconfig.json create mode 100644 types/tslint.json diff --git a/index.d.ts b/index.d.ts deleted file mode 100644 index e50a1e7c..00000000 --- a/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from 'testing-library__react' diff --git a/package.json b/package.json index cb9f9324..9bf9b277 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.0.0-semantically-released", "description": "Simple and complete React DOM testing utilities that encourage good testing practices.", "main": "dist/index.js", + "types": "types/index.d.ts", "module": "dist/@testing-library/react.esm.js", "engines": { "node": ">=10" @@ -17,12 +18,14 @@ "setup": "npm install && npm run validate -s", "test": "kcd-scripts test", "test:update": "npm test -- --updateSnapshot --coverage", + "typecheck": "dtslint ./types/", "validate": "kcd-scripts validate" }, "files": [ "dist", "dont-cleanup-after-each.js", - "pure.js" + "pure.js", + "types" ], "keywords": [ "testing", @@ -40,13 +43,14 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.2", - "@testing-library/dom": "^7.9.0", - "@types/testing-library__react": "^10.0.1" + "@testing-library/dom": "^7.9.0" }, "devDependencies": { "@reach/router": "^1.3.3", "@testing-library/jest-dom": "^5.9.0", + "@types/react-dom": "^16.9.8", "dotenv-cli": "^3.1.0", + "dtslint": "3.6.9", "kcd-scripts": "^6.2.0", "npm-run-all": "^4.1.5", "react": "^16.13.1", diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 00000000..09824704 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,59 @@ +// TypeScript Version: 3.8 + +import {OptionsReceived as PrettyFormatOptions} from 'pretty-format' +import {queries, Queries, BoundFunction} from '@testing-library/dom' +import {act as reactAct} from 'react-dom/test-utils' + +export * from '@testing-library/dom' + +export type RenderResult = { + container: HTMLElement + baseElement: HTMLElement + debug: ( + baseElement?: + | HTMLElement + | DocumentFragment + | Array, + maxLength?: number, + options?: PrettyFormatOptions, + ) => void + rerender: (ui: React.ReactElement) => void + unmount: () => boolean + asFragment: () => DocumentFragment +} & {[P in keyof Q]: BoundFunction} + +export interface RenderOptions { + container?: HTMLElement + baseElement?: HTMLElement + hydrate?: boolean + queries?: Q + wrapper?: React.ComponentType +} + +type Omit = Pick> + +/** + * Render into a container which is appended to document.body. It should be used with cleanup. + */ +export function render( + ui: React.ReactElement, + options?: Omit, +): RenderResult +export function render( + ui: React.ReactElement, + options: RenderOptions, +): RenderResult + +/** + * Unmounts React trees that were mounted with render. + */ +export function cleanup(): Promise + +/** + * Simply calls ReactDOMTestUtils.act(cb) + * If that's not available (older version of react) then it + * simply calls the given callback immediately + */ +export const act: typeof reactAct extends undefined + ? (callback: () => void) => void + : typeof reactAct diff --git a/types/pure.d.ts b/types/pure.d.ts new file mode 100644 index 00000000..7b527195 --- /dev/null +++ b/types/pure.d.ts @@ -0,0 +1 @@ +export * from './' diff --git a/types/test.tsx b/types/test.tsx new file mode 100644 index 00000000..c273feb0 --- /dev/null +++ b/types/test.tsx @@ -0,0 +1,70 @@ +import * as React from 'react' +import {render, fireEvent, screen, waitFor} from '@testing-library/react' +import * as pure from '@testing-library/react/pure' + +async function testRender() { + const page = render(
) + + // single queries + page.getByText('foo') + page.queryByText('foo') + await page.findByText('foo') + + // multiple queries + page.getAllByText('bar') + page.queryAllByText('bar') + await page.findAllByText('bar') + + // helpers + const {container, rerender, debug} = page +} + +async function testPureRender() { + const page = pure.render(
) + + // single queries + page.getByText('foo') + page.queryByText('foo') + await page.findByText('foo') + + // multiple queries + page.getAllByText('bar') + page.queryAllByText('bar') + await page.findAllByText('bar') + + // helpers + const {container, rerender, debug} = page +} + +async function testRenderOptions() { + const container = document.createElement('div') + const options = {container} + render(
, options) +} + +async function testFireEvent() { + const {container} = render(
, + ) + const button = container.firstChild.firstChild + + fireEvent.focus(button) + + expect(handleBlur).toHaveBeenCalledTimes(0) + expect(handleBubbledBlur).toHaveBeenCalledTimes(0) + expect(handleFocus).toHaveBeenCalledTimes(1) + expect(handleBubbledFocus).toHaveBeenCalledTimes(1) + + fireEvent.blur(button) + + expect(handleBlur).toHaveBeenCalledTimes(1) + expect(handleBubbledBlur).toHaveBeenCalledTimes(1) + expect(handleFocus).toHaveBeenCalledTimes(1) + expect(handleBubbledFocus).toHaveBeenCalledTimes(1) +}) From 9aac1570d8bccfdf4584b22196cc23a479b47aff Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 5 Aug 2020 04:02:17 +0200 Subject: [PATCH 187/327] fix(fireEvent): Make sure react dispatches focus/blur events (#758) * test: Run CI with experimental React * stable -> latest * fix(fireEvent): Make sure react dispatches focus/blur events * Remove todo --- .travis.yml | 11 ++++++----- src/fire-event.js | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index c2f47b7a..eae48ee7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,14 +9,14 @@ node_js: - 14 - node env: - - REACT_NEXT=false - - REACT_NEXT=true + - REACT_DIST=latest + - REACT_DIST=next + - REACT_DIST=experimental install: - npm install # as requested by the React team :) # https://reactjs.org/blog/2019/10/22/react-release-channels.html#using-the-next-channel-for-integration-testing - - if [ "$REACT_NEXT" = true ]; then npm install react@next - react-dom@next; fi + - npm install react@$REACT_DIST react-dom@$REACT_DIST script: - npm run validate - npx codecov@3 @@ -27,7 +27,8 @@ branches: jobs: allow_failures: - - env: REACT_NEXT=true + - REACT_DIST=next + - REACT_DIST=experimental include: - stage: release node_js: 14 diff --git a/src/fire-event.js b/src/fire-event.js index 071aff8a..b4e60928 100644 --- a/src/fire-event.js +++ b/src/fire-event.js @@ -41,4 +41,18 @@ fireEvent.select = (node, init) => { fireEvent.keyUp(node, init) } +// React event system tracks native focusout/focusin events for +// running blur/focus handlers +// @link https://github.com/facebook/react/pull/19186 +const blur = fireEvent.blur +const focus = fireEvent.focus +fireEvent.blur = (...args) => { + fireEvent.focusOut(...args) + return blur(...args) +} +fireEvent.focus = (...args) => { + fireEvent.focusIn(...args) + return focus(...args) +} + export {fireEvent} From 276eb656feffed6e3da14b34965df889ed31b0cd Mon Sep 17 00:00:00 2001 From: Ryan Bigg Date: Fri, 21 Aug 2020 16:45:14 +1000 Subject: [PATCH 188/327] fix: Bump @testing-library/dom to 7.22.3 (#766) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 652c7d04..acb3f0ac 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.3", - "@testing-library/dom": "^7.17.1" + "@testing-library/dom": "^7.22.3" }, "devDependencies": { "@testing-library/jest-dom": "^5.10.1", From 5a10621fd081f44074a3a77a2ebc9e246c1c4db2 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 21 Aug 2020 09:08:56 +0200 Subject: [PATCH 189/327] docs: add radar as a contributor (#767) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 0a5aea46..2e621d62 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1140,6 +1140,15 @@ "contributions": [ "code" ] + }, + { + "login": "radar", + "name": "Ryan Bigg", + "avatar_url": "https://avatars3.githubusercontent.com/u/2687?v=4", + "profile": "http://ryanbigg.com", + "contributions": [ + "maintenance" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index f33fde6c..30f00cd2 100644 --- a/README.md +++ b/README.md @@ -590,6 +590,7 @@ Thanks goes to these people ([emoji key][emojis]):
Braden Lee

πŸ“–
Kamran Ayub

πŸ’» ⚠️
Matan Borenkraout

πŸ’» +
Ryan Bigg

🚧 From 693228ce10f23e2b695730ea88dbdaa35506e00e Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Sun, 30 Aug 2020 05:23:18 +0200 Subject: [PATCH 190/327] feat: use act to flush instead of custom implementation (#768) BREAKING CHANGE: cleanup is now synchronous and wraps the unmounting process in `act`. --- src/__tests__/cleanup.js | 93 +++++++++++++++++++++++++++++++++++++--- src/flush-microtasks.js | 67 ----------------------------- src/pure.js | 10 ++--- 3 files changed, 91 insertions(+), 79 deletions(-) delete mode 100644 src/flush-microtasks.js diff --git a/src/__tests__/cleanup.js b/src/__tests__/cleanup.js index c0f1676d..4b67814a 100644 --- a/src/__tests__/cleanup.js +++ b/src/__tests__/cleanup.js @@ -1,7 +1,7 @@ import React from 'react' import {render, cleanup} from '../' -test('cleans up the document', async () => { +test('cleans up the document', () => { const spy = jest.fn() const divId = 'my-div' @@ -17,17 +17,17 @@ test('cleans up the document', async () => { } render() - await cleanup() + cleanup() expect(document.body).toBeEmptyDOMElement() expect(spy).toHaveBeenCalledTimes(1) }) -test('cleanup does not error when an element is not a child', async () => { +test('cleanup does not error when an element is not a child', () => { render(
, {container: document.createElement('div')}) - await cleanup() + cleanup() }) -test('cleanup runs effect cleanup functions', async () => { +test('cleanup runs effect cleanup functions', () => { const spy = jest.fn() const Test = () => { @@ -37,6 +37,87 @@ test('cleanup runs effect cleanup functions', async () => { } render() - await cleanup() + cleanup() expect(spy).toHaveBeenCalledTimes(1) }) + +describe('fake timers and missing act warnings', () => { + beforeEach(() => { + jest.resetAllMocks() + jest.spyOn(console, 'error').mockImplementation(() => { + // assert messages explicitly + }) + jest.useFakeTimers() + }) + + afterEach(() => { + jest.useRealTimers() + }) + + test('cleanup does not flush immediates', () => { + const microTaskSpy = jest.fn() + function Test() { + const counter = 1 + const [, setDeferredCounter] = React.useState(null) + React.useEffect(() => { + let cancelled = false + setImmediate(() => { + microTaskSpy() + if (!cancelled) { + setDeferredCounter(counter) + } + }) + + return () => { + cancelled = true + } + }, [counter]) + + return null + } + render() + + cleanup() + + expect(microTaskSpy).toHaveBeenCalledTimes(0) + // console.error is mocked + // eslint-disable-next-line no-console + expect(console.error).toHaveBeenCalledTimes(0) + }) + + test('cleanup does not swallow missing act warnings', () => { + const deferredStateUpdateSpy = jest.fn() + function Test() { + const counter = 1 + const [, setDeferredCounter] = React.useState(null) + React.useEffect(() => { + let cancelled = false + setImmediate(() => { + deferredStateUpdateSpy() + if (!cancelled) { + setDeferredCounter(counter) + } + }) + + return () => { + cancelled = true + } + }, [counter]) + + return null + } + render() + + jest.runAllImmediates() + cleanup() + + expect(deferredStateUpdateSpy).toHaveBeenCalledTimes(1) + // console.error is mocked + // eslint-disable-next-line no-console + expect(console.error).toHaveBeenCalledTimes(1) + // eslint-disable-next-line no-console + expect(console.error.mock.calls[0][0]).toMatch( + 'a test was not wrapped in act(...)', + ) + }) +}) diff --git a/src/flush-microtasks.js b/src/flush-microtasks.js deleted file mode 100644 index e1d8fe6f..00000000 --- a/src/flush-microtasks.js +++ /dev/null @@ -1,67 +0,0 @@ -/* istanbul ignore file */ -// the part of this file that we need tested is definitely being run -// and the part that is not cannot easily have useful tests written -// anyway. So we're just going to ignore coverage for this file -/** - * copied and modified from React's enqueueTask.js - */ - -function getIsUsingFakeTimers() { - return ( - typeof jest !== 'undefined' && - typeof setTimeout !== 'undefined' && - (setTimeout.hasOwnProperty('_isMockFunction') || - setTimeout.hasOwnProperty('clock')) - ) -} - -let didWarnAboutMessageChannel = false -let enqueueTask - -try { - // read require off the module object to get around the bundlers. - // we don't want them to detect a require and bundle a Node polyfill. - const requireString = `require${Math.random()}`.slice(0, 7) - const nodeRequire = module && module[requireString] - // assuming we're in node, let's try to get node's - // version of setImmediate, bypassing fake timers if any. - enqueueTask = nodeRequire.call(module, 'timers').setImmediate -} catch (_err) { - // we're in a browser - // we can't use regular timers because they may still be faked - // so we try MessageChannel+postMessage instead - enqueueTask = callback => { - const supportsMessageChannel = typeof MessageChannel === 'function' - if (supportsMessageChannel) { - const channel = new MessageChannel() - channel.port1.onmessage = callback - channel.port2.postMessage(undefined) - } else if (didWarnAboutMessageChannel === false) { - didWarnAboutMessageChannel = true - - // eslint-disable-next-line no-console - console.error( - 'This browser does not have a MessageChannel implementation, ' + - 'so enqueuing tasks via await act(async () => ...) will fail. ' + - 'Please file an issue at https://github.com/facebook/react/issues ' + - 'if you encounter this warning.', - ) - } - } -} - -export default function flushMicroTasks() { - return { - then(resolve) { - if (getIsUsingFakeTimers()) { - // without this, a test using fake timers would never get microtasks - // actually flushed. I spent several days on this... Really hard to - // reproduce the problem, so there's no test for it. But it works! - jest.advanceTimersByTime(0) - resolve() - } else { - enqueueTask(resolve) - } - }, - } -} diff --git a/src/pure.js b/src/pure.js index f2f3438f..8a062038 100644 --- a/src/pure.js +++ b/src/pure.js @@ -7,7 +7,6 @@ import { } from '@testing-library/dom' import act, {asyncAct} from './act-compat' import {fireEvent} from './fire-event' -import flush from './flush-microtasks' configureDTL({ asyncWrapper: async cb => { @@ -100,17 +99,16 @@ function render( } } -async function cleanup() { +function cleanup() { mountedContainers.forEach(cleanupAtContainer) - // flush microtask queue after unmounting in case - // unmount sequence generates new microtasks - await flush() } // maybe one day we'll expose this (perhaps even as a utility returned by render). // but let's wait until someone asks for it. function cleanupAtContainer(container) { - ReactDOM.unmountComponentAtNode(container) + act(() => { + ReactDOM.unmountComponentAtNode(container) + }) if (container.parentNode === document.body) { document.body.removeChild(container) } From 534ea33d514297ed368530f39e210675e1553979 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Wed, 2 Sep 2020 11:41:32 -0600 Subject: [PATCH 191/327] chore: update all deps --- package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index acb3f0ac..61bfefef 100644 --- a/package.json +++ b/package.json @@ -43,20 +43,20 @@ "author": "Kent C. Dodds (https://kentcdodds.com)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.10.3", - "@testing-library/dom": "^7.22.3" + "@babel/runtime": "^7.11.2", + "@testing-library/dom": "^7.23.0" }, "devDependencies": { - "@testing-library/jest-dom": "^5.10.1", + "@testing-library/jest-dom": "^5.11.4", "@types/react-dom": "^16.9.8", - "dotenv-cli": "^3.1.0", - "dtslint": "3.6.12", - "kcd-scripts": "^6.2.3", + "dotenv-cli": "^3.2.0", + "dtslint": "4.0.0", + "kcd-scripts": "^6.3.0", "npm-run-all": "^4.1.5", "react": "^16.13.1", "react-dom": "^16.13.1", "rimraf": "^3.0.2", - "typescript": "^3.9.5" + "typescript": "^4.0.2" }, "peerDependencies": { "react": "*", From 88d42769f1d13a43e2e073677bf9fcff844b2d49 Mon Sep 17 00:00:00 2001 From: Anton Halim Date: Wed, 2 Sep 2020 15:02:24 -0700 Subject: [PATCH 192/327] Improve some documentation (#770) --- README.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 30f00cd2..388ec957 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ practices.

- [The problem](#the-problem) -- [This solution](#this-solution) +- [The solution](#the-solution) - [Installation](#installation) - [Suppressing unnecessary warnings on React DOM 16.8](#suppressing-unnecessary-warnings-on-react-dom-168) - [Examples](#examples) @@ -83,7 +83,7 @@ maintainable in the long run so refactors of your components (changes to implementation but not functionality) don't break your tests and slow you and your team down. -## This solution +## The solution The `React Testing Library` is a very lightweight solution for testing React components. It provides light utility functions on top of `react-dom` and @@ -104,7 +104,7 @@ npm install --save-dev @testing-library/react or -for installation via [yarn](https://classic.yarnpkg.com/en/) +for installation via [yarn][yarn] ``` yarn add --dev @testing-library/react @@ -132,7 +132,7 @@ the following snippet to your test configuration ```js // this is just a little hack to silence a warning that we'll get until we -// upgrade to 16.9: https://github.com/facebook/react/pull/14853 +// upgrade to 16.9. See also: https://github.com/facebook/react/pull/14853 const originalError = console.error beforeAll(() => { console.error = (...args) => { @@ -156,8 +156,8 @@ afterAll(() => { // hidden-message.js import React from 'react' -// NOTE: React Testing Library works with React Hooks _and_ classes just as well -// and your tests will be the same however you write your components. +// NOTE: React Testing Library works well with React Hooks and classes. +// Your tests will be the same regardless of how you write your components. function HiddenMessage({children}) { const [showMessage, setShowMessage] = React.useState(false) return ( @@ -372,7 +372,7 @@ You can also find React Testing Library examples at If you are interested in testing a custom hook, check out [React Hooks Testing Library][react-hooks-testing-library]. -> NOTE it is not recommended to test single-use custom hooks in isolation from +> NOTE: it is not recommended to test single-use custom hooks in isolation from > the components where it's being used. It's better to test the component that's > using the hook rather than the hook itself. The `React Hooks Testing Library` > is intended to be used for reusable hooks/libraries. @@ -383,7 +383,7 @@ Library][react-hooks-testing-library]. > confidence they can give you.][guiding-principle] We try to only expose methods and utilities that encourage you to write tests -that closely resemble how your react components are used. +that closely resemble how your React components are used. Utilities are included in this project based on the following guiding principles: @@ -397,8 +397,8 @@ principles: `react-dom`. 3. Utility implementations and APIs should be simple and flexible. -At the end of the day, what we want is for this library to be pretty -light-weight, simple, and understandable. +Most importantly, we want React Testing Library to be pretty +light-weight, simple, and easy to understand. ## Docs @@ -407,8 +407,8 @@ light-weight, simple, and understandable. ## Issues -_Looking to contribute? Look for the [Good First Issue][good-first-issue] -label._ +Looking to contribute? Look for the [Good First Issue][good-first-issue] +label. ### πŸ› Bugs @@ -608,6 +608,7 @@ Contributions of any kind welcome! [npm]: https://www.npmjs.com/ +[yarn]: https://classic.yarnpkg.com [node]: https://nodejs.org [build-badge]: https://img.shields.io/travis/testing-library/react-testing-library.svg?style=flat-square [build]: https://travis-ci.org/testing-library/react-testing-library From 491bedc294f7bfc56127ecfc396430aa0d3debb1 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 2 Sep 2020 18:28:18 -0400 Subject: [PATCH 193/327] docs: add antonhalim as a contributor (#775) * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 +++ 2 files changed, 12 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 2e621d62..f826d705 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1149,6 +1149,15 @@ "contributions": [ "maintenance" ] + }, + { + "login": "antonhalim", + "name": "Anton Halim", + "avatar_url": "https://avatars1.githubusercontent.com/u/10498035?v=4", + "profile": "https://antonhalim.com", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 388ec957..e53be16d 100644 --- a/README.md +++ b/README.md @@ -592,6 +592,9 @@ Thanks goes to these people ([emoji key][emojis]):
Matan Borenkraout

πŸ’»
Ryan Bigg

🚧 + +
Anton Halim

πŸ“– + From 9191890c882314c0048206e23a1fff40561b7ee4 Mon Sep 17 00:00:00 2001 From: Artem Malko Date: Thu, 3 Sep 2020 13:29:06 +0700 Subject: [PATCH 194/327] fix: Update typings for cleanup (#776) --- types/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/index.d.ts b/types/index.d.ts index 09824704..50702ecc 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -47,7 +47,7 @@ export function render( /** * Unmounts React trees that were mounted with render. */ -export function cleanup(): Promise +export function cleanup(): void /** * Simply calls ReactDOMTestUtils.act(cb) From 20acad35b1a9a3f614fa183b82a5bd606336889f Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2020 08:51:36 +0200 Subject: [PATCH 195/327] docs: add artem-malko as a contributor (#777) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index f826d705..2eceb2e6 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1158,6 +1158,15 @@ "contributions": [ "doc" ] + }, + { + "login": "artem-malko", + "name": "Artem Malko", + "avatar_url": "https://avatars0.githubusercontent.com/u/1823689?v=4", + "profile": "http://artmalko.ru", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index e53be16d..b3a2f588 100644 --- a/README.md +++ b/README.md @@ -594,6 +594,7 @@ Thanks goes to these people ([emoji key][emojis]):
Anton Halim

πŸ“– +
Artem Malko

πŸ’» From 220d8d4fd1f29c64e5094a6efa46fdee7b8105de Mon Sep 17 00:00:00 2001 From: Gerrit Alex Date: Thu, 3 Sep 2020 19:43:27 +0200 Subject: [PATCH 196/327] fix(cleanup): remove unnecessary async/await (#778) --- src/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/index.js b/src/index.js index b69f6555..4f92e02b 100644 --- a/src/index.js +++ b/src/index.js @@ -9,15 +9,15 @@ if (!process.env.RTL_SKIP_AUTO_CLEANUP) { // ignore teardown() in code coverage because Jest does not support it /* istanbul ignore else */ if (typeof afterEach === 'function') { - afterEach(async () => { - await cleanup() + afterEach(() => { + cleanup() }) } else if (typeof teardown === 'function') { // Block is guarded by `typeof` check. // eslint does not support `typeof` guards. // eslint-disable-next-line no-undef - teardown(async () => { - await cleanup() + teardown(() => { + cleanup() }) } } From b32fea015c87c018277d52a88ed9f161455f145c Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2020 20:03:59 +0200 Subject: [PATCH 197/327] docs: add ljosberinn as a contributor (#779) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 2eceb2e6..de7f33aa 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1167,6 +1167,15 @@ "contributions": [ "code" ] + }, + { + "login": "ljosberinn", + "name": "Gerrit Alex", + "avatar_url": "https://avatars1.githubusercontent.com/u/29307652?v=4", + "profile": "http://gerritalex.de", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index b3a2f588..ff6fe55f 100644 --- a/README.md +++ b/README.md @@ -595,6 +595,7 @@ Thanks goes to these people ([emoji key][emojis]):
Anton Halim

πŸ“–
Artem Malko

πŸ’» +
Gerrit Alex

πŸ’» From 865c4fd6f96145f717a4b517d247cd68f034cfce Mon Sep 17 00:00:00 2001 From: tapico-weyert <70971917+tapico-weyert@users.noreply.github.com> Date: Wed, 9 Sep 2020 00:24:17 +0100 Subject: [PATCH 198/327] docs: update the cheat sheet pdf + source file to fix typo (#782) fixes #759 --- other/cheat-sheet.pdf | Bin 46907 -> 48836 bytes other/design files/cheat-sheet.afpub | Bin 158235 -> 137815 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/other/cheat-sheet.pdf b/other/cheat-sheet.pdf index 8f1d1e60f63aeadc0fef01c599cb974ba3bfc0e4..d8288e0316d570ce25261e7f1fb019239a543dfa 100644 GIT binary patch delta 14384 zcmb7r1z1&E^EV+~3P>XdX#`FO-KCV2q!J!NDQN`Rbe9|u>5@=FIz(wi1*8;E5D5Xn z0;LS#e-4V*xc7O#k4Jd+o;_>U#BXNJ+I!jZo}_z+oDBK=9A29}}z`z4Qp&$rIUrvtN!_ysW?M&_a z+$d?;CPaZYEY!Dx+K@R#^q4~ZoRMu0X~5pNC{-1eTtyQ!Hl(QN>cBr>Y%a3y zT}GAXbw_FaLijXO!Q}9l5H>a=CtA$w%rOe67>(_NLTrd*VpO$qHGHuHaF1%M8dD(F7Nwff6yfk&E9y6KHz?DXS ztg%~W`LL=-E!HL$QcyAI*`D zGhQEdgespgpIwcON?8py_PU4)CgFI>F@5CfloM^5Z>Pb=A->WXHsoS|hzCQdsr9PNy<|3~OV*f@g)Q{mMSaKBhLv1J$c3=sV01sC@ zC@#=nU`GFVj)osRh7oXbg3>_S+T$V!&%4LYzYi4<@E20BBldhsmzaCka+J$ zZ=Ge&FL(07j@|P{Vf*^2u~_U;u;CWVi)|T9+Xos9<>&1$&~M9Zfvs|symks!dTx}K zZhBTkOyM=1oqW6047TBFHH8=piO4Pi@RmBWbVe_$Z)|jYJQL;iUBEa0!6~KV`~tBm zo!co-5O>yTgS3{4i_c@1UM=dCKJ1GOQChOIKYBE6DCL@>9~pa(>f9sI#1#&zC&oA< zk;<~PlUP`K%E%C<_JHBj@%jhmlh384q|7xf8DGE8KRI2XXJc}k`pXw6Ehk%8zI9xI zVJQ-$6Gs%6Fgwo#kqie~9G+YdS3Eolhe)gUgWKmAXA6wLZ`Lp03&0*78$(-pocd5~ zK8+I2_Vy;;G^_&hJmF3}9LO7mwnP}or{5sQa?623dcYW;s^a3sjvg2l6B~67!VV+&%X4~y@GjyG%&ZK>9$?rjY^WD^cq$m zz1Q7s3-T0|DW#LSzEkVe46DDY{t#iBF$VXWsef^U8)JXLYVJF<7v8NKOD%YMC5dRbPUi=8L>#jAwsZveKdXmz3W zHtCg@atP>&{MT!5`gS5_2JZ#%zC5~O zT^wgbmCL_&*T1H={4`8#YN`zx&LdL63y5^zFu!RpD>}yB3G*w}r zwferYyj`X45XS^!7?-=xJJobsb}F0X5076r#C5z>d?;=mihbVr+{5fKW7R6rwZku? zXx7LiMNUaXQ@PoEyiU?aV)v|Hwuy{}&4S!o)rvVM}XsKqY6%igRz#9shphUAnle^Qd9~ zNzenP^_jy=$zJ(6d6AX9p0$bU#2mH1gj30wqLA8P~|YIeK0mzufXLCFdG3k%rF6CBLdZ;lLZO-CMR4 zFdCDY&6!JE!8>YeU+bjhutkO!q1@T|g9edEg*a)=r8~T<6sbEGh^317 z`l>htICZyqSJVoOy~h^@kJ)BD`t1bpx^;4(S2y_R5p#6sl%g-I#P!iIMY&P>I(d_8;6wIjkMa0FGn?fJldsltoBPap0tpaR zrSyb#2-Gl5Ka-v``DzV2E@QFzndgz9U_){YWl0)0;OMzxUlDYr^H7tad)ViZdILhcdVYCec#b)nanBV zL26PN69CER%D%c((oaVumaS+$`0_Ns65jt=z>}TNgEY@v)mDZ~G2dJ{+op2QMKqAX zV;9L00R3v{mK6cSUXjo;QfegPn@`l&x0-u&O}8-$m!#i=B3T^u1H3uUbfo~XE}X^J z=OeCs9f_8(w7V?O*RA&g{7GvXM`uVzgJjEOoD2=SH0oQminDd++80 zpcuwm!CBTY`R4kXtsT|gktI3ax65s)P?za0r*F-gow@Vg64EVO_l>Bic4b=I5>j_! z$sHOWoj7h?CdGN>q=LM7f(@e=ke3p^*GD@P8;hGO19{7@3_q!MGIihCZg%r0E)&1Y z8YZ7O_E3d=#@$-c_C>Uy_wBXd*`^*A51Q4@3qoXZ4suC~w5#ED$IF89tBy2_gNktJqe*9$qEQ)x>sBpxyC?bq0nMlfjsP329LpP< zmCLYqG9>e6pKn8fkxL4SsmQ?r%x8tRX-Z666MtTDazc7TAIkeX!zv+|eN@^0<8y{W^|HN2(?ss(eguO(&Jx$2e0sRk;=p>{*&*CcDe!-d7q%%5B^ zt4WY5655r;m7gpVDOz-!xD429dag2Ul|Nn+ z5GZqkT)edYWbci9zb~07spsD_DDT!gAh^bjPg$cYM-$nr`Sq8AKABwH9RH|4QsB3F z1w2{l(~|Nr7~!v8Nm0iVeEZcm=arG>thVg!Zt{7DwPBvUj&tjb=Wy=8#G=~O*<6+z z^B)}4xkEy=7Y83Cv#x4#r#^e-&9uBlu`GBy0!cIrd8^2qo2d#9l-SKt^D(1=r}u}} z7VJeYjw{QP7BuR$2B_A8Q#bsCNQmD^Jxe&diyv4ua3oG+#+Q`GHUUdRxG~ zJ+(X6G(KFJ%RIa&>}gsE18}?_T(6`0uDRDPhbH>61c*zP<-@)*zRZ~5pX?LAu@r0H z5n80!eMMCJY%W#z8T&p&8i+VhL#Y7EdEBMs$kZb+sA`te&JzE`W zJ8LfIj$LWYU;OxWW36XAr7ADf!}<(;s*fl8uK2Mr|bp9YfZV6Ou|=pcy^ zBz-$XL_{PcB*)oVBt`g)WT1{(@|R6c23zQyM2gc=Q3`Xjn#m)>&gmuD8z*25DagrA z@NoDTsoSbaAEBjo)>h;?dKi41E6Q3QA;=@h$)YGBq>F*D9-%)(N^(h0Sq&;mM@s_} z6_7zAv1d&Z!vY#_<-h3fxRsq^tpZ4MeLQ? z!H(8K9N^_reKq7+XMI7SYnC_mK~=u8oOEwRZsYan`^}ZqRFvU%rdFnghZ*SI9BjsW zTiT1RP50evsk}i>PA1IHH`H|N*~3;oo?|COgeE#_W(K>p)Rp?~+#cy{!oZ=x*uBb> z=wKdh&RksVOn-a0e_%pr*n>MY8p;Zdw~9L2d!S-6{%)S$PIh6J-E}pM(&OXP<0E8{ zs#a&LJ8Q~ni?f-T7(4544Yk+va#^>phSKcG`%MBMZUjU;&fm?=+GL>Rc1dEe zv8GZ(9`4L(t+W`x=#&aKJL_P5$*t7br!8eR#yV1PiR{?G(L1;Jj&U7f02n%MX28Tm z?pNm4WFQgNVO&+i*NZAB@Aw9s?G*pSe%nAGSDoqscJ3PDQ^)b24e( zM7@7@DsukrjpU|ebnmT4%2`4^>P1dPZw&=f+jO^RgL?Yut4QCvYo575ak#dfOZJMc z&-}_Ku;a$Nwnh2JBKb;=Jtt!JGC5U6E{8>n?+9h~ZC-?;|4a6~8#Q*|l(XeMK=W@Er4i@sao&-R#z=nY(*8eQ4S)Gtv36No*C~ zUrYyX2gV52u^B^x60pNnVdPxNyCd?!6!{+tDMfpSw>Ml}x8fxbiZ#OL*1Jl-wlufQ zGm{K#%3cV3Eg)>oHLRgGntzG$-F?TVte)#Bd{|N99xrODG5NFcfr*8|E2{F#!Huu7 zFgNEmo^pkHOWX@>g$I4|nr|7F$Wp(tuJiIPfDn4F75Y_&qUX8ggefPosJ7j}ROEsj z@Mf;347ib9r$R^j{OIhK;-S8{u&jD6lv47Tn*Sx{QFX9=QpC{t_l0gn zW(;R;wfdPRNoyqrEstI!4PYa71NW)~LKOgLcos%!^);o5_4B!PQ}Fz+A(1Mxs}dr%T*(xH%<-nI}W$sFJi`Q!gd_O zy6OfC6VhWJjC>2ok~n{R=Zz`in>Av|Gz_wotxk?oIQ7KQCC(n$kZDurE|%@SdsHBz z=%R`9d#qaDM&(iKM=2qclB+dq$7v}frR@@0BtJh5b&zH9A$QP>o0yDc>BvElTk>lG zH8!2RMQWjOH)d|1tt;ezjffq(`*{sg^mZ|_HcM(x?0D<-G4C@pMA*~v9E}ntdiPzQ zFHc^YYl`|J!EB-#X%#Pg{6yh!y^yF&6k@7Ar(I6hG%<2DnUP{5;Yvsmy~Q)Cg7C_w zFq*O};i0=|B@vHX-fmL%H*ZO#4|Nmyi30Y~qw$HgWZ}Fg`&RVX7i9BKRjMvp#%7f< z`w*>>q!oqvKm@0z{VqL>=Oxz^tb6-(d}lRwqyI%C*ON2MJ-dlxU&mWdGo71aS}k1d zC4D>MEv1mqdE{A!CReZglQjResYInWlfy-U>(<{KUPzs?AJO`JT6RHOV)&eHXL|`4 zDCiwDyWT)5MqILNeXWkCRYQGqV1qg{n!ADThJnRf&z+N`Zz8>Psb143`_(a7dZs8j zgM;6Xl(ob|x+W7!?sz?+sWbrZXgn{!w?%^Z=ve7LW7fwSDz>bqJZ)e| zi)6aW1=PNsc1_z%(= zS5a7)RiXSw6RTTQrQZ0HoJyI?r;l9o8)aJ6kT^{Cq(Eq z!?K4fXB#0aIdfy;c>Ja;-CUCV)kAU#_m5#&+TEY+KHVkf%F(zve3;aaST7!PHz`F} zU`8Zdu)*@0_g!_cMtxo1h;1HSznOjzdlVplktNWQw~$B0UakJij=N_4!!H6ko?=sV zu_hjpiJmK>AIIC$TDo<wQJq?9~2%82mREIb4IKFGSI_x84BcjOW z%wUfhs;SxNOcC!*pDj%7el4BY><};2_9*?uiHe9N*DE95Z616N6cjsy4ey>Wy*R?? zgz0}+{B?L2oh-NrVkodraABCEjC0VtOHRVH5M|)5@VtR%;el{*?sdt9#5UV7Y2Xy? zt#17{KC;t@IiyWAoK}CBEXwDEFYTyRCUSJFhRcZMaiPB{@~x>3B&3A_fPni<96H0ffr^_l z{VT2v4K3td(bad)hK*!iliTu$^xb%2M6XWoJ{c$<>4QT~l_is{AAh^L*nT@>F5<~! zr3iIKU^n1#+1?DCB-b${jClR^uHqgaJOYxWBY#D9uVz!n-BPnkzG(m>e2N=45$V;M zxYnxaYkK-Hc+o5X2d+)b=GVH}0|bwfm-1#ow+Hc*juh+pl`OQand z(4Ow>ZLSK~X+_stiptzT$pSa)lmVI6L8S<4ofwkt}*I9 zX$tOfPIO}MP+D~8>!#N4%w^KoScuQocB4o zxp~}YY<-4&YjBcTZR}!_K&#%>g#;guoYL(ftM&T~=~+1YtFQB6tk@}@T_0KRH;2C_ zb*mFyx~b^8aB*%z+=ff(%TQ1iB(Q9?azRkpf4$PmbH_pya4kI1lXeVd z5aL!9c)=sXQOjpjk)_!!m-hrmzlB+E+UsF8Pqr~CCGB*oE6H71-L=(e3KG#DlGayJYN?ErqYj@Rm3Zxax_@05>9zo0LSx>lC;*f&dcpqph%#BJPC zwE|4B?QpI}Gc@!h)4bn-+3eVh!8!~f62q4C@MuV{q|cXfv5lg$6j8c;rxLox=T|DE%!4H2 zUw+Spr6MIZljB=Ku>Isat~2k>(W?91S$*P3Lv-<8&k&9acG1EK&#Kd=Sl< zsxprQGhcD+=o3hJHPs>?8}*r&;&RCu{2lGKyG>8XXp%$< z=wihcXfvzblgWf(R6Va^~A6dXHG>Ct&jS28UuMyS7?Mop`^O3YY3t)24J(xZ}{ z({|6}Omih9$+Xot+SqPkZM(Nk+1nllVh2iz`&gn+n<$?jmK?XcP<*LVz(DSCKMM5n z>;NLNh$VP@?wRv&!Rq^zW?>eMv96G)62P`K3Vmi?GtEjBSiQNdpI?l+q}21k}BXCFM;`t&|m zQ4@?DW?8@a-nYv{_Gqn~<%}`ILtR$YS$&Sd2~p}M;CBaT;@**at}D< znOj-zJdQ1VXKO<36ff8v-L6_!q9~zB!;c26!j1p zMBV2MkK9>XmK-DzGF&Yhj!8*cW3eh5m5bTb(6!S&70uN1u|0Cnbm8;8MHS3ba(BI? zHrlcqoI^Zf0}n$M-qMKW-4G4$Wn?)!r;yo`tN=Zn1CnHZy(FUo%!^ZzvVZ8j?IF}w zBI|d`{~>v5RCo?;*{i4ilDEvHa$D03bnP#7Ye&K}PKwA}cwiqk#CG_@5~=? zpjg&>wHaXNa578hbooULNnRWA4!pajWM;|p0q+PaGKG1Y^Q_*d5&Mf`_le>?9D@t0 zSOPY>xI$IgZM8`y^a0z6+n)f@Q+n%dIbS*7b>&pgF{&CKG9l8o=_HX$*rH`$;4Y>VlW#T7Vik8ykcder%xM^^Z z>2X(WY0U{P3fCb1k7ZUIJTupam(EbR6Mxv@FoR$U!bfQoh`+5)3W|fIw~(ci*Dk}w z9`V&qh?yKRUj5)Cq#+ub8SEQPX+>E)@Y!G7&yzv<3+qY*pg{LhT|DQk9A)>6deo9X{O>RTS zIO_~o1EY6IqsnpeQR@4dkD_*Ut!_N>6Xy%-|F~*>-R)j??A}W3h1M@0RdGYnMV;5n z`Se6CR~b1yu!#WDt-UBk^Wtph%T0O49$oNYL0DYu*2uhOJq+hn%T`UmuzoEt6()Pn zOm7qHE^?7*SkOGemrRgYgS@Zd(#?Q(flk$OiAPeL*D;XX>M&aNmr!PNw&5&i(b}tD zsX8mARa3NML7E^Kr#@-0{Lw>?dh6ph`J9)sHK0wn*yGy(=#D=)BA|ZR>PvooDDxp+ z>`Hy++L5`IX1#)5$LuKnwXLcW*ybaq_u@)wkZ%sub~*X9kBWrWuoQOO4a4_n7tY_y zW~QE4ybm9eZK_N=vrZNAQtQ^`7j$0~k>fnKV~@!{P9=)qOX^mB7MdXdC%tQD zBcP{uY()ZU2∋3~-MXAr>}^%S(Fnc-=X@3RfIWtoGW= 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 delta 12486 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 diff --git a/other/design files/cheat-sheet.afpub b/other/design files/cheat-sheet.afpub index 73c75ca0106fc3162b7916de85923b8e87f0a9f2..bd0b0329cb30b517a7f3a19ecbb963227be5eeaa 100644 GIT binary patch delta 59020 zcmXt91y~i&*QUF>r5mJ?lJ4#hq`Onnr5mJ6>6C7yyOC}L=>|y!guCDM_kX^#&(6%A zot>GTy?ge|d*1tb5p|^*1%LsSCDCDEU|c*sH0TsvY#xW82T(zp{9oQa_`m%BQ|&8# z(|=_+=uQpYH9TCs;GsF4oV^os%j*{yg@^z+rDt$i4~Oe4mJa5T(WQ4=fHT{L!KL^4 zV_tmHuT^FXoMZwFIoXfLp5nkA3kt`10;FWDmK`(OrLp-XnEai5m89~-6unULyY)1? zRx_KVt*3A*`cERhfllDx5)4i(PAnN2*=&}GDg0j^@;z zd<7WVaz7!zVrg-GEefn3_?){?<}$dux|V>irq&bEZarFds(9m4ob@ zD>Rm13McsCO^R%-0>YcC_K@;%QqP!AVH7(0+p}B)ARhvP+Vt@*5{Ah7s&2J}?U;cT zi3A2${TQEIt69x*oX%j{L1@I8P=@(hXrVbflIPdGGlpPsA>iP-fO?1|a$IXL7F#U# zfiu->e^?ePnaiSJhdEAAUMBG;Tx;4_?)E@8ct&L$c9yh0ANQ27(0$zc?LK@J>YYJY zq*EiykJJt9)w`za(fk+p01>Qs&+mNWYP75?eCCYYJ}J9#71W3qmvgu zIHNq5KtXDmO`xn?S)kEcfrw+@_JgvPwTT?5{eSJ0zRE0aMS??I3WOY8nN1>!cfLzu zHT@3iYe>c+8R}40>&^DVZaz4>3)f#y7D_H=jD5g6^zVG2A;&PF6`(ymM2GLRw zx$`X>^*OCGRYfuW5H@SH&pygGBbxHPQ!`4pm@3B)Mt$`1iPY|`n%kb*>|(k z%zFOWnQ`I1ZO=!BXr_;#2_%2!UF?2Z=p|4iHB3lu%B_V&ZqCMTY+7wF=HEY2ucD|o zCZ(Sd?-kQ7y13C`C#UmI7E{q!g4bbTRZt4bFtB7`M#eB(xImC_ps%PO{As*{F{qRS ziq9*7#FF6aA~31|#GVuO`OyAnx#KP9>}B<;iH;KN3&RR`>$|-*519r>+W|q0#C=eJ zvLViDqXz4T;w7YRutJr_)H#=1>o=Z!N_a$LQ+!0Za7H0Bn`L2KcxeruYLveSQF%d< z-;dXQtCC?z-?2WCI%HYwb+gtWi`|0wC06*qQ|-}jK|$ax2;fJQgT3~MU!%y@9$(nC zl*o&~CIzuSGZLcj(wEff0D;NV99g`g^d!TQyuY+GTNk}H$^M#wAA!)DlIZAXzq{$5 zGN8(xcc%=YLM804=97{(OY#T!p*S`ACx z1ojUYRIy8E_{P#WsVrO@FFc!io7*#k>fQ;pu#PtXA1HncqC##OG?$QxhI?o!8XQuIDWCdYv42-Pps{+OE zK=z@|VYR237NF$*1<38{5oIq*xtb|Vm3ahBiRk3-)5aI)7|_j`&M@S?*avkPR=AvN zj+7eTe~R_@p9nBt1t^+7+`3KSyX8P-q`rIEr)ek1vxw@Ubsmrl*xmq-_6xTXW%0SF zX=!Pn6saRX5J;TOTLKat)b#}A3wUj(zewJSmjhjYP)R&d!@%D02*eb6#rbD@_dW1C z2lKYu8w!^Q?+V_`bOhGj@4{tc44~;iY7@EU{V*Dd|9`@+k%6mmx=< zg!OO_z) z|J+EwM=kiLOQ{6ZYX zzqJt2LHs{LVKzMa^(sIKi4gE(})(*)O!YCIqy z^5c=BMZ^#=uA%<)DvI=f!wEM2(Gzo1;sdFZY?8$kuK>St**!>pzY0SGtNh=WzE?x? zaR18~gID%y5qg$R__@I2K@#_Iruazr^kDy}aLe%SmAvNP5v#lWDF35JkZOPM;_~-l z;=166J5cuGOnYtpL!C>f_M=}#Ya{4r@ZlFQb}Wv4;RyoBkHkelaflAF0>Uo!(X7-B zkoQwfdx3=NOBuJeQT_fWwhSb2`54CEe z%3#%Op4$USLQ;XsTa>wN;tJ7x+^h=b&-t5)rn9}5LVvJ;6ri;V zA1wdq(?+lR@zPIy9aOo!u;7^y`!#-;=lSb;W$rPbcKwaPv?q4w&W~Hxd$|`!pW@d@ zkAR%%dqO7Y!Jra|P2co+v#6Hg;vNL{&zLoD#1Yn==n}wtBkj|jF5`}~5qU*UdkmgwCfsNB-vHeB;>jgw} zV>1OTT=PLPSMzihfq${RYtelKC?5exJ41|G3;fHuTP4UZ+5R3!O>gs$@nZ!fO47TV zsgiKnnc~G(7j@~S7m@V4b1q4E)rm)!dq&Ql$GdS9mlfIA!Oac@pcNFexsaRi%X2O< z%4;FF4_s!Ax2~{fE?tX%?sdO(Qg{QRCb>MQzA$kb>4W*wb(Nj5Rb(4CAlmZE3F+~X zjM0mD(nM<|{MSn-(WHrWJ!CD-5BJ6OuZch=d4<1+D}o#v8=H)C0Fp)9yeg8G2{rZS zXL0x!n2RsLAGO{9_h%sVX@W=mf6!il#D7-dRJ_i?=`WxQ$)EEM%7wf#(SCy{zz>xK zLq|n+JSJKN2_ils8FtcLd_?SU7AKG0mo;D3&1B@GbYqAyO~Z>dGYO zx|rpn4%f^V9PbS!>t|*73Y^i1@iBE2mgIAoB2X0>>(et#h+5uhRTB9 z^Njrr2N4{DAu~IrtanfX%{fC+p|W+lIhte30G_NmQ9R;bQ+nn<#fSTO?*eP5kPsw+ zvI%@N7&AumEs4+=^5uO=Ov+dFRDI9t_dj-NxfpSUx$D0ajH26+@Co?RBH<%&$JA3Z z!r-y9sM5-j&85M*nI%3N(j~kyR^lSRLX3TFrS8NP_n_EM>=Z~HXE^kU)J_ZUb(ZWG zRj61_(OQUq;gU(Z0n3hv{sxbOyqdu59H|Ue=%?vdH!%}FRoM4F>}c06E)d?0Fjp{t z0`!c%+xh|#N1Rx4%PSD2YhgMcF?a6V$RbSqlT~%$GE70gAy>uT>0G=7)(MeL#~l5s zlNS4oIrHn)X^X&Ts+IL(9i7e93|{GkFA;O}banlXbEo{ixrC1(Ss-xf2Kigj zf1*|jqF=jQg7DXg;Sk$&Tl^;=S2r(#h`fIVIk-um;0P2#Cv30xT^=KoOh(udI0g_M zIyWhN#+H#@dbtBOa^X7_+%NfWzDtzmZXCFMyY2l%I@Nh_ES}$8^x#)97BLJ~9%ZAC zuCSwOVynsQgKxA-{u~aa0%fq$ToTc%Yf7VZdD*{AF!y!C91VYMW4LWjig5( zL3>w=C-$yL1-5MF5DrrUZWI|mtQhxBM@xt6ZU~d>L4&7kKisUJ3ka)%QB2uK5oE2X zmq?)(3Kc>`rO!sj$+PmCkBF%no}iBYL@Drw)!^bd_^TEUKD}z+%aa8$(uc0SwPsPJ zEQIp{X)F|K{TAbexqBl;J{1#dcAa5;(%Mod3{65=`4$~_vyL4Yc&=bf#EKo2cT7$Z zHFa8qgUgBo1C37U=72KC(p71P+S)N~AD*Mz94|r=`@81r=5QD#yFME8@&pQ2J8HP` zB>VxA?=S}uTzt&YX^gb zu)Y9II~;G34yjBMTvcsXrB6{CCtIvlD)FU_ z1}r0H4$O^<1{Fn?q&-7An7RgQ4*fDj=?p4KNccPok|}cJ4)aJdeH1-hEhGvL)ZI?k z^caLx+7cyb1>+a1$zhQ?&?UKo{F}L9S`!Y#YKDLq8kW}Sq_hO1cAvGL%7;Sai;UZ9NLCsEwLn zSk^cH{7_p5+zxlR(8)>WP-0s0X9Qh47su=WuVs8l8!ui|qLLbxg(>SB_s7kA3tm>h@uZyZG^Rb@h!`OkaYzw zhyA1vX@<peB?aov4<_fON!)iL}R}lDUjN+x2)q zEro&xn@D1^ME{OUk^_BA3I&zxqy9YoxR9U1$Xqp%vR7$UWuAFuncb@YSL>`;c5Zsh zdIR>L?wivX7)2MIhaUzZQ3(htJN-lks|ElqA{}=8@nhkA^GqYAl5riC!l3Ow+@Zt9 zVDp@iXhza55+2tI(gaPo4O!V>ofwQoxBi4j>Hcv7G9N1#*g-P6MuWldXIoqV$E?vU zgp)2zaVS-ve;6N^znE|u;7s`yj)my!ENpUHjh_ABhe%sSSiE`UVsZ@W~bYtoriu!iz&yUMFkb(<4(wcheALi0t zcP@_2ls0=o_0nrDslj<7#|T6v#q5h?kDDRU0DW4rE6U;NtWF$*Jl=&newEe=9Z+NI zJUmMn6r=S~wzr6uMXQA1B^Fvdm%OC*Op4g2@(Zh$oTf&mv8Knc9yey!ufot=@sH%u ztHRJ-8AE$lM5b)r$YXhx77z)O5)ns*FTpJJ%#(yE;49Jf!5Pa1s5>7MZ~XLwu5Q<8 zVDW~+l4f!#G~z@E3caMZ4{!$!8?dU3SVpCxr+rj>`)<})zLi?v?B-c9tc)oqCwxrs z5$cj|>}#Z-#D&LvW$n??XKs`+7>n(nNQ(bjtD&OoO`+_;G)nwhMAW9jygVBFtrf+i zoT|-1V3UH{LA9p<&>t9lH-Ibc+xKk7zXwZAvy)Eh%WM0n*&ZXHBaCRzn$o!HSH_h| zmPbd5ZbEAm$;A^C!PyZ0mAQI2@+-d7%|gEf5fwpKAN;}SCyb0F+U8)MysmF5)C93C zYD#qK({Tdu)=C9_6SIAh%(nY(A>;)6{Cu-dJ-cLn-@EG`fP91Dnki28?)O+-?xs-0 zZA8BFN1~?$_l=WAIWR6) z$*oN|s|_+kvv~T0;^inuvjYMUKlUP?{2fsvXI;_TByxr9JLbJ7!*gqhAo_QYc9ps~ zxVX54!?nrKp?GS#Y5jSbq4WN!U+(%v8~7763Q*f7m-dCmvXuNw>SqleX8G1G?4Aj! zj$x3i$Nb@;Z{WMeM!oY|ldqg2WA*vlZagzl!DBvM^ml96)UYIWP6UrxF85U!_%t^uc>F9Cfk1OxUkUu%NM>a; zvrrVVTNpC4q!JW-xhw(Wogv3al1Rf~GP1RfusBelne;W4>$;mPI$1m18yn(6DhwQ} zfxo864ejh^L#xKy01V0e?2S18-mnPQObhAj>63WkPrtzY@s{OdLRCtQ22@>=_HSxS>K@b>UjleWZ91CMK)DLRJ8NH#pl`I{Vy z>Fy;?I>K;mnNeH5vmrP%6ex2Zdt1INz5#y6z-R1_6N^`?bFiPBpl~YsC%$$lcz#*G zd4c((XN&X0{_iGBipx&V?G5am^L=jMv;CqDO|xf|QH7sLKXE`67YeqyuVO?FP8 zxB>r~D>@Z$;_>SI&vV^P_XVNG*PsCR%d$c2%9yi&4K^AaX9{-tzgw*e|MY4vu98q- z_ph(q(RA{~9%+lPe9pEp393`XbDg{Q1(uJcDVBHzqnO)Y|4w7v)$VRl`jzFLCQ!sn zg7Tw=&~rgfpD4ux6dj)27e^Kuuj#JUL@)VJ3+%fHtE4e&HhS(y|7mUCNM^j84C`lW zCrhH5tLO;4gkN2 z_qAF?DK$43qpOCIHFz13bV4H&I`IjT7BRdEP(*HdaxfOjSY>trj>^3xY}G4i>0?j> zI^CnIbhCT?muFj}OV|deFGHPz>9YCIizxgL#Ig*Bj~!!54RNC_g4K$28y_K>iWo7d z=EXGUAR?>eZpN6r5tVK%O>u|=2uQhL>A%G93?R!_x6l)fDl;IPjIfMzG>Y z49$B25}`gBT6h6=9BFuI6`l@Mvq#BMf~Key&ts;3zHtb(N;9wkRv3 zabYPXg4M665PgJokmS^8&?~5r!vKA`By2oP9uqnbDKY^@o8Nh#F6~Hz>@N%^gX*PF z;(aUoQRS0z1&qc9l+i

>xswVuqVujVW4Qw;)rOIz_4qE<43bfn{ur3^M#Tnp5Qj zMVrhBGV$Xqi{BC@;da0XDTm&-rI#6|t^w$$1oL^{GBTK;d70n!bJ&d0?8f2tZSQGy z=Lf6E-|e>mMWcXvAIo4k%}B{x#k>+p8G@z~-6+pHZ`Ud?o9N8{4YtD{q9zsMW_`o5 zzu7gA)G}U8^+MH0U~SfE0%Rx8xqzH;8fNe<;@{_6D}KG~eGg24x0M?WsSw^Yf)975 zAP+R7KNWAPbN+4WIezZ=IYzE7fVVNCbXWxRk5F;k(+tdDa9(4*@2@|lN7=e6AsuFB z$LV@h#Oc~mgttcMCx-$RGEjvfwQp*E?!)>9DC)VBHFY}`;eNw@xf9QLaRT;Y5rznM z{pse8`v^#MZO$ba-oZP3xQt{i$@v)=nRd@Ik?P0(p_PszyzjoL3`t zMTSz08V$lyGf{2_!cyb6J5W;G&}&`@Vi}M51?Vf(9kX*elcCxA{v9YACWioP({g|F z!|bjh`G!Vapd&~2@<_FBEAon-4X&k3t~ta8PfaHK+A@I4VV`}5JEEqRJ7`===P)*+ z@(hZUw@ygmwlrhrZ=kHct|BuzKV|@FmA}X@qoqT}E8;CE3s*r$$&dZq8wht95lbH-5Q*q&&CraX8{C^E>$G07!nXn&kCY(cNsV^QNx z3?H9Oi$FQMeF6ukQ*kvbLqwrR(dWtv|8v^njD6IAh0es0G`1=_(tc7mvSDrsZ8S?I zu-)q9lib;Z(QTH*;9BgZ{rjy0c$l>i0ESFr@uRx%H>a)==Cx2;bmT9|aN$I(Z%Vh7 zlkwuI$GUc65yH7fqF22-%;1@LSZ7tpMIVZyW6)oB=nzPh$&dZJzSSdalr=nsA$Q38qN8@Vu5zYF- zAw)ZFw78x9_P+qAWo23dwZs;5fe}_kzQ6_@1A~EOp78N${V`VE>^P_NoF%@C{mf>> zggndyoI#8?+Vc+_$&pb+^E{L#A$+K0FvVy5u?_S5iS_y@VTJV?hj^1or4#cS1S`Zs z9U3pG&aZiFRLnd2F$%jR@F_$?u5k;)k%OZpf@#dTP|aeAEfP&0L($g10C3VNH-T88 z$VGOvk+0X3KkhQj+~ly0z42g$drx&W2m?1e9EWDqXpGwUp*2am(Q8|Ftm((q_89Ju z(Aq@eSCXO4p6V`_e_Kzcy*2+Roegd%>2UWq>Ktk4buB#G_Mf~o((6*Oy#E~=>A z7areo9UGd>@MnWQ)E*wzUU_XNeh?-9SA%0s2UC@g2D(U88ci5xgA&#SSKizA z2U!sxNf6tI2@6w`K-ao0#qb^NY+clh3KHDn%pBWl_|Wk-U!?64sd&&wzH3`?l>D>V zjtQ+Jx`|6K;`1ke?by(oaIroDw(jd=uUbm6yn=eN?#QBcS)-AIL933zw+w62yfbEW z^%P^%*B&x}vj!aPq09;rHhJwi47}S1Wd&G?F=<9wEA4 z*I}_JU5-BrEYMh|q3bTKtTh-kt|C~fFX1Yj*3`lANdkev(Uv@n&ilT04+V0{Su{R8 zNXEP_*$g%cHI?I!eV@rkow1=&XOcfgBm<@GyIA~<~2aiSx z#Zr;KAktsw&BD)!IJPChsg7xnAeLj8rBPSN?J3B*(`$1h5@^^_2$v?Tx=CZ%3<1$r zg|cI^|Ak*TJtY(H&Y!A-yD&%204%6ib_3e{@^Hh}S>Hfxl=9f;^>77WSIo(Jq2xqU z6-i+$axk-9Ah>k3BwbyHVy&2K{fWr9x=8gaivh#&D?g(A%?4YNhwI3>*oUTszAOM zPC^J$5pYa?A^m4o^e#~|A(snpB&FY?LF2dZoJK~+1eZXq-2?0BN=0Qw5A{C)-R70C zFSlG=d1e&$33}2C!nYymGmWo4wdfnWAnQN$#tz*J@u@7m)rf-_i1$ioA}gx9!7y>C z!gyB)HM}Jits3{G&R$r$L{A`i#UAk!lPs#|8ZLeihjDeaLMSwtkP-gN*Xty6MmQy$ z@pQvo1lj7Ode~)cn<-fY%Ee>N!jtihPk682s}w>s~F{xVAUc(MbMFlq}LQul-_+zn+XCH&7zZY zrO;0xowSb59FDA^HHx-nU6NO!_1C=YxGvd9iDgV@UCk%D z;6)F}t~e@A^>c_NnJ<5nDb1E(k4-ftv~a+1vy!Q8NRqZfLNPjC`Bt!_BZsSB`^Z%k zN-3XamYVi49M-DLP+w&iwhM0G*7F2u4aw|%!QyrZj}vt;w;@4J{cbRQS|pkeg{IV~ zRc`cLrMVJ*wNn&UCXDZTsB$K}0*SypKE)reeY)&xK zL%LeyF3-G?tUe_avo0~v^CS`xlN86oqEW+Sitb~L?f1N|lJ90|(O86898u zhDAfsH;Q23>2|sK0(^qU&`^c;v4x5zP!#yuUHk&SiAshk?$HtzM;CKlV3TS{z@c*i z_5=k%h^%UK*x#K4JB$?0WJ*aRa;GsP-@Apamjr|d*GDeN4SZj+yZP;1> z$1jI$pR)O1Sd~$A3`L`PNM>9xbDJo`cgEzivH^YH&{Ei# z!Qc~LPn3K^&m~;-tnnSt?EWI?pWx-6l zZ5a3w`rxsWh7<)lC0x=m!Ay%;Lo;};*NorcS7RrUUnt-c@d(TkRGI7?%y6Kd2;t1r zVG0KMcHzAg=7J(>hlJ8XsAf;QOjtVhK1py6AC+J;7Y+=)1nwz^WIs{rZ{eG;*zrBXC=Om3N{Mh=PkY$+N*clZ&;fna*hOM0=*Z%uGO%%) zB7Hne$tq$ku?rn2+0lTd1=w)neFZXu6~gF{=&8---_JI}CsLXoe^wUtdhFwM3qO%T z5Vf177*2BK9Pe9zL7~4I@VZ$z)FPt$Z*p>t9R z2=xoh8`mNk`K`F%kKql?+z~UWB$6EZaLunu3{z-Xp)x`54;Ybo{IBk`3bq%ud_OFk zfQGD6t1$!Xz&t(?y6F)rx+#wyX&$|Bq#c{Cxvg?3?LQm0OsyD(N?JlKdHTqS@94qQ z%c6vdz`~1zfC2@=ea@HroE=TpL2A2_=ps0cFMe?F6;6cj991Zly)gCDBO)6z3?iAU zog#_=r|=qjmK?u7zE5JFXHpYl`>Q(nubYd@hfB@%~v>gMt_|E4r+LKJE7w9Fru9twvu-MrLt| zCT1Hk)JY!EH1Pz=Y7B&77ot0da9PmQw15p#PJ=fvueqVJvu*it4Fncs`WJ|x;fKK; z`o59ue?*xOxTPi(D;(s!pLGZbDPtrkg-Hl87#*Bi7?;bkjUkslKl2i8;axk4yng0! zjzW-Q1h6tZhv4JQhTn6M#*P@5ev4!}Lqyj#FpNB!Opjzb)iN)hgq7VVxB3W}8(cl& zjl4cVRRA#r1BSu;9S8Y0p!nydG&hL&%oR8r9_#=)dbQ3z-0ol*q*va4{k~L96Dt1* zd8c2oZH7VH56&|uV1ADi_R;cWh#;{CCPTTWA+=#x%M#1MmD5Ec@!c!r?-$+0m}J7H zmxo9ZU6ikx$AfGok7oejm1O%Hs@q#KzA$iQYMnww4)oi+C;(Zw>$(c^vK$q~u1>|P zs#{}CX91+$uhO7)HO3J6X-x0z<9@3@SyQJjWbN^X9uy=@qkPJrALl2c!UJC^fltUU zrh8uGCibAVl85us+)!QDpYP+`VgKVRg+GFh%YTTfF1G+*meqmw`(9Pn7_|etQt~%| zdBlG7#|eejZqBZW-GQ#9O*d9LnuFbq&mxV(21!nOZJSn+4ppq7oGH>{QZkXjf;cw; zZx#HKz;faGo#416Og=N3Flv%&Xn)&c5+0|cPnL=?)Uf=L0GhWMnuc`R;S4C-LL zl-TI}x7N9HzHX|Y4Xm@pMv%PX5kbAPH6{gu)?1r-LEeK|uv zHhm`nc0fyL$ELi{tD!A2y__-J)iD)#SN@xaYXiSuP%^B@@{a&*Aor~O!2!3f>g{a*F zr;K1PiV=m@ZGPi8l)~k%@RC1~48BrOx`&VYL@wswTjFz!-k7-9gsAxlAUf}VCfL6% zX)vcdl922{1;oED_qm6XGgfHQmD@0kf%ohQ&*C$)V@!@Nl8rQS9+yqr#Ce0^Fd{qMx)PyJzI7ET z_+?^7rjz^v_ z01oK=fR1c8pmxrF>YB1Sj87i2mko*{S%yBR7j4Ml1|nYcYxeyS3hZj zXG~sZ)Szuhc3>VKVcPhSqUW9r#M4;98kRzJA9T^7Ug1hE3jR0&@}kzx6X?!-t$YMl zl=nZ2Uz~M50(i!yER{bzD^CHjkY|vs`WJ^@P4(%asWLT~|MikwELuL~UJ2+aoVz71NfQzcm5;WEJGvpd@d0aPhmMBZFh=Zko`C{&d?22}oaxn{@1o~$ezaVZ7KVxD{9eAv3xo>usMn!tP9 z_7N9`>-MP4E3m0MpN{8o1v_iWP6S+!77YvdniV%s_4D*(^0!`l^hI}-k=C5XcaShB zz@gGOyhp6cSV!4N|Mh8zYZdgcO_vkRVMmwq^!h;WweZgm-UU>qF6ncCVdcA*8S&2U z!AFeu3rn_cIkg@+wH>+{n`#B=mGgQOgmW${H<`>@w&H>|ndPAPoYQa5Vo*gV?GoaM zY*kd`#RTby)6-u|GDy1xrB7xwrpJ@*+Wgga*iONjZBmuPnaYkHreg2Nf1woZ6$v}c za0rrgq$a?_1vJ zztqi3K$)`t;vD?N-bbcjlA~Oe+En%Ix$XTkZ`dZGI@!CwThHR_BekcX;l?}d18=0x zDjEt-PP~KTOC*NaQ{e4SN`fU`Hm`XeHooEn&~<9r6NtJ!n^|toxFPL;tAlvz1T^w= zKDVT2g!-wi7=B(@7bZ7V4p3`g{F}u=ye{nepj%pRMVIii*BBexBHdvbMPn@7eL+rCaCK3W zu56gJo~@&^?l8z&v#h5(#SVS`+16|9Yy!;D9|k3Ji=g7r^-9CT!=-ZPf z;`EP%DS}f+H~a==Yeu7qT741nJeF)LTMIwyN=CZ4Q34UL1=ojR}izMyY9`T6zlPX-AUbbj{r zEck)-{>2OeoO!iLrbFpg0UyA7%VaXuQT zpRp+t)AqRpUa@0u2}!%v9O;~`SunjEL8E0Sy+jfaX#8v_w|S5I*CjJmG1#?SFbi?y z@~dH(8#5M>{Q|;$|do!q|F6Y{;@Qb{Qtk=o51wbv)4i%RaKd1v zo4&u-{E*0^K3~sLeMteOIM$teK*Uj^SP%L*u@N`PznSZg2i<^h0w}t09v>Q>2C>Gi z6vYYw!iO;LtaF^Ty1L=^Hm(?j)MAsroPOSlW|y14PI^SzGFM$xBybjS)1!s2|N9$= zx07HlT~_&iM3C49CW0gmy;RBg@9X$=hHvB;m%icdbf70 z^bbs|QB7N`lOYRk%_EdU7Mcd;{!qlY#Oai+Ed`mJZI`Rc`HXEBE_@sWSD)zmwC1#C z3F5=jZFUs2WJX;d^~`2^RQjR?7yUN+Ee`ht-?j{e)Dnj4%O!@83ma*NPugYna&Crw)tH^3Q3N^Kz{Ukp$tW4a*I9ic@2A`;USD68d{L z6w_(r8vAL6moMhGXVP~=j z)qcRA?_iUmgVLL)l}7sI-=(uxH+Oot0*4UrK6W87W z+ECIgU4ml8&~YYbgIx*>4Vn}Zw^h7mnI_=^sRRa6DE+8A{RkH}K`=Hp2AdEI6%INf zPP{A}6yCsyfwzD`8HB+Yl;9heAW&V zc~Rx}>@;rVwIj05lHJzbeor~hY&KgFQqtjos0DYVeN{A%|nyd`H{aQa+B{gcOL^lTP zw!~{oIr%d=Pc&_0^OLqz$ME#z#W&n4A@i86`F2sD+68wF=j^Sf!8-q*Bymf|AZyYm;+@xKG%76^zxTWy z8Anm!CMNiX1W61nqLYI)xLsjZlh-oe1WScf{{ESq*jY$FC97bfg@pesJcnO7SfDJw z=ZTVstczH2dOX19i6W(z>+njiwIlEXyH1RZg@0(;HaiIUw@S|M_5_JBfb%iB!shp% zn3$LdFQE=K44M~4fvK1*avYc7)`O=Q~3gT>3}VLHFs z=aDkZ7=$@BQn}f$9^WOul_{k~!H_PNn>6cv(}h8iP?2w1jeZEh&pOE^#ZK!E?4go5 zCoolV3cC6VBZ}HEX+G~H2TXK*vvVxOR$wCdHfQ)8wQJS(UeSaCb|8aAmw9A60)6g_ zOOsEziyc~zx_zw<*{8*vUl_lJUj&Re#$S=P&}F=P-4F4(=tc)wtzJ2qrLI0sO6j4s5WMm(aA z9{(ylZbYv0c-`osWn^Jz-%C4ogEv)<6|kWf>jb8JBmEsYV!Y%hmQbyxknzKGM>oyf z&Gkc_gTy2mGA%buJlsArqoWVwCm!(d`lRzdrswn{qs}fN{g_%AJzUuA!RKZr<#^uZ za_i5Z9_v-l4O-GG@B@HaiPOq^PrOvGcy!1xi(0gEF&X*c=h{R9A^w5V(c=_%JrS zMMRmTx3c>=%E5=ZLy7&;Qi*>*y|MB8lXgL;chvgc{m&KS3iMwUt@pTn7=~9(jQIWi zDqlEnMZWHF?Z$C2#-|p(B&2G~uSE=+<%+G26L%f%J?fOUU<@tJb9wJhUl}_2tPbAL ziR}4*;W4IY(%Uy0#KFoPH|*Tw`(=3$t4e{Ur~17pJ1(ng;7VY5JB3{IG*4F9f|s1w zuNq}R3ZwZNtB}(ZaF(KTj+0jSB$8NqiMN_8YLs@YKeSS(irkDvHf?L9huIq}xJ97k zSLZL`c)HB#6zdC@%bd?7g}RUD`rXBF>pGt&Z*3=oTrWkXX>ZK_S5aT8I>p;WhiLu{ zZgF$s1W-PK(HLvKz-yAd!;tb#rlZT3h+>b*pRLWGF!605K-(5$pF|{!Kc?v4CzszG z4sd&)?Gwf7!Zu0$6Bn~lX6nL6i{#Pg?7sBnATMd?+<%zO_KoRj?Xg(5v{F{V-vROb z`S@>LE;g*3Bnv7nfv(XS$`sD(hZDIgOprX+5GlpX&BAP97EDBPhP_TYFV0q^a&Fyy z!g%IQ+cQ4~1Wai+(HOhlBF%1!_A2~ln0YowgtXgd7ukd^@3B3@A>*g$;vyv!>Z!oG zKFY=#Jyx8qjlhQL>8sEwP4csSBc`9(&SL#Ma$v)4+O#}qy5Jr)0(+iYN^QCA2%kn* zfzZ|%-K3tdrzOd}Z(GN7u=izXVWNlR8$CUukVJSn@NxH#Zwb0gqNw7NV+eyHpNoFw zh&j)lU0+AQM?tsQkE0tJ=?I*xZ)91%+Z<`INyf?t77mqNw1m}DT$(VybET`#h%YyAyRg;xaignykxlF#^yU+*j5O2g%{PM* zE91v3)!zu2n`?fw_Xu!QEt>|v60N_Lmo@NwwlhyoZnh|~WF8o+;0q>{i1$M02#ukQ z*P}DD_?ah?3ZZAsX1M#9J9GyE&2q@wM;HPXlPSTc5ifg z6keTnm$)ahJNokTz=RnUGoH0F91VO6Rg=EG@M2?&)sN+3&w}_dDb5&A3z?Hk9$7v z)&+O@`tPRzP3_m;yY%C)1E^oSaU(3MmV;9+ae_$P@01Gt=#wH%hV)OvSujuj`jOEa zW`w8_ms6AE@5cK_zGW$IVBA9KE$5}>e6-*OG~On;tRW|28V8grge$OM+vp@E&uR*o zNkyY=bcJcVV*WZSRd&!OU#tRR9M5s;8&lR$a*}o$=Vn3F|+eOi7-La}uUNLH6uWaYB z0;%YBxr5A%2hJjc-`d|r(=gc6&E^@G(zIM*4#PH(=8(>*Yb{go%r00vH#9|h4L|JQ zYX#Qd|Dj7$M9n2{PsSh{8a=%kY1qj-yw<^FV4fV;jKvVR`))SQqo7?>oL zoYw1YRPjwG7j5<}HS40u9&>yxwU0ICYoMJF($pfxV?TzSqC!(W(l^Y6E^kxNjgx5< zr9$e!Riu^79*HP68kLbN$25vdw_8r*1D9#x`Z#9Ja<~@zu&*rhORC8{p%S74Ecr@!ES+XGu8Jed^Bz6Fa5*T-6>9y`pu+dudg1f9Ix{ z^DL|$>iD*II3V?t>|fHW$V@oy_<&aY8Wan?%AF7;1-dTxE<#+TXpB(^fGH)oxs zY|Q86-s$nj<(D7c%SS)&Ff>$`B4JZdwLQlF&YA!0W_@nMvF+{Cwz#mMX$dsT80?Vc zt(P+gQ{3awH1w7U%#0DLO35IF$GF@7f#G(|wV2`~M4&|b(C4UxCZ!PUI$Lf+;Ln=X z`02<>i5Rh8o`BgBvt1xD2qQ7u`UjDHg>Urg8>{iAfgQq!;8)CKfl6NQBRCNhm28(V z*kl?ct)6|}or*rHE3i^GS~LJ*tOztjXSZ)j++5H`VUt}14NR~jtxDdHYreb*{i&K1 zh-So8w-FdQX<^y7zA)Bi4xwSF|39L>10Kuv4V#jkEi-$QGLpTr$x28vvSsgmD=T|E z_6&(aR@B6;z_x|4ZDv$fV?rWUqaUREUU$551IMckf1Rv@f z>rd;e2^9>n9Z!BZQHN>#tF^5BV$-2!tL`~@mi_3TA|-3`aD#`D$zrbFsY4FsgUyMz zTQ!XuB5Ro1=;+0|vxU^+Rpm6Y#e}JJ&m1g30 zV1%|tvcPh=jfS0_0nJ~E@ZaYI$y}Eyb{typmS@YA`dSZVy39X)QOTP;N^iLQ*X(A* zvwP0@*XkX{w$3pcn`YFH+MV6dnh2X!ZLM=U;vIjInT(n*7&6E~%Sn&cVxdSLGy9_rk%sj3JRK!@FxW zhZ@8}*B>*M;P&~62S)SldR@orPP`a+IM*oe!KM>)t>naqqMbkvF(zPJ_=exfn8OiT z`?ONz2X+0Y^jVuukADJF*fg6#WW>DPc59<9LUHklnfFTr_PVZxYN`e1Gx@sZD2_-G ze!17UVy`_;xFPy4v&_vco$Vc$AQwP5$_I=rcS?(QEnF_{pF8)J%^zpmn*w>Ndf z?TYQY`CrjHrElVal;M?Mku{uCs+Oj$Mk3us>T7M&+M1We z+Y9=*i?+lBg|r-WYFt}hH7;6vjOgYu3DwwdZ%7aED*RO`CRX}kJLoKN9Nc6Ovg}7Z zTObr16l-L$vf_pzHTq@1wc#Mlr<09BMbcodt$Y$`aMPm0MywRn*G*ell9P0Lmux?q zh=&tDtu(S7X}wZxeyg?rcTa%Qk$EI00b%>wM$^gffivpkm{&XVHTqFr+$ zCt=;bu3(uAP8v7NJYaQi~JNljZ!<`X-;oRGDFCX;RlR7i?EA8j|{IygMXv(k}WDfW0 z4_FM=J{ruM{&%4)PN_;MiA%_-I7yxVO)%`z@#xy=TSjk&j~$vsW`;5uj4Q|WOXs8? zuSFk8)qf;;|0ZS{hk^3Uq{2}0i?-mFo?L*nkucvkY+p=&8f15zUeNGrpKahCfA5bm z=Sbl`7LRThf*tHGoaZdwglpfP4fguF>#J9B@Ctkv%t$&lcZk`KWtHqqR}Q&(zcZAT zT}zq3i>bjzi5-{z6}exGN_X)4$`#$DRqfzMbt+A`irgpK57|n3jhSjSs8QWLl$Y|$ ztqg`LBvW$)#T^jd1?A<{Zfl>16j(;Dn1AJW1bj1kFxcNSumebIG*79QC=n(@uDm|$8b!WpR~aA?zal7IC=B?Lx<0-s;%5V zq(|Jj@9)Q1@tZb7LDOhkZsM}yq(f|Rdy^r#DNQ~7nLv*OB5T5MR9M#IsS<8tYtmldvdN%Z?Q z#b!Q6k6t;1 zQzBk8p=t6~**6z{$r5D(&QKGFjO-AL+`!j0se(FctFML-!dg7NY=_m>-9gEoL(O{A zWOJTZdoOyuiTAH8yzU{=nw$ywLqKYqOdREQCDq=9=+9(GZP&Dv{^j3irZwS|IYMRg zy0VWOa2BU9SadRFU1PMwk20`P;j4vhdPll5tp<_b55{A?sB_*YQB?e;HVHT$k-3-L z-1*=~m({&|D#R(kpya8)<6sL-WwgPN7S_MuyIS|MvJ=`fuyp2jX)3MaS-hg8?uEQr z_lVVc(DY7Uz7gYvvSSLFp%Q-c^$GX(mqFqN#V#vnYM&OA)5Ns5-bAPwemeWM&&TGz z$NTN+F1~5^n)u?H>D>}9UQUwTJ5pF8ZKG8-jH;+aVo`r&Q1mPI+np^cD)-MM56DOU z#!2YB_)19Js-7hAgHhCH^vqxY|K6RA0AcTYt07I^>@P+&4eXD?xx=E}B4jaJv*t&# zNxzR;h2iBsky$9}X=eFdsQ=D;P9J+(i;J3+PRN0)oy07>m?}V2zAi~YxO}5Zq|NZC zP#;s&W>0@S7fCGGt9$j>aF;u>UzRmxFxZp8>%qK@-l4J)J>?*_)#fURZ_CH7ld5Lc zO?p~o%&c;i{mVEv9vtI~>f~l(S6N65`uwN~UpUWw%W^}~=4lT#-^WH$c>(PgQGLG3 zG=y6nf-fIfVBYI{-NzCxGnaq1OsW(|VL&lFb9iY+^!YC&PE99lGX8b_cW29~+AUvu z{4$j@19hL9Zem-d9WDYF-t0K#qw`|zAO3Pbw0^(lAZvef^=qd?#lm{KjHW5!GE=}& z7xO~v9;sTb-fD%aE8){&N4jNshH{lwY!$zON6lP8*SR8OFC1G4(}JFc8+`M;eI@Ye zs^B=c(sS;29}q*fwXn(DWI>WN=dz>C_r03xH#43M%d8cy1c~#o-CH!!M$OGkhOZ;4ecjqBG|D-4l(&0R6`ujq3=If4$Tqy)ZcSUc~c@$`RGgC z7tAFlkG}#qkL_e-ST3vD8So?*JWdFH{JX9!LiKfEy>>(RVZxM7X|---^#ecK3)Wov ztFL-|G78*I5FIItVD)%~-e7F|7@5au5kS+QlN6E| z5?23lZ*1RK=h=ip+t<$+%gG7mZ}=+Ahv;=O=PNb)Ckk&6B!2yL&&xhFk}Z^UhADCf zUZL0J>C#EWwDn)WUyd}l*gd)$HOPNpx@f_)v$mYo z&!hS>s`VO+2#fLS5`nQ{c87tvKW7b!`P=Oeb!1Xs`AnPPnJ5$vxZbL_dopo*Ni%%k z%Fp0uQ0Ids<3|J`zrXN%#%i)TWMRzVm=DPzowTgu)lIjW^DufBeCgEg>6*;%#?v0z zUbh{86?Ha(^vzgP6kZt?)x)7!#^M)uPfxk8-gQ$rP^(~wR&|P2jZC@prL``r*Kp|4jSLS>B@S4B`)-X)8VV4z6Ldef z{CQ{b6oDs2Qgp?fBx?xaNPWA`+teoq#08%?6~)+)err(RSsnK%}ou z7I}Dyw8ALY+uuGo-!0T1X*_BQh@fF*wbgq!VfKlhB#>vnna#>1fvqxHHFk}s4MX}- zrKlPG&Rr4--yt)TuMf>dl3XxCJDZ<9we#$Yrus4v(M!BGDalNoeshE8#nM&0ZpI&O zdZWC*cw<%mAn#@K7=J0WnuLg55Nh^{tIiZpkcxJt`u-aq;qAPp$`H#Nv&&`E<@KKL z_8*K!g15?v;;cjo)YQGzjafzf8^H_CEz@>_1ZBL=k_k(?x>h!uk260XC9|7b?lzgL z)nT$K;mhmX$n)-En#`o^>uP@eN+v)f@UN6jb*IGgi(JGiWV2o2bq9CNdDY92)#Tg` zz5@J|FRMPX!lH$NmZtPl%`;RdB}teY(YLPLz){{`dB$!1LCbx8(PN#BU~FLDMI(do z(Fba6uE{{zsiX!$%hf-}q1;s@&nV5X*Ak=ledgYJia3+sn$ zePu;?3>n_ow;iXEEVT{AS%+K1ntxO)?xy}A3AK>6mYN@b@xiR}WJ(z{yF}^Mz5q*}Jk-7LcJ!aYCIH}M6qf75bs6OW`kM!+?ZW3GyZS)`e zcJw#LxR>eTRfVct-Uw742qlFsq9DZ&ec(@HD)x^ zX3iju_pmPD^ZySBtQErWTFX|iOwPc(Rr5)U!;|#?9xC|%4jn`tc3j87poMbiEwT75j&WdCc*z^{>@ zo6e{?xDye&S%!Mv&5d&v-6TX%dfi;u=u;Fi7EuRX+}OD2<_5~PiyH?U-MnOsBIx46 zCPlYxP{eRKI&@PDwGH>fM>p9~UGRH2=%zhN44Qc8W;QAfnpo&&D5?y)i9U4^qZg$K zO)7M=A9WM1K#Xp3p{k&7=%W}hv{8ZZ1qO7J8-?`o2w|d|D(HW~M|||ZKVtZ5{qN7- zuHhJ$(049<{PHahhNZIwzoofHS`IBH?NvD~OpO1=1AZ)A*FlS^S&vA*I~hDg?rj%l z=w#?@4V2{s{@P1M=IZ^wRs<5!I%(x*5eV4Pd00$8|WXFd-R_U&zjO z|H=w-m7N_Svqqk(8=jr5@O~Vf)|K9WuS`hXjTLlKokp{L?K8KlXy?PwJL$l*ABj%Y zxbiXoK~c3}oGsRj4)PFrE8DH99*Eqg)Yz>t2rLkaEuP76YTsJ48SneInEP@fJmaK; z{E}AlD%EwPv%^7Iwd~)yT$jH7U?lH9S)%)xEQ(0`j3gk(%T%vPf?qXl6SZ( z-Ip~5g@nXlgoz?TWX@N$CN{k`yd;8J88bA(jrqGR1 z$_#QGC?x0aD^q>_E-=XWtQMsiHv0(VYrlwzA$-^J*NDM?Lx3d_clO`kIsw{PtPnZ< z3X>c7$32#U;o;#&O|7RA#{5)LQc@*)Jk2IIXHRDiMScD-(TO;iZO^oP8yic^%Zt~2 z^QyA)RuPeq<};&5kKVj_bNq#$I6K-$Qq$Y}4kaZ*Ssd2z(`m!&)NY(SvP0Sasi`R= zPfApFHhtW6iLSDTH64|3ztGFS$$R_thYzW6D%`c3CK|rJVpdjGD<0y0ets(I z>WjJlTWyTJ(&);VqRKZ~- z)5yg+Jk-9QRA*=Bm#jPSTU$gM zb-IuZQF(c}o`C@?syF@i(`!phOB$M*Nf{X#Nj7X``ETFir>J$#UYyS&)^Rt2^ghqu zk~y6mI$ASm<>6uPvlN863OA|fHoG-<;P+zW+g`3vwLhtP(KQhBe5pt_^Drqv6bBZ8l;fv&<>i#KLuWk$XD_};#(w+$ zJ!(fyO-(xTZP1f1^rhK}M7cDUL;H6R+KRK^zZb?R(=WB9$lk=$MWHr*qU5x(N?(@u#E*s&V5ENiVuQsgiR^TcPkW5sD|=K2bLcha)zq+*`e>rX z|IX>*cJcf7$#38CK=jd)+`+{j+|BvvUzv$)+-u&C!osU8mu9;}m?xHw&X zeQXUGn!38W(VstKb>Fbj#*)Q%cb>AdvW67r`r()B_nV%NnMTfV*ko(G(c_WNPcTG^ zEd?WgI(0jU)Oc^3^!4>YXzFsR6A}?ol9R)PW6p$c-xfgr1;CEEdiCnUVP|Mc-z zB)~nRD0yFWKB@od^t^43eY_xn5CabnFLH>+zBaS=>3C9ZZd~V+`Ns8k7W1FO=*2x= zzyy;=D!>+|prkYx$#NB?FEedri0^JUy*Mxx5)(Vl@9yEdMi7Vu2EuBG#hgj@!EH%x z+NsXAqt{Z<&)*-t(7u;F`gb=(+x)dod4_k0!iIw|0$U5>1O$KUfy~Zdzh15UZYnDyOi>GiTUpmcDs}(eoPuCboS%;w-_6=M zs{ck0z0^v^?923dO)AoU{4hF0f-c0azK?G6rNiLJiD`2BcXTpMMz-9JAPP3u$jA&> z>}!p(J?)=9wSdh@9jm1O&Nze2+4{p}O>sFlQTpWvU1!I8orlGPl^Dh4c9$W76$ivA z6&9CU<%!dY2<^GAnLNLLU9ES?ZP@=ePCrgZMufYoy?E9Dc0%T_zh>=T%otV_E z(RlyrYnrriMu+}4JJ#6FwMMa;#TJv*Rt50{sNQ5U?=D|TCfWzIvA^$5dFN->VZI#i zIr`o>6vul%vLCgnrMg>6M#dOMOw^o5$?t)hTMC8bcr|i}Y^0(*6#eO-eDNMfcA;8{ zBs9M4{a?GN1LMeQq%vp{U1fC?i>CU>V@Kl#2q!h(;B_4&XQD+=Y-EuX z>@s+fdx}N6kKHcMp$wN(5=7~!tnfaKZcA;~@3@><z6;(JQaV~|*yqx1;hL5YSYnu>8uTRnrKfJ;m_3lRCgj#th zNBfGS(MW&UzJs@}mnZZ2sWC=O4z=>rVO@W9_T59z!=|RTP3#()lT(PWt8GC$V8?k@ zB{1f5QwUoRG- zsqyjuczT$pb^%_A3@=<}0h|GrucbcEI(b-Qctg0JmurTi_Ve>>^3DZ}f*i_0N zO^i{B^pmtL({JX~G&8M@io6@4Vp@q|>Mwy=Oy0dV)SNRT;Q2} zDf^rU@`Q`a%;V6>AvTsC*${~Oc=A9vBjZS1!Zo}2b85%Zz!$w^U_TlQVD z(4>T-i)85Ogy@VM;|)YqZhH`OTDiL?Yx$)!a>&Fvv%=vWcfEUq@2xWzB@PlCf-`@- z+_sv{@Fg#ROkARPmQfN{Jxx>Qr@!ROvCkDjS3*L*e#gFkz0#9+W9I7dv9>93ajtgN zwIZF5@35G;Z_S8B_L{@ew3=$&x~qb}zeUf)ASNcE9dNqIR;c6QC7~Ab%#uZ}>-m+A z07Sa$?^fsdn4+yu`WuVxugl98{5O>yYw|xBsfM;=ot((>7w;Lg%3IWs9{9Ml99(0S z@Mh^)d?J>(3IRT>T_%)3vlYSRED`fJ6`X53Uyn;o^S|1~nY$e~`e&p}J8n`8PCMAV+a*FJ{f1l7`iC5_Vcg}D9hSK3i+xYOa!wx)b z5yvNM69RGn@-9M(Ybg=$J2VE5!zxM%);A{8d3e4qFD2GGOoq+S=5c>;nEVU{lbyZ& zLhPLxQ5)mDq3)*bk6CV;E5n77dtZb;y(e6MeJ@K>Jxzt}sPkq}n{&_}-9mA|xDY)e z>GS9Q&RMDk$BvKWatuI{)y+*Qi}dkztHZ6I%NjC}2ydmY;R#U_qDvw(qp|Xun!Rk_ zjoH?`pH1GyqFW8xfQfxiR*UcN#wZm+rLxX&L;vy43a** zYpx$I9?FsU%!g5R95#7vs^QHdRTkZfrR_1~l`?1Z#N11Hu^IkOzqexq{OlVo1$*JK zhSGxo?*Inxs*LWuGK8UUuJidm=^3jWeJxG8drU{WtB3v#rKV?Fj+*$_ekVxKDp=@R z^ofi#6y^0jRaapBv>h>`tD>G2y^@*RMby1<)ZsZ8o0^tc$jX?Y6z343n=}fy$VG_ zN%vhrhVF#4?w)s#snyk95iVa`x+ta|xvT_;ncLz1ES`gN>`a9CBW^W1tCxee{*u0VNg^h#JGzR_2Zl3RZ&o!nD1H z^$D;zxf(Y`EZxN91tXin3R>Kz&?E-j62Y!vV6>Y`?3EUvCj z+MKF$Ki#a0wn5GMEMA3zt3T}~6;f$}oO^nRU$?KNEgS}@M7pFQ#Xx*5IxI1f6zWmH zj#eHX$-TX*9~`H`JD-@FnPC)<_KqP2rUS6Z9zxw|VPOH#pt`085Vgb4#uOk303o3Z zStzN1OCT;B?t#K#veAh=p4;5HiOi)7u;tppe- z_xSPk)4!W{-{_5e{rab2565Mp1Mhho6O1~aAyOG!oEMbY8BJAVH_GAEa-h$EoVfy^ zQM9w;?v7`)`Pt~%{O2=)!*qQjAbY?*htuxyKK$nnxX*(}S33YwiHY^zM2^*mmjM(P z!uZ6+5na1s)ZvVrKGM;^nS*+UUcxKp`SVMF<4T}58gKn~8;TV83qtJ62y}MiM{Ts{ z`u8fwDUqaJ0L|erWLu5v{JDN>+}1<612sd^(e3jutEx!Ty;fe0*#igS@Z)`?AzxSK z?WYsfRs?{;n$LFor(N2wHlP2U+L&%YZ6g<_7?S^v7N-OD1|&~6YS>V!P^{>@(L?{# zf4e2kCf7H7vIeo)J6W%A@4r!3xp9t@-_|CVi~RG|FEecWJ&*-;CYsHGx_PU9k!Xh= z4p=_303`0|=}9l?lW@A#6ptLIA@j}`f1Qudw-GIXmYT&VD8JC(p9wttnap{HUd-kC z>P}AlH=F-lg1UW{{U@he8+P!I66@X;WUpgLkcRK1Non`D7QrpU=#hk8rW?qKQq8r@ zDvI>`knqme-}v@fYMV%(ds|;SIo~GEAl&-sf3n>bJKA_8)b~=51{Qxtrh#9^g8Wq4mz(9b z{|(-mdL4}?<~F&+N;;E zUxy-rj3}a$vF7z_4p=0xE3C%eKCra5t_A{5#9>0#)AKd~75|yS4_;L7%E}6plvGYs z6h71uIy@=Ho?{Qt38SEZ1u%P?SptL)C@t>F$;ly66Op}^pB+TVqdT>EQec%tMMqCo zS>V{&**Q#9K7)N1fBWh8xx-U#Uf#l*8X!m#De|eIm#V6G&txGl^r7qa?!|mS`KVqt zqAek^R$%!ce2k2aKCHIHlknbRqri9l={b)1bzSk!~++(f+;^UOQV`GdH&+Ag^A(evJ;7z`8+5URz(kKdmx8 zKE5}a_b)j-92=;BJF@{oGAF}Gd{2M>T@oxbUj)G)%?dfUo_|Q^zjG%II0iQ`ApyVB zW=4{s(Is^_jd~&}PEXX>)Z{9j19SjctP-$b>=37xAI+XzLvJwHf6f7mbTE-{S235q z-y%7h-Sh1c-2D8|r{6J7oi{lI=OqW{Hm0j`A{dc?;Btu}sjFPfuKCkJ>js8Z_P1xx zrY>A(?4TH|3tYPP_N~oMVcywxawTwfOeAw1k>mwV7XTY7jmim$h*;A4xp{aB%FAPq z_mIBpG0x!9yUwmX_w- z8We0e^R-o`b)?0`GZ!9g>Y`NG&_uxYAu25`LanHvurLHjHJE)|?2wq)Se^U#?>al* zgc5yW@DTFReM3VPb8}|MAk>7|*f=->)Pztgc6E36_V*VyHD$pZ#3-=>v1!PsB+0-D z#Mkh!4rDG13&g^Z?;7N%_V#wD)DuQ{L|vY!b;p@)x{x;UTdLjr zEAMS~A^q{Z+}7p@Iz$G@I|}OR1Pu)h zPxAa*OyU@%)U2%7H#aw-E*6rOj$^__M}OcA*Vfk1nKCvOi9I?Gf(;~|69++omX0n` zfdwY#i?t98WQfDYLk#8;bAe01#X^?f2o~scb;2)Douku>WaxsiX+E#Et}<<#@KO= zYTk=*T&)Ju&{sZ=zi)dzp=ukJCc#SD;ljO?_=YspQvSa$H{I{c@eQo}DRdxtkfPC{8@Dp>UXCOQH&XO@ z0-NNj_`~>&#*ef7Rk_<~IWdZ_Pw$hYuS|IFp8Cn0Ye>l$ZuxYZ2n4xIM^wEmfpQ~CAu|g_NU@EiEwEtMvPe(oRgSK98EJ8?;RzssNY#&wC^4r z*Z8;aXf*t zS7aqOif#Ixdz_kym@}9b7;WCx(Jbd)yf&NMWMh$ANW?(C7bwXyQ1$vG?+gZtu8j|$ z|3wm{4zbVLb0C58<_x)vW>Hjpq{|5K+ly&Bz9CN@g8o+PsqZg0cDJyoKd%THbYo9@ zOnXX<)Fy;tY8|8(IlU};csOX{$!Hm6(-Mb{B7dTiEbvZT_`&{m zK&qv%hTj<3iMO=+K-vY~_`D1%M)7O9&<+uOq3zPR>(;TegB1a_<5XO^17=ll#9Te< zIeQ(t&t>fHcBi8k9EEOp`Mu1|m%DqAM@Lp?Tm19~>)NZu#lttk&^NgD==ed*d#8M} zUPqsk%$_HGEdwE&<0Zuq z&x$Lr_K*y?s91trOcjN@)HSc;KM-!6vVN~V=4@w?lV7~tA#d^xo0l}6P784+7k^4r zHAk_!L?B>gV8;7M)^F*_XY#u-471OQ>+r&ilr8N;_oEa$STO}{%0DGM;QM_8#jCwK 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%0D0hO<-Z72M;WmjCCgXVLicsTk)z~ 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 delta 79625 zcmXVW1zZ)+_cq-fmzM7CmhSHEi!{>xb!q9A?oJ75L_)f|K|mx0Nfm{=@Adb8pZ)C2 z?(FQ$?9A-UInO!k?HC0sm;eH(A%~5Cf#B)uqsyq~`AUou5#b*i{(tP7`b^e!( zkll1{{qG75e$v5DU7y!}Sn!xp*~Oi$gZCLhH8})H{Wq{?Ou%=Mz=-e{(q-dCm8023 z)MfKVMo0NnTqJ>9kqI?QFP-+!&NQ%xT88aZA;YdtoE57nYPR)eFuAE>wUpWMRYu_i zw+A#vPLQo))3Od7FG>WDY#V%;jYEgWjVHlWvW+aNb27%g!Q$cd*V+qnuk?o%lD7nP z+}BpR3Frqp40z&&ebFLF?9L}^{j1kQeftSSIs(TJm&-XEhP3q!#|6VC0d2FOY6gn@ zI<{C|W6ID;s0+@;(*T-D!Z7qCag;$p|G%O#HO*^7rz)$TzUl5ab)g(lNyO?eUI=LUV3hzPmw7a!P#8ie_v9c$+ z34A8A(msPQN7H0vAwI=p-Pcv9Rgk)-2uV639rPa$04i;eU297u)<=^re<`c?THx0p zz6Yujp2rCYgJuW@K!9HZ&Ge^mtn|M9mWZt-!=u`Wi$m1*{Iotal#LZ0B*t9uBn0Xp zqH>e-ZMwIp+p(g%JLJq>w!aLDlG^C9AfMS>M7kA2G$~lWGVelt=Ux@Ss@C?-oa)Ew zCDnWmvRR8X(w7ZKxfh|xqRqRHX|@peOp)#njK{3sdOaX~z$-bgUt8PBs9%lIyFPK! z?XX;u?Q9|*vN9VgM50($m2SHPUgJ$v?zT#Cml83lX0%^fSV#mWwnwjbUUNh4GKuao z&2PFd2`{dM4mJ@J+4@zCJw2A1;xaqC+J`PLZv3F)?KKVQ1k?ncnjQUYHbt6I zq7oI|xGjB8_O7fy=*Ky1itkLEWne!r7@A>DtG-j7*$MRzj}2i|Afhp&zc4iW zaKn5qp!a&boWkIL&|~YSulkIbiy^B;K^cxPLrCRr2Lsuo(@~>9ATN?)?41w@R=$Jb zN5Wn!f}kwOTJFDd>&KJg0l>a|pOA4@mE1!_r@~n*J^A$kEe|Yl^M=q(g0CeHMb3cE zO`7g^ThG8aVW|9@a{S*-N@*6}n zd`cnbppXe!3AA z8N!}$KtVN5h~^+&Mu>~~jW!h*kg1q~qiakqfs`YB}#3n+632!g!ho#^A4uf?=eJo8)VCx#2vQex7F zEPua_N->4uQ`zuHhqH2f{{9xEmtO6X{}N=)F{Vwrj+~trKJHRn!zY9UJ2r_V|&K)^VXYvG{7M|u$FXRyoM9i*1UZAIzFXgLPwhXt|6VNjnZOM}} zU3YyYRSqV7;&=kZH>=x$5gR9mRAUg>4iyA}cVN<$cGW7lJ{P$CwBA9v)cM$4zqwaD z3s_-Kc~HIZq*TykXhl&H%y(;V4@9R2-OfF4z;*h78ebO0knE>s_N|^=ZQX)xZhB_6 z+PeI|VDb@Y^4#9*aYylE!s<+>hHvXHh=1Fosin2LB{p$9P`@_TSqQ$G1gzS9`HL>V zmsk2f06eT)Z*V{rR`TCY6*-5@-$qX05`ZkRA57pp2Dn{_V*XZpZWjOVYOAePMGT}} zvG?|H*XS2f0mW6x3KVZk)}MdEfZf-rNw5#e(&ixT4CqThV-#Oz{wuB{LW*YN(E1+4 zqrHgrcYqZOg+*fwkBsW*e0DEaY5JedrPX~YnsnS-VHA}(S zoxTTU&prolUpe8;A#Z)xTn6kmo&kT*fzqmt z8B+AOa^MNy*P|l<-W&yZzl!OXZp?tf&Yh(PtPeJ%V>mMG6mRqo04mzRx|+7NG(FaEfDHukM%@76zQLJihIVYj|u=zU3iXAcNO0Z;ggERUHi3yp%rqY@Z5Ube8g1+mO^g~7XCv(~diysH5YM^W7= z&j2ai%T8X5JM++OvQv1yvs2)Y2~dzgTP?ax8Y3>}!=nvj3k)pjE#;pEqkAWA*<12qbi zr3og(W@T1@Ud7$?Q0mv;^dhVH@?6Hwh6|>fmLW3NY@?snR$x>PQnz0*7gA?+%E^g7 z0(eMRhjOThWi99Hpi$8UY#ykeqxl2Sm}yxUtpLW$zkh-vkHAZ#)tEn^fs!5R?|V3e zlsnj))JhYW5RDd0afYHNbV!=f4Qk67T2PPg!P7p*smGEC=PT|LFhV!0`VM@{R)x6P zxP5>2+xfcTgD0nw1Zd;tU@-@*YPxLuga@c9fF%klkJ-@Lax6edUG3#!!ZgmCmo3dX z;MZDq3tALsI|Sl^7Xq(H*^=H!yOba8TV<4zxlEw{d~gjr0(&qX_#=LofG0#a|67Ka zL!ahr@p%gDxEKW+VvV&gNTGV)9^?!uOF0c_doyEW3q?eN6H-0)0HW z2rdK$Tls8-c2^}slu|iyw76uUa4(87=pY%}r(C(ZGA5*nWZtb)1OqjcG>RG`BJM23 zTpc(Z)ES@yg?zHPx3uHvWMKFt=$lTEfvE_IOxFZx+k)qU8i*ePxbXVBMZn<8p>ELR z8%Uw$(2d(!=38&U8BMmRgU>8eazlx#*aPwbCF}->#y?zSnrt~b^iFw zq4y(T`R;Fg$oESYsx$lDa}fw8>9WYDvxPZEn*)Qh36B=n_Fi0L7iHKNw1SU?po}}; z)CXV@gzt%eK{?)~1+ef_R~fi2{@-ii4^AW}pg2B7M@x`#;wsW8VYFEpNL=~d)8Dw9 ziu0Zpeb%uHZ--@6;@5-ad{CC301xkOxMFs1U-sfxT$TL88oF^ z7nnOI2p|Qm@`9wR*{)M#Qi$FNB?Q*uzz#+hne+ZwLSiblOn!FaqZ~Rd$pSL|*E33| z3d+oW^HyD@NmJEwJ^^a@D4vF-*PIbKVY2-vN@_buC@!4^p^GVXVjM+L)Y-U>{K51Y zgVc(Ell+wrG5NSR4x)+@De0IuwE|lmbvhKCO}AGlxW|+X<8kOK%Qy;WF%5wgK;)V+ zg4u0lvopM(68z&*f0$18Ewz`}U~P3}LZ>yKzm&qg($uhFbb6WkocTdsu@firGF72F zUpNAmE;6DspI#1yfdfa9=IDZBN^2UE74%enQYgBL*LN)h*A`Qx`y0!6Hc8-BgFchw)k6+|a6LWiIyZNqDj)oR;h7F5n{ z7L>w3@yVKzBIU?UWXzNihZhAQ3ERf}dUzO%F_AQLa>j5hKj!3jLQFGx5{?sJ298Zl zd~u_oQJF?2oEqYcztpz%r)f`8euyHi_=Sl21QWa5JbAuzkfD)^FWP zz^o=vIAq;Iz*5ead&-b!Dm#pGi^d3HOZ~Vnq=crMrCK&K7(uGAl6L5Vj*U5`^&{5m z2l!gOOD&DLn&YD);kPP89V@K;;Q>CY8165_eq0uxLalr(HV8Wr29tsp5Yb)+?KtD= z6WnF$BSqT3(bpb?D+l3&0L|TAL2gMF5dq0vCX(F$h5RygOkRm!JNO7>*qQ#0b@J^T z265wX9CUDpCCbF=L%2TCjN9@MLmXP?_@mQX1vTf>am-HKA-(3O;%&B0@7OBYm?}Ap z>gkl|;m43k$m^6Y-=EKnj?J7 zYLu@l)hS32y?>Xl*i+v)+_#}-@fn5aB4)CLE00I1Kp51AL|j2qFgO4(G%?3}lzTV8FK1HU>3fnSQJEi3cI3?2p*;|;N( z2TFv(1c_a)p7)SaR$>11H=mCrT)NCEa5?ivom&AA(~+`0{MK>n6CKsp8iAuo&lE@Q zt_qnNjO3B^^b7NjP|kWQfcNGDR|msW*Cs*~SC;P+!XYc_h>mLv%E>S<$+iFPPjt*$ zXpG{S^p^UiXQ+n7j1JaGXD>Beufc7j(?LJ9{2g=K>-iUX%;WVW+SPZ2n@sbjwClb8 z|5Vg~#vQ*a4@~$#@AY;4z<|o_VVn1yS(5B*65eI@UP2TP&r(u0a5>_=zhC?eE6spw zm2%9j?+WJnBP1o^)2NBG2z%_K3Hq={;kTGnSF{NaXl7VNqDv9!%32J)8o|>#(Gd;kYQNU)%1Mw(G=&eB=J zZPM1I_7k*qL1}J+FFV79+_%S++hqD^Qn8;VQLj=WGP9a`>(mYz7dsjWgG#&f8O#GR z_Cub)>8fhJAQ%|v!$dDiAAGlEb-I+cKMl1|DO!aLeIx<$Ko<&fBZeG z>VSP1YS*ZgL4T&d=p~ZTw5X|KhGT5piuChM4|n!QOFfn>Cd))0WP;V@I z!hTenM8qv!&~OaPijfmi|ACxh3V3x)J`Am6EB~77{T;eWM00>gA~s!W@|#VL8*9S; z6oc=L=@Q$dM4sy0A{UuPSea{nK7D?<(`jTCG%kUQpW2Z>4<}~mmctc6-OKQ4U$v|T z7e#Yu2x7KndKk@!mvDVEMA|VQeiN0&Gj&=gKQ>RO?X*aY#Hkt^OE8434{TLmbp~n4 z;c--_Az}Y7U~d^j!nTUgB4RSbVk;NRsLPcHC(;$1SNS8nGwkAO$Uo9?c(l+Y^AB&0 zzCv&&A}cLJD!g?XCgu>lp7?!$Dv|;nLc@HVr=u=4EJLzliS@x?dp}E}r?8P?C+B>X>FNyh1zX_jAF$+zhqP}nXU)D zt!VM1ZPLbxcK*D7>SB+GrhV^r1vwkQ`yF#YfibXu+|jpI^!(#sWU0rZ5)@-2_@~kw z;rpaNIWbVoyg0%$t@|Ar&o7W%2URU^78IJz!Wm!Zgp~7a0(HfF-c$3ZPEaAoDUynk z#re}5@d+v@?rqw4MyE9X2{I`CSNEi%#?8bBpY(%A{aLRupLDxFuC4Mpxl;?9Niz^d zM_T$wKJNnsBy#3B8@voTG`u*`)YTy_$O{TpSo(iZBg08k^?Yu#iI5(9de_d07Se+L zVF*@c>(WLefS$@u%JrP}rnB@hMN_W0^m{M~nvRZ?G-|r{Eok%h)1sY1c?&;Fc^!s^ zP1yvI1HA@>@v~m`CwW5VW#dHZV85`N;bjFh%AlnC1%T|v-i<-UmWL$S;}fQ2%&s%(?e@jydrl24?(<(fI8 z^**U*i!D$=?TsYF_MBY~TUsw1p~p6!T>*=Yaca5&N2070sbl4QF?h(jbOysuhk|^C z?i&s@N4P=cOe~(hl?jxwL1LX0pQNV8Xp^~qeK|s`DRg9OkUYL-yOrk@Ks9@iDdFS! zv=5{J12|1r0XPo>N$}|@pW{u#G*Lh2KT6n`Ua~sDIN?%SHa`KyPwfKPBVSJKndOV`_Z@mQi|!pe;9u?tEs ztoaL{k5PD7bv@u6akY_{>hj0@3s51HiL|{UpXoc^prVVEB67CP0SKf9&Q?mw3QETQ z?>UwEm0)EH`p!ltz2#$rs0*t9S4V2iKk&o9e+sOa_@A;UmmcN!(RgOQlLGHd22GG! zU*mWn1*|t3UopRSFE}_%n)6a^+RiscKs?kor1%z-hlcQTsw19rE=?XWAC!nTrXeP$ zj^*nB@E7DNKGGv&s}5u0tg#ij{%)JvM_{eO)z2jeMg;y+LO~%&L=7&B>7{ z649+Rb#VG7UHD2#&T?8|sfVjOGtI99l!+#%prH6hD})VwAt>b-oqMLIj3a21#qUr( zgZIjn?E`eof+GPfqev^^%pGTkN&yDhR*EzWpAq zy0zQukuaim;kk(}DKio6=r?L!^obyGMIo>xVj6Z2>PNZU2vo(B2nC?}byqB9F~O#;zW4mKV+C z1((E*b|$k%_BEYch?VhMg~LjJ8}gCz&%%!ba{u;O*i%03jtjti5?$oH+x2sx`fZvv zrb;yuNy{@pOl&KU#3(^!wBp_~;tQ#-Ajfuqs>kvZuVGm*;)oQaH*@v}CUW-wI|38` z9kt9MgcAgG^6^YBN|7;*6F#Xf!^PPnE^4bvicTmCMehVTW#?FSlA_XPE@QTs1NFE! zv`6~AEimYqTnt&jVB$Wij%nog*8T9}w)d9MGCldW$3XT4c?o9f zJO)Zx#g}J zy13ZjSBW4QEf;4>ZvGrp2q+^fPx`IyaJ(0v%rV~VW|>d82x zi^;iJeQlH2Xvgen#1jFx!#n`dRGdYTKp3E~=7=fom_|23ey@U=C6oY1Qrj|S59=}N zydVSRkAbTUCv`<>JutXB`U-YY{Up=SN272iqax?43O?}ui^^el=X=heaL&hG(fpvJ z&TdAFHS>>m%?1;~BA)T{f>qKMWiQD)A2A}uq+QI*Ngx=9PXHsv;eBQN5|UhDv5=l3 z!N{W-U0h~K$#2sgP}A)ocSf)&##ey*>RbDi`3h*mEP&)~y*|pG{6>x!AG1d24{EE$ z+vQ9aM^WtK0j&RaH{itQ&sXst#W5RAS!FAGyCHrLLg0O+IW&3`z`2o zxZ+WY{RVjH-v|8cnnijrW+H9Pyc>(q>);WlSqP}mf#BmZLZ6UNjlSSJui#V0ctE^0bRJIh$NpL-s%Wz0k zABj^sQL4-7w!e?f$jbBayQPPc$)W^BQgo4v1d#FScSt)5cscXht5I-0Jm{ za#HuF>(H>@T0%PSjpMzbK)!(E6sBPa%Mp>gLEHH!GeshSISey($u@OT5DrY#I z0XUt83{B{IbePk#*Ein?PnGl4g?XHzC{s06EX1o48V-^!gv0G_aJ`0a`)9~^kWN{t z^NC+r&wq?zTrj$I$y9aBP#|em({zGidDG1=J!Dn*`KYEHHMyEF1|bSZ+;HhPcY5{P z7fXWNl~L^&ln6~^jm%RMCJm%fF|8XE0Jak^TzNjj!Bx_WNp4!Ni@3#A9>d|#7RjPb zBXyRKV&nTnpRq4XK!7I8gj0i{dn3Ox#AqQamt$zJw(#rZg%@1{i|y}>ekhx@0Cz)h zWFcci*7YF*Ey}(;884f&-7o|6&YdEj&tui9G}*q>3zrpBK zqe=?pDn!-nJUy;&M(^vN&k?oxrT_ol`xA^ zYM#sSA2ebZ!5+dVkp2ynK*sTNQ&h?OW8XjFi=$%rE{1oBNuixt^0O%=qn?o?W~=PD zc}rvOYsk&|%MfP+kI|W%Z}uI!LQIb36rH*dieY;;P9~LA=7e*NzObFJqugKT0Y6Yp z)WVzr{nTE^F~v3PVGXEME3%p}fyN&qs0^aW z!-Ax{dyohAmqSoQNs?@Nk>nIpCht zc)8y$fZ$sf)+hG`aiJ8*K2X08OnQnYuP}+ofgT2VG*gpz z{A2_^x}R0@YU#%|X!ytKqSh#+&A9V6d?vN?D2JEe25CmM*hYh*m>TxtR*I=5Gk^nw zXw2D)z)-m-BDIo+8_!Ph`RDo;gqCF3o>6;S2}-4G>Q{u)#gv2tIg8?R0j6B;vK9^IzkSk+4frFf9usft)Z6=YMi z$Q)h%J;|lu<`%Jv4!$0U0v`u>6cVA!qhuHpt!L$lNv*4X>C|u|*R=ieX!;3|3H||+ z$;A_!o)GnB?BW_JX*Q9?Nno7M&6BoIZyvEtewHU{!oVtBV2R11*^fzUlf2kIB=%&I z;j<}6RLs{4rpc8V%Ombvsee9D?-G#VGPQqm+bXTIjpbP+$=}z2_i^h9}bW(Wn~c^wU9b$WMhIy5FzHJ zWyl7#x=V`a0#lS(CG63v0`y-{XhfY$2n$o=$*Y+bA2A4{T@pF;9o)k?4jliPp$*q! zqY+{NjijunHcacXv;M1I_bH?Z7GBzlH=8JE0dgdD^p3c!=qR!ngHyZ(C96vkUqY)J$5u zYfF*Ua8xQecRCzCsCEIS?F4T@VYoYUy*oSL)=8`H*HS+7;mxK{6dHsN4N=K4IYyCE zKdxIA-j2^HNEC6w>~7S9Cf3rYPUJpG;RvplFXbGNeG%B}gVuNp>?a2C8p&L6~!flew%3+q|{38}XA&E}B;k%$=mYE|RqAcv#F9K6*d9oA(O&)O^%8;caV?5E`HB-|_?QTV)#PZx9)$Sm{pXqR=p7;g!XbA-{+l zOuU`c$3P)*F@Vg;c41IHBErrAvmrD;)J)39bx2|Ce=19nYOkr3{f%Ko?b_*ZPQkOjnQv z+pd}d+fEQdk^glQONT6fOw&YNiRJv#v{5YsjhJ6kE#v6UO8FQ#(s^T$Mo!Qc^)Wn+ zjsQ+jdAlM1O7?IAV@lH*5-?@Gk1??e1&#db+S-+hU2Cfw1+#h-1*9A*IZ2$FawSsA z^J=MI2;`d@5h|eca(G%A`jwg-gS;d$%s+`0%t#(UUSDe`*6iBvo@yuka2JNRYY?$r z+oQ1>q+m6?U&(;S0Zmt^)33d3>c@;uyfZN4pYE$$8jpFzkeeoJXf4mIwkg(YSxY`O zXUtVt#6*$bN(d=-XpHHFI-^W6UJ@ynvPj9jcIt*MBJBL1cZJTQV-9oNRtDVG&_j)~ zCFXk!cYDz-%&%5Ndwu%&tR{sJ?>>}!N6&CC<(n{A5rP7BXuwg*ze`^jz3@^y@Ze3kz;e)4y1X)-HvUM1I~oQ}gu%xG)<92Y)`eXU4m( z7+6C<+aIil5qE>z2orRDr%t0CAQI-gP(bu-!aXU+tEcnyR+FuJbus8$lK{aF^sXhK zvxsvMFv|7d)MSDUWWoIL{|wAs{;XSrHDo~xdK=yidG#O^=`QKPVS2lv@c^uBp}VSpzB zCQS8booQjfS^+c%aGx&-Pi<<-faF-%1I3?phJ^vV2$(HcEdTfv5^G<%4Apv$)9z-QyYac;6G*X59YHQ_Nh(5 z;s8$ta2XBrN4;-mF9mj^VGk(x&3Ow0+2Jt%EZ76lpLN28f!J_Z2a$P0P#hh;5h}cI zB*1xv)gCb_1L0qI%Qe-Y5y=r)qVLZ$#}c!+hqAdtrFmfe$0jBd^v(O1daMLU)9sx% z{For|Pva4}Ywn$tyAc@`p3npv{Ek3$xkN=5n32dMD924y1saJ*)_Nh-J(k^;h1Lq- zuX5&Y-6&TNCO-j@A_Cf&x1mcrE$RMgbOX^9?rRfeXeop%mFY%8LbrgHBqKO4LS@B)t-BWo3mV zh0V28w`frZN>wTZZXs==u{}4>erL-BD+c4AiiL;`=>}MF@lbD@D=-T%k8Byhw+cu- zEb1N6DYCE|Do!~nYI`ldQOx0(SGj1-wz403Sip#s*>M4k zn(svLO`?1;-0Qw1F-dn1&|)E@D3iKbxALo>i&JDQ0$JrF;{0BACImG&k&I=)WN@p8 zps>Q~`cMILCvq~IYa9P2geKBb5Uifg%piV+`K#FW;zesGDAw-Jd-mj{@Xr8J7Hb<$ zfQ?~4Lrh?Q+W|YkzWf~UpZj|)0Ni#)Jpx5*FUE8`8U0Ueex-S+oNLcq5a2pL;3!6I z8|mazT^v4vlVeS@V6*7@t4t%xo%eA*JsWXZB~q3o>>}WYv)l3wsb+;&+|3H@<`*(} z`L4G~P&^RdrI7=N-&Ki!| z{3vyMSx+ASn@qd5`tab@0`>=u3== zx>R`DEq*?pcvYU^2&SvyW3}%lF3BgJ<|^AL{4=|_Ir^HHETnq7m*ncCcI>fBfVR=Q z(}6Min)>_%9rTHFiX(vWxQ5Cn1nsf#kN?z}nt_3k$Wd1H){5cN>k5N{{Dfeu^*xT} zi>Y?=m}qOuIZR3gXz*iHU=|ivEUOP@s&Q8*k0Z5xY z@l=nl`zXtCaf#NtLR47ayIq-20q-)_si>4d(O}i9(2NbhdVzxNjVXBz4||*PBc`(i z6C$C~JP8`zepNJ^Qx+?Ohw1%-Tq>0!9Rf1JwLGU=xb+}?EXL2&A$fEaDZ+|z?CKZX z)l6zp@#Lzftw`f)spyCLmsP{QFG#|73 z^~%4-(?Qb~ZIm_!n~Pe00Pk0|e-FH;&(SwTnGia<$1xuTJ)MP}wMG$-gq*dMo==24 ze8C4CaV;a0r$r_*bkY_3__Eq3-h}k6B2XnUT>m!j71i+by1>!aU(cI?7aT}{y3wC` zAqx+1o&U(t-|9w&^7$8Z-|sUjf&%Qzxy`^IKugQts@C5n5aq$9YO$2r^y$1(5P4jcENzJUHYL2n{(j@g??e!KYvqrWjq1e)d?s&0l&-Uy@ z_d*+P9G68qJjfbpYX8d5gU|k=0&LtWUxB&tnRT$QjyP3twcmru&VVG#os?hYun0Kd zNmr;2!ky19fJ=E;$#O@(+%stMMUS+o+uvV2?QLbE#SYx%>@u*Xf9R9wafftyQP7ty z4qnae&5r@=p}P=`f~&#H(3L}x9i9%e0Q>Ib!~mF1S*xVl$;A3}tA=5qbIqMiv+06| zg5tKdG1u9eT_ia+z=s&K-1HSrmqUu@K9mYSP_U=*<>}c zoQv+&E0REV2#0#KK7V=9c_{IcnH60}3@Ey~b&jl~L)aZhOx-+su;~){xuRN_y10l% zQY#?;)RIM<`r~qR&BVX;ZZt++sgUl*G$+2#0LlL0?VUY}bwi5WPw7_NiHEz> zc6j#re!ip|`awkY^TAV$07b4vm5}wHT~5aMDfI2`Ws2I2!_td>vCcSRW)}YWUG|9Yo`L;EM8s7rVp7sd zUTp=W)de1LE*^H(v{w3wKch|MdDxT+_x)_snKSq*;)sj!>ZFkZ-M)?e%nHeWqDW?w zZ#RUy#P(xWfe$%_MqI(SCLk@oq4%- z2D@nfmV%m+?_9wLtjAMTc8F1GpmML##|jTdkoJeWhWKOf?!zG{vG-sv0BFmXsPb{Z zK$Bk(g;meLk@H#MK@Ff)VH{Frz0w8OgyK4nwx72>3lwiwx3sh)kr)&$h0hJ(ME+&q z*C%iaYB9AqP|V)c1)9f58JNGef3*t+_xJGUl^kCMJuu|=jfUm-37moA&hI_gPX_Sv zGkT{V&pNwTLCeIz{zB~5(8S&gvOPky z9YM4mT|Sf!gVkKw4%uDF{VlpL1>Q7_f7SH8pp;85%HKRC$t$t(4nu!jrr`2&+dAUJ zk6I+CubiwI?8nwk0*U>Lf&w#lYidlK{X)sDR;<^8OqfQ7bEz5#-4g-9*u&4f?-ibW zMQT_hT{>hV>d1FTa)ul0Jubpt1l0 zqOpw;w1~))1()rMK4#I9c&t6&i7`Juuh3yT)cF-mXK7QuKS_;w`x4mKB4mjskL(z_ zaLb59ta84(mZJ-Xnrs6*a^-w)?Ziw{yYGTGMTKja=(~q&X889G0+L(buC1V&MI$kI zhIRC$LyGxBzYt?ISx4^b6P@*(3ba#?wjjvdDPqj3W2`fqMx)fk6$#UnkPPTuzks|+ ze;I;3G}kg{{_d>h{okP_Cotc zrZ1fy_J+^EUbIf8$P{;)`C@mC>@$7{r~I^+pJ2o}$^#chHmOL*7UX))kaTxmF(>vH z`GOd(2vL$0qVxF_b`B29cY)k(&IGxilQr%tY*I4u9!z^$(@Qa?7qOhs1Oox|_mE?^ zu7>X++p}yp$w}!zq%dAT-?&0JKpv}AhG*$Y<3)mcvc1LKVbpWpU>IOV5KZ)q_pT{b z@UsIEXW3y?lYesOJlALwitvmnT3u)P6#CULPW>;QYKm2!GrBC2DCjDHCJ;4&8DWK2 zbqxKEJUWVB8G_J3$U|kt0gx4bpXe!0kQC_UPfki?mdFF}ztw&*JkJU!wEZPiucc1I zC|p&9*}t%qfe?adlDO!fQGk~Zft{93*Y>G zxv2KfpH0Ka8}4-9U`XqB&-^}9QO=vbj;dG zc&k$RTyD<*V$s1M6Pj(e)TPaMwW8br7{;{ zGk>AcIg^|Zzeip^pNc;k_e>I~b7Eq`hFHtCMi^cxP=%CP#eWeBkLIVaTJDZ&Gxy6b z7)bS#(#5MdPKu`t5cBUj)?KmPeB6~|6r59+)hnk2ytEkEgo9H3k~r;ykEdHH`%yF$ z8@#u!4#!x%IZVHdmr8KV?VihA7ifAqpM;9=)S=U?Z)Zle=klKHYpc#|r&E4TnQc-a z(k^!Ol@WY6t*rM~Bd3jOJnuF=-vDl3lkViur_9z4o4Dz}p#Hw;Lh_YONX9#i)Fr{s zUw6R;i1R0jg1udyM$c?`+!)ES3$Ajc(IlYJo=c{E;Zra?YUU3mWlJFrO#D2I)tvpV z!tA9_0wn+VIQy~1Oa-N0L(u7AIJxqGCYk9s!O))7ygBpbnzCX7=b)Q6%AdxRkutIW z{L;6}5%&iF8_=WW;l8jXWe&iQFzy-i-o0DL0EQ0phG+|u4bH8kr9`YebvA0eH1Jc1 zf-_=De`B2CPd9y>nQxfo*2Q;W`>V#M{3bO%MYU}xh;@EHzjM={q2xb4I-26rS;z9l zgXYtUCfUDM7Ce%Dd0&}7j4r9?E}VV|nMR;SWL#{}MO!D^?(`HSx8e5xZa|%Ovw;1o zX9_Sc$Ox0djUkvitc>u~-Ce1BBc9%>Fz1F`(a5L_sT1mW$y=tPXE1p@X!2Hz;9Bju zg0#1Y_&&x+Q^UT#_0iad;2R&gEV~DBg8q?l)E~bzvUf#fj5_E|zCo|GL|B4<++uUs z4WWESL^v-#5nB3>d4fIaGF;TfYGvj&EbIVao3WK|qhxWAw*7{>&poE5XE7pKvM=Vf z)Y}rOc(&sj_$%^=!oyWGF6e5QP0X#T`$F<+;bnM#3knpc_p;>{NiB$ToKOFY7*A9R zlI>6V>t`V}rIgY~0ZE;DoN+M7tjfJ2Qq?2itdPbbQs+_Yy3=aTaZ(rL>L~dLhwK@^t0 z81jRRP7*CI9^5um+LZj9S%B+GF`7wbt`Q~Vc#laE=ZIa3>!k&%_~BTI405inMF+Rq zVFcT!FA@6TS1vTk8+6h77-_dPU1b@#B}!CY>Ms?#)7UBvU~x)jBm44}*&LRLjazyt zSFckTnuQ!#b8m@OA7zZv_fv7jmGX=Bq|p2V@}t&pt_U;4qb6Lx`vQzppHLlk%9m;4 zV(ZhxY(20N7R_P%9xhq*F1|6HuwlR54l;0meeP4PtUT3fL zfL^5y`4K}he!0?e&y%)*&=y}!{e}~rs!6hW{SM1mTfF|1R*N$zA-F=~>?KJv?5nkB zv}m)sXi!;Q`?uKT6|;ypRE9!)?Qjd%(Dn zCiC!0p7U%u{|y52c0Agq_|k`%MBU%)Ia?G>dBuEM5>YA?y`4QWjjhKU>4!yO8$Qn+ z@?0J0@hNh6ZyV~WfYjijj~yS*=@uNiPa{sLql0jEjyZoYs87D1C z>1rL5j6))sNT^zQ$xGnkK9SK8(U0AQEJ?8X>tzuWmIsDetM-jRErIx@+u_h9ZbU{& zVV}P3C@LE1BoUW=T9|6l>)UK3tSQflO4E)?;_3`5YH!<~0)WmJE8Hb@DeV7|c9ubL zL|vH1-QC?GI0Oi8!5xCTyF(zM@!&QDch}$=faQ?zBzMO!w`3-t)XwQ=syB%#cnv{lmzJjn(6((5~sgXO1OLKP^&ml+h*Qj-h>C z^2gckz-^~_jq%$5!|}rlb{(_&1i8!}bBUL4RHgTW0*9UJ*4+Q>ANAlg252TS4<3Gg zs1wJsR4^iY+WA$lT|zbNTX?L2h^IuT=Cx6T*y`s%K!xdy?6XRUhrrb=P6LrBf%61Y zD7(|l2Mgio7AnV)HZ__&r#jn`#wVj67@iywe0*Hj=E=I7v}d+r7ML!3dSYtUEt!?= zg-D(dA|W{V)y3=;`fPd-(wRZ^dnCQkvDIYTj$ejZ__x|S z13#NY>2HABa<{$n;Igjiwng9*k%X1Rg*l?{@grI)jDxrRbqlkcya8xTXo6$;a9 z$gxD@3ZI4~Aa3U2+--9UY`$gFFd8+VoZCk`r znC6%ZYhz|#25W}!t6XZrNqZJ@&)!}}7xE9w)u%g4{vW5XG*#SIe+5LRQgc~rD2p!3 zbY(<62l#ty<}p4*G0JKTcU%ufpwnvn)`;xou>6jUEcez-OYtI=;&?>#O0B^Nf4bxE z+X~Z0jn)LFej~XMF=7wL$PzQ8^^DNpEDh|%2OX76BL$;`e}?9yg4E1MCHt01zRRUP zpZuD_svJ=f%tS2hQE9~U#twN+ssdmA=?RiwnmAxuvy;y`)v?Ph{Z3j4!2t*6kQfIS#S`sroS_psgE^8huy>MGWNa&19wo%>p9&O4+ z{5v&Hdi;8-_*qc1Y@(UpgYUNjWgIMytkvqUryQ)iKc+6Dx0(1>Fx@>cs$b$N+myU` z^$|$BNnCrSm;d`@l@)<~YefTgUKAHSqCs4ialM{WQLsElM`j$`IG8vgDfJDNh+%=o z{H>T&{qu>8$!=6H<&xPbv90T?`>q(^!X zzU?a4rForh>Ug9=^m5=?>W1f#c{VA9*Ng|kJ?HA#Ls{9F*WZ3}tIRcn*xwQ8S}*@_ z^Q1X*P~N3dBm8;VHnGM*yFkrM$_d2PZm+EFd`M7w)r!}yf1H)z{^1DSF12q zR^vF)d(ra2)Sl$-`_Ytl zJ4atf(UqOpK^y*Qvx=V%505cvSd2fQ{&ZG^kpxSglY7!8!X-&~-T~e9Cut>x%QGFN zqnb03J*FW)2Tg{AYDFU7->ql8$LSnxIO;{4ILi-(mP&Y_NPxhDkVlQKTGEH4`5fhiqHzbsk$`I%l3)X z0*&xBR0GtRh-q^NW4!0(XxNKRCIy2W>tz#u;}8kv6$!ZGXOW9-l^Cuqa~4=WzF;0o zAyn|W`z~_n=E=&{72%<__=?LIcv%yi_!1f4XY*;J1jTwVdV@WZi%aAJP_U zYtvV{hrI914jBPz1Nn9}FYClu*jrqy&qyMIz)RE}ozU#+wZ70Ha*Xg#{eWc5?AwEv z5oqcjwwYj+!SmC>A+2{lPZdq1EY49WluX&eM>ZwU_kDvtc)jgWa*-Sp_&b!nktLAT znTpy*$$S=e%zCyEEM_|WeNRo+a{b8_-bwaDN7*oConTv{SMTS*U8|wh2{*s9m03_iT0MVI3m7P^sh!_ zisGD9`vqW;PdAaE#rx)>Ih2RIiAKE}E_RA|%>ycGlINwxDrrA{LsSsw+U1AD_eqUW=IMEFPNESrKC+!dNN6@{b#Qnf={WW6KOpUW(ov;=gl^(F zpjI2Dlw(1IGw!Fd-?xRW+tb66;4O2otAJCbLZT)7R%rxk~Cs z7s;Nr68i|zP0}m7Ojk#75DmEeNvChNOBNeQ}a2pwD|j}K>i=vaY|QzQI*TVI;}(^cASE=6jvW2JNy?fL!JCyebb3M*z>osn<7 z)24#M(emuLL&pr76K{NNG_9W6Eco?`D;YwhPs&bSDE zp%}3wkfOFiaoLX?iaJ$=i3)uCTo%aaC1))2EIVp0cZRgSWInK(QsvmWzk~!u7s+V& zYpWjF*frwfn27bq4a@OHHP$rUqirm$ZhzrurgFsywLedfY>;g!e)6}Zq(3)(dTv-K zhe%U-ngz;=QnqhX0isIFe~Zjln>lWgs!}&sIW>ptgrCXv{KQvC_~lw1ouNGzRF~*Z zH8uJeKz3Cnjz{bMiZ`(|XEw;79Nx^L{O-w(ncn5FwDB0|f z>@YCPOa^QPXJ09mUzPGBP=sLceA7zE%X~QyA(8qnPy7QJ+TuG`YMRZ7>rVP%{IleN zhXfI2OQ){-U>Stp{&%8;p=q$@ZzPYxOqx`! zl6Y{u6xeJN)u;zV3|z&Y$>GAr|EL9}ieR~9djfOq8F6{_DS*+D8WFUmLrGnj71yw?ph>AJOxT_LLp0+rx@qZ)#>OQlMCo_B6mONk;3@ zZTOvs&pi(a!PfX2pm3BxA$n|$nOH^`Vg$MN zBtu`~1}!iHDCJ)<@P?xAZCS#t3ts8RX7yK7 zvi%WWoDlb|-Od!_^I0CkFmqU5u;r)}ZDPCC-&ecVE{@Tls*arqDak_M64Bn#t?=x` z0gJw36r0aAaN<8O)_m}r)q4}?*})p@(npb7f2I)mFo4G_lC5qmmZ`AgoJvi`X7e-f z8D)zj5E0sWWQ#uW@JYmjMhf$p%394E)`rqk>R&kpSl>G#DdHZo5jCV{`yiJvy&$LjZ# ze^ z}E=wL#v`Rh) z6sak%eYY|dXBc`BWnU!Q#ARXA52L5982=nNrJ>6;z24zk^dW7xAN@7$jinSvKH}sB zeNV3hfe+(zNiGldqYVo}!FToIIT&qY+Oh%8vHxWQ9!x<%KxoPv`OowJe5C(xuz-qy zfQW$f4=kwi-!}Ti|D7|~T)Co#gbuxU+o5%gj$rR)$7^rnj|88)4)$e|6Ac+23c%c_ zIMGnxp#!W5YK7K}fS?3B8s|iZ6ABS_&0v`m9BA+rA*jQ2p*b+%;YXPL1Sc9MJbVcY zhg#tXLj*J!6BJ^@!%>(BGy@Ji41i6IaiZhG!_zPrIfFH%i z2-wK%ya7=sz|^s7CByN^!it&{r|XQu)?XS*g2MW`I93h9R~eHF6e~9X?i-Sr$r!C%SprRcf8_)rE>mtp*=Q6ce_0@;kHdoZ$#~AM@jPJzW?4&E$Z6gZ zb=kJ;v4%?kLvdEuEyx(SdVD97tmNtu_|pS3oTsE_iE_(qbz(;yv|70%2HzAE^)1vEjl7*_A0%$P8_f? zOBZZ3?7{L9|8NbAGE(J9y9}j&@@SOt7_D@E>l{Q*>}QXoQ;Lx~Giy0}{KJuB zRaLTxm5tv@PRh&sVi-GbVX~zh4j~{J1EoQGN?5uWTKzA4h9{vANdOPPH=ZxjRI^)Ned4;zMt>4n^s2`4B02h30Ab_MCBu2M+sm zdOEE=6|li$Jsr9Aqoa!&d%O|P^W`(yZp}}8-EiWCT1_kpRB$BMwfJL;Hcj=d-E&h} zR+Tgsm(8wD{~u&7m`xtQwi(YpJL^7s$Bxei^U9{na2qn2Zb)jw=T8-8gzO$(E>Rn+ zyGME9jRY87Pu~Wvt^|L+iVMhRi7=ySiUIqEGvE{!DYuUc>te)CdvUS0YE$wZF&Q@8 z`>rv(1}_R5vO`F)Ni4K_DtUC{BobJqQ%eXsDnCQ;#!LKZK3yP=t7$Im?kl09<^62k zLFOjUNp7sIst}f4yqUn~(P~Gvo`nxyqEsP1H?zVd<7Z&solL%%Fy?V|p z(Y4__P#*(e#zq4{K~$k6ZkGp8mHVC^<^F5j0~qn3t$5P??Z}*F#Jsp@!3+zM2 z6QwAVoBip8D+tQ0?(oQFfL{YgJr+FLo_KS2`~_2(ucGgk9Hz!8HQbZ!cnWeWc!U?p zC=-PA$oj`Aj+wMGAv8;R0%lM3JrWL`u=Cun3m`254USiX;A**GHa{z@xqQkj2Lx{Z z-hkO`iud3LZq;|^7_&dEU~^Q2_kiYc2Y?siWn}a?)u?Lu68gj zS1&9qH34a?#`!K(c=o3vsChvj>3H^`y)&7wk@8oB9*#>p=P+?&H%;q4NREhL3e@bE z1BPx{H7SQ2t#jljI2QZCv9&nLv5)jfMubFDm~qBK~?r zrFh_{uz&R~pxG3*QAmpshtXgI%uzkRzM|2#+|i5nn};B1n|}WF;ddF6=A!V+2W{R) zX^L&s{9?ChulNRfCZ1o%G6eTB`0u(Y)WG$sie7L4X87kL6E7w}YZ{*kLM8nzuk+eW zK81W7&Y2V(Sy^XN5TRWr2&k=+XtgfROOUwj_5Kc|CF;XBhwjZmI9K-Gg`g zCeX(lFN(G4DgJ;GaD+}e3O2m+*`Lm zD_>n3NUp{Mm~LHzzKNJU5W7)-d-J&>Ncqz68uV+`bOGZAX2$6nAHdE(jt?LgNV!?4 zRu4(ZegY7+(M_bnd`jY+@5+&NS{{iXu{Bra1>NtCOpb>01SgMTL9&Xb zpBPCGsmx%>b6Go=h91Yfo}d%Z5MnT%gCeiH%z)$-5eb9G;%sxEPfAwc#)XF6b1w+r z*mX&dPD0B&xi6a!1Uv(>5Y-afJ-p$S5$KK<^m=C4R@tjq_h02gcN@|6 zG+F{4d>V5gvGhY|nlbBh`Ms!zS)1|y>Olv=z4 z@Xlz|E->L0x|yvd!YdIP$x1fEYE$`C^`LlEtTzAUvoYC%*5 zXMy2lPT>qJqMwDRq(ueQ0tTK<`NuM=FSO1e$?ZvS&eAJU2}h${VVUplQdWOJ6O~`r!v*oez<_KWZNB_~=`QyZ(g`u9N6_7c~JgMc=u@{RU0 zU^wMjlDYXkxa53^!y%M_fDdpwA5d0VC7zmeImxT1 z&j)R0EbtSOv3>?ZU)Wy%9}mTmFOILYNT${UB|hiW?u&0)E+7SMu#Ig)#VQ*By>KA= zk>p}v#-qix!ljTE&Vrc3c#Ou)l)LvfP+v$KL=X2|GoV#pg zUq{g7k_1Oj$dale)s?hRL}I2Fb6Db6=_mn8*4WcW;C#^2%ySv!`OjuEAaW^(<^hPW ztA^Za(si`>dw%Pg)22~^|HHsPl51V=LgzPx)3n$JnO7-ik0y1LNS!k?UX+n$Q{KI> zw&DZd>*{w(W6TXBu!Tw4Pjl%|+=nbEP7b|gfzX0!_}@>KuO~o1!ecw6-!kAVz)JD& zJY4%RqoMu$Kb%x>-kv{1PmL30Z94pR5ocWv&q!|Y;t+owo0JFSAi2?iHEn7cB zK?DpzqcSywaH4pk_kS0TUw&aU2f{bFQ@gdBJZZxL}bc#K!{?;70j? zO;eyy-ri2h13m7-x^GFrPeSU6A??b2c1KVuL@=l>^Z_)PE{4r>_$%DRp z{@1YV%W2iYAL7fk4NcL7vEF459wM$Pj~9!jg-`p3s~6HYte2ews2diN?gns0pNoUQ znsugAIS5@6ufQnFic+|4Rsn4CyZz$oILk2u`q2rx+Wc-Ht4B>>#%PlV*;Upzj~f&p z8y!OG_z#}6K(}T>z>oA)G+qx{?d%V^ATYN@UR@5lUnT80F_n{%fg6&Gregh;N;x6C zElRP?Ye}SewKbgv`l9=oamd%vzoxd8OZsGy9~+s!*t?!@H=o9rxGo8&3#QOs6{B9x z`M#VG!=*MZPZX2BJ(18NznUninJuO+d-S#z0Xby?I4W&N;6#z4=44|C8IC1?!A_}M za~Nqn#1G3K6iczg5aX(YgOMrZRlmitJdur9sGR&T)+;-KPY0dXjema+Kg@ut>mi8X z?G70lygomh2n|tUFMI@1S%lTF{W7w4m$HmckF1I*3CGZP1#9*~(u_0r%a(l)BK7=Osvu38H{S!HjW5L(SNQ2f8yE?A*VBCia*d_9L16 zbxAep&0^IiFivF?%!puZe!UP$PG&@50yN}kI93U+@JPOY#`9v#+FmRw-Tqoa^TNKc z7Rw^fKW!U_g1Dq4fhd|#j~T@pmaDa1z0mE(91P(sj;A1@m@`sosF83RJXOL4P)8B@-T8B_l5E#Wtl_enQO=VdY+PfpkNMc##EbrdUqZg_;WhwF^;LIl_p-5_FQS1iDzAs!uRE+53%w-47zL9!Guw8l`N?lr}QT zeq~|Y_iJLqM3i)o;F%z(L_~A{6d;`b?O?1CLH>9tvXU>_J4p6xb$5RYMEcP4`G1(=p+O;FFG2 zRn59&`M!F(IL(vLzo^n3m`@wRvO-P(kY`N%gW87_H*9IHE6@^ z6GT)L>stOc*tq1GhWcEB00KN_t_Ez-^FvriQEw;oxZ)+(nCL%0PM@gReyj5HQV+jY z{S5~>GGL!s&P{0^lx@wVv-P1mEaHS=iI?onZ%1fV`Y%~HHR?eK$A)puWh(L^0hUEz{7F^1PyIkqKJ zVM^+H;HMPut50RoH9POvoQmS?3y>yDL9*nvbqae@ruL@okRB{%$Plx zlmD?`fOYa>cYE=C_AL4_kOr@&6~>H+#}rc4Clhk2=E2n_WW%-t9%bODW+%k9rMo9P zN=(@{wOj}zna{x>g>{KM<4lHXnNh~N8G&-a*Y0)Vh zo6r#zdQZTnu0%-tKFN-~KI;%8sASLt?cMNGOjli5GKHt%zeh5ZRaYhzeN!BJjCZgN z7ngA6Nu(6Wc~}(;0Q>lDj>JiO4xFrKy2v__d6w0rE83l+&)dAk*`m|OoHJkNRDlx>bgXoIwujX0KB5evaoIhT+*#f8R8+ z_ok`fdm zqsNf1hL^`{GPG^-J(q>?-c9Vq2l}Dk{ym_$8bbtn%E@gooavagwG#AgKogVY&fCJT zO9cc12KjJiWv@};^%g(A1NiJ&Gn-8J@8u%k5HdC(EpbnVc+&ccA!tx-j9eor-9>{{ zfe7+KajCM0u8J)L0h3yn(ee6W$}-I5ocdK1_eo*O1JiO}7~Ilc+0%Tx^+g-%#~^#G zGZcr}a{k~DIPNnE27(e7$#~R6G06gino7pESV~zG*e0zMlqszjqzN3koq*}y1ayud zFQOBi8?>ue`6-xcAFx@Di%1{ZPB9F@fyBFFq@@76nn$lajy)6kBF+M|`I0fZ*W?o$ zjsf#$Jd0fLfrg}=s|nD(SAtXA`Q+heMCY4&-N!S|C%uh93{L5lgOLfG74V1VIpe#z z4obY*OK!1dL|o(a0JNGM`4cWdDlRxlQXqlz3_m98A8S$sjW=95q2Uko z7vuCu8;(X`37_M}4Ua%oOXAm6G#Me)>UNB?$wX-`&8?N}z6SKmfp!4@z!0dll$@qVD<(%D_Cnr*mhC=WLDG zAxgTa)s!>qED7{y3R};OspIp?snNagAYqwfOgdGG0m1kNA3m%dQ@V^9hoQpgiu!wy zadcv0f&(luVK@hJwmF$cHBtp_b8gC#D1{sX`SlfYS%vxq>vP+aRuG}WHTN?-?CCwG ze-Ou+(%zPNwXM&8Mz^h_7!`ym%22Dv-f_hFeLV*?(PbT6Lw-R_#?Geqi!mxtA=DGk zpb1Yhbf}wDtq_U)$tMLW^4dg!0J2W#iVHthJoH%rEz_VA(FwcImM;=C-fwri&>>#b zPrO&fnXuDVh6SzFp}>#O07CW{5^swq-^#Y{wW_$wOWwq9QSb|jbMXhNNAUJakkdLS z&;4tt{Tai0|DU)`xgD0(VO54Fdw?c1>q##xj^3G>9|0Ce@SqR+Q+za^C>x7FsK)XefmWqi??NeWALok6Y5S1r zV>7GJ=I8DnaB~%#7{NdCG6`9xVqCH%h!G-bhBl`|Gz+Ls>D+x62 zzz+6Q`N@91$`Z}-k6IUf(2n@$FhVkqz;rgbM_&?aJxBsDTDE0zUr9LdWW~n{K;xhK z>#DIVE_vIBYVVgs60qY23AM+qOOcrk@)z=0T<`Bes|V?RTvUzqZy><)_YZmt^F|#9 z7Z+EgAe(~fGQ&pltp1E_oCz?YC_`_+MnVcrF-NMzmwK{c_>wFoEW6PJo|q|AI&?mA z)Fg2c03s7>t_4c#b#s*3WRxy85r0`cZ%T?~B{S+8BMy>(T4fza+1@n77q^kfbGlAw zna~OBUm`HHspj5Kkou-`b*KwRSkh?I2fjLg(c5P#y-BsvdL*H;jjW_NkMLRnW0soR zemmw;Hc<$f5n{twN}Fg34Br66UmUemV=(~Iv=?h~m6Eo|h->_pl~pVwALMcWVI(=! zZG-P2j=-(llR-?=6RPaxp(@P@hk)jrulsNlk+{yDbC9}~R~@RU zKw%s&kx?tD&^0hHu+J>invfFECO3EhloiX*WM<=>`@mlHB2L0f#ruO?qF&%{Q~nv) z0FieqK^oMLjQ6Vp@Td6O+4|7(`&IKZ2;{hvzOj?yZsPWPWwl_3rSFsfmr_(0x5dli7CZ#p;Cy zohbFu@hohuW}SaUHsI*AJx8Y8ogIwV?~35PzQ0*I{e(KuGhaF~&h`|KkPCa=dyAmd zHQHT7goy-IUi7tE^sVefRR_kh(nQu+6-bUW#gw_?!vNUXZz%fk&q{`o%ika=B$ zPJL#O9ZucYU%=As_d`?19u;-d&MKX|*=xllfdJ*3Y!xv9hjFjdp#wsgu$i;Q%MP72 z9!V!Ylbn7HK?A2_9uhmQdWZfwewScQH&#B@!>yz3Lyl=uZZ3YZxvd=}yYE{WsKjJ* zNj88VLZ03$0zGSF@)%S+{Xhg?CA7YYNY)YSo!SgnbwxX8=V5!txH1;XGB#{nE1_I> zny1DM9Y6HK1@vE}AyY|NNS3I*rp>eNwW&n>UdQ|El&4ptm6h3PSDjTsmvojO;N67I zN=VOemOI<9rO?IG@_-kOp(}IV{bixIAN$;aa0W?y*@g)^>|7!K?Ahl3BvF9fWtU6N3 zgD_;{@}#27BPL0x&|P^0YrmpCy9-OuxLx>-DJEizeL4{iE6QvlGr!nVjrUZAzMYv*tg$ zDAfruW_wObLpysa;-^cm%Sum_ib_vVnH4&gU1KV0`o~u}5{E0!Ix2}NJla#_*_o7d z5TD5+tEDlVCchtsga5!N3exp6;Qf-~GG!voEWx;%9V4YaguWKCVNBF;YMNI%He9`c z6)%tp=P8pQ;Rx>OsP1+t=Fx?y%(kcDEigGFv|Bc3aWGpo8sU(Q+dAQm7~dHmJIvv`43j^BG+$MKQg|XZRor1il(g7O@szed+z3- zKIb_+7M<-{IA!?lFLo6W1Z4bzEbCM=woG|`zG>_@aEr1EI9cO?4<)=AJNscu;hs7e z1g9xN)WwdWk9KY09%SBsQwGUAVWJpt`v^5S3$lr71nXtX6XumEHy8nhc1Y!xCk63dZ18R8t`j zN;XGj5B>7QhKRs5e%&I#=zsc|eaW48lq{(UITfq&56a z{Rbp2C`paxCky(0`Z(NOSpkY_?fD5lPZD*r3aJ=JTM%KGM8A_ z6QvnbK@)TuXKqpAa95kUi*!^hox?3q>ftsJuKDiAQgI_owzJNpOzW#xF&C6kC9l~kVa#e%~8j9 zdggPUZU?2v-;tZM{w`IOI?kdbHsQ-rH&Du@n9*3HOmR-cu{qEno0&FtLxaWNDxb`m z+Mo7GQpqx+b2{NuYRpjp5h!dKJkM>g7OGW{-W3UN1=Q?`Nr?BxSq_;u`iUx7v_Lpq zhZ@&dfgH8i778ltr^b2x)7dq!OyP=Oc&gi&d?8;bT45P6uY=+_Ybj-9-yFVvvd4jd z*@Z$EVovoohQxWeNRW%)4#5sZUPR&*7Zyuy0%u9M{J|X8%L+7Vz?)yehy@#0UKD9` zgmZmQkaUS>sPQM(wI{z3=+%kY@XL0%A1he;5EO}Qv@1sMedifJ=Q45yyMrH zHtlF3aWk@ZC4AOEA(OhWZcajMQ?_%gASHy>7IKW`$)!Mj9Gdam>`{!~y6d!Fo& zfhul%UZx#?Q{mjXQcwu8plQp2j;!@Q<;)y8<&^0$dHN9t+!C~Hd!Kbu?r8MlBN@Xpy&{Sx*$FBjP324tv`VtWO+VG1Rq9oKv7gwN?OGQC0A` zBfz2VbYIJ$LQx(dr$hM-O*$j6T`ZdLa>EK3Nxla{Z7wX?^5QR@9tJSy!eK z%QjsQlmZZVUsa zb^ml+L~&7z%t}h=6+6fF_BDUP{UH#*dpH1laUNx8l3Ovr*^j(}5aChDHz_OaQKBaK z(;`sw;RF=1-Q(#zLst}d#n|fVZ;!vHbKP_?z!vrU?>9d4b!Zt#EFiB6bAPvxF6>|z zoNz>0#GZ&_SBpcI(gb7C7xGK*n!ukhofutncdTRjgk{DrLN=^LPFW-bkWuAve4-j7 zZ%~~cdL)^q`>9)_GCo{m3T8!W>xva_px9YkqHiCIZhE-UU4m#BoBpixp2HT2P9?+m zbyj#ZVRY51k>W5SAL5zcy8Q?bvH+j1^Oh{-WBkF)dQ44om+%Gg5fsTZmKOat+N0j{ zvX$`x;|dA%WaXCl-iVd_09xi{UTiL#7=wbQSHjznRgC0L(R1A0PVYa3OqaMHS zEXOk(bMaENpr>K$(Id98*f=7b&uV!q31wE>EN7PrxSa{dGB-&?BiCemQqqt0sD>OI z)UD+Re^Z2rJl647LZLZ}r?6p-W-c&qlaetn$|-H|AxxA*(W6*-1z@uvAfjf9U@jFQ zk?s?s8#_nD;%Su1s}j>raJcD&RS_^vM!z8T|6KA?*;|^;HYY>zfLW2C>QS9aatmTz zboRdlsR=a^5(%$>-q{DX;FzjEy(g`l*eH2@FOqH@h$+@kbt_^sMG9yL5Ev1-2i%Ed zF}evwG0GaYrPGvvWSeonQ$$OZ(=Y>wScxNb@xsP2s+A2T1z+w7_g=Op@-If`r>Kt{ z8ebKVYlMjn`mGxvlewd`MDP!$iF>exGY+`>BDKD*X{~Hn4^x>RN)VjAby&oqG9IKr zA$cuAM&zQxxPx@#K#cPQ%bsDsvcU(z>iK0!vCV`4#8&hHZcvhOrx7b^c1#A`6Bv=7 zG+Wl_N>j>_tGXD8L9|K7?ghk6q?y*05wvVnM4fGDF2V3rmS7Af2V9h4BnqS=2=mCV zAjQVIrnh3P5^lg5DtXYX6w8Sm4#6fl2R~q7l#D}f3}1C^E7~BtwG+8MGg+J&Itq3M zF(leLKxPLun~wcAIl@_oMSK_ELGMxIDN}4y|B0bp?E6-iSG=^>s7V~f;U(y}R4f$G z#waXtf*Fwbrr2dHL+tV%VZwic+Zt!?F~i=X(_m zNLO6aUbv->DHg-u@N;*~p={GMXvKl0{+&IxmE#z+Qik}A&K?nqxXPX{xYDxsyuYrI zeero41j+Iy)A?LZ(jNHW_MCXAc{#GYk(ii@-&hSYGLy?c#3Yn{cOM&GSIsD;q_)`> zA2+R0k5w*_T;K(4P+W(JF9KuL$#4fXwV>(oU8Yr_No36FHH%21dady#m9CO3n7o zYu_au`1A}EV5o^PE=ep3#8>hP=PxQ-R_YNI?ExD5FdKvG8=`S-PA-fk0?3(Acydhc zvcd*V36pp1oipN&8H1!n{VD=vX#WRp1()hcG2SXx z4Bt;uJy(moIm`?2RT^)K*^LQl*%0XF+jtA2)QM)9ln)(dUcJ8-~pn*a^*4rkmHjkM2Q80U9;D;Qz+5>D# zFMk4FXSnMJiTs9h10^bT{+St46yAX%b%}`{rk@idc^dS=uQk5yu9ex|EYGo3Qo>7` z1T(xmv72&CuMIbF>wWbyc*lDrD$EL4kCZ*uHDf2Ls^}s2HWfM~sY8VKa{aStT)1bz za#}u4x3zZ!0Vxj#lHyB?Kas%Sy9q9OC|?mMDy5kADgo)f-ut3yp%i$X{9q`4(KK8N z7(x-(eSQ0bp$S-bVx@g#HBbti#y$i<@J80T0Y?Qe59M~%?a->e6p%u?KM}rYnx7kx zhM0~}GvnNVRyp7S%?+^|8RiDq6u=OidpCiLCYcg|HueGNK)+}jnj3hK2R~uopYUEZ zRbDjp%nf{z2Th^>@eZw=AR;8hbR@l9rGc6u%pwGDY@8dIf#{1+o57)#HZ%i-gM?U( z4N7;oQKR@COmpi>Ca!fg&g(zFj4n0|rtS z1}ve4kZxBA<_3)9-AM5X_e$$zUs^mn0H4=LkUQDc?SHYkUAh=ZfIx}*bu(k@75ty_ z8S+D;I6td{_19#W}uIb))4T0k2c;KnCY@j*kOV zkc)ARQrX1-*HZ#gJO&XNz(Cp`-*CS)1XcgZmkE;YbWnRvd7M)&45HnMw&D@(WqW6S zq!M2m6o||dZcT_)erR%W+5>ahA~mpwURE60py8WRlFrGdf#4Ho`#o@#WNv(pcy4qs zLgDWq?xQ4)a|GNZh~D@z9R!8>oGs=moXzb&kqJNY?eBTi_vse^K^$!i!+3YLT|u{{ ztWEnkch_61ppvM39K9c$tOU7T3EbdqBt)vZ;y#)&Y#>yE9l5j)X8?&<`d64^ zB-Y-a3Sg*I_8~ynMkse0NXH5iAbsGg*4Bb7}KnfTHfFvfd8#(D-;m-Ke8DO)Uxf)ep}#aW%6IIn^GaCf-)7;c-?!k8|z#N|PI8DLQeOP+6R z52!hmL~o>?k#l(g;bw^707z3z;PTt4(Wl-gpsB^;)qpe;IO_rd2ycN;y?+7aukH6u z$rCOop1<7|@*NEA%>FC@rx2<-GJvl~=XSL-pa~2hTiLN8r-`B~%=F=>O7aeFCVec;gATjfVdB zsdtBPO!e-2yNivU_Psxj<)o!Ixr&ATyKajkg7dTes2a-Z7p+Mw97qg<>Lo{VJ0_2-0WX z8xeY4CJh@efYrc|aL#n`qCtSR@(IrF4)#O+8`6>vqzmvXJSj5Fv;BqG9m>00(Z7P; zW+CVfcZ6bsEN=*G5#^GeBgt#@ugJV8eYy4~^<&2oK;0OA2ciXRQcML_{J1-zYduxj zjDJpBhS*pX;q3kPSk=$Y0`ePO@9ww(FZVyWx2geA8>G6tQ#@|swXt) zh9TwQsmdzO3&kK}1amS@QGSb8p(c~^pW8(v#27?C>6@FPDk1ldV~o59?3(9>2(?EK ze@E6nO@yQq)=X$bAq|5*3%f&D1$4ri6cM`>@1sabE-nT~;X)XlLz4(7QOOutGN&*O zSHc#EFP-%bo`Jcfj9f)$QC{%9oo4zNCF?EU$^_OMv{&N4tXr_WDrE0+9>(> z$?y3Mu!=VE$vi-#QPk_P^ZC6GFU1NZ3*ychXz?xYtsmSnyX2_v4>}Ic z9!`+`ZvI@MHbB{yA3R zo4NcE7}RZYOI-%t*uO&-(;dVQO>PsFB%}bMAg;Jnl+o`2YExWOeIEpI=usCG*WCCF zNGWLPFOvfB{s?M^u`LG|m}pxOcmU2bm1MrCT95SxJ8*ig`pxc|UL}OND)(;IOx4eYvIZF;cM*S8>dwfICUcmK>q*cp>-p!b0IH#)Gh>|YOZ z(T?&C?SROq7SJ$wU#I6^tAVunj({}zq0^mzNQ+VZBccCqsW zSnlm?#OvN0u$(m~p`{AbgMf}bZW0#InApQ=!vWd?;t&`j;wM@-n;D{Ov|jzR9%4y* z-J5W73fwF ziwG8D_2E7ZPWqsb@cvMyzLTQ^q|z|*P!svR&Vl{t9$@~IGAW5qTiXnwS*bCqAt~|K zja#d?Y2bmshnEfrE(aMXv3pur;O#LU?T~dLcd7o}bn$BbnG8JlNOfla($zVIy%-2p zKU`XNjV)9?@%~HK(T&@s?vYhU;kjE@2hU44;TDsYcOTg+r)o^R)Vvk%;K01^!s{+&ez|+z zzqE*pm^Ln3ddSGRNPQwl?JU@SXkjk(Y=}S}F`_W)H<%caPj-lW*uOw1%HGo%+^#5; z0d@1W)wkQS1SmsHN(E4kZd7n`+Zr0M4Ae&d3haoY$`QP(o(QTU(_v3 zcL_*$cS{OLcXxLS(hZ01?(SAV1ZfFrkrEJ)Zt0eWyLo@_9pAWreP=ivf+zObd+oL6 zoNGVxG3Wchh~dW1|Ng6|{wLCGMY>~P{+Pl!ngV)ohld<{NBNrlau|po?c%}Te9$ki zLvo0Ah(>)64j9>qtHtm)eDM>arIR;JCiQF)qT@`I^Sj)br&3PK>VNB13HPOA`N~sX zF)e59^b)ss#7R5L3DQhi@ija<&|Qx84~{uDZi&wLQkWusi-y z_Pkrv)?A+V3=y=I-)GycT-?xpc4J++a%Jm3X5Cp(wyi&Zk0@zCiX>%MQlX9-FaQ4; zHzJ86aQfg${)|2eUjg4nh@_o7qCpNYZX_6* z)$%|;CNF8KsfIS*k_xjb^iV-EU%gkF@i1-AJ?ZLLDNz$82*v4e-i+VlL>=_3l!iie zhyDC@&f_76Ld}QdjqrjaJe>PVOqj6og)oV7PhqLrAp>&G z@$-5I>vCrWA&;Ne*!M~!kt!nK(`x)9%k!~#Q5-rWVDy>$t2QkuHqJB68^M25Bs4M4;!5#!r<7D}z;GEl)6}5!R_*oArb&1dqBo6osaf>#qioPv zZHT?7WlV{o!A=l&6-H%uqGG6&lBVtS=wdogIn0|Bq7D7##>BV7d!g|waNu+UdW=nz0ofiwo2m>=Jk13 z^o%;Hdx5MVK9|t? z$2BBa9zYIPDE(TY+CpCGy`3z(Z^u+Y0kqW&OJf>wj!g?QgZrfOSM9r%AY<2_Y~}%e zUg+kuDnzDlkZENWGy~GBh?JEI+&~Vs@xM#YZw-x@-8_~Z+m?UqHye7DqbWBd;#v!o zTz(5HxyJnb<8`IH>>hi$#Qm8z#y5FvlAHq8E#~VZ6t+*t^5Zqc*OtTT#X9Zb(Y5b|9+y#!6XAe+z(cER2eHMpJyiMG?9;rTA^`W2m}ZR?l`<3jdD1}8;3930qgAsvi!bKW zyY*J=x`8PbCt+5W&Y(msd)fydU&Lox*P;@BcHL!P`Z?H-%SW`zeX+Hs0FvjSf`MS( zl@%&PsRnVBu}726&?ZfBcdg04ADJm_tobc$=8yJ8|Dttf{kd<0DXxf-q){!reyFTp zljCrjp-ba$;KmKpuh)C~szuXu2Nd5sP-PYo>9ucLqZ#|2{?v#Rdz;%^Xi=`Q zqA0A%>*20~R8^!mk$~;}TEg^(f=6mp>xW)W@R3?ELci&0sJ^LU|u5u6Kyr_Ar)(d1NkhDlkTf#80s42DTfG{Ij>O1 zD|e1#+=F>HLb!`!W*E1T?>w}xP6ctrd17%0+Qr^{(s=Zu8YO3}AA`$@AXw0{+rR4! zBU2hnAr7tAEHwR|XaA1b-B0;1{xN|Z(a|6yM6r0o}IvSnk-{D+2R5$IIsNf?U zp`+djSlp(uta*el>7oBl>s*X1Nnx(LdRGlLFM0JXjt4A zRUytHO76@$ZR%AnhA@dGL5E}Yg^W2jg_?M!mrYu#)=3t1tKy`@3ovFsnWE=P$Y_fP zkK{*e6%nw|^ITKC`d-(a@?+Dt_a50R{rY7u)c?9JSxDR}Bz~``6)Bz3GH6nY&z&W| zbcd`rYWnGN6U^j`-?56? zVD}2AQR4|u$8N(SByjs>@F*5EKa)wriF~(C3cf@zyu(5~vP^4We@&ghp{(yJ{|kBE z!qCz;HD0)aH59IKRq%#JW2yIBbJ_~71@W=#`ssLvhOyWKb}ULUo8^8V#p>nj=Mbzr>z|m5@04A{X^uIp?EA-LX#P~` zW*v@x-lz_{**@994=2@_s&O~prpU4ShtmX4p+4flfkm-6O3Wzr1Yy$P*_pw0$4=G(6+Hl-1{nHm)N z<^DHq+>$zPA#P;vlF6>VBz`4KJQy{hnhs#TR?;W&=GDYUL6efmOQWzQ79z;_Ji2#8N^pb3Q=1*lnLIHs#VJZ$$>o0DPL$^ zPd1AVGIn3t>YNVK>CNV^I}#d15gOYmfYV?Va%_i_Q+5s6-)kguEFXRr6{*yrH%`A3 zsrq>~rA?8aa7%4%i(@a-mqOzdRdPV!6}BXNSS*ZhzyPr-+v?&AE9phH?NNs4Sv%s3 zJM1$Gq^Oltdr}^I$QnVZvoUD=Gn2Vc{V~sv=Bu}bs;Z%wCLs|>Ig+*_j^N~JFXny35RaJCVMb3BC0_AdjvITv!pO0FDooT{lXDx_qya}JXK5L;73 zE7rfQRz`t;%9yT>Dlk+S_8gP3_GiH5le4Yoo5Xu5GNobb8-#)jOLvy{056grJ8pWCirzWBjgw)Vx1-vvX30 zXe7V;VmP4D8h`q^PGaSt*e-jVsI^8RteB%YomQ~8vF_Ho>dFk36qTqePPz&u;x?_# zHomjp8PRNKQD=C)@PiLmlTHq5z&WZ}!6^3dzufQs2p)G`jQsd0617>?hql5}Ut+cz z=iZHd=es4Jk(bv$s!BMlfS_K;N`B?0j82RgkQlSI%x>bV6vkyU>!Ez>U}K~pe8(?9 z?M2K%D#f0q&ieTvot*RZTK|NKU{x>LInwNNnCW z3SVOGon@p~8H7d-SGiI4P9VE3v$c9uL=AwOh?r^D{-89tB zTLdOkYE-JPS@o_jOq3x?wM=g`zPjvfwiWo~uIkxME__+|BeZr@qxJg=DRIfc^WMTb zbAFgt&vQW^)h%(iEmM2nNUNiosHRU%V8~>ehw{}ezKcT=B(|Z@q3pdQSsC%@e6FAc zrdQI8{RK_^zy|biK`&Kg1v?g(#6lEq@?%4FJ#%&=+y~>ajR9DQrisHrUH(2YceWzR z_30Y-cQWyn{k?`D_j+%S;(2XYdMBp}1V)&Zh^&ID#!FXdk)D z^gP88#H5jLl$y9D)YcB3M$V1-sO1IY5(h~?%W!OPVP8>w&-&Wyii}k@>K9f0F_M#D zVEAdXte%xaM)JrQa#;Fimex^T*=6tD!~P#`sP4@2Dq<4E&>hOh=9)wpR=B zni~;XM5uWEajYzALu_A>!lQ11=C@IjNk5h~$fZEdT9MFv3(4uMMaiBtm(%5U`>5uV zY}qTXK|mOA#wsm5tsLJ{kzR_NVvp{ed?RZQE4{Tnoj*+{Kp;~boyWS9K}4U@`2`*? zj<4k5RWwx^TTYuB5-1t_$6$ z*>--9F(*b`;+4n8DAsrh8})i+)1ApmUA-u z%L4xvUEDjG&peZAuu9e;)OE5y#E0xSDLpj$u_7C(=_+oJ`luHz1nr-HA)KXwvz-(% zO;pHIR>2- z!~P(88=uF2o?%%mPTtxo{MJyHrs3N8&P2}dP!L*fvy8Y_6{J|J(Zt*8c%opN(pre3 zG->m~cR9NpEV~botDPUeQus%(s7vk)v9d$`V`hbNC*ExcN7Um&&4ub-!V}afI}a(O zZYD6pg~J%X zGFI@?mlr`HWC|^vkZK3DCdlu*Gs?Wcb`Q6ak%S{u`XQMiHgUoY{HHAk#veoY8hcONu(a% zQ1(*vLT$eGJ{-0%BqWsmu@n9l9o!%t^A8tNTbbsrC(65cST)b`+h4aX&0+^lonv@Z z54ZPdLdZ-uEzrm=(XXW-r0T+GsyO5gVL>8_oml#12DN|af_n8PO;5QBj8Ftj+&6@$ z2)UITxYhT&8K%4~@a-{-lIw zv=RRmIdWK~aQF&LFE4*qxlS;V8laWbOdKB*6LusUbhrw@=8etn0j@1e`-C|t^{*vU z^Of@ceESYZAXU1=f6e%6Wl2gq0^ODSkYQgX5_zttu7m|nF=r0o()Ep(l=&pQEJTV|gM zly9k&<=!K%Irotc@@?1LeK-)1RBIh*2v}oh&B)2f9SLcRF1}c~Y=m3jCn2uzgqSM@ z6)Xt_CeJE76REWkYG-@Jez;q1pDNw@74?R8J3HjM-dkkz-y3ot`}4q(+Vs~*;SRdN z+x0`{Kb59_*41gnWPIFl`&tx>J?LsLo7Qt)b~Q&RpKEzF%_=xRHCB%_B-yqFZ&hk< z{2d0eInmhTngJ;pS5T7eqmtpPgNG3{3eGAsg-Jc$?*q`>TXIE#>voP z=~wW=bNv`GpE=gfPyAw7hdfTa;hj}j?{$Oo#Xpmm&-Bv%l!Za)+iP|;K7}k-EvaG; z@N8McFO?mg3}UVAK$8jON`||dj1*DsVu~nOL+c0zlp4IPMhVbu6IIREASXVoR6)ER zUt##vT}{xJwa1Wz+bvzP5FLZPMu1(V-wS*9)A>v10PYdYg5Q4HukT(zsD)Rq(j&3t zUsE#a|Mi;rqr;i08z!6K7QzeZWie;SB>xdE@cl_}EoP?*eYUnz7su;T;gl`vmvz&V z;TwjzM~#CH3YVTQ+y41%n}M^26%$WRQpIoFx@@YH-_k|~^WrcoFX+6PX;}Oy32coI zY{R(DstfGijS3E{(zahsaxGj+-F*#G`4o@Hj$+L1kP_Mo`GB$hi#_vo zOsld+?Kc+EU}kBW4d4F6^wMq)1z9VEVcV4Opk!Vl^|BN~0^7s`FZaCP9c6mHH+$%< zeB%+a*p5*F==K|*B4eVU3YdwjXWmv0!b$#qRK>ipQel8 zItya3I*L$`h*{aZB5Hlb4RPvH*8fxc>HX*CY54&YYU2sY8k}Ado&5t(Vf;loa^xD* z=NR3DRYYy_tw`fuRbm(Mx|?@RH?R&FH9PBaei1kp{BQ$}BgB;7l(OEoLi0OLYn9FTaQ)4Vfu2U^3mX0jJhOBLjV0Ix>W~s+lB-^qXe&hvMbs{S7Gf%e0;!cu1F6`w9 zg1M1x$b`wae9ie34oDmRi3^DpaZFlw%2z{DhB@=^YV~-Jdr~CR!ffp)I01=V(8$sJ zt8d+*6|}@z%MPQ1nw$2t7)`SHc6-v=q=?Hg>#OGWQU=!u=E!2CE7wd-hojd?(uCyr zX|4tw5Xt=BxH+<-F>&Sd@IMuv*-3oWiI!g3Y9EHRO^{AXmS({W5pCfrMRvBHDJ}a!^!`JipSefj!Xj^ zCfW8dLCe*wq6N}YtYq}PFYLny=2ay$fpDUOAEiwMv)SDT*cO2fv}GLD=v!AbC#1Xz zhaWzxspxdtyHfRtd~>9_Uo5iTF$7kP&i$CN0nR@Q%r8s0T#{&pJn3dN5yQ>{4?-A_ zApM&XJljg~)wFmzwsIqzVa_tQv9tvucFEn**;#y8rcR3;|w^-2Zts2E2GR zdcAlxveEQXw~7rk1rp+SJ&;eC^35erRdKE_ZgT!-)kxPLkD2>>IR3}GCWvtAvJ&qU z0o*sDwlWP9+^{+5?-b4{cTPjhzZ;{^yz={TagbuO`*!W)SR|{wj?$?hurPe3#c|aO z{$__8++{h0F$z`;>u+I+FW6z#is4$l-NoKmFdb2a*vV^Y)0a|~n27y-71B1%kJyVg z;Dq;%<2!Q&N!ny3VZ|EHuVFRU>Z3H(7pq1X11sGb^LOPO^>jHpJ9LLCLa~Y|r4c*8 zs!^Wdjmng28QUe=GsYC8$KbfCc2DOSYv$2#LLDmj-4|MK$4-K_kAIlLZM!h2ZGM!S z!evBQUG6lS$(`1EwH&E;-}-qfIv@sQOyIsDeboE-WdR$3;iNZ)+aEh0#kIHWwCQ)! zF2a<8UeEOU0i1~^GKa9MrUp?*BUXdhk8`|)hRF$fduFFl4>n#kh`we?IKioM(i)i$ zn#FD5&wC5Gf7iCTJ|4siZ|x`3sv@}6c*I@TjC};rz8oWwGdsjKGGLq%|8}UUrJjI} z^Ey>%c(H0s)sQSA-)%cVt56HQ{H;G)Zo+z?u%B9#k#Nyfn1L|sX!CB;ZS zCb;4GV08v={iXEVFmap6CfCcv+b1}Tcl9xg=3S``M8zw2|CkijVBRX$a7|bZCzE-n zlX4gPYVe{qkMOy^X)|#y?i7A%E)N1$jX5i`=1OqS;6V+M*5vuq|6&aY1(or?u8kjw z{&Qg5#QuMs82|eT3W^^*7ySF>N9h0S@JRc=u8ndkFYg2eb++4__CKzTI;hu@|F6g3 z%jas^I-0+{-V{v*8tQ*c3c(K=jpU=stq}RT{hxDzOgbLnb^EHb0x}-j;sTUIH6s1U zynFGeb_vim4NZ!B!B=~a*@gQ<=Y991>rTIu)sCdqr++Q|=A0~esI|4V{+qbglT7o=3@{=TlaS;&{%gM=^ zoveIQR8;(IJw{~gy$(d@J=@8-r` z-+7LrrKLsk);no?G?SZ$Cv0@veEUcG{E;UL3W_%v;_%2wac3t`iS0G**}Z6RS{76r2BE?!DELG4p-sz+^ef^s#Ip-ixny&21!vxMa0sQVVXSc?d>hHV-_mP%%4B&~W)3*&-h@zU(o^{}w8Rhmp+zI@^L*vGxt8N-N{F=rI1NY}ULjvXy2tDqoc zW3V!s*S-_^&CM=>+4^6>hj+dw>y09)C#iu6p}T^f1rqo_-5MMNSGgv15}XUJGZ)D0 zPM`nkc6hSh|2ryeZ_fe#OJE+Q?d%w7X=(qu3*Oz`$to-Fblo5Ktvi3Vo2JubdYve8 z$KcsP+5uS}?|vBV=HTGy!GzpM=o=X5eKzeKTCT+m)34p>MI`Uvy+}?=lQc7@8-xS{5fzW6sHP^SxtZ7A!J+M9TnLBiEGVm< z$l&7UmhkoU70>Q9O^S&@0YiSiNqoMEUTF5NhJ%3){MT4`#s|6JD^V{|q}!aS)}W!K zEuK4YX)~Oeot;`)Q3hW>QS^x)Q}_}K3`bE($>pH7#rX3xy>g!EY>gI36~BJ{qJj`X ztvhEuKTJGZg2lGwAxa<@Rd#XV1SVE-ad8}6Tp?rDrJbE`i#wB(Up48oVnl|frQzP) z-!rnY;q89ecJ=xGC()VzXR$=&@Xw!?_Vy^LBmIB>G8C&uMMNMRdI|-07bYZN{Iuo< z8>ezw4vY#RGNn`JG&MC%PEPimo^pVgCJ}HAJ3n{rG-h93UPePlSJTjt02vD;R`0iD zc&z$i;>8qLNY1BgVoc1;Q}$oMq=9t<&)wSD`2u+k{4qKTCJS=oFT%+dvG5)*K34#K z6ccvjgqG3;8jnTS`FD_!kr8WG;eB%M{i|$0qUyRjybExFaR9E;<8aoZwg5fpTfX6f zgUJ1FDgwZk4oa5=Z;F9`6(`S-4gUZNggAUrSJ%_0P8)gTiCGsm9-?^N@k)==LTYaA z)a-0Rd3ky7bI1sN+tqJ_g;p18zki3lAU=IAtp6P?4uJ_}U}LK&DS^oy8%$LZLGFn_ zC!RdG+GPa?Z;Ph)IEdnrT}PSHW8&h_eoaqjXJr+YmBB@c5_)-h{#sm&Rj;POMR^r1 z*?&(9vPoruFG{WU=<3taYRnYfZir&FCeuS;_k0CJmnCA%y3dl!WvvGqjEI1kxX-$g zQ$Rot1nJn=7!My`qwN$G2*0bVtBq@L(DVn6%G=;x)3tG-6H8xTqS7f@Yil~9_=txG zf3VzOmCRxoa8ahFrh=6#!G4=uT8dkEU(wpC+lfb)Du?D@K4shgkB^6kgO@jA@d)yg zFFIEd5D}5X#R=l2LCDL3vP2Z0lAbQ5uTNCpb;krQ8u(=VEytNZu5TS=!GOQ|xGB&S zl$4Zbj1slljb?oa>KYoHxnoP-oAEE#&sS8?flY~w5Lz{B52_SLwxXq_<;%X$Q>Hh0 z+}Fv@&h}Y#w6t!_4hC0*$Hc~hSXP!bXtYMhh?L;ju;e0qe0<~qBmA)P78eB`SULQ? z^5v8clP)#e9E=C46L_40i_ob^Ff>$E$vhPkfI%{poTQj$5GamdE5{`!#;(K(NKi8} zMt^mfqe6lKr37p(MLHa6YHF}O)zs9I*Wj}y=u#UXV7WmElO;xiOqXGSborY?-mn{E8qUfvxrHmpWJ)uyZY}t)Jskmd|%!|*`QqgB?pvfe*~-4YRFde@#7i9`z=1tWE~v7 zBNTxL*KylX=z*JptRdR7TXZiA4NaZYjQ!WY9$-2xuJ&gM&=7uq(o0SHFun*~8A@Sg zX=$iQ8Vl|(zgoCw20flLjZpRJlj02tO89ursK_)i@9wRD8*6ViborKR8-eh}w=39^ z-F5LiA7goWly~1dpR=hTW^M?{v-V017RR03=oM{Ab0|gb@VK0yVH&IOp?>1_rvBDIz_3!xyeCwq2AoD8rg|ATtBA;+Ss#mi) z5N`~%C7tPix=+Ucl4R!!Dt;_f16y@_F5W08jF&Q)1r~w_33~eHXy`i2^bV3!A zIbStDu*p2t9S7>@=zQOwO~BwF5-Sa^pc@{84~2#tdREnj!y@+V!KE`j-Ts~Oewxvo z|B9+z9}$XJT!CN=A?4y)tH?DS&nnEzqai?x`Q73$BQbqqpyzwyPbXA~{1ZWrS)rG2 zTc$XLdv=qi^tZgcnLotE);{L*B6?q+BHx?hiHV^G3&e$%rI6qD1B-K!ZFLD}MjgXT zt;x-hAu{TN2x8UTG07z-OB8tSp#(FdZ#mTxk&|T=DGznS5$cr|hxuNgXXd!OY%q8B z?WMtx0Ljm27pzDi5i3j${a6a?ri3oe6XWHK)g~Rep{xu>HR?&%pxbE8^IN&O3(NnftDJi<`nNnYWK2Pyv&^EA{9N zx`!-$_XBV=DL3xUJ0efl$9vBlUAqcen*O3I!1ndvmIC@STlnZdsNr;1>pPn>rCW$g zUe0%Lv&H^G!M`6!23=fJ^1=zx4vC95$Be)1E)G|HRrhgg;J-l)>6xF`70*V*6!#N~ zi|aQL7CwDE87lnu%{Xba_!F98-3?Bl4u0n)Hi-xc=H&EmJkj0SmZB0Wm($3bC1WqI zmYapFV)_qqcy~Oc-#Q|O4RXc`hA_AxE4%}eyJ$E^8gZoL_!kFX8adN5aXdSsZ~T!O z2pCcEOqtk+o_-s^4Gx{5qp$Cs$V5rY+1d7}>qHh8LFwq=7pxeE>Bg<=7>i}54=5_2 z{&QUX{9!R;jaAmpmSWAhXmalq9b;qvuzz_fm`#YddwIMX^6XWSn=4nqmsoZPdEX9s zba3Y-PFU_3S?nYPi`LrFj#Z+zl%L-!DCk_kAKXzH*>l5x_uwCrnmXU&XkmV0j9}~? zoV_`O%unL}csIxIc}Q{Sj!i&J&A}^ut)XJZ!bs^cMYU!BCYzYg`1t4|xgp@*)AMj% z4B&$gUAH^%7wyYVp2thsz@B((B=zmZPwsby5m)It#sUYOwmd)B1J6(c?-y4AA|00( z^}YN%gni437rX8*$eu+HYTN26WSl2+bf7EXp3VDdYm27qx^>ZCgxsLT34Wu-$>wPy zKUN|Vqv6A9S6Gj5rh6?EG#-2SxxQzt*iHyR_m4a@OT2|e&HjF?boy5&d*qB zKU(pN>M^zJ;&w+zf`9*Rr7vnHdI)4-2y$FB-5hKkg4*D7(9%kuN6a>i;G7Nux72AI zkI}C$G4|QPa^X=FLS`QsJInQtUsf0Q?khlrKGV^LVd!dO8#B`eF2}n;#!CncxcLYcR0Hc)^ zW2eqD>A>rbRTsbnFHD}VOyUv}0Hn2ZaDZ6!MWA=yY{dHSa2Ha(d6O=5+#1^bbX5;P zgxllQTqB5FJT}AO%|y}hWv|t-c8>#*OA$mEXn>faC8+>n3hAW)pnQB>88CW)+KU12 z1MvCok`2)J$`0g$itQ5!Hlj8EFk;Ee#;0Rsix1RKf>z#*4 zy-xdaR9-+DfN*vnKG*Sx=N+q$%DB_e{DBYrmCE^4?CgmJ1!VjC`!{1B0z*eE!7nhs z8LNP?`duGefzJW+5(|(sK!pDOd49)jkpN)F{Q09_5b#fri;K(F))s05Iv?;Q0M>Mj zeZm1ly1P19=n4=5U$*n%e00hGVyyG=-y#I)4d=@zf%rl61>PZxP95<|JB=Cc{kH{a>Q&8$-gw=q2fdDtY^`{w%wq@96vXFx26M^fqA z4(dAk10F=5&JxwCHD_jKoG<^Xk$JB{KV6wTr*}W!ckcqC3+v(G0XP$9FR4UgwrcG|of?z*+cf{QyzPYRgJf?{~u*HQ5zJB?3B zaT{f&NKHPkb9WrCZHaOGvHAtxlIs#4e)lj*u{esD@}z=rrFQWYa*SUjr$X;If}J$7 zapnIbX>|MjpC&mHG!U&ITOS`gC6EYwf4p90M-T-J1s4~0&9lSK(NU^e69kx~j|vby zq)Ur|*0Hf+4ig-7WAS@wNs$F_^F<0X>d3gfbjKijI}G#)0F8ma1TDE7#EOd$Fw3%v z3UzI5h%^Ku3ZfmXS^_8;YO1P1t0zOd7gLLiqab2NMn@H}ggA-fvlQvRuXBJWg3tia zA8_ue6E^CR-+I?0~qF z6B|f$Kur4a;|E9XSjp!fB)z6sfKFasHdRqw+ey^VxlIUPs~Q?A1_TJ3+0d4^~cY?%vVS_TuUj zFBmKFhtA}H`+sVnB2o0#YBKr!Td>gs{0?wfkOGp@(+3U@Su`{>($XR6W?%KIKYmm| zqBhde8B&4VY3v^yAj82dc`iCW{FM=<0-BW=mM-`#ux4-X{+7P%+6^DDM}Xp&3P`G> zBdbUuX13yB!1Z#b>04_{%So_ylapApv$H^?1%ye$&rfLeVTaG>>2{Zph-l-$ziGk-3>|a#LNXGS4Lz3nHw1%F6!*1S9tz(B#=D5|JvfDoJ5wQzM! zsi|RlS*jmDuywkC?wkw6f%A)t?7Te5`Z;bODjC-gnQ{Q3TM7aS=eKX)KzTqzfCYpW zFk2ezUi+_HoSeZxOmua{Zd`~HFE)MuJ}x8#rex}`K)JF+F&0oMx3;&VgRKB%2GwN) z3dV(+o&;m_%o_;~rmV7Z6A*R+H2!>LO(w07{l%p#0&;TE$}dZPASWWryFmF7U!Ue9 zlCKRwbWFPcGPp-#l5VYlRKII-#~mK7L&qjbgS~##vPwr!FGJD^CuTZPAe@$-?gGO6 z^ky@$(d)$c{QUeyb9|9nKYzvw7f&w2@}`6nD*~wiY8PpLVOofD2UHvu77m(|0@wMr@f3 zRwU7q1SBN=_Fp$VJ4S#s=k1+!cIE)&(z3U&AuwuaY)t+6Q&Ej(_{ftRWD20u zfCT~5PEVk9GL$h^SlZPUd?Io;fuC-|1w|vG=C6wo6xLsUF2@VClGqk*ziVJh=i=d7 zjSvKJw~+-8L#v-{<>kF58{)F!@365?`o6Xs9qJ!mX9r{;s6>Ax9f3+}tpP!cABV{f zgddk$s_a(m|9Q+&==4J&jVIuoE5fej5((yWv~;OrVVSGJQR0dIJ9apppKsuE!Dz}; z4)r#E7bX1;3+dh(`Q935KVL|c=p2HR*ryqu%xDvxMN18$k!J_7{5M54aYwlWPZ^%FSO^S-RIj4b@bu8$8ckc_ierWUT zYFVkSgEbFaoxu`kiSg=WFIN7K=ZolAqL?1u@SbNpqLayBQqIxHRkuO44zZWa6mk!fSE3%1Mc*2YL_l)Vo+%3uTmm2%hoYA)D zqzNZBENfpxR(e_5clAky3x6rj=95s@hc53|7GodOT8|xux6TH*6EYlcDrJVN7Khim zM5!{FlbJQ)tPh9N?Ma57<@ERYo?sZ{{v*eOO;hgus_))}qOAxco-u!K z9M+Px3*FJxfBVdGSA=Vyk8}Qpr9m}lCT1IrS43eJzbo-^-XtnK)K+n?H9|%0^A0oG z(KETaJRbK{b8cG703__2vcHDJ7V9%r=>1bvxh=FKxJgP`I{T0)cZ|agu7E;U(9o0w z_~x2&E`03*-3h&eHgb&L63%`fy}W2V7%%T}te=X~JUQuxRL(Gp3E~GE6J)4f!HLOMDTs@2{AzuV`Hly&HDnt9!I4nl20J4~s&YC+ z9qZuQwt5Qz^aNWSCIOyKUJ~p!B^#hJ4lI48di>u=Hdns_er0KmOzw@9&-pP-cE9$+@a^0cSsUZ~V zia+jto6uH7_Pm94JcR*M=MrWMmu)C^{6(n07efBd;S2Uz$5hUzvNTq)-1o7W<-a#_ z3EtKH#y%fUYP|FeIhGSYW~>mrF8!4)J6=sy>o2g=sgG+<>RL|JJ)JO^mf+QiSw0?B z?oA2y8u%92mvn~LvOS?#@kN|v*yxB^r2Glusr@%2q`TUR?b29q!QJ;A-J54ak zkgUz2L~dbWB`+^NP>1{hNmIglyeZqbz83&w0JIB0(;DuOfvmW^ZWxmcCTUc6#0rsez$KMM& zAyA-=^Y-7oMM;`H=uV0hCIX$?+S>XBIvgDx8Z$ z|8(D0?E^N~f?e)+Q|3W|$&m7*U|s$w&W|J#(#SZFBfrT?{36Z)t)t65c(6s1)w-iU zuS%)wli|>NnGZ9Fy?d8$NyjK$XbTQHv?|ic6w6TwbmKi=A|(eQx&@Nnetg2K6@V@O z9i(nU1D;mohwb zK{lj|F6F|W1AnGeskxZ5+~Q}oX*q=DS7L;+`P))Al&-lJR-*JF z`r#}e2J(@TIk?(FwwCN?1~nh1spt1aLK$07%B2&aJ_5t-?Df7 z?vV)hP0@?AU;PVGxO}W(Ic4p8LXalnA|S+3H_Ly2xlR$Ni?PuMtk|dgI!_vT-FlRt zg-VPSrBYj_^NEJ&((I#N;-55W782Y_QuhoNp26uFC)e_vpSOIkE)^+}IQ?;8)82Px z+S17S4#%`PzJ#0m;Qg-Zh@co?RF+Wg4o-25Yg(UuV2qV zY@MC|HlhArzmjM)95=c17Jb`jPS2jnR5)v_8&v zLqxf<<3J@QgFLuEVUUX`f}S+!T|8{ji<*Js0H1UlLb|#{KwRDcia7-M1ZepegSI6A zD4;QXz2e6Xf!f~Qeu?^RgVj6Gpos?X@jWl`P$GF{bv1J7)bRIk)EC$S#0@}LfM(%y zIVI!sw>T1X=?+)B3qg}lx!~!3G?e^wm^v|UdeoWr?AG7^qQH+PF}y$W z$M7)6)fGB^{__{~ptw6FNr|T$oVFE32#A9}SUPXi_v6a6KD~>QQnSAt)*`ax63F;| z%itkB^`;u>@lFYzsblkn~;5g0N2#`TI+9Ft3oT0oF5Gz^7L~UR%>+ZrYi9vQPc49 zwZR~2HJn~QWvhL`hp?^G=P_;7OgoKlElsOu*jpH~j;fPns%g{GQcHdZg9G)Cq<+XV za0<)dD55cekZW__*v6Q?0dsq_|5{(cTD*H_UkF%w`Pj^*s=>Vb{k@Skxc1FlVaq3n z;Ic9rpb7!BhlYkWIX5Q*0V@W?jhB@IgeAGK@Hu+fTt{1bFyCusq*|l$FHm%pB93h!SXHiJ6#?V*;TdQslk%_<{zflwTLo;SiWGe`U1a zREE@!S*{-m{@lx`%h%&9k1|T3;uwyEU|HC%UVy3v7Pj;kkxQb-D`amD-B$8 z;!r$hHX0>S?;C#wMC;%*TEScrw3ktfQM1L`9N7)rLK%CI@tg75Asg=jZiiHxM zUxT?p`I^vR@u8&Aa=pQebE;j!FjxefkQmBRi&@c+60a`4&Nsn9zlF{swJ$%~h73&I zC3qhy8cNV-?+O3V9o0^gqjSj&!HQoybfm&V;SlmqX~?LJEA&PTr$e^n@=py_^vGLW z_TfagubEUyDsd|?y&yZK`UY?05W_XD8=UB>|Qft z8?Fet(KUwBBl*~H%*P-rCSso}QcF^w(QiS){0JAZ}^&=si9WbDL zwW-I~dcuOG335XVmsbGLmtQDhMOzXS(54aIw+RJduIe#(=0BNas^4It!mARiZ=m8C z;bh*=zOWZr*}P0N#@j%SLSLiP9$O!M95S+RZ&vn44P-*?;CXC+BPn6#8`-w zZ{jGh{&n=%+SqL5l1M@-R7*7JK?RwKzy6jKMYgE88DJF5l*MHu_A2$FfILO7uVmUBL zt?jK;f>4`7t90d;f@y-(sYmf3sL}f?p}_7*`2?@%MGm0?fI7J-)3zs;(S{7r1cJsN zE_vR>7SfCrOH5F3a3Ed)kQ-=0uh@xl`)eUQ_k<&HPNz74RqMUoZ zkjUD3m3&11RL>ewrHHp8MZY~Pd!=-vCNT7?tYMTFvH78ZG5|OVK(T}%AH*%ZHrJoz4hO>{vLFI~La-!? zXE=mrVm5C~296y5Rq(0O*h175}jX$vWERKbo7o6O=_wJ$a;_a`MvM^{L_=_JMM8^=Xo5TETAaasqn^5996mUUi zx3v{ZO-+S%@!`^cVy~5i=wuaPrj3&B+Z>*S@#~w;nL8^-tOop#5 zX{Sr(7!5MFJUry#EU{Mq<5 zW>Iq1L&?S69oWdBbLV2ejd;!xBP|^r)Q8m6C_$w_LYwjDFGDg~rbg&`zEHr%n8FdTjcMuW zPfm!E2N6A2MTHtZu8o6(6)?yrPXwT5$xU@|xRjL%WyrV|xrX>)Pt(%_z_!6{ zyIVh;^5zZO?TSOV6!kJ#aZLhP0fqn3d+CSq4QY= zJzf)gVR%9M1z&^W%#XisZVBHWA1Ep+N*i~LtZXbCteqy&^7{8oBt{8HWx2 zTkbYkS=0n?gER^t^uwo5f^1t(8X4(;`qV0WfmvbBZO3JE9sAY)Q{*XgI*wWqRw6JB z&6Dfv>*cQxP{9q%Z2vSi_RJ7eSn9K9G({$Qk{oQx91!sF=1_(4)o|tEc#|h*2^~qe zUdBd#5N(~EMkI%plqAB~f>_PBPxOxs={qA33#*g2?LclTE9`B?k zFK|7*uvLK~QkyEL<3`f{-ekNRxXC7YZFJc72fH>^4f?jqUo7kikJ1+QJLNgm`GGFo z=bPw*PkGt*(l+v6KQK$ou2}16d+Qc9`@MlR5dLZ>A0yvFACrmW&Go{~1m1~qyquJ4 zPFHC0sLe)m=AKj^(4CFs0KIrOCT2SrN>Op~5;K+bQ=WRUKc_%3)Yr3~la7sv35HE{ z6_4e>?dmbtAPdBAFmNCy(K*)5%`NKTLtR^26CFu{gT57um#b_3nAqE{UvCNu@~j#j z`twDhxgTjt4tF=B$Z9~}sp)DZcS?3OaLCjB%Htx1i0n-N>VP7wiV%mpH_ND~0PxH$Y%P5A=6(zjvmMS$ zlhPdh#idW@W|q8xr{f1Wfl#4m!T3eQ#@6*$1pYsj&&t}#Oaq=&@M|7UB)OE^$l%oo_)}QA z(4~IOHr*p(qTtv^p_dU&a?;G&NrNwgvlM+(<7!XZr9Jy7p8j^)FgR$FWx%GR6IwRASw4B0`&YQK zW~a{rv6U`hCOj;q;R6s7bMd`9B~`*cSyo!*&HicAcLtFU=3RIP#k878w9jPZm@xiR z2{L(036CelM51nR_SLms6|x`Vy)h}p$;qj$t6OQCZ!Uw!#hGscF>Hxjxa9YzJ-~qn zW<7v5R!lF<1*)#xLSuI7YJB{Xr6pB)Z&NeT%*=Jr{&7Y|Al9}?x8iRj>ub~Nz%}F0*<&}M z_+VHNcC+f%lUL087x_pgD*L&BU7HB~kt1W$(#@BxQtCgat;buRI4|z;@85@_c>_OI zR^f9sgCcQf#c-Bu?1X6i{tOABloFUN!+|>iMFhY=wNDxN%k@>Fd|eg*GS;!{TlGcR z2Cy8mZQuU8W}j~)mIG}4cy`odtZi@`{Wj6rz~#qPSOR>3G|*wMkqiMGIOrPir~Y^; z!}9R!+Kr5MU_pGa=bRI12!&i+ z@x#&vU;)U#H5M`em%t$4c3IZP>;;!C1xDfTWanX5*8>#6X~HXv)HY)NGR<=Y-+RZ$%KZ1c~yY;7gq+@Z!N~`yD}3Sf&U6c z{X@)}rc5gz4j^ncSZ{PSMZDGOg zwW9L@TII_#fnQ!|;N}r?ado97RM(f90umM7x2PoRFSaGG3Bxn)kJRGbN?yu#rv1=ESyNh`k$=ZfT;!_-euV%cz!F3Qs8(H$n>0JAV(WLJz9Q2# z8Vt(XEfZV3xxg|1ofja|lwN)1vmlH4}Ei8n{t)Ou2-vmnDE0yZatIG?{pltwb*TUzo>nQts zVE1HB^?{EW=PESR2Q17${RdW6oWE8Y04}`w$zeEwr;Uw+O(e8Xl5j49sHq%wdeUwS zU`gEYRo|e)+Hw>!6}XG^h>U2QMO-5k8pEY1A#jG{*0G%ckOE(Utrd|Ab`VIDlP@`_ zv~xND&IcJ}?v$4|qSv%6=!&c##@U^EHz9#<#Td9TKwS+t86-_}<$gzw@VeV364rp! z@d5)iA)Tc+WVeR|ARdA>aQEK5=_MtPh%aBxAnXD)bHE`{9@QgO5)=<)e!w7el_vY8 zfAuaV9oiEEtThh|Hk7n#q@J7w!H%mJo0p|@{IlKr00IW&8fR@ssU*Jr@bfb)AvG%P zpKf&(T(gF2t%zPhC~KikbxkT<>Gy}rv8*9AadB~r@5OwhpcoPD{xX|T$k2+i1ydQB z>b3yzx zaq%PuclA`5oX~IHzcXf-_sT9#TJz7Mmtlpz{mww4v4OW_&__6Zc&p2Cvk%%P@zdNk zYUu}33bt*1!~-Kh{kih5hx4JX$*zq{arW1Qv&?HebJR}R;t3g77G^BFcs~a)z{`Sy zBDHrrqjYBxlU@6F53c2~OA_{lA2Nlm@75qvPpf?GOCL zgj=TNb;i!hF)52;<8bH}MW|2i5SKH4`$Xq$RIv-4#oqHeu#li`O}e(ub*u-b6E>7# zgG5c-*|1Y~W`D-)EcccKtR2L^=5v|t_d+(U; zodwYbJ9^&^<+`^N4DSBvw5CdEGOor~x?Z&Kn0D6imIzjvTYw%0Wni@{S&;Mh(arAz z{rPEVGr#U6OOFAQznnL1gzrk_L5#dK)OQpXY0`r_vprUm-x7pJJ5mm&MchwnI(CuO zi0+yioSJ-d`Rpgrw4=i4QcGcbq*XU3zVO*S|j-q`4g6xs16a??0-OV-f(_t->IbIfNyS zx5l`bcZak;VR&Er{o#?71W0NU3wGq@hV4yQqKg8e?WGUmJI9iQVfWBVINtPYcV`Vb z0yQip-;yQdj@0nykQ?;1@6?!SJfD7iL_~Y&HMVw1Sw4s~e#@5MqyAx(DxTgoYDfGr zJ@}DS0-Em+=s8_r2$(3-Y>(kH-+ke3>C*Af#HM*mi52k=mhgbUj~bUU!h{z~)Ol(B zbU_qqEv!b;pR#%sCTWvpd{p=2fPdM2pTBC|fAxMF`0SYW;Dc!RFK2~Xx@d#*rHwtg zN&YKW<_65wodSZPArFa{^5E}K)J|>@^p)-TNC|bjxI0H}z(N?b%DfjX5ulD%@A@Y- z580%Ew(*s?^Bh{tRM#_8_-XvBF12jqqoE?vmFc1jIqVb#U5SoL=scB`eR{k`z*uSs zM&>n^a!-Hmb`7gBUtC@DUld>r9DMn&(bCQB@5TX8=qw$!5 z0FBfQYi~ANDG3n4+3Sj=b^QE5M1Ef$G&fSh`%?SGU;3;9>$@-9r|M%M<>&xu|MLe*vCoJ$H%2O?aHKgTtFlBk&@@{ zmwa9OXBp|4XFcu)RQWe@+$ZB>Y3r7NvFYj2rO{+yd9z>7U!!CW(vXl7H5G#( zfE^31FmE_@LDxNg8Zf(nvf>jHw^>+GkXc*jQ9b0`EG#U{W%5= zsaoMk1`&$xQs89F;BprtLw(^t0^+@|#0`c+?)u@PUeXE*x`12}j6~UtvKqAOPB6(NcAMinpJ_g% za8I*paZwJ9&Cu|Aa_KT-=+AeoW$THGrP`@Io3};yZ{eZhxJ_wcVP6+kN>#U4&;DA{ zn})pW2R~ZexHyep^?K%?Dt@fhQ)h7>eEn^+B5`w^rSz^K?R<~5X6pES&nVLq%1*P} zlx>Zpd}&1}H=IXkHf%?Q*lluI@Yf)3hQ*!X0g%kHbV+jI|}yTTZpf*7tE99hE0$H(NxuY7oA?4=jN z(R-Om;yGX}I8~%P)m6Z{B>;_qAWIO^uZHEm%553?qrgF}zrVSHRGAsXKKSpDDUfY# zYj3adr)7O*oOR~hIiY%KL>Di$q#Plc#wKEIPP9d|%GLGRJ&P zIdrHjbIr8%Gj23+zIG^y4C}bKYdX95gyoKFc6+}5cKV{g6IF5OgM*e`ZbWo+)m)Qm z(`_adk5AKerWf_Uj2>=2^)V?1eI+(8)oiLZ$ocV&|*-OjcEZ*;jLq=vMU1odmM@wJ}|1s^tA|k*4vwrF4 zP%#cV%EifEjdxGSp4LF+p@Xk|Ty@~+dxs_wwgp6L}wQIxq!i9Cd zeEljdCwEu89<*a<(5=U!Tb385t;bu_L9B0t-ZZMRAP-Ox_g`=ztBUucr0fru)86F- z^iW88?@=Ctg5=+|E6_|*8{{kCNAmKiuCDf|v+l??g@o(mneg=+#D_}n|#n*i2xc*M}HbM9Xj*E{b>GRJ87%h6H zl0U6SC%+Txo)};5)VXtkRsG0#`m3&v z>vJo6-A99NX{33Q4J!=%WZc~##NiS@fk%r{`~eV51plE)55Y>lgupflb4Ep>tHO#f zFz-d`$@%%jgXGmoYi>Emo9O>ZAs2%Jrn-w}*9}Q26Sof5Cy3$wb4wnG4kCYwUCAKl z!f~>XVWc^f-eR`gJt}EsZLxQc(00cCE{ikTgBJ|$6g;Q(G3Jb^RCm$QiTnNAkw-ar z?mcD7g?&-R4Y&AKDDHjq&woj;le3Eu5V*Cr=G*tB>S3qs4=S;3PrFV0e0&PScx$>^ z{nFY~K1hq{Y|s&G?h4@!GV9IXQpYBgI&o3tzrrk=`- z6xu37OKTIVNg=&`uX_5ann3e?Z<}m)ci0GV25CIY%1VD}Z%JkQ=binvYZ;Fp-`qsd z>6Hc#*?)d`AOwsi`VcY|P*%o^^<2Cj4f3Uf2`AYCN=iyRQmIjyF!MdZsl&NJ2Qlbg zi8T~Z52O`bE@A-{K83$0615;o~euq^-qKxl`7 zkYzw9irhSfSQ3^MB#Rx2V5i-~e#u(i;oE(NISNYldzFdk04exm;4kvXPN?9yx|~RaBgN z$DMMdQ-CIgZ-5C3HE6EoaepE?vn$y<3fm@*)oXEVtk)G1 zah~X~#^Z_(YPTiL8sw9sp?hH%!NBf_Yfyb~6MRG%W!R~I-m6aI>jv&%W43W#}Eb zDk*7lPRsntZrf7c{1)vm(^?iXQA&iX7{%I@!;sB=qw>W~Cv(^vW`}hG8F>aUlY_c% zp?qB#A^JtFvefDU^U#A_@&!G?x=|;%?mc7JT&cG!_Yg%_Rsjp$<`xl=+Hh(!2~qys zG^(rSg2CeZ`)^TW4WFO=HjYbr#ne>ePN0rbPhZ7{=09()v^CDRzI%z7JHZBJ3#a@} ziYR#PvejSLQZYFL65ea^(`U|T$Z@OeON?rnP++DxfoK49^42sRQpx)CX<#cIWY586 z{LTR(2!PHjVJ5iB9zG1#O&_S`x~6fGjT|SDBFaZwmU`;BVVU<*99u6%$3;Tv+P zjn*H6u+*hWDsa;)+$&cCHEeDy>d?QsbEzP0Lw6+IyYkd>Pu(YsnnQN6l3u`cxIKX@T2dY zpWnGr$~NJ;`zx)4NvXs_^>M!$9S!P3g(=V5ZE+__xE;X1kdRLa*+b*UPtcruvY(d{ z6`u9KwAcE+sr-*_YYSJVOvIW@+TzbmW*eVvJRx<1aYFW5(fhMo{kMMAn5fCF+<`9y zE#QyWs#X$vxQM{1%yuAwST8y6iIkblx1C_y1YgbA_d&E_uD5R!w;`6G#(<`VJCTk5*U043Xg zhi*AoQP}!~S%M^$ls>2FM8i7Jj;dym4fP*p46L&M_UaadA2=A>Y9KaUac~e}33>%% z3=5zf*16c0Pn6P($f05P8_Fu^Nx@W+*sb-Hid5zh%3@E{Q!2~AodSbd@lTAh`u|z> z6>89c@79>#$3Pb>cqmNtg;~hCJCKf35I7Tyt*EEGLqOy6EnhD&Ve)e<+L}p0)qh%= zgP#0`7?*MacHPO7TM^F!?;n+r5RxJau8XWJf!Luw`ey$&?_JmD`uf4#I^HUbgn{RR zG8k72{BlfLK_0XZJqp&pmhSG)V8yU#lCPAQ$PlVgq2$Lw((~#UYJ8+2inJXyW(bxjYgF4Q@zAbu!AhDtVOsuI^SF&=jVJ*R^_`1iVfZ;A|Dx;5d)%-fG#P; z9WJ+nF%TP?j?&~S{1LoY%rdYvdI~xbMkD#2-}CL_Q9&X-@%5{L6^_q{cM|u4I1Jw$ zpI>$vK5T+C=icoPrV^!zeH|V`<&i#t6E3^((^u)-`SV9TJ(sMV#JAF(D2%$RMd9bT zqxd@)(YN1jWfRe_E2Kc-hi6wiZe!u0P-CW2E8LRUG8tP@LHT#G$LGm}APogh;i)qw z-np6Z9vzP;rZOH{&9zwRyI2-z&eA#JPj__N*l46y+1~$Ni2Yl94$+d%oVd`s>18ng zO|RYp3Ab%nWwN)JGv34-@tXu_P|^1XOG!32O%bNWScClc7~&P#i?{eW_S|K>=~(lv z%yrL$uD7OGcFq;1rKN?KZc>xm*Lalr(5VX7;mx(_n3^W69lrn0$qe&O`i-3V!3#`O zG+Jg(W!p;)jyODgSl~{ref++mVRps~35{5xJH`x0Gj_}bn$_hpKR#jJb}BBt-$u(n zri>U{dY0`N5GfpVQDyGDdPQGNcCh2N6PX8+<04NoOHhxdZRX1wUO zr)re%sXZ6_(DQmo_^zqfzv~z-B&}MB6|6iRUf?eX~#cHi>P8=1YJuNn&Zm)p$Hz+d3V`TT4P2{Z~(IgHU_L#ri zwP`~y)2l!6DiaU3`ZJxB|EsCP1m_)i$UNaf znax{PQK@)i_1h1@?sR^duwDy>y}M!&$&BfnL@V88AVTj#TT3fqkD1)CWPh=t$J zY=*OJbN zX-mGS^>02nc4q7VA$DhV;F=z@zq8N)1N>tmrS_w8t4Xruou_T@?Yvv1eMt81$&q=sMIELCk9FmvW8 z))L`7?eV+)67R)Jm%r_cwvSmX-^b)!$1TL_{6?v;`tyj8fZJChaB;MY<-_sQgG{?u z?DMI0Hm%z|-&Cqsv#;lG-`{$r)d#}w9!cHtkzQXdi%qcRj8nOwbb_Z}qCK4S+9i!?&8rx)kvX*D;eBpUHA$;BV*GLQ>19P;1s%gWm z5y>N+52coUOgMkq924NaWoD?BaaL-#etqor1f!)}vA*X*TTH7WbBDEG3^J_G_HNVs z6mhxv#o0IpF}L=>#hNaMwWV-9lMC_X_J4@iUivq+Vs}YrYP%;j0#iGeIoCru254Hg ze2D>l7<^`wbtGQ}VgXGo?xP*NydxhXg-~o6WSayD>p;zeUmS>VE}VE|8xh<7*47-q!6#c= ztWyQHB5hS((CbU?+2mvl3^PEgWwNVapGr#(6a>`31S$@4vKtP5d*->k|K=x+TKksi z;nLbadD_D)H{LR&I&VVB`%+R6SH=!c$DjbVkm?Qx-9A+V28#nng&%4fPblBJG-Yb@ zG-c)sLw4I9)?hLJlr4uZ?1LrFe(mx z6*{(#3DS(DWfiGjs0VOpBO|E8LRjVPfVYUVK-Oxn#ZwK!yA3Ahy#QgMB1X4}CJ^ZH zp;Y<#oqvt8wK?V&=_H~)v-G^zwpbmqtHQo$q7tu7UpAK^u;EgGYSx0Z*F;&WipJG* z{@-?gKfh`5ch028%9dw+W=A=S&yPf^7B}0SUAc1m7{AhQ`E%36?`Zo-nj@ON>%)q? zt*krEr3<~KRXwZj?czr}Irh4a#(x{{O8)IPRJ4Sl0JFh27dh=HBlE+q%mr~M$|~g* zrg?4-4Ov1S$+K?K%xH_mTt!KaAq2x8=j1Sc<{LM>zFZ%t zhbxf?hxj0MR`1Y5w%m*P;yaLj>?lB!sZIpPg5gaOpO4ijevOlJ^+ zk`fbh2Qw3Yxk2i{XfR}KPGUAz{jeYheH8wv-S%FrfDQ{-M@uU!^SsUzne7-Eu|epb zH$XpBoG3xPi2vwH%J-JiEnmK9U?f*iP!O8!?BXefM|##JvtR;KQd4hx&XEXbVB2^a zcq(wPM}I2PYHizmNB_;x;S2Es(?P#d?>S34r8uXEdQY}iRP?iU`PFePpKfT5-R9__ zSHgR5x5db|LhsZrwv=4fVOM#*k~*$4Gn;FO#B$Ubfx7ay&*y&n)wNhq$7kU@92Rar z=b>a>O8+V=>mJBMl05>F6`bw=kYF)`vBPSTTeQvG8qd%vqCcR z^XDz9s4wcGVbfds_xxw?1TU9DQE%IFn_?+^c#A7p7veWruW~!b$*G4iQ&m3m*at|A{#6r*hgL-(x#GU zk-r-6B&soa_(@u-(|zs9FU$TZLLVP`-6^guQ5pNSuHE-s#ht0*!?)Lp3JQAXti! zGE+&18Fe-FL=RZ0^?y0*x*&b8m9HK|#(VZEwmJmZ7{QK0wFKiZ+E;PAWPNQ}G`RBO z`oD9S+JJx~^y=F6s_tUG+XI619#LUVlKb6@2tdV6r&=ioj_&|on(VPc|@4y z36^pmMZM~N51@{uR!JTmj6mQUm(ds&HO*%H`7fL$DBz0o+Y{}tx1BS)%ahf0w_1>X zDe=z@ujhD8=d($-@h4m zcUC94vEGs$#5wk=U8cPh)9o*xUZ43E$5{WkAo+w$^{vKIq0yIFEJl%?-GxcD6&59h z?mOFmEJtpOe-V?lSf%nM>drxHIwJA#uUR`Etf#TZrnaapikmoPQlP8>`_BNq0s9;6 z1Kk=#8f7WU{-p2gca&TF9b0}3EIBluK@xZYfW0&~>Wm2`;JUqZ^!xITUhfuK%nT=AzM)?Kfm z(*V?gsy(RA}&o5NW?!O9Uqbc`&v+T1P4h>r{?Igf#4qLi!T@kx z=B`as3HrL_pOqeRANbQL-&_n-M%Qf!lI5H@{nULM_FKO~1L}-Ma&yKPK0;^c;36R*?VVb2GT4=nuVnuH}Gq3Gswg zh<5YFp%L{ftupWBNHhb!D*7cJdTP_jU*C=#=`op9*`)uWf$*I+MHj~k)LFIt!8`(UPeBlNA{^PIvMlcD z>4~U7YKx6T2yGBjEZvS(3{c8vF{%wcF@As$2reLUVm4}ZY)tUwU_yJ(R8S*1iy<63 z$BqdrDspjr>>iy@x_dbRUK|!S*c<>i_j~>xT6~KWeZg~h8%{qERg8wVw#e%oo0`&$ z5{CJsqpfWQ7Z2Wxc-cjD^$q`{6Ugx_a6%y2K_*OXw;h}&hfIN6=0g<&KK-eFa-;G> z_w7#mwa~`N@!_E%_}HXk52xVKqt9T{;nYA}#`G2VG2jTHA=cE?09w67d z>AV4!@sCYSyO6tpu?Q+W9yKg#U3_VnOAv8!mn$eJz-one0GkNZd`O`6X6<9ghCqDp zL|9;!7_7rb+xg5@LEgtojRhy>bewnAvuyzb2PhoE9<<}=m^W)(uss)i^at{;u0cC zGX81pf{FKgQ{UO~xi@*-#9HZotSDrOb^GkSrCtHG&#vvxg{ZB_Xa zyl=AR*@0FW%vB4O-VjLY4!A!P$Z4mgDn_BC&!H{8#8~& zF~M13?BB;mSJOHg*<gRkEpq%Ff1N7pD9e_@H!mOYDbGiT+s9s( z?~$huBz;8EOL};kVB3^$d|Z?bP;^}{A7dbj1->Go(2r7O|7AMA}yi^8U6lNM|I@TERDEn0*RMC)Vzk@D z{wbGM-{&}JCvj3fI4vsT49jalq35-3k1u;#j;Sj1c&mK)NKj_ESvuSluiAavLu`wa zOt5YiZ&BD;vHLb`?X!{m@+?8uPP1*=x&1KbUY9@4IxNBBssBy{_OLodKh{?oK47-M z5M`yuH^;ME)IudXEvnXgB)VLP0=R^r<#?pfW-u?+Jv{YZ z%g1{?C<9b~uQ3s_le^YcjBAI#ELJ_YU@-Ym#}3zvuh>T>q3^-S(4D!V&`7>U9x1QY z(6V)x&YkU1oCoT-!lKJ0vWyi+l=)QF0=1rLa!t0>38!}HXSa>@ehkbBY3bEkS2oqY zdQaxBzS174(feI0-HYL0s6Tzu^wm46xb!XK%1ZdP`)|JI68jSWaEuLI6?^bgLuma; z(_DWopWM|!rqC-ZmnN4~J3l5bRZTCY)m~)ImWf@9EBc=TDBeMz6ES}e8}&s-vytab%*>McQOl6_|5Dl z$Nt^?4-F@?3$q<4t3CdWXTSnJv2vjJN29*)?`SE?L`$QQ2H9RJvsW){k9G1~E4luC zkkP(N^UHKy*Y{v<#^k>~KQR6{P(7pjEyC?>n_U%zaML}_tG~-iM+GL}-*cwUxt<#o zf39_^W8M;wdwfEu5jeZ5$<>5x^Ol<#%N)OT)B?f^?TX6(a(NGbQ=L^`uq$bu8_CGd z;WuHFXgW`!CU-bEWdL7EFL)3v$6K3G7Q5o*Qlxobg#;S^N0kn_G;B9*b z@=AJvIDi`_4JdM!Uc8jW=1haEO04|=x3&;lwmi$p*@b8mN^9gXNCO-bst}+DZ=AiT z8%s{=gH8g!8mrgFLl(K!TxatuZcfZxqIey$babt13;6;q@1cgKrAgHIv zxWh~1eE3sa$d$Fe-U4U~T2^VhuP<3I|5>om*0&z(Q}Z@8jk7-pnCFA>YyZaeB|Z>A zW2a8h{GGofA^P5DlH=WdHu%=JrW_)KyX(SEIyNc0lrQk=oPHW1?JPoZyh%AwH?!t` z^zDN50OHTmTub^>^ADc{A{0v>?&$bBFi45ItrIR&y%Sf;}Tf&LaFf_2VcS6d*XPUZuPV z4VpSSP`YNA)@PWo7fqEeT(C5Njxn3_;N)g<6Lh($GlN7yYYY6dO| z9XZ6Z8q8ZGJw)IS!m_gLM^26*AW9NPakQ_+fnqImJ2N3>)I6*BXXr|sX3WwRnKY!U zF#IzjQtjKgu$Ssu`IrA@>W>%RvCS>c^6MCG*}{>XwR4*8BLB}>v)7%P3X+3$Ld5v|pR3;v zRg^CH3FGYDm0hF2+(X0wcD#Hcc&%m&OK`~SL0Nz|T=Kgl*d?X?q8>fM@HF{fufLwY zVzf@(TF;JH^Q#d(-n`?Hms14z!YzG6uHH@%@UnW6u&Li^rzVB}9%J$Cc=W<+`%Y;v z7${fB7?;cVDHz%HM9kh)w4Qc3r7_vr5`ex~m@c5c4!~G89Cv7#bI5IkLsRRY_4sdS z&DdDqlR#eeC}EPwsxUKad?b(CjfH+QDxWkcB>-$d^6{clC7)|ThLAqp-;F1fcqpHZ z^54CW$^G!gL6vn+myaLEqN0O52qn>6j`*W7=y3!rS_Gxp_h~W)?#Rv*%1_x4-Eilt zEw=3aVzxb$w|Fk-FhlY<;~<5xB9&{(NU74!&}FG)x;&<`;QIrpLA+JPfaxi?P#*1MYp?|RK|U8kIj8cFOwD?$^S zv44u9@CR?wKO%hBK1)-oTiK1-`o3*OkfBvZc;wI zJ~*Jdr$uyY@Fr%i|7V$p@49f#RQHp%sfx>j!)|fzC4mFmPCHC#C;sswhP3^kuK9)< z8Kq^ULpu!9O;^Y)+{Sr3;Lqx-@5AuQ7qO ze;wsf$;nORtRJX_Kp`LxZjAn@apcG*0D2@i^YUVO5;R~k;Ekmn&={ya3X=l|EH7Jy z9dn%XaGd%P;@T?gwBFA*wn8MY3%E9NchApj8(&q@$W~EKB%iWTv}E-N6Nww^4_oB& z2daavdo|s2@7Lchefh&>d3n)0kH$d3*=HslkK&rlY};iQ-9aZEjaD4N!NY)F!FOQn ztn{^>pyK|BA7S5Zsz;qJ_2%Aw<2mPum|A0lY}@ZjI%4dl!6~bTO6=uQyQu4ul!crr zZS8cD;=Jr`6v}ah1A)L90g96^I5nZ#J3~| zY$L3wiU8_O9M0N}I}@djR9q;&HyNLt>fT#Cw9mV*`k;>BnbU{+KJG%i)lk+!sh-$# zoLOR@^%qLfJ^M!836H<(9Y>fOi=(T4eQj^QzP`GEsaY_w0j17i4)6&B1E5Y|HYIqs z6am)&-m!&_j%?meKRxyYL?4Gv$N4j7s)0m6aadEw+6=9MEOb&^IIc-1BqZ!c*r>Re zEBYf_(^PCi!chXZOi++eSoo?MGQH>gHU8R$tXD1 zBFOp33D1^LVf6)Y2t?Db!ff#aHw7^_8_DEu%Hw%)Mer|=;t4MLMFqtmFQv54acZMK z+tZp70&}t$4r^{s`sc+`|0zO-lM@9==q5TEM*7Ej#)J1%4>ddNy8O>Y;R2Bu8bC+O z#8juHmWE;N{g==gDxPTx4)J^THG=uIN7y5!?*F+p)gOlH4TpYNLI8;mA+q7YKF z$TY0{6L4vVHwWL|Ne}FOO;775rZT_T2LW1 zhOf*hF`hUbX?hIGZLzTgvR8t+Q&@gjkDMgU7fhnG?yn5M&8Q53SQ>yB#x9FuZ|@{t zUnV(qdFK)4Edg;VJ_?ZF?shoKtod|h=0u@fx${z--pHtW#rMs2x|kHfcRfDrcAoM( z=-652muwb)UDFX2tHj!+dt{U7mYwU%1nZc*)TxE3;^{DXK4|%HP>_R%ycMEP^<~@z zJ{JZWRe&S}BY7FqG6~2+KO9ttiw=woJ(h~szWC}UZWa^<(stW56YgCv=nX4K-{gFO zm$s(HaF@Qwx886(5#(RubRWh8C&X!2RtH&pI`&X$M{2_z+@9AvI>Lo{^$XE|SXOmI=`+i#K~0zB&O6C*t7fOQJbKHx>$K$#c{cS`+UIT$Y}kZ%Cu!60WAyqJnJ>IeED+)` zDT)pSt6Zknp5Gr{`aVb#;rx>#Wms!pK+W^g)+_Oup8DRSCb3Eh&*Lp(*@G<)RX)%N zCB5YT++B85*Fb%sO+(L>OSI4f@rF9C2F51lqV@Ih;|{^II2PA-S&!LWy-E%MA)jjl zH4$LhSu(F`X@sYBU0EH-oKhn8pz zOI|!)oY3gVt}mn7*g;5_yBS=js~px`t>Od9$6m|=lZ5R^e?!N)$e5(YdD&3YE}oDY zL=b>p!g#~VLQdfj-2y#vCkMUL57&;!$VfHxLTF{d**`YOB%fD>NCnDzm5Va;pf=o?W)rRi)@H!OJe1Z7l5oS35&oSm2 zg*ybjGdFWmH_CHp1l2(6tK<59f5(0rM#dB=&PW#p)GD^6Nqz4RDVarJbIEVHi%lr* zLBLmY$_K$HqfZ-q34Tw+bAvFA82S-DjBWnI+FC-BB#MDBbKZk#hcx{q^m!N_jSJ;N zV`EtClc=;vdAeK<&pigrJ9um35|96Wa|I6;VF?ay78Z_>@szerWL%w1Cs6u{2vE)y zUN@}&Bsn@NbVVjEeBZ*xyB?*M;wE>2Ii4`oh74@O%8G%(7|MW}NlP0N z+8v|1rVvS1*-kk|w|ZNGR0J4ID}&hHo0duNKKJzJHf5xKv|J=LuDLyZALnUJYb|QN zmlx}PEcB3e<%|GT|7*b!3YyqbI%R6Jwx`D-gd1=t8xdkC&B#YCdCU&%mpFIwzLc7q zgug{y*u8OzP~L?qVvbFMI#OG>Y;wBoQL&-ip>Kol;}jUJ=PsNQITIRR-WUF_Q=#y| zA#sZL`OiC|E^~A3QTt5EoGm=C^(Mc!-_BioPb(%Os_vx!E?SwD{oO3JO6y`c?}C%v z$}K6oHPwcq(-WZ_r?vc8)7cu=KDb5KR`2aB@cy@DOXX$FV;k6F#TO_!iT}B9{~w(T z0=+hTn$53jm16N1k7#bVW< zjogl_T3P#}l;@l&s7!s{IIOVN6!=mv=j!@pt4L=^q&ts_5y1{?2eY`=HH??kz5bRR z*PS(~bWohiHvVL=!WCtFRAy*!%x+z?Hf=)Z)q_^|8K2fq>?sFCQoeH97_Z-ms%sKn z_+CuO@vJj+)o|zYBhIsm3YdN>8XTH;h3WLvD(%(t>vwiv=1wfWunT`t=R=Zq)0+Fo z1Y%!S!a3=whua84X)PzgZxe6#8x}uENhm+w_OJJ}%UnSVCu=00N3bz#ENh4V9cm7_ zcR`az1zTr}Xr3Jq9=hK*^`ho}%tGfydO!Z^psf`B!5u||2R<7GEN<=^U=Rq^xDyhv z@z2za*df}ySEh5DWH!@{4~IDBpJiq6ij+}UX_RoX`VnS)Z3DqSR#Bwh}-e-qr$B*zdUL)3=mW14fvgkiL zAv>nz)NRMT>2-``h_ZFAFJ7$j`>%1$#h3aV7v6TPuBDLfsKM5pc#;S`6;sd@49gkNny2C+5tbpmF~nZpWS%aYX59__v)uHT&lvGsn*gw+40^ z&q>H7GYoH^Xb7bpdv>UGZ07HQCm*D6E(#UxP7HBe3b#0BgjW*C+2~yBLGf-OTjW}W z&zq|^cn_c2-aJ@&40#V^+iD_`|VGu!)rlB(T@3ig3rwqs(7?!T=-J|glW+( z-;or)+)_+51TBo*H*e(7KULwf;jprh>&fSL7Xw>3#0!lXCA-fa#*dF(@f`YG!q9tY zPcXO8P;TnMIQ>T^Mk15$0?+fS)qQ2WoL5RXU&aqLmQ&jiQ5TBmjYaPrzaHbt=|)2y3pA2r+v+FVMXKZ%rc z7~5k}IZn6M{0W8=Y$jRMvT~yu zoB37hpnM*U@P#(Ql1@{h@qI3ja4}aRZSZZ=KeC9%=J*PAdhp$DxY5jd(u>iazr`oC z=k~tV-dEe|n*-;fC$Cz)@??766VpGu{8KiJ^N#lXTgm1(bX{+4zR&Pc(928-xA*EE z?9ux3?e9s`ztqHnD@!7SWuO;_{dZ;C8@YcE;|OuB^&Vv4Oj=Qy&EEVv_k#3oQ~HC` zmmXi=_4W!O`Q>%^nQL@f$!k)FvzDb=ufO}Nd^`U5R^_*eCboCi?qpSeXDqwH9>7m? zlZL`y%IxtK_MXb?X{o>1j>|h2vLA}tRsuO~(}NE$?);>6v|m+zbM40cMjpb&AVwHJ zF1#H;|8_Fnb)xFcRUiLBuJsU)x=SlNS+$N^9bG86^pm*qy+B!4f@g5Cc3m(wOrW^? znS-j&JQryh1NR`1@NG^*`U-HYd2X<*r`; zqj7(Pp*+oceeMshcjT1M#CZ1-mBh8XCu+`Ep5^LXs7)L?+oYz?*jzM6d&l_ile*$~Hrj{kotBP)fh?2b{6Jr6}z z99xl@kzM9F_WCFx$t_AY;xkheZRl^xcBk6*B>4p=XiYPdp=*! zF)y#?!ODHZx&6lLIez9C`tGg-!#BCU$OG1*uU7o;-+b(ly*dK1`7k`gTf_hYyqYhu4}V z;rDxBT%&{DzO>6+x9`N4#BMmVnLl7(t21?M zuJh9RI+pcSwUw2WnfHwa1YNJ_1R-XcM4xU#;clc9Nbn|XXoz~B?L6ouGtj#T`{DUP_ipg^H4^!Iq8! zN&=^R78P%lyRNqxh#{%H76xwmvI@s5gQwJ;PfXPJ=K=A3KUA>WXun?9_>I>b&)J5d z%dD$CgfEv8b{=G4?~ONwgXY0Cibi^{aNZk_h>Omv5A@g!WFBDW)O{RT?tq^Sx(?Vu z>VR>NdvRokCNN*$N`B&k>QOK|Yw`}9tb$X2%^a+Crfg5m@!p+W*X9Q7KJw6RyXv9< z*=*a@&(6Ln3#ltnY0}5ZHll-*&d~V;!@tzR2rEX{Q>qtXR$x2Zjgh~uJbw6L?9Z7_ zwKD}WepWc-PxS9JRa};-0uTO@3d(U>ALk4l1|PJKM?w zk0xe;0}Vkia0N+lg-$1pl8Av5Aj5^_OT+2b7oF5)kSSIHkJP`@$qt>bQi@#^FM{o} ze4or1L=}t4hw+xbv-n4@xi@fBQ%wtOpKI`08AnnAPVz7N9!0#8ycUHlHR&)RWVqE~R|6S{R6R5ZT%e}k^p#aDbi(Ej;1!~Sn z@*lxH@E-<&k502Knczd{f^rJ)YZImf*z=|PK$KfcHCe0Rc)P@6`}6WxX$UD>@KT>u zAH7liwL-0%%~0c2?-@X${B|&=bcfiqPR7v;MK%>!xA(+d1eQ?Y#N;$SmtSK|s+nL%}NQ2knRi$h-|F)5iXKWB@Qybzvu5_)<&&5yn- z>x`^Z3}cNqmLiCaIvDo$p-t3~(>!W9;7embKIY4)$^fGWqjYV^0u%p`VyH6DATJo@ z^&x(OgBU3ArmF(C?k;ci?I@SZ2WGp;dt9`nyiiV#VX-7?dM6h z?x6Vf19+x6PhN;5RrD^P7Z5OF*Y=9+A{g}|il*#|1}L+=6&uU}+o}uuFkq2I6F~%W zcmdC}H<2F!aJq{+JqWo4TRf<^xHxPq8*F>xVW6r8_%oBPUo!!eER*?Nm=YkL8i48p zpv2F$GB=ViD@yS>we-)PeX9ccBLzJUHqsc<*el{q(3?x#+-{pSa|eos z4EZB&qXxQ$EBd&R!l-;E$~Go@>1NPw29GTBif=g+J{fa#fm{lkn==8HC=&R0f4-O9 z65vbVf^)lSA9?p|f}vseJBIB*+KMb9-k2fhWS1|i@@4MY$~AcQ+wux>fmofUPlUnv z2#W5T^68dKKlS8)c!a+J10i-d^v9(W?NEWf!E!>U^abM;+OjOI;-XYMl7j5ruWKbK zie4YWb(bLV;eXCxk^*PCR3I^)6ycnz4{v$)6Mt2Kv9E)LVE*#9R`zAfNl>G@03QLz z8!)8-C3|>H91uVNV^1`d5@Znpf;Fhx4T;-7HNVSN1PT#=pa-&;Fu+_)5x^zDys&O^ z0F|yKWU)i2OW8r(FAhX-biW3~qNiq`Nw|{VO;pg~2#2*lno1LvA zL-m7?j$Tof^j+c$xU7KpS9TIog%J`^UI8>U7a#UKy`rw1rm2tP?N+Osp2NtZOax&S z<@B`nHNx0FM7C<4t{J{jH^dI4Z$(H+}@Njq5Tu5~NaUl>a_>Kp$QTF2!@94ONn zawytWP*}7|mzdG3?B(*3#?swLmJ-i+Ac%OK57<%fm)pBx-34K8;gLO*o_Qy`!c{%< zC)XdyME{|R|04^2=bmJ4f|h@awJX6wyRrPnD1+jj>RFnGQ%cHZjtp%u?FGy=8xs)Z zv6G08LrvjtA9q_rJ}-e+UKP-}0a2KY*&0P#`gOvKVO9wYvjVa|l`t=;J~!{mmY5~A zC<#3>d8`0Np&lC=TOR+VufpGT@eKLrAu$8CF|>mfq8M&F(1_vKHqWN^x>Eo zyv&Q~_LshE>>soXip^=nlg_(7&KnMP-%%Xc<@T^{0ZmyT9uGe+%%8uuK2ZmNABa!(Wu-tz$24QWAv-JZ3t0 zi93qbE|^`1UupaDfC$_PwgKeBH9sHo&!n0cPeR(ytV93%JJKu|a>{2qN?Uu2`pb+ovsb{?hL?uNeg!@Ah&3|vtL$t;+05b6SNzF|9Tww-eTEwEOZvNjpNiKNk}sZZ$dUyLOB20S&ION_SyyP!24p+_gbCjtbs*6ggn{$bWa zayA5Wko+7gR@B&F*?Y4uek@(8wXyq13*gJq-Xi6_op_U|Sr^S8 zH^t&$SNvctRWfP{YV)T$9jS(!3sU9zmCp7576_=Fwb7>qL5JdhU}BOXj_KT<%md9l zrGY%`=6{yfrkT!~g!)SD{ZD>JItr#0#?{P08y{WZ6mM>kpX1di%QY4#l8IMiOx1W3 zEzFZUSo#0`d|dD2q(MG#3%%t;jUD5y4~R}@mrq})Q8j&5+#z2=sY@5vaNYnL%cSLy z=Rj|n2}u;(X?CZmBeEqHJwH>vq?LHQkjN=>O4YLClkthc|2K+H!>kTzs!i| z5kikCiEt67$_i4UaP``EZFkm7Z(&l;i$)2*Gc@?jk5XdT`?-*F?#KYEg6uRD17@>t zXvW^Mm*yt*I)1zFGJYk}QO-9mri>7xh~cRW@(%ly>`V5SE~r+nRidxy^I_WEdc;6i zl8?``uhH<G<2G#yhXr+I@!W|0RjB21ABdOP~KP|l5NUBNR4w0W9d5e^pE?al% zOIiHYdRt>v@G%jIH-=h_P_d)HD51;ZT*XT32*Z z#2@0JqP3sVnI%b!tZg`OV!!@XS*sz^6)zZ#p~|+nkzX^mXpybvR>9r17w%b>wr%xW zTuL?#y{&kg58wP6VhcWM*m|Y%$Ui#AaJhtut>yHT^A0)P_ZuIke4W{JoHVMNMZ$}} zExHSC`O5WF`-@R#@JVB`{@DGnk(xb!6#pstq(GSoH;ReF0ilQ*ZL6K}Xz}EJ6nc+b zUOrH==l$UiVzn&8r~l62U;QL|&Ko$}W*%hzl1n)J(1ZO_m4P=~$H(@&))k0Qc2o0j zAkvn+C&e}(nc}@>-UZFtck>BUJT5rxmyEjTkgDU+_F1=Z4AC2+w&VA5J-cJ_pyS)w(*?Www3Bb zx7>HQ*uT!CEIWj^F7&u;HOh3{Tc=%&P0?R&`=kinPl)ACk((JX3=->T`{=U#7~$?` zo7Ep($Z{l?IQO!_+>2F88Y&EbnWLFyXxHgPjcG|+D)SOsWs}otd}>dVW-0&SQ&dD- z4L^jRI?$ywe));Pr+dN;BZds}FqPxBN-Yq(i|^aEHmm&EHLb(_L6Fta-r>&Aq{ibx z>%qTE#CJ3b8yn7-==@DlW>8`B_AK-K55wWRkZu>2?cc9Q` z*uuF_4>Bu~wG;XDYk)dieQvM!*o-DwU}v{iZzT;*)ibr1dMRjM|I(wR6sZ{%=Yj-n z1>Hi9+=^1Uc67O2_{a=Oe`Sr;vC*1dFu7kUh#kA&%NCH1fl8{5C& z=u#`Wc)SNvwS^9MQxg@uBmn=x(VGPMa)o+bpMeja{%5(Bp;M@9W?Pv6M~K@$gEMH4 z@lp3|IHFBRByk6%q^VM!1I`RYuQT|BpE{;{41SlkGgXSm1FE}e;#0Z5 zwBPmZyz6YeYOTL?qTXCRXgSq^&ZVd&;{4O<21&zl=EqyiozcFROklQ+>N#`7xK@OjDZ0PR^H#f?TV9rUZr)AHlvpw62|um0Q%y;!#p8aJ zAe)iGr4G+!cO)e@JX%#N+A|fNCQhU5AV@Yza&KiSro0DQbQ*4qa-3vw#QYF(h#Pe- zOyc{gUoQ={#6$-rz->KT1`76CdulO0GqqAQ=>PI4mo(-`{ z>^R2uw9X;NIPNPIDU9WW&WbhKuhaxy;;oSRg{&f4 zx}{G6TU8uDGSAx_X;$-Zd&ZXYDNs8&cF1D+5ceKb(G%F>s6Q?ez& zM18OL$*X&V=cnnYDKFz#Q?T?FA64RV7Ae!UI&hLg^GI7mMSko*C;CDHo`uHf>K1M* zTlp`GOHHmCPxLWPaMB)i~Gegt#=ujBrL#(G2|of zo${)UkxKWsA+#TLSWOzJiEL8)#sCK9(sjkAiDwmHA+#FXQyI+?N|*}PfvJz)qnaLd zLD+acA^kN*ai-q!0Ed?Fds>KIF3}$fA(r>;4y74R2vZr3@^44-b$HZUeIz|lUiAiTBH#KTi|42ouW8L*fI7 zkuNt@s{_t@g;iy!yd>7~s3&r>jgqg%?m?*ME1GJ|+R4XXry1>ZsUu3>! zG|(56~lV3oqc=E#EMWk(cjQB9Qh!7pqj{TAJ?M z@0O1@AN-tZwEWaenQ11OwacSSM(o?+avVoq!7MCGykQB>{#*#Rw-Llj88Y%|z@gk)Wn0Av#o1UDbWH1_I)f?m1M-kPJHHR)8lNeRHe7!8q-yhjvLCWhhfL?c*y^cgKa3{Tk$7qoS%Vh;DdLDgh%%SjPd<9MTo zSVbwTb-m2ShlxhRiUzQ-VS3ug%zeB|1a}Sd&2`UW3S0Fya(@$4hnQp}Ps0@-8!(^L z>l;ZU^ENxKb#~C$|BKI|6zwnfitG8U&+xH>hCXJ4CG|3{J$=^);={o=iI z`yr2g_iF!bm#}#Hh|gLR6%hq+l82IF{04`0Oq%8Tx3BWU#OVD^D3i2)jk^hJjNcN0 za=*9MvSccOyP)HF_rd92F4hbA?v>3|Pv-s-eZ-K9u4yp}sz>K9Wa!OPp0c=z3B%JX z3=3QOa-{iachy^^2A|muTi?p2+9onzRp% z)0;~NYq$u<1onRXcCC1Cu9|4&l~{dNNV0OilpsOFl>RfQL;sX zk&JO(-YhJs){#{>^>HDpVk8F!6U*yW2~0<4w|w7DGBU%KJesu?7PPQJg{u2!BPS!) z?<7^JtvEf?Ffd1?wQr(o6RR`G0)$w5<0a-aK3$@OV9v~qRJCkBGT9VvYEIhem8KV# zv8d5>a;CJLHQgfjoUH zZ(8j~LH*;28s87(0q2#BvL@dTiArMNyA=Up;h3|oIa47#{n=95wbEviBf0Zdwy~Ba zC-wtYlJuK1_!+ir-o2WbB~B!6>6|6k`WqB5vJ`s6aGl@^QtB;F-7me;~a78wdLj?Dqel pZ2)S#K-j)>fC~q3S{vj3Ibj8(!PcG&;u`_@L8@pgmnmAl{9jGD*Uta| From c7b5622bf7fa4b5435a0b12d8deaf4f57923cf8d Mon Sep 17 00:00:00 2001 From: Karthick Raja <47154512+karthick3018@users.noreply.github.com> Date: Sun, 13 Sep 2020 21:20:55 +0530 Subject: [PATCH 199/327] fix: Trigger onPointerEnter/Leave when calling pointerEnter/Leave (#784) --- src/__tests__/events.js | 20 ++++++++++++++++++++ src/fire-event.js | 11 +++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/__tests__/events.js b/src/__tests__/events.js index bac063de..bc36dab3 100644 --- a/src/__tests__/events.js +++ b/src/__tests__/events.js @@ -197,6 +197,26 @@ test('onChange works', () => { expect(handleChange).toHaveBeenCalledTimes(1) }) +test('calling `onPointerEnter` directly works too', () => { + const handlePointerEnter = jest.fn() + const handlePointerLeave = jest.fn() + const {container} = render( +

, + ) + const button = container.firstChild.firstChild + + fireEvent.pointerEnter(button) + expect(handlePointerEnter).toHaveBeenCalledTimes(1) + + fireEvent.pointerLeave(button) + expect(handlePointerLeave).toHaveBeenCalledTimes(1) +}) + test('calling `fireEvent` directly works too', () => { const handleEvent = jest.fn() const { diff --git a/src/fire-event.js b/src/fire-event.js index b4e60928..cb790c7f 100644 --- a/src/fire-event.js +++ b/src/fire-event.js @@ -24,6 +24,17 @@ fireEvent.mouseLeave = (...args) => { return fireEvent.mouseOut(...args) } +const pointerEnter = fireEvent.pointerEnter +const pointerLeave = fireEvent.pointerLeave +fireEvent.pointerEnter = (...args) => { + pointerEnter(...args) + return fireEvent.pointerOver(...args) +} +fireEvent.pointerLeave = (...args) => { + pointerLeave(...args) + return fireEvent.pointerOut(...args) +} + const select = fireEvent.select fireEvent.select = (node, init) => { select(node, init) From 732f3a19d46306d298dda88e4bfe0ea127c2973d Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 13 Sep 2020 18:16:14 +0200 Subject: [PATCH 200/327] docs: add karthick3018 as a contributor (#785) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index de7f33aa..5e1d0fd4 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1176,6 +1176,15 @@ "contributions": [ "code" ] + }, + { + "login": "karthick3018", + "name": "Karthick Raja", + "avatar_url": "https://avatars1.githubusercontent.com/u/47154512?v=4", + "profile": "https://github.com/karthick3018", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index ff6fe55f..12749724 100644 --- a/README.md +++ b/README.md @@ -596,6 +596,7 @@ Thanks goes to these people ([emoji key][emojis]):
Anton Halim

πŸ“–
Artem Malko

πŸ’»
Gerrit Alex

πŸ’» +
Karthick Raja

πŸ’» From c546a6f4927f925bf1187e631ca0444001f067f5 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Sun, 13 Sep 2020 20:33:30 +0200 Subject: [PATCH 201/327] fix: Trigger ongot-/onlostpointercapture when calling got-/lostpointercapture (#786) --- package.json | 2 +- src/__tests__/events.js | 36 ++++++++++++++++-------------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 61bfefef..291427b3 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.11.2", - "@testing-library/dom": "^7.23.0" + "@testing-library/dom": "^7.24.2" }, "devDependencies": { "@testing-library/jest-dom": "^5.11.4", diff --git a/src/__tests__/events.js b/src/__tests__/events.js index bc36dab3..0e28848f 100644 --- a/src/__tests__/events.js +++ b/src/__tests__/events.js @@ -62,6 +62,22 @@ const eventTypes = [ ], elementType: 'button', }, + { + type: 'Pointer', + events: [ + 'pointerOver', + 'pointerEnter', + 'pointerDown', + 'pointerMove', + 'pointerUp', + 'pointerCancel', + 'pointerOut', + 'pointerLeave', + 'gotPointerCapture', + 'lostPointerCapture', + ], + elementType: 'button', + }, { type: 'Selection', events: ['select'], @@ -197,26 +213,6 @@ test('onChange works', () => { expect(handleChange).toHaveBeenCalledTimes(1) }) -test('calling `onPointerEnter` directly works too', () => { - const handlePointerEnter = jest.fn() - const handlePointerLeave = jest.fn() - const {container} = render( -
-
, - ) - const button = container.firstChild.firstChild - - fireEvent.pointerEnter(button) - expect(handlePointerEnter).toHaveBeenCalledTimes(1) - - fireEvent.pointerLeave(button) - expect(handlePointerLeave).toHaveBeenCalledTimes(1) -}) - test('calling `fireEvent` directly works too', () => { const handleEvent = jest.fn() const { From 6b9a7207adee15f9f94cfbd23903f9f54fc178ec Mon Sep 17 00:00:00 2001 From: Abdelrahman Ashraf Date: Wed, 14 Oct 2020 21:11:26 +0800 Subject: [PATCH 202/327] feat: bump @testing-library/dom to v7.26.0 (#799) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 291427b3..9b314d91 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.11.2", - "@testing-library/dom": "^7.24.2" + "@testing-library/dom": "^7.26.0" }, "devDependencies": { "@testing-library/jest-dom": "^5.11.4", From d9a36fa88c0d9e52e9f19639c72e32d626d88abd Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 14 Oct 2020 07:11:56 -0600 Subject: [PATCH 203/327] docs: add theashraf as a contributor (#800) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 5e1d0fd4..58552c8c 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1185,6 +1185,15 @@ "contributions": [ "code" ] + }, + { + "login": "theashraf", + "name": "Abdelrahman Ashraf", + "avatar_url": "https://avatars1.githubusercontent.com/u/39750790?v=4", + "profile": "https://github.com/theashraf", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 12749724..6bccc9ac 100644 --- a/README.md +++ b/README.md @@ -597,6 +597,7 @@ Thanks goes to these people ([emoji key][emojis]):
Artem Malko

πŸ’»
Gerrit Alex

πŸ’»
Karthick Raja

πŸ’» +
Abdelrahman Ashraf

πŸ’» From 332a6d5972733975980d5e0b3e9583927aadf4d1 Mon Sep 17 00:00:00 2001 From: Lidor Avitan <35113398+lidoravitan@users.noreply.github.com> Date: Mon, 26 Oct 2020 20:59:24 +0200 Subject: [PATCH 204/327] docs: update complex example (#806) Co-authored-by: Lidor Avitan --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6bccc9ac..529d5c17 100644 --- a/README.md +++ b/README.md @@ -233,7 +233,9 @@ function Login() { password: passwordInput.value, }), }) - .then(r => r.json()) + .then((r) => + r.json().then((data) => (r.ok ? data : Promise.reject(data))) + ) .then( user => { setState({loading: false, resolved: true, error: null}) @@ -282,9 +284,10 @@ import {setupServer} from 'msw/node' import {render, fireEvent, screen} from '@testing-library/react' import Login from '../login' +const fakeUserResponse = { token: 'fake_user_token' } const server = setupServer( rest.post('/api/login', (req, res, ctx) => { - return res(ctx.json({token: 'fake_user_token'})) + return res(ctx.json(fakeUserResponse)) }), ) @@ -322,7 +325,7 @@ test('allows the user to login successfully', async () => { test('handles server exceptions', async () => { // mock the server error response for this test suite only. server.use( - rest.post('/', (req, res, ctx) => { + rest.post('/api/login', (req, res, ctx) => { return res(ctx.status(500), ctx.json({message: 'Internal server error'})) }), ) From 50f54b59c621b93463abfe743b2aa68218ad3f63 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2020 13:00:20 -0600 Subject: [PATCH 205/327] docs: add lidoravitan as a contributor (#807) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 58552c8c..0fd4f4ab 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1194,6 +1194,15 @@ "contributions": [ "code" ] + }, + { + "login": "lidoravitan", + "name": "Lidor Avitan", + "avatar_url": "https://avatars0.githubusercontent.com/u/35113398?v=4", + "profile": "https://github.com/lidoravitan", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 529d5c17..ba9848ea 100644 --- a/README.md +++ b/README.md @@ -601,6 +601,7 @@ Thanks goes to these people ([emoji key][emojis]):
Gerrit Alex

πŸ’»
Karthick Raja

πŸ’»
Abdelrahman Ashraf

πŸ’» +
Lidor Avitan

πŸ“– From c2806fcc88d488663e0202a45e9c5ff528fb39fc Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Thu, 29 Oct 2020 15:06:17 +0100 Subject: [PATCH 206/327] test: Fix node 15 (#809) --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index eae48ee7..fbe104b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,12 +7,15 @@ node_js: - 10.14.2 - 12 - 14 - - node + - 15 env: - REACT_DIST=latest - REACT_DIST=next - REACT_DIST=experimental install: + # 7.0.6 fixed CI environments prompting user input. + # Can be removed once node15 bumps the shipped npm version. + - npm install --global npm@>=7.0.6 - npm install # as requested by the React team :) # https://reactjs.org/blog/2019/10/22/react-release-channels.html#using-the-next-channel-for-integration-testing From 0db811283819fdc9774e36155ff806f44500533c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20De=20Boey?= Date: Thu, 29 Oct 2020 22:08:52 +0100 Subject: [PATCH 207/327] chore: update React imports (#811) --- README.md | 22 ++++++++++------------ src/__tests__/act.js | 2 +- src/__tests__/auto-cleanup-skip.js | 2 +- src/__tests__/auto-cleanup.js | 2 +- src/__tests__/cleanup.js | 2 +- src/__tests__/debug.js | 2 +- src/__tests__/end-to-end.js | 2 +- src/__tests__/events.js | 2 +- src/__tests__/multi-base.js | 2 +- src/__tests__/render.js | 2 +- src/__tests__/rerender.js | 2 +- src/__tests__/stopwatch.js | 2 +- src/act-compat.js | 2 +- src/pure.js | 2 +- 14 files changed, 23 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index ba9848ea..a43cb5a6 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,7 @@ afterAll(() => { ```jsx // hidden-message.js -import React from 'react' +import * as React from 'react' // NOTE: React Testing Library works well with React Hooks and classes. // Your tests will be the same regardless of how you write your components. @@ -184,7 +184,7 @@ export default HiddenMessage import '@testing-library/jest-dom' // NOTE: jest-dom adds handy assertions to Jest and is recommended, but not required -import React from 'react' +import * as React from 'react' import {render, fireEvent, screen} from '@testing-library/react' import HiddenMessage from '../hidden-message' @@ -209,7 +209,7 @@ test('shows the children when the checkbox is checked', () => { ```jsx // login.js -import React from 'react' +import * as React from 'react' function Login() { const [state, setState] = React.useReducer((s, a) => ({...s, ...a}), { @@ -233,9 +233,7 @@ function Login() { password: passwordInput.value, }), }) - .then((r) => - r.json().then((data) => (r.ok ? data : Promise.reject(data))) - ) + .then(r => r.json().then(data => (r.ok ? data : Promise.reject(data)))) .then( user => { setState({loading: false, resolved: true, error: null}) @@ -276,7 +274,7 @@ export default Login // again, these first two imports are something you'd normally handle in // your testing framework configuration rather than importing them in every file. import '@testing-library/jest-dom' -import React from 'react' +import * as React from 'react' // import API mocking utilities from Mock Service Worker. import {rest} from 'msw' import {setupServer} from 'msw/node' @@ -284,7 +282,7 @@ import {setupServer} from 'msw/node' import {render, fireEvent, screen} from '@testing-library/react' import Login from '../login' -const fakeUserResponse = { token: 'fake_user_token' } +const fakeUserResponse = {token: 'fake_user_token'} const server = setupServer( rest.post('/api/login', (req, res, ctx) => { return res(ctx.json(fakeUserResponse)) @@ -400,8 +398,8 @@ principles: `react-dom`. 3. Utility implementations and APIs should be simple and flexible. -Most importantly, we want React Testing Library to be pretty -light-weight, simple, and easy to understand. +Most importantly, we want React Testing Library to be pretty light-weight, +simple, and easy to understand. ## Docs @@ -410,8 +408,7 @@ light-weight, simple, and easy to understand. ## Issues -Looking to contribute? Look for the [Good First Issue][good-first-issue] -label. +Looking to contribute? Look for the [Good First Issue][good-first-issue] label. ### πŸ› Bugs @@ -607,6 +604,7 @@ Thanks goes to these people ([emoji key][emojis]): + This project follows the [all-contributors][all-contributors] specification. diff --git a/src/__tests__/act.js b/src/__tests__/act.js index 97438d77..b60aac37 100644 --- a/src/__tests__/act.js +++ b/src/__tests__/act.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import {render, fireEvent, screen} from '../' test('render calls useEffect immediately', () => { diff --git a/src/__tests__/auto-cleanup-skip.js b/src/__tests__/auto-cleanup-skip.js index e5ef35ae..5696d4e3 100644 --- a/src/__tests__/auto-cleanup-skip.js +++ b/src/__tests__/auto-cleanup-skip.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' let render beforeAll(() => { diff --git a/src/__tests__/auto-cleanup.js b/src/__tests__/auto-cleanup.js index 27debe45..450a6136 100644 --- a/src/__tests__/auto-cleanup.js +++ b/src/__tests__/auto-cleanup.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import {render} from '../' // This just verifies that by importing RTL in an diff --git a/src/__tests__/cleanup.js b/src/__tests__/cleanup.js index 4b67814a..6043ae06 100644 --- a/src/__tests__/cleanup.js +++ b/src/__tests__/cleanup.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import {render, cleanup} from '../' test('cleans up the document', () => { diff --git a/src/__tests__/debug.js b/src/__tests__/debug.js index 14c0779a..e4e9faa0 100644 --- a/src/__tests__/debug.js +++ b/src/__tests__/debug.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import {render, screen} from '../' beforeEach(() => { diff --git a/src/__tests__/end-to-end.js b/src/__tests__/end-to-end.js index cbbf0973..87c70f1b 100644 --- a/src/__tests__/end-to-end.js +++ b/src/__tests__/end-to-end.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import {render, waitForElementToBeRemoved, screen} from '../' const fetchAMessage = () => diff --git a/src/__tests__/events.js b/src/__tests__/events.js index 0e28848f..8a6899af 100644 --- a/src/__tests__/events.js +++ b/src/__tests__/events.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import {render, fireEvent} from '../' const eventTypes = [ diff --git a/src/__tests__/multi-base.js b/src/__tests__/multi-base.js index 06ad0902..ef5a7e11 100644 --- a/src/__tests__/multi-base.js +++ b/src/__tests__/multi-base.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import {render} from '../' // these are created once per test suite and reused for each case diff --git a/src/__tests__/render.js b/src/__tests__/render.js index 4e78afa6..fdc1ff4c 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import ReactDOM from 'react-dom' import {render, screen} from '../' diff --git a/src/__tests__/rerender.js b/src/__tests__/rerender.js index 7cb9156d..f8ea377e 100644 --- a/src/__tests__/rerender.js +++ b/src/__tests__/rerender.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import {render} from '../' test('rerender will re-render the element', () => { diff --git a/src/__tests__/stopwatch.js b/src/__tests__/stopwatch.js index 3fe423b1..eeaf395c 100644 --- a/src/__tests__/stopwatch.js +++ b/src/__tests__/stopwatch.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import {render, fireEvent, screen} from '../' class StopWatch extends React.Component { diff --git a/src/act-compat.js b/src/act-compat.js index e999ecfe..40ecdab9 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import ReactDOM from 'react-dom' import * as testUtils from 'react-dom/test-utils' diff --git a/src/pure.js b/src/pure.js index 8a062038..75098f78 100644 --- a/src/pure.js +++ b/src/pure.js @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import ReactDOM from 'react-dom' import { getQueriesForElement, From 1fc17466722be4dcc3224b2997b9c1f3bda4f740 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 30 Oct 2020 09:17:11 -0600 Subject: [PATCH 208/327] chore: adjust .travis to install latest npm (#812) As recommended by @ljharb https://github.com/testing-library/react-testing-library/pull/809/files#r514441103 --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index fbe104b8..026c7f4b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,10 +12,9 @@ env: - REACT_DIST=latest - REACT_DIST=next - REACT_DIST=experimental +before_install: + - nvm install-latest-npm install: - # 7.0.6 fixed CI environments prompting user input. - # Can be removed once node15 bumps the shipped npm version. - - npm install --global npm@>=7.0.6 - npm install # as requested by the React team :) # https://reactjs.org/blog/2019/10/22/react-release-channels.html#using-the-next-channel-for-integration-testing From 48d2e73d8e7c77d03c63ec0876faa4196fdcfde9 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 30 Oct 2020 09:18:54 -0600 Subject: [PATCH 209/327] docs: add ljharb as a contributor (#813) * docs: update README.md * docs: update .all-contributorsrc * docs: update README.md * docs: update .all-contributorsrc Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 10 ++++++++++ README.md | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 0fd4f4ab..bf9b7cac 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1203,6 +1203,16 @@ "contributions": [ "doc" ] + }, + { + "login": "ljharb", + "name": "Jordan Harband", + "avatar_url": "https://avatars1.githubusercontent.com/u/45469?v=4", + "profile": "https://github.com/ljharb", + "contributions": [ + "review", + "ideas" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index a43cb5a6..32eba9dc 100644 --- a/README.md +++ b/README.md @@ -599,12 +599,12 @@ Thanks goes to these people ([emoji key][emojis]):
Karthick Raja

πŸ’»
Abdelrahman Ashraf

πŸ’»
Lidor Avitan

πŸ“– +
Jordan Harband

πŸ‘€ πŸ€” - This project follows the [all-contributors][all-contributors] specification. From e07e6416f25fd75df510c5d4211dc06f9f7398d7 Mon Sep 17 00:00:00 2001 From: Weyert de Boer Date: Tue, 3 Nov 2020 14:25:18 +0000 Subject: [PATCH 210/327] fix: upgrade dependencies, typescript, @testing-library/dom etc (#816) Co-authored-by: Weyert de Boer --- package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 9b314d91..e4b15e4a 100644 --- a/package.json +++ b/package.json @@ -43,20 +43,20 @@ "author": "Kent C. Dodds (https://kentcdodds.com)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.11.2", - "@testing-library/dom": "^7.26.0" + "@babel/runtime": "^7.12.1", + "@testing-library/dom": "^7.26.4" }, "devDependencies": { - "@testing-library/jest-dom": "^5.11.4", + "@testing-library/jest-dom": "^5.11.5", "@types/react-dom": "^16.9.8", - "dotenv-cli": "^3.2.0", - "dtslint": "4.0.0", - "kcd-scripts": "^6.3.0", + "dotenv-cli": "^4.0.0", + "dtslint": "4.0.4", + "kcd-scripts": "^6.6.0", "npm-run-all": "^4.1.5", "react": "^16.13.1", "react-dom": "^16.13.1", "rimraf": "^3.0.2", - "typescript": "^4.0.2" + "typescript": "^4.0.5" }, "peerDependencies": { "react": "*", From 2712dc2da46bc8af456b4759d5e4b2c971c54092 Mon Sep 17 00:00:00 2001 From: Marco Moretti Date: Tue, 10 Nov 2020 20:04:53 +0100 Subject: [PATCH 211/327] fix: import pretty-format from @testing-library/dom (#821) --- package.json | 2 +- types/index.d.ts | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e4b15e4a..96c7df0f 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.1", - "@testing-library/dom": "^7.26.4" + "@testing-library/dom": "^7.26.6" }, "devDependencies": { "@testing-library/jest-dom": "^5.11.5", diff --git a/types/index.d.ts b/types/index.d.ts index 50702ecc..953f05d6 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,7 +1,11 @@ // TypeScript Version: 3.8 -import {OptionsReceived as PrettyFormatOptions} from 'pretty-format' -import {queries, Queries, BoundFunction} from '@testing-library/dom' +import { + queries, + Queries, + BoundFunction, + prettyFormat, +} from '@testing-library/dom' import {act as reactAct} from 'react-dom/test-utils' export * from '@testing-library/dom' @@ -15,7 +19,7 @@ export type RenderResult = { | DocumentFragment | Array, maxLength?: number, - options?: PrettyFormatOptions, + options?: prettyFormat.OptionsReceived, ) => void rerender: (ui: React.ReactElement) => void unmount: () => boolean From 007b0b72d60fe018c950de1c07cb9889d7682f68 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 10 Nov 2020 12:09:13 -0700 Subject: [PATCH 212/327] docs: add marcosvega91 as a contributor (#822) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 +++ 2 files changed, 12 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index bf9b7cac..8c514263 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1213,6 +1213,15 @@ "review", "ideas" ] + }, + { + "login": "marcosvega91", + "name": "Marco Moretti", + "avatar_url": "https://avatars2.githubusercontent.com/u/5365582?v=4", + "profile": "https://github.com/marcosvega91", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 32eba9dc..c7033e52 100644 --- a/README.md +++ b/README.md @@ -601,6 +601,9 @@ Thanks goes to these people ([emoji key][emojis]):
Lidor Avitan

πŸ“–
Jordan Harband

πŸ‘€ πŸ€” + +
Marco Moretti

πŸ’» + From 3af1b4ba12dfc3a5c8f4968c1b92dba53823f9af Mon Sep 17 00:00:00 2001 From: Nick McCurdy Date: Sat, 14 Nov 2020 11:19:21 -0500 Subject: [PATCH 213/327] chore: switch to github actions (#826) Co-authored-by: Kent C. Dodds --- .github/workflows/validate.yml | 88 ++++++++++++++++++++++++++++++++++ .travis.yml | 38 --------------- README.md | 15 +++--- other/MAINTAINING.md | 8 ++-- package.json | 15 +++--- types/test.tsx | 26 ++++++---- 6 files changed, 127 insertions(+), 63 deletions(-) create mode 100644 .github/workflows/validate.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 00000000..dcb53ad2 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,88 @@ +name: validate +on: + push: + branches: + [ + '+([0-9])?(.{+([0-9]),x}).x', + 'master', + 'next', + 'next-major', + 'beta', + 'alpha', + '!all-contributors/**', + ] + pull_request: + branches-ignore: ['all-contributors/**'] +jobs: + main: + continue-on-error: ${{ matrix.react != 'latest' }} + strategy: + matrix: + node: [10.13, 12, 14, 15] + react: [latest, next, experimental] + runs-on: ubuntu-latest + steps: + - name: ⬇️ Checkout repo + uses: actions/checkout@v2 + + - name: βŽ” Setup node + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node }} + + - name: πŸ“₯ Download deps + uses: bahmutov/npm-install@v1 + with: + useLockFile: false + + # as requested by the React team :) + # https://reactjs.org/blog/2019/10/22/react-release-channels.html#using-the-next-channel-for-integration-testing + - name: βš›οΈ Setup react + run: npm install react@${{matrix.react}} react-dom@${{matrix.react}} + + - name: ▢️ Run validate script + run: npm run validate + + - name: ⬆️ Upload coverage report + uses: codecov/codecov-action@v1 + + release: + needs: main + runs-on: ubuntu-latest + if: + ${{ github.repository == 'testing-library/react-testing-library' && + contains('refs/heads/master,refs/heads/beta,refs/heads/next,refs/heads/alpha', + github.ref) && github.event_name == 'push' }} + steps: + - name: ⬇️ Checkout repo + uses: actions/checkout@v2 + + - name: βŽ” Setup node + uses: actions/setup-node@v1 + with: + node-version: 14 + + - name: πŸ“₯ Download deps + uses: bahmutov/npm-install@v1 + with: + useLockFile: false + + - name: πŸ— Run build script + run: npm run build + + - name: πŸš€ Release + uses: cycjimmy/semantic-release-action@v2 + with: + semantic_version: 17 + branches: | + [ + '+([0-9])?(.{+([0-9]),x}).x', + 'master', + 'next', + 'next-major', + {name: 'beta', prerelease: true}, + {name: 'alpha', prerelease: true} + ] + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 026c7f4b..00000000 --- a/.travis.yml +++ /dev/null @@ -1,38 +0,0 @@ -language: node_js -cache: npm -notifications: - email: false -node_js: - # technically we support 10.0.0, but some of our tooling doesn't - - 10.14.2 - - 12 - - 14 - - 15 -env: - - REACT_DIST=latest - - REACT_DIST=next - - REACT_DIST=experimental -before_install: - - nvm install-latest-npm -install: - - npm install - # as requested by the React team :) - # https://reactjs.org/blog/2019/10/22/react-release-channels.html#using-the-next-channel-for-integration-testing - - npm install react@$REACT_DIST react-dom@$REACT_DIST -script: - - npm run validate - - npx codecov@3 -branches: - only: - - master - - beta - -jobs: - allow_failures: - - REACT_DIST=next - - REACT_DIST=experimental - include: - - stage: release - node_js: 14 - script: kcd-scripts travis-release - if: fork = false diff --git a/README.md b/README.md index c7033e52..73e421bb 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,12 @@ practices.

[![Build Status][build-badge]][build] [![Code Coverage][coverage-badge]][coverage] -[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] +[![version][version-badge]][package] +[![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] - -[![All Contributors](https://img.shields.io/badge/all_contributors-102-orange.svg?style=flat-square)](#contributors) -[![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] +[![All Contributors][all-contributors-badge]](#contributors) +[![PRs Welcome][prs-badge]][prs] +[![Code of Conduct][coc-badge]][coc] [![Discord][discord-badge]][discord] [![Watch on GitHub][github-watch-badge]][github-watch] @@ -608,6 +609,7 @@ Thanks goes to these people ([emoji key][emojis]): + This project follows the [all-contributors][all-contributors] specification. @@ -622,8 +624,8 @@ Contributions of any kind welcome! [npm]: https://www.npmjs.com/ [yarn]: https://classic.yarnpkg.com [node]: https://nodejs.org -[build-badge]: https://img.shields.io/travis/testing-library/react-testing-library.svg?style=flat-square -[build]: https://travis-ci.org/testing-library/react-testing-library +[build-badge]: https://img.shields.io/github/workflow/status/testing-library/react-testing-library/validate?logo=github&style=flat-square +[build]: https://github.com/testing-library/react-testing-library/actions?query=workflow%3Avalidate [coverage-badge]: https://img.shields.io/codecov/c/github/testing-library/react-testing-library.svg?style=flat-square [coverage]: https://codecov.io/github/testing-library/react-testing-library [version-badge]: https://img.shields.io/npm/v/@testing-library/react.svg?style=flat-square @@ -644,6 +646,7 @@ Contributions of any kind welcome! [twitter-badge]: https://img.shields.io/twitter/url/https/github.com/testing-library/react-testing-library.svg?style=social [emojis]: https://github.com/all-contributors/all-contributors#emoji-key [all-contributors]: https://github.com/all-contributors/all-contributors +[all-contributors-badge]: https://img.shields.io/github/all-contributors/testing-library/react-testing-library?color=orange&style=flat-square [guiding-principle]: https://twitter.com/kentcdodds/status/977018512689455106 [bugs]: https://github.com/testing-library/react-testing-library/issues?q=is%3Aissue+is%3Aopen+label%3Abug+sort%3Acreated-desc [requests]: https://github.com/testing-library/react-testing-library/issues?q=is%3Aissue+sort%3Areactions-%2B1-desc+label%3Aenhancement+is%3Aopen diff --git a/other/MAINTAINING.md b/other/MAINTAINING.md index 703126da..cade1c2a 100644 --- a/other/MAINTAINING.md +++ b/other/MAINTAINING.md @@ -32,9 +32,9 @@ any more of you than that. As a maintainer, you're fine to make your branches on the main repo or on your own fork. Either way is fine. -When we receive a pull request, a travis build is kicked off automatically (see -the `.travis.yml` for what runs in the travis build). We avoid merging anything -that breaks the travis build. +When we receive a pull request, a github action is kicked off automatically (see +the `.github/workflows/validate.yml` for what runs in the action). We avoid +merging anything that breaks the validate action. Please review PRs and focus on the code rather than the individual. You never know when this is someone's first ever PR and we want their experience to be as @@ -49,7 +49,7 @@ to release. See the next section on Releases for more about that. ## Release Our releases are automatic. They happen whenever code lands into `master`. A -travis build gets kicked off and if it's successful, a tool called +github action gets kicked off and if it's successful, a tool called [`semantic-release`](https://github.com/semantic-release/semantic-release) is used to automatically publish a new release to npm as well as a changelog to GitHub. It is only able to determine the version and whether a release is diff --git a/package.json b/package.json index 96c7df0f..086e82bc 100644 --- a/package.json +++ b/package.json @@ -43,18 +43,19 @@ "author": "Kent C. Dodds (https://kentcdodds.com)", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.12.1", + "@babel/runtime": "^7.12.5", "@testing-library/dom": "^7.26.6" }, "devDependencies": { - "@testing-library/jest-dom": "^5.11.5", - "@types/react-dom": "^16.9.8", + "@testing-library/jest-dom": "^5.11.6", + "@types/estree": "0.0.45", + "@types/react-dom": "^16.9.9", "dotenv-cli": "^4.0.0", - "dtslint": "4.0.4", - "kcd-scripts": "^6.6.0", + "dtslint": "4.0.5", + "kcd-scripts": "^7.0.3", "npm-run-all": "^4.1.5", - "react": "^16.13.1", - "react-dom": "^16.13.1", + "react": "^17.0.1", + "react-dom": "^17.0.1", "rimraf": "^3.0.2", "typescript": "^4.0.5" }, diff --git a/types/test.tsx b/types/test.tsx index c273feb0..3971037d 100644 --- a/types/test.tsx +++ b/types/test.tsx @@ -2,7 +2,7 @@ import * as React from 'react' import {render, fireEvent, screen, waitFor} from '@testing-library/react' import * as pure from '@testing-library/react/pure' -async function testRender() { +export async function testRender() { const page = render(
) // single queries @@ -17,9 +17,10 @@ async function testRender() { // helpers const {container, rerender, debug} = page + return {container, rerender, debug} } -async function testPureRender() { +export async function testPureRender() { const page = pure.render(
) // single queries @@ -34,20 +35,21 @@ async function testPureRender() { // helpers const {container, rerender, debug} = page + return {container, rerender, debug} } -async function testRenderOptions() { +export function testRenderOptions() { const container = document.createElement('div') const options = {container} render(
, options) } -async function testFireEvent() { +export function testFireEvent() { const {container} = render(
@@ -362,9 +362,9 @@ You'll find runnable examples of testing with different libraries in [the `react-testing-library-examples` codesandbox](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples). Some included are: -- [`react-redux`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-redux.js&previewwindow=tests) -- [`react-router`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-router.js&previewwindow=tests) -- [`react-context`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-context.js&previewwindow=tests) +- [`react-redux`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/main/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-redux.js&previewwindow=tests) +- [`react-router`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/main/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-router.js&previewwindow=tests) +- [`react-context`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/main/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-context.js&previewwindow=tests) You can also find React Testing Library examples at [react-testing-examples.com](https://react-testing-examples.com/jest-rtl/). @@ -636,11 +636,11 @@ Contributions of any kind welcome! [downloads-badge]: https://img.shields.io/npm/dm/@testing-library/react.svg?style=flat-square [npmtrends]: http://www.npmtrends.com/@testing-library/react [license-badge]: https://img.shields.io/npm/l/@testing-library/react.svg?style=flat-square -[license]: https://github.com/testing-library/react-testing-library/blob/master/LICENSE +[license]: https://github.com/testing-library/react-testing-library/blob/main/LICENSE [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square [prs]: http://makeapullrequest.com [coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square -[coc]: https://github.com/testing-library/react-testing-library/blob/master/CODE_OF_CONDUCT.md +[coc]: https://github.com/testing-library/react-testing-library/blob/main/CODE_OF_CONDUCT.md [github-watch-badge]: https://img.shields.io/github/watchers/testing-library/react-testing-library.svg?style=social [github-watch]: https://github.com/testing-library/react-testing-library/watchers [github-star-badge]: https://img.shields.io/github/stars/testing-library/react-testing-library.svg?style=social diff --git a/other/MAINTAINING.md b/other/MAINTAINING.md index cade1c2a..da09ba7c 100644 --- a/other/MAINTAINING.md +++ b/other/MAINTAINING.md @@ -48,7 +48,7 @@ to release. See the next section on Releases for more about that. ## Release -Our releases are automatic. They happen whenever code lands into `master`. A +Our releases are automatic. They happen whenever code lands into `main`. A github action gets kicked off and if it's successful, a tool called [`semantic-release`](https://github.com/semantic-release/semantic-release) is used to automatically publish a new release to npm as well as a changelog to From 8a1c8e9396aa7f4843b54e31e2c95404ab8ad940 Mon Sep 17 00:00:00 2001 From: Johannes Ewald Date: Fri, 14 May 2021 14:39:23 +0200 Subject: [PATCH 236/327] fix: Guard against `process` not being defined (#911) Webpack 5 doesn't shim Node's process object by default anymore. Only instances of process.env.NODE_ENV are replaced statically. This means that unguarded checks of process.env will crash in browser environments (such as Karma). --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 4f92e02b..c89dc1a2 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,7 @@ import {cleanup} from './pure' // this ensures that tests run in isolation from each other // if you don't like this then either import the `pure` module // or set the RTL_SKIP_AUTO_CLEANUP env variable to 'true'. -if (!process.env.RTL_SKIP_AUTO_CLEANUP) { +if (typeof process === "undefined" || !process.env?.RTL_SKIP_AUTO_CLEANUP) { // ignore teardown() in code coverage because Jest does not support it /* istanbul ignore else */ if (typeof afterEach === 'function') { From 3d47043432a10b8279fd88eb99cd82f512f0d851 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 14 May 2021 14:40:04 +0200 Subject: [PATCH 237/327] docs: add jhnns as a contributor (#912) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index ad6a5484..89091cb7 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1252,6 +1252,15 @@ "contributions": [ "test" ] + }, + { + "login": "jhnns", + "name": "Johannes Ewald", + "avatar_url": "https://avatars.githubusercontent.com/u/781746?v=4", + "profile": "https://github.com/jhnns", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index f4b495c5..80d7ad9e 100644 --- a/README.md +++ b/README.md @@ -607,6 +607,7 @@ Thanks goes to these people ([emoji key][emojis]):
sanchit121

πŸ› πŸ’»
Solufa

πŸ› πŸ’»
Ari PerkkiΓΆ

⚠️ +
Johannes Ewald

πŸ’» From 830da02407429b4a4a72f8eed7455adca33a39d8 Mon Sep 17 00:00:00 2001 From: "Angus J. Pope" <44686792+anpaopao@users.noreply.github.com> Date: Mon, 24 May 2021 19:40:27 +1000 Subject: [PATCH 238/327] docs: Fix link to egghead open source contribution how to (#916) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c5876fb3..68e77e6f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,6 +50,6 @@ Also, please watch the repo and respond to questions/bug reports/feature requests! Thanks! [egghead]: - https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github + https://app.egghead.io/series/how-to-contribute-to-an-open-source-project-on-github [all-contributors]: https://github.com/all-contributors/all-contributors [issues]: https://github.com/testing-library/react-testing-library/issues From 875ee5b5c255dcd8af42197ca5489a39b9334b3d Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 8 Jun 2021 10:55:05 +0200 Subject: [PATCH 239/327] chore: Don't test with node 15 (#922) --- .github/workflows/validate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index dc793472..d747c513 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -17,7 +17,7 @@ jobs: if: ${{ !contains(github.head_ref, 'all-contributors') }} strategy: matrix: - node: [10.13, 12, 14, 15, 16] + node: [10.13, 12, 14, 16] react: [latest, next, experimental] runs-on: ubuntu-latest steps: From 770246e5cf15593bee96de5ce8b43305826c0893 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 8 Jun 2021 11:30:21 +0200 Subject: [PATCH 240/327] fix: Bump testing-library/dom to v8 alpha (#923) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fde78a35..717cdf7a 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^7.28.1" + "@testing-library/dom": "^8.0.0-alpha.3" }, "devDependencies": { "@testing-library/jest-dom": "^5.11.6", From c1a931d769dfba1bef49442de34132c2dd3837ef Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 8 Jun 2021 20:05:19 +0200 Subject: [PATCH 241/327] chore: Bump kcd-scripts to 11.x (#921) --- package.json | 7 +++++-- src/__tests__/cleanup.js | 11 ++++++----- src/__tests__/debug.js | 4 ++-- src/__tests__/new-act.js | 4 ++-- src/__tests__/no-act.js | 6 +++--- src/__tests__/old-act.js | 34 +++++++++++++++++----------------- src/__tests__/render.js | 16 ++++++++-------- types/test.tsx | 32 ++++++++++++++++---------------- 8 files changed, 59 insertions(+), 55 deletions(-) diff --git a/package.json b/package.json index 717cdf7a..74cbf66d 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "@testing-library/jest-dom": "^5.11.6", "@types/react-dom": "^17.0.0", "dotenv-cli": "^4.0.0", - "kcd-scripts": "^7.5.1", + "kcd-scripts": "^11.1.0", "npm-run-all": "^4.1.5", "react": "^17.0.1", "react-dom": "^17.0.1", @@ -68,7 +68,10 @@ "react/no-adjacent-inline-elements": "off", "import/no-unassigned-import": "off", "import/named": "off", - "testing-library/no-dom-import": "off" + "testing-library/no-container": "off", + "testing-library/no-dom-import": "off", + "testing-library/no-unnecessary-act": "off", + "testing-library/prefer-user-event": "off" } }, "eslintIgnore": [ diff --git a/src/__tests__/cleanup.js b/src/__tests__/cleanup.js index 6043ae06..0dcbac12 100644 --- a/src/__tests__/cleanup.js +++ b/src/__tests__/cleanup.js @@ -54,15 +54,16 @@ describe('fake timers and missing act warnings', () => { jest.useRealTimers() }) - test('cleanup does not flush immediates', () => { + test('cleanup does not flush microtasks', () => { const microTaskSpy = jest.fn() function Test() { const counter = 1 const [, setDeferredCounter] = React.useState(null) React.useEffect(() => { let cancelled = false - setImmediate(() => { + Promise.resolve().then(() => { microTaskSpy() + // eslint-disable-next-line jest/no-if -- false positive if (!cancelled) { setDeferredCounter(counter) } @@ -92,12 +93,12 @@ describe('fake timers and missing act warnings', () => { const [, setDeferredCounter] = React.useState(null) React.useEffect(() => { let cancelled = false - setImmediate(() => { + setTimeout(() => { deferredStateUpdateSpy() if (!cancelled) { setDeferredCounter(counter) } - }) + }, 0) return () => { cancelled = true @@ -108,7 +109,7 @@ describe('fake timers and missing act warnings', () => { } render() - jest.runAllImmediates() + jest.runAllTimers() cleanup() expect(deferredStateUpdateSpy).toHaveBeenCalledTimes(1) diff --git a/src/__tests__/debug.js b/src/__tests__/debug.js index e4e9faa0..f3aad595 100644 --- a/src/__tests__/debug.js +++ b/src/__tests__/debug.js @@ -43,8 +43,8 @@ test('allows same arguments as prettyDOM', () => { expect(console.log).toHaveBeenCalledTimes(1) expect(console.log.mock.calls[0]).toMatchInlineSnapshot(` Array [ - "
- ...", +
+ ..., ] `) }) diff --git a/src/__tests__/new-act.js b/src/__tests__/new-act.js index 56ce4970..42552594 100644 --- a/src/__tests__/new-act.js +++ b/src/__tests__/new-act.js @@ -49,7 +49,7 @@ test('async act recovers from errors', async () => { expect(console.error.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - "call console.error", + call console.error, ], ] `) @@ -67,7 +67,7 @@ test('async act recovers from sync errors', async () => { expect(console.error.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - "call console.error", + call console.error, ], ] `) diff --git a/src/__tests__/no-act.js b/src/__tests__/no-act.js index 039a79ae..686d78bb 100644 --- a/src/__tests__/no-act.js +++ b/src/__tests__/no-act.js @@ -2,7 +2,7 @@ let act, asyncAct beforeEach(() => { jest.resetModules() - act = require('..').act + act = require('../pure').act asyncAct = require('../act-compat').asyncAct jest.spyOn(console, 'error').mockImplementation(() => {}) }) @@ -53,7 +53,7 @@ test('async act recovers from errors', async () => { expect(console.error.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - "call console.error", + call console.error, ], ] `) @@ -71,7 +71,7 @@ test('async act recovers from sync errors', async () => { expect(console.error.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - "call console.error", + call console.error, ], ] `) diff --git a/src/__tests__/old-act.js b/src/__tests__/old-act.js index b3de9377..0153fea3 100644 --- a/src/__tests__/old-act.js +++ b/src/__tests__/old-act.js @@ -32,18 +32,18 @@ test('async act works even when the act is an old one', async () => { console.error('sigil') }) expect(console.error.mock.calls).toMatchInlineSnapshot(` - Array [ - Array [ - "sigil", - ], - Array [ - "It looks like you're using a version of react-dom that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.", - ], - Array [ - "sigil", - ], - ] - `) + Array [ + Array [ + sigil, + ], + Array [ + It looks like you're using a version of react-dom that supports the "act" function, but not an awaitable version of "act" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning., + ], + Array [ + sigil, + ], + ] + `) expect(callback).toHaveBeenCalledTimes(1) // and it doesn't warn you twice @@ -71,10 +71,10 @@ test('async act recovers from async errors', async () => { expect(console.error.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - "It looks like you're using a version of react-dom that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.", + It looks like you're using a version of react-dom that supports the "act" function, but not an awaitable version of "act" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning., ], Array [ - "call console.error", + call console.error, ], ] `) @@ -92,7 +92,7 @@ test('async act recovers from sync errors', async () => { expect(console.error.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - "call console.error", + call console.error, ], ] `) @@ -109,11 +109,11 @@ test('async act can handle any sort of console.error', async () => { Array [ Array [ Object { - "error": "some error", + error: some error, }, ], Array [ - "It looks like you're using a version of react-dom that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.", + It looks like you're using a version of react-dom that supports the "act" function, but not an awaitable version of "act" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning., ], ] `) diff --git a/src/__tests__/render.js b/src/__tests__/render.js index fdc1ff4c..fea1a649 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -78,14 +78,14 @@ test('renders options.wrapper around node', () => { expect(screen.getByTestId('wrapper')).toBeInTheDocument() expect(container.firstChild).toMatchInlineSnapshot(` -
-
-
-`) +
+
+
+ `) }) test('flushes useEffect cleanup functions sync on unmount()', () => { diff --git a/types/test.tsx b/types/test.tsx index 5f9575ac..239caed6 100644 --- a/types/test.tsx +++ b/types/test.tsx @@ -3,39 +3,39 @@ import {render, fireEvent, screen, waitFor} from '.' import * as pure from './pure' export async function testRender() { - const page = render( + ) + } + const ui = + const container = document.createElement('div') + document.body.appendChild(container) + container.innerHTML = ReactDOMServer.renderToString(ui) + + expect(container).toHaveTextContent('clicked:0') + + render(ui, {container, hydrate: true}) + + expect(console.error).not.toHaveBeenCalled() + + fireEvent.click(container.querySelector('button')) + + expect(container).toHaveTextContent('clicked:1') +}) + +test('hydrate can have a wrapper', () => { + const wrapperComponentMountEffect = jest.fn() + function WrapperComponent({children}) { + React.useEffect(() => { + wrapperComponentMountEffect() + }) + + return children + } + const ui =
+ const container = document.createElement('div') + document.body.appendChild(container) + container.innerHTML = ReactDOMServer.renderToString(ui) + + render(ui, {container, hydrate: true, wrapper: WrapperComponent}) + + expect(wrapperComponentMountEffect).toHaveBeenCalledTimes(1) +}) + +test('legacyRoot uses legacy ReactDOM.render', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}) + render(
, {legacyRoot: true}) + + expect(console.error).toHaveBeenCalledTimes(1) + expect(console.error).toHaveBeenNthCalledWith( + 1, + "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ) +}) + +test('legacyRoot uses legacy ReactDOM.hydrate', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}) + const ui =
+ const container = document.createElement('div') + container.innerHTML = ReactDOMServer.renderToString(ui) + render(ui, {container, hydrate: true, legacyRoot: true}) + + expect(console.error).toHaveBeenCalledTimes(1) + expect(console.error).toHaveBeenNthCalledWith( + 1, + "Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ) +}) diff --git a/src/__tests__/stopwatch.js b/src/__tests__/stopwatch.js index 400fce10..eeaf395c 100644 --- a/src/__tests__/stopwatch.js +++ b/src/__tests__/stopwatch.js @@ -53,8 +53,5 @@ test('unmounts a component', async () => { // and get an error. await sleep(5) // eslint-disable-next-line no-console - expect(console.error).toHaveBeenCalledTimes( - // ReactDOM.render is deprecated in React 18 - React.version.startsWith('18') ? 1 : 0, - ) + expect(console.error).not.toHaveBeenCalled() }) diff --git a/src/act-compat.js b/src/act-compat.js index 40ecdab9..d7a09d68 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -1,135 +1,85 @@ -import * as React from 'react' -import ReactDOM from 'react-dom' import * as testUtils from 'react-dom/test-utils' -const reactAct = testUtils.act -const actSupported = reactAct !== undefined +const domAct = testUtils.act -// act is supported react-dom@16.8.0 -// so for versions that don't have act from test utils -// we do this little polyfill. No warnings, but it's -// better than nothing. -function actPolyfill(cb) { - ReactDOM.unstable_batchedUpdates(cb) - ReactDOM.render(
, document.createElement('div')) +function getGlobalThis() { + /* istanbul ignore else */ + if (typeof self !== 'undefined') { + return self + } + /* istanbul ignore next */ + if (typeof window !== 'undefined') { + return window + } + /* istanbul ignore next */ + if (typeof global !== 'undefined') { + return global + } + /* istanbul ignore next */ + throw new Error('unable to locate global object') } -const act = reactAct || actPolyfill +function setIsReactActEnvironment(isReactActEnvironment) { + getGlobalThis().IS_REACT_ACT_ENVIRONMENT = isReactActEnvironment +} -let youHaveBeenWarned = false -let isAsyncActSupported = null +function getIsReactActEnvironment() { + return getGlobalThis().IS_REACT_ACT_ENVIRONMENT +} -function asyncAct(cb) { - if (actSupported === true) { - if (isAsyncActSupported === null) { - return new Promise((resolve, reject) => { - // patch console.error here - const originalConsoleError = console.error - console.error = function error(...args) { - /* if console.error fired *with that specific message* */ - /* istanbul ignore next */ - const firstArgIsString = typeof args[0] === 'string' - if ( - firstArgIsString && - args[0].indexOf( - 'Warning: Do not await the result of calling ReactTestUtils.act', - ) === 0 - ) { - // v16.8.6 - isAsyncActSupported = false - } else if ( - firstArgIsString && - args[0].indexOf( - 'Warning: The callback passed to ReactTestUtils.act(...) function must not return anything', - ) === 0 - ) { - // no-op - } else { - originalConsoleError.apply(console, args) - } +function withGlobalActEnvironment(actImplementation) { + return callback => { + const previousActEnvironment = getIsReactActEnvironment() + setIsReactActEnvironment(true) + try { + // The return value of `act` is always a thenable. + let callbackNeedsToBeAwaited = false + const actResult = actImplementation(() => { + const result = callback() + if ( + result !== null && + typeof result === 'object' && + typeof result.then === 'function' + ) { + callbackNeedsToBeAwaited = true } - let cbReturn, result - try { - result = reactAct(() => { - cbReturn = cb() - return cbReturn - }) - } catch (err) { - console.error = originalConsoleError - reject(err) - return - } - - result.then( - () => { - console.error = originalConsoleError - // if it got here, it means async act is supported - isAsyncActSupported = true - resolve() - }, - err => { - console.error = originalConsoleError - isAsyncActSupported = true - reject(err) - }, - ) - - // 16.8.6's act().then() doesn't call a resolve handler, so we need to manually flush here, sigh - - if (isAsyncActSupported === false) { - console.error = originalConsoleError - /* istanbul ignore next */ - if (!youHaveBeenWarned) { - // if act is supported and async act isn't and they're trying to use async - // act, then they need to upgrade from 16.8 to 16.9. - // This is a seamless upgrade, so we'll add a warning - console.error( - `It looks like you're using a version of react-dom that supports the "act" function, but not an awaitable version of "act" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.`, + return result + }) + if (callbackNeedsToBeAwaited) { + const thenable = actResult + return { + then: (resolve, reject) => { + thenable.then( + returnValue => { + setIsReactActEnvironment(previousActEnvironment) + resolve(returnValue) + }, + error => { + setIsReactActEnvironment(previousActEnvironment) + reject(error) + }, ) - youHaveBeenWarned = true - } - - cbReturn.then(() => { - // a faux-version. - // todo - copy https://github.com/facebook/react/blob/master/packages/shared/enqueueTask.js - Promise.resolve().then(() => { - // use sync act to flush effects - act(() => {}) - resolve() - }) - }, reject) + }, } - }) - } else if (isAsyncActSupported === false) { - // use the polyfill directly - let result - act(() => { - result = cb() - }) - return result.then(() => { - return Promise.resolve().then(() => { - // use sync act to flush effects - act(() => {}) - }) - }) + } else { + setIsReactActEnvironment(previousActEnvironment) + return actResult + } + } catch (error) { + // Can't be a `finally {}` block since we don't know if we have to immediately restore IS_REACT_ACT_ENVIRONMENT + // or if we have to await the callback first. + setIsReactActEnvironment(previousActEnvironment) + throw error } - // all good! regular act - return act(cb) } - // use the polyfill - let result - act(() => { - result = cb() - }) - return result.then(() => { - return Promise.resolve().then(() => { - // use sync act to flush effects - act(() => {}) - }) - }) } +const act = withGlobalActEnvironment(domAct) + export default act -export {asyncAct} +export { + setIsReactActEnvironment as setReactActEnvironment, + getIsReactActEnvironment, +} /* eslint no-console:0 */ diff --git a/src/index.js b/src/index.js index 96fbe155..bb0d0270 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,4 @@ +import {getIsReactActEnvironment, setReactActEnvironment} from './act-compat' import {cleanup} from './pure' // if we're running in a test runner that supports afterEach @@ -20,6 +21,21 @@ if (typeof process === 'undefined' || !process.env?.RTL_SKIP_AUTO_CLEANUP) { cleanup() }) } + + // No test setup with other test runners available + /* istanbul ignore else */ + if (typeof beforeAll === 'function' && typeof afterAll === 'function') { + // This matches the behavior of React < 18. + let previousIsReactActEnvironment = getIsReactActEnvironment() + beforeAll(() => { + previousIsReactActEnvironment = getIsReactActEnvironment() + setReactActEnvironment(true) + }) + + afterAll(() => { + setReactActEnvironment(previousIsReactActEnvironment) + }) + } } export * from './pure' diff --git a/src/pure.js b/src/pure.js index 75098f78..64b761b0 100644 --- a/src/pure.js +++ b/src/pure.js @@ -1,20 +1,32 @@ import * as React from 'react' import ReactDOM from 'react-dom' +import * as ReactDOMClient from 'react-dom/client' import { getQueriesForElement, prettyDOM, configure as configureDTL, } from '@testing-library/dom' -import act, {asyncAct} from './act-compat' +import act, { + getIsReactActEnvironment, + setReactActEnvironment, +} from './act-compat' import {fireEvent} from './fire-event' configureDTL({ + unstable_advanceTimersWrapper: cb => { + return act(cb) + }, + // We just want to run `waitFor` without IS_REACT_ACT_ENVIRONMENT + // But that's not necessarily how `asyncWrapper` is used since it's a public method. + // Let's just hope nobody else is using it. asyncWrapper: async cb => { - let result - await asyncAct(async () => { - result = await cb() - }) - return result + const previousActEnvironment = getIsReactActEnvironment() + setReactActEnvironment(false) + try { + return await cb() + } finally { + setReactActEnvironment(previousActEnvironment) + } }, eventWrapper: cb => { let result @@ -25,32 +37,70 @@ configureDTL({ }, }) +// Ideally we'd just use a WeakMap where containers are keys and roots are values. +// We use two variables so that we can bail out in constant time when we render with a new container (most common use case) +/** + * @type {Set} + */ const mountedContainers = new Set() +/** + * @type Array<{container: import('react-dom').Container, root: ReturnType}> + */ +const mountedRootEntries = [] -function render( - ui, - { - container, - baseElement = container, - queries, - hydrate = false, - wrapper: WrapperComponent, - } = {}, +function createConcurrentRoot( + container, + {hydrate, ui, wrapper: WrapperComponent}, ) { - if (!baseElement) { - // default to document.body instead of documentElement to avoid output of potentially-large - // head elements (such as JSS style blocks) in debug output - baseElement = document.body + let root + if (hydrate) { + act(() => { + root = ReactDOMClient.hydrateRoot( + container, + WrapperComponent ? React.createElement(WrapperComponent, null, ui) : ui, + ) + }) + } else { + root = ReactDOMClient.createRoot(container) } - if (!container) { - container = baseElement.appendChild(document.createElement('div')) + + return { + hydrate() { + /* istanbul ignore if */ + if (!hydrate) { + throw new Error( + 'Attempted to hydrate a non-hydrateable root. This is a bug in `@testing-library/react`.', + ) + } + // Nothing to do since hydration happens when creating the root object. + }, + render(element) { + root.render(element) + }, + unmount() { + root.unmount() + }, } +} - // we'll add it to the mounted containers regardless of whether it's actually - // added to document.body so the cleanup method works regardless of whether - // they're passing us a custom container or not. - mountedContainers.add(container) +function createLegacyRoot(container) { + return { + hydrate(element) { + ReactDOM.hydrate(element, container) + }, + render(element) { + ReactDOM.render(element, container) + }, + unmount() { + ReactDOM.unmountComponentAtNode(container) + }, + } +} +function renderRoot( + ui, + {baseElement, container, hydrate, queries, root, wrapper: WrapperComponent}, +) { const wrapUiIfNeeded = innerElement => WrapperComponent ? React.createElement(WrapperComponent, null, innerElement) @@ -58,9 +108,9 @@ function render( act(() => { if (hydrate) { - ReactDOM.hydrate(wrapUiIfNeeded(ui), container) + root.hydrate(wrapUiIfNeeded(ui), container) } else { - ReactDOM.render(wrapUiIfNeeded(ui), container) + root.render(wrapUiIfNeeded(ui), container) } }) @@ -75,11 +125,15 @@ function render( console.log(prettyDOM(el, maxLength, options)), unmount: () => { act(() => { - ReactDOM.unmountComponentAtNode(container) + root.unmount() }) }, rerender: rerenderUi => { - render(wrapUiIfNeeded(rerenderUi), {container, baseElement}) + renderRoot(wrapUiIfNeeded(rerenderUi), { + container, + baseElement, + root, + }) // Intentionally do not return anything to avoid unnecessarily complicating the API. // folks can use all the same utilities we return in the first place that are bound to the container }, @@ -99,28 +153,73 @@ function render( } } -function cleanup() { - mountedContainers.forEach(cleanupAtContainer) +function render( + ui, + { + container, + baseElement = container, + legacyRoot = false, + queries, + hydrate = false, + wrapper, + } = {}, +) { + if (!baseElement) { + // default to document.body instead of documentElement to avoid output of potentially-large + // head elements (such as JSS style blocks) in debug output + baseElement = document.body + } + if (!container) { + container = baseElement.appendChild(document.createElement('div')) + } + + let root + // eslint-disable-next-line no-negated-condition -- we want to map the evolution of this over time. The root is created first. Only later is it re-used so we don't want to read the case that happens later first. + if (!mountedContainers.has(container)) { + const createRootImpl = legacyRoot ? createLegacyRoot : createConcurrentRoot + root = createRootImpl(container, {hydrate, ui, wrapper}) + + mountedRootEntries.push({container, root}) + // we'll add it to the mounted containers regardless of whether it's actually + // added to document.body so the cleanup method works regardless of whether + // they're passing us a custom container or not. + mountedContainers.add(container) + } else { + mountedRootEntries.forEach(rootEntry => { + // Else is unreachable since `mountedContainers` has the `container`. + // Only reachable if one would accidentally add the container to `mountedContainers` but not the root to `mountedRootEntries` + /* istanbul ignore else */ + if (rootEntry.container === container) { + root = rootEntry.root + } + }) + } + + return renderRoot(ui, { + container, + baseElement, + queries, + hydrate, + wrapper, + root, + }) } -// maybe one day we'll expose this (perhaps even as a utility returned by render). -// but let's wait until someone asks for it. -function cleanupAtContainer(container) { - act(() => { - ReactDOM.unmountComponentAtNode(container) +function cleanup() { + mountedRootEntries.forEach(({root, container}) => { + act(() => { + root.unmount() + }) + if (container.parentNode === document.body) { + document.body.removeChild(container) + } }) - if (container.parentNode === document.body) { - document.body.removeChild(container) - } - mountedContainers.delete(container) + mountedRootEntries.length = 0 + mountedContainers.clear() } // just re-export everything from dom-testing-library export * from '@testing-library/dom' export {render, cleanup, act, fireEvent} -// NOTE: we're not going to export asyncAct because that's our own compatibility -// thing for people using react-dom@16.8.0. Anyone else doesn't need it and -// people should just upgrade anyway. - /* eslint func-name-matching:0 */ diff --git a/tests/setup-env.js b/tests/setup-env.js index 6c0b953b..264828a9 100644 --- a/tests/setup-env.js +++ b/tests/setup-env.js @@ -1,20 +1 @@ import '@testing-library/jest-dom/extend-expect' - -let consoleErrorMock - -beforeEach(() => { - const originalConsoleError = console.error - consoleErrorMock = jest - .spyOn(console, 'error') - .mockImplementation((message, ...optionalParams) => { - // Ignore ReactDOM.render/ReactDOM.hydrate deprecation warning - if (message.indexOf('Use createRoot instead.') !== -1) { - return - } - originalConsoleError(message, ...optionalParams) - }) -}) - -afterEach(() => { - consoleErrorMock.mockRestore() -}) diff --git a/types/index.d.ts b/types/index.d.ts index 604b3966..a9bfa279 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -60,6 +60,11 @@ export interface RenderOptions< * @see https://testing-library.com/docs/react-testing-library/api/#hydrate) */ hydrate?: boolean + /** + * Set to `true` if you want to force synchronous `ReactDOM.render`. + * Otherwise `render` will default to concurrent React if available. + */ + legacyRoot?: boolean /** * Queries to bind. Overrides the default set from DOM Testing Library unless merged. * From 93bc2c8afc8a7988ef9b4f5cb7f4101a2400735d Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 11 Apr 2022 19:59:54 +0200 Subject: [PATCH 264/327] test(types): Don't assume implicit children (#1042) * test(types): Don't assume implicit children * format --- types/test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/types/test.tsx b/types/test.tsx index eae6e81f..a8a7c7ae 100644 --- a/types/test.tsx +++ b/types/test.tsx @@ -129,6 +129,7 @@ export function wrappedRenderC( options?: pure.RenderOptions, ) { interface AppWrapperProps { + children?: React.ReactNode userProviderProps?: {user: string} } const AppWrapperProps: React.FunctionComponent = ({ From 2a889e80658ce93882c5ba253ea65f5542ece2d0 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Mon, 11 Apr 2022 11:03:31 -0700 Subject: [PATCH 265/327] fix: Specify a non-* version for @types/react-dom (#1040) fixes https://github.com/testing-library/react-testing-library/issues/1039 Co-authored-by: Sebastian Silbermann --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4781e962..8d7c629b 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "dependencies": { "@babel/runtime": "^7.12.5", "@testing-library/dom": "^8.5.0", - "@types/react-dom": "*" + "@types/react-dom": "^18.0.0" }, "devDependencies": { "@testing-library/jest-dom": "^5.11.6", From c8c93f83228a68a270583c139972e79b1812b7d3 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Mon, 11 Apr 2022 20:06:24 +0200 Subject: [PATCH 266/327] docs: add Nokel81 as a contributor for bug, code (#1043) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 10 ++++++++++ README.md | 1 + 2 files changed, 11 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index df9690ed..0eb9e2a5 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1307,6 +1307,16 @@ "code", "bug" ] + }, + { + "login": "Nokel81", + "name": "Sebastian Malton", + "avatar_url": "https://avatars.githubusercontent.com/u/8225332?v=4", + "profile": "https://github.com/Nokel81", + "contributions": [ + "bug", + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 0bc06ceb..ea31e3f8 100644 --- a/README.md +++ b/README.md @@ -615,6 +615,7 @@ Thanks goes to these people ([emoji key][emojis]):
Marcos GΓ³mez

πŸ“–
Akash Shyam

πŸ›
Fabian Meumertzheim

πŸ’» πŸ› +
Sebastian Malton

πŸ› πŸ’» From 2c451b346815b30dace8a5f7b2ed6a78d17f47cc Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 13 Apr 2022 16:38:43 +0200 Subject: [PATCH 267/327] chore: Run release from 12.x branch (#1044) (#1045) --- .github/workflows/validate.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 45cc7d13..7e95b942 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -2,7 +2,9 @@ name: validate on: push: branches: - - '+([0-9])?(.{+([0-9]),x}).x' + # Match SemVer major release branches + # e.g. "12.x" or "8.x" + - '[0-9]+.x' - 'main' - 'next' - 'next-major' @@ -61,8 +63,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.repository == 'testing-library/react-testing-library' && - contains('refs/heads/main,refs/heads/beta,refs/heads/next,refs/heads/alpha', - github.ref) && github.event_name == 'push' }} + github.event_name == 'push' }} steps: - name: πŸ›‘ Cancel Previous Runs uses: styfle/cancel-workflow-action@0.9.0 From 9535eff82ada685c410b3b25ef3e2313ea3a86aa Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Fri, 15 Apr 2022 20:55:24 +0200 Subject: [PATCH 268/327] feat: Add `renderHook` (#991) Co-authored-by: Michael Peyper Co-authored-by: Kent C. Dodds --- src/__tests__/renderHook.js | 62 +++++++++++++++++++++++++++++++++++++ src/pure.js | 30 +++++++++++++++++- types/index.d.ts | 46 +++++++++++++++++++++++++++ types/test.tsx | 25 ++++++++++++++- 4 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 src/__tests__/renderHook.js diff --git a/src/__tests__/renderHook.js b/src/__tests__/renderHook.js new file mode 100644 index 00000000..fd6b95a4 --- /dev/null +++ b/src/__tests__/renderHook.js @@ -0,0 +1,62 @@ +import React from 'react' +import {renderHook} from '../pure' + +test('gives comitted result', () => { + const {result} = renderHook(() => { + const [state, setState] = React.useState(1) + + React.useEffect(() => { + setState(2) + }, []) + + return [state, setState] + }) + + expect(result.current).toEqual([2, expect.any(Function)]) +}) + +test('allows rerendering', () => { + const {result, rerender} = renderHook( + ({branch}) => { + const [left, setLeft] = React.useState('left') + const [right, setRight] = React.useState('right') + + // eslint-disable-next-line jest/no-if + switch (branch) { + case 'left': + return [left, setLeft] + case 'right': + return [right, setRight] + + default: + throw new Error( + 'No Props passed. This is a bug in the implementation', + ) + } + }, + {initialProps: {branch: 'left'}}, + ) + + expect(result.current).toEqual(['left', expect.any(Function)]) + + rerender({branch: 'right'}) + + expect(result.current).toEqual(['right', expect.any(Function)]) +}) + +test('allows wrapper components', async () => { + const Context = React.createContext('default') + function Wrapper({children}) { + return {children} + } + const {result} = renderHook( + () => { + return React.useContext(Context) + }, + { + wrapper: Wrapper, + }, + ) + + expect(result.current).toEqual('provided') +}) diff --git a/src/pure.js b/src/pure.js index 64b761b0..4c416d44 100644 --- a/src/pure.js +++ b/src/pure.js @@ -218,8 +218,36 @@ function cleanup() { mountedContainers.clear() } +function renderHook(renderCallback, options = {}) { + const {initialProps, wrapper} = options + const result = React.createRef() + + function TestComponent({renderCallbackProps}) { + const pendingResult = renderCallback(renderCallbackProps) + + React.useEffect(() => { + result.current = pendingResult + }) + + return null + } + + const {rerender: baseRerender, unmount} = render( + , + {wrapper}, + ) + + function rerender(rerenderCallbackProps) { + return baseRerender( + , + ) + } + + return {result, rerender, unmount} +} + // just re-export everything from dom-testing-library export * from '@testing-library/dom' -export {render, cleanup, act, fireEvent} +export {render, renderHook, cleanup, act, fireEvent} /* eslint func-name-matching:0 */ diff --git a/types/index.d.ts b/types/index.d.ts index a9bfa279..fda03e5b 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -98,6 +98,52 @@ export function render( options?: Omit, ): RenderResult +interface RenderHookResult { + /** + * Triggers a re-render. The props will be passed to your renderHook callback. + */ + rerender: (props?: Props) => void + /** + * This is a stable reference to the latest value returned by your renderHook + * callback + */ + result: { + /** + * The value returned by your renderHook callback + */ + current: Result + } + /** + * Unmounts the test component. This is useful for when you need to test + * any cleanup your useEffects have. + */ + unmount: () => void +} + +interface RenderHookOptions { + /** + * The argument passed to the renderHook callback. Can be useful if you plan + * to use the rerender utility to change the values passed to your hook. + */ + initialProps?: Props + /** + * Pass a React Component as the wrapper option to have it rendered around the inner element. This is most useful for creating + * reusable custom render functions for common data providers. See setup for examples. + * + * @see https://testing-library.com/docs/react-testing-library/api/#wrapper + */ + wrapper?: React.JSXElementConstructor<{children: React.ReactElement}> +} + +/** + * Allows you to render a hook within a test React component without having to + * create that component yourself. + */ +export function renderHook( + render: (initialProps: Props) => Result, + options?: RenderHookOptions, +): RenderHookResult + /** * Unmounts React trees that were mounted with render. */ diff --git a/types/test.tsx b/types/test.tsx index a8a7c7ae..17ba7012 100644 --- a/types/test.tsx +++ b/types/test.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import {render, fireEvent, screen, waitFor} from '.' +import {render, fireEvent, screen, waitFor, renderHook} from '.' import * as pure from './pure' export async function testRender() { @@ -161,6 +161,29 @@ export function testBaseElement() { ) } +export function testRenderHook() { + const {result, rerender, unmount} = renderHook(() => React.useState(2)[0]) + + expectType(result.current) + + rerender() + + unmount() +} + +export function testRenderHookProps() { + const {result, rerender, unmount} = renderHook( + ({defaultValue}) => React.useState(defaultValue)[0], + {initialProps: {defaultValue: 2}}, + ) + + expectType(result.current) + + rerender() + + unmount() +} + /* eslint testing-library/prefer-explicit-assert: "off", From 9171163fccf0a7ea43763475ca2980898b4079a5 Mon Sep 17 00:00:00 2001 From: Andrew Hummel Date: Fri, 15 Apr 2022 17:07:31 -0500 Subject: [PATCH 269/327] fix(TS): export interface RenderHookResult (#1049) --- types/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/index.d.ts b/types/index.d.ts index fda03e5b..1948114f 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -98,7 +98,7 @@ export function render( options?: Omit, ): RenderResult -interface RenderHookResult { +export interface RenderHookResult { /** * Triggers a re-render. The props will be passed to your renderHook callback. */ From 46b28ade730f97a49a253d630f5b97c17ff24f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20B=C3=B6ttcher?= Date: Tue, 3 May 2022 20:34:37 +0200 Subject: [PATCH 270/327] feat: Export RenderHookOptions type (#1062) --- types/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/index.d.ts b/types/index.d.ts index 1948114f..e3f5bc60 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -120,7 +120,7 @@ export interface RenderHookResult { unmount: () => void } -interface RenderHookOptions { +export interface RenderHookOptions { /** * The argument passed to the renderHook callback. Can be useful if you plan * to use the rerender utility to change the values passed to your hook. From 00c89dce86585d6a163c383a05abaf5a7f646bf6 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 3 May 2022 20:36:41 +0200 Subject: [PATCH 271/327] docs: add mboettcher as a contributor for code (#1063) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 0eb9e2a5..e267d285 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1317,6 +1317,15 @@ "bug", "code" ] + }, + { + "login": "mboettcher", + "name": "Martin BΓΆttcher", + "avatar_url": "https://avatars.githubusercontent.com/u/2325337?v=4", + "profile": "https://github.com/mboettcher", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index ea31e3f8..9992250a 100644 --- a/README.md +++ b/README.md @@ -616,6 +616,7 @@ Thanks goes to these people ([emoji key][emojis]):
Akash Shyam

πŸ›
Fabian Meumertzheim

πŸ’» πŸ›
Sebastian Malton

πŸ› πŸ’» +
Martin BΓΆttcher

πŸ’» From f176285e4e92754751b708e1b1adf1f38edea6a8 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 17 May 2022 20:51:03 +0200 Subject: [PATCH 272/327] chore: Run with latest Node 16 again (#1071) --- .github/workflows/validate.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 7e95b942..9379216c 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -20,8 +20,7 @@ jobs: strategy: fail-fast: false matrix: - # 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 - node: [12, 14, '16.9.1'] + node: [12, 14, 16] react: [latest, next, experimental] runs-on: ubuntu-latest steps: From c80809a956b0b9f3289c4a6fa8b5e8cc72d6ef6d Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Sat, 28 May 2022 10:18:06 +0200 Subject: [PATCH 273/327] feat: Use `globalThis` if available (#1070) --- package.json | 3 +++ src/act-compat.js | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/package.json b/package.json index 8d7c629b..4cba00fd 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,9 @@ }, "eslintConfig": { "extends": "./node_modules/kcd-scripts/eslint.js", + "globals": { + "globalThis": "readonly" + }, "rules": { "react/prop-types": "off", "react/no-adjacent-inline-elements": "off", diff --git a/src/act-compat.js b/src/act-compat.js index d7a09d68..86518196 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -4,6 +4,10 @@ const domAct = testUtils.act function getGlobalThis() { /* istanbul ignore else */ + if (typeof globalThis !== 'undefined') { + return globalThis + } + /* istanbul ignore next */ if (typeof self !== 'undefined') { return self } From 73ee9ba13cb4b337f06e2ed61099d6af9a4968da Mon Sep 17 00:00:00 2001 From: Felix Yan Date: Mon, 22 Aug 2022 12:40:43 +0300 Subject: [PATCH 274/327] test: Correct a typo in test name (#1112) --- src/__tests__/renderHook.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/renderHook.js b/src/__tests__/renderHook.js index fd6b95a4..b65d67a2 100644 --- a/src/__tests__/renderHook.js +++ b/src/__tests__/renderHook.js @@ -1,7 +1,7 @@ import React from 'react' import {renderHook} from '../pure' -test('gives comitted result', () => { +test('gives committed result', () => { const {result} = renderHook(() => { const [state, setState] = React.useState(1) From 27a9584629e28339b9961edefbb2134d7c570678 Mon Sep 17 00:00:00 2001 From: Dominik Dorfmeister Date: Sun, 4 Sep 2022 18:47:54 +0200 Subject: [PATCH 275/327] feat(renderHook): allow passing of all render options to renderHook (#1118) --- src/__tests__/renderHook.js | 26 ++++++++++++++++++++++++++ src/pure.js | 4 ++-- types/index.d.ts | 24 ++++++++++++++---------- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/__tests__/renderHook.js b/src/__tests__/renderHook.js index b65d67a2..92bc47ed 100644 --- a/src/__tests__/renderHook.js +++ b/src/__tests__/renderHook.js @@ -60,3 +60,29 @@ test('allows wrapper components', async () => { expect(result.current).toEqual('provided') }) + +test('legacyRoot uses legacy ReactDOM.render', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}) + + const Context = React.createContext('default') + function Wrapper({children}) { + return {children} + } + const {result} = renderHook( + () => { + return React.useContext(Context) + }, + { + wrapper: Wrapper, + legacyRoot: true, + }, + ) + + expect(result.current).toEqual('provided') + + expect(console.error).toHaveBeenCalledTimes(1) + expect(console.error).toHaveBeenNthCalledWith( + 1, + "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ) +}) diff --git a/src/pure.js b/src/pure.js index 4c416d44..94b3b2bd 100644 --- a/src/pure.js +++ b/src/pure.js @@ -219,7 +219,7 @@ function cleanup() { } function renderHook(renderCallback, options = {}) { - const {initialProps, wrapper} = options + const {initialProps, ...renderOptions} = options const result = React.createRef() function TestComponent({renderCallbackProps}) { @@ -234,7 +234,7 @@ function renderHook(renderCallback, options = {}) { const {rerender: baseRerender, unmount} = render( , - {wrapper}, + renderOptions, ) function rerender(rerenderCallbackProps) { diff --git a/types/index.d.ts b/types/index.d.ts index e3f5bc60..558edfad 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -120,28 +120,32 @@ export interface RenderHookResult { unmount: () => void } -export interface RenderHookOptions { +export interface RenderHookOptions< + Props, + Q extends Queries = typeof queries, + Container extends Element | DocumentFragment = HTMLElement, + BaseElement extends Element | DocumentFragment = Container, +> extends RenderOptions { /** * The argument passed to the renderHook callback. Can be useful if you plan * to use the rerender utility to change the values passed to your hook. */ initialProps?: Props - /** - * Pass a React Component as the wrapper option to have it rendered around the inner element. This is most useful for creating - * reusable custom render functions for common data providers. See setup for examples. - * - * @see https://testing-library.com/docs/react-testing-library/api/#wrapper - */ - wrapper?: React.JSXElementConstructor<{children: React.ReactElement}> } /** * Allows you to render a hook within a test React component without having to * create that component yourself. */ -export function renderHook( +export function renderHook< + Result, + Props, + Q extends Queries = typeof queries, + Container extends Element | DocumentFragment = HTMLElement, + BaseElement extends Element | DocumentFragment = Container, +>( render: (initialProps: Props) => Result, - options?: RenderHookOptions, + options?: RenderHookOptions, ): RenderHookResult /** From bef9e07c1743affa6fca459fda5ab5b488ccd9bf Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 4 Sep 2022 18:48:26 +0200 Subject: [PATCH 276/327] docs: add TkDodo as a contributor for code (#1119) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index e267d285..2d451b71 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1326,6 +1326,15 @@ "contributions": [ "code" ] + }, + { + "login": "TkDodo", + "name": "Dominik Dorfmeister", + "avatar_url": "https://avatars.githubusercontent.com/u/1021430?v=4", + "profile": "http://tkdodo.eu", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 9992250a..bbe8d94e 100644 --- a/README.md +++ b/README.md @@ -617,6 +617,7 @@ Thanks goes to these people ([emoji key][emojis]):
Fabian Meumertzheim

πŸ’» πŸ›
Sebastian Malton

πŸ› πŸ’»
Martin BΓΆttcher

πŸ’» +
Dominik Dorfmeister

πŸ’» From 7c7dc785501f2e75cbcb5d49df78340914dfba8c Mon Sep 17 00:00:00 2001 From: Stephen Sauceda Date: Sat, 1 Oct 2022 15:20:38 -0400 Subject: [PATCH 277/327] docs: acknowledge peer dependency requirements (#1131) --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index bbe8d94e..8704fa2b 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,16 @@ yarn add --dev @testing-library/react This library has `peerDependencies` listings for `react` and `react-dom`. +_React Testing Library versions 13+ require React v18. If your project uses an +older version of React, be sure to install version 12:_ + +``` +npm install --save-dev @testing-library/react@12 + + +yarn add --dev @testing-library/react@12 +``` + You may also be interested in installing `@testing-library/jest-dom` so you can use [the custom jest matchers](https://github.com/testing-library/jest-dom). From bca9bf8bca1dfb9655980801838fb851d0ef8763 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 1 Oct 2022 21:23:18 +0200 Subject: [PATCH 278/327] add stephensauceda as a contributor for doc (#1132) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 ++ README.md | 364 ++++++++++++++++++++++---------------------- 2 files changed, 194 insertions(+), 179 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 2d451b71..270dd6a0 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1335,6 +1335,15 @@ "contributions": [ "code" ] + }, + { + "login": "stephensauceda", + "name": "Stephen Sauceda", + "avatar_url": "https://avatars.githubusercontent.com/u/1017723?v=4", + "profile": "https://stephensauceda.com", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 8704fa2b..45324901 100644 --- a/README.md +++ b/README.md @@ -450,185 +450,191 @@ Thanks goes to these people ([emoji key][emojis]): - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️

Ryan Castner

πŸ“–

Daniel Sandiego

πŸ’»

PaweΕ‚ MikoΕ‚ajczyk

πŸ’»

Alejandro ÑÑñez Ortiz

πŸ“–

Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️

Justin Hall

πŸ“¦

Anto Aravinth

πŸ’» ⚠️ πŸ“–

Jonah Moses

πŸ“–

Łukasz Gandecki

πŸ’» ⚠️ πŸ“–

Ivan Babak

πŸ› πŸ€”

Jesse Day

πŸ’»

Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–

Josef Maxx Blake

πŸ’» πŸ“– ⚠️

Michal Baranowski

πŸ“ βœ…

Arthur Puthin

πŸ“–

Thomas Chia

πŸ’» πŸ“–

Thiago Galvani

πŸ“–

Christian

⚠️

Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”

Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️

Maddi Joyce

πŸ’»

Ryan Vice

πŸ“–

Ian Wilson

πŸ“ βœ…

Daniel

πŸ› πŸ’»

Giorgio Polvara

πŸ› πŸ€”

John Gozde

πŸ’»

Sam Horton

πŸ“– πŸ’‘ πŸ€”

Richard Kotze (mobile)

πŸ“–

Brahian E. Soto Mercedes

πŸ“–

Benoit de La Forest

πŸ“–

Salah

πŸ’» ⚠️

Adam Gordon

πŸ› πŸ’»

Matija Marohnić

πŸ“–

Justice Mba

πŸ“–

Mark Pollmann

πŸ“–

Ehtesham Kafeel

πŸ’» πŸ“–

Julio PavΓ³n

πŸ’»

Duncan L

πŸ“– πŸ’‘

Tiago Almeida

πŸ“–

Robert Smith

πŸ›

Zach Green

πŸ“–

dadamssg

πŸ“–

Yazan Aabed

πŸ“

Tim

πŸ› πŸ’» πŸ“– ⚠️

Divyanshu Maithani

βœ… πŸ“Ή

Deepak Grover

βœ… πŸ“Ή

Eyal Cohen

πŸ“–

Peter Makowski

πŸ“–

Michiel Nuyts

πŸ“–

Joe Ng'ethe

πŸ’» πŸ“–

Kate

πŸ“–

Sean

πŸ“–

James Long

πŸ€” πŸ“¦

Herb Hagely

πŸ’‘

Alex Wendte

πŸ’‘

Monica Powell

πŸ“–

Vitaly Sivkov

πŸ’»

Weyert de Boer

πŸ€” πŸ‘€ 🎨

EstebanMarin

πŸ“–

Victor Martins

πŸ“–

Royston Shufflebotham

πŸ› πŸ“– πŸ’‘

chrbala

πŸ’»

Donavon West

πŸ’» πŸ“– πŸ€” ⚠️

Richard Maisano

πŸ’»

Marco Biedermann

πŸ’» 🚧 ⚠️

Alex Zherdev

πŸ› πŸ’»

AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️

Daniel K.

πŸ› πŸ’» πŸ€” ⚠️ πŸ‘€

mohamedmagdy17593

πŸ’»

Loren ☺️

πŸ“–

MarkFalconbridge

πŸ› πŸ’»

Vinicius

πŸ“– πŸ’‘

Peter Schyma

πŸ’»

Ian Schmitz

πŸ“–

Joel Marcotte

πŸ› ⚠️ πŸ’»

Alejandro Dustet

πŸ›

Brandon Carroll

πŸ“–

Lucas Machado

πŸ“–

Pascal Duez

πŸ“¦

Minh Nguyen

πŸ’»

LiaoJimmy

πŸ“–

Sunil Pai

πŸ’» ⚠️

Dan Abramov

πŸ‘€

Christian Murphy

πŸš‡

Ivakhnenko Dmitry

πŸ’»

James George

πŸ“–

JoΓ£o Fernandes

πŸ“–

Alejandro Perea

πŸ‘€

Nick McCurdy

πŸ‘€ πŸ’¬ πŸš‡

Sebastian Silbermann

πŸ‘€

AdriΓ  Fontcuberta

πŸ‘€ πŸ“–

John Reilly

πŸ‘€

MichaΓ«l De Boey

πŸ‘€ πŸ’»

Tim Yates

πŸ‘€

Brian Donovan

πŸ’»

Noam Gabriel Jacobson

πŸ“–

Ronald van der Kooij

⚠️ πŸ’»

Aayush Rajvanshi

πŸ“–

Ely Alamillo

πŸ’» ⚠️

Daniel Afonso

πŸ’» ⚠️

Laurens Bosscher

πŸ’»

Sakito Mukai

πŸ“–

TΓΌrker Teke

πŸ“–

Zach Brogan

πŸ’» ⚠️

Ryota Murakami

πŸ“–

Michael Hottman

πŸ€”

Steven Fitzpatrick

πŸ›

Juan Je GarcΓ­a

πŸ“–

Championrunner

πŸ“–

Sam Tsai

πŸ’» ⚠️ πŸ“–

Christian Rackerseder

πŸ’»

Andrei Picus

πŸ› πŸ‘€

Artem Zakharchenko

πŸ“–

Michael

πŸ“–

Braden Lee

πŸ“–

Kamran Ayub

πŸ’» ⚠️

Matan Borenkraout

πŸ’»

Ryan Bigg

🚧

Anton Halim

πŸ“–

Artem Malko

πŸ’»

Gerrit Alex

πŸ’»

Karthick Raja

πŸ’»

Abdelrahman Ashraf

πŸ’»

Lidor Avitan

πŸ“–

Jordan Harband

πŸ‘€ πŸ€”

Marco Moretti

πŸ’»

sanchit121

πŸ› πŸ’»

Solufa

πŸ› πŸ’»

Ari PerkkiΓΆ

⚠️

Johannes Ewald

πŸ’»

Angus J. Pope

πŸ“–

Dominik Lesch

πŸ“–

Marcos GΓ³mez

πŸ“–

Akash Shyam

πŸ›

Fabian Meumertzheim

πŸ’» πŸ›

Sebastian Malton

πŸ› πŸ’»

Martin BΓΆttcher

πŸ’»

Dominik Dorfmeister

πŸ’»
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€ 🎨
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️ πŸ‘€
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
Pascal Duez
Pascal Duez

πŸ“¦
Minh Nguyen
Minh Nguyen

πŸ’»
LiaoJimmy
LiaoJimmy

πŸ“–
Sunil Pai
Sunil Pai

πŸ’» ⚠️
Dan Abramov
Dan Abramov

πŸ‘€
Christian Murphy
Christian Murphy

πŸš‡
Ivakhnenko Dmitry
Ivakhnenko Dmitry

πŸ’»
James George
James George

πŸ“–
JoΓ£o Fernandes
JoΓ£o Fernandes

πŸ“–
Alejandro Perea
Alejandro Perea

πŸ‘€
Nick McCurdy
Nick McCurdy

πŸ‘€ πŸ’¬ πŸš‡
Sebastian Silbermann
Sebastian Silbermann

πŸ‘€
AdriΓ  Fontcuberta
AdriΓ  Fontcuberta

πŸ‘€ πŸ“–
John Reilly
John Reilly

πŸ‘€
MichaΓ«l De Boey
MichaΓ«l De Boey

πŸ‘€ πŸ’»
Tim Yates
Tim Yates

πŸ‘€
Brian Donovan
Brian Donovan

πŸ’»
Noam Gabriel Jacobson
Noam Gabriel Jacobson

πŸ“–
Ronald van der Kooij
Ronald van der Kooij

⚠️ πŸ’»
Aayush Rajvanshi
Aayush Rajvanshi

πŸ“–
Ely Alamillo
Ely Alamillo

πŸ’» ⚠️
Daniel Afonso
Daniel Afonso

πŸ’» ⚠️
Laurens Bosscher
Laurens Bosscher

πŸ’»
Sakito Mukai
Sakito Mukai

πŸ“–
TΓΌrker Teke
TΓΌrker Teke

πŸ“–
Zach Brogan
Zach Brogan

πŸ’» ⚠️
Ryota Murakami
Ryota Murakami

πŸ“–
Michael Hottman
Michael Hottman

πŸ€”
Steven Fitzpatrick
Steven Fitzpatrick

πŸ›
Juan Je GarcΓ­a
Juan Je GarcΓ­a

πŸ“–
Championrunner
Championrunner

πŸ“–
Sam Tsai
Sam Tsai

πŸ’» ⚠️ πŸ“–
Christian Rackerseder
Christian Rackerseder

πŸ’»
Andrei Picus
Andrei Picus

πŸ› πŸ‘€
Artem Zakharchenko
Artem Zakharchenko

πŸ“–
Michael
Michael

πŸ“–
Braden Lee
Braden Lee

πŸ“–
Kamran Ayub
Kamran Ayub

πŸ’» ⚠️
Matan Borenkraout
Matan Borenkraout

πŸ’»
Ryan Bigg
Ryan Bigg

🚧
Anton Halim
Anton Halim

πŸ“–
Artem Malko
Artem Malko

πŸ’»
Gerrit Alex
Gerrit Alex

πŸ’»
Karthick Raja
Karthick Raja

πŸ’»
Abdelrahman Ashraf
Abdelrahman Ashraf

πŸ’»
Lidor Avitan
Lidor Avitan

πŸ“–
Jordan Harband
Jordan Harband

πŸ‘€ πŸ€”
Marco Moretti
Marco Moretti

πŸ’»
sanchit121
sanchit121

πŸ› πŸ’»
Solufa
Solufa

πŸ› πŸ’»
Ari PerkkiΓΆ
Ari PerkkiΓΆ

⚠️
Johannes Ewald
Johannes Ewald

πŸ’»
Angus J. Pope
Angus J. Pope

πŸ“–
Dominik Lesch
Dominik Lesch

πŸ“–
Marcos GΓ³mez
Marcos GΓ³mez

πŸ“–
Akash Shyam
Akash Shyam

πŸ›
Fabian Meumertzheim
Fabian Meumertzheim

πŸ’» πŸ›
Sebastian Malton
Sebastian Malton

πŸ› πŸ’»
Martin BΓΆttcher
Martin BΓΆttcher

πŸ’»
Dominik Dorfmeister
Dominik Dorfmeister

πŸ’»
Stephen Sauceda
Stephen Sauceda

πŸ“–
From 4d76a4a75541ceccbc23a452ac6b291e6bfde927 Mon Sep 17 00:00:00 2001 From: Sergey Bunas Date: Wed, 5 Oct 2022 21:32:52 +0300 Subject: [PATCH 279/327] Update outdated LICENSE year (#1133) --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 4c43675b..ca399d57 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ The MIT License (MIT) -Copyright (c) 2017 Kent C. Dodds +Copyright (c) 2017-Present Kent C. Dodds Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 185e3142a320908fc2a707c7aba815444abf675c Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Sat, 8 Oct 2022 13:22:18 +0200 Subject: [PATCH 280/327] test: Add Node.js 18.x to test matrix (#1138) --- .github/workflows/validate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 9379216c..ad4adccf 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - node: [12, 14, 16] + node: [12, 14, 16, 18] react: [latest, next, experimental] runs-on: ubuntu-latest steps: From 801ad37ac79caced867aa05931b914035c6b527a Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 6 Dec 2022 21:25:35 +0100 Subject: [PATCH 281/327] test: Fail on unexpected console.warn and console.error (#1139) --- package.json | 2 + src/__tests__/cleanup.js | 1 + src/__tests__/new-act.js | 2 +- src/__tests__/render.js | 37 ++-- src/__tests__/renderHook.js | 33 ++- tests/failOnUnexpectedConsoleCalls.js | 129 +++++++++++ tests/setup-env.js | 1 + tests/shouldIgnoreConsoleError.js | 43 ++++ tests/toWarnDev.js | 303 ++++++++++++++++++++++++++ 9 files changed, 510 insertions(+), 41 deletions(-) create mode 100644 tests/failOnUnexpectedConsoleCalls.js create mode 100644 tests/shouldIgnoreConsoleError.js create mode 100644 tests/toWarnDev.js diff --git a/package.json b/package.json index 4cba00fd..d2dd6a97 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,9 @@ }, "devDependencies": { "@testing-library/jest-dom": "^5.11.6", + "chalk": "^4.1.2", "dotenv-cli": "^4.0.0", + "jest-diff": "^27.5.1", "kcd-scripts": "^11.1.0", "npm-run-all": "^4.1.5", "react": "^18.0.0", diff --git a/src/__tests__/cleanup.js b/src/__tests__/cleanup.js index 0dcbac12..4517c098 100644 --- a/src/__tests__/cleanup.js +++ b/src/__tests__/cleanup.js @@ -51,6 +51,7 @@ describe('fake timers and missing act warnings', () => { }) afterEach(() => { + jest.restoreAllMocks() jest.useRealTimers() }) diff --git a/src/__tests__/new-act.js b/src/__tests__/new-act.js index 05f9d45a..4909d4a6 100644 --- a/src/__tests__/new-act.js +++ b/src/__tests__/new-act.js @@ -13,7 +13,7 @@ beforeEach(() => { }) afterEach(() => { - console.error.mockRestore() + jest.restoreAllMocks() }) test('async act works when it does not exist (older versions of react)', async () => { diff --git a/src/__tests__/render.js b/src/__tests__/render.js index 88e2b98d..46925f49 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -3,12 +3,6 @@ import ReactDOM from 'react-dom' import ReactDOMServer from 'react-dom/server' import {fireEvent, render, screen} from '../' -afterEach(() => { - if (console.error.mockRestore !== undefined) { - console.error.mockRestore() - } -}) - test('renders div into document', () => { const ref = React.createRef() const {container} = render(
) @@ -126,7 +120,6 @@ test('can be called multiple times on the same container', () => { }) test('hydrate will make the UI interactive', () => { - jest.spyOn(console, 'error').mockImplementation(() => {}) function App() { const [clicked, handleClick] = React.useReducer(n => n + 1, 0) @@ -145,8 +138,6 @@ test('hydrate will make the UI interactive', () => { render(ui, {container, hydrate: true}) - expect(console.error).not.toHaveBeenCalled() - fireEvent.click(container.querySelector('button')) expect(container).toHaveTextContent('clicked:1') @@ -172,26 +163,26 @@ test('hydrate can have a wrapper', () => { }) test('legacyRoot uses legacy ReactDOM.render', () => { - jest.spyOn(console, 'error').mockImplementation(() => {}) - render(
, {legacyRoot: true}) - - expect(console.error).toHaveBeenCalledTimes(1) - expect(console.error).toHaveBeenNthCalledWith( - 1, - "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + expect(() => { + render(
, {legacyRoot: true}) + }).toErrorDev( + [ + "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ], + {withoutStack: true}, ) }) test('legacyRoot uses legacy ReactDOM.hydrate', () => { - jest.spyOn(console, 'error').mockImplementation(() => {}) const ui =
const container = document.createElement('div') container.innerHTML = ReactDOMServer.renderToString(ui) - render(ui, {container, hydrate: true, legacyRoot: true}) - - expect(console.error).toHaveBeenCalledTimes(1) - expect(console.error).toHaveBeenNthCalledWith( - 1, - "Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + expect(() => { + render(ui, {container, hydrate: true, legacyRoot: true}) + }).toErrorDev( + [ + "Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ], + {withoutStack: true}, ) }) diff --git a/src/__tests__/renderHook.js b/src/__tests__/renderHook.js index 92bc47ed..f6b7a343 100644 --- a/src/__tests__/renderHook.js +++ b/src/__tests__/renderHook.js @@ -62,27 +62,26 @@ test('allows wrapper components', async () => { }) test('legacyRoot uses legacy ReactDOM.render', () => { - jest.spyOn(console, 'error').mockImplementation(() => {}) - const Context = React.createContext('default') function Wrapper({children}) { return {children} } - const {result} = renderHook( - () => { - return React.useContext(Context) - }, - { - wrapper: Wrapper, - legacyRoot: true, - }, + let result + expect(() => { + result = renderHook( + () => { + return React.useContext(Context) + }, + { + wrapper: Wrapper, + legacyRoot: true, + }, + ).result + }).toErrorDev( + [ + "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ], + {withoutStack: true}, ) - expect(result.current).toEqual('provided') - - expect(console.error).toHaveBeenCalledTimes(1) - expect(console.error).toHaveBeenNthCalledWith( - 1, - "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", - ) }) diff --git a/tests/failOnUnexpectedConsoleCalls.js b/tests/failOnUnexpectedConsoleCalls.js new file mode 100644 index 00000000..83e0c641 --- /dev/null +++ b/tests/failOnUnexpectedConsoleCalls.js @@ -0,0 +1,129 @@ +// Fork of https://github.com/facebook/react/blob/513417d6951fa3ff5729302b7990b84604b11afa/scripts/jest/setupTests.js#L71-L161 +/** +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +/* eslint-disable prefer-template */ +/* eslint-disable func-names */ +const util = require('util') +const chalk = require('chalk') +const shouldIgnoreConsoleError = require('./shouldIgnoreConsoleError') + +const patchConsoleMethod = (methodName, unexpectedConsoleCallStacks) => { + const newMethod = function (format, ...args) { + // Ignore uncaught errors reported by jsdom + // and React addendums because they're too noisy. + if (methodName === 'error' && shouldIgnoreConsoleError(format, args)) { + return + } + + // Capture the call stack now so we can warn about it later. + // The call stack has helpful information for the test author. + // Don't throw yet though b'c it might be accidentally caught and suppressed. + const stack = new Error().stack + unexpectedConsoleCallStacks.push([ + stack.substr(stack.indexOf('\n') + 1), + util.format(format, ...args), + ]) + } + + console[methodName] = newMethod + + return newMethod +} + +const isSpy = spy => + (spy.calls && typeof spy.calls.count === 'function') || + spy._isMockFunction === true + +const flushUnexpectedConsoleCalls = ( + mockMethod, + methodName, + expectedMatcher, + unexpectedConsoleCallStacks, +) => { + if (console[methodName] !== mockMethod && !isSpy(console[methodName])) { + throw new Error( + `Test did not tear down console.${methodName} mock properly.`, + ) + } + if (unexpectedConsoleCallStacks.length > 0) { + const messages = unexpectedConsoleCallStacks.map( + ([stack, message]) => + `${chalk.red(message)}\n` + + `${stack + .split('\n') + .map(line => chalk.gray(line)) + .join('\n')}`, + ) + + const message = + `Expected test not to call ${chalk.bold( + `console.${methodName}()`, + )}.\n\n` + + 'If the warning is expected, test for it explicitly by:\n' + + `1. Using the ${chalk.bold('.' + expectedMatcher + '()')} ` + + `matcher, or...\n` + + `2. Mock it out using ${chalk.bold( + 'spyOnDev', + )}(console, '${methodName}') or ${chalk.bold( + 'spyOnProd', + )}(console, '${methodName}'), and test that the warning occurs.` + + throw new Error(`${message}\n\n${messages.join('\n\n')}`) + } +} + +const unexpectedErrorCallStacks = [] +const unexpectedWarnCallStacks = [] + +const errorMethod = patchConsoleMethod('error', unexpectedErrorCallStacks) +const warnMethod = patchConsoleMethod('warn', unexpectedWarnCallStacks) + +const flushAllUnexpectedConsoleCalls = () => { + flushUnexpectedConsoleCalls( + errorMethod, + 'error', + 'toErrorDev', + unexpectedErrorCallStacks, + ) + flushUnexpectedConsoleCalls( + warnMethod, + 'warn', + 'toWarnDev', + unexpectedWarnCallStacks, + ) + unexpectedErrorCallStacks.length = 0 + unexpectedWarnCallStacks.length = 0 +} + +const resetAllUnexpectedConsoleCalls = () => { + unexpectedErrorCallStacks.length = 0 + unexpectedWarnCallStacks.length = 0 +} + +expect.extend({ + ...require('./toWarnDev'), +}) + +beforeEach(resetAllUnexpectedConsoleCalls) +afterEach(flushAllUnexpectedConsoleCalls) diff --git a/tests/setup-env.js b/tests/setup-env.js index 264828a9..a4ddfa17 100644 --- a/tests/setup-env.js +++ b/tests/setup-env.js @@ -1 +1,2 @@ import '@testing-library/jest-dom/extend-expect' +import './failOnUnexpectedConsoleCalls' diff --git a/tests/shouldIgnoreConsoleError.js b/tests/shouldIgnoreConsoleError.js new file mode 100644 index 00000000..75528267 --- /dev/null +++ b/tests/shouldIgnoreConsoleError.js @@ -0,0 +1,43 @@ +// Fork of https://github.com/facebook/react/blob/513417d6951fa3ff5729302b7990b84604b11afa/scripts/jest/shouldIgnoreConsoleError.js +/** +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +module.exports = function shouldIgnoreConsoleError(format) { + if (process.env.NODE_ENV !== 'production') { + if (typeof format === 'string') { + if (format.indexOf('Error: Uncaught [') === 0) { + // This looks like an uncaught error from invokeGuardedCallback() wrapper + // in development that is reported by jsdom. Ignore because it's noisy. + return true + } + if (format.indexOf('The above error occurred') === 0) { + // This looks like an error addendum from ReactFiberErrorLogger. + // Ignore it too. + return true + } + } + } + // Looks legit + return false +} diff --git a/tests/toWarnDev.js b/tests/toWarnDev.js new file mode 100644 index 00000000..ac5f1b19 --- /dev/null +++ b/tests/toWarnDev.js @@ -0,0 +1,303 @@ +// Fork of https://github.com/facebook/react/blob/513417d6951fa3ff5729302b7990b84604b11afa/scripts/jest/matchers/toWarnDev.js +/** +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +/* eslint-disable no-unsafe-finally */ +/* eslint-disable no-negated-condition */ +/* eslint-disable @babel/no-invalid-this */ +/* eslint-disable prefer-template */ +/* eslint-disable func-names */ +/* eslint-disable complexity */ +const util = require('util') +const jestDiff = require('jest-diff').default +const shouldIgnoreConsoleError = require('./shouldIgnoreConsoleError') + +function normalizeCodeLocInfo(str) { + if (typeof str !== 'string') { + return str + } + // This special case exists only for the special source location in + // ReactElementValidator. That will go away if we remove source locations. + str = str.replace(/Check your code at .+?:\d+/g, 'Check your code at **') + // V8 format: + // at Component (/path/filename.js:123:45) + // React format: + // in Component (at filename.js:123) + // eslint-disable-next-line prefer-arrow-callback + return str.replace(/\n +(?:at|in) ([\S]+)[^\n]*/g, function (m, name) { + return '\n in ' + name + ' (at **)' + }) +} + +const createMatcherFor = (consoleMethod, matcherName) => + function matcher(callback, expectedMessages, options = {}) { + if (process.env.NODE_ENV !== 'production') { + // Warn about incorrect usage of matcher. + if (typeof expectedMessages === 'string') { + expectedMessages = [expectedMessages] + } else if (!Array.isArray(expectedMessages)) { + throw Error( + `${matcherName}() requires a parameter of type string or an array of strings ` + + `but was given ${typeof expectedMessages}.`, + ) + } + if ( + options != null && + (typeof options !== 'object' || Array.isArray(options)) + ) { + throw new Error( + `${matcherName}() second argument, when present, should be an object. ` + + 'Did you forget to wrap the messages into an array?', + ) + } + if (arguments.length > 3) { + // `matcher` comes from Jest, so it's more than 2 in practice + throw new Error( + `${matcherName}() received more than two arguments. ` + + 'Did you forget to wrap the messages into an array?', + ) + } + + const withoutStack = options.withoutStack + const logAllErrors = options.logAllErrors + const warningsWithoutComponentStack = [] + const warningsWithComponentStack = [] + const unexpectedWarnings = [] + + let lastWarningWithMismatchingFormat = null + let lastWarningWithExtraComponentStack = null + + // Catch errors thrown by the callback, + // But only rethrow them if all test expectations have been satisfied. + // Otherwise an Error in the callback can mask a failed expectation, + // and result in a test that passes when it shouldn't. + let caughtError + + const isLikelyAComponentStack = message => + typeof message === 'string' && + (message.includes('\n in ') || message.includes('\n at ')) + + const consoleSpy = (format, ...args) => { + // Ignore uncaught errors reported by jsdom + // and React addendums because they're too noisy. + if ( + !logAllErrors && + consoleMethod === 'error' && + shouldIgnoreConsoleError(format, args) + ) { + return + } + + const message = util.format(format, ...args) + const normalizedMessage = normalizeCodeLocInfo(message) + + // Remember if the number of %s interpolations + // doesn't match the number of arguments. + // We'll fail the test if it happens. + let argIndex = 0 + format.replace(/%s/g, () => argIndex++) + if (argIndex !== args.length) { + lastWarningWithMismatchingFormat = { + format, + args, + expectedArgCount: argIndex, + } + } + + // Protect against accidentally passing a component stack + // to warning() which already injects the component stack. + if ( + args.length >= 2 && + isLikelyAComponentStack(args[args.length - 1]) && + isLikelyAComponentStack(args[args.length - 2]) + ) { + lastWarningWithExtraComponentStack = { + format, + } + } + + for (let index = 0; index < expectedMessages.length; index++) { + const expectedMessage = expectedMessages[index] + if ( + normalizedMessage === expectedMessage || + normalizedMessage.includes(expectedMessage) + ) { + if (isLikelyAComponentStack(normalizedMessage)) { + warningsWithComponentStack.push(normalizedMessage) + } else { + warningsWithoutComponentStack.push(normalizedMessage) + } + expectedMessages.splice(index, 1) + return + } + } + + let errorMessage + if (expectedMessages.length === 0) { + errorMessage = + 'Unexpected warning recorded: ' + + this.utils.printReceived(normalizedMessage) + } else if (expectedMessages.length === 1) { + errorMessage = + 'Unexpected warning recorded: ' + + jestDiff(expectedMessages[0], normalizedMessage) + } else { + errorMessage = + 'Unexpected warning recorded: ' + + jestDiff(expectedMessages, [normalizedMessage]) + } + + // Record the call stack for unexpected warnings. + // We don't throw an Error here though, + // Because it might be suppressed by ReactFiberScheduler. + unexpectedWarnings.push(new Error(errorMessage)) + } + + // TODO Decide whether we need to support nested toWarn* expectations. + // If we don't need it, add a check here to see if this is already our spy, + // And throw an error. + const originalMethod = console[consoleMethod] + + // Avoid using Jest's built-in spy since it can't be removed. + console[consoleMethod] = consoleSpy + + try { + callback() + } catch (error) { + caughtError = error + } finally { + // Restore the unspied method so that unexpected errors fail tests. + console[consoleMethod] = originalMethod + + // Any unexpected Errors thrown by the callback should fail the test. + // This should take precedence since unexpected errors could block warnings. + if (caughtError) { + throw caughtError + } + + // Any unexpected warnings should be treated as a failure. + if (unexpectedWarnings.length > 0) { + return { + message: () => unexpectedWarnings[0].stack, + pass: false, + } + } + + // Any remaining messages indicate a failed expectations. + if (expectedMessages.length > 0) { + return { + message: () => + `Expected warning was not recorded:\n ${this.utils.printReceived( + expectedMessages[0], + )}`, + pass: false, + } + } + + if (typeof withoutStack === 'number') { + // We're expecting a particular number of warnings without stacks. + if (withoutStack !== warningsWithoutComponentStack.length) { + return { + message: () => + `Expected ${withoutStack} warnings without a component stack but received ${warningsWithoutComponentStack.length}:\n` + + warningsWithoutComponentStack.map(warning => + this.utils.printReceived(warning), + ), + pass: false, + } + } + } else if (withoutStack === true) { + // We're expecting that all warnings won't have the stack. + // If some warnings have it, it's an error. + if (warningsWithComponentStack.length > 0) { + return { + message: () => + `Received warning unexpectedly includes a component stack:\n ${this.utils.printReceived( + warningsWithComponentStack[0], + )}\nIf this warning intentionally includes the component stack, remove ` + + `{withoutStack: true} from the ${matcherName}() call. If you have a mix of ` + + `warnings with and without stack in one ${matcherName}() call, pass ` + + `{withoutStack: N} where N is the number of warnings without stacks.`, + pass: false, + } + } + } else if (withoutStack === false || withoutStack === undefined) { + // We're expecting that all warnings *do* have the stack (default). + // If some warnings don't have it, it's an error. + if (warningsWithoutComponentStack.length > 0) { + return { + message: () => + `Received warning unexpectedly does not include a component stack:\n ${this.utils.printReceived( + warningsWithoutComponentStack[0], + )}\nIf this warning intentionally omits the component stack, add ` + + `{withoutStack: true} to the ${matcherName} call.`, + pass: false, + } + } + } else { + throw Error( + `The second argument for ${matcherName}(), when specified, must be an object. It may have a ` + + `property called "withoutStack" whose value may be undefined, boolean, or a number. ` + + `Instead received ${typeof withoutStack}.`, + ) + } + + if (lastWarningWithMismatchingFormat !== null) { + return { + message: () => + `Received ${ + lastWarningWithMismatchingFormat.args.length + } arguments for a message with ${ + lastWarningWithMismatchingFormat.expectedArgCount + } placeholders:\n ${this.utils.printReceived( + lastWarningWithMismatchingFormat.format, + )}`, + pass: false, + } + } + + if (lastWarningWithExtraComponentStack !== null) { + return { + message: () => + `Received more than one component stack for a warning:\n ${this.utils.printReceived( + lastWarningWithExtraComponentStack.format, + )}\nDid you accidentally pass a stack to warning() as the last argument? ` + + `Don't forget warning() already injects the component stack automatically.`, + pass: false, + } + } + + return {pass: true} + } + } else { + // Any uncaught errors or warnings should fail tests in production mode. + callback() + + return {pass: true} + } + } + +module.exports = { + toWarnDev: createMatcherFor('warn', 'toWarnDev'), + toErrorDev: createMatcherFor('error', 'toErrorDev'), +} From c43512a9271f5738496a3ed49aed7e3e9dad071c Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 12 Dec 2022 19:33:05 +0200 Subject: [PATCH 282/327] GitHub Workflows security hardening (#1162) --- .github/workflows/validate.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index ad4adccf..0f99d084 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -12,6 +12,10 @@ on: - 'alpha' - '!all-contributors/**' pull_request: {} +permissions: + actions: write # to cancel/stop running workflows (styfle/cancel-workflow-action) + contents: read # to fetch code (actions/checkout) + jobs: main: continue-on-error: ${{ matrix.react != 'latest' }} @@ -58,6 +62,10 @@ jobs: flags: ${{ matrix.react }} release: + permissions: + actions: write # to cancel/stop running workflows (styfle/cancel-workflow-action) + contents: write # to create release tags (cycjimmy/semantic-release-action) + needs: main runs-on: ubuntu-latest if: From 9b7a1e2bea5bf20ba9728f98eb7c68cdb80b7fdd Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 31 Jan 2023 05:53:01 +0100 Subject: [PATCH 283/327] feat: Drop support for Node.js 12.x (#1169) BREAKING CHANGE: Minimum supported Node.js version is now 14.x --- .codesandbox/ci.json | 2 +- .github/workflows/validate.yml | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index bf3237bb..d5850328 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -1,5 +1,5 @@ { "installCommand": "install:csb", "sandboxes": ["new", "github/kentcdodds/react-testing-library-examples"], - "node": "12" + "node": "14" } diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 0f99d084..53093e67 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - node: [12, 14, 16, 18] + node: [14, 16, 18] react: [latest, next, experimental] runs-on: ubuntu-latest steps: diff --git a/package.json b/package.json index d2dd6a97..9ee97f1d 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "types": "types/index.d.ts", "module": "dist/@testing-library/react.esm.js", "engines": { - "node": ">=12" + "node": ">=14" }, "scripts": { "prebuild": "rimraf dist", From 1934bf224f9d45f3fc91cb722e31d3885aa9c7a0 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 15 Feb 2023 17:52:48 +0100 Subject: [PATCH 284/327] Bump kcd-scripts to 13.0.0 (#1170) * Bump kcd-scripts to 13.0.0 * Resolve lint issues --- package.json | 8 ++++++-- src/__tests__/cleanup.js | 3 ++- src/__tests__/debug.js | 3 +-- src/__tests__/new-act.js | 8 ++++---- src/__tests__/renderHook.js | 2 +- tests/setup-env.js | 3 +++ tests/toWarnDev.js | 2 +- types/test.tsx | 1 - 8 files changed, 18 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 9ee97f1d..b475390a 100644 --- a/package.json +++ b/package.json @@ -53,8 +53,8 @@ "@testing-library/jest-dom": "^5.11.6", "chalk": "^4.1.2", "dotenv-cli": "^4.0.0", - "jest-diff": "^27.5.1", - "kcd-scripts": "^11.1.0", + "jest-diff": "^29.4.1", + "kcd-scripts": "^13.0.0", "npm-run-all": "^4.1.5", "react": "^18.0.0", "react-dom": "^18.0.0", @@ -67,6 +67,9 @@ }, "eslintConfig": { "extends": "./node_modules/kcd-scripts/eslint.js", + "parserOptions": { + "ecmaVersion": 2022 + }, "globals": { "globalThis": "readonly" }, @@ -76,6 +79,7 @@ "import/no-unassigned-import": "off", "import/named": "off", "testing-library/no-container": "off", + "testing-library/no-debugging-utils": "off", "testing-library/no-dom-import": "off", "testing-library/no-unnecessary-act": "off", "testing-library/prefer-user-event": "off" diff --git a/src/__tests__/cleanup.js b/src/__tests__/cleanup.js index 4517c098..9f17c722 100644 --- a/src/__tests__/cleanup.js +++ b/src/__tests__/cleanup.js @@ -64,7 +64,7 @@ describe('fake timers and missing act warnings', () => { let cancelled = false Promise.resolve().then(() => { microTaskSpy() - // eslint-disable-next-line jest/no-if -- false positive + // eslint-disable-next-line jest/no-if, jest/no-conditional-in-test -- false positive if (!cancelled) { setDeferredCounter(counter) } @@ -96,6 +96,7 @@ describe('fake timers and missing act warnings', () => { let cancelled = false setTimeout(() => { deferredStateUpdateSpy() + // eslint-disable-next-line jest/no-conditional-in-test -- false-positive if (!cancelled) { setDeferredCounter(counter) } diff --git a/src/__tests__/debug.js b/src/__tests__/debug.js index f3aad595..c6a1d1fe 100644 --- a/src/__tests__/debug.js +++ b/src/__tests__/debug.js @@ -42,7 +42,7 @@ test('allows same arguments as prettyDOM', () => { debug(container, 6, {highlight: false}) expect(console.log).toHaveBeenCalledTimes(1) expect(console.log.mock.calls[0]).toMatchInlineSnapshot(` - Array [ + [
..., ] @@ -52,5 +52,4 @@ test('allows same arguments as prettyDOM', () => { /* eslint no-console: "off", - testing-library/no-debug: "off", */ diff --git a/src/__tests__/new-act.js b/src/__tests__/new-act.js index 4909d4a6..0412a8a3 100644 --- a/src/__tests__/new-act.js +++ b/src/__tests__/new-act.js @@ -47,8 +47,8 @@ test('async act recovers from errors', async () => { } expect(console.error).toHaveBeenCalledTimes(1) expect(console.error.mock.calls).toMatchInlineSnapshot(` - Array [ - Array [ + [ + [ call console.error, ], ] @@ -65,8 +65,8 @@ test('async act recovers from sync errors', async () => { } expect(console.error).toHaveBeenCalledTimes(1) expect(console.error.mock.calls).toMatchInlineSnapshot(` - Array [ - Array [ + [ + [ call console.error, ], ] diff --git a/src/__tests__/renderHook.js b/src/__tests__/renderHook.js index f6b7a343..11b7009a 100644 --- a/src/__tests__/renderHook.js +++ b/src/__tests__/renderHook.js @@ -21,7 +21,7 @@ test('allows rerendering', () => { const [left, setLeft] = React.useState('left') const [right, setRight] = React.useState('right') - // eslint-disable-next-line jest/no-if + // eslint-disable-next-line jest/no-if, jest/no-conditional-in-test -- false-positive switch (branch) { case 'left': return [left, setLeft] diff --git a/tests/setup-env.js b/tests/setup-env.js index a4ddfa17..c9b976f5 100644 --- a/tests/setup-env.js +++ b/tests/setup-env.js @@ -1,2 +1,5 @@ import '@testing-library/jest-dom/extend-expect' import './failOnUnexpectedConsoleCalls' +import {TextEncoder} from 'util' + +global.TextEncoder = TextEncoder diff --git a/tests/toWarnDev.js b/tests/toWarnDev.js index ac5f1b19..ca58346f 100644 --- a/tests/toWarnDev.js +++ b/tests/toWarnDev.js @@ -24,7 +24,7 @@ SOFTWARE. */ /* eslint-disable no-unsafe-finally */ /* eslint-disable no-negated-condition */ -/* eslint-disable @babel/no-invalid-this */ +/* eslint-disable no-invalid-this */ /* eslint-disable prefer-template */ /* eslint-disable func-names */ /* eslint-disable complexity */ diff --git a/types/test.tsx b/types/test.tsx index 17ba7012..c33f07b6 100644 --- a/types/test.tsx +++ b/types/test.tsx @@ -188,7 +188,6 @@ export function testRenderHookProps() { eslint testing-library/prefer-explicit-assert: "off", testing-library/no-wait-for-empty-callback: "off", - testing-library/no-debug: "off", testing-library/prefer-screen-queries: "off" */ From 153a095369cdbe3149a720df9435dc698024c678 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Thu, 16 Feb 2023 23:34:19 +0100 Subject: [PATCH 285/327] chore: Allow semantic-release to post updates in issues (#1176) --- .github/workflows/validate.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 53093e67..5db8153c 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -65,6 +65,7 @@ jobs: permissions: actions: write # to cancel/stop running workflows (styfle/cancel-workflow-action) contents: write # to create release tags (cycjimmy/semantic-release-action) + issues: write # to post release that resolves an issue (cycjimmy/semantic-release-action) needs: main runs-on: ubuntu-latest From 6653c239c0acbafd204326c8951cde8206d39898 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Thu, 16 Feb 2023 23:37:50 +0100 Subject: [PATCH 286/327] feat: Bump `@testing-library/dom` to 9.0.0 (#1177) BREAKING CHANGE: See https://github.com/testing-library/dom-testing-library/releases/tag/v9.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b475390a..f9061345 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^8.5.0", + "@testing-library/dom": "^9.0.0", "@types/react-dom": "^18.0.0" }, "devDependencies": { From f78839bf4147a777a823e33a429bcf5de9562f9e Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Thu, 16 Feb 2023 23:46:50 +0100 Subject: [PATCH 287/327] fix: Prevent "missing act" warning for queued microtasks (#1137) * Add intended behavior * fix: Prevent "missing act" warning for in-flight promises * Disable TL lint rules in tests * Implementation without macrotask * Now I member --- package.json | 2 + src/__tests__/end-to-end.js | 211 ++++++++++++++++++++++++++---------- src/pure.js | 30 ++++- 3 files changed, 182 insertions(+), 61 deletions(-) diff --git a/package.json b/package.json index f9061345..70aebdad 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,8 @@ "testing-library/no-debugging-utils": "off", "testing-library/no-dom-import": "off", "testing-library/no-unnecessary-act": "off", + "testing-library/prefer-explicit-assert": "off", + "testing-library/prefer-find-by": "off", "testing-library/prefer-user-event": "off" } }, diff --git a/src/__tests__/end-to-end.js b/src/__tests__/end-to-end.js index cf222aec..005591d3 100644 --- a/src/__tests__/end-to-end.js +++ b/src/__tests__/end-to-end.js @@ -1,73 +1,164 @@ import * as React from 'react' import {render, waitForElementToBeRemoved, screen, waitFor} from '../' -const fetchAMessage = () => - new Promise(resolve => { - // we are using random timeout here to simulate a real-time example - // of an async operation calling a callback at a non-deterministic time - const randomTimeout = Math.floor(Math.random() * 100) - setTimeout(() => { - resolve({returnedMessage: 'Hello World'}) - }, randomTimeout) - }) - -function ComponentWithLoader() { - const [state, setState] = React.useState({data: undefined, loading: true}) - React.useEffect(() => { - let cancelled = false - fetchAMessage().then(data => { - if (!cancelled) { - setState({data, loading: false}) - } +describe.each([ + ['real timers', () => jest.useRealTimers()], + ['fake legacy timers', () => jest.useFakeTimers('legacy')], + ['fake modern timers', () => jest.useFakeTimers('modern')], +])( + 'it waits for the data to be loaded in a macrotask using %s', + (label, useTimers) => { + beforeEach(() => { + useTimers() + }) + + afterEach(() => { + jest.useRealTimers() }) - return () => { - cancelled = true + const fetchAMessageInAMacrotask = () => + new Promise(resolve => { + // we are using random timeout here to simulate a real-time example + // of an async operation calling a callback at a non-deterministic time + const randomTimeout = Math.floor(Math.random() * 100) + setTimeout(() => { + resolve({returnedMessage: 'Hello World'}) + }, randomTimeout) + }) + + function ComponentWithMacrotaskLoader() { + const [state, setState] = React.useState({data: undefined, loading: true}) + React.useEffect(() => { + let cancelled = false + fetchAMessageInAMacrotask().then(data => { + if (!cancelled) { + setState({data, loading: false}) + } + }) + + return () => { + cancelled = true + } + }, []) + + if (state.loading) { + return
Loading...
+ } + + return ( +
+ Loaded this message: {state.data.returnedMessage}! +
+ ) } - }, []) - if (state.loading) { - return
Loading...
- } + test('waitForElementToBeRemoved', async () => { + render() + const loading = () => screen.getByText('Loading...') + await waitForElementToBeRemoved(loading) + expect(screen.getByTestId('message')).toHaveTextContent(/Hello World/) + }) + + test('waitFor', async () => { + render() + await waitFor(() => screen.getByText(/Loading../)) + await waitFor(() => screen.getByText(/Loaded this message:/)) + expect(screen.getByTestId('message')).toHaveTextContent(/Hello World/) + }) - return ( -
- Loaded this message: {state.data.returnedMessage}! -
- ) -} + test('findBy', async () => { + render() + await expect(screen.findByTestId('message')).resolves.toHaveTextContent( + /Hello World/, + ) + }) + }, +) describe.each([ ['real timers', () => jest.useRealTimers()], ['fake legacy timers', () => jest.useFakeTimers('legacy')], ['fake modern timers', () => jest.useFakeTimers('modern')], -])('it waits for the data to be loaded using %s', (label, useTimers) => { - beforeEach(() => { - useTimers() - }) - - afterEach(() => { - jest.useRealTimers() - }) - - test('waitForElementToBeRemoved', async () => { - render() - const loading = () => screen.getByText('Loading...') - await waitForElementToBeRemoved(loading) - expect(screen.getByTestId('message')).toHaveTextContent(/Hello World/) - }) - - test('waitFor', async () => { - render() - const message = () => screen.getByText(/Loaded this message:/) - await waitFor(message) - expect(screen.getByTestId('message')).toHaveTextContent(/Hello World/) - }) - - test('findBy', async () => { - render() - await expect(screen.findByTestId('message')).resolves.toHaveTextContent( - /Hello World/, - ) - }) -}) +])( + 'it waits for the data to be loaded in a microtask using %s', + (label, useTimers) => { + beforeEach(() => { + useTimers() + }) + + afterEach(() => { + jest.useRealTimers() + }) + + const fetchAMessageInAMicrotask = () => + Promise.resolve({ + status: 200, + json: () => Promise.resolve({title: 'Hello World'}), + }) + + function ComponentWithMicrotaskLoader() { + const [fetchState, setFetchState] = React.useState({fetching: true}) + + React.useEffect(() => { + if (fetchState.fetching) { + fetchAMessageInAMicrotask().then(res => { + return ( + res + .json() + // By spec, the runtime can only yield back to the event loop once + // the microtask queue is empty. + // So we ensure that we actually wait for that as well before yielding back from `waitFor`. + .then(data => data) + .then(data => data) + .then(data => data) + .then(data => data) + .then(data => data) + .then(data => data) + .then(data => data) + .then(data => data) + .then(data => data) + .then(data => data) + .then(data => data) + .then(data => { + setFetchState({todo: data.title, fetching: false}) + }) + ) + }) + } + }, [fetchState]) + + if (fetchState.fetching) { + return

Loading..

+ } + + return ( +
Loaded this message: {fetchState.todo}
+ ) + } + + test('waitForElementToBeRemoved', async () => { + render() + const loading = () => screen.getByText('Loading..') + await waitForElementToBeRemoved(loading) + expect(screen.getByTestId('message')).toHaveTextContent(/Hello World/) + }) + + test('waitFor', async () => { + render() + await waitFor(() => { + screen.getByText('Loading..') + }) + await waitFor(() => { + screen.getByText(/Loaded this message:/) + }) + expect(screen.getByTestId('message')).toHaveTextContent(/Hello World/) + }) + + test('findBy', async () => { + render() + await expect(screen.findByTestId('message')).resolves.toHaveTextContent( + /Hello World/, + ) + }) + }, +) diff --git a/src/pure.js b/src/pure.js index 94b3b2bd..845aede1 100644 --- a/src/pure.js +++ b/src/pure.js @@ -12,6 +12,20 @@ import act, { } from './act-compat' import {fireEvent} from './fire-event' +function jestFakeTimersAreEnabled() { + /* istanbul ignore else */ + if (typeof jest !== 'undefined' && jest !== null) { + return ( + // legacy timers + setTimeout._isMockFunction === true || // modern timers + // eslint-disable-next-line prefer-object-has-own -- No Object.hasOwn in all target environments we support. + Object.prototype.hasOwnProperty.call(setTimeout, 'clock') + ) + } // istanbul ignore next + + return false +} + configureDTL({ unstable_advanceTimersWrapper: cb => { return act(cb) @@ -23,7 +37,21 @@ configureDTL({ const previousActEnvironment = getIsReactActEnvironment() setReactActEnvironment(false) try { - return await cb() + const result = await cb() + // Drain microtask queue. + // Otherwise we'll restore the previous act() environment, before we resolve the `waitFor` call. + // The caller would have no chance to wrap the in-flight Promises in `act()` + await new Promise(resolve => { + setTimeout(() => { + resolve() + }, 0) + + if (jestFakeTimersAreEnabled()) { + jest.advanceTimersByTime(0) + } + }) + + return result } finally { setReactActEnvironment(previousActEnvironment) } From f6c6d9610da4fe90ec64445391e0ea8bfe39e65d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20De=20Boey?= Date: Wed, 26 Apr 2023 12:56:53 +0200 Subject: [PATCH 288/327] chore: remove `styfle/cancel-workflow-action` usage (#1204) --- .github/workflows/validate.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 5db8153c..60e8fd44 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -11,7 +11,12 @@ on: - 'beta' - 'alpha' - '!all-contributors/**' - pull_request: {} + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + permissions: actions: write # to cancel/stop running workflows (styfle/cancel-workflow-action) contents: read # to fetch code (actions/checkout) @@ -28,9 +33,6 @@ jobs: react: [latest, next, experimental] runs-on: ubuntu-latest steps: - - name: πŸ›‘ Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.9.0 - - name: ⬇️ Checkout repo uses: actions/checkout@v2 @@ -73,9 +75,6 @@ jobs: ${{ github.repository == 'testing-library/react-testing-library' && github.event_name == 'push' }} steps: - - name: πŸ›‘ Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.9.0 - - name: ⬇️ Checkout repo uses: actions/checkout@v2 From 5dc81dc790b1831707e89cf52b3fecb3c3d294d2 Mon Sep 17 00:00:00 2001 From: Matan Borenkraout Date: Thu, 4 May 2023 15:17:31 +0300 Subject: [PATCH 289/327] chore: rename `next` channel to `canary` (#1207) * chore: add canary to our test matrix * chore: rename next to canary --- .github/workflows/validate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 60e8fd44..f1359d76 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -30,7 +30,7 @@ jobs: fail-fast: false matrix: node: [14, 16, 18] - react: [latest, next, experimental] + react: [latest, canary, experimental] runs-on: ubuntu-latest steps: - name: ⬇️ Checkout repo From 6b4180e71286cef86a359435697965e59d408d91 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Sun, 28 May 2023 11:03:05 +0200 Subject: [PATCH 290/327] test: Add test for flushing before exiting `waitFor` (#1215) --- src/__tests__/end-to-end.js | 72 ++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/src/__tests__/end-to-end.js b/src/__tests__/end-to-end.js index 005591d3..f93c23be 100644 --- a/src/__tests__/end-to-end.js +++ b/src/__tests__/end-to-end.js @@ -80,7 +80,7 @@ describe.each([ ['fake legacy timers', () => jest.useFakeTimers('legacy')], ['fake modern timers', () => jest.useFakeTimers('modern')], ])( - 'it waits for the data to be loaded in a microtask using %s', + 'it waits for the data to be loaded in many microtask using %s', (label, useTimers) => { beforeEach(() => { useTimers() @@ -162,3 +162,73 @@ describe.each([ }) }, ) + +describe.each([ + ['real timers', () => jest.useRealTimers()], + ['fake legacy timers', () => jest.useFakeTimers('legacy')], + ['fake modern timers', () => jest.useFakeTimers('modern')], +])( + 'it waits for the data to be loaded in a microtask using %s', + (label, useTimers) => { + beforeEach(() => { + useTimers() + }) + + afterEach(() => { + jest.useRealTimers() + }) + + const fetchAMessageInAMicrotask = () => + Promise.resolve({ + status: 200, + json: () => Promise.resolve({title: 'Hello World'}), + }) + + function ComponentWithMicrotaskLoader() { + const [fetchState, setFetchState] = React.useState({fetching: true}) + + React.useEffect(() => { + if (fetchState.fetching) { + fetchAMessageInAMicrotask().then(res => { + return res.json().then(data => { + setFetchState({todo: data.title, fetching: false}) + }) + }) + } + }, [fetchState]) + + if (fetchState.fetching) { + return

Loading..

+ } + + return ( +
Loaded this message: {fetchState.todo}
+ ) + } + + test('waitForElementToBeRemoved', async () => { + render() + const loading = () => screen.getByText('Loading..') + await waitForElementToBeRemoved(loading) + expect(screen.getByTestId('message')).toHaveTextContent(/Hello World/) + }) + + test('waitFor', async () => { + render() + await waitFor(() => { + screen.getByText('Loading..') + }) + await waitFor(() => { + screen.getByText(/Loaded this message:/) + }) + expect(screen.getByTestId('message')).toHaveTextContent(/Hello World/) + }) + + test('findBy', async () => { + render() + await expect(screen.findByTestId('message')).resolves.toHaveTextContent( + /Hello World/, + ) + }) + }, +) From 6de5f4c29f73e740152de31bbe3ccc6e711aa210 Mon Sep 17 00:00:00 2001 From: Matan Borenkraout Date: Wed, 26 Jul 2023 21:57:48 +0300 Subject: [PATCH 291/327] docs(readme): remove deprecated link (#1229) Resolves #1228 --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 45324901..6752c3d2 100644 --- a/README.md +++ b/README.md @@ -376,9 +376,6 @@ Some included are: - [`react-router`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/main/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-router.js&previewwindow=tests) - [`react-context`](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/main/?fontsize=14&module=%2Fsrc%2F__tests__%2Freact-context.js&previewwindow=tests) -You can also find React Testing Library examples at -[react-testing-examples.com](https://react-testing-examples.com/jest-rtl/). - ## Hooks If you are interested in testing a custom hook, check out [React Hooks Testing From 5b489166e50d5d53608d98b283e8e936e1cce91d Mon Sep 17 00:00:00 2001 From: Colin Diesh Date: Sun, 10 Sep 2023 15:58:41 -0400 Subject: [PATCH 292/327] docs: fix readme CI badge (#1237) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6752c3d2..b129c789 100644 --- a/README.md +++ b/README.md @@ -651,7 +651,7 @@ Contributions of any kind welcome! [npm]: https://www.npmjs.com/ [yarn]: https://classic.yarnpkg.com [node]: https://nodejs.org -[build-badge]: https://img.shields.io/github/workflow/status/testing-library/react-testing-library/validate?logo=github&style=flat-square +[build-badge]: https://img.shields.io/github/actions/workflow/status/testing-library/react-testing-library/validate.yml?branch=main&logo=github [build]: https://github.com/testing-library/react-testing-library/actions?query=workflow%3Avalidate [coverage-badge]: https://img.shields.io/codecov/c/github/testing-library/react-testing-library.svg?style=flat-square [coverage]: https://codecov.io/github/testing-library/react-testing-library From c04b8f006c5a683d05c460c8ee1e2248d6f74350 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 10 Sep 2023 23:00:37 +0300 Subject: [PATCH 293/327] docs: add cmdcolin as a contributor for doc (#1238) * docs: update README.md * docs: update .all-contributorsrc --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 13 +- README.md | 286 ++++++++++++++++++++++---------------------- 2 files changed, 155 insertions(+), 144 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 270dd6a0..16957ca9 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1344,8 +1344,19 @@ "contributions": [ "doc" ] + }, + { + "login": "cmdcolin", + "name": "Colin Diesh", + "avatar_url": "https://avatars.githubusercontent.com/u/6511937?v=4", + "profile": "http://cmdcolin.github.io", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, - "repoHost": "https://github.com" + "repoHost": "https://github.com", + "commitType": "docs", + "commitConvention": "angular" } diff --git a/README.md b/README.md index b129c789..a3731749 100644 --- a/README.md +++ b/README.md @@ -449,189 +449,189 @@ Thanks goes to these people ([emoji key][emojis]): - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + + + + - - -
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Ryan Castner
Ryan Castner

πŸ“–
Daniel Sandiego
Daniel Sandiego

πŸ’»
PaweΕ‚ MikoΕ‚ajczyk
PaweΕ‚ MikoΕ‚ajczyk

πŸ’»
Alejandro ÑÑñez Ortiz
Alejandro ÑÑñez Ortiz

πŸ“–
Matt Parrish
Matt Parrish

πŸ› πŸ’» πŸ“– ⚠️
Justin Hall
Justin Hall

πŸ“¦
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Anto Aravinth
Anto Aravinth

πŸ’» ⚠️ πŸ“–
Jonah Moses
Jonah Moses

πŸ“–
Łukasz Gandecki
Łukasz Gandecki

πŸ’» ⚠️ πŸ“–
Ivan Babak
Ivan Babak

πŸ› πŸ€”
Jesse Day
Jesse Day

πŸ’»
Ernesto GarcΓ­a
Ernesto GarcΓ­a

πŸ’¬ πŸ’» πŸ“–
Josef Maxx Blake
Josef Maxx Blake

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Michal Baranowski
Michal Baranowski

πŸ“ βœ…
Arthur Puthin
Arthur Puthin

πŸ“–
Thomas Chia
Thomas Chia

πŸ’» πŸ“–
Thiago Galvani
Thiago Galvani

πŸ“–
Christian
Christian

⚠️
Alex Krolick
Alex Krolick

πŸ’¬ πŸ“– πŸ’‘ πŸ€”
Johann Hubert Sonntagbauer
Johann Hubert Sonntagbauer

πŸ’» πŸ“– ⚠️
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Maddi Joyce
Maddi Joyce

πŸ’»
Ryan Vice
Ryan Vice

πŸ“–
Ian Wilson
Ian Wilson

πŸ“ βœ…
Daniel
Daniel

πŸ› πŸ’»
Giorgio Polvara
Giorgio Polvara

πŸ› πŸ€”
John Gozde
John Gozde

πŸ’»
Sam Horton
Sam Horton

πŸ“– πŸ’‘ πŸ€”
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Richard Kotze (mobile)
Richard Kotze (mobile)

πŸ“–
Brahian E. Soto Mercedes
Brahian E. Soto Mercedes

πŸ“–
Benoit de La Forest
Benoit de La Forest

πŸ“–
Salah
Salah

πŸ’» ⚠️
Adam Gordon
Adam Gordon

πŸ› πŸ’»
Matija Marohnić
Matija Marohnić

πŸ“–
Justice Mba
Justice Mba

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
Mark Pollmann
Mark Pollmann

πŸ“–
Ehtesham Kafeel
Ehtesham Kafeel

πŸ’» πŸ“–
Julio PavΓ³n
Julio PavΓ³n

πŸ’»
Duncan L
Duncan L

πŸ“– πŸ’‘
Tiago Almeida
Tiago Almeida

πŸ“–
Robert Smith
Robert Smith

πŸ›
Zach Green
Zach Green

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
dadamssg
dadamssg

πŸ“–
Yazan Aabed
Yazan Aabed

πŸ“
Tim
Tim

πŸ› πŸ’» πŸ“– ⚠️
Divyanshu Maithani
Divyanshu Maithani

βœ… πŸ“Ή
Deepak Grover
Deepak Grover

βœ… πŸ“Ή
Eyal Cohen
Eyal Cohen

πŸ“–
Peter Makowski
Peter Makowski

πŸ“–
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Michiel Nuyts
Michiel Nuyts

πŸ“–
Joe Ng'ethe
Joe Ng'ethe

πŸ’» πŸ“–
Kate
Kate

πŸ“–
Sean
Sean

πŸ“–
James Long
James Long

πŸ€” πŸ“¦
Herb Hagely
Herb Hagely

πŸ’‘
Alex Wendte
Alex Wendte

πŸ’‘
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€ 🎨
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Monica Powell
Monica Powell

πŸ“–
Vitaly Sivkov
Vitaly Sivkov

πŸ’»
Weyert de Boer
Weyert de Boer

πŸ€” πŸ‘€ 🎨
EstebanMarin
EstebanMarin

πŸ“–
Victor Martins
Victor Martins

πŸ“–
Royston Shufflebotham
Royston Shufflebotham

πŸ› πŸ“– πŸ’‘
chrbala
chrbala

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️ πŸ‘€
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Donavon West
Donavon West

πŸ’» πŸ“– πŸ€” ⚠️
Richard Maisano
Richard Maisano

πŸ’»
Marco Biedermann
Marco Biedermann

πŸ’» 🚧 ⚠️
Alex Zherdev
Alex Zherdev

πŸ› πŸ’»
AndrΓ© Matulionis dos Santos
AndrΓ© Matulionis dos Santos

πŸ’» πŸ’‘ ⚠️
Daniel K.
Daniel K.

πŸ› πŸ’» πŸ€” ⚠️ πŸ‘€
mohamedmagdy17593
mohamedmagdy17593

πŸ’»
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Loren ☺️
Loren ☺️

πŸ“–
MarkFalconbridge
MarkFalconbridge

πŸ› πŸ’»
Vinicius
Vinicius

πŸ“– πŸ’‘
Peter Schyma
Peter Schyma

πŸ’»
Ian Schmitz
Ian Schmitz

πŸ“–
Joel Marcotte
Joel Marcotte

πŸ› ⚠️ πŸ’»
Alejandro Dustet
Alejandro Dustet

πŸ›
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
Pascal Duez
Pascal Duez

πŸ“¦
Minh Nguyen
Minh Nguyen

πŸ’»
LiaoJimmy
LiaoJimmy

πŸ“–
Sunil Pai
Sunil Pai

πŸ’» ⚠️
Dan Abramov
Dan Abramov

πŸ‘€
Brandon Carroll
Brandon Carroll

πŸ“–
Lucas Machado
Lucas Machado

πŸ“–
Pascal Duez
Pascal Duez

πŸ“¦
Minh Nguyen
Minh Nguyen

πŸ’»
LiaoJimmy
LiaoJimmy

πŸ“–
Sunil Pai
Sunil Pai

πŸ’» ⚠️
Dan Abramov
Dan Abramov

πŸ‘€
Christian Murphy
Christian Murphy

πŸš‡
Ivakhnenko Dmitry
Ivakhnenko Dmitry

πŸ’»
James George
James George

πŸ“–
JoΓ£o Fernandes
JoΓ£o Fernandes

πŸ“–
Alejandro Perea
Alejandro Perea

πŸ‘€
Nick McCurdy
Nick McCurdy

πŸ‘€ πŸ’¬ πŸš‡
Sebastian Silbermann
Sebastian Silbermann

πŸ‘€
Christian Murphy
Christian Murphy

πŸš‡
Ivakhnenko Dmitry
Ivakhnenko Dmitry

πŸ’»
James George
James George

πŸ“–
JoΓ£o Fernandes
JoΓ£o Fernandes

πŸ“–
Alejandro Perea
Alejandro Perea

πŸ‘€
Nick McCurdy
Nick McCurdy

πŸ‘€ πŸ’¬ πŸš‡
Sebastian Silbermann
Sebastian Silbermann

πŸ‘€
AdriΓ  Fontcuberta
AdriΓ  Fontcuberta

πŸ‘€ πŸ“–
John Reilly
John Reilly

πŸ‘€
MichaΓ«l De Boey
MichaΓ«l De Boey

πŸ‘€ πŸ’»
Tim Yates
Tim Yates

πŸ‘€
Brian Donovan
Brian Donovan

πŸ’»
Noam Gabriel Jacobson
Noam Gabriel Jacobson

πŸ“–
Ronald van der Kooij
Ronald van der Kooij

⚠️ πŸ’»
AdriΓ  Fontcuberta
AdriΓ  Fontcuberta

πŸ‘€ πŸ“–
John Reilly
John Reilly

πŸ‘€
MichaΓ«l De Boey
MichaΓ«l De Boey

πŸ‘€ πŸ’»
Tim Yates
Tim Yates

πŸ‘€
Brian Donovan
Brian Donovan

πŸ’»
Noam Gabriel Jacobson
Noam Gabriel Jacobson

πŸ“–
Ronald van der Kooij
Ronald van der Kooij

⚠️ πŸ’»
Aayush Rajvanshi
Aayush Rajvanshi

πŸ“–
Ely Alamillo
Ely Alamillo

πŸ’» ⚠️
Daniel Afonso
Daniel Afonso

πŸ’» ⚠️
Laurens Bosscher
Laurens Bosscher

πŸ’»
Sakito Mukai
Sakito Mukai

πŸ“–
TΓΌrker Teke
TΓΌrker Teke

πŸ“–
Zach Brogan
Zach Brogan

πŸ’» ⚠️
Aayush Rajvanshi
Aayush Rajvanshi

πŸ“–
Ely Alamillo
Ely Alamillo

πŸ’» ⚠️
Daniel Afonso
Daniel Afonso

πŸ’» ⚠️
Laurens Bosscher
Laurens Bosscher

πŸ’»
Sakito Mukai
Sakito Mukai

πŸ“–
TΓΌrker Teke
TΓΌrker Teke

πŸ“–
Zach Brogan
Zach Brogan

πŸ’» ⚠️
Ryota Murakami
Ryota Murakami

πŸ“–
Michael Hottman
Michael Hottman

πŸ€”
Steven Fitzpatrick
Steven Fitzpatrick

πŸ›
Juan Je GarcΓ­a
Juan Je GarcΓ­a

πŸ“–
Championrunner
Championrunner

πŸ“–
Sam Tsai
Sam Tsai

πŸ’» ⚠️ πŸ“–
Christian Rackerseder
Christian Rackerseder

πŸ’»
Ryota Murakami
Ryota Murakami

πŸ“–
Michael Hottman
Michael Hottman

πŸ€”
Steven Fitzpatrick
Steven Fitzpatrick

πŸ›
Juan Je GarcΓ­a
Juan Je GarcΓ­a

πŸ“–
Championrunner
Championrunner

πŸ“–
Sam Tsai
Sam Tsai

πŸ’» ⚠️ πŸ“–
Christian Rackerseder
Christian Rackerseder

πŸ’»
Andrei Picus
Andrei Picus

πŸ› πŸ‘€
Artem Zakharchenko
Artem Zakharchenko

πŸ“–
Michael
Michael

πŸ“–
Braden Lee
Braden Lee

πŸ“–
Kamran Ayub
Kamran Ayub

πŸ’» ⚠️
Matan Borenkraout
Matan Borenkraout

πŸ’»
Ryan Bigg
Ryan Bigg

🚧
Andrei Picus
Andrei Picus

πŸ› πŸ‘€
Artem Zakharchenko
Artem Zakharchenko

πŸ“–
Michael
Michael

πŸ“–
Braden Lee
Braden Lee

πŸ“–
Kamran Ayub
Kamran Ayub

πŸ’» ⚠️
Matan Borenkraout
Matan Borenkraout

πŸ’»
Ryan Bigg
Ryan Bigg

🚧
Anton Halim
Anton Halim

πŸ“–
Artem Malko
Artem Malko

πŸ’»
Gerrit Alex
Gerrit Alex

πŸ’»
Karthick Raja
Karthick Raja

πŸ’»
Abdelrahman Ashraf
Abdelrahman Ashraf

πŸ’»
Lidor Avitan
Lidor Avitan

πŸ“–
Jordan Harband
Jordan Harband

πŸ‘€ πŸ€”
Anton Halim
Anton Halim

πŸ“–
Artem Malko
Artem Malko

πŸ’»
Gerrit Alex
Gerrit Alex

πŸ’»
Karthick Raja
Karthick Raja

πŸ’»
Abdelrahman Ashraf
Abdelrahman Ashraf

πŸ’»
Lidor Avitan
Lidor Avitan

πŸ“–
Jordan Harband
Jordan Harband

πŸ‘€ πŸ€”
Marco Moretti
Marco Moretti

πŸ’»
sanchit121
sanchit121

πŸ› πŸ’»
Solufa
Solufa

πŸ› πŸ’»
Ari PerkkiΓΆ
Ari PerkkiΓΆ

⚠️
Johannes Ewald
Johannes Ewald

πŸ’»
Angus J. Pope
Angus J. Pope

πŸ“–
Dominik Lesch
Dominik Lesch

πŸ“–
Marco Moretti
Marco Moretti

πŸ’»
sanchit121
sanchit121

πŸ› πŸ’»
Solufa
Solufa

πŸ› πŸ’»
Ari PerkkiΓΆ
Ari PerkkiΓΆ

⚠️
Johannes Ewald
Johannes Ewald

πŸ’»
Angus J. Pope
Angus J. Pope

πŸ“–
Dominik Lesch
Dominik Lesch

πŸ“–
Marcos GΓ³mez
Marcos GΓ³mez

πŸ“–
Akash Shyam
Akash Shyam

πŸ›
Fabian Meumertzheim
Fabian Meumertzheim

πŸ’» πŸ›
Sebastian Malton
Sebastian Malton

πŸ› πŸ’»
Martin BΓΆttcher
Martin BΓΆttcher

πŸ’»
Dominik Dorfmeister
Dominik Dorfmeister

πŸ’»
Stephen Sauceda
Stephen Sauceda

πŸ“–
Marcos GΓ³mez
Marcos GΓ³mez

πŸ“–
Akash Shyam
Akash Shyam

πŸ›
Fabian Meumertzheim
Fabian Meumertzheim

πŸ’» πŸ›
Sebastian Malton
Sebastian Malton

πŸ› πŸ’»
Martin BΓΆttcher
Martin BΓΆttcher

πŸ’»
Dominik Dorfmeister
Dominik Dorfmeister

πŸ’»
Stephen Sauceda
Stephen Sauceda

πŸ“–
Colin Diesh
Colin Diesh

πŸ“–
From d80319f5695d0ddbd93f7d63ca1cb71450663ba6 Mon Sep 17 00:00:00 2001 From: Matan Borenkraout Date: Wed, 8 Nov 2023 08:51:17 +0200 Subject: [PATCH 294/327] feat: add warnings when globals are missing (#1244) * feat: add warnings when globals are missing * revert the istanbul ignore removal * improve error message * Apply suggestions from code review Co-authored-by: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> --------- Co-authored-by: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> --- src/index.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/index.js b/src/index.js index bb0d0270..26028a9a 100644 --- a/src/index.js +++ b/src/index.js @@ -20,6 +20,10 @@ if (typeof process === 'undefined' || !process.env?.RTL_SKIP_AUTO_CLEANUP) { teardown(() => { cleanup() }) + } else { + console.warn( + `The current test runner does not support afterEach/teardown hooks. This means we won't be able to run automatic cleanup and you should be calling cleanup() manually.`, + ) } // No test setup with other test runners available @@ -35,6 +39,10 @@ if (typeof process === 'undefined' || !process.env?.RTL_SKIP_AUTO_CLEANUP) { afterAll(() => { setReactActEnvironment(previousIsReactActEnvironment) }) + } else { + console.warn( + 'The current test runner does not support beforeAll/afterAll hooks. This means you should be setting IS_REACT_ACT_ENVIRONMENT manually.', + ) } } From fd52a593a7987a14d3cf5c94f112795a1630725d Mon Sep 17 00:00:00 2001 From: Matan Borenkraout Date: Fri, 17 Nov 2023 16:46:53 +0200 Subject: [PATCH 295/327] fix: log globals warning only once (#1252) Resolves #1249 --- src/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index 26028a9a..42cfe59e 100644 --- a/src/index.js +++ b/src/index.js @@ -20,7 +20,8 @@ if (typeof process === 'undefined' || !process.env?.RTL_SKIP_AUTO_CLEANUP) { teardown(() => { cleanup() }) - } else { + } else if (!process.env.RTL_AFTEREACH_WARNING_LOGGED) { + process.env.RTL_AFTEREACH_WARNING_LOGGED = true console.warn( `The current test runner does not support afterEach/teardown hooks. This means we won't be able to run automatic cleanup and you should be calling cleanup() manually.`, ) @@ -39,7 +40,8 @@ if (typeof process === 'undefined' || !process.env?.RTL_SKIP_AUTO_CLEANUP) { afterAll(() => { setReactActEnvironment(previousIsReactActEnvironment) }) - } else { + } else if (!process.env.RTL_AFTERALL_WARNING_LOGGED) { + process.env.RTL_AFTERALL_WARNING_LOGGED = true console.warn( 'The current test runner does not support beforeAll/afterAll hooks. This means you should be setting IS_REACT_ACT_ENVIRONMENT manually.', ) From 1c67477443244e52c3ae57db49e1a6e8226e0c0d Mon Sep 17 00:00:00 2001 From: Matan Borenkraout Date: Fri, 17 Nov 2023 17:46:40 +0200 Subject: [PATCH 296/327] fix: revert missing hooks warnings (#1255) --- src/index.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/index.js b/src/index.js index 42cfe59e..bb0d0270 100644 --- a/src/index.js +++ b/src/index.js @@ -20,11 +20,6 @@ if (typeof process === 'undefined' || !process.env?.RTL_SKIP_AUTO_CLEANUP) { teardown(() => { cleanup() }) - } else if (!process.env.RTL_AFTEREACH_WARNING_LOGGED) { - process.env.RTL_AFTEREACH_WARNING_LOGGED = true - console.warn( - `The current test runner does not support afterEach/teardown hooks. This means we won't be able to run automatic cleanup and you should be calling cleanup() manually.`, - ) } // No test setup with other test runners available @@ -40,11 +35,6 @@ if (typeof process === 'undefined' || !process.env?.RTL_SKIP_AUTO_CLEANUP) { afterAll(() => { setReactActEnvironment(previousIsReactActEnvironment) }) - } else if (!process.env.RTL_AFTERALL_WARNING_LOGGED) { - process.env.RTL_AFTERALL_WARNING_LOGGED = true - console.warn( - 'The current test runner does not support beforeAll/afterAll hooks. This means you should be setting IS_REACT_ACT_ENVIRONMENT manually.', - ) } } From 03a301f2488b32c94d6f6f139191f6ff71221944 Mon Sep 17 00:00:00 2001 From: Matan Borenkraout Date: Fri, 8 Dec 2023 18:32:16 +0200 Subject: [PATCH 297/327] chore: update stackblitz url in issue template (#1258) --- .github/ISSUE_TEMPLATE/Bug_Report.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_Report.md b/.github/ISSUE_TEMPLATE/Bug_Report.md index daefe8c6..c04bef38 100644 --- a/.github/ISSUE_TEMPLATE/Bug_Report.md +++ b/.github/ISSUE_TEMPLATE/Bug_Report.md @@ -60,13 +60,8 @@ https://github.com/testing-library/testing-library-docs ### Reproduction: ### Problem description: From 0880eba4a01c030f942ad93600081bbb86eac959 Mon Sep 17 00:00:00 2001 From: Yusuke Iinuma Date: Wed, 31 Jan 2024 06:20:01 +0900 Subject: [PATCH 298/327] feat: add `reactStrictMode` option to enable strict mode render (#1241) * feat: add `reactStrictMode` option and override `getConfig` and `configure` functions from DTL * feat: update types for overridden `getConfig` and `configure` functions * test: add tests for checking configure APIs support RTL option and do not degrade * refactor: use a wrapper option for simplicity * refactor: use same function for wrapping UI if needed * feat: enable strict mode render if `reactStrictMode` option is true * test: add tests for checking strict mode works and can be combine with wrapper --------- Co-authored-by: Sebastian Silbermann --- src/__tests__/__snapshots__/render.js.snap | 2 +- src/__tests__/config.js | 66 ++++ src/__tests__/render.js | 332 ++++++++++++--------- src/__tests__/rerender.js | 113 +++++-- src/config.js | 34 +++ src/pure.js | 35 ++- types/index.d.ts | 13 + types/test.tsx | 22 ++ 8 files changed, 443 insertions(+), 174 deletions(-) create mode 100644 src/__tests__/config.js create mode 100644 src/config.js diff --git a/src/__tests__/__snapshots__/render.js.snap b/src/__tests__/__snapshots__/render.js.snap index eaf41443..345cd937 100644 --- a/src/__tests__/__snapshots__/render.js.snap +++ b/src/__tests__/__snapshots__/render.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`supports fragments 1`] = ` +exports[`render API supports fragments 1`] = `
diff --git a/src/__tests__/config.js b/src/__tests__/config.js new file mode 100644 index 00000000..7fdb1e00 --- /dev/null +++ b/src/__tests__/config.js @@ -0,0 +1,66 @@ +import {configure, getConfig} from '../' + +describe('configuration API', () => { + let originalConfig + beforeEach(() => { + // Grab the existing configuration so we can restore + // it at the end of the test + configure(existingConfig => { + originalConfig = existingConfig + // Don't change the existing config + return {} + }) + }) + + afterEach(() => { + configure(originalConfig) + }) + + describe('DTL options', () => { + test('configure can set by a plain JS object', () => { + const testIdAttribute = 'not-data-testid' + configure({testIdAttribute}) + + expect(getConfig().testIdAttribute).toBe(testIdAttribute) + }) + + test('configure can set by a function', () => { + // setup base option + const baseTestIdAttribute = 'data-testid' + configure({testIdAttribute: baseTestIdAttribute}) + + const modifiedPrefix = 'modified-' + configure(existingConfig => ({ + testIdAttribute: `${modifiedPrefix}${existingConfig.testIdAttribute}`, + })) + + expect(getConfig().testIdAttribute).toBe( + `${modifiedPrefix}${baseTestIdAttribute}`, + ) + }) + }) + + describe('RTL options', () => { + test('configure can set by a plain JS object', () => { + configure({reactStrictMode: true}) + + expect(getConfig().reactStrictMode).toBe(true) + }) + + test('configure can set by a function', () => { + configure(existingConfig => ({ + reactStrictMode: !existingConfig.reactStrictMode, + })) + + expect(getConfig().reactStrictMode).toBe(true) + }) + }) + + test('configure can set DTL and RTL options at once', () => { + const testIdAttribute = 'not-data-testid' + configure({testIdAttribute, reactStrictMode: true}) + + expect(getConfig().testIdAttribute).toBe(testIdAttribute) + expect(getConfig().reactStrictMode).toBe(true) + }) +}) diff --git a/src/__tests__/render.js b/src/__tests__/render.js index 46925f49..39f4bc92 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -1,84 +1,100 @@ import * as React from 'react' import ReactDOM from 'react-dom' import ReactDOMServer from 'react-dom/server' -import {fireEvent, render, screen} from '../' +import {fireEvent, render, screen, configure} from '../' + +describe('render API', () => { + let originalConfig + beforeEach(() => { + // Grab the existing configuration so we can restore + // it at the end of the test + configure(existingConfig => { + originalConfig = existingConfig + // Don't change the existing config + return {} + }) + }) -test('renders div into document', () => { - const ref = React.createRef() - const {container} = render(
) - expect(container.firstChild).toBe(ref.current) -}) + afterEach(() => { + configure(originalConfig) + }) -test('works great with react portals', () => { - class MyPortal extends React.Component { - constructor(...args) { - super(...args) - this.portalNode = document.createElement('div') - this.portalNode.dataset.testid = 'my-portal' - } - componentDidMount() { - document.body.appendChild(this.portalNode) - } - componentWillUnmount() { - this.portalNode.parentNode.removeChild(this.portalNode) - } - render() { - return ReactDOM.createPortal( - , - this.portalNode, - ) - } - } - - function Greet({greeting, subject}) { - return ( -
- - {greeting} {subject} - -
- ) - } - - const {unmount} = render() - expect(screen.getByText('Hello World')).toBeInTheDocument() - const portalNode = screen.getByTestId('my-portal') - expect(portalNode).toBeInTheDocument() - unmount() - expect(portalNode).not.toBeInTheDocument() -}) + test('renders div into document', () => { + const ref = React.createRef() + const {container} = render(
) + expect(container.firstChild).toBe(ref.current) + }) -test('returns baseElement which defaults to document.body', () => { - const {baseElement} = render(
) - expect(baseElement).toBe(document.body) -}) + test('works great with react portals', () => { + class MyPortal extends React.Component { + constructor(...args) { + super(...args) + this.portalNode = document.createElement('div') + this.portalNode.dataset.testid = 'my-portal' + } + componentDidMount() { + document.body.appendChild(this.portalNode) + } + componentWillUnmount() { + this.portalNode.parentNode.removeChild(this.portalNode) + } + render() { + return ReactDOM.createPortal( + , + this.portalNode, + ) + } + } -test('supports fragments', () => { - class Test extends React.Component { - render() { + function Greet({greeting, subject}) { return (
- DocumentFragment is pretty cool! + + {greeting} {subject} +
) } - } - const {asFragment} = render() - expect(asFragment()).toMatchSnapshot() -}) + const {unmount} = render() + expect(screen.getByText('Hello World')).toBeInTheDocument() + const portalNode = screen.getByTestId('my-portal') + expect(portalNode).toBeInTheDocument() + unmount() + expect(portalNode).not.toBeInTheDocument() + }) -test('renders options.wrapper around node', () => { - const WrapperComponent = ({children}) => ( -
{children}
- ) + test('returns baseElement which defaults to document.body', () => { + const {baseElement} = render(
) + expect(baseElement).toBe(document.body) + }) + + test('supports fragments', () => { + class Test extends React.Component { + render() { + return ( +
+ DocumentFragment is pretty cool! +
+ ) + } + } - const {container} = render(
, { - wrapper: WrapperComponent, + const {asFragment} = render() + expect(asFragment()).toMatchSnapshot() }) - expect(screen.getByTestId('wrapper')).toBeInTheDocument() - expect(container.firstChild).toMatchInlineSnapshot(` + test('renders options.wrapper around node', () => { + const WrapperComponent = ({children}) => ( +
{children}
+ ) + + const {container} = render(
, { + wrapper: WrapperComponent, + }) + + expect(screen.getByTestId('wrapper')).toBeInTheDocument() + expect(container.firstChild).toMatchInlineSnapshot(`
@@ -87,102 +103,138 @@ test('renders options.wrapper around node', () => { />
`) -}) + }) -test('flushes useEffect cleanup functions sync on unmount()', () => { - const spy = jest.fn() - function Component() { - React.useEffect(() => spy, []) - return null - } - const {unmount} = render() - expect(spy).toHaveBeenCalledTimes(0) + test('renders options.wrapper around node when reactStrictMode is true', () => { + configure({reactStrictMode: true}) - unmount() + const WrapperComponent = ({children}) => ( +
{children}
+ ) + const {container} = render(
, { + wrapper: WrapperComponent, + }) - expect(spy).toHaveBeenCalledTimes(1) -}) + expect(screen.getByTestId('wrapper')).toBeInTheDocument() + expect(container.firstChild).toMatchInlineSnapshot(` +
+
+
+ `) + }) + + test('renders twice when reactStrictMode is true', () => { + configure({reactStrictMode: true}) -test('can be called multiple times on the same container', () => { - const container = document.createElement('div') + const spy = jest.fn() + function Component() { + spy() + return null + } - const {unmount} = render(, {container}) + render() + expect(spy).toHaveBeenCalledTimes(2) + }) - expect(container).toContainHTML('') + test('flushes useEffect cleanup functions sync on unmount()', () => { + const spy = jest.fn() + function Component() { + React.useEffect(() => spy, []) + return null + } + const {unmount} = render() + expect(spy).toHaveBeenCalledTimes(0) - render(, {container}) + unmount() - expect(container).toContainHTML('') + expect(spy).toHaveBeenCalledTimes(1) + }) - unmount() + test('can be called multiple times on the same container', () => { + const container = document.createElement('div') - expect(container).toBeEmptyDOMElement() -}) + const {unmount} = render(, {container}) -test('hydrate will make the UI interactive', () => { - function App() { - const [clicked, handleClick] = React.useReducer(n => n + 1, 0) + expect(container).toContainHTML('') - return ( - - ) - } - const ui = - const container = document.createElement('div') - document.body.appendChild(container) - container.innerHTML = ReactDOMServer.renderToString(ui) + render(, {container}) - expect(container).toHaveTextContent('clicked:0') + expect(container).toContainHTML('') - render(ui, {container, hydrate: true}) + unmount() - fireEvent.click(container.querySelector('button')) + expect(container).toBeEmptyDOMElement() + }) - expect(container).toHaveTextContent('clicked:1') -}) + test('hydrate will make the UI interactive', () => { + function App() { + const [clicked, handleClick] = React.useReducer(n => n + 1, 0) -test('hydrate can have a wrapper', () => { - const wrapperComponentMountEffect = jest.fn() - function WrapperComponent({children}) { - React.useEffect(() => { - wrapperComponentMountEffect() - }) + return ( + + ) + } + const ui = + const container = document.createElement('div') + document.body.appendChild(container) + container.innerHTML = ReactDOMServer.renderToString(ui) - return children - } - const ui =
- const container = document.createElement('div') - document.body.appendChild(container) - container.innerHTML = ReactDOMServer.renderToString(ui) + expect(container).toHaveTextContent('clicked:0') - render(ui, {container, hydrate: true, wrapper: WrapperComponent}) + render(ui, {container, hydrate: true}) - expect(wrapperComponentMountEffect).toHaveBeenCalledTimes(1) -}) + fireEvent.click(container.querySelector('button')) -test('legacyRoot uses legacy ReactDOM.render', () => { - expect(() => { - render(
, {legacyRoot: true}) - }).toErrorDev( - [ - "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", - ], - {withoutStack: true}, - ) -}) + expect(container).toHaveTextContent('clicked:1') + }) + + test('hydrate can have a wrapper', () => { + const wrapperComponentMountEffect = jest.fn() + function WrapperComponent({children}) { + React.useEffect(() => { + wrapperComponentMountEffect() + }) + + return children + } + const ui =
+ const container = document.createElement('div') + document.body.appendChild(container) + container.innerHTML = ReactDOMServer.renderToString(ui) -test('legacyRoot uses legacy ReactDOM.hydrate', () => { - const ui =
- const container = document.createElement('div') - container.innerHTML = ReactDOMServer.renderToString(ui) - expect(() => { - render(ui, {container, hydrate: true, legacyRoot: true}) - }).toErrorDev( - [ - "Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", - ], - {withoutStack: true}, - ) + render(ui, {container, hydrate: true, wrapper: WrapperComponent}) + + expect(wrapperComponentMountEffect).toHaveBeenCalledTimes(1) + }) + + test('legacyRoot uses legacy ReactDOM.render', () => { + expect(() => { + render(
, {legacyRoot: true}) + }).toErrorDev( + [ + "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ], + {withoutStack: true}, + ) + }) + + test('legacyRoot uses legacy ReactDOM.hydrate', () => { + const ui =
+ const container = document.createElement('div') + container.innerHTML = ReactDOMServer.renderToString(ui) + expect(() => { + render(ui, {container, hydrate: true, legacyRoot: true}) + }).toErrorDev( + [ + "Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ], + {withoutStack: true}, + ) + }) }) diff --git a/src/__tests__/rerender.js b/src/__tests__/rerender.js index be3c259c..6c48c4dd 100644 --- a/src/__tests__/rerender.js +++ b/src/__tests__/rerender.js @@ -1,31 +1,98 @@ import * as React from 'react' -import {render} from '../' - -test('rerender will re-render the element', () => { - const Greeting = props =>
{props.message}
- const {container, rerender} = render() - expect(container.firstChild).toHaveTextContent('hi') - rerender() - expect(container.firstChild).toHaveTextContent('hey') -}) +import {render, configure} from '../' + +describe('rerender API', () => { + let originalConfig + beforeEach(() => { + // Grab the existing configuration so we can restore + // it at the end of the test + configure(existingConfig => { + originalConfig = existingConfig + // Don't change the existing config + return {} + }) + }) + + afterEach(() => { + configure(originalConfig) + }) + + test('rerender will re-render the element', () => { + const Greeting = props =>
{props.message}
+ const {container, rerender} = render() + expect(container.firstChild).toHaveTextContent('hi') + rerender() + expect(container.firstChild).toHaveTextContent('hey') + }) + + test('hydrate will not update props until next render', () => { + const initialInputElement = document.createElement('input') + const container = document.createElement('div') + container.appendChild(initialInputElement) + document.body.appendChild(container) + + const firstValue = 'hello' + initialInputElement.value = firstValue -test('hydrate will not update props until next render', () => { - const initialInputElement = document.createElement('input') - const container = document.createElement('div') - container.appendChild(initialInputElement) - document.body.appendChild(container) + const {rerender} = render( null} />, { + container, + hydrate: true, + }) - const firstValue = 'hello' - initialInputElement.value = firstValue + expect(initialInputElement).toHaveValue(firstValue) - const {rerender} = render( null} />, { - container, - hydrate: true, + const secondValue = 'goodbye' + rerender( null} />) + expect(initialInputElement).toHaveValue(secondValue) }) - expect(initialInputElement).toHaveValue(firstValue) + test('re-renders options.wrapper around node when reactStrictMode is true', () => { + configure({reactStrictMode: true}) - const secondValue = 'goodbye' - rerender( null} />) - expect(initialInputElement).toHaveValue(secondValue) + const WrapperComponent = ({children}) => ( +
{children}
+ ) + const Greeting = props =>
{props.message}
+ const {container, rerender} = render(, { + wrapper: WrapperComponent, + }) + + expect(container.firstChild).toMatchInlineSnapshot(` +
+
+ hi +
+
+ `) + + rerender() + expect(container.firstChild).toMatchInlineSnapshot(` +
+
+ hey +
+
+ `) + }) + + test('re-renders twice when reactStrictMode is true', () => { + configure({reactStrictMode: true}) + + const spy = jest.fn() + function Component() { + spy() + return null + } + + const {rerender} = render() + expect(spy).toHaveBeenCalledTimes(2) + + spy.mockClear() + rerender() + expect(spy).toHaveBeenCalledTimes(2) + }) }) diff --git a/src/config.js b/src/config.js new file mode 100644 index 00000000..dc8a5035 --- /dev/null +++ b/src/config.js @@ -0,0 +1,34 @@ +import { + getConfig as getConfigDTL, + configure as configureDTL, +} from '@testing-library/dom' + +let configForRTL = { + reactStrictMode: false, +} + +function getConfig() { + return { + ...getConfigDTL(), + ...configForRTL, + } +} + +function configure(newConfig) { + if (typeof newConfig === 'function') { + // Pass the existing config out to the provided function + // and accept a delta in return + newConfig = newConfig(getConfig()) + } + + const {reactStrictMode, ...configForDTL} = newConfig + + configureDTL(configForDTL) + + configForRTL = { + ...configForRTL, + reactStrictMode, + } +} + +export {getConfig, configure} diff --git a/src/pure.js b/src/pure.js index 845aede1..3939a11a 100644 --- a/src/pure.js +++ b/src/pure.js @@ -11,6 +11,7 @@ import act, { setReactActEnvironment, } from './act-compat' import {fireEvent} from './fire-event' +import {getConfig, configure} from './config' function jestFakeTimersAreEnabled() { /* istanbul ignore else */ @@ -76,6 +77,18 @@ const mountedContainers = new Set() */ const mountedRootEntries = [] +function strictModeIfNeeded(innerElement) { + return getConfig().reactStrictMode + ? React.createElement(React.StrictMode, null, innerElement) + : innerElement +} + +function wrapUiIfNeeded(innerElement, wrapperComponent) { + return wrapperComponent + ? React.createElement(wrapperComponent, null, innerElement) + : innerElement +} + function createConcurrentRoot( container, {hydrate, ui, wrapper: WrapperComponent}, @@ -85,7 +98,7 @@ function createConcurrentRoot( act(() => { root = ReactDOMClient.hydrateRoot( container, - WrapperComponent ? React.createElement(WrapperComponent, null, ui) : ui, + strictModeIfNeeded(wrapUiIfNeeded(ui, WrapperComponent)), ) }) } else { @@ -129,16 +142,17 @@ function renderRoot( ui, {baseElement, container, hydrate, queries, root, wrapper: WrapperComponent}, ) { - const wrapUiIfNeeded = innerElement => - WrapperComponent - ? React.createElement(WrapperComponent, null, innerElement) - : innerElement - act(() => { if (hydrate) { - root.hydrate(wrapUiIfNeeded(ui), container) + root.hydrate( + strictModeIfNeeded(wrapUiIfNeeded(ui, WrapperComponent)), + container, + ) } else { - root.render(wrapUiIfNeeded(ui), container) + root.render( + strictModeIfNeeded(wrapUiIfNeeded(ui, WrapperComponent)), + container, + ) } }) @@ -157,10 +171,11 @@ function renderRoot( }) }, rerender: rerenderUi => { - renderRoot(wrapUiIfNeeded(rerenderUi), { + renderRoot(rerenderUi, { container, baseElement, root, + wrapper: WrapperComponent, }) // Intentionally do not return anything to avoid unnecessarily complicating the API. // folks can use all the same utilities we return in the first place that are bound to the container @@ -276,6 +291,6 @@ function renderHook(renderCallback, options = {}) { // just re-export everything from dom-testing-library export * from '@testing-library/dom' -export {render, renderHook, cleanup, act, fireEvent} +export {render, renderHook, cleanup, act, fireEvent, getConfig, configure} /* eslint func-name-matching:0 */ diff --git a/types/index.d.ts b/types/index.d.ts index 558edfad..1f1135c5 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -5,12 +5,25 @@ import { Queries, BoundFunction, prettyFormat, + Config as ConfigDTL, } from '@testing-library/dom' import {Renderer} from 'react-dom' import {act as reactAct} from 'react-dom/test-utils' export * from '@testing-library/dom' +export interface Config extends ConfigDTL { + reactStrictMode: boolean +} + +export interface ConfigFn { + (existingConfig: Config): Partial +} + +export function configure(configDelta: ConfigFn | Partial): void + +export function getConfig(): Config + export type RenderResult< Q extends Queries = typeof queries, Container extends Element | DocumentFragment = HTMLElement, diff --git a/types/test.tsx b/types/test.tsx index c33f07b6..3486a9a8 100644 --- a/types/test.tsx +++ b/types/test.tsx @@ -62,6 +62,28 @@ export function testFireEvent() { fireEvent.click(container) } +export function testConfigure() { + // test for DTL's config + pure.configure({testIdAttribute: 'foobar'}) + pure.configure(existingConfig => ({ + testIdAttribute: `modified-${existingConfig.testIdAttribute}`, + })) + + // test for RTL's config + pure.configure({reactStrictMode: true}) + pure.configure(existingConfig => ({ + reactStrictMode: !existingConfig.reactStrictMode, + })) +} + +export function testGetConfig() { + // test for DTL's config + pure.getConfig().testIdAttribute + + // test for RTL's config + pure.getConfig().reactStrictMode +} + export function testDebug() { const {debug, getAllByTestId} = render( <> From 4509fb68aaf42f3b750e57a3e2d073a498fc59db Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 22:21:05 +0100 Subject: [PATCH 299/327] docs: add yinm as a contributor for code (#1269) * docs: update README.md * docs: update .all-contributorsrc --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 16957ca9..de2ba851 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1353,6 +1353,15 @@ "contributions": [ "doc" ] + }, + { + "login": "yinm", + "name": "Yusuke Iinuma", + "avatar_url": "https://avatars.githubusercontent.com/u/13295106?v=4", + "profile": "http://yinm.info", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index a3731749..1ffc881d 100644 --- a/README.md +++ b/README.md @@ -630,6 +630,7 @@ Thanks goes to these people ([emoji key][emojis]): Colin Diesh
Colin Diesh

πŸ“– + Yusuke Iinuma
Yusuke Iinuma

πŸ’» From 55e79c290d3ec8a8eb3d39539e2c05bf35dff3d9 Mon Sep 17 00:00:00 2001 From: Jeff Way Date: Thu, 1 Feb 2024 11:49:10 -0800 Subject: [PATCH 300/327] fix: Update types to support all possible react component return values (#1272) * Update types to support all possible react component return values * Update type test types --- types/index.d.ts | 8 ++++---- types/test.tsx | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index 1f1135c5..5db1d201 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -39,7 +39,7 @@ export type RenderResult< maxLength?: number, options?: prettyFormat.OptionsReceived, ) => void - rerender: (ui: React.ReactElement) => void + rerender: (ui: React.ReactNode) => void unmount: () => void asFragment: () => DocumentFragment } & {[P in keyof Q]: BoundFunction} @@ -90,7 +90,7 @@ export interface RenderOptions< * * @see https://testing-library.com/docs/react-testing-library/api/#wrapper */ - wrapper?: React.JSXElementConstructor<{children: React.ReactElement}> + wrapper?: React.JSXElementConstructor<{children: React.ReactNode}> } type Omit = Pick> @@ -103,11 +103,11 @@ export function render< Container extends Element | DocumentFragment = HTMLElement, BaseElement extends Element | DocumentFragment = Container, >( - ui: React.ReactElement, + ui: React.ReactNode, options: RenderOptions, ): RenderResult export function render( - ui: React.ReactElement, + ui: React.ReactNode, options?: Omit, ): RenderResult diff --git a/types/test.tsx b/types/test.tsx index 3486a9a8..6ff899de 100644 --- a/types/test.tsx +++ b/types/test.tsx @@ -123,10 +123,10 @@ export function testQueries() { } export function wrappedRender( - ui: React.ReactElement, + ui: React.ReactNode, options?: pure.RenderOptions, ) { - const Wrapper = ({children}: {children: React.ReactElement}): JSX.Element => { + const Wrapper = ({children}: {children: React.ReactNode}): JSX.Element => { return
{children}
} @@ -134,7 +134,7 @@ export function wrappedRender( } export function wrappedRenderB( - ui: React.ReactElement, + ui: React.ReactNode, options?: pure.RenderOptions, ) { const Wrapper: React.FunctionComponent<{children?: React.ReactNode}> = ({ @@ -147,7 +147,7 @@ export function wrappedRenderB( } export function wrappedRenderC( - ui: React.ReactElement, + ui: React.ReactNode, options?: pure.RenderOptions, ) { interface AppWrapperProps { From edb6344d578a8c224daf0cd6e2984f36cc6e8d86 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 20:49:43 +0100 Subject: [PATCH 301/327] docs: add trappar as a contributor for code (#1273) * docs: update README.md * docs: update .all-contributorsrc --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index de2ba851..c3b86064 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1362,6 +1362,15 @@ "contributions": [ "code" ] + }, + { + "login": "trappar", + "name": "Jeff Way", + "avatar_url": "https://avatars.githubusercontent.com/u/525726?v=4", + "profile": "https://github.com/trappar", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 1ffc881d..85613475 100644 --- a/README.md +++ b/README.md @@ -631,6 +631,7 @@ Thanks goes to these people ([emoji key][emojis]): Colin Diesh
Colin Diesh

πŸ“– Yusuke Iinuma
Yusuke Iinuma

πŸ’» + Jeff Way
Jeff Way

πŸ’» From 7e42f4e84115510f560be36b5febb3d9f20e8899 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 19 Mar 2024 23:24:53 +0100 Subject: [PATCH 302/327] chore: Fix tests (#1288) --- jest.config.js | 16 ++++++++++++++++ package.json | 2 +- src/__tests__/render.js | 31 +++++++++++++++++++++++-------- src/__tests__/renderHook.js | 19 +++++++++++++++---- tests/toWarnDev.js | 2 +- 5 files changed, 56 insertions(+), 14 deletions(-) create mode 100644 jest.config.js diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..30654cdb --- /dev/null +++ b/jest.config.js @@ -0,0 +1,16 @@ +const {jest: jestConfig} = require('kcd-scripts/config') + +module.exports = Object.assign(jestConfig, { + coverageThreshold: { + ...jestConfig.coverageThreshold, + // Full coverage across the build matrix (React versions) but not in a single job + // Ful coverage is checked via codecov + './src/pure.js': { + // minimum coverage of jobs using different React versions + branches: 97, + functions: 88, + lines: 94, + statements: 94, + }, + }, +}) diff --git a/package.json b/package.json index 70aebdad..0b7f83d8 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@testing-library/jest-dom": "^5.11.6", "chalk": "^4.1.2", "dotenv-cli": "^4.0.0", - "jest-diff": "^29.4.1", + "jest-diff": "^29.7.0", "kcd-scripts": "^13.0.0", "npm-run-all": "^4.1.5", "react": "^18.0.0", diff --git a/src/__tests__/render.js b/src/__tests__/render.js index 39f4bc92..b5222d81 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -3,6 +3,13 @@ import ReactDOM from 'react-dom' import ReactDOMServer from 'react-dom/server' import {fireEvent, render, screen, configure} from '../' +// Needs to be changed to 19.0.0 once alpha started. +const isReactExperimental = React.version.startsWith('18.3.0-experimental') +const isReactCanary = React.version.startsWith('18.3.0') + +// Needs to be changed to isReactExperimental || isReactCanary once alpha started. +const testGateReact18 = isReactExperimental ? test.skip : test + describe('render API', () => { let originalConfig beforeEach(() => { @@ -213,27 +220,35 @@ describe('render API', () => { expect(wrapperComponentMountEffect).toHaveBeenCalledTimes(1) }) - test('legacyRoot uses legacy ReactDOM.render', () => { + testGateReact18('legacyRoot uses legacy ReactDOM.render', () => { expect(() => { render(
, {legacyRoot: true}) }).toErrorDev( - [ - "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", - ], + isReactCanary + ? [ + "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://react.dev/link/switch-to-createroot", + ] + : [ + "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ], {withoutStack: true}, ) }) - test('legacyRoot uses legacy ReactDOM.hydrate', () => { + testGateReact18('legacyRoot uses legacy ReactDOM.hydrate', () => { const ui =
const container = document.createElement('div') container.innerHTML = ReactDOMServer.renderToString(ui) expect(() => { render(ui, {container, hydrate: true, legacyRoot: true}) }).toErrorDev( - [ - "Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", - ], + isReactCanary + ? [ + "Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://react.dev/link/switch-to-createroot", + ] + : [ + "Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ], {withoutStack: true}, ) }) diff --git a/src/__tests__/renderHook.js b/src/__tests__/renderHook.js index 11b7009a..34259b44 100644 --- a/src/__tests__/renderHook.js +++ b/src/__tests__/renderHook.js @@ -1,6 +1,13 @@ import React from 'react' import {renderHook} from '../pure' +// Needs to be changed to 19.0.0 once alpha started. +const isReactExperimental = React.version.startsWith('18.3.0-experimental') +const isReactCanary = React.version.startsWith('18.3.0') + +// Needs to be changed to isReactExperimental || isReactCanary once alpha started. +const testGateReact18 = isReactExperimental ? test.skip : test + test('gives committed result', () => { const {result} = renderHook(() => { const [state, setState] = React.useState(1) @@ -61,7 +68,7 @@ test('allows wrapper components', async () => { expect(result.current).toEqual('provided') }) -test('legacyRoot uses legacy ReactDOM.render', () => { +testGateReact18('legacyRoot uses legacy ReactDOM.render', () => { const Context = React.createContext('default') function Wrapper({children}) { return {children} @@ -78,9 +85,13 @@ test('legacyRoot uses legacy ReactDOM.render', () => { }, ).result }).toErrorDev( - [ - "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", - ], + isReactCanary + ? [ + "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://react.dev/link/switch-to-createroot", + ] + : [ + "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ], {withoutStack: true}, ) expect(result.current).toEqual('provided') diff --git a/tests/toWarnDev.js b/tests/toWarnDev.js index ca58346f..2aae39f0 100644 --- a/tests/toWarnDev.js +++ b/tests/toWarnDev.js @@ -29,7 +29,7 @@ SOFTWARE. /* eslint-disable func-names */ /* eslint-disable complexity */ const util = require('util') -const jestDiff = require('jest-diff').default +const jestDiff = require('jest-diff').diff const shouldIgnoreConsoleError = require('./shouldIgnoreConsoleError') function normalizeCodeLocInfo(str) { From 3da62fd9741ca74bcd0d2bc668ba76a2d8f3751f Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 19 Mar 2024 23:54:12 +0100 Subject: [PATCH 303/327] fix: Remove unused types (#1287) --- types/index.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/types/index.d.ts b/types/index.d.ts index 5db1d201..49a1b7ff 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -7,7 +7,6 @@ import { prettyFormat, Config as ConfigDTL, } from '@testing-library/dom' -import {Renderer} from 'react-dom' import {act as reactAct} from 'react-dom/test-utils' export * from '@testing-library/dom' From cf045b4743afeb651b14bd7bb0d04b955768c010 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 20 Mar 2024 00:08:40 +0100 Subject: [PATCH 304/327] chore: Update Codecov configuration to latest (#1289) --- .github/workflows/validate.yml | 12 +++++++----- codecov.yml | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 codecov.yml diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index f1359d76..c2e20a61 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -34,10 +34,10 @@ jobs: runs-on: ubuntu-latest steps: - name: ⬇️ Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: βŽ” Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} @@ -59,9 +59,11 @@ jobs: run: npm run validate - name: ⬆️ Upload coverage report - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v4 with: + fail_ci_if_error: true flags: ${{ matrix.react }} + token: ${{ secrets.CODECOV_TOKEN }} release: permissions: @@ -76,10 +78,10 @@ jobs: github.event_name == 'push' }} steps: - name: ⬇️ Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: βŽ” Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version: 14 diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..472fcd83 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,20 @@ +coverage: + status: + project: + default: + # basic + target: 100% + threshold: 0% + flags: + - canary + - experimental + - latest + branches: + - main + - 12.x + if_ci_failed: success + if_not_found: failure + informational: false + only_pulls: false +github_checks: + annotations: true From 4e10ba3a788f6f66287dab5bb4a09f658664ec50 Mon Sep 17 00:00:00 2001 From: Matan Borenkraout Date: Thu, 21 Mar 2024 11:24:52 +0200 Subject: [PATCH 305/327] chore: change canary version to specific prefix (#1290) --- src/__tests__/render.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/render.js b/src/__tests__/render.js index b5222d81..175174ca 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -5,7 +5,7 @@ import {fireEvent, render, screen, configure} from '../' // Needs to be changed to 19.0.0 once alpha started. const isReactExperimental = React.version.startsWith('18.3.0-experimental') -const isReactCanary = React.version.startsWith('18.3.0') +const isReactCanary = React.version.startsWith('18.3.0-canary') // Needs to be changed to isReactExperimental || isReactCanary once alpha started. const testGateReact18 = isReactExperimental ? test.skip : test From 9c4a46d5b9923c21c936d206614a8febcc939fc2 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 8 Apr 2024 16:07:24 +0200 Subject: [PATCH 306/327] feat: Add support for React 19 Canary (#1294) --- .github/workflows/validate.yml | 2 +- jest.config.js | 15 ++++++----- src/__tests__/new-act.js | 13 +++++---- src/__tests__/render.js | 48 ++++++++++++++++++++-------------- src/__tests__/renderHook.js | 39 ++++++++++++++++++--------- src/act-compat.js | 7 ++--- src/pure.js | 17 ++++++++++++ types/index.d.ts | 1 + 8 files changed, 96 insertions(+), 46 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index c2e20a61..4a20e2ab 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -30,7 +30,7 @@ jobs: fail-fast: false matrix: node: [14, 16, 18] - react: [latest, canary, experimental] + react: ['18.x', latest, canary, experimental] runs-on: ubuntu-latest steps: - name: ⬇️ Checkout repo diff --git a/jest.config.js b/jest.config.js index 30654cdb..860358cd 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,14 +3,17 @@ const {jest: jestConfig} = require('kcd-scripts/config') module.exports = Object.assign(jestConfig, { coverageThreshold: { ...jestConfig.coverageThreshold, - // Full coverage across the build matrix (React versions) but not in a single job + // Full coverage across the build matrix (React 18, 19) but not in a single job // Ful coverage is checked via codecov - './src/pure.js': { - // minimum coverage of jobs using different React versions - branches: 97, + './src/act-compat': { + branches: 90, + }, + './src/pure': { + // minimum coverage of jobs using React 18 and 19 + branches: 95, functions: 88, - lines: 94, - statements: 94, + lines: 92, + statements: 92, }, }, }) diff --git a/src/__tests__/new-act.js b/src/__tests__/new-act.js index 0412a8a3..0464ad24 100644 --- a/src/__tests__/new-act.js +++ b/src/__tests__/new-act.js @@ -1,10 +1,13 @@ let asyncAct -jest.mock('react-dom/test-utils', () => ({ - act: cb => { - return cb() - }, -})) +jest.mock('react', () => { + return { + ...jest.requireActual('react'), + act: cb => { + return cb() + }, + } +}) beforeEach(() => { jest.resetModules() diff --git a/src/__tests__/render.js b/src/__tests__/render.js index 175174ca..16f7dbe2 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -3,12 +3,11 @@ import ReactDOM from 'react-dom' import ReactDOMServer from 'react-dom/server' import {fireEvent, render, screen, configure} from '../' -// Needs to be changed to 19.0.0 once alpha started. -const isReactExperimental = React.version.startsWith('18.3.0-experimental') -const isReactCanary = React.version.startsWith('18.3.0-canary') +const isReact18 = React.version.startsWith('18.') +const isReact19 = React.version.startsWith('19.') -// Needs to be changed to isReactExperimental || isReactCanary once alpha started. -const testGateReact18 = isReactExperimental ? test.skip : test +const testGateReact18 = isReact18 ? test : test.skip +const testGateReact19 = isReact19 ? test : test.skip describe('render API', () => { let originalConfig @@ -224,17 +223,21 @@ describe('render API', () => { expect(() => { render(
, {legacyRoot: true}) }).toErrorDev( - isReactCanary - ? [ - "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://react.dev/link/switch-to-createroot", - ] - : [ - "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", - ], + [ + "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ], {withoutStack: true}, ) }) + testGateReact19('legacyRoot throws', () => { + expect(() => { + render(
, {legacyRoot: true}) + }).toThrowErrorMatchingInlineSnapshot( + `\`legacyRoot: true\` is not supported in this version of React. Please use React 18 instead.`, + ) + }) + testGateReact18('legacyRoot uses legacy ReactDOM.hydrate', () => { const ui =
const container = document.createElement('div') @@ -242,14 +245,21 @@ describe('render API', () => { expect(() => { render(ui, {container, hydrate: true, legacyRoot: true}) }).toErrorDev( - isReactCanary - ? [ - "Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://react.dev/link/switch-to-createroot", - ] - : [ - "Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", - ], + [ + "Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ], {withoutStack: true}, ) }) + + testGateReact19('legacyRoot throws even with hydrate', () => { + const ui =
+ const container = document.createElement('div') + container.innerHTML = ReactDOMServer.renderToString(ui) + expect(() => { + render(ui, {container, hydrate: true, legacyRoot: true}) + }).toThrowErrorMatchingInlineSnapshot( + `\`legacyRoot: true\` is not supported in this version of React. Please use React 18 instead.`, + ) + }) }) diff --git a/src/__tests__/renderHook.js b/src/__tests__/renderHook.js index 34259b44..c7c8b066 100644 --- a/src/__tests__/renderHook.js +++ b/src/__tests__/renderHook.js @@ -1,12 +1,11 @@ import React from 'react' import {renderHook} from '../pure' -// Needs to be changed to 19.0.0 once alpha started. -const isReactExperimental = React.version.startsWith('18.3.0-experimental') -const isReactCanary = React.version.startsWith('18.3.0') +const isReact18 = React.version.startsWith('18.') +const isReact19 = React.version.startsWith('19.') -// Needs to be changed to isReactExperimental || isReactCanary once alpha started. -const testGateReact18 = isReactExperimental ? test.skip : test +const testGateReact18 = isReact18 ? test : test.skip +const testGateReact19 = isReact19 ? test : test.skip test('gives committed result', () => { const {result} = renderHook(() => { @@ -85,14 +84,30 @@ testGateReact18('legacyRoot uses legacy ReactDOM.render', () => { }, ).result }).toErrorDev( - isReactCanary - ? [ - "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://react.dev/link/switch-to-createroot", - ] - : [ - "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", - ], + [ + "Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ], {withoutStack: true}, ) expect(result.current).toEqual('provided') }) + +testGateReact19('legacyRoot throws', () => { + const Context = React.createContext('default') + function Wrapper({children}) { + return {children} + } + expect(() => { + renderHook( + () => { + return React.useContext(Context) + }, + { + wrapper: Wrapper, + legacyRoot: true, + }, + ).result + }).toThrowErrorMatchingInlineSnapshot( + `\`legacyRoot: true\` is not supported in this version of React. Please use React 18 instead.`, + ) +}) diff --git a/src/act-compat.js b/src/act-compat.js index 86518196..5877755c 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -1,6 +1,7 @@ -import * as testUtils from 'react-dom/test-utils' +import * as React from 'react' +import * as DeprecatedReactTestUtils from 'react-dom/test-utils' -const domAct = testUtils.act +const reactAct = React.act ?? DeprecatedReactTestUtils.act function getGlobalThis() { /* istanbul ignore else */ @@ -78,7 +79,7 @@ function withGlobalActEnvironment(actImplementation) { } } -const act = withGlobalActEnvironment(domAct) +const act = withGlobalActEnvironment(reactAct) export default act export { diff --git a/src/pure.js b/src/pure.js index 3939a11a..38ec519f 100644 --- a/src/pure.js +++ b/src/pure.js @@ -207,6 +207,14 @@ function render( wrapper, } = {}, ) { + if (legacyRoot && typeof ReactDOM.render !== 'function') { + const error = new Error( + '`legacyRoot: true` is not supported in this version of React. Please use React 18 instead.', + ) + Error.captureStackTrace(error, render) + throw error + } + if (!baseElement) { // default to document.body instead of documentElement to avoid output of potentially-large // head elements (such as JSS style blocks) in debug output @@ -263,6 +271,15 @@ function cleanup() { function renderHook(renderCallback, options = {}) { const {initialProps, ...renderOptions} = options + + if (renderOptions.legacyRoot && typeof ReactDOM.render !== 'function') { + const error = new Error( + '`legacyRoot: true` is not supported in this version of React. Please use React 18 instead.', + ) + Error.captureStackTrace(error, renderHook) + throw error + } + const result = React.createRef() function TestComponent({renderCallbackProps}) { diff --git a/types/index.d.ts b/types/index.d.ts index 49a1b7ff..e7cf02bc 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -73,6 +73,7 @@ export interface RenderOptions< */ hydrate?: boolean /** + * Only works if used with React 18. * Set to `true` if you want to force synchronous `ReactDOM.render`. * Otherwise `render` will default to concurrent React if available. */ From 787cb85f8baa3d2e2a9916b7dad12c0a76d787a4 Mon Sep 17 00:00:00 2001 From: Matan Borenkraout Date: Wed, 10 Apr 2024 18:18:28 +0300 Subject: [PATCH 307/327] Release: 15.0.0 (#1295) BREAKING CHANGE: Minimum supported Node.js version is 18.0 BREAKING CHANGE: New version of `@testing-library/dom` changes various roles. Check out the changed tests in https://github.com/testing-library/dom-testing-library/commit/2c570553d8f31b008451398152a9bd30bce362b3 to get an overview about what changed. --- .codesandbox/ci.json | 2 +- .github/workflows/validate.yml | 2 +- package.json | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index d5850328..002bafb4 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -1,5 +1,5 @@ { "installCommand": "install:csb", "sandboxes": ["new", "github/kentcdodds/react-testing-library-examples"], - "node": "14" + "node": "18" } diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 4a20e2ab..aa4eeed7 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -29,7 +29,7 @@ jobs: strategy: fail-fast: false matrix: - node: [14, 16, 18] + node: [18, 20] react: ['18.x', latest, canary, experimental] runs-on: ubuntu-latest steps: diff --git a/package.json b/package.json index 0b7f83d8..9483256a 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "types": "types/index.d.ts", "module": "dist/@testing-library/react.esm.js", "engines": { - "node": ">=14" + "node": ">=18" }, "scripts": { "prebuild": "rimraf dist", @@ -46,7 +46,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^9.0.0", + "@testing-library/dom": "^10.0.0", "@types/react-dom": "^18.0.0" }, "devDependencies": { From 1645d21950ab8e3c6740b7e51b8a179a4c975c24 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Thu, 11 Apr 2024 19:03:17 +0200 Subject: [PATCH 308/327] fix: Stop using nullish coalescing (#1299) --- src/act-compat.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/act-compat.js b/src/act-compat.js index 5877755c..6eaec0fb 100644 --- a/src/act-compat.js +++ b/src/act-compat.js @@ -1,7 +1,8 @@ import * as React from 'react' import * as DeprecatedReactTestUtils from 'react-dom/test-utils' -const reactAct = React.act ?? DeprecatedReactTestUtils.act +const reactAct = + typeof React.act === 'function' ? React.act : DeprecatedReactTestUtils.act function getGlobalThis() { /* istanbul ignore else */ From c63b873072d62c858959c2a19e68f8e2cc0b11be Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Sat, 13 Apr 2024 11:21:10 +0200 Subject: [PATCH 309/327] fix: Improve `legacyRoot` error message (#1301) --- src/__tests__/render.js | 4 ++-- src/__tests__/renderHook.js | 2 +- src/pure.js | 8 ++++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/__tests__/render.js b/src/__tests__/render.js index 16f7dbe2..f00410b4 100644 --- a/src/__tests__/render.js +++ b/src/__tests__/render.js @@ -234,7 +234,7 @@ describe('render API', () => { expect(() => { render(
, {legacyRoot: true}) }).toThrowErrorMatchingInlineSnapshot( - `\`legacyRoot: true\` is not supported in this version of React. Please use React 18 instead.`, + `\`legacyRoot: true\` is not supported in this version of React. If your app runs React 19 or later, you should remove this flag. If your app runs React 18 or earlier, visit https://react.dev/blog/2022/03/08/react-18-upgrade-guide for upgrade instructions.`, ) }) @@ -259,7 +259,7 @@ describe('render API', () => { expect(() => { render(ui, {container, hydrate: true, legacyRoot: true}) }).toThrowErrorMatchingInlineSnapshot( - `\`legacyRoot: true\` is not supported in this version of React. Please use React 18 instead.`, + `\`legacyRoot: true\` is not supported in this version of React. If your app runs React 19 or later, you should remove this flag. If your app runs React 18 or earlier, visit https://react.dev/blog/2022/03/08/react-18-upgrade-guide for upgrade instructions.`, ) }) }) diff --git a/src/__tests__/renderHook.js b/src/__tests__/renderHook.js index c7c8b066..fe7551a2 100644 --- a/src/__tests__/renderHook.js +++ b/src/__tests__/renderHook.js @@ -108,6 +108,6 @@ testGateReact19('legacyRoot throws', () => { }, ).result }).toThrowErrorMatchingInlineSnapshot( - `\`legacyRoot: true\` is not supported in this version of React. Please use React 18 instead.`, + `\`legacyRoot: true\` is not supported in this version of React. If your app runs React 19 or later, you should remove this flag. If your app runs React 18 or earlier, visit https://react.dev/blog/2022/03/08/react-18-upgrade-guide for upgrade instructions.`, ) }) diff --git a/src/pure.js b/src/pure.js index 38ec519f..f546af98 100644 --- a/src/pure.js +++ b/src/pure.js @@ -209,7 +209,9 @@ function render( ) { if (legacyRoot && typeof ReactDOM.render !== 'function') { const error = new Error( - '`legacyRoot: true` is not supported in this version of React. Please use React 18 instead.', + '`legacyRoot: true` is not supported in this version of React. ' + + 'If your app runs React 19 or later, you should remove this flag. ' + + 'If your app runs React 18 or earlier, visit https://react.dev/blog/2022/03/08/react-18-upgrade-guide for upgrade instructions.', ) Error.captureStackTrace(error, render) throw error @@ -274,7 +276,9 @@ function renderHook(renderCallback, options = {}) { if (renderOptions.legacyRoot && typeof ReactDOM.render !== 'function') { const error = new Error( - '`legacyRoot: true` is not supported in this version of React. Please use React 18 instead.', + '`legacyRoot: true` is not supported in this version of React. ' + + 'If your app runs React 19 or later, you should remove this flag. ' + + 'If your app runs React 18 or earlier, visit https://react.dev/blog/2022/03/08/react-18-upgrade-guide for upgrade instructions.', ) Error.captureStackTrace(error, renderHook) throw error From 067d0c6d2e87092f6ecaa8c9fcf505e4576055cf Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 23 Apr 2024 12:21:18 +0200 Subject: [PATCH 310/327] fix: Don't raise TypeScript errors when hydating `document` (#1304) --- types/index.d.ts | 60 ++++++++++++++++++++++++++++++++++++++++++------ types/test.tsx | 11 +++++++++ 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index e7cf02bc..566e3d05 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,5 +1,5 @@ // TypeScript Version: 3.8 - +import * as ReactDOMClient from 'react-dom/client' import { queries, Queries, @@ -43,10 +43,10 @@ export type RenderResult< asFragment: () => DocumentFragment } & {[P in keyof Q]: BoundFunction} -export interface RenderOptions< - Q extends Queries = typeof queries, - Container extends Element | DocumentFragment = HTMLElement, - BaseElement extends Element | DocumentFragment = Container, +export interface BaseRenderOptions< + Q extends Queries, + Container extends RendererableContainer | HydrateableContainer, + BaseElement extends Element | DocumentFragment, > { /** * By default, React Testing Library will create a div and append that div to the document.body. Your React component will be rendered in the created div. If you provide your own HTMLElement container via this option, @@ -93,6 +93,44 @@ export interface RenderOptions< wrapper?: React.JSXElementConstructor<{children: React.ReactNode}> } +type RendererableContainer = ReactDOMClient.Container +type HydrateableContainer = Parameters[0] +export interface ClientRenderOptions< + Q extends Queries, + Container extends Element | DocumentFragment, + BaseElement extends Element | DocumentFragment = Container, +> extends BaseRenderOptions { + /** + * If `hydrate` is set to `true`, then it will render with `ReactDOM.hydrate`. This may be useful if you are using server-side + * rendering and use ReactDOM.hydrate to mount your components. + * + * @see https://testing-library.com/docs/react-testing-library/api/#hydrate) + */ + hydrate?: false | undefined +} + +export interface HydrateOptions< + Q extends Queries, + Container extends Element | DocumentFragment, + BaseElement extends Element | DocumentFragment = Container, +> extends BaseRenderOptions { + /** + * If `hydrate` is set to `true`, then it will render with `ReactDOM.hydrate`. This may be useful if you are using server-side + * rendering and use ReactDOM.hydrate to mount your components. + * + * @see https://testing-library.com/docs/react-testing-library/api/#hydrate) + */ + hydrate: true +} + +export type RenderOptions< + Q extends Queries = typeof queries, + Container extends RendererableContainer | HydrateableContainer = HTMLElement, + BaseElement extends Element | DocumentFragment = Container, +> = + | ClientRenderOptions + | HydrateOptions + type Omit = Pick> /** @@ -100,11 +138,19 @@ type Omit = Pick> */ export function render< Q extends Queries = typeof queries, - Container extends Element | DocumentFragment = HTMLElement, + Container extends RendererableContainer = HTMLElement, + BaseElement extends Element | DocumentFragment = Container, +>( + ui: React.ReactNode, + options: ClientRenderOptions, +): RenderResult +export function render< + Q extends Queries = typeof queries, + Container extends HydrateableContainer = HTMLElement, BaseElement extends Element | DocumentFragment = Container, >( ui: React.ReactNode, - options: RenderOptions, + options: HydrateOptions, ): RenderResult export function render( ui: React.ReactNode, diff --git a/types/test.tsx b/types/test.tsx index 6ff899de..da0bda06 100644 --- a/types/test.tsx +++ b/types/test.tsx @@ -206,6 +206,17 @@ export function testRenderHookProps() { unmount() } +export function testContainer() { + render('a', {container: document.createElement('div')}) + render('a', {container: document.createDocumentFragment()}) + // @ts-expect-error Only allowed in React 19 + render('a', {container: document}) + render('a', {container: document.createElement('div'), hydrate: true}) + // @ts-expect-error Only allowed for createRoot + render('a', {container: document.createDocumentFragment(), hydrate: true}) + render('a', {container: document, hydrate: true}) +} + /* eslint testing-library/prefer-explicit-assert: "off", From 48282c2f35fb7338834b40983c12b889af35f5d1 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Tue, 23 Apr 2024 17:32:08 +0200 Subject: [PATCH 311/327] fix: Ensure `renderHook` options extend options for `render` (#1308) --- types/index.d.ts | 63 ++++++++++++++++++++++++++++++++++++++++++------ types/test.tsx | 19 +++++++++++++++ 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index 566e3d05..78302693 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -179,12 +179,12 @@ export interface RenderHookResult { unmount: () => void } -export interface RenderHookOptions< +export interface BaseRenderHookOptions< Props, - Q extends Queries = typeof queries, - Container extends Element | DocumentFragment = HTMLElement, - BaseElement extends Element | DocumentFragment = Container, -> extends RenderOptions { + Q extends Queries, + Container extends RendererableContainer | HydrateableContainer, + BaseElement extends Element | DocumentFragment, +> extends BaseRenderOptions { /** * The argument passed to the renderHook callback. Can be useful if you plan * to use the rerender utility to change the values passed to your hook. @@ -192,6 +192,45 @@ export interface RenderHookOptions< initialProps?: Props } +export interface ClientRenderHookOptions< + Props, + Q extends Queries, + Container extends Element | DocumentFragment, + BaseElement extends Element | DocumentFragment = Container, +> extends BaseRenderHookOptions { + /** + * If `hydrate` is set to `true`, then it will render with `ReactDOM.hydrate`. This may be useful if you are using server-side + * rendering and use ReactDOM.hydrate to mount your components. + * + * @see https://testing-library.com/docs/react-testing-library/api/#hydrate) + */ + hydrate?: false | undefined +} + +export interface HydrateHookOptions< + Props, + Q extends Queries, + Container extends Element | DocumentFragment, + BaseElement extends Element | DocumentFragment = Container, +> extends BaseRenderHookOptions { + /** + * If `hydrate` is set to `true`, then it will render with `ReactDOM.hydrate`. This may be useful if you are using server-side + * rendering and use ReactDOM.hydrate to mount your components. + * + * @see https://testing-library.com/docs/react-testing-library/api/#hydrate) + */ + hydrate: true +} + +export type RenderHookOptions< + Props, + Q extends Queries = typeof queries, + Container extends Element | DocumentFragment = HTMLElement, + BaseElement extends Element | DocumentFragment = Container, +> = + | ClientRenderHookOptions + | HydrateHookOptions + /** * Allows you to render a hook within a test React component without having to * create that component yourself. @@ -200,11 +239,21 @@ export function renderHook< Result, Props, Q extends Queries = typeof queries, - Container extends Element | DocumentFragment = HTMLElement, + Container extends RendererableContainer = HTMLElement, + BaseElement extends Element | DocumentFragment = Container, +>( + render: (initialProps: Props) => Result, + options?: ClientRenderHookOptions, +): RenderHookResult +export function renderHook< + Result, + Props, + Q extends Queries = typeof queries, + Container extends HydrateableContainer = HTMLElement, BaseElement extends Element | DocumentFragment = Container, >( render: (initialProps: Props) => Result, - options?: RenderHookOptions, + options?: HydrateHookOptions, ): RenderHookResult /** diff --git a/types/test.tsx b/types/test.tsx index da0bda06..734d70e7 100644 --- a/types/test.tsx +++ b/types/test.tsx @@ -45,6 +45,8 @@ export function testRenderOptions() { const options = {container} const {container: returnedContainer} = render(