Skip to content

Commit

Permalink
add support for react-testing-library
Browse files Browse the repository at this point in the history
  • Loading branch information
Raice Hannay committed Jul 8, 2021
1 parent 2d7279a commit c64677e
Show file tree
Hide file tree
Showing 35 changed files with 2,447 additions and 2,388 deletions.
36 changes: 32 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ project requires additional functionality as part of your component test setup.
The concept behind it is that you can create a single instance of the wrapper class at the top of
your test file and define the defaults to use there, then in each test scenario you can reference
the single instance and define the scenario-specific props/children etc. chaining the public methods,
then finally calling the `mount`, `shallow` or `render` method to return the Enzyme wrapper and merged props.
then finally calling the `mount`, `shallow` or `render` method (only `render` is available in the
`react-testing-library` variants) to return the rendering result.

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

For example:
## Example
### With `enzyme`
```typescript jsx
const component = new Wrapper(SomeComponent)
.withDefaultChildren(<div className="Child" />)
Expand All @@ -44,10 +46,36 @@ describe("when testing a scenario", () => {
});
```

### With `react-testing-library`
```typescript jsx
const component = new Wrapper(SomeComponent)
.withDefaultChildren(<div className="Child" />)
.withDefaultProps({
prop1: "Default value 1",
prop2: "Default value 2"
});

describe("when testing a scenario", () => {
const { getByText } = component
.withProps({
prop1: "Scenario value 1"
})
.mount();

it("uses the scenario-specific value for prop1", () => {
expect(getByText("Scenario value 1")).toBeDefined();
});

it("uses the default value for prop2", () => {
expect(getByText("Default value 2")).toBeDefined();
});
});
```

The classes
-----------
Package contents
----------------

- [`Wrapper`](./docs/Wrapper.md)
- [`WrapperWithIntl`](./docs/WrapperWithIntl.md)
- [`WrapperWithRedux`](./docs/WrapperWithRedux.md)
- [Custom `react-testing-library` queries](./docs/react-testing-library/queries.md)
22 changes: 21 additions & 1 deletion docs/Wrapper.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,29 @@ There's a `WrappingComponent` property on the `Wrapper` class that will automati
This is very useful when testing components that require some form of context provider component to
exist in the React tree.

### For `enzyme`
```typescript jsx
import * as React from "react";
import { Wrapper as BaseWrapper } from "react-test-wrapper";
import { Wrapper as BaseWrapper } from "react-test-wrapper/enzyme";

export class WrapperWithCustomStuff<
C extends React.ComponentType<any>,
P extends React.ComponentProps<C> = React.ComponentProps<C>
> extends BaseWrapper<C, P> {
protected WrappingComponent: React.FC = ({ children }) => (
<SomeProviderComponent>
{children}
</SomeProviderComponent>
);

// Add custom properties and methods here
}
```

### For `react-testing-library`
```typescript jsx
import * as React from "react";
import { Wrapper as BaseWrapper } from "react-test-wrapper/react-testing-library";

export class WrapperWithCustomStuff<
C extends React.ComponentType<any>,
Expand Down
74 changes: 74 additions & 0 deletions docs/react-testing-library/queries.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
Custom `react-testing-library` queries
======================================

Because this functionality is missing by default and is still useful, the following custom queries
are provided.

## Finding by `id`
- `getById`
- `getAllById`
- `findById`
- `findAllById`
- `queryById`
- `queryAllById`

## Finding by `className`
- `getByClassName`
- `getAllByClassName`
- `findByClassName`
- `findAllByClassName`
- `queryByClassName`
- `queryAllByClassName`

## Finding by CSS selector
- `getBySelector`
- `getAllBySelector`
- `findBySelector`
- `findAllBySelector`
- `queryBySelector`
- `queryAllBySelector`


## Usage
### Via the return value of `.render()`
The internals of all of the `Wrapper` classes integrate with the `render` function provided by
`react-testing-library` to include the custom queries to be returned along with everything else that's
usually returned there (such as their existing query functions).
```typescript
import { Wrapper } from "react-test-wrapper/react-testing-library";

const component = new Wrapper(SomeComponent);

describe("when testing a scenario", () => {
const { getByClassName } = component.render();

it("renders button A", () => {
expect(getByClassName("SomeComponent--buttonA")).toBeDefined();
});

it("doesn't render button B", () => {
expect(getByClassName("SomeComponent--buttonB")).toBeUndefined();
});
});
```

### Via the custom `screen` provided by this package
If you want to use `screen`, just import the one from this package instead of their one.

```typescript
import { screen, Wrapper } from "react-test-wrapper/react-testing-library";

const component = new Wrapper(SomeComponent);

