react-mock-hoc-utils
v1.0.1
Published
"A Higher-Order-Component mocking tool that allows for mocking any component that is wrapped by one or more HOCs - additionally, supporting prop injection on a per-hoc-basis. Is built for React and Jest.
Downloads
22
Maintainers
Readme
React Mock HOC Utilities
This package of Higher-Order-Component utilities contain the following:
This library mixes well with the test-component-builder, to allow for easy to setup tests
Mock Hoc
A Higher-Order-Component mocking tool that allows for mocking any component that is wrapped by one or more HOCs - additionally, supporting prop injection on a per-hoc-basis. Is built for React and Jest.
To install run npm install react-mock-hoc-utils
The control of this tool goes through a single function called constructMockHoc
. This function returns a MockHoc
object, that is used to construct a mocked higher-order-component enviroment around a component.
It functions just like a regular hoc mock, using jest.doMock
, passing in the paths and injected props and finally does a require
of the wrapped component. Only it handles all of this behind the scenes, and structures it in a much nicer, and automated format.
Here is an example of a component that is wrapped by 3 different higher order components - where 2 of them inject props into the component, and 1 does not:
import constructMockHoc from "react-mock-hoc-utils";
const MyWrappedComponent = constructMockHoc("../MyWrappedComponent.js")
.mock("../HigherOrderComponent__1.js")
.with({ hoc1: "bob" })
.mock("../HigherOrderComponent__2.js")
.mock("../HigherOrderComponent__3.js")
.with({ anotherProp: "flower" })
.create();
const mockedWrappedComponent = shallow(<MyWrappedComponent />)
.dive()
.dive()
.dive();
Would result in getting your wrapped component, with the injected props: {hoc1: "bob", anotherProp: "flower"}
There is a lot going on here, so here is a break down of the MockHoc
object and all of its functions.
Description
The object uses a chained method design. Where the functions return the object, allowing for chaining multiple calls, as shown in the example above
constructMockHoc
const MyWrappedComponent = constructMockHoc("../MyWrappedComponent.js", __dirname, false);
As mentioned this function simply creates a new MockHoc
object -
the parameters it takes, is as follows:
| Parameter | Type | Description |
| -------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| wrappedComponentPath
| string | Is the path to the wrapped component, *usually relative to the file that constructs the MockHoc
. |
| origin
(optional) | string | Sets the starting point in which to base the wrappedComponentPath
on. If you do not specify a trailing "/", then the object will add it for you automatically |
| clearOnCreation
(optional) | bool | the default value is true: if set to true, it will call jest.resetModules()
before construction the MockHoc
. This is normally true, due to the nature of unit tests |
- The reason it is usually relative to the file, is because as shown, you can pass in your own starting point (
origin
), but if you do not pass in an origin; then the object will automatically attempt to figure out the origin based on what file called theconstructMockHoc
function.
mock
constructMockHoc(/*...*/).mock(
"../HigherOrderComponent.js",
"#uc",
(path, method) => jest.doMock(path, () => method))
);
| Parameters | Type | Description |
| ------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| path
| string | Is the path to the higher-order-component, if this is not defined, then the object will throw an error, relative to the origin specified in constructMockHoc
|
| methodName
(optional) | string | is the name of the exported method, within the file specified in path. This parameter has two automated formats. if the following strings are typed in: "#uc"
or "#lc"
, then it will try and parse the file name from path, and then format: - "#uc"
: start with an upper-case letter - "#lc"
: starts with a lower-case letter If nothing is passed in, then it will assume that the file does not have a sub object, and instead return the pure object. This can happen in later versions of React, where if export default
, then it will not contain any sub objects - whereas, in previous versions, the sub object will simply be called default
.If this is the case, then you can quite simply write default as the method name side-note: If you're relying on a later version of react, then consider using createPure
instead of create
if the exports are default |
| contextModuleMethod
(optional) | function | by default, this value is set to use jest.doMock
internally. This is fine for cases where custom higher order components are used. However, when you have to mock another installed module, you will have to provide your own method. This method can be the exact same as shown in the snippet above. The reason for this limitation, is because the react-moc-hoc-utils
module does not know of the existence of the other installed modules. Using your own method however works, because then the scope of the mock is in your project, whereas otherwise it would be within the react-moc-hoc-utils
package |
with
The with functions relative to the last mock
. So if you call an mock
followed by a with
, then the props passed into that with
will be injected into the wrapped component through that mock
.
Generally, you just need to remember that if you desire to mock a HOC, and that HOC injects props into the wrapped component, then you do one mock
specificing the HOC, followed by a with
, specifying what props that HOC should inject.
Additionally, you can nest with
's, and it will just merge the the props and add them to the last mock
. There is no use for this behaviour, but it exists as a by-product of the chained function design.
/*...*/.mock(/*...*/).with({injectedProp: "MUAHAHA"})
| Parameters | Type | Description | | ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | injectedProps | object | This is simply an object that is to be injected into wrapped component. Using this, it means that a prop called injectedProp with the value "MUAHAHA" can be found in the wrapped component's prop object |
create
The create
method is the only thing that does not return itself, but instead, it returns the desired export of the WrappedComponent file path. Because of that, this is the method you call when you have nothing left to chain, and it is ready to formulate the mocked Wrapped Component
/*...*/.mock(/*...*/).create("default");
| Parameters | Type | Description |
| --------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| target (optional) | string | is used to fetch a specific export within the wrapped pomponent path
(the path provided in the constructMockHoc
). By default it is set to the default
export |
createPure
The createPure
is a simplified version of the regular create
function, where it mocks the component and does a simple require
. Whereas, create
, does the same, only it also auto extracts the export
method of your choice from the required file
/*...*/.mock(/*...*/).createPure();
This may be desirable, if the mocked component does not contain a default
export, or any other export object for that matter.
Diving Utilities
There are multiple shallow diving methods available in this utility - they are as follows:
Each of one of them take in a shallow
component as their first parameter. Meaning that for it to function, you have to pass in a shallow
object by Enzyme. The reason for it is because of the diving method inside the shallow
object. Each one returns a shallow
object back in respect to the amount of dives it did.
diveThroughComponents(shallow(<MyComponent />), [View, Text]);
| Parameters | Type | Description | | ---------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | diveTos | array [components] | Will find the component in the array, and then proceed to dive through it, repating itself until it has iterated over the entire array |
diveThroughComponent(shallow(<MyComponent />), View);
| Parameters | Type | Description | | ---------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | diveTo | object | Functions just like the previous method, only it dives through a single layer. Meaning that he will find the component and dive through it, then stop |
diveStaticAmount(shallow(<MyComponent />), 3);
| Parameters | Type | Description | | ---------- | ------ | ------------------------------------------------------------------------------------------------------------------ | | diveCount | number | Will very simply dive through the shallow component n number of times, using the first element it finds per layer) |
diveSingleToComponent(shallow(<MyComponent />), "MySwimSuitComponent");
| Parameters | Type | Description |
| ---------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| diveTarget | string | Will dive down the first element per layer, where it checks against each one for the name that matches diveTarget
. If it finds one, then return the object. |
diveThroughMockHocs(shallow(<MyComponent />));
Will attempt to dive through each of the mocked higher order components that wrap MyComponent
.
diveSingleToComponent
and diveThroughMockHocs
both have a max dive depth, of 50
by default. This can be altered by changing the value of the static property MAX_DIVES