@gpx/render-composer
v3.2.0
Published
Create complex renders for react-testing-library
Readme
The problem
When working with Testing Library within a large project often you need to wrap your component in several providers:
const history = createMemoryHistory();
const locale = 'en';
const user = {name: 'Giorgio'};
render(
<Router history={history}>
<IntlProvider locale={locale}>
<UserContext.Provider value={user}>
<MyComponent />
</UserContext.Provider>
</IntlProvider>
</Router>,
);This can lead to a lot of overhead and is not very flexible.
The solution
Render Composer allows you to declare reusable and configurable wraps that define a single provider. These wraps can then be combined to generate more complex hierarchies.
const RouterWrap = wrap((children, {history}) => (
<Router history={history}>{children}</Router>
)).defaultData(() => ({
history: createMemoryHistory(),
}));
const IntlWrap = wrap((children, {locale}) => (
<IntlProvider locale={locale}>{children}</IntlProvider>
)).defaultData({locale: 'en'});
const UserWrap = wrap((children, {user}) => (
<UserContext.Provider value={user}>{children}</UserContext.Provider>
)).defaultData({user: {name: 'Giorgio'}});
const appRender = RouterWrap.wraps(IntlWrap)
.wraps(UserWrap)
.withRenderMethod(render);
appRender(<MyComponent />);Installation
With NPM:
npm install @gpx/render-composer --save-devWith Yarn:
yarn add @gpx/render-composer --devNow simply import it in your tests:
import wrap from '@gpx/render-composer';
// or
var wrap = require('@gpx/render-composer');Usage
You can create a wrap with the wrap method:
const Wrap = wrap((children, data) => <div>{children}</div>);data is an empty object by default. You can set some default values with defaultData:
Wrap.defaultData({foo: 'bar'});If you need the data to be generated every time rather than be static you can also
pass a function to defaultData:
Wrap.defaultData(() => ({foo: Math.random()}));You can compose the wraps with the wraps method. You can chain as many wraps you want:
WrapA.wraps(WrapB)
.wraps(WrapC)
.wraps(WrapD);Once you are satisfied with your wrap you can get a render method with withRenderMethod:
import {render} from '@testing-library/react';
const renderWrap = Wrap.withRenderMethod(render);
renderWrap(<MyComponent />);The generated render method will also accept data to overwrite the default values you defined in your wraps. The data will be returned too:
Wrap.defaultData(() => ({foo: 'bar'}));
// This `foo` will have value `'bar'`
const {foo} = renderWrap(<MyComponent />);
// This `foo` will have value `'baz'`
const {foo} = renderWrap(<MyComponent />, {foo: 'baz'});Note that wraps are immutable so that they can be defined in one file and exported and combined.
