This commit is contained in:
Philippe Torrel
2026-11-06 13:28:47 +01:00
parent d918c197ae
commit cf5e373303
7 changed files with 281 additions and 85 deletions
@@ -25,7 +25,7 @@
"axios-mock-adapter": "^2.1.0",
"jsdom": "^31.0.0",
"oxlint": "^1.91.0",
"sass-embedded": "^1.108.0",
"sass-embedded": "1.107",
"vite": "^8.3.6",
"vitest": "^5.1.0"
}
@@ -2808,9 +2808,9 @@
}
},
"node_modules/sass": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.108.0.tgz",
"integrity": "sha512-9HwnefouIfwY+XuA1rS5xOhALH5vsoe3SzYICG3MEwpkMbE7tpuh5ytZFRXUKPYkxY7lKdIbqxl+DxQGo8jwQQ==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.107.1.tgz",
"integrity": "sha512-aJ1/LvxOOb04YhmiBjzZn3jVwdHKol+OVhoMV6fFl02fF9T3i+5Mg9l/CnzqtM+NX5Jn5o3lAbs/ZJivTCLHfQ==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -2830,9 +2830,9 @@
}
},
"node_modules/sass-embedded": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.108.0.tgz",
"integrity": "sha512-F72wK29zJaTGjrwZogHDi+nRMYe8lEOtWzok9CVDjVdnBhbDu5TLFJ1a52/en3EDdFGj1HjrI/wwFT3E3u4eTQ==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.107.1.tgz",
"integrity": "sha512-DpU0lgDxNE2H7iycTfvvmig1NZ92SqO63D1PPRI8sBniHdpEOzxQno71YRXvEDQgPkaJ7mnljwX16s80AqydaQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2851,30 +2851,30 @@
"node": ">=20.19.0"
},
"optionalDependencies": {
"sass-embedded-all-unknown": "1.108.0",
"sass-embedded-android-arm": "1.108.0",
"sass-embedded-android-arm64": "1.108.0",
"sass-embedded-android-riscv64": "1.108.0",
"sass-embedded-android-x64": "1.108.0",
"sass-embedded-darwin-arm64": "1.108.0",
"sass-embedded-darwin-x64": "1.108.0",
"sass-embedded-linux-arm": "1.108.0",
"sass-embedded-linux-arm64": "1.108.0",
"sass-embedded-linux-musl-arm": "1.108.0",
"sass-embedded-linux-musl-arm64": "1.108.0",
"sass-embedded-linux-musl-riscv64": "1.108.0",
"sass-embedded-linux-musl-x64": "1.108.0",
"sass-embedded-linux-riscv64": "1.108.0",
"sass-embedded-linux-x64": "1.108.0",
"sass-embedded-unknown-all": "1.108.0",
"sass-embedded-win32-arm64": "1.108.0",
"sass-embedded-win32-x64": "1.108.0"
"sass-embedded-all-unknown": "1.107.1",
"sass-embedded-android-arm": "1.107.1",
"sass-embedded-android-arm64": "1.107.1",
"sass-embedded-android-riscv64": "1.107.1",
"sass-embedded-android-x64": "1.107.1",
"sass-embedded-darwin-arm64": "1.107.1",
"sass-embedded-darwin-x64": "1.107.1",
"sass-embedded-linux-arm": "1.107.1",
"sass-embedded-linux-arm64": "1.107.1",
"sass-embedded-linux-musl-arm": "1.107.1",
"sass-embedded-linux-musl-arm64": "1.107.1",
"sass-embedded-linux-musl-riscv64": "1.107.1",
"sass-embedded-linux-musl-x64": "1.107.1",
"sass-embedded-linux-riscv64": "1.107.1",
"sass-embedded-linux-x64": "1.107.1",
"sass-embedded-unknown-all": "1.107.1",
"sass-embedded-win32-arm64": "1.107.1",
"sass-embedded-win32-x64": "1.107.1"
}
},
"node_modules/sass-embedded-all-unknown": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.108.0.tgz",
"integrity": "sha512-QJXGw8zPjuWgvo5ASY15xldo/ZWB/aKDFb/0OMj57hUNMb6dvL6xEihn8Jc1xWLscQH7BWc7q3Vs3fOOwUsx2w==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.107.1.tgz",
"integrity": "sha512-8JVe87KQHSu/uMmcbcRa33AVDdwf0FSCR1tqA9fTaLrsqpgApD2YgqFr7KKCYTNRVSwzqAKdDaD2YJgx/siuVQ==",
"cpu": [
"!arm",
"!arm64",
@@ -2885,13 +2885,13 @@
"license": "MIT",
"optional": true,
"dependencies": {
"sass": "1.108.0"
"sass": "1.107.1"
}
},
"node_modules/sass-embedded-android-arm": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.108.0.tgz",
"integrity": "sha512-dsuky1EE7wvvIl02S9xTuEEY9+Mc1ypuZbPxy2XfBGHapgPh43k5Sg632HJZ3H84FOCAWHZ/zyFmhDkMvRdwIA==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.107.1.tgz",
"integrity": "sha512-qst7MmgqFwAHjbDN9Z+zjwMqmPM6RGu5ynXJFZmEmkkjCoQQX8DHUZhNCc2bASeLk/wyz1/9RCziUcJ6kn+E5w==",
"cpu": [
"arm"
],
@@ -2906,9 +2906,9 @@
}
},
"node_modules/sass-embedded-android-arm64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.108.0.tgz",
"integrity": "sha512-+yCynl1pBAEfv80Vc51KAlGwPVeu4rrNO8vhTWLBvT3nhkA4yzZqHRfWIKRhpiyeWbfJyKbePj9e3ko1y918Tw==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.107.1.tgz",
"integrity": "sha512-tk1uq03Jqba2OuktUuIVQ0eSERB4oCcYiZ88wdzX1edWT/Yc7c4x6ECl2+7zqXec6SGIUDZlI86nurN5fTJLHA==",
"cpu": [
"arm64"
],
@@ -2923,9 +2923,9 @@
}
},
"node_modules/sass-embedded-android-riscv64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.108.0.tgz",
"integrity": "sha512-UI3m/tKz9aXcaWBWLWyVj503GsCYI1NSMzXtaWzfjB2hGAhd6D5kdExFoBn4LggX6X4if6PbOBZx6bed9T0kug==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.107.1.tgz",
"integrity": "sha512-WzBSIg44+XP15kc+G2qtpfYBm0BtxjuC/X11eEg2L5Ihw45DoBtSLkpkSpLd9tvxDJOiTK3AHd1/iv5oGNvibg==",
"cpu": [
"riscv64"
],
@@ -2940,9 +2940,9 @@
}
},
"node_modules/sass-embedded-android-x64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.108.0.tgz",
"integrity": "sha512-dUZZ8CnBBbhXsyZ5wd9hBzIriNZ7Ifff4+YE9+AZ+B09v4elhStPS7AlOT14JeYVJjGbNXhbxCfe3T7KZ6gGhw==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.107.1.tgz",
"integrity": "sha512-K6YN7kqj9aBLmraVDiPIHF7U8qoD9E/6AJIVwj1Y5H0EgPjGOsv1sYu9Uy6SBLvWGg4dsydhbPU7VC+hTGWk9A==",
"cpu": [
"x64"
],
@@ -2957,9 +2957,9 @@
}
},
"node_modules/sass-embedded-darwin-arm64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.108.0.tgz",
"integrity": "sha512-Szzt9gF7x4IENOW7qslyCciXipKNk9YSesLqhJr79LZMrRIMpkPo9BeDfQDJlZ9WMDGHCL2JXfxR10BKWX4+Hw==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.107.1.tgz",
"integrity": "sha512-okhyzPI4cLNwa/xRIWbpkRGKmebaNp1+15V5PxVsQbzd8c+dn7eZje2Vf5CWxv9jRZ0nJgM1K/F61Wwb0w8Tyg==",
"cpu": [
"arm64"
],
@@ -2974,9 +2974,9 @@
}
},
"node_modules/sass-embedded-darwin-x64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.108.0.tgz",
"integrity": "sha512-DWNGSd7yHD0zg4esDQk5cwaJef85SeVXZBINt/63UvaYRhzMcUYB/E1mBcGv+wV/bN9cWI7YHILZrrbgkOQDsw==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.107.1.tgz",
"integrity": "sha512-hMMcxMxTiWoMaCfEvZqofN2l/yW++S0ANdVA3uHbVYO1LeRf9MrOWlOkJCjsbJO5FvfZdKGUxq/hc/5FKX9PXQ==",
"cpu": [
"x64"
],
@@ -2991,9 +2991,9 @@
}
},
"node_modules/sass-embedded-linux-arm": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.108.0.tgz",
"integrity": "sha512-6ReA1J1WJl0WjN+ffmfh1qtJt7phF5r8rkyQzWy06NK8aunJRnb+Syd2Wx2N+0LbEXqqYKmyILnEeiXkAsuqRQ==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.107.1.tgz",
"integrity": "sha512-k/UIsseDf63xo5qwV1kZgTmJtFlBAKLQf3xb++NmQPv7zvdOZxJ/MVUd1cuDx7vuanVKhM+U6R1mW2GuQxEGHA==",
"cpu": [
"arm"
],
@@ -3009,9 +3009,9 @@
}
},
"node_modules/sass-embedded-linux-arm64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.108.0.tgz",
"integrity": "sha512-GE6oESJuGtLYbifeK7r0AJ2LKOiM8doCmI1hYfVbyG2SqGV0vdEEo1P156PJy07TaDoal4zOLViQ4a+S1VgTkA==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.107.1.tgz",
"integrity": "sha512-cDeuJi63cL2cfr9OZoB2z1jd7Omhdgbj7zBxawZ62NFLe/gYVgeUsHbkB0rh1xbsuMJ9nOu9Mu6bkw8N0XnigQ==",
"cpu": [
"arm64"
],
@@ -3027,9 +3027,9 @@
}
},
"node_modules/sass-embedded-linux-musl-arm": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.108.0.tgz",
"integrity": "sha512-oOWV5mlrmk54/7tluqifbPQUkNcJ/A7Zp0wVFTvrPu6mu5QVks5yWHyT4uNkk8MNNdvPqHr3OvKg4qGDbXXxgw==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.107.1.tgz",
"integrity": "sha512-jshFSmPp7/tq3zV5l7KEDWuZKN6aewTnKMkWzgXN4oiBvRKFWAeQqG2Acn+gjMwtrvY0aRGZxrgreJGwRmFZlg==",
"cpu": [
"arm"
],
@@ -3045,9 +3045,9 @@
}
},
"node_modules/sass-embedded-linux-musl-arm64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.108.0.tgz",
"integrity": "sha512-VqTP2WROzT1qtHP08YV4JYebA/N9KYRWTWp42MRnpvZu7ZrPlsIWV0whLY/XHhOOvtQOj6nKP+X9QXi+FEU+yA==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.107.1.tgz",
"integrity": "sha512-Pr7kApBThIJjKG7FkGIsFvYrhj8aCu7kEuov7WiK3ExUiv5m+Vz8eYzjqIEGGCAyVIGMuuvHCvPmuMUynPZ1CA==",
"cpu": [
"arm64"
],
@@ -3063,9 +3063,9 @@
}
},
"node_modules/sass-embedded-linux-musl-riscv64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.108.0.tgz",
"integrity": "sha512-8z0jeVucmMj3a5RG0yDHfdfnQtC260XHsuRybNTFUNgrTk7SZksCvECS7f3NvFkqLXHVizonzBJbQwjSnRGbIw==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.107.1.tgz",
"integrity": "sha512-5oJVR7xt0yQnIlW/1Xz+H5Bl2Tix5Gl4qrlrVvUCzfdFUWBwLSZi6KlabjC41UjRisandO3nxHXPZeI1T99krQ==",
"cpu": [
"riscv64"
],
@@ -3081,9 +3081,9 @@
}
},
"node_modules/sass-embedded-linux-musl-x64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.108.0.tgz",
"integrity": "sha512-zRy5k4IACKRsElljiuJ/5ZDXgIe2TI5B3lEe16XgfZvbfdPAsBrrtm735CbVeWn5Unnwdo8PatHbZG7qH2QBpQ==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.107.1.tgz",
"integrity": "sha512-ntHvwls0ImF6p9qgZBuIF+BKIZ+6FqrRKZn0JhiFzb48y5o/V0mre6YEmdq8YcYVxPrGaU+Ajk96lpTE7gUC8w==",
"cpu": [
"x64"
],
@@ -3099,9 +3099,9 @@
}
},
"node_modules/sass-embedded-linux-riscv64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.108.0.tgz",
"integrity": "sha512-ioEI9Kjeq7r0bXOYvwdoiV2viu8kSgWgF/Z7eEHWuYPBG+hHgvO8L2FqVIeTcVLDawVjtIjRB1ND5m41HKjisw==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.107.1.tgz",
"integrity": "sha512-m8zLEdUPafxCAXtqx5FgBylIlPaUcb4eBx1lE8ENp/kaqqTMmaapofl+YWFI8xII3id+4rePZBipR142vHnNpQ==",
"cpu": [
"riscv64"
],
@@ -3117,9 +3117,9 @@
}
},
"node_modules/sass-embedded-linux-x64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.108.0.tgz",
"integrity": "sha512-bf1UD1+Nl9yoyjPWIsNKx6Q+5TM7IKSb3LGKkI/GGbkkI7dtfXDuEX4K8raAe7vyl6YwsOuk5CIqLC8keJGGiQ==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.107.1.tgz",
"integrity": "sha512-ix29w9TrUrvpzjOir+Ndx3RH5VLJncjq6CMystVUVbx5rpYyyaSzciOm5NKF227ifivhuhWYOFPCkq1NedmXfQ==",
"cpu": [
"x64"
],
@@ -3135,9 +3135,9 @@
}
},
"node_modules/sass-embedded-unknown-all": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.108.0.tgz",
"integrity": "sha512-8LekO+SieJSup8RR4iZlXEPiIC5+LAla6qdbezTgnEiFeE6TlnRUJC4ymwlgNVSuW439lIZxzEslE1gdQMlluw==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.107.1.tgz",
"integrity": "sha512-7JKs9q+V/kyVBesAjMa8hXx/qk6/cGKq/7cPSZoAWGu6oHx41wiJVfkZVAYt+fOFRHFXQunIKxIR9ZV7nA63PA==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -3148,13 +3148,13 @@
"!win32"
],
"dependencies": {
"sass": "1.108.0"
"sass": "1.107.1"
}
},
"node_modules/sass-embedded-win32-arm64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.108.0.tgz",
"integrity": "sha512-thH2piu717tsswAUNzR5oUvCN99F1JhjgOposze0xD5RfVNrNZk91FKokOJS04raf564x0JieOe7zF7iwsemIA==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.107.1.tgz",
"integrity": "sha512-/DmYPuToDvhsT4Oz1RQuOvQuYFzhcjzAfxjwhRPdWXxGO1OR8+BhbxyXqOUMpMLwgFT9Du3GPjD1yvy8BXnTZQ==",
"cpu": [
"arm64"
],
@@ -3169,9 +3169,9 @@
}
},
"node_modules/sass-embedded-win32-x64": {
"version": "1.108.0",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.108.0.tgz",
"integrity": "sha512-zrkPoApM8srP2ZStPxy9S/+LFfRpbxGsCSKNQMNUSXNfntQhMApejlSmcqryS3tJnp65RE/VnOEfLQIYy4c8nw==",
"version": "1.107.1",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.107.1.tgz",
"integrity": "sha512-B25UYFtuhnYiqvfLNlJZyDp2xV7T0aT9nueE2w+QhDPM/wCZyeQfj1dgMgq0HYBwEybgx0oLuxomgTqplmQ+eg==",
"cpu": [
"x64"
],
@@ -30,7 +30,7 @@
"axios-mock-adapter": "^2.1.0",
"jsdom": "^31.0.0",
"oxlint": "^1.91.0",
"sass-embedded": "^1.108.0",
"sass-embedded": "1.107",
"vite": "^8.3.6",
"vitest": "^5.1.0"
}
@@ -1,6 +1,7 @@
import Button from './components/buttons/Button';
import ExampleUserList from './components/examples/ExampleUserList';
// import ExampleUserList from './components/examples/ExampleUserList';
import FormContact from './components/forms/FormContact';
import ListUser from './components/lists/ListUser';
function App(props) {
// const { } = props;
@@ -9,7 +10,7 @@ function App(props) {
<div className="container py-5">
<h1>Testing in React</h1>
<hr />
<ExampleUserList />
<ListUser />
<hr />
<Button />
<hr />
@@ -0,0 +1,80 @@
import axios from 'axios';
import { useEffect, useState } from 'react';
const ListUser = (props) => {
// const { } = props;
const [users, setUsers] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
const controller = new AbortController(); // 2019
setIsLoading(true);
axios
.get('https://dummyjson.com/users?limit=100', {
signal: controller.signal,
})
.then(({ data }) => {
console.log(data);
setUsers(data?.users ?? []);
setError(null);
})
.catch((err) => {
//
// if (err.name === 'AbortError') {}
if (axios.isCancel(err)) {
console.error('Request abgebrochen:', err.message);
} else {
console.error('Error:', err);
setError(err);
}
})
.finally(() => {
// Nur wenn die Komponente nicht abgebrochen/unmounted wurde,
// den Lade-Zustand auf false setzen
if (!controller.signal.aborted) {
setIsLoading(false);
}
});
return () => {
// umount
controller.abort();
};
}, []);
if (isLoading) {
return <p className="text-muted alert alert-secondary">is loading users...</p>;
}
if (error) {
const status = error.response?.status;
return (
<p className="alert alert-danger" role="alert">
{status ? `Failed to load users (HTTP ${status})` : 'Failed to load users'}
</p>
);
}
return (
<ul className="list-todo list-group">
{users.length > 0 &&
users.map(({ id, firstName, lastName, age, email }, idx) => (
<li key={`list-item-user-${id}`} className="list-group-item list-item-user">
<p>
<strong>Name:</strong>
{firstName} {lastName}
<br />
<strong>age:</strong> {age}
<br />
<strong>email:</strong> {email}
<br />
</p>
</li>
))}
</ul>
);
};
export default ListUser;
@@ -1,7 +1,27 @@
import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import ExampleUserList from '../components/examples/ExampleUserList';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
const mock = new MockAdapter(axios);
describe('ExampleUserList', () => {
it('should load and display user names', () => {
it('should load and display user names', async () => {
const mockData = {
users: [
{ id: 1, firstName: 'John' }, //
],
};
mock.onGet('https://dummyjson.com/users?limit=3').reply(200, mockData);
render(<ExampleUserList />);
const user = await screen.findByText(/John/i);
screen.debug();
expect(user).toBeInTheDocument();
});
});
@@ -0,0 +1,89 @@
import { expect, it, describe, beforeEach, afterEach, vi } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import ListUser from '../components/lists/ListUser';
const USERS_API_URL = 'https://dummyjson.com/users?limit=100';
const userResponse = {
users: [
{
id: 1,
firstName: 'John',
lastName: 'Doe',
age: 28,
email: 'john.doe@example.com',
},
],
total: 1,
skip: 0,
limit: 100,
};
const mock = new MockAdapter(axios);
beforeEach(() => {
vi.spyOn(console, 'log');
vi.spyOn(console, 'error');
});
afterEach(() => {
mock.reset();
vi.restoreAllMocks();
});
describe('ListUser', () => {
it('should load and display user data on HTTP status 200', async () => {
mock.onGet(USERS_API_URL).reply(200, userResponse);
render(<ListUser />);
expect(screen.getByText(/is loading users/i)).toBeInTheDocument();
expect(await screen.findByText(/John/i)).toBeInTheDocument();
expect(screen.getByText(/Doe/i)).toBeInTheDocument();
expect(screen.getByText(/28/)).toBeInTheDocument();
expect(screen.getByText(/john.doe@example.com/)).toBeInTheDocument();
expect(screen.queryByText(/is loading users/i)).not.toBeInTheDocument();
});
it('should show an empty list on HTTP 200 when no users are returned', async () => {
mock.onGet(USERS_API_URL).reply(200, { users: [], total: 0, skip: 0, limit: 100 });
render(<ListUser />);
await waitFor(() => {
expect(screen.queryByText(/is loading users/i)).not.toBeInTheDocument();
});
expect(screen.queryByRole('listitem')).not.toBeInTheDocument();
expect(screen.queryByRole('alert')).not.toBeInTheDocument();
});
it.each([
[400, 'Bad Request'],
[401, 'Unauthorized'],
[403, 'Forbidden'],
[404, 'Not Found'],
[500, 'Internal Server Error'],
[503, 'Service Unavailable'],
])('should show an error for HTTP %s (%s)', async (status) => {
mock.onGet(USERS_API_URL).reply(status);
render(<ListUser />);
expect(await screen.findByRole('alert')).toHaveTextContent(`Failed to load users (HTTP ${status})`);
expect(screen.queryByText(/John/i)).not.toBeInTheDocument();
expect(screen.queryByText(/is loading users/i)).not.toBeInTheDocument();
});
it('should show a generic error on network failure', async () => {
mock.onGet(USERS_API_URL).networkError();
render(<ListUser />);
expect(await screen.findByRole('alert')).toHaveTextContent('Failed to load users');
expect(screen.queryByText(/HTTP/i)).not.toBeInTheDocument();
expect(screen.queryByText(/John/i)).not.toBeInTheDocument();
});
});
+6
View File
@@ -0,0 +1,6 @@
# Meeting Fr. 06.11.2026
- [ ] Benjamin 14:30 - 14:35
- [ ] Florian 14:35 - 14:40
- [ ] Christian 14:45 - 14:50
- [ ] Stefan 14:50 - 14:55