describe("when testing a scenario", () => {
component.render();

it("renders button A", () => {
expect(screen.getByClassName("SomeComponent--buttonA")).toBeDefined();
});

it("doesn't render button B", () => {
expect(screen.getByClassName("SomeComponent--buttonB")).toBeUndefined();
});
});
```
11 changes: 9 additions & 2 deletions jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import "@testing-library/react/dont-cleanup-after-each";

import { configure as configureRTL } from "@testing-library/react";
import EnzymeAdapter from "@wojtekmaj/enzyme-adapter-react-17";
import { configure } from "enzyme";
import { configure as configureEnzyme } from "enzyme";

configureEnzyme({ adapter: new EnzymeAdapter() });

configure({ adapter: new EnzymeAdapter() });
configureRTL({
testIdAttribute: "data-automationid",
});
44 changes: 27 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
"author": "Raice Hannay <voodoocreation@gmail.com>",
"description": "A set of classes to make setting up React components for unit tests easy.",
"license": "ISC",
"version": "2.1.1",
"version": "3.0.0",
"keywords": [
"component",
"enzyme",
"react-testing-library",
"jest",
"react",
"react-intl",
Expand All @@ -28,9 +29,9 @@
"format": "prettier --write \"**/*.{js,jsx,json,ts,tsx}\"",
"lint": "eslint \"./src/**/*.ts?(x)\"",
"lint:fix": "eslint \"./src/**/*.ts?(x)\" --fix",
"test": "cross-env NODE_ENV=test jest --no-cache --config ./jest.config.js",
"test": "cross-env NODE_ENV=test jest --no-cache --runInBand --config ./jest.config.js",
"test:all": "npm-run-all format typecheck lint:fix test:coverage",
"test:coverage": "cross-env NODE_ENV=test jest --no-cache --coverage --config ./jest.config.js",
"test:coverage": "cross-env NODE_ENV=test jest --no-cache --runInBand --coverage --config ./jest.config.js",
"typecheck": "tsc"
},
"prepublish": "tsc",
Expand All @@ -44,51 +45,60 @@
"homepage": "https://github.com/voodoocreation/react-test-wrapper#readme",
"types": "dist/index.d.ts",
"peerDependencies": {
"@testing-library/react": ">= 12.0.0",
"enzyme": ">= 3.11.0",
"react": ">= 17.0.2",
"react-intl": ">= 5.17.5",
"react-redux": ">= 7.2.4",
"redux": ">= 4.1.0"
},
"peerDependenciesMeta": {
"enzyme": {
"optional": true
},
"react-intl": {
"optional": true
},
"react-redux": {
"optional": true
},
"@testing-library/react": {
"optional": true
},
"redux": {
"optional": true
}
},
"devDependencies": {
"@types/enzyme": "^3.10.8",
"@types/jest": "^26.0.23",
"@types/react": "^17.0.5",
"@types/react-redux": "^7.1.16",
"@typescript-eslint/eslint-plugin": "^4.23.0",
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.1",
"@testing-library/react": "^12.0.0",
"@types/enzyme": "^3.10.9",
"@types/jest": "^26.0.24",
"@types/react": "^17.0.14",
"@types/react-redux": "^7.1.17",
"@typescript-eslint/eslint-plugin": "^4.28.2",
"@typescript-eslint/parser": "^4.28.2",
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.2",
"cross-env": "^7.0.3",
"enzyme": "^3.11.0",
"enzyme-to-json": "^3.6.2",
"eslint": "^7.26.0",
"eslint": "^7.30.0",
"eslint-config-voodoocreation": "^2.0.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-jest": "^24.3.6",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-prefer-arrow": "^1.2.3",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-hooks": "^4.2.0",
"jest": "^26.6.3",
"jest": "^27.0.6",
"npm-run-all": "^4.1.5",
"prettier": "^2.3.0",
"prettier": "^2.3.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-intl": "^5.17.5",
"react-intl": "^5.20.4",
"react-redux": "^7.2.4",
"redux": "^4.1.0",
"ts-jest": "^26.5.6",
"typescript": "^4.2.4",
"ts-jest": "^27.0.3",
"typescript": "^4.3.5",
"typescript-fsa": "^3.0.0",
"typescript-fsa-reducers": "^1.2.2"
},
Expand Down
29 changes: 0 additions & 29 deletions src/__snapshots__/WrapperWithRedux.test.tsx.snap

This file was deleted.

8 changes: 2 additions & 6 deletions src/Wrapper.test.tsx → src/enzyme/Wrapper.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ReactWrapper, ShallowWrapper } from "enzyme";
import * as React from "react";

import { Dummy } from "../test/Dummy";
import { Dummy } from "../../test/Dummy";
import Wrapper from "./Wrapper";

describe("Wrapper", () => {
Expand All @@ -18,7 +18,7 @@ describe("Wrapper", () => {
});

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

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

it("has the correct root node", () => {
expect(wrapper.instance()).toBeInstanceOf(Dummy);
});

it("matches snapshot", () => {
expect(wrapper).toMatchSnapshot();
});
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IntlDummy } from "../test/IntlDummy";
import Wrapper, { messages } from "../test/TestWrapperWithIntl";
import Wrapper, { messages } from "../../test/enzyme/TestWrapperWithIntl";
import { IntlDummy } from "../../test/IntlDummy";

describe("WrapperWithIntl", () => {
const component = new Wrapper(IntlDummy).withDefaultProps({
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { ReactWrapper } from "enzyme";

import * as actions from "../test/actions";
import { ConnectedDummy } from "../test/Dummy";
import Wrapper from "../test/TestWrapperWithRedux";
import * as actions from "../../test/actions";
import Wrapper from "../../test/enzyme/TestWrapperWithRedux";
import { ReduxDummy } from "../../test/ReduxDummy";

const initialState = {
test: {
value: "Default value",
},
};

const component = new Wrapper(ConnectedDummy).withDefaultReduxState(
initialState
);
const component = new Wrapper(ReduxDummy).withDefaultReduxState(initialState);

describe("WrapperWithRedux", () => {
describe("when using the different render methods", () => {
Expand All @@ -30,7 +28,7 @@ describe("WrapperWithRedux", () => {
});

it("has the component in the tree", () => {
expect(wrapper.find(ConnectedDummy)).toHaveLength(1);
expect(wrapper.find(ReduxDummy)).toHaveLength(1);
});

it("matches snapshot", () => {
Expand Down
File renamed without changes.
Loading

0 comments on commit c64677e

Please sign in to comment.