Skip to content

Commit b561529

Browse files
committed
Add tests & ESLint support
1 parent 68696cb commit b561529

34 files changed

Lines changed: 18343 additions & 9408 deletions

.eslintrc.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
module.exports = {
2+
plugins: ['@typescript-eslint/eslint-plugin'],
3+
extends: [
4+
'react-app',
5+
'react-app/jest',
6+
'eslint-config-prettier',
7+
'plugin:@typescript-eslint/recommended',
8+
'plugin:prettier/recommended',
9+
],
10+
root: true,
11+
env: {
12+
browser: true,
13+
jest: true,
14+
},
15+
rules: {
16+
'@typescript-eslint/interface-name-prefix': 'off',
17+
'@typescript-eslint/explicit-function-return-type': 'off',
18+
'@typescript-eslint/explicit-module-boundary-types': 'off',
19+
'@typescript-eslint/no-explicit-any': 'off',
20+
'@typescript-eslint/no-unused-vars': [
21+
'warn',
22+
{ vars: 'all', args: 'after-used', ignoreRestSiblings: false },
23+
],
24+
'prettier/prettier': [
25+
'error',
26+
{
27+
singleQuote: true,
28+
printWidth: 100,
29+
endOfLine: 'auto',
30+
},
31+
],
32+
eqeqeq: ['warn', 'always'],
33+
34+
// from https://reactjs.org/docs/hooks-rules.html#eslint-plugin
35+
'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
36+
'react-hooks/exhaustive-deps': 'error', // Checks effect dependencies
37+
},
38+
};

babel.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
presets: [
3+
['@babel/preset-env', { targets: { node: 'current' } }],
4+
'@babel/preset-typescript',
5+
],
6+
};

jest.config.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/** @type {import('jest').Config} */
2+
const config = {
3+
preset: 'ts-jest',
4+
testEnvironment: 'jsdom',
5+
transform: {
6+
'^.+\\.ts|tsx?$': 'ts-jest',
7+
'\\.js|jsx?$': '<rootDir>/node_modules/babel-jest',
8+
},
9+
transformIgnorePatterns: ['<rootDir>/node_modules/'],
10+
coveragePathIgnorePatterns: ['<rootDir>/src/index.tsx'],
11+
testRegex: 'src/.*\\.test\\.tsx?$',
12+
setupFiles: ['<rootDir>/src/setupTests.ts'],
13+
};
14+
15+
module.exports = config;

package-lock.json

