Testing
FrontHub already brings all the test environments set up and ready to develop. The front-hub-commons
dependency brings Jest and Testing Library React as default test runners.
When you create a new app with front-hub-cli
the created App comes with a Welcome
component. This component comes with a test boilerplate file (Welcome.test.js
).
import { render, screen } from '@testing-library/react'
import Welcome from './Welcome'
it('should render title', () => {
render(<Welcome />)
expect(screen.getByRole('heading')).toBeInTheDocument()
})
Testing localization
FrontHub brings the renderWithTranslation
utility function. This allows us to test components using react-i18next. See the example below:
import { screen } from '@testing-library/react'
import {
instanceMock,
renderWithTranslation,
} from '@resultadosdigitais/front-hub/react/jest'
import MyComponent from './MyComponent'
import translation from './locales/pt-BR.json'
describe('when rendering my component', () => {
it('should show the hello message', async () => {
await renderWithTranslation(instanceMock(<MyComponent />, translation)
expect(screen.getByText('Olá!')).toBeInTheDocument()
})
})
Caveats
If your micro frontend wasn't created by using the front-hub-cli
, you'll need to create a setup test file.
There are two different ways to create the setup test file.
Application created with Create React App
If your application was created with Create React App you'll need to create a setupTests.js
file in the micro frontend folder, and call the setup
method from the FrontHub as shown below.
import '@testing-library/jest-dom/extend-expect'
import { setup } from '@resultadosdigitais/front-hub/react/jest'
import 'jest-styled-components'
import fronthubConfig from '../front-hub.config'
setup(fronthubConfig)
Application not created with Create React App
If you didn't create your application with Create React App you'll need to create a configure jest.config.js
file by using the Jest configuration.
const { setup } = require('@resultadosdigitais/front-hub/react/jest')
setup(require('../front-hub.config.js'))
Wrapping your components with your custom render (React Testing Library)
Some times you'll need to include some things provided by the FrontHub in the render method like global context, providers, stores, etc. As React Testing Library advice, you can create your custom render method by re-exporting everything from React Testing Library. This way you can use your custom RTL from all your imports.
See the below example:
import {
renderWithTranslation as customRenderWithTranslation,
useMock,
withMock,
} from '@resultadosdigitais/front-hub/react/jest'
import { render as customRender } from '@testing-library/react'
export * from '@testing-library/react'
export const render = (comp, config) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
return customRender(useMock(comp, config))
}
export const renderWithTranslation = async (comp, config, translation) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
return customRenderWithTranslation(useMock(comp, config), translation)
}
withMock
and instanceMock
Sometimes when you use some advanced feature provided by FrontHub such as useFeature
, renderWithTranslation
, withHostContext
, or any other, you'll need to mock such features in an easy and quick way in your tests. That´s where withMock
and instanceMock
come into the picture.
instanceMock
You can use instanceMock
when you need to mock some feature in a specific spec, that is, you don't need to reuse your mock in other specs.
Example:
import React from 'react';
import { useTranslation } from 'react-i18next';
export default const Posts = ({ posts }) => {
const { t } = useTranslation();
return (
<Posts>
<h1>{t('postsTitle')}</h1>
{
posts.length > 0 && (
<ul>
{
posts.map(post => <li key={post.id}>{post.title}</li>)
}
</ul>
)
}
</Posts>
)
}
import React from 'react'
import { render } from '@testing-library/react'
import {
instanceMock,
renderWithTranslation,
} from '@resultadosdigitais/front-hub/react/jest'
import Posts from '.'
const mockPosts = [
{ id: 1, title: 'Post title one' },
{ id: 2, title: 'Post title two' },
]
describe('Posts', () => {
it('should render a post with title "post title one"', () => {
const { getByText } = render(
renderWithTranslation(instanceMock(<Posts posts={mockPosts} />)),
)
expect(getByText(/post title one/i)).toBeInTheDocument()
})
})
withMock
You can use withMock
when you need to reuse your mock in more than one spec, you need a reusable mock.
import React from 'react'
import { render } from '@testing-library/react'
import {
withMock,
renderWithTranslation,
} from '@resultadosdigitais/front-hub/react/jest'
import Posts from '.'
const mockPosts = [
{ id: 1, title: 'Post title one' },
{ id: 2, title: 'Post title two' },
]
const frontHubPosts = withMock(Posts)
describe('Posts', () => {
it('should render a post with title "post title one"', () => {
const { getByText } = render(
renderWithTranslation(<fronHubPosts posts={mockPosts} />),
)
expect(getByText(/post title one/i)).toBeInTheDocument()
})
it('should render a post with title "post title two"', () => {
const { getByText } = render(
renderWithTranslation(<fronHubPosts posts={mockPosts} />),
)
expect(getByText(/post title two/i)).toBeInTheDocument()
})
})
renderWithFrontHub
You can use renderWithFrontHub
to render a component wrapped by the basic FrontHub context.
The renderWithFrontHub
function doesn't make localization and communication features available to the rendered component. Use renderWithTranslation
and renderWithCommunication
when you need to test these features.
import logo from './logo.png'
import { Image } from '@resultadosdigitais/front-hub/react'
const Logo = () => {
return <Image alt="My company logo" src={logo} />
}
export default Logo
import React from 'react'
import { renderWithFrontHub } from '@resultadosdigitais/front-hub/react/jest'
import Logo from './Logo'
describe('Logo', () => {
it('should render a image with alt text "My company logo"', () => {
const { getByRole } = renderWithFrontHub(<Logo />)
const logo = getByRole('img')
expect(logo).toHaveAttribute('alt', 'My company logo')
})
})