From 4ed443af39384117c7d2c66f5f22bf11a8cbbfa3 Mon Sep 17 00:00:00 2001 From: Johann Hubert Sonntagbauer Date: Thu, 3 May 2018 19:52:28 +0200 Subject: [PATCH 1/5] feat(rerender): implement rerender (#65) * update readme * update examples * tests * typescript typings --- .all-contributorsrc | 11 +++++++ README.md | 50 ++++++++++++------------------ examples/__tests__/update-props.js | 6 ++-- src/__tests__/rerender.js | 13 ++++++++ src/index.js | 1 + typings/index.d.ts | 1 + 6 files changed, 47 insertions(+), 35 deletions(-) create mode 100644 src/__tests__/rerender.js diff --git a/.all-contributorsrc b/.all-contributorsrc index c7563662..f76f6a43 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -207,6 +207,17 @@ "example", "ideas" ] + }, + { + "login": "johann-sonntagbauer", + "name": "Johann Hubert Sonntagbauer", + "avatar_url": "https://avatars3.githubusercontent.com/u/1239401?v=4", + "profile": "https://github.com/johann-sonntagbauer", + "contributions": [ + "code", + "doc", + "test" + ] } ] } diff --git a/README.md b/README.md index 30043989..c55a9f26 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-20-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-21-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] @@ -167,6 +167,21 @@ The containing DOM node of your rendered React Element (rendered using > Tip: To get the root element of your rendered element, use `container.firstChild`. +#### `rerender` +It'd probably be better if you test the component that's doing the prop updating +to ensure that the props are being updated correctly (see +[the Guiding Principles section](#guiding-principles)). That said, if you'd +prefer to update the props of a rendered component in your test, this function +can be used to update props of the rendered component. +```javascript +const {rerender} = render() + +// re-render the same component with different props +rerender() +``` +[Open the tests](https://github.com/kentcdodds/react-testing-library/blob/master/examples/__tests__/update-props.js) +for a full example of this. + #### `unmount` This will cause the rendered component to be unmounted. This is useful for @@ -274,7 +289,8 @@ const usernameInputElement = getByTestId('username-input') ### `renderIntoDocument` -Render into `document.body`. Should be used with [cleanup](#cleanup) +Render into `document.body`. Should be used with [cleanup](#cleanup). +`renderIntoDocument` will return the same object as [render](#render) ```javascript renderIntoDocument(
) @@ -527,32 +543,6 @@ to just stick with `data-testid`s (which is not bad anyway).
-How do I update the props of a rendered component? - -It'd probably be better if you test the component that's doing the prop updating -to ensure that the props are being updated correctly (see -[the Guiding Principles section](#guiding-principles)). That said, if you'd -prefer to update the props of a rendered component in your test, the easiest -way to do that is: - -```javascript -const {container, getByTestId} = render() -expect(getByTestId('number-display').textContent).toBe('1') - -// re-render the same component with different props -// but pass the same container in the options argument. -// which will cause a re-render of the same instance (normal React behavior). -render(, {container}) -expect(getByTestId('number-display').textContent).toBe('2') -``` - -[Open the tests](https://github.com/kentcdodds/react-testing-library/blob/master/examples/__tests__/update-props.js) -for a full example of this. - -
- -
- If I can't use shallow rendering, how do I mock out components in tests? In general, you should avoid mocking out components (see @@ -759,13 +749,11 @@ light-weight, simple, and understandable. Thanks goes to these people ([emoji key][emojis]): - | [
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](http://audiolion.github.io)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=audiolion "Documentation") | [
Daniel Sandiego](https://www.dnlsandiego.com)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=dnlsandiego "Code") | [
PaweΕ‚ MikoΕ‚ajczyk](https://github.com/Miklet)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=Miklet "Code") | [
Alejandro ÑÑñez Ortiz](http://co.linkedin.com/in/alejandronanez/)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=alejandronanez "Documentation") | [
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](https://github.com/wKovacs64)
[πŸ“¦](#platform-wKovacs64 "Packaging/porting to new platform") | | :---: | :---: | :---: | :---: | :---: | :---: | :---: | | [
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](https://github.com/JonahMoses)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=JonahMoses "Documentation") | [
Ł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](https://sompylasar.github.io)
[πŸ›](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Asompylasar "Bug reports") [πŸ€”](#ideas-sompylasar "Ideas, Planning, & Feedback") | [
Jesse Day](https://github.com/jday3)
[πŸ’»](https://github.com/kentcdodds/react-testing-library/commits?author=jday3 "Code") | [
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](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](https://twitter.com/baranovskim)
[πŸ“](#blog-mbaranovski "Blogposts") [βœ…](#tutorial-mbaranovski "Tutorials") | [
Arthur Puthin](https://github.com/aputhin)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=aputhin "Documentation") | [
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](http://ilegra.com/)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=thiagopaiva99 "Documentation") | [
Christian](http://Chriswcs.github.io)
[⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=ChrisWcs "Tests") | [
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") | - +| [
Michal Baranowski](https://twitter.com/baranovskim)
[πŸ“](#blog-mbaranovski "Blogposts") [βœ…](#tutorial-mbaranovski "Tutorials") | [
Arthur Puthin](https://github.com/aputhin)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=aputhin "Documentation") | [
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](http://ilegra.com/)
[πŸ“–](https://github.com/kentcdodds/react-testing-library/commits?author=thiagopaiva99 "Documentation") | [
Christian](http://Chriswcs.github.io)
[⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=ChrisWcs "Tests") | [
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](https://github.com/johann-sonntagbauer)
[🎨](#design-johann-sonntagbauer "Design") | This project follows the [all-contributors][all-contributors] specification. diff --git a/examples/__tests__/update-props.js b/examples/__tests__/update-props.js index 2f8952e7..58731fec 100644 --- a/examples/__tests__/update-props.js +++ b/examples/__tests__/update-props.js @@ -20,13 +20,11 @@ class NumberDisplay extends React.Component { } test('calling render with the same component on the same container does not remount', () => { - const {container, getByTestId} = render() + const {getByTestId, rerender} = render() expect(getByTestId('number-display').textContent).toBe('1') // re-render the same component with different props - // but pass the same container in the options argument. - // which will cause a re-render of the same instance (normal React behavior). - render(, {container}) + rerender() expect(getByTestId('number-display').textContent).toBe('2') expect(getByTestId('instance-id').textContent).toBe('1') diff --git a/src/__tests__/rerender.js b/src/__tests__/rerender.js new file mode 100644 index 00000000..bfbcb5e3 --- /dev/null +++ b/src/__tests__/rerender.js @@ -0,0 +1,13 @@ +import React from 'react' +import {render, cleanup} from '../' +import 'jest-dom/extend-expect' + +afterEach(cleanup) + +it('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') +}) \ No newline at end of file diff --git a/src/index.js b/src/index.js index 98919e52..84edd741 100644 --- a/src/index.js +++ b/src/index.js @@ -7,6 +7,7 @@ function render(ui, {container = document.createElement('div')} = {}) { return { container, unmount: () => ReactDOM.unmountComponentAtNode(container), + rerender: rerenderUi => render(rerenderUi, {container}), ...bindElementToQueries(container), } } diff --git a/typings/index.d.ts b/typings/index.d.ts index 819e4b59..4ce23f86 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -5,6 +5,7 @@ type TextMatch = string | RegExp | TextMatchFunction interface RenderResult { container: HTMLDivElement + rerender: (ui: React.ReactElement) => void unmount: VoidFunction queryByTestId: (id: TextMatch) => HTMLElement | null getByTestId: (id: TextMatch) => HTMLElement From e6cf3057ed9b114ab5fd39e49032c0c39d533ccd Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 3 May 2018 12:23:22 -0600 Subject: [PATCH 2/5] Update index.js --- src/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 84edd741..4a637b90 100644 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,11 @@ function render(ui, {container = document.createElement('div')} = {}) { return { container, unmount: () => ReactDOM.unmountComponentAtNode(container), - rerender: rerenderUi => render(rerenderUi, {container}), + rerender: rerenderUi => { + render(rerenderUi, {container}) + // 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 + }, ...bindElementToQueries(container), } } From 38ef5f0f2fbc14adb0553eeb409817c6c19ff02e Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 3 May 2018 12:23:39 -0600 Subject: [PATCH 3/5] Update rerender.js --- src/__tests__/rerender.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__tests__/rerender.js b/src/__tests__/rerender.js index bfbcb5e3..79f80875 100644 --- a/src/__tests__/rerender.js +++ b/src/__tests__/rerender.js @@ -4,10 +4,10 @@ import 'jest-dom/extend-expect' afterEach(cleanup) -it('rerender will re-render the element', () => { +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') -}) \ No newline at end of file +}) From aa950006ca6f8ecada7b63e43db997870b7aa122 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 3 May 2018 12:23:55 -0600 Subject: [PATCH 4/5] Update rerender.js --- src/__tests__/rerender.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/__tests__/rerender.js b/src/__tests__/rerender.js index 79f80875..2a1c332d 100644 --- a/src/__tests__/rerender.js +++ b/src/__tests__/rerender.js @@ -1,9 +1,7 @@ import React from 'react' -import {render, cleanup} from '../' +import {render} from '../' import 'jest-dom/extend-expect' -afterEach(cleanup) - test('rerender will re-render the element', () => { const Greeting = props =>
{props.message}
const {container, rerender} = render() From d87bc01620ce2d9917535bcabbbd8f3acc8e6c2f Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 3 May 2018 12:24:30 -0600 Subject: [PATCH 5/5] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c55a9f26..30b0645a 100644 --- a/README.md +++ b/README.md @@ -168,17 +168,20 @@ The containing DOM node of your rendered React Element (rendered using > Tip: To get the root element of your rendered element, use `container.firstChild`. #### `rerender` + It'd probably be better if you test the component that's doing the prop updating to ensure that the props are being updated correctly (see [the Guiding Principles section](#guiding-principles)). That said, if you'd prefer to update the props of a rendered component in your test, this function can be used to update props of the rendered component. + ```javascript const {rerender} = render() // re-render the same component with different props rerender() ``` + [Open the tests](https://github.com/kentcdodds/react-testing-library/blob/master/examples/__tests__/update-props.js) for a full example of this.