Skip to content

Commit

Permalink
feat(testing-library): add React Testing Library setup
Browse files Browse the repository at this point in the history
  • Loading branch information
rozsival committed Oct 29, 2023
1 parent 20f87f8 commit 01b2aac
Show file tree
Hide file tree
Showing 21 changed files with 811 additions and 65 deletions.
75 changes: 75 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Test

on:
push:
branches:
- '*'
pull_request:
branches:
- develop
- main

env:
CACHE_KEY: ${{ github.sha }}-${{ github.run_number }}-${{ github.run_attempt }}
CACHE_PATH: ./*

jobs:
setup:
runs-on: ubuntu-latest
strategy:
matrix:
node-version:
- 20.9.0
pnpm-version:
- 8.9.2
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup pnpm v${{ matrix.pnpm-version }}
uses: pnpm/action-setup@v2
with:
version: ${{ matrix.pnpm-version }}
- name: Setup node.js v${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: pnpm install
- name: Build packages
run: pnpm run build
- name: Cache setup
uses: actions/cache@v3
id: cache-setup
with:
key: ${{ env.CACHE_KEY }}
path: ${{ env.CACHE_PATH }}
- name: Set node-version
id: set-node-version
run: echo "node-version=${{ matrix.node-version }}" >> $GITHUB_OUTPUT
- name: Set pnpm-version
id: set-pnpm-version
run: echo "pnpm-version={{ matrix.pnpm-version }}" >> $GITHUB_OUTPUT
test:
needs: setup
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: ${{ needs.setup.outputs.pnpm-version }}
- name: Setup node.js
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: ${{ needs.setup.outputs.node-version }}
- name: Restore setup
uses: actions/cache@v3
id: restore-setup
with:
key: ${{ env.CACHE_KEY }}
path: ${{ env.CACHE_PATH }}
- name: Run tests
run: pnpm run test
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ tsconfig.build.tsbuildinfo

# Builds
/packages/*/dist

# Coverage
/packages/*/coverage
7 changes: 7 additions & 0 deletions packages/testing-library/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
extends: '@apitree/eslint-config/react',
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: __dirname,
},
};
3 changes: 3 additions & 0 deletions packages/testing-library/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/coverage
/dist
/node_modules
51 changes: 51 additions & 0 deletions packages/testing-library/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<div align="center">

<a href="https://github.com/ApiTreeCZ">
<img alt="ApiTree s.r.o." src="https://www.apitree.cz/static/images/logo-header.svg" width="120" />
</a>

# Testing Library

### [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/) setup for [Vitest](https://vitest.dev) in ApiTree projects.

</div>

## Installation

```bash
pnpm add --save-dev @apitree/testing-library @apitree/vitest-config vitest
```

## Usage

1. Create `vitest.config.ts` in your project root:

```typescript
import { config } from '@apitree/vitest-config/react';
import { mergeConfig } from 'vitest/config';
import type { UserConfig } from 'vitest/config';

export default mergeConfig<UserConfig, UserConfig>(config, {
test: { setup: 'tests/setup.ts' },
});
```

2. Create `tests/setup.ts`:

```typescript
import '@apitree/testing-library/setup';
```

3. Create test renderers in `tests/testing-library.ts`

```typescript jsx
import { createRenderers } from '@apitree/testing-library';
export * from '@apitree/testing-library';
export const { render, renderHook } = createRenderers();
```

> See [`CreateRenderersProps`](./src/testing-library.ts) for `createRenderers` props reference.
4. Write your tests in `tests` directory and run them with `vitest --run` command.

> Use `tests/testing-library.ts` for importing Testing Library utilities.
8 changes: 8 additions & 0 deletions packages/testing-library/lint-staged.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
'./**/*.{cjs,js}': 'eslint --cache --fix',
'./**/*.{json,md}': 'prettier --write',
'./**/*.{ts,tsx}': [
() => 'tsc --build tsconfig.json',
'eslint --cache --fix',
],
};
50 changes: 50 additions & 0 deletions packages/testing-library/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"name": "@apitree/testing-library",
"version": "0.0.0",
"description": "React Testing Library setup for Vitest in ApiTree projects.",
"repository": {
"type": "git",
"url": "https://github.com/ApiTreeCZ/toolbox",
"directory": "packages/testing-library"
},
"sideEffects": false,
"type": "module",
"exports": {
".": "./dist/index.js",
"./setup": "./dist/setup.js"
},
"scripts": {
"build": "tsc --build tsconfig.build.json",
"cleanup": "rimraf .eslintcache .turbo tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo dist node_modules",
"fix": "run-p ts format:fix lint:fix",
"format": "prettier --check \"./**/*.{json,md}\"",
"format:fix": "pnpm run format --write",
"lint": "eslint --cache --ext cjs,ts,tsx .",
"lint:fix": "pnpm run lint --fix",
"qa": "run-p ts format lint",
"test": "vitest --run",
"test:coverage": "pnpm run test --coverage",
"ts": "tsc --build tsconfig.json"
},
"dependencies": {
"@testing-library/dom": "^9.3.3",
"@testing-library/jest-dom": "^6.1.4",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.5.1",
"jsdom": "^22.1.0"
},
"devDependencies": {
"@apitree/vitest-config": "workspace:*",
"@types/react": "^18.2.33",
"@types/react-dom": "^18.2.14",
"@vitest/coverage-istanbul": "^0.34.6",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"vitest": "^0.34.6"
},
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"vitest": "^0.34.6"
}
}
1 change: 1 addition & 0 deletions packages/testing-library/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './testing-library.js';
5 changes: 5 additions & 0 deletions packages/testing-library/src/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { cleanup } from '@testing-library/react';
import { afterEach } from 'vitest';
import '@testing-library/jest-dom/vitest';

