Skip to content

Commit

Permalink
implement beforeMount method
Browse files Browse the repository at this point in the history
  • Loading branch information
Raice Hannay committed Dec 12, 2019
1 parent 421bf64 commit 30fcaa1
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 77 deletions.
10 changes: 10 additions & 0 deletions docs/Wrapper.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ extend this one, so all methods defined on this class are also available on the

As with all of these classes, you can extend it to implement your own additional functionality.


Protected abstract methods to define when extending
---------------------------------------------------

### `beforeMount`
This method is called before `mount`, `render` or `shallow` are called. The intention is to use this
when defining any instance properties that need to be passed as props in your `WrappingComponent`,
such as the Redux store instance (see [`WrapperWithRedux`](./WrapperWithRedux.md) for example).


Public read-only properties
---------------------------

Expand Down
1 change: 0 additions & 1 deletion docs/WrapperWithRedux.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ How to extend for use in your project

```typescript jsx
import * as React from "react";
import { IntlConfig } from "react-intl";
import { WrapperWithRedux as BaseWrapper } from "react-test-wrapper";

import { createStore, TStoreState } from "../store";
Expand Down
4 changes: 2 additions & 2 deletions 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.5",
"version": "1.0.6",
"keywords": [
"component",
"enzyme",
Expand Down Expand Up @@ -87,6 +87,6 @@
"typescript-fsa-reducers": "^1.2.1"
},
"dependencies": {
"ts-deepmerge": "^1.0.0"
"ts-deepmerge": "^1.0.2"
}
}
10 changes: 10 additions & 0 deletions src/Wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export default class Wrapper<
};

public mount = () => {
this.beforeMount();

const props = this.defineProps() as P;
const wrapper = mount<C>(<this.Component {...props} />, {
wrappingComponent: this.WrappingComponent
Expand All @@ -62,6 +64,8 @@ export default class Wrapper<
};

public render = () => {
this.beforeMount();

const props = this.defineProps() as P;
const wrapper = render(
this.WrappingComponent ? (
Expand All @@ -79,6 +83,8 @@ export default class Wrapper<
};

public shallow = () => {
this.beforeMount();

const props = this.defineProps() as P;
const wrapper = shallow(
this.WrappingComponent ? (
Expand All @@ -95,6 +101,10 @@ export default class Wrapper<
return wrapper;
};

protected beforeMount = () => {
// Implement this method when extending to define properties to pass to `WrappingComponent`
};

protected defineProps = () => {
this.mergedProps = merge(this.defaultProps, this.scenarioProps, {
children: this.scenarioChildren || this.defaultChildren
Expand Down
18 changes: 1 addition & 17 deletions src/WrapperWithIntl.test.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
import * as React from "react";
import { IntlConfig } from "react-intl";

import { IntlDummy } from "../test/IntlDummy";
import WrapperWithIntl from "./WrapperWithIntl";

const messages = {
BUTTON: "Button"
};

class Wrapper<
C extends React.ComponentType<any>,
P extends React.ComponentProps<C> = React.ComponentProps<C>
> extends WrapperWithIntl<C, P> {
protected intlProviderProps: Partial<IntlConfig> = {
messages
};
}
import Wrapper, { messages } from "../test/TestWrapperWithIntl";

describe("WrapperWithIntl", () => {
const component = new Wrapper(IntlDummy).withDefaultProps({
Expand Down
74 changes: 25 additions & 49 deletions src/WrapperWithRedux.test.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,21 @@
import { ReactWrapper } from "enzyme";
import * as React from "react";
import { DeepPartial, Middleware } from "redux";

import * as actions from "../test/actions";
import { ConnectedDummy } from "../test/Dummy";
import { createStore, TStoreState } from "../test/store";
import WrapperWithRedux from "./WrapperWithRedux";

class Wrapper<
C extends React.ComponentType<any>,
S extends {} = TStoreState,
P extends React.ComponentProps<C> = React.ComponentProps<C>
> extends WrapperWithRedux<C, S, P> {
protected createStore(
initialState: DeepPartial<S>,
middlewares: Middleware[]
) {
return createStore(initialState, middlewares);
import Wrapper from "../test/TestWrapperWithRedux";

const initialState = {
test: {
value: "Default value"
}
}
};

const component = new Wrapper(ConnectedDummy).withDefaultReduxState(
initialState
);

describe("WrapperWithRedux", () => {
describe("when using the different render methods", () => {
const component = new Wrapper(ConnectedDummy).withDefaultReduxState({
test: {
value: "Default value"
}
});

describe("when using 'shallow'", () => {
it("throws an error", () => {
expect(() => component.shallow()).toThrowError();
Expand Down Expand Up @@ -58,12 +46,6 @@ describe("WrapperWithRedux", () => {
});

describe("when using the reduxState API", () => {
const component = new Wrapper(ConnectedDummy).withDefaultReduxState({
test: {
value: "Default value"
}
});

it("mounts with default reduxState correctly", () => {
const wrapper = component.mount();

Expand All @@ -90,13 +72,16 @@ describe("WrapperWithRedux", () => {
});

describe("when using the reduxHistory API", () => {
const component = new Wrapper(ConnectedDummy);
const wrapper = component.mount();

it("starts with an empty history", () => {
expect(component.reduxHistory).toEqual([]);
});

it("renders the correct value", () => {
expect(wrapper.find(".Dummy--value").text()).toBe("Default value");
});

it("clicks the button", () => {
wrapper.find(".Dummy--button").simulate("click");
});
Expand All @@ -110,6 +95,10 @@ describe("WrapperWithRedux", () => {
expect(matchingActions[0].payload).toBe("Click");
});

it("renders the correct value", () => {
expect(wrapper.find(".Dummy--value").text()).toBe("Click");
});

it("clicks the button again", () => {
wrapper.find(".Dummy--button").simulate("click");
});
Expand Down Expand Up @@ -156,27 +145,19 @@ describe("WrapperWithRedux", () => {
describe("when accessing the store", () => {
let wrapper: ReactWrapper<typeof ConnectedDummy>;
const payload = "Dispatched value";
const state = {
test: {
value: "Default value"
}
};
const component = new Wrapper(ConnectedDummy).withDefaultReduxState(state);

it("doesn't have the store defined before mounting", () => {
expect(component.store).toBeUndefined();
});

it("mounts the component", () => {
wrapper = component.mount();
});

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

it("has the expected state in the store", () => {
expect(component.store?.getState()).toEqual(state);
it("renders the default value", () => {
expect(wrapper.find(".Dummy--value").text()).toBe(
initialState.test.value
);
});

it("dispatches an action", () => {
Expand All @@ -198,12 +179,7 @@ describe("WrapperWithRedux", () => {
});

it("renders the new value", () => {
expect(
wrapper
.update()
.find(".Dummy--value")
.text()
).toBe(payload);
expect(wrapper.find(".Dummy--value").text()).toBe(payload);
});
});
});
8 changes: 4 additions & 4 deletions src/WrapperWithRedux.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export default abstract class WrapperWithRedux<
};

public render = () => {
this.beforeMount();
this.reset();

throw new Error(
Expand All @@ -51,6 +52,7 @@ export default abstract class WrapperWithRedux<
};

public shallow = () => {
this.beforeMount();
this.reset();

throw new Error(
Expand All @@ -67,12 +69,10 @@ export default abstract class WrapperWithRedux<
middlewares: Middleware[]
): Store;

protected defineStore = () => {
protected beforeMount = () => {
this.reduxStore = this.createStore(this.mergedReduxState, [
this.reduxHistoryMiddleware
]);

return this.reduxStore;
};

protected reduxHistoryMiddleware: Middleware = () => next => action => {
Expand All @@ -81,7 +81,7 @@ export default abstract class WrapperWithRedux<
};

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

protected reset() {
Expand Down
17 changes: 17 additions & 0 deletions test/TestWrapperWithIntl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as React from "react";
import { IntlConfig } from "react-intl";

import WrapperWithIntl from "../src/WrapperWithIntl";

export const messages = {
BUTTON: "Button"
};

export default class TestWrapperWithIntl<
C extends React.ComponentType<any>,
P extends React.ComponentProps<C> = React.ComponentProps<C>
> extends WrapperWithIntl<C, P> {
protected intlProviderProps: Partial<IntlConfig> = {
messages
};
}
18 changes: 18 additions & 0 deletions test/TestWrapperWithRedux.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from "react";
import { DeepPartial, Middleware } from "redux";

import WrapperWithRedux from "../src/WrapperWithRedux";
import { createStore, TStoreState } from "./store";

export default class TestWrapperWithRedux<
C extends React.ComponentType<any>,
S extends {} = TStoreState,
P extends React.ComponentProps<C> = React.ComponentProps<C>
> extends WrapperWithRedux<C, S, P> {
protected createStore(
initialState: DeepPartial<S>,
middlewares: Middleware[]
) {
return createStore(initialState, middlewares);
}
}
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4088,10 +4088,10 @@ tr46@^1.0.1:
dependencies:
punycode "^2.1.0"

ts-deepmerge@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ts-deepmerge/-/ts-deepmerge-1.0.0.tgz#f068b4ffc547fa67124d46f6b89f3a4f15a9bd61"
integrity sha512-ExxHq1g8SptwuDLYiW5yFtk6DyNIZ4pOeSRwE38VffDJAMUk51yD/Jn8j7AsPVhY4rfeajYi2+i8r9r2nVDTRA==
ts-deepmerge@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/ts-deepmerge/-/ts-deepmerge-1.0.2.tgz#28d0799dadb62cfa1eb557e7b72929ce07109f99"
integrity sha512-FKzWi+9FFueqdDuhtxYyAHlUyFbmBi09tQQvlG5PvR0NmD745DMnpiAzZZVShwFnBdir5e1gz+wwPKTykMKkKg==

ts-jest@^24.2.0:
version "24.2.0"
Expand Down

0 comments on commit 30fcaa1

Please sign in to comment.