How to do it...

We can use snapshot testing for all of our components, but it's more interesting for those whose output varies in terms of their props, so different behaviors are to be expected. We will be using a different way of rendering: instead of producing HTML elements, we'll use renderers that produce text output that can be stored and compared in a easy way.

First, the simplest cases are for components with a standard, fixed kind of output. We have some examples of that: for our <ClicksDisplay> component, the test would be written as follows:

// Source file: src/counterApp/clicksDisplay.test.js

import React from "react";
import TestRenderer from "react-test-renderer";

import { ClicksDisplay } from "./";

describe("clicksDisplay", () => {
it("renders correctly", () => {
const tree = TestRenderer
.create(<ClicksDisplay clicks={22} />)
.toJSON();
expect(tree).toMatchSnapshot();
});
});

Basically, we import the special TestRenderer renderer function, use it to produce output for our component, and then compare that with the stored snapshot; we'll see how this looks soon. Tests are pretty much always the same: for our <Counter> component, the test code would be totally analog:

// Source file: src/counterApp/counter.test.js

import React from "react";
import TestRenderer from "react-test-renderer";

import { Counter } from "./counter.component";

describe("clicksDisplay", () => {
it("renders correctly", () => {
const tree = TestRenderer
.create(<Counter count={9} dispatch={() => null} />)
.toJSON();
expect(tree).toMatchSnapshot();
});
});

The differences are minimal; it's just a matter of providing the correct expected props, and nothing more. Let's move on to more interesting cases.

Should you have to render an object with prop values that cannot be predetermined (not the most likely case), you'll have to use special Property Matchers; you can read more about them at https://jestjs.io/docs/en/snapshot-testing#property-matchers.

When you have components whose output varies depending on their props, snapshot tests become more interesting because they let you verify that different results are produced as expected. With our countries and regions code, we had these kind of cases: for example, the <RegionsTable> component was expected to display a list of regions (if any were provided) or a "No regions" text (if none were available). We should write these tests, then. Let's proceed:

// Source file: src/regionsApp/regionsTable.snapshot.test.js

import React from "react";
import TestRenderer from "react-test-renderer";

import { RegionsTable } from "./regionsTable.component";

describe("RegionsTable", () => {
it("renders correctly an empty list", () => {
const tree = TestRenderer.create(<RegionsTable list={[]} />).toJSON();
expect(tree).toMatchSnapshot();
});

it("renders correctly a list", () => {
const tree = TestRenderer
.create(
<RegionsTable
list={[
{
countryCode: "UY",
regionCode: "10",
regionName: "Montevideo"
},
.
.
.
]}
/>
)
.toJSON();
expect(tree).toMatchSnapshot();
});
});

We have two distinct cases, just like we described previously: one snapshot will match the no regions case, and the other will match what's expected if some regions were given. For the <CountrySelect> component, the code would be similar:

// Source file: src/regionsApp/countrySelect.snapshot.test.js

import React from "react";
import TestRenderer from "react-test-renderer";

import { CountrySelect } from "./countrySelect.component";

describe("CountrySelect", () => {
it("renders correctly when loading, with no countries", () => {
const tree = TestRenderer
.create(
<CountrySelect
loading={true}
onSelect={() => null}
getCountries={() => null}
list={[]}
/>
)
.toJSON();
expect(tree).toMatchSnapshot();
});

it("renders correctly a countries dropdown", () => {
const tree = TestRenderer
.create(
<CountrySelect
loading={false}
onSelect={() => null}
getCountries={() => null}
list={[
{
countryCode: "UY",
countryName: "Uruguay"
},
.
.
.
]}
/>
)
.toJSON();
expect(tree).toMatchSnapshot();
});
});

So, testing components with more than one possible output isn't hard at all, and only requires you to write more than one snapshot test; a simple solution.

Finally, in order to simplify tests, when you have components that themselves have more components, using shallow rendering helps concentrate on the main, high level aspects, and leave the details of the inner components' rendering to other tests. We could whip up something like this, with an invented <CountryAndRegions> component that shows both our countries' drop-down and regions table:

// Source file: src/regionsApp/countryAndRegions.test.js

import React from "react";
import ShallowRenderer from "react-test-renderer/shallow";

import { CountrySelect } from "./countrySelect.component";
import { RegionsTable } from "./regionsTable.component";

class CountryAndRegions extends React.Component {
render() {
return (
<div>
<div>
Select:
<CountrySelect
loading={true}
onSelect={() => null}
getCountries={() => null}
list={[]}
/>
</div>
<div>
Display: <RegionsTable list={[]} />
</div>
</div>
);
}
}

describe("App for Regions and Countries", () => {
it("renders correctly", () => {
const tree = new ShallowRenderer().render(<CountryAndRegions />);
expect(tree).toMatchSnapshot();
});
});

Note that the way to use the ShallowRenderer differs from the other renderer: you must create a new object, call its .render() method, and not use .toJSON() anymore. We'll look at how this new test differs from the previous ones soon.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.148.144.228