Skip to content

Commit c64677e

Browse files
author
Raice Hannay
committed
add support for react-testing-library
1 parent 2d7279a commit c64677e

35 files changed

+2447
-2388
lines changed

README.md

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ project requires additional functionality as part of your component test setup.
1212
The concept behind it is that you can create a single instance of the wrapper class at the top of
1313
your test file and define the defaults to use there, then in each test scenario you can reference
1414
the single instance and define the scenario-specific props/children etc. chaining the public methods,
15-
then finally calling the `mount`, `shallow` or `render` method to return the Enzyme wrapper and merged props.
15+
then finally calling the `mount`, `shallow` or `render` method (only `render` is available in the
16+
`react-testing-library` variants) to return the rendering result.
1617

1718
The scenario-specific definitions are reset each time you call `mount`, `render` or `shallow`, which
1819
will ensure it reverts back to only the defaults set at the top and prevents scenario data from leaking
1920
between tests.
2021

21-
For example:
22+
## Example
23+
### With `enzyme`
2224
```typescript jsx
2325
const component = new Wrapper(SomeComponent)
2426
.withDefaultChildren(<div className="Child" />)
@@ -44,10 +46,36 @@ describe("when testing a scenario", () => {
4446
});
4547
```
4648

49+
### With `react-testing-library`
50+
```typescript jsx
51+
const component = new Wrapper(SomeComponent)
52+
.withDefaultChildren(<div className="Child" />)
53+
.withDefaultProps({
54+
prop1: "Default value 1",
55+
prop2: "Default value 2"
56+
});
57+
58+
describe("when testing a scenario", () => {
59+
const { getByText } = component
60+
.withProps({
61+
prop1: "Scenario value 1"
62+
})
63+
.mount();
64+
65+
it("uses the scenario-specific value for prop1", () => {
66+
expect(getByText("Scenario value 1")).toBeDefined();
67+
});
68+
69+
it("uses the default value for prop2", () => {
70+
expect(getByText("Default value 2")).toBeDefined();
71+
});
72+
});
73+
```
4774

48-
The classes
49-
-----------
75+
Package contents
76+
----------------
5077

5178
- [`Wrapper`](./docs/Wrapper.md)
5279
- [`WrapperWithIntl`](./docs/WrapperWithIntl.md)
5380
- [`WrapperWithRedux`](./docs/WrapperWithRedux.md)
81+
- [Custom `react-testing-library` queries](./docs/react-testing-library/queries.md)

docs/Wrapper.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,29 @@ There's a `WrappingComponent` property on the `Wrapper` class that will automati
6262
This is very useful when testing components that require some form of context provider component to
6363
exist in the React tree.
6464

