From 78f22ee7597e19c8bc092a05f98543c94a8f6ffd Mon Sep 17 00:00:00 2001 From: jwbay Date: Thu, 12 May 2016 22:10:55 -0400 Subject: [PATCH] use getter for .node and .nodes in ShallowWrapper to ensure render output is always fresh. removes need for .update, fixes #360 --- docs/README.md | 1 - docs/api/ShallowWrapper/update.md | 33 --------------------------- docs/api/shallow.md | 3 --- src/ShallowWrapper.js | 25 +++++++++------------ test/ShallowWrapper-spec.js | 37 +++++++++++++++++++++++++++++++ 5 files changed, 48 insertions(+), 51 deletions(-) diff --git a/docs/README.md b/docs/README.md index a0a7508b0..adf09d7e4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -65,7 +65,6 @@ * [text()](/docs/api/ShallowWrapper/text.md) * [type()](/docs/api/ShallowWrapper/type.md) * [unmount()](/docs/api/ShallowWrapper/unmount.md) - * [update()](/docs/api/ShallowWrapper/update.md) * [Full DOM Rendering](/docs/api/mount.md) * [at(index)](/docs/api/ReactWrapper/at.md) * [contains(nodeOrNodes)](/docs/api/ReactWrapper/contains.md) diff --git a/docs/api/ShallowWrapper/update.md b/docs/api/ShallowWrapper/update.md index 3dc372353..e69de29bb 100644 --- a/docs/api/ShallowWrapper/update.md +++ b/docs/api/ShallowWrapper/update.md @@ -1,33 +0,0 @@ -# `.update() => Self` - -Forces a re-render. Useful to run before checking the render output if something external -may be updating the state of the component somewhere. - -NOTE: can only be called on a wrapper instance that is also the root instance. - - -#### Returns - -`ShallowWrapper`: Returns itself. - - - -#### Example - -```jsx -class ImpureRender extends React.Component { - constructor(props) { - super(props); - this.count = 0; - } - render() { - return
{this.count++}
- } -} -``` -```jsx -const wrapper = shallow(); -expect(wrapper.text()).to.equal("0"); -wrapper.update(); -expect(wrapper.text()).to.equal("1"); -``` diff --git a/docs/api/shallow.md b/docs/api/shallow.md index a67d2694d..7bda112e6 100644 --- a/docs/api/shallow.md +++ b/docs/api/shallow.md @@ -169,9 +169,6 @@ Manually sets context of the root component. #### [`.instance() => ReactComponent`](ShallowWrapper/instance.md) Returns the instance of the root component. -#### [`.update() => ShallowWrapper`](ShallowWrapper/update.md) -Calls `.forceUpdate()` on the root component instance. - #### [`.debug() => String`](ShallowWrapper/debug.md) Returns a string representation of the current shallow render tree for debugging purposes. diff --git a/src/ShallowWrapper.js b/src/ShallowWrapper.js index f940253ab..6f8fba03d 100644 --- a/src/ShallowWrapper.js +++ b/src/ShallowWrapper.js @@ -80,8 +80,16 @@ export default class ShallowWrapper { } }); }); - this.node = this.renderer.getRenderOutput(); - this.nodes = [this.node]; + Object.defineProperty(this, 'node', { + get() { + return this.renderer.getRenderOutput(); + }, + }); + Object.defineProperty(this, 'nodes', { + get() { + return [this.renderer.getRenderOutput()]; + }, + }); this.length = 1; } else { this.root = root; @@ -121,21 +129,10 @@ export default class ShallowWrapper { } /** - * Forces a re-render. Useful to run before checking the render output if something external - * may be updating the state of the component somewhere. - * - * NOTE: can only be called on a wrapper instance that is also the root instance. - * + * @deprecated * @returns {ShallowWrapper} */ update() { - if (this.root !== this) { - throw new Error('ShallowWrapper::update() can only be called on the root'); - } - this.single(() => { - this.node = this.renderer.getRenderOutput(); - this.nodes = [this.node]; - }); return this; } diff --git a/test/ShallowWrapper-spec.js b/test/ShallowWrapper-spec.js index fa6cb4c97..c72027dee 100644 --- a/test/ShallowWrapper-spec.js +++ b/test/ShallowWrapper-spec.js @@ -3496,4 +3496,41 @@ describe('shallow', () => { }); }); + describe('out-of-band state updates', () => { + const promise = Promise.resolve(); + const returnsPromise = () => promise; + const Child = () => ; + + class Test extends React.Component { + asyncUpdate() { + returnsPromise().then(() => { + this.setState({ showSpan: true }); + }); + } + + render() { + return ( +
+ {this.state && this.state.showSpan && } +
+ ); + } + } + + it('should have updated output after an asynchronous setState', () => { + const wrapper = shallow(); + wrapper.find('.async-btn').simulate('click'); + return promise.then(() => { + expect(wrapper.find('.show-me').length).to.equal(1); + }); + }); + + it('should have updated output after child prop callback invokes setState', () => { + const wrapper = shallow(); + wrapper.find(Child).props().callback(); + expect(wrapper.find('.show-me').length).to.equal(1); + }); + }); });