Skip to content

Commit 0f21368

Browse files
icd2k3jschrader-nr
andauthored
chore: Convert tests to TS and update dev dependencies (#63)
* chore: Convert tests to TS and update dev dependencies * chore: update node version for github actions * chore: adjust hooks Co-authored-by: Justin Schrader <[email protected]>
1 parent 2cbfce2 commit 0f21368

File tree

12 files changed

+4233
-3972
lines changed

12 files changed

+4233
-3972
lines changed

.eslintrc

+4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
{
22
"extends": [
33
"airbnb",
4+
"airbnb-typescript",
45
"plugin:@typescript-eslint/eslint-recommended",
56
"plugin:@typescript-eslint/recommended"
67
],
8+
"parserOptions": {
9+
"project": "./tsconfig.eslint.json"
10+
},
711
"parser": "@typescript-eslint/parser",
812
"plugins": [
913
"@typescript-eslint",

.github/workflows/nodejs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515

1616
strategy:
1717
matrix:
18-
node-version: [15.14.0]
18+
node-version: [16.17.0]
1919

2020
steps:
2121
- uses: actions/checkout@v2

.husky/pre-commit

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/bin/sh
22
. "$(dirname "$0")/_/husky.sh"
33

4-
yarn build && yarn lint && yarn test
4+
yarn types && yarn lint && yarn test

.husky/pre-push

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/bin/sh
22
. "$(dirname "$0")/_/husky.sh"
33

4-
yarn build && yarn types && yarn lint && yarn test-build
4+
yarn build && yarn test-build

.nvmrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v15.14.0
1+
v16.17.0

.yarn/releases/yarn-2.4.2.cjs

-55
This file was deleted.

.yarn/releases/yarn-3.2.3.cjs

+783
Large diffs are not rendered by default.

.yarnrc.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ plugins:
44
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
55
spec: "@yarnpkg/plugin-interactive-tools"
66

7-
yarnPath: .yarn/releases/yarn-2.4.2.cjs
7+
yarnPath: .yarn/releases/yarn-3.2.3.cjs

package.json

+34-33
Original file line numberDiff line numberDiff line change
@@ -15,50 +15,51 @@
1515
},
1616
"scripts": {
1717
"prepublishOnly": "yarn build && pinst --disable",
18-
"build": "rollup -c && yarn types",
18+
"build": "rollup -c && yarn type-declarations",
1919
"test": "jest",
2020
"test-build": "sh ./scripts/test-build.sh",
21-
"types": "tsc -p tsconfig.json --declaration --emitDeclarationOnly",
21+
"types": "tsc -p tsconfig.json --noEmit",
22+
"type-declarations": "tsc -p tsconfig.json --declaration --emitDeclarationOnly --excludeFiles ./src/index.test.tsx",
2223
"lint": "eslint ./src/**",
2324
"postpublish": "pinst --enable",
2425
"prepare": "husky install"
2526
},
2627
"devDependencies": {
27-
"@babel/cli": "^7.17.6",
28-
"@babel/core": "^7.17.9",
29-
"@babel/plugin-transform-runtime": "^7.17.0",
30-
"@babel/preset-env": "^7.16.11",
31-
"@babel/preset-react": "^7.16.7",
32-
"@babel/preset-typescript": "^7.16.7",
33-
"@commitlint/cli": "^12.1.4",
34-
"@commitlint/config-conventional": "^12.1.4",
35-
"@rollup/plugin-babel": "^5.3.0",
36-
"@rollup/plugin-typescript": "^8.2.1",
37-
"@testing-library/jest-dom": "^5.16.4",
38-
"@testing-library/react": "^13.0.1",
39-
"@types/react": "^17.0.11",
40-
"@types/react-dom": "^17.0.7",
41-
"@typescript-eslint/eslint-plugin": "^4.26.1",
42-
"@typescript-eslint/parser": "^4.26.1",
43-
"babel-eslint": "^10.1.0",
44-
"eslint": "^7.28.0",
45-
"eslint-config-airbnb": "^18.2.1",
46-
"eslint-plugin-import": "^2.23.4",
47-
"eslint-plugin-jsx-a11y": "^6.4.1",
48-
"eslint-plugin-react": "^7.24.0",
49-
"eslint-plugin-react-hooks": "^4.2.0",
50-
"husky": "^6.0.0",
51-
"jest": "^27.0.4",
28+
"@babel/cli": "^7.18.10",
29+
"@babel/core": "^7.19.0",
30+
"@babel/plugin-transform-runtime": "^7.18.10",
31+
"@babel/preset-env": "^7.19.0",
32+
"@babel/preset-react": "^7.18.6",
33+
"@babel/preset-typescript": "^7.18.6",
34+
"@commitlint/cli": "^17.1.2",
35+
"@commitlint/config-conventional": "^17.1.0",
36+
"@rollup/plugin-babel": "^5.3.1",
37+
"@rollup/plugin-typescript": "^8.5.0",
38+
"@testing-library/jest-dom": "^5.16.5",
39+
"@testing-library/react": "^13.4.0",
40+
"@types/react": "^18.0.18",
41+
"@types/react-dom": "^18.0.6",
42+
"@typescript-eslint/eslint-plugin": "^5.36.2",
43+
"@typescript-eslint/parser": "^5.36.2",
44+
"eslint": "^8.23.0",
45+
"eslint-config-airbnb": "^19.0.4",
46+
"eslint-config-airbnb-typescript": "^17.0.0",
47+
"eslint-plugin-import": "^2.26.0",
48+
"eslint-plugin-jsx-a11y": "^6.6.1",
49+
"eslint-plugin-react": "^7.31.8",
50+
"eslint-plugin-react-hooks": "^4.6.0",
51+
"husky": "^8.0.1",
52+
"jest": "^29.0.2",
53+
"jsdom": "^20.0.0",
5254
"jsdom-global": "^3.0.2",
53-
"pinst": "^2.1.6",
54-
"prop-types": "^15.7.2",
55-
"react": "^18.0.0",
56-
"react-dom": "^18.0.0",
55+
"pinst": "^3.0.0",
56+
"react": "^18.2.0",
57+
"react-dom": "^18.2.0",
5758
"react-router": "^6.3.0",
58-
"rollup": "^2.51.1",
59+
"rollup": "^2.79.0",
5960
"rollup-plugin-size": "^0.2.2",
6061
"rollup-plugin-terser": "^7.0.2",
61-
"typescript": "^4.3.2"
62+
"typescript": "^4.8.3"
6263
},
6364
"keywords": [
6465
"react",

src/index.test.js renamed to src/index.test.tsx

+57-103
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1+
/* eslint-disable react/require-default-props */
12
/* eslint-disable react/no-array-index-key */
2-
/* eslint-disable react/jsx-filename-extension */
33
import '@testing-library/jest-dom';
44
import React from 'react';
5-
import PropTypes from 'prop-types';
65
import { render, screen } from '@testing-library/react';
7-
import { MemoryRouter as Router, Route, useLocation } from 'react-router';
8-
import useBreadcrumbs, { getBreadcrumbs, createRoutesFromChildren } from './index.tsx';
6+
import { MemoryRouter as Router, useLocation } from 'react-router';
7+
import useBreadcrumbs, { getBreadcrumbs, createRoutesFromChildren, BreadcrumbsRoute, Route, Options } from './index';
98

109
// imports to test compiled builds
1110
import useBreadcrumbsCompiledES, {
1211
getBreadcrumbs as getBreadcrumbsCompiledES,
1312
} from '../dist/es/index';
1413
import useBreadcrumbsCompiledUMD, {
14+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
15+
// @ts-ignore
1516
getBreadcrumbs as getBreadcrumbsCompiledUMD,
1617
} from '../dist/umd/index';
1718
import useBreadcrumbsCompiledCJS, {
@@ -24,6 +25,10 @@ const components = {
2425
options,
2526
routes,
2627
...forwardedProps
28+
}: {
29+
useBreadcrumbs: (r?: BreadcrumbsRoute[], o?: Options) => []
30+
options?: Options
31+
routes?: BreadcrumbsRoute[]
2732
}) => {
2833
const breadcrumbs = useBreadcrumbsHook(routes, options);
2934
const location = useLocation();
@@ -34,8 +39,10 @@ const components = {
3439
<div data-test-id="forwarded-props">
3540
{forwardedProps
3641
&& Object.values(forwardedProps)
37-
.filter((v) => typeof v === 'string')
38-
.map((value) => <span key={value}>{value}</span>)}
42+
.filter((v: unknown) => typeof v === 'string')
43+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
44+
// @ts-ignore
45+
.map((value: string) => <span key={value}>{value}</span>)}
3946
</div>
4047
<div className="breadcrumbs-container">
4148
{breadcrumbs.map(({ breadcrumb, key }, index) => (
@@ -48,28 +55,44 @@ const components = {
4855
</h1>
4956
);
5057
},
51-
BreadcrumbMatchTest: ({ match }) => <span>{match.params.number}</span>,
52-
BreadcrumbRouteTest: ({ match }) => <span>{match.route?.arbitraryProp}</span>,
53-
BreadcrumbNavLinkTest: ({ match }) => <a role="link" to={match.pathname}>Link</a>,
58+
BreadcrumbMatchTest: (
59+
{ match }: { match?: { params?: { number?: number } } },
60+
) => <span>{match?.params?.number}</span>,
61+
62+
BreadcrumbRouteTest: (
63+
{ match }: { match: { route?: { arbitraryProp: string } } },
64+
) => <span>{match.route?.arbitraryProp}</span>,
65+
66+
BreadcrumbNavLinkTest: (
67+
{ match }: { match: { pathname: string } },
68+
) => <a href={match.pathname}>Link</a>,
69+
5470
BreadcrumbLocationTest: ({
55-
location: {
56-
state: { isLocationTest },
57-
},
58-
}) => <span>{isLocationTest ? 'pass' : 'fail'}</span>,
59-
BreadcrumbExtraPropsTest: ({ foo, bar }) => (
71+
location,
72+
}: {
73+
location?: {
74+
state?: { isLocationTest?: boolean }
75+
}
76+
}) => <span>{location?.state?.isLocationTest ? 'pass' : 'fail'}</span>,
77+
78+
BreadcrumbExtraPropsTest: ({ foo, bar }: { foo: string, bar: string }) => (
6079
<span>
6180
{foo}
6281
{bar}
6382
</span>
6483
),
84+
6585
BreadcrumbMemoized: React.memo(() => <span>Memoized</span>),
86+
6687
// eslint-disable-next-line react/prefer-stateless-function
6788
BreadcrumbClass: class BreadcrumbClass extends React.PureComponent {
6889
render() {
6990
return <span>Class</span>;
7091
}
7192
},
72-
Layout: React.memo(({ children }) => <div>{children}</div>),
93+
94+
// eslint-disable-next-line react/require-default-props
95+
Layout: React.memo(({ children }: { children?: React.ReactNode }) => <div>{children}</div>),
7396
};
7497

7598
const getHOC = () => {
@@ -98,13 +121,24 @@ const getMethod = () => {
98121
}
99122
};
100123

101-
const renderer = ({ options, pathname, routes, state, props }) => {
124+
const renderer = (
125+
{ options, pathname, routes, state, props }:
126+
{
127+
options?: Options
128+
pathname: string
129+
routes?: BreadcrumbsRoute<string>[]
130+
state?: { isLocationTest: boolean }
131+
props?: { [x: string]: unknown }
132+
},
133+
) => {
102134
const useBreadcrumbsHook = getHOC();
103135
const { Breadcrumbs } = components;
104136

105137
const wrapper = render(
106138
<Router initialIndex={0} initialEntries={[{ pathname, state }]}>
107139
<Breadcrumbs
140+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
141+
// @ts-ignore
108142
useBreadcrumbs={useBreadcrumbsHook}
109143
options={options}
110144
routes={routes}
@@ -118,88 +152,8 @@ const renderer = ({ options, pathname, routes, state, props }) => {
118152
};
119153
};
120154

121-
const matchShape = {
122-
params: PropTypes.shape().isRequired,
123-
pathname: PropTypes.string.isRequired,
124-
pattern: PropTypes.object.isRequired,
125-
};
126-
127-
components.Breadcrumbs.propTypes = {
128-
useBreadcrumbs: PropTypes.func.isRequired,
129-
options: PropTypes.shape({
130-
excludePaths: PropTypes.arrayOf(PropTypes.string),
131-
disableDefaults: PropTypes.bool,
132-
}),
133-
routes: PropTypes.arrayOf(
134-
PropTypes.oneOfType([
135-
PropTypes.shape({
136-
path: PropTypes.string,
137-
breadcrumb: PropTypes.oneOfType([
138-
PropTypes.node,
139-
PropTypes.func,
140-
PropTypes.object,
141-
]),
142-
}),
143-
PropTypes.shape({
144-
index: PropTypes.bool,
145-
breadcrumb: PropTypes.oneOfType([
146-
PropTypes.node,
147-
PropTypes.func,
148-
PropTypes.object,
149-
]),
150-
}),
151-
PropTypes.shape({
152-
children: PropTypes.arrayOf(PropTypes.shape()).isRequired,
153-
breadcrumb: PropTypes.oneOfType([
154-
PropTypes.node,
155-
PropTypes.func,
156-
PropTypes.object,
157-
]),
158-
}),
159-
]),
160-
),
161-
};
162-
163-
components.Breadcrumbs.defaultProps = {
164-
routes: null,
165-
options: null,
166-
};
167-
168-
components.BreadcrumbMatchTest.propTypes = {
169-
match: PropTypes.shape(matchShape).isRequired,
170-
};
171-
172-
components.BreadcrumbRouteTest.propTypes = {
173-
match: PropTypes.shape(matchShape).isRequired,
174-
};
175-
176-
components.BreadcrumbNavLinkTest.propTypes = {
177-
match: PropTypes.shape(matchShape).isRequired,
178-
};
179-
180-
components.BreadcrumbLocationTest.propTypes = {
181-
location: PropTypes.shape({
182-
state: PropTypes.shape({
183-
isLocationTest: PropTypes.bool.isRequired,
184-
}).isRequired,
185-
}).isRequired,
186-
};
187-
188-
components.BreadcrumbExtraPropsTest.propTypes = {
189-
foo: PropTypes.string.isRequired,
190-
bar: PropTypes.string.isRequired,
191-
};
192-
193-
components.Layout.propTypes = {
194-
children: PropTypes.node,
195-
};
196-
197-
components.Layout.defaultProps = {
198-
children: null,
199-
};
200-
201-
const getByTextContent = (text) => screen.getByText((content, element) => {
202-
const hasText = (ele) => ele.textContent === text;
155+
const getByTextContent = (text: string) => screen.getByText((content, element) => {
156+
const hasText = (ele: Element | null) => ele?.textContent === text;
203157
const elementHasText = hasText(element);
204158
const childrenDontHaveText = (element?.children ? Array.from(element.children) : [])
205159
.every((child) => !hasText(child));
@@ -210,15 +164,16 @@ const getByTextContent = (text) => screen.getByText((content, element) => {
210164
describe('use-react-router-breadcrumbs', () => {
211165
describe('Valid routes', () => {
212166
it('Should render breadcrumb components as expected', () => {
213-
const routes = [
167+
const { BreadcrumbMatchTest } = components;
168+
const routes: BreadcrumbsRoute[] = [
214169
// test home route
215170
{ path: '/', breadcrumb: 'Home' },
216171
// test breadcrumb passed as string
217172
{ path: '/1', breadcrumb: 'One' },
218173
// test simple breadcrumb component
219174
{ path: '/1/2', breadcrumb: () => <span>TWO</span> },
220175
// test advanced breadcrumb component (user can use `match` however they wish)
221-
{ path: '/1/2/:number', breadcrumb: components.BreadcrumbMatchTest },
176+
{ path: '/1/2/:number', breadcrumb: BreadcrumbMatchTest },
222177
// test NavLink wrapped breadcrumb
223178
{
224179
path: '/1/2/:number/4',
@@ -232,7 +187,7 @@ describe('use-react-router-breadcrumbs', () => {
232187
routes,
233188
});
234189
expect(getByTextContent('Home / One / TWO / 3 / Link / Any')).toBeTruthy();
235-
expect(screen.getByRole('link')).toHaveAttribute('to', '/1/2/3/4');
190+
expect(screen.getByRole('link')).toHaveAttribute('href', '/1/2/3/4');
236191
});
237192
});
238193

@@ -536,7 +491,6 @@ describe('use-react-router-breadcrumbs', () => {
536491
it('Should be able to set options without defining a routes array', () => {
537492
renderer({
538493
pathname: '/one/two',
539-
routes: null,
540494
options: { excludePaths: ['/', '/one'] },
541495
});
542496
expect(getByTextContent('Two')).toBeTruthy();
@@ -569,7 +523,7 @@ describe('use-react-router-breadcrumbs', () => {
569523
renderer({
570524
pathname: '/one/two/three_four',
571525
routes,
572-
options: { defaultFormatter: (breadcrumb) => breadcrumb.replace(/two/g, 'changed') },
526+
options: { defaultFormatter: (breadcrumb: string) => breadcrumb.replace(/two/g, 'changed') },
573527
});
574528

575529
expect(getByTextContent('Home / One / changed / three_four')).toBeTruthy();

tsconfig.eslint.json

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"include": ["src/index.test.tsx"]
4+
}

0 commit comments

Comments
 (0)