Skip to content

Commit bc72ddd

Browse files
author
Raice Hannay
committed
add store instance to WrapperWithRedux's returned ReactWrapper
1 parent 1776a0b commit bc72ddd

File tree

4 files changed

+68
-13
lines changed

4 files changed

+68
-13
lines changed

docs/WrapperWithRedux.md

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,41 @@ define your own `createStore` method to return an instance of your Redux store,
99
`initialState` and `middlewares` that this class provides - it is important to ensure that your
1010
store uses these, because if it disregards them, none of the methods this class provides will function.
1111

12+
Extensions to the returned `ReduxWrapper`
13+
-----------------------------------------
14+
15+
The return type of the `mount` method extends Enzyme's `ReactWrapper` by adding a store property to
16+
it, so you can access the store instance that the component was mounted with. This is useful for
17+
some edge cases where you may want to test how your component reacts to actions being dispatched
18+
outside of the component's scope.
19+
20+
For example:
21+
```typescript jsx
22+
const component = new WrapperWithRedux(SomeComponent);
23+
24+
describe("when testing a scenario", () => {
25+
const wrapper = component
26+
.withReduxState({
27+
test: {
28+
value: "Scenario value 1"
29+
}
30+
})
31+
.mount();
32+
33+
it("renders the initial value", () => {
34+
expect(wrapper.find(".SomeComponent--value").text()).toBe("Initial value");
35+
});
36+
37+
it("dispatches actions.setValue", () => {
38+
wrapper.store.dispatch(actions.setValue("New value"));
39+
});
40+
41+
it("renders the updated value", () => {
42+
expect(wrapper.find(".SomeComponent--value").text()).toBe("New value");
43+
});
44+
});
45+
```
46+
1247

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

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

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

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

4579
How to extend for use in your project
4680
-------------------------------------

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"author": "Raice Hannay <[email protected]>",
44
"description": "A set of classes to make setting up React components for unit tests easy.",
55
"license": "ISC",
6-
"version": "1.0.8",
6+
"version": "2.0.0",
77
"keywords": [
88
"component",
99
"enzyme",

src/WrapperWithRedux.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ describe("WrapperWithRedux", () => {
151151
});
152152

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

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

163163
it("dispatches an action", () => {
164-
component.store?.dispatch(actions.setValue(payload));
164+
wrapper.store.dispatch(actions.setValue(payload));
165165
});
166166

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

173173
it("updates the store", () => {
174-
expect(component.store?.getState()).toEqual({
174+
expect(wrapper.store.getState()).toEqual({
175175
test: {
176176
value: payload
177177
}

src/WrapperWithRedux.tsx

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
import { mount, ReactWrapper } from "enzyme";
12
import * as React from "react";
23
import { Provider } from "react-redux";
34
import { AnyAction, DeepPartial, Middleware, Store } from "redux";
45
import merge from "ts-deepmerge";
56

67
import Wrapper from "./Wrapper";
78

9+
type TWrapperWithStore<P, S> = ReactWrapper<P> & {
10+
store: Store<S>;
11+
};
12+
813
export default abstract class WrapperWithRedux<
914
C extends React.ComponentType<any>,
1015
S,
@@ -22,10 +27,6 @@ export default abstract class WrapperWithRedux<
2227
return this.dispatchedActions;
2328
}
2429

25-
public get store() {
26-
return this.reduxStore;
27-
}
28-
2930
protected get mergedReduxState(): S {
3031
return merge(this.defaultReduxState, this.scenarioReduxState) as S;
3132
}
@@ -42,6 +43,26 @@ export default abstract class WrapperWithRedux<
4243
return this;
4344
};
4445

46+
// @ts-ignore
47+
public mount = () => {
48+
this.beforeMount();
49+
50+
const props = this.defineProps() as P;
51+
// @ts-ignore
52+
const wrapper: TWrapperWithStore<P, S> = mount<P>(
53+
<this.Component {...props} />,
54+
{
55+
wrappingComponent: this.WrappingComponent
56+
}
57+
);
58+
59+
this.reset();
60+
61+
wrapper.store = this.reduxStore!;
62+
63+
return wrapper;
64+
};
65+
4566
public render = () => {
4667
this.beforeMount();
4768
this.reset();
@@ -81,7 +102,7 @@ export default abstract class WrapperWithRedux<
81102
};
82103

83104
protected WrappingComponent: React.FC = ({ children }) => (
84-
<Provider store={this.store!}>{children}</Provider>
105+
<Provider store={this.reduxStore!}>{children}</Provider>
85106
);
86107

87108
protected reset() {

0 commit comments

Comments
 (0)