65+
### For `enzyme`
6566
```typescript jsx
6667
import * as React from "react";
67-
import { Wrapper as BaseWrapper } from "react-test-wrapper";
68+
import { Wrapper as BaseWrapper } from "react-test-wrapper/enzyme";
69+
70+
export class WrapperWithCustomStuff<
71+
C extends React.ComponentType<any>,
72+
P extends React.ComponentProps<C> = React.ComponentProps<C>
73+
> extends BaseWrapper<C, P> {
74+
protected WrappingComponent: React.FC = ({ children }) => (
75+
<SomeProviderComponent>
76+
{children}
77+
</SomeProviderComponent>
78+
);
79+
80+
// Add custom properties and methods here
81+
}
82+
```
83+
84+
### For `react-testing-library`
85+
```typescript jsx
86+
import * as React from "react";
87+
import { Wrapper as BaseWrapper } from "react-test-wrapper/react-testing-library";
6888

6989
export class WrapperWithCustomStuff<
7090
C extends React.ComponentType<any>,
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
Custom `react-testing-library` queries
2+
======================================
3+
4+
Because this functionality is missing by default and is still useful, the following custom queries
5+
are provided.
6+
7+
## Finding by `id`
8+
- `getById`
9+
- `getAllById`
10+
- `findById`
11+
- `findAllById`
12+
- `queryById`
13+
- `queryAllById`
14+
15+
## Finding by `className`
16+
- `getByClassName`
17+
- `getAllByClassName`
18+
- `findByClassName`
19+
- `findAllByClassName`
20+
- `queryByClassName`
21+
- `queryAllByClassName`
22+
23+
## Finding by CSS selector
24+
- `getBySelector`
25+
- `getAllBySelector`
26+
- `findBySelector`
27+
- `findAllBySelector`
28+
- `queryBySelector`
29+
- `queryAllBySelector`
30+
31+
32+
## Usage
33+
### Via the return value of `.render()`
34+
The internals of all of the `Wrapper` classes integrate with the `render` function provided by
35+
`react-testing-library` to include the custom queries to be returned along with everything else that's
36+
usually returned there (such as their existing query functions).
37+
```typescript
38+
import { Wrapper } from "react-test-wrapper/react-testing-library";
39+
40+
const component = new Wrapper(SomeComponent);
41+
42+
describe("when testing a scenario", () => {
43+
const { getByClassName } = component.render();
44+
45+
it("renders button A", () => {
46+
expect(getByClassName("SomeComponent--buttonA")).toBeDefined();
47+
});
48+
49+
it("doesn't render button B", () => {
50+
expect(getByClassName("SomeComponent--buttonB")).toBeUndefined();
51+
});
52+
});
53+
```
54+
55+
### Via the custom `screen` provided by this package
56+
If you want to use `screen`, just import the one from this package instead of their one.
57+
58+
```typescript
59+
import { screen, Wrapper } from "react-test-wrapper/react-testing-library";
60+
61+
const component = new Wrapper(SomeComponent);
62+
63+
describe("when testing a scenario", () => {
64+
component.render();
65+
66+
it("renders button A", () => {
67+
expect(screen.getByClassName("SomeComponent--buttonA")).toBeDefined();
68+
});
69+
70+
it("doesn't render button B", () => {
71+
expect(screen.getByClassName("SomeComponent--buttonB")).toBeUndefined();
72+
});
73+
});
74+
```

jest.setup.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1+
import "@testing-library/react/dont-cleanup-after-each";
2+
3+
import { configure as configureRTL } from "@testing-library/react";
14
import EnzymeAdapter from "@wojtekmaj/enzyme-adapter-react-17";
2-
import { configure } from "enzyme";
5+
import { configure as configureEnzyme } from "enzyme";
6+
7+
configureEnzyme({ adapter: new EnzymeAdapter() });
38

4-
configure({ adapter: new EnzymeAdapter() });
9+
configureRTL({
10+
testIdAttribute: "data-automationid",
11+
});

package.json

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
"author": "Raice Hannay <voodoocreation@gmail.com>",
44
"description": "A set of classes to make setting up React components for unit tests easy.",
55
"license": "ISC",
6-
"version": "2.1.1",
6+
"version": "3.0.0",
77
"keywords": [
88
"component",
99
"enzyme",
10+
"react-testing-library",
1011
"jest",
1112
"react",
1213
"react-intl",
@@ -28,9 +29,9 @@
2829
"format": "prettier --write \"**/*.{js,jsx,json,ts,tsx}\"",
2930
"lint": "eslint \"./src/**/*.ts?(x)\"",
3031
"lint:fix": "eslint \"./src/**/*.ts?(x)\" --fix",
31-
"test": "cross-env NODE_ENV=test jest --no-cache --config ./jest.config.js",
32+
"test": "cross-env NODE_ENV=test jest --no-cache --runInBand --config ./jest.config.js",
3233
"test:all": "npm-run-all format typecheck lint:fix test:coverage",
33-
"test:coverage": "cross-env NODE_ENV=test jest --no-cache --coverage --config ./jest.config.js",
34+
"test:coverage": "cross-env NODE_ENV=test jest --no-cache --runInBand --coverage --config ./jest.config.js",
3435
"typecheck": "tsc"
3536
},
3637
"prepublish": "tsc",
@@ -44,51 +45,60 @@
4445
"homepage": "https://github.com/voodoocreation/react-test-wrapper#readme",
4546
"types": "dist/index.d.ts",
4647
"peerDependencies": {
48+
"@testing-library/react": ">= 12.0.0",
4749
"enzyme": ">= 3.11.0",
4850
"react": ">= 17.0.2",
4951
"react-intl": ">= 5.17.5",
5052
"react-redux": ">= 7.2.4",
5153
"redux": ">= 4.1.0"
5254
},
5355
"peerDependenciesMeta": {
56+
"enzyme": {
57+
"optional": true
58+
},
5459
"react-intl": {
5560
"optional": true
5661
},
5762
"react-redux": {
5863
"optional": true
5964
},
65+
"@testing-library/react": {
66+
"optional": true
67+
},
6068
"redux": {
6169
"optional": true
6270
}
6371
},
6472
"devDependencies": {
65-
"@types/enzyme": "^3.10.8",
66-
"@types/jest": "^26.0.23",
67-
"@types/react": "^17.0.5",
68-
"@types/react-redux": "^7.1.16",
69-
"@typescript-eslint/eslint-plugin": "^4.23.0",
70-
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.1",
73+
"@testing-library/react": "^12.0.0",
74+
"@types/enzyme": "^3.10.9",
75+
"@types/jest": "^26.0.24",
76+
"@types/react": "^17.0.14",
77+
"@types/react-redux": "^7.1.17",
78+
"@typescript-eslint/eslint-plugin": "^4.28.2",
79+
"@typescript-eslint/parser": "^4.28.2",
80+
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.2",
7181
"cross-env": "^7.0.3",
7282
"enzyme": "^3.11.0",
7383
"enzyme-to-json": "^3.6.2",
74-
"eslint": "^7.26.0",
84+
"eslint": "^7.30.0",
7585
"eslint-config-voodoocreation": "^2.0.1",
76-
"eslint-plugin-import": "^2.22.1",
86+
"eslint-plugin-import": "^2.23.4",
7787
"eslint-plugin-jest": "^24.3.6",
7888
"eslint-plugin-jsx-a11y": "^6.4.1",
7989
"eslint-plugin-prefer-arrow": "^1.2.3",
80-
"eslint-plugin-react": "^7.23.2",
90+
"eslint-plugin-react": "^7.24.0",
8191
"eslint-plugin-react-hooks": "^4.2.0",
82-
"jest": "^26.6.3",
92+
"jest": "^27.0.6",
8393
"npm-run-all": "^4.1.5",
84-
"prettier": "^2.3.0",
94+
"prettier": "^2.3.2",
8595
"react": "^17.0.2",
8696
"react-dom": "^17.0.2",
87-
"react-intl": "^5.17.5",
97+
"react-intl": "^5.20.4",
8898
"react-redux": "^7.2.4",
8999
"redux": "^4.1.0",
90-
"ts-jest": "^26.5.6",
91-
"typescript": "^4.2.4",
100+
"ts-jest": "^27.0.3",
101+
"typescript": "^4.3.5",
92102
"typescript-fsa": "^3.0.0",
93103
"typescript-fsa-reducers": "^1.2.2"
94104
},

src/__snapshots__/WrapperWithRedux.test.tsx.snap

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ReactWrapper, ShallowWrapper } from "enzyme";
22
import * as React from "react";
33

4-
import { Dummy } from "../test/Dummy";
4+
import { Dummy } from "../../test/Dummy";
55
import Wrapper from "./Wrapper";
66

77
describe("Wrapper", () => {
@@ -18,7 +18,7 @@ describe("Wrapper", () => {
1818
});
1919

2020
it("has the correct root node", () => {
21-
expect(wrapper.instance()).toBeInstanceOf(Dummy);
21+
expect(wrapper.hasClass("Dummy")).toBe(true);
2222
});
2323

2424
it("matches snapshot", () => {
@@ -33,10 +33,6 @@ describe("Wrapper", () => {
3333
expect(wrapper).toBeInstanceOf(ReactWrapper);
3434
});
3535

36-
it("has the correct root node", () => {
37-
expect(wrapper.instance()).toBeInstanceOf(Dummy);
38-
});
39-
4036
it("matches snapshot", () => {
4137
expect(wrapper).toMatchSnapshot();
4238
});
File renamed without changes.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { IntlDummy } from "../test/IntlDummy";
2-
import Wrapper, { messages } from "../test/TestWrapperWithIntl";
1+
import Wrapper, { messages } from "../../test/enzyme/TestWrapperWithIntl";
2+
import { IntlDummy } from "../../test/IntlDummy";
33

44
describe("WrapperWithIntl", () => {
55
const component = new Wrapper(IntlDummy).withDefaultProps({

0 commit comments

Comments
 (0)