Skip to content

Commit 55c6dee

Browse files
committed
[Testing]: add more example about testing custom hooks
1 parent 614a130 commit 55c6dee

24 files changed

Lines changed: 11565 additions & 100 deletions

File tree

react/altri-hook/client/README.md

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,12 @@
1-
# React + TypeScript + Vite
1+
# Alrti hook
22

3-
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
3+
In questo piccolo progetto puoi vedere un client al lavoro con react-hook-form.
44

5-
Currently, two official plugins are available:
5+
- [torna alla home](/)
66

7-
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8-
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
7+
## Come fare...
98

10-
## Expanding the ESLint configuration
11-
12-
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13-
14-
- Configure the top-level `parserOptions` property like this:
15-
16-
```js
17-
export default {
18-
// other rules...
19-
parserOptions: {
20-
ecmaVersion: 'latest',
21-
sourceType: 'module',
22-
project: ['./tsconfig.json', './tsconfig.node.json'],
23-
tsconfigRootDir: __dirname,
24-
},
25-
}
269
```
27-
28-
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
29-
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
30-
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
10+
npm install
11+
npm run dev
12+
```

state-management/redux/README.md

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,12 @@
1-
# React + TypeScript + Vite
1+
# Redux
22

3-
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
3+
In questo piccolo progetto puoi vedere un esempio di Redux.
44

5-
Currently, two official plugins are available:
5+
- [torna alla home](/)
66

7-
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8-
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
7+
## Come fare...
98

10-
## Expanding the ESLint configuration
11-
12-
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13-
14-
- Configure the top-level `parserOptions` property like this:
15-
16-
```js
17-
export default {
18-
// other rules...
19-
parserOptions: {
20-
ecmaVersion: 'latest',
21-
sourceType: 'module',
22-
project: ['./tsconfig.json', './tsconfig.node.json'],
23-
tsconfigRootDir: __dirname,
24-
},
25-
}
269
```
27-
28-
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
29-
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
30-
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
10+
npm install
11+
npm run dev
12+
```
Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,12 @@
1-
# React + TypeScript + Vite
1+
# Styled hello world
22

3-
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
3+
In questo piccolo progetto puoi vedere qualche esempio di styled component.
44

5-
Currently, two official plugins are available:
5+
- [torna alla home](/)
66

7-
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8-
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
7+
## Come fare...
98

