Skip to content

Commit

Permalink
add store instance to WrapperWithRedux's returned ReactWrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
Raice Hannay committed Dec 16, 2019
1 parent 1776a0b commit bc72ddd
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 13 deletions.
42 changes: 38 additions & 4 deletions docs/WrapperWithRedux.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,41 @@ define your own `createStore` method to return an instance of your Redux store,
`initialState` and `middlewares` that this class provides - it is important to ensure that your
store uses these, because if it disregards them, none of the methods this class provides will function.

Extensions to the returned `ReduxWrapper`
-----------------------------------------

The return type of the `mount` method extends Enzyme's `ReactWrapper` by adding a store property to
it, so you can access the store instance that the component was mounted with. This is useful for
some edge cases where you may want to test how your component reacts to actions being dispatched
outside of the component's scope.

For example:
```typescript jsx
const component = new WrapperWithRedux(SomeComponent);

describe("when testing a scenario", () => {
const wrapper = component
.withReduxState({
test: {
value: "Scenario value 1"
}
})
.mount();

it("renders the initial value", () => {
expect(wrapper.find(".SomeComponent--value").text()).toBe("Initial value");
});

it("dispatches actions.setValue", () => {
wrapper.store.dispatch(actions.setValue("New value"));
});

it("renders the updated value", () => {
expect(wrapper.find(".SomeComponent--value").text()).toBe("New value");
});
});
```


Public read-only properties
---------------------------
Expand All @@ -17,10 +52,6 @@ Public read-only properties
An array of actions that have been dispatched, used when asserting that actions have been
dispatched as expected during interactions or in the component lifecycle.

### `store`
The instance of the Redux store used. However, this is only available after calling `mount`.
If accessed prior to mounting your component, it will be `undefined`.


Public methods
--------------
Expand All @@ -41,6 +72,9 @@ Sets the default Redux store state to be used for the wrapper instance.
### `withReduxState`
Sets the scenario-specific Redux store state to be used - cleared after `mount`, `render` or `shallow` are called.

### `mount`
Mounts the component with the Enzyme `mount` function, using the currently-set data.
Returns a `ReactWrapper` instance, which also includes a `store` property.

How to extend for use in your project
-------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"author": "Raice Hannay <voodoocreation@gmail.com>",
"description": "A set of classes to make setting up React components for unit tests easy.",
"license": "ISC",
"version": "1.0.8",
"version": "2.0.0",
"keywords": [
"component",
"enzyme",
Expand Down
6 changes: 3 additions & 3 deletions src/WrapperWithRedux.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ describe("WrapperWithRedux", () => {
});

it("has the expected state in the store", () => {
expect(component.store?.getState()).toEqual(initialState);
expect(wrapper.store.getState()).toEqual(initialState);
});

it("renders the default value", () => {
Expand All @@ -161,7 +161,7 @@ describe("WrapperWithRedux", () => {
});

it("dispatches an action", () => {
component.store?.dispatch(actions.setValue(payload));
wrapper.store.dispatch(actions.setValue(payload));
});

it("has the action in the history", () => {
Expand All @@ -171,7 +171,7 @@ describe("WrapperWithRedux", () => {
});

it("updates the store", () => {
expect(component.store?.getState()).toEqual({
expect(wrapper.store.getState()).toEqual({
test: {
value: payload
}
Expand Down
31 changes: 26 additions & 5 deletions src/WrapperWithRedux.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { mount, ReactWrapper } from "enzyme";
import * as React from "react";
import { Provider } from "react-redux";
import { AnyAction, DeepPartial, Middleware, Store } from "redux";
import merge from "ts-deepmerge";

import Wrapper from "./Wrapper";

type TWrapperWithStore<P, S> = ReactWrapper<P> & {
store: Store<S>;
};

export default abstract class WrapperWithRedux<
C extends React.ComponentType<any>,
S,
Expand All @@ -22,10 +27,6 @@ export default abstract class WrapperWithRedux<
return this.dispatchedActions;
}

public get store() {
return this.reduxStore;
}

protected get mergedReduxState(): S {
return merge(this.defaultReduxState, this.scenarioReduxState) as S;
}
Expand All @@ -42,6 +43,26 @@ export default abstract class WrapperWithRedux<
return this;
};

// @ts-ignore
public mount = () => {
this.beforeMount();

const props = this.defineProps() as P;
// @ts-ignore
const wrapper: TWrapperWithStore<P, S> = mount<P>(
<this.Component {...props} />,
{
wrappingComponent: this.WrappingComponent
}
);

this.reset();

wrapper.store = this.reduxStore!;

return wrapper;
};

public render = () => {
this.beforeMount();
this.reset();
Expand Down Expand Up @@ -81,7 +102,7 @@ export default abstract class WrapperWithRedux<
};

protected WrappingComponent: React.FC = ({ children }) => (
<Provider store={this.store!}>{children}</Provider>
<Provider store={this.reduxStore!}>{children}</Provider>
);

protected reset() {
Expand Down

0 comments on commit bc72ddd

Please sign in to comment.