Skip to content

Commit

Permalink
test: add components test to ensure TypeScript is working as expected
Browse files Browse the repository at this point in the history
Related to #97
  • Loading branch information
jorisre committed Jan 5, 2021
1 parent 8e10721 commit 627cc39
Show file tree
Hide file tree
Showing 9 changed files with 437 additions and 4 deletions.
3 changes: 2 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testEnvironment: 'jsdom',
restoreMocks: true,
testMatch: ['**/__tests__/**/*.+(js|jsx|ts|tsx)'],
transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$'],
moduleNameMapper: {
'^@hookform/resolvers$': '<rootDir>/src',
},
setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
};
57 changes: 57 additions & 0 deletions joi/src/__tests__/Form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import { render, screen, act } from '@testing-library/react';
import user from '@testing-library/user-event';
import { useForm } from 'react-hook-form';
import * as Joi from 'joi';
import { joiResolver } from '..';

const schema = Joi.object({
username: Joi.string().required(),
password: Joi.string().required(),
});

interface FormData {
username: string;
password: string;
}

interface Props {
onSubmit: (data: FormData) => void;
}

function TestComponent({ onSubmit }: Props) {
const { register, errors, handleSubmit } = useForm<FormData>({
resolver: joiResolver(schema), // Useful to check TypeScript regressions
});

return (
<form onSubmit={handleSubmit(onSubmit)}>
<input name="username" ref={register} />
{errors.username && <span role="alert">{errors.username.message}</span>}

<input name="password" ref={register} />
{errors.password && <span role="alert">{errors.password.message}</span>}

<button type="submit">submit</button>
</form>
);
}

test("form's validation with Joi and TypeScript's integration", async () => {
const handleSubmit = jest.fn();
render(<TestComponent onSubmit={handleSubmit} />);

expect(screen.queryAllByRole(/alert/i)).toHaveLength(0);

await act(async () => {
user.click(screen.getByText(/submit/i));
});

expect(
screen.getByText(/"username" is not allowed to be empty/i),
).toBeInTheDocument();
expect(
screen.getByText(/"password" is not allowed to be empty/i),
).toBeInTheDocument();
expect(handleSubmit).not.toHaveBeenCalled();
});
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,11 @@
},
"homepage": "https://react-hook-form.com",
"devDependencies": {
"@testing-library/jest-dom": "^5.11.8",
"@testing-library/react": "^11.2.2",
"@testing-library/user-event": "^12.6.0",
"@types/jest": "^26.0.19",
"@types/react": "^17.0.0",
"@typescript-eslint/eslint-plugin": "^4.11.1",
"@typescript-eslint/parser": "^4.11.1",
"check-export-map": "^1.0.1",
Expand All @@ -124,6 +128,7 @@
"npm-run-all": "^4.1.5",
"prettier": "^2.2.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-hook-form": "^6.14.0",
"semantic-release": "^17.3.1",
"superstruct": "^0.13.1",
Expand Down
58 changes: 58 additions & 0 deletions superstruct/src/__tests__/Form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import { render, screen, act } from '@testing-library/react';
import user from '@testing-library/user-event';
import { useForm } from 'react-hook-form';
import { object, string, Infer, size } from 'superstruct';
import { superstructResolver } from '..';

const schema = object({
username: size(string(), 2),
password: size(string(), 6),
});

type FormData = Infer<typeof schema>;

interface Props {
onSubmit: (data: FormData) => void;
}

function TestComponent({ onSubmit }: Props) {
const { register, errors, handleSubmit } = useForm<FormData>({
resolver: superstructResolver(schema), // Useful to check TypeScript regressions
});

return (
<form onSubmit={handleSubmit(onSubmit)}>
<input name="username" ref={register} />
{errors.username && <span role="alert">{errors.username.message}</span>}

<input name="password" ref={register} />
{errors.password && <span role="alert">{errors.password.message}</span>}

<button type="submit">submit</button>
</form>
);
}

test("form's validation with Superstruct and TypeScript's integration", async () => {
const handleSubmit = jest.fn();
render(<TestComponent onSubmit={handleSubmit} />);

expect(screen.queryAllByRole(/alert/i)).toHaveLength(0);

await act(async () => {
user.click(screen.getByText(/submit/i));
});

expect(
screen.getByText(
/Expected a string with a length of `2` but received one with a length of `0`/i,
),
).toBeInTheDocument();
expect(
screen.getByText(
/Expected a string with a length of `6` but received one with a length of `0`/i,
),
).toBeInTheDocument();
expect(handleSubmit).not.toHaveBeenCalled();
});
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"strictNullChecks": true,
"isolatedModules": true
"isolatedModules": true,
"jsx": "react"
}
}
60 changes: 60 additions & 0 deletions vest/src/__tests__/Form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import { render, screen, act } from '@testing-library/react';
import user from '@testing-library/user-event';
import { useForm } from 'react-hook-form';
import vest from 'vest';
import { vestResolver } from '..';

interface FormData {
username: string;
password: string;
}

const validationSuite = vest.create('form', (data: FormData) => {
vest.test('username', 'Username is required', () => {
vest.enforce(data.username).isNotEmpty();
});

vest.test('password', 'Password must contain a symbol', () => {
vest.enforce(data.password).matches(/[^A-Za-z0-9]/);
});
});

interface Props {
onSubmit: (data: FormData) => void;
}

function TestComponent({ onSubmit }: Props) {
const { register, errors, handleSubmit } = useForm<FormData>({
resolver: vestResolver(validationSuite), // Useful to check TypeScript regressions
});

return (
<form onSubmit={handleSubmit(onSubmit)}>
<input name="username" ref={register} />
{errors.username && <span role="alert">{errors.username.message}</span>}

<input name="password" ref={register} />
{errors.password && <span role="alert">{errors.password.message}</span>}

<button type="submit">submit</button>
</form>
);
}

test("form's validation with Vest and TypeScript's integration", async () => {
const handleSubmit = jest.fn();
render(<TestComponent onSubmit={handleSubmit} />);

expect(screen.queryAllByRole(/alert/i)).toHaveLength(0);

await act(async () => {
user.click(screen.getByText(/submit/i));
});

expect(screen.getByText(/Username is required/i)).toBeInTheDocument();
expect(
screen.getByText(/Password must contain a symbol/i),
).toBeInTheDocument();
expect(handleSubmit).not.toHaveBeenCalled();
});
Loading

0 comments on commit 627cc39

Please sign in to comment.