The Testbed is a small library to help testing React components. It is most useful when testing application "sections" (or pages) in **integration**
than when unit testing single components in isolation.
## Motivation
The Elasticsearch UI team built this to support client-side integration testing. When testing complete "pages" we get to test
our application in a way that is closer to how a user would interact with it in a browser. It also gives us more confidence in
our tests and avoids testing implementation details.
We test everything up to the HTTP Requests made from the client to the Node.js API server. Those requests need to be mocked. This means that with a good
**API integration test** coverage of those endpoints, we can reduce the functional tests to a minimum.
With this in mind, we needed a way to easily mount a component on a React Router `<Route>` (this component could possibily have _child_ routes and
need access to the browser URL parameters and query params). In order to solve that, the Testbed wraps the component around a `MemoryRouter`.
On the other side, the majority of our current applications use Redux as state management so we needed a simple way to wrap our component under test
inside a redux store provider.
## How to use it
At the top of your test file (you only need to declare it once), register a new Testbed by providing a React Component and an optional configuration object.
You receive in return a function that you need to call to mount the component in your test.
**Example 1**
```ts
// remote_clusters_list.helpers.ts
import { registerTestBed } from '../../../../test_utils';
import { RemoteClusterList } from '../../app/sections/remote_cluster_list';
import { remoteClustersStore } from '../../app/store';
import routing from '../../app/services/routing';
const config = {
memoryRouter: {
onRouter(router) {
routing.registerRouter(router); // send the router instance to the routing service
},
initialEntries: ['/some-resource-name'], // the Router initial URL
componentRoutePath: '/:name' // the Component <Route/> path
The Testbed utils are meant to be used with test subjects. Test subjects are elements that are tagged specifically for selecting from tests. Use test subjects over CSS selectors when possible.
If you need to access a CSS selector, target first the closest test subject.
```ts
const text = find('containerButton').find('.link--active').text();
```
## Typescript
If you use Typescript, you can provide a string union type for your test subjects and you will get **autocomplete** on the test subjects in your test. To automate finding all the subjects on the page, use the Chrome extension below.
```ts
type TestSubjects = 'indicesTable' | 'createIndexButton' | 'pageTitle';
There is a small Chrome extension that you can install in order to track the test subject on the current page. As it is meant to be used
during development, the extension is only active when navigating a `localhost` URL.
You will find the "Test subjects finder" extension in the `x-pack/test_utils/chrome_extension` folder.
### Install the extension
- open the "extensions" window in Chrome
- activate the "Developer mode" (top right corner)
- drag and drop the `test_subjects_finder` folder on the window.
You can specify a DOM node (the tree "root") from which the test subjects will be found. If you don't specify any, the document `<body>` will be used. The output format can either be `Typescript` (to export a string union type) or `List`.
### Output
Once you start tracking the test subjects on the page, the output will be printed in the **Chrome dev console**.
## API
## `registerTestBed(Component [, testBedConfig])`
Instantiate a new TestBed to test a React component. The arguments it receives are
-`Component` (the React component to test)
-`testBedConfig` (optional). An optional Testbed configuration object.
**@returns** A function to instantiate and mount the component.
### `testBedConfig`
The `testBedConfig` has the following properties (all **optional**)
-`defaultProps` The default props to pass to the mounted component. Those props can be overriden when calling the `setup([props])` callback
-`memoryRouter` Configuration object for the react-router `MemoryRouter` with the following properties
-`wrapComponent` Flag to provide or not a `MemoryRouter`. If set to `false`, there won't be any router and the component won't be added on a `<Route />`. (default: `true`)