Skip to main content

Test Helpers: React Providers

Proposed change

Creating new helpers in libs/test-helpers to ease the usage of React Context Providers in the unit tests.

The goal is to reduce the complexity and the unstructured way of wrapping the target component (the one we really want to test) with all the necessary Providers.

Instead of rendering the Providers à la React, we will be able to do it in a more declarative way.

Note: We are already using this strategy for the IntlProvider.

How it looks now

return renderWithProviders(
<DynamicRoutingProvider parameters={{ cardId: '435h7736htug', accountId: 'dkjhwgb63xu' }}>
<AccountsContext.Provider value={{ isLoading: false, accounts: [] }}>
<CardsContext.Provider value={cardsContextValues}>
<MyComponent />
</CardsContext.Provider>
</AccountsContext.Provider>
</DynamicRoutingProvider>,
providersOptions
);

Alternative

const providersOptions = new MockProvidersOptions();
providersOptions
.withIntl(translations)
.withDynamicRouting(routeParameters)
.withContext(AccountsContext, { isLoading: false, accounts: [] })
.withContext(CardsContext, cardsContextValues);

return renderWithProviders(<MyComponent />, providersOptions);

Motivation

With all the different contexts we are using in our codebase, the code to render a test for a simple component is becoming very verbose.

The goal here is to reduce the code and complexity we have now when writing the unit tests of components. This will make our unit tests more simple and readable.

Since this is a non-breaking change, we don't need to update all our codebase right after the change is merged (even though it's recommended we do it as soon as possible).

Proposed transition strategy

This change won't affect the existing code (it's not a breaking change).

The only thing we need to do, to make our code compliant with this change, is updating our tests that are currently using Context Providers (I think almost all of them are using at least one provider).

How to update the existing code

DynamicRoutingProvider

The places using DynamicRoutingProvider can be updated to call the withDynamicRouting(parameters, navigateTo) function.

Before

return render(
<DynamicRoutingProvider parameters={{ cardId: '435h7736htug', accountId: 'dkjhwgb63xu', navigateTo: myMockFunction }}>
<MyComponent />
</DynamicRoutingProvider>
);

After

const providersOptions = new MockProvidersOptions();
providersOptions.withDynamicRouting({ cardId: '435h7736htug', accountId: 'dkjhwgb63xu' }, myMockFunction);

return renderWithProviders(<MyComponent />, providersOptions);

Other Providers

All the other Providers can be updated to use the generic context withContext(context, contextValue).

Before

return render(
<SomeContext.Provider value={{ data: [], isLoading: true }}>
<MyComponent />
</SomeContext.Provider>
);

After

const providersOptions = new MockProvidersOptions();
providersOptions.withContext(SomeContext, { data: [], isLoading: true });

return renderWithProviders(<MyComponent />, providersOptions);