afterEach(() => cleanup());
36 changes: 36 additions & 0 deletions packages/testing-library/src/testing-library.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { RenderHookOptions, RenderOptions } from '@testing-library/react';
import { render, renderHook } from '@testing-library/react';
import type { ReactElement } from 'react';

export interface CreateRenderersProps {
/**
* The default wrapper to use for rendering components (e.g. a `ThemeProvider`).
*/
defaultWrapper?: RenderOptions['wrapper'] | undefined;
}

export const createRenderers = ({
defaultWrapper = function defaultWrapper({ children }) {
return children;
},
}: CreateRenderersProps = {}) => {
const customRender = (ui: ReactElement, options?: RenderOptions) => {
const { wrapper = defaultWrapper } = options ?? {};
return render(ui, { ...options, wrapper });
};
const customRenderHook = <Result, Props>(
render: (initialProps: Props) => Result,
options?: RenderHookOptions<Props>,
) => {
const { wrapper = defaultWrapper } = options ?? {};
return renderHook(render, {
...options,
wrapper,
});
};
return { render: customRender, renderHook: customRenderHook };
};

export { queries } from '@testing-library/dom';
export * from '@testing-library/react';
export * from '@testing-library/user-event';
1 change: 1 addition & 0 deletions packages/testing-library/tests/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '../src/setup.js';
30 changes: 30 additions & 0 deletions packages/testing-library/tests/testing-library.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { PropsWithChildren } from 'react';
import { describe, expect, it } from 'vitest';

import { createRenderers, screen } from '../src/testing-library.js';

describe('createRenderers', () => {
it('creates React Testing Library renderers', () => {
const { render, renderHook } = createRenderers();
render(<div />);
expect(renderHook).toBeTypeOf('function');
});
it('creates React Testing Library render function with a default wrapper', () => {
const defaultWrapper = ({ children }: PropsWithChildren) => (
<div data-testid="default-wrapper">{children}</div>
);
const { render } = createRenderers({ defaultWrapper });
render(<div data-testid="render-content" />);
expect(screen.getByTestId('default-wrapper')).toContainElement(
screen.getByTestId('render-content'),
);
});
it('creates React Testing Library renderHook function with a default wrapper', () => {
const defaultWrapper = ({ children }: PropsWithChildren) => (
<div data-testid="default-wrapper">{children}</div>
);
const { renderHook } = createRenderers({ defaultWrapper });
renderHook(() => 'hook-content');
expect(screen.getByTestId('default-wrapper')).toBeEmptyDOMElement();
});
});
9 changes: 9 additions & 0 deletions packages/testing-library/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": false,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["./src"]
}
5 changes: 5 additions & 0 deletions packages/testing-library/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"extends": "@apitree/ts-config/library",
"include": [".eslintrc.cjs", "./*.js", "**/*.ts", "**/*.tsx"],
"exclude": ["dist", "node_modules"]
}
9 changes: 9 additions & 0 deletions packages/testing-library/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { config } from '@apitree/vitest-config/react';
import { mergeConfig } from 'vitest/config';
import type { UserConfig } from 'vitest/config';

export default mergeConfig<UserConfig, UserConfig>(config, {
test: {
setupFiles: ['tests/setup.ts'],
},
});
5 changes: 3 additions & 2 deletions packages/vitest-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
## Installation

```bash
pnpm add --save-dev @apitree/vitest-config vite vitest
pnpm add --save-dev @apitree/vitest-config vitest
```

## Usage
Expand All @@ -39,8 +39,9 @@ You can customize the configuration with `mergeConfig` function:
```typescript
import { config } from '@apitree/vitest-config';
import { mergeConfig } from 'vitest/config';
import type { UserConfig } from 'vitest/config';

export default mergeConfig(config, {
export default mergeConfig<UserConfig, UserConfig>(config, {
// project specific configuration
});
```
Expand Down
5 changes: 2 additions & 3 deletions packages/vitest-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,13 @@
},
"dependencies": {
"@vitejs/plugin-react": "^4.1.0",
"@vitest/coverage-istanbul": "^0.34.6"
"@vitest/coverage-istanbul": "^0.34.6",
"vite": "^4.5.0"
},
"devDependencies": {
"vite": "^4.5.0",
"vitest": "^0.34.6"
},
"peerDependencies": {
"vite": "^4.5.0",
"vitest": "^0.34.6"
}
}
Loading

0 comments on commit 01b2aac

Please sign in to comment.