Lines changed: 17731 additions & 9308 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,31 @@
2525
"typescript": "^4.7.4",
2626
"web-vitals": "^2.1.4"
2727
},
28+
"devDependencies": {
29+
"@babel/core": "^7.19.1",
30+
"@babel/preset-env": "^7.19.1",
31+
"@babel/preset-typescript": "^7.18.6",
32+
"@types/react-test-renderer": "^18.0.0",
33+
"babel-jest": "^29.0.3",
34+
"eslint": "^8.23.1",
35+
"eslint-config-prettier": "^8.5.0",
36+
"eslint-plugin-prettier": "^4.2.1",
37+
"msw": "^0.47.3",
38+
"ts-jest": "^29.0.1"
39+
},
2840
"scripts": {
2941
"start": "react-scripts start",
3042
"build": "react-scripts build",
3143
"test": "react-scripts test",
32-
"eject": "react-scripts eject"
44+
"eject": "react-scripts eject",
45+
"lint": "eslint ./src"
46+
},
47+
"jest": {
48+
"collectCoverageFrom": [
49+
"src/**/*.{ts,tsx}",
50+
"!src/index.tsx",
51+
"!**/src/index.tsx"
52+
]
3353
},
3454
"eslintConfig": {
3555
"extends": [

src/App.test.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
import React from 'react';
2-
import { render } from '@testing-library/react';
1+
import { cleanup, render, screen } from '@testing-library/react';
32
import { Provider } from 'react-redux';
3+
import { BrowserRouter } from 'react-router-dom';
44
import { store } from './app/store';
55
import App from './App';
66

7-
test('renders learn react link', () => {
8-
const { getByText } = render(
9-
<Provider store={store}>
10-
<App />
11-
</Provider>
12-
);
7+
describe('App component', () => {
8+
test('should handle without signed in', async () => {
9+
render(
10+
<Provider store={store}>
11+
<BrowserRouter>
12+
<App />
13+
</BrowserRouter>
14+
</Provider>
15+
);
16+
expect(screen.getByText('Sign up')).toBeInTheDocument();
1317

14-
expect(getByText(/learn/i)).toBeInTheDocument();
18+
cleanup();
19+
});
1520
});

src/app/const.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
export enum LocalStorageKeys {
22
AccessToken = 'access_token',
33
Code = 'code',
4-
}
4+
}

src/app/context.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { createContext, PropsWithChildren } from "react";
2-
import { AxiosClient } from "./axios";
1+
import { createContext, PropsWithChildren } from 'react';
2+
import { AxiosClient } from './axios';
33

44
export interface AppContextValue {
55
axios: AxiosClient;
@@ -12,9 +12,5 @@ export interface AppProviderProps {
1212
export const AppContext = createContext<AppContextValue | null>(null);
1313

1414
export default function AppProvider({ axios, children }: PropsWithChildren<AppProviderProps>) {
15-
return (
16-
<AppContext.Provider value={{ axios }}>
17-
{children}
18-
</AppContext.Provider>
19-
);
20-
}
15+
return <AppContext.Provider value={{ axios }}>{children}</AppContext.Provider>;
16+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { cleanup, render, screen } from '@testing-library/react';
2+
import { Provider } from 'react-redux';
3+
import { BrowserRouter } from 'react-router-dom';
4+
import { store } from '../app/store';
5+
import { mockCommits } from '../test';
6+
import CommitsTable, { mapCommits } from './CommitsTable';
7+
8+
describe('CommitsTable component', () => {
9+
test('should handle loading without data', async () => {
10+
render(
11+
<Provider store={store}>
12+
<BrowserRouter>
13+
<CommitsTable org="test" />
14+
</BrowserRouter>
15+
</Provider>
16+
);
17+
expect(screen.getByRole('grid')).toBeInTheDocument();
18+
19+
cleanup();
20+
});
21+
22+
test('should handle mapping commits', () => {
23+
const result = mapCommits(mockCommits);
24+
25+
expect(result).toEqual(
26+
expect.arrayContaining([
27+
{
28+
id: 0,
29+
author: mockCommits[0].commit.author.name,
30+
committer: mockCommits[0].commit.committer.name,
31+
message: mockCommits[0].commit.message,
32+
date: mockCommits[0].commit.committer.date,
33+
},
34+
])
35+
);
36+
});
37+
});

src/components/Navbar.test.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { cleanup, render, screen } from '@testing-library/react';
2+
import { Provider } from 'react-redux';
3+
import { BrowserRouter } from 'react-router-dom';
4+
import { setAccessToken } from '../app/auth';
5+
import { store } from '../app/store';
6+
import { infoToDisplay } from './Navbar';
7+
import { mockUser } from '../test';
8+
import Navbar from './Navbar';
9+
10+
describe('Navbar component', () => {
11+
test('should handle user loading', async () => {
12+
setAccessToken('token');
13+
14+
render(
15+
<Provider store={store}>
16+
<BrowserRouter>
17+
<Navbar />
18+
</BrowserRouter>
19+
</Provider>
20+
);
21+
screen.getByText('Loading...');
22+
23+
expect(await screen.findByText(/github react app/i)).toBeInTheDocument();
24+
for (const key of infoToDisplay) {
25+
expect(await screen.findByText(mockUser[key])).toBeInTheDocument();
26+
}
27+
cleanup();
28+
});
29+
});

0 commit comments

Comments
 (0)