Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added context support #62

Merged
merged 1 commit into from
Dec 10, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
* [simulate(event[, data])](/docs/api/ShallowWrapper/simulate.md)
* [setState(nextState)](/docs/api/ShallowWrapper/setState.md)
* [setProps(nextProps)](/docs/api/ShallowWrapper/setProps.md)
* [setContext(context)](/docs/api/ShallowWrapper/setContext.md)
* [instance()](/docs/api/ShallowWrapper/instance.md)
* [update()](/docs/api/ShallowWrapper/update.md)
* [debug()](/docs/api/ShallowWrapper/debug.md)
Expand Down Expand Up @@ -69,6 +70,7 @@
* [simulate(event[, data])](/docs/api/ReactWrapper/simulate.md)
* [setState(nextState)](/docs/api/ReactWrapper/setState.md)
* [setProps(nextProps)](/docs/api/ReactWrapper/setProps.md)
* [setContext(context)](/docs/api/ReactWrapper/setContext.md)
* [instance()](/docs/api/ReactWrapper/instance.md)
* [update()](/docs/api/ReactWrapper/update.md)
* [type()](/docs/api/ReactWrapper/type.md)
Expand Down
55 changes: 55 additions & 0 deletions docs/api/ReactWrapper/setContext.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# `.setContext(context) => Self`

A method that sets the context of the root component, and re-renders. Useful for when you are
wanting to test how the component behaves over time with changing contexts.

NOTE: can only be called on a wrapper instance that is also the root instance.


#### Arguments

1. `context` (`Object`): An object containing new props to merge in with the current state



#### Returns

`ReactWrapper`: Returns itself.



#### Example

```jsx
const SimpleComponent = React.createClass({
contextTypes: {
name: React.PropTypes.string,
},
render() {
return <div>{this.context.name}</div>;
},
});
```
```jsx
const context = { name: 'foo' };
const wrapper = mount(<SimpleComponent />, { context });
expect(wrapper.text()).to.equal('foo');
wrapper.setContext({ name: 'bar' });
expect(wrapper.text()).to.equal('bar');
wrapper.setContext({ name: 'baz' });
expect(wrapper.text()).to.equal('baz');
```

#### Common Gotchas

- `.setContext()` can only be used on a wrapper that was initially created with a call to `mount()`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this guaranteed, ie, will it throw an exception? I don't see any tests that cover this case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good call. will add some tests.

that includes a `context` specified in the options argument.
- The root component you are rendering must have a `contextTypes` static property.


#### Related Methods

- [`.setState(state) => Self`](setState.md)
- [`.setProps(props) => Self`](setProps.md)


1 change: 1 addition & 0 deletions docs/api/ReactWrapper/setProps.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ expect(spy.calledOnce).to.be.true;
#### Related Methods

- [`.setState(state) => Self`](setState.md)
- [`.setContext(context) => Self`](setContext.md)


1 change: 1 addition & 0 deletions docs/api/ReactWrapper/setState.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,6 @@ expect(wrapper.find('.bar')).to.have.length(1);
#### Related Methods

- [`.setProps(props) => Self`](setProps.md)
- [`.setContext(context) => Self`](setContext.md)


55 changes: 55 additions & 0 deletions docs/api/ShallowWrapper/setContext.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# `.setContext(context) => Self`

A method that sets the context of the root component, and re-renders. Useful for when you are
wanting to test how the component behaves over time with changing contexts.

NOTE: can only be called on a wrapper instance that is also the root instance.


#### Arguments

1. `context` (`Object`): An object containing new props to merge in with the current state



#### Returns

`ShallowWrapper`: Returns itself.



#### Example

```jsx
const SimpleComponent = React.createClass({
contextTypes: {
name: React.PropTypes.string,
},
render() {
return <div>{this.context.name}</div>;
},
});
```
```jsx
const context = { name: 'foo' };
const wrapper = shallow(<SimpleComponent />, { context });
expect(wrapper.text()).to.equal('foo');
wrapper.setContext({ name: 'bar' });
expect(wrapper.text()).to.equal('bar');
wrapper.setContext({ name: 'baz' });
expect(wrapper.text()).to.equal('baz');
```

#### Common Gotchas

- `.setContext()` can only be used on a wrapper that was initially created with a call to `shallow()`
that includes a `context` specified in the options argument.
- The root component you are rendering must have a `contextTypes` static property.


#### Related Methods

- [`.setState(state) => Self`](setState.md)
- [`.setProps(props) => Self`](setProps.md)


1 change: 1 addition & 0 deletions docs/api/ShallowWrapper/setProps.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ expect(spy.calledOnce).to.be.true;
#### Related Methods

