Skip to content

Commit

Permalink
Fix shallow renderer callbacks (#10106)
Browse files Browse the repository at this point in the history
* Add failing test to show that shallow test renderer doesn't call setState's callback arg
* Record tests
* Fix shallow renderer's setState/replaceState/forceUpdate to execute any callbacks passed. (#10089)
* Ensure shallow renderer callbacks are called with the correct  binding.
  • Loading branch information
Dheeraj Kumar authored and bvaughn committed Jul 10, 2017
1 parent 5bc25cb commit 5ac6209
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 0 deletions.
3 changes: 3 additions & 0 deletions scripts/fiber/tests-passing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1955,6 +1955,9 @@ src/renderers/dom/test/__tests__/ReactTestUtils-test.js
* can setState in componentWillMount when shallow rendering
* can setState in componentWillReceiveProps when shallow rendering
* can setState with an updater function
* can setState with a callback
* can replaceState with a callback
* can forceUpdate with a callback
* can pass context when shallowly rendering
* should track context across updates
* can fail context when shallowly rendering
Expand Down
102 changes: 102 additions & 0 deletions src/renderers/dom/test/__tests__/ReactTestUtils-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,108 @@ describe('ReactTestUtils', () => {
expect(result.props.children).toEqual(2);
});

it('can setState with a callback', () => {
let instance;

class SimpleComponent extends React.Component {
state = {
counter: 0,
};
render() {
instance = this;
return (
<p>
{this.state.counter}
</p>
);
}
}

const shallowRenderer = createRenderer();
const result = shallowRenderer.render(<SimpleComponent />);
expect(result.props.children).toBe(0);

const callback = jest.fn(function() {
expect(this).toBe(instance);
});

instance.setState({counter: 1}, callback);

const updated = shallowRenderer.getRenderOutput();
expect(updated.props.children).toBe(1);
expect(callback).toHaveBeenCalled();
});

it('can replaceState with a callback', () => {
let instance;

class SimpleComponent extends React.Component {
state = {
counter: 0,
};
render() {
instance = this;
return (
<p>
{this.state.counter}
</p>
);
}
}

const shallowRenderer = createRenderer();
const result = shallowRenderer.render(<SimpleComponent />);
expect(result.props.children).toBe(0);

const callback = jest.fn(function() {
expect(this).toBe(instance);
});

// No longer a public API, but we can test that it works internally by
// reaching into the updater.
shallowRenderer._updater.enqueueReplaceState(
instance,
{counter: 1},
callback,
);

const updated = shallowRenderer.getRenderOutput();
expect(updated.props.children).toBe(1);
expect(callback).toHaveBeenCalled();
});

it('can forceUpdate with a callback', () => {
let instance;

class SimpleComponent extends React.Component {
state = {
counter: 0,
};
render() {
instance = this;
return (
<p>
{this.state.counter}
</p>
);
}
}

const shallowRenderer = createRenderer();
const result = shallowRenderer.render(<SimpleComponent />);
expect(result.props.children).toBe(0);

const callback = jest.fn(function() {
expect(this).toBe(instance);
});

instance.forceUpdate(callback);

const updated = shallowRenderer.getRenderOutput();
expect(updated.props.children).toBe(0);
expect(callback).toHaveBeenCalled();
});

it('can pass context when shallowly rendering', () => {
class SimpleComponent extends React.Component {
static contextTypes = {
Expand Down
12 changes: 12 additions & 0 deletions src/renderers/testing/ReactShallowRendererEntry.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,19 @@ class Updater {

enqueueForceUpdate(publicInstance, callback, callerName) {
this._renderer.render(this._renderer._element, this._renderer._context);

if (typeof callback === 'function') {
callback.call(publicInstance);
}
}

enqueueReplaceState(publicInstance, completeState, callback, callerName) {
this._renderer._newState = completeState;
this._renderer.render(this._renderer._element, this._renderer._context);

if (typeof callback === 'function') {
callback.call(publicInstance);
}
}

enqueueSetState(publicInstance, partialState, callback, callerName) {
Expand All @@ -219,6 +227,10 @@ class Updater {
};

this._renderer.render(this._renderer._element, this._renderer._context);

if (typeof callback === 'function') {
callback.call(publicInstance);
}
}
}

Expand Down

0 comments on commit 5ac6209

Please sign in to comment.