Provider Wrapping with Souvlaki

Provider Wrapping with Souvlaki

Souvlaki is a tool made by Thoughtworker Cam Jackson that greatly simplifies the process of wrapping components inside unit tests.
Normally, when you render a components inside a test, you’ll need lots of state in order for it to function. This might be a login store, some existing navigation or even a dark/light mode theme.
Souvlaki makes this repetitive code waay more reusable and shortens the amount of boiler plate
 
 
The Old Way:
const { getByText } = render( <ThemeProvider> <Provider store={store}> <Context.Provider language={'english'}> <SomeComponent {...props} /> </Context.Provider> </Provider> </ThemeProvider> );
The New Way:
const { getByText } = render( <SomeComponent {...props} />, { wrapper: wrap( withTheme(), withStore(), withContext({ language: 'english' })), ), }, );
 

Install Souvlaki

yarn add -D souvlaki
npm i -D souvlaki
 

Create a Helper

Create a new file named with<x>
import { createHelper } from 'souvlaki'; export const withTheme = createHelper((chosenTheme) => ({ children }) => ( <Theme.Provider value={chosenTheme}> {children} </Theme.Provider> ));
This is where you’d traditionally wrap a provider around the component, but now we just wrap the children and call it a day

Wrap Test Component

import { withTheme } from './themeWrapper' it('excellent test name', () => { const theme = { darkMode: true, background: 'black' } const { getByText } = render( <SomeComponent />, { wrapper: wrap( withTheme(theme) ) } ); }; expect(getByText('something').toBeDefined()
 

Default Provider

Add a builder to the helper so you always have default data in the provider, but make sure this can be overridden
 
Create a builder in a new file (Or in the helper if you want):
export const themeBuilder = (overrides) => ({ darkMode: true, background: 'black', ...overrides })
 
Import the builder and add to the createHelper props
import { createHelper } from 'souvlaki'; import { themeBuilder } from './themeBuilder' export const withTheme = createHelper((chosenTheme = themeBuilder()) => ({ children }) => ( <Theme.Provider value={chosenTheme}> {children} </Theme.Provider> ));
This will now always use dark mode as a default to the provider, meaning withTheme() is good enough for the wrapper
See what I mean:
it('excellent test name', () => { const { getByText } = render( <SomeComponent />, { wrapper: wrap( withTheme() ) } ); };
 
Then to override, simply pass in a new theme
const theme = { darkMode: false, background: 'white' } const { getByText } = render( <SomeComponent />, { wrapper: wrap( withTheme(theme) ) } );
 

Guides and practical notes, training references, and code snippets shared freely for learning and career growth.