- [`.setState(state) => Self`](setState.md)
- [`.setContext(context) => Self`](setContext.md)


1 change: 1 addition & 0 deletions docs/api/ShallowWrapper/setState.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,6 @@ expect(wrapper.find('.bar')).to.have.length(1);
#### Related Methods

- [`.setProps(props) => Self`](setProps.md)
- [`.setContext(context) => Self`](setContext.md)


15 changes: 15 additions & 0 deletions docs/api/mount.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ describe('<Foo />', () => {
});
```

## `mount(node[, options]) => ReactWrapper`

#### Arguments

1. `node` (`ReactElement`): The node to render
2. `options` (`Object` [optional]):
- `options.context`: (`Object` [optional]): Context to be passed into the component

#### Returns

`ReactWrapper`: The wrapper instance around the rendered output.


## ReactWrapper API

Expand Down Expand Up @@ -109,6 +121,9 @@ Manually sets state of the root component.
#### [`.setProps(nextProps) => ReactWrapper`](ReactWrapper/setProps.md)
Manually sets props of the root component.

#### [`.setContext(context) => ReactWrapper`](ReactWrapper/setContext.md)
Manually sets context of the root component.

#### [`.instance() => ReactComponent`](ReactWrapper/instance.md)
Returns the instance of the root component.

Expand Down
15 changes: 15 additions & 0 deletions docs/api/shallow.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ describe('<MyComponent />', () => {

```

## `shallow(node[, options]) => ReactWrapper`

#### Arguments

1. `node` (`ReactElement`): The node to render
2. `options` (`Object` [optional]):
- `options.context`: (`Object` [optional]): Context to be passed into the component

#### Returns

`ShallowWrapper`: The wrapper instance around the rendered output.


## ShallowWrapper API

Expand Down Expand Up @@ -121,6 +133,9 @@ Manually sets state of the root component.
#### [`.setProps(nextProps) => ShallowWrapper`](ShallowWrapper/setProps.md)
Manually sets props of the root component.

#### [`.setContext(context) => ShallowWrapper`](ShallowWrapper/setContext.md)
Manually sets context of the root component.

#### [`.instance() => ReactComponent`](ShallowWrapper/instance.md)
Returns the instance of the root component.

Expand Down
32 changes: 29 additions & 3 deletions src/ReactWrapper.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { flatten, unique, compact } from 'underscore';
import ReactWrapperComponent from './ReactWrapperComponent';
import createWrapperComponent from './ReactWrapperComponent';
import {
instHasClassName,
childrenOfInst,
Expand Down Expand Up @@ -45,7 +45,7 @@ function filterWhereUnwrapped(wrapper, predicate) {
*/
export default class ReactWrapper {

constructor(nodes, root) {
constructor(nodes, root, options = {}) {
if (!global.window && !global.document) {
throw new Error(
`It looks like you called \`mount()\` without a jsdom document being loaded. ` +
Expand All @@ -54,10 +54,12 @@ export default class ReactWrapper {
}

if (!root) {
const ReactWrapperComponent = createWrapperComponent(nodes, options);
this.component = renderIntoDocument(
<ReactWrapperComponent
Component={nodes.type}
props={nodes.props}
context={options.context}
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not due to this diff, but the airbnb styleguide shows this closing wrapper to be back 2 spaces. https://github.com/airbnb/javascript/tree/master/react#alignment

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tru dat

);
this.root = this;
Expand All @@ -76,6 +78,7 @@ export default class ReactWrapper {
}
this.length = this.nodes.length;
}
this.options = options;
}

/**
Expand Down Expand Up @@ -147,7 +150,7 @@ export default class ReactWrapper {
if (this.root !== this) {
throw new Error('ReactWrapper::setProps() can only be called on the root');
}
this.component.setProps(props);
this.component.setChildProps(props);
return this;
}

Expand All @@ -171,6 +174,29 @@ export default class ReactWrapper {
return this;
}

/**
* A method that sets the context of the root component, and re-renders. Useful for when you are
* wanting to test how the component behaves over time with changing contexts.
*
* NOTE: can only be called on a wrapper instance that is also the root instance.
*
* @param {Object} context object
* @returns {ReactWrapper}
*/
setContext(context) {
if (this.root !== this) {
throw new Error('ReactWrapper::setContext() can only be called on the root');
}
if (!this.options.context) {
throw new Error(
'ShallowWrapper::setContext() can only be called on a wrapper that was originally passed ' +
'a context option'
);
}
this.component.setChildContext(context);
return this;
}

/**
* Whether or not a given react element exists in the mount render tree.
*
Expand Down
Loading