$
This commit is contained in:
parent
873dd8c458
commit
3cf55ab609
@ -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();
|
|
||||||
});
|
|
@ -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 :)
|
|
||||||
});
|
|
@ -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"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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
316
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -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}>
|
||||||
|
@ -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 (
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
color: red;
|
color: $red;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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 = () => {
|
||||||
|
@ -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">
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -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 />} />
|
||||||
|
0
src/tests/services/password.test.js
Normal file
0
src/tests/services/password.test.js
Normal file
Binary file not shown.
Binary file not shown.
@ -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()],
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user