10-
## Expanding the ESLint configuration
11-
12-
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13-
14-
- Configure the top-level `parserOptions` property like this:
15-
16-
```js
17-
export default {
18-
// other rules...
19-
parserOptions: {
20-
ecmaVersion: 'latest',
21-
sourceType: 'module',
22-
project: ['./tsconfig.json', './tsconfig.node.json'],
23-
tsconfigRootDir: __dirname,
24-
},
25-
}
269
```
27-
28-
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
29-
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
30-
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
10+
npm install
11+
npm run dev
12+
```
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module.exports = {
2+
root: true,
3+
env: { browser: true, es2020: true },
4+
extends: [
5+
'eslint:recommended',
6+
'plugin:@typescript-eslint/recommended',
7+
'plugin:react-hooks/recommended',
8+
],
9+
ignorePatterns: ['dist', '.eslintrc.cjs'],
10+
parser: '@typescript-eslint/parser',
11+
plugins: ['react-refresh'],
12+
rules: {
13+
'react-refresh/only-export-components': [
14+
'warn',
15+
{ allowConstantExport: true },
16+
],
17+
},
18+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Testare un custom hook
2+
3+
In questo piccolo progetto puoi vedere come testare un custom hook.
4+
5+
- [torna alla home](/)
6+
7+
## Come fare...
8+
9+
```
10+
npm install
11+
npm run test
12+
```
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { renderHook } from "@testing-library/react";
2+
import { useEffect, useState } from "react";
3+
import { waitFor } from "@testing-library/react";
4+
5+
const useProductName = () => {
6+
const [productName, setProductName] = useState(null);
7+
const [loading, setLoading] = useState(true);
8+
const [isProductRoute, setIsProductRoute] = useState(false);
9+
const [isValidPath, setIsValidPath] = useState(true);
10+
const [categoryId, setCategoryId] = useState<string | null>(null);
11+
12+
useEffect(() => {
13+
const fetchProductName = async (productId) => {
14+
try {
15+
setLoading(true);
16+
const response = await fetch(
17+
`https://api.example.com/products/${productId}`
18+
);
19+
if (!response.ok) throw new Error("Network response was not ok");
20+
const data = await response.json();
21+
setProductName(data.name);
22+
} catch (err) {
23+
/* empty */
24+
} finally {
25+
setLoading(false);
26+
}
27+
};
28+
29+
const path = window.location.pathname;
30+
const matchProductPath = path.match(/\/products\/(\d+)/);
31+
const matchCategoryProductPath = path.match(/(\d+)\/products\/(\d+)/);
32+
const productId = matchProductPath ? matchProductPath[1] : null;
33+
const cat = matchCategoryProductPath ? matchCategoryProductPath[1] : null;
34+
35+
setCategoryId(cat);
36+
setIsProductRoute(path.slice(1).split("/").length === 2 && !!productId);
37+
fetchProductName(productId);
38+
setIsValidPath(!!productId);
39+
}, []);
40+
41+
return { productName, loading, isProductRoute, categoryId, isValidPath };
42+
};
43+
44+
export default useProductName;
45+
46+
global.fetch = jest.fn();
47+
48+
const mockLocation = (pathname) => {
49+
delete window.location;
50+
window.location = new URL("https://example.com" + pathname);
51+
};
52+
53+
describe("useProductName", () => {
54+
afterEach(() => {
55+
jest.resetAllMocks();
56+
});
57+
58+
it("should fetch and return product name based on product ID in URL", async () => {
59+
const mockProductId = "42";
60+
const mockProductName = "Sample Product";
61+
mockLocation(`/products/${mockProductId}`);
62+
fetch.mockResolvedValueOnce({
63+
ok: true,
64+
json: async () => ({ name: mockProductName }),
65+
});
66+
const { result } = renderHook(() => useProductName());
67+
await waitFor(() => expect(result.current.loading).toBe(false));
68+
expect(result.current.productName).toBe(mockProductName);
69+
expect(result.current.isProductRoute).toBe(true);
70+
expect(result.current.isValidPath).toBe(true);
71+
});
72+
73+
it("should fetch and return product name based on product ID in URL", async () => {
74+
const mockProductId = "42";
75+
const mockProductName = "Sample Product";
76+
mockLocation(`/products/${mockProductId}`);
77+
fetch.mockResolvedValueOnce({
78+
ok: false,
79+
json: async () => ({ name: mockProductName }),
80+
});
81+
const { result } = renderHook(() => useProductName());
82+
await waitFor(() => expect(result.current.loading).toBe(false));
83+
expect(result.current.productName).toBe(null);
84+
expect(result.current.isProductRoute).toBe(true);
85+
expect(result.current.isValidPath).toBe(true);
86+
});
87+
88+
it("should fetch and return product name based on product ID in URL", async () => {
89+
const mockProductId = "42";
90+
const categoryId = "43";
91+
const mockProductName = "Sample Product";
92+
mockLocation(`/${categoryId}/products/${mockProductId}`);
93+
fetch.mockResolvedValueOnce({
94+
ok: true,
95+
json: async () => ({ name: mockProductName }),
96+
});
97+
const { result } = renderHook(() => useProductName());
98+
await waitFor(() => expect(result.current.loading).toBe(false));
99+
expect(result.current.productName).toBe(mockProductName);
100+
expect(result.current.isProductRoute).toBe(false);
101+
expect(result.current.categoryId).toBe("43");
102+
expect(result.current.isValidPath).toBe(true);
103+
});
104+
105+
it("should fetch and return product name based on product ID in URL", async () => {
106+
const mockProductName = "Sample Product";
107+
mockLocation(`/invalid/path`);
108+
fetch.mockResolvedValueOnce({
109+
ok: true,
110+
json: async () => ({ name: mockProductName }),
111+
});
112+
const { result } = renderHook(() => useProductName());
113+
await waitFor(() => expect(result.current.loading).toBe(false));
114+
expect(result.current.productName).toBe(mockProductName);
115+
expect(result.current.isProductRoute).toBe(false);
116+
expect(result.current.categoryId).toBe(null);
117+
expect(result.current.isValidPath).toBe(false);
118+
});
119+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
presets: [
3+
"@babel/preset-env",
4+
"@babel/preset-react",
5+
"@babel/preset-typescript",
6+
],
7+
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vite + React + TS</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
testEnvironment: "jsdom",
3+
};

0 commit comments

Comments
 (0)