This commit is contained in:
pro.boooooo 2024-04-04 23:15:54 +02:00
parent 873dd8c458
commit 3cf55ab609
20 changed files with 70 additions and 440 deletions

View File

@ -1,19 +0,0 @@
// src/__ tests __/App.test.tsx
import { expect, test } from "vitest";
import { render } from "@testing-library/react";
import App from "../src/App.jsx";
import { BrowserRouter } from "react-router-dom";
test("demo", () => {
expect(true).toBe(true);
});
test("Renders the main page", () => {
render(
<BrowserRouter>
<App />
</BrowserRouter>,
);
expect(true).toBeTruthy();
});

View File

@ -1,53 +0,0 @@
import { describe, it, expect, beforeEach, vi, afterEach } from "vitest";
import { render, fireEvent, screen, cleanup } from "@testing-library/react";
import { Login } from "../../../src/pages/index.js";
import { AuthenticationContext } from "../../../src/contexts/index.js";
describe("Login Component", () => {
let loginFunction;
beforeEach(() => {
loginFunction = vi.fn(); // Mock login function
render(
<AuthenticationContext.Provider value={{ login: loginFunction }}>
<Login />
</AuthenticationContext.Provider>,
);
});
afterEach(() => {
cleanup();
});
it("renders without errors", () => {
expect(screen.getByText("Login page")).toBeTruthy();
});
it("allows entering a username and password", () => {
fireEvent.change(screen.getByPlaceholderText("username"), {
target: { value: "testuser" },
});
fireEvent.change(screen.getByPlaceholderText("password"), {
target: { value: "Password123!!@" },
});
expect(screen.getByPlaceholderText("username").value).toBe("testuser");
expect(screen.getByPlaceholderText("password").value).toBe(
"Password123!!@",
);
});
it("handles submit event", async () => {
fireEvent.change(screen.getByPlaceholderText("username"), {
target: { value: "testuser" },
});
fireEvent.change(screen.getByPlaceholderText("password"), {
target: { value: "Password123!!@" },
});
fireEvent.click(screen.getByText("submit"));
expect(loginFunction).toHaveBeenCalledWith("testuser", "Password123!!@");
});
//TODO add more tests please :)
});

View File

@ -1,7 +1,8 @@
{ {
"name": "projet-but3", "name": "2024-dev-but3",
"description": "Gestionnaire de depense portant le nom de : T'as cru j'etais riche ? (TCJR abrege).",
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.1",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@ -42,7 +43,6 @@
"husky": "^9.0.6", "husky": "^9.0.6",
"lint-staged": "^15.2.0", "lint-staged": "^15.2.0",
"prettier": "^3.2.4", "prettier": "^3.2.4",
"vite": "^5.0.8", "vite": "^5.0.8"
"vitest": "^1.2.2"
} }
} }

View File

@ -31,6 +31,8 @@ export default defineConfig({
trace: "on-first-retry", trace: "on-first-retry",
}, },
outputDir: "./tests/traces",
/* Configure projects for major browsers */ /* Configure projects for major browsers */
projects: [ projects: [
{ {

316
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@ export default function NavBar() {
{user ? ( {user ? (
<div className="leaf-into"> <div className="leaf-into">
<li className="leaf"> <li className="leaf">
<Link to="profile">Profile</Link> <Link to="profile">Profil</Link>
</li> </li>
<button className="leaf-btn" onClick={onLogout}> <button className="leaf-btn" onClick={onLogout}>

View File

@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import LoaderSpace from "../components/LoaderSpace/LoaderSpace";
import { import {
createUser as registerApi, createUser as registerApi,
isLoggedIn, isLoggedIn,
@ -17,7 +17,7 @@ const initState = {
export const AuthenticationContext = React.createContext({ export const AuthenticationContext = React.createContext({
...initState, ...initState,
login: async () => {}, login: async () => {},
register: () => {}, register: async () => {},
logout: async () => {}, logout: async () => {},
}); });
@ -90,7 +90,7 @@ export const AuthenticationProvider = ({ children }) => {
}, [location]); }, [location]);
if (isLoading) { if (isLoading) {
return <p>Loading...</p>; return <LoaderSpace isVisible={true} isCenterLoader={true} />;
} }
return ( return (

View File

@ -15,7 +15,7 @@
} }
.error { .error {
color: red; color: $red;
font-weight: bold; font-weight: bold;
} }

View File

@ -3,13 +3,13 @@ import { useAuth } from "../../hooks";
import { useEffect } from "react"; import { useEffect } from "react";
import "./authanticated.scss"; import "./authanticated.scss";
import "../../components/StylizedBtn/StylizedBtn.scss"; import "../../components/StylizedBtn/StylizedBtn.scss";
import passwordCheck from "../../services/password";
export const Login = () => { export const Login = () => {
const { login } = useAuth(); const { login } = useAuth();
const [username, setUsername] = useState(""); const [username, setUsername] = useState("");
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
const [error, setError] = useState();
useEffect(() => { useEffect(() => {
document.title = "Connexion"; document.title = "Connexion";
@ -17,18 +17,13 @@ export const Login = () => {
const onSubmit = async (e) => { const onSubmit = async (e) => {
e.preventDefault(); e.preventDefault();
const response = await login(username, password); await login(username, password);
if (response && !response.success) {
setError(response.error);
}
}; };
return ( return (
<div className="container"> <div className="container">
<form className="form" onSubmit={onSubmit}> <form className="form" onSubmit={onSubmit}>
<h3 className="title">Connexion</h3> <h3 className="title">Connexion</h3>
{error && <p>{error}</p>}
<input <input
type="text" type="text"

View File

@ -1,14 +1,13 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import "../../components/StylizedBtn/StylizedBtn.scss"; import "../../components/StylizedBtn/StylizedBtn.scss";
import { useAuth } from "../../hooks"; import { useAuth } from "../../hooks";
import passwordCheck from "../../services/password";
export const Register = () => { export const Register = () => {
const { register } = useAuth(); const { register } = useAuth();
const [username, setUsername] = useState(""); const [username, setUsername] = useState("");
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
const [confirmation, setConfirmation] = useState(""); const [confirmation, setConfirmation] = useState("");
const [error, setError] = useState(null);
useEffect(() => { useEffect(() => {
document.title = "Inscription"; document.title = "Inscription";
@ -17,19 +16,13 @@ export const Register = () => {
const onSubmit = async (e) => { const onSubmit = async (e) => {
try { try {
e.preventDefault(); e.preventDefault();
const response = await register(username, password, confirmation); if (!passwordCheck(password, confirmation)) {
alert(
if (!response) {
setError(
"Assurez vous que le mot de passe contient au moins 8 caracteres dont une majuscule, un symbole special et au minimum un chiffre.",
);
}
if (response && !response.success) {
setError(
"Assurez vous que le mot de passe contient au moins 8 caracteres dont une majuscule, un symbole special et au minimum un chiffre.", "Assurez vous que le mot de passe contient au moins 8 caracteres dont une majuscule, un symbole special et au minimum un chiffre.",
); );
return;
} }
await register(username, password, confirmation);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
@ -40,8 +33,6 @@ export const Register = () => {
<form className="form" onSubmit={onSubmit}> <form className="form" onSubmit={onSubmit}>
<h3 className="title">Inscription</h3> <h3 className="title">Inscription</h3>
{error ? <div className="error">{error}</div> : null}
<input <input
type="text" type="text"
value={username} value={username}

View File

@ -26,7 +26,6 @@ export const Home = () => {
setupRoomsStats(res.rooms); setupRoomsStats(res.rooms);
setupGlobalStat({ years: res.years, global: res.global }); setupGlobalStat({ years: res.years, global: res.global });
} catch (err) { } catch (err) {
window.location.href = "/login";
console.error(err); console.error(err);
} }
}); });

View File

@ -27,7 +27,7 @@ export default function Profile() {
const [isInAfterImport, setIsInAfterImport] = useState(false); const [isInAfterImport, setIsInAfterImport] = useState(false);
useEffect(() => { useEffect(() => {
document.title = `Profile`; document.title = `Profil de ${user.user.username}`;
}); });
const handleHelpIE = () => { const handleHelpIE = () => {

View File

@ -6,8 +6,10 @@ import AddBtn from "../../components/AddBtn/AddBtn";
import { createItem, deleteItem, updateItem } from "../../api/"; import { createItem, deleteItem, updateItem } from "../../api/";
import StylizedBtn from "../../components/StylizedBtn/StylizedBtn"; import StylizedBtn from "../../components/StylizedBtn/StylizedBtn";
import LoaderSpace from "../../components/LoaderSpace/LoaderSpace"; import LoaderSpace from "../../components/LoaderSpace/LoaderSpace";
import { useAuth } from "../../hooks";
export default function Room() { export default function Room() {
const { _user } = useAuth();
const { id } = useParams(); const { id } = useParams();
const [data, setData] = useState({}); const [data, setData] = useState({});
const [isInForm, setInForm] = useState(false); const [isInForm, setInForm] = useState(false);
@ -55,10 +57,17 @@ export default function Room() {
setIsInFormUpdate(!isInFormUpdate); setIsInFormUpdate(!isInFormUpdate);
}; };
const handleDelete = (id) => { const handleDelete = (item) => {
deleteItem(id).then((_) => { const confirmation = prompt(
`Etes-vous sur de vouloir supprimer ${item.brand} ${item.model} ? (oui ou non)`,
"oui",
);
if (!confirmation || confirmation.toLocaleLowerCase() !== "oui") return;
deleteItem(item._id).then((_) => {
const cpy = [...data.items]; const cpy = [...data.items];
const filtered = cpy.filter((e) => e._id !== id); const filtered = cpy.filter((e) => e._id !== item._id);
setData({ ...data, items: filtered }); setData({ ...data, items: filtered });
}); });
}; };
@ -127,7 +136,11 @@ export default function Room() {
<div id="item-actions-container"> <div id="item-actions-container">
<button <button
onClick={() => { onClick={() => {
handleDelete(e._id); handleDelete({
_id: e._id,
brand: e.brand,
model: e.model,
});
}} }}
id="item-delete-btn" id="item-delete-btn"
> >
@ -240,28 +253,28 @@ export default function Room() {
handleFormUpdateDataChange(e, "brand"); handleFormUpdateDataChange(e, "brand");
}} }}
type="text" type="text"
placeholder={formUpdateData.brand} placeholder={`(Marque) ${formUpdateData.brand}`}
/> />
<input <input
onChange={(e) => { onChange={(e) => {
handleFormUpdateDataChange(e, "model"); handleFormUpdateDataChange(e, "model");
}} }}
type="text" type="text"
placeholder={formUpdateData.model} placeholder={`(Modele) ${formUpdateData.model}`}
/> />
<input <input
onChange={(e) => { onChange={(e) => {
handleFormUpdateDataChange(e, "description"); handleFormUpdateDataChange(e, "description");
}} }}
type="text" type="text"
placeholder={formUpdateData.description} placeholder={`(Description) ${formUpdateData.description}`}
/> />
<input <input
onChange={(e) => { onChange={(e) => {
handleFormUpdateDataChange(e, "price"); handleFormUpdateDataChange(e, "price");
}} }}
type="number" type="number"
placeholder={formUpdateData.price} placeholder={`(Prix) ${formUpdateData.price}`}
/> />
<input <input
onChange={(e) => { onChange={(e) => {
@ -277,7 +290,7 @@ export default function Room() {
handleFormUpdateDataChange(e, "link"); handleFormUpdateDataChange(e, "link");
}} }}
type="text" type="text"
placeholder={formUpdateData.link} placeholder={`(Lien) ${formUpdateData.link}`}
/> />
<div id="actions"> <div id="actions">

View File

@ -11,7 +11,6 @@
height: 100%; height: 100%;
top: 0; top: 0;
left: 0; left: 0;
filter: blur(30px);
background: $primary; background: $primary;
z-index: 99; z-index: 99;
} }
@ -41,16 +40,16 @@
#item-actions-container { #item-actions-container {
position: absolute; position: absolute;
width: 25px; width: 30px;
height: 25px; height: 30px;
top: 10px; top: 0px;
right: 10px; right: 0px;
#item-update-btn { #item-update-btn {
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: 50px;
border: none; border: none;
border-bottom-left-radius: $my_border_rad;
&:hover { &:hover {
background-color: $orange; background-color: $orange;
@ -61,8 +60,9 @@
#item-delete-btn { #item-delete-btn {
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: 50px; font-size: 1em;
border: none; border: none;
border-top-right-radius: $my_border_rad;
&:hover { &:hover {
background: $red; background: $red;

View File

@ -4,11 +4,14 @@ import { createRoom, getRooms, deleteRoom } from "../../api";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import LoaderSpace from "../../components/LoaderSpace/LoaderSpace"; import LoaderSpace from "../../components/LoaderSpace/LoaderSpace";
import AddBtn from "./../../components/AddBtn/AddBtn"; import AddBtn from "./../../components/AddBtn/AddBtn";
import { useAuth } from "../../hooks";
export default function Rooms() { export default function Rooms() {
const { _user } = useAuth();
const [rooms, setRooms] = useState(null); const [rooms, setRooms] = useState(null);
const [isLoad, setIsLoad] = useState(true); const [isLoad, setIsLoad] = useState(true);
const [isErr, setIsErr] = useState(false); const [isErr, setIsErr] = useState(false);
const [splicedRooms, setSplicedRooms] = useState(null);
const onClickCreate = () => { const onClickCreate = () => {
const name = prompt("Nom de la piece ?"); const name = prompt("Nom de la piece ?");
@ -21,6 +24,22 @@ export default function Rooms() {
}); });
}; };
const configureRooms = (data) => {
const splicer = (rms, datasPerPage) => {
const partitions = [];
let index = 0;
while (index < rms.length) {
partitions.push(rms.slice(index, index + datasPerPage));
index += datasPerPage;
}
return partitions;
};
console.log(splicer(data, 8));
};
const onClickDelete = (id, name) => { const onClickDelete = (id, name) => {
const confirmation = prompt( const confirmation = prompt(
`Etes-vous sur de vouloir supprimer ${name} ? (oui ou non)`, `Etes-vous sur de vouloir supprimer ${name} ? (oui ou non)`,
@ -45,6 +64,7 @@ export default function Rooms() {
} }
setRooms(res); setRooms(res);
configureRooms(res);
}); });
}, []); }, []);

View File

@ -9,6 +9,7 @@ export const Router = () => (
<Routes> <Routes>
<Route index element={<Home />} /> <Route index element={<Home />} />
<Route path="home" element={<Home />} /> <Route path="home" element={<Home />} />
<Route path="stats" element={<Home />} />
<Route path="login" element={<Login />} /> <Route path="login" element={<Login />} />
<Route path="register" element={<Register />} /> <Route path="register" element={<Register />} />
<Route path="rooms/" element={<Rooms />} /> <Route path="rooms/" element={<Rooms />} />

View File

View File

@ -5,10 +5,5 @@ export default defineConfig({
server: { server: {
port: 3001, port: 3001,
}, },
test: {
include: ["__tests__/**/*.test.{js,jsx}"],
environment: "happy-dom",
},
plugins: [react()], plugins: [react()],
}); });