diff --git a/.gitignore b/.gitignore index 2bc6ec5..875c1d5 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,7 @@ coverage.txt /playwright-report/ /blob-report/ /playwright/.cache/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/README.md b/README.md index 3d1d432..5ad160f 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,12 @@ pnpm run dev ``` +### Test + +``` + +``` + ## Membre Bilal Boudjemline diff --git a/__tests__/pages/authenticated/Login.test.jsx b/__tests__/pages/authenticated/Login.test.jsx index db646c2..f299537 100644 --- a/__tests__/pages/authenticated/Login.test.jsx +++ b/__tests__/pages/authenticated/Login.test.jsx @@ -28,11 +28,13 @@ describe("Login Component", () => { target: { value: "testuser" }, }); fireEvent.change(screen.getByPlaceholderText("password"), { - target: { value: "password123" }, + target: { value: "Password123!!@" }, }); expect(screen.getByPlaceholderText("username").value).toBe("testuser"); - expect(screen.getByPlaceholderText("password").value).toBe("password123"); + expect(screen.getByPlaceholderText("password").value).toBe( + "Password123!!@", + ); }); it("handles submit event", async () => { @@ -40,11 +42,11 @@ describe("Login Component", () => { target: { value: "testuser" }, }); fireEvent.change(screen.getByPlaceholderText("password"), { - target: { value: "password123" }, + target: { value: "Password123!!@" }, }); fireEvent.click(screen.getByText("submit")); - expect(loginFunction).toHaveBeenCalledWith("testuser", "password123"); + expect(loginFunction).toHaveBeenCalledWith("testuser", "Password123!!@"); }); //TODO add more tests please :) diff --git a/e2e-tests/example.spec.js b/e2e-tests/example.spec.js deleted file mode 100644 index 9912e2c..0000000 --- a/e2e-tests/example.spec.js +++ /dev/null @@ -1,9 +0,0 @@ -// @ts-check -import { test, expect } from "@playwright/test"; - -test("has title on my project", async ({ page }) => { - await page.goto("/"); - - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle("Vite + React"); -}); diff --git a/index.html b/index.html index 0c589ec..8b9304d 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,13 @@ - - - - - - Vite + React - - -
- - + + + + + + + + +
+ + diff --git a/package.json b/package.json index 3b9de7e..ac4b120 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "test": "vitest", "test-e2e": "npx playwright test", "show-e2e": "npx playwright show-report", + "ui-test": "npx playwright test --ui", "preview": "vite preview", "format": "prettier --write 'src/**/*.{js,jsx}'", "prepare": "husky install" @@ -26,7 +27,7 @@ "sass": "^1.72.0" }, "devDependencies": { - "@playwright/test": "^1.41.1", + "@playwright/test": "^1.42.1", "@testing-library/react": "^14.1.2", "@types/node": "^20.11.9", "@types/react": "^18.2.43", @@ -43,4 +44,4 @@ "vite": "^5.0.8", "vitest": "^1.2.2" } -} +} \ No newline at end of file diff --git a/playwright.config.js b/playwright.config.js index e5b1c2a..95de71c 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -1,42 +1,78 @@ +// @ts-check import { defineConfig, devices } from "@playwright/test"; +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * @see https://playwright.dev/docs/test-configuration + */ export default defineConfig({ - // Look for test files in the "tests" directory, relative to this configuration file. - testDir: "e2e-tests", - - // Run all tests in parallel. + testDir: "./tests", + /* Run tests in files in parallel */ fullyParallel: true, - - // Fail the build on CI if you accidentally left test.only in the source code. - forbidOnly: !!import.meta.env.process.env.CI, - - // Retry on CI only. - retries: import.meta.env.process.env.CI ? 2 : 0, - - // Opt out of parallel tests on CI. - workers: import.meta.env.process.env.CI ? 1 : undefined, - - // Reporter to use + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: "html", - + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { - // Base URL to use in actions like `await page.goto('/')`. - baseURL: "http://localhost:5173/", + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: "http://127.0.0.1:3000", - // Collect trace when retrying the failed test. + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: "on-first-retry", }, - // Configure projects for major browsers. + + /* Configure projects for major browsers */ projects: [ { name: "chromium", use: { ...devices["Desktop Chrome"] }, }, + + // { + // name: "firefox", + // use: { ...devices["Desktop Firefox"] }, + // }, + + // { + // name: "webkit", + // use: { ...devices["Desktop Safari"] }, + // }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, ], - // Run your local dev server before starting the tests. + + //Run your local dev server before starting the tests / webServer: { command: "npm run dev", - url: "http://localhost:5173/", - reuseExistingServer: !import.meta.env.process.env.CI, + url: "http://127.0.0.1:3000", + reuseExistingServer: !process.env.CI, }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5c197e8..899500c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,7 +35,7 @@ dependencies: devDependencies: '@playwright/test': - specifier: ^1.41.1 + specifier: ^1.42.1 version: 1.42.1 '@testing-library/react': specifier: ^14.1.2 diff --git a/public/favico.ico b/public/favico.ico new file mode 100644 index 0000000..7482205 Binary files /dev/null and b/public/favico.ico differ diff --git a/public/favico.png b/public/favico.png new file mode 100644 index 0000000..4b200de Binary files /dev/null and b/public/favico.png differ diff --git a/src/components/NavBar/NavBar.jsx b/src/components/NavBar/NavBar.jsx index 1d03595..04c1e75 100644 --- a/src/components/NavBar/NavBar.jsx +++ b/src/components/NavBar/NavBar.jsx @@ -9,7 +9,6 @@ export default function NavBar() { const onLogout = () => { logout().then((res) => { if (res === "Ok") { - alert("etes vous sur de vouloir quitter"); window.location.reload(); } }); diff --git a/src/components/Stats/Stats.jsx b/src/components/Stats/Stats.jsx deleted file mode 100644 index fa98353..0000000 --- a/src/components/Stats/Stats.jsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Stats({ chart = null, datas }) { - return
{chart ? chart : null}
; -} diff --git a/src/contexts/auth-context.jsx b/src/contexts/auth-context.jsx index d716c6b..9e588b8 100644 --- a/src/contexts/auth-context.jsx +++ b/src/contexts/auth-context.jsx @@ -33,22 +33,25 @@ export const AuthenticationProvider = ({ children }) => { }; const login = async (email, password) => { - loginApi(email, password) - .then((user) => { - setAuthState({ user }); - redirect(); - }) - .catch(() => { - console.error("ici ca catch fort"); - setAuthState({ user: undefined }); - }); + try { + const user = await loginApi(email, password); + setAuthState({ user }); + redirect(); + } catch (error) { + console.error("Erreur lors de la connexion :", error); + setAuthState({ user: undefined }); + } }; const register = async (username, password, confirmation) => { - registerApi(username, password, confirmation).then((user) => { + try { + const user = await registerApi(username, password, confirmation); setAuthState({ user }); redirect(); - }); + } catch (error) { + console.error("Erreur lors de l'inscription :", error); + setAuthState({ user: undefined }); + } }; const logout = () => { diff --git a/src/pages/authenticated/login.jsx b/src/pages/authenticated/login.jsx index bca0e78..b740514 100644 --- a/src/pages/authenticated/login.jsx +++ b/src/pages/authenticated/login.jsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; - import { useAuth } from "../../hooks"; +import { useEffect } from "react"; export const Login = () => { const { login } = useAuth(); @@ -9,6 +9,10 @@ export const Login = () => { const [password, setPassword] = useState(""); const [error, setError] = useState(); + useEffect(() => { + document.title = "Connexion"; + }, []); + const onSubmit = async (e) => { e.preventDefault(); const response = await login(username, password); diff --git a/src/pages/authenticated/register.jsx b/src/pages/authenticated/register.jsx index 6e9e48e..76cbe9b 100644 --- a/src/pages/authenticated/register.jsx +++ b/src/pages/authenticated/register.jsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { useAuth } from "../../hooks"; @@ -10,6 +10,10 @@ export const Register = () => { const [confirmation, setConfirmation] = useState(""); const [error, setError] = useState(); + useEffect(() => { + document.title = "Inscription"; + }, []); + const onSubmit = async (e) => { e.preventDefault(); const response = await register(username, password, confirmation); diff --git a/src/pages/home/home.jsx b/src/pages/home/home.jsx index 1843c4e..8c43d18 100644 --- a/src/pages/home/home.jsx +++ b/src/pages/home/home.jsx @@ -4,7 +4,7 @@ import { useEffect } from "react"; import { getState } from "../../api"; import { useState } from "react"; import Chart from "react-apexcharts"; -import "./home.scss"; +import "./Home.scss"; import { Link } from "react-router-dom"; import LoaderSpace from "../../components/LoaderSpace/LoaderSpace"; @@ -16,6 +16,8 @@ export const Home = () => { const [isLoad, setIsLoad] = useState(true); useEffect(() => { + document.title = "Accueil"; + getState().then((res) => { try { setIsLoad(false); @@ -24,6 +26,7 @@ export const Home = () => { setupRoomsStats(res.rooms); setupGlobalStat({ years: res.years, global: res.global }); } catch (err) { + window.location.href = "/login"; console.error(err); } }); diff --git a/src/pages/index.js b/src/pages/index.js index e465d9e..07a281f 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -1,2 +1,2 @@ export * from "./authenticated"; -export * from "./home/home"; +export * from "./home/Home"; diff --git a/src/pages/profile/Profile.jsx b/src/pages/profile/Profile.jsx index 602d654..54cb460 100644 --- a/src/pages/profile/Profile.jsx +++ b/src/pages/profile/Profile.jsx @@ -15,11 +15,15 @@ export default function Profile() { const [confirmPassword, setConfirmPassword] = useState(""); useEffect(() => { - if (!user.user.username) { - console.log("pas de login"); - } + document.title = `Profile`; }); + const handleHelpIE = () => { + alert( + 'En cliquant sur le boutton "Exporter", vous recupererez un fichier .tascrujetaisriche qui contiendra les donnees de votre profile. Il pourra etre reutiliser sur un autre compte via le boutton "Importer"', + ); + }; + const handleUsername = (e) => { setUsername(e.target.value); }; @@ -91,7 +95,7 @@ export default function Profile() { perso_style={{ width: "100px", height: "50px", - background: "red", + background: "#ce5353", fontWeight: "bold", }} handle={handleDeleteUser} @@ -141,6 +145,24 @@ export default function Profile() { /> + +
+ + Fais voyager tes depenses. + + + + + +
); } diff --git a/src/pages/room/Room.jsx b/src/pages/room/Room.jsx index 4c59051..b619b2a 100644 --- a/src/pages/room/Room.jsx +++ b/src/pages/room/Room.jsx @@ -16,6 +16,7 @@ export default function Room() { useEffect(() => { getRoom(id).then((res) => { console.log(res); + document.title = `Piece - ${res.name}`; setData(res); }); }, []); diff --git a/src/pages/rooms/Rooms.jsx b/src/pages/rooms/Rooms.jsx index 4c18573..4612b6b 100644 --- a/src/pages/rooms/Rooms.jsx +++ b/src/pages/rooms/Rooms.jsx @@ -35,6 +35,8 @@ export default function Rooms() { }; useEffect(() => { + document.title = `Pieces`; + getRooms().then((res) => { if (res.length === 0) { setIsLoad(false); diff --git a/src/router.jsx b/src/router.jsx index 0cf0d10..2e883c7 100644 --- a/src/router.jsx +++ b/src/router.jsx @@ -8,6 +8,7 @@ import { Home, Login, Register } from "./pages"; export const Router = () => ( } /> + } /> } /> } /> } /> diff --git a/tests/authenticated/login.test.js b/tests/authenticated/login.test.js new file mode 100644 index 0000000..8e79c0d --- /dev/null +++ b/tests/authenticated/login.test.js @@ -0,0 +1,26 @@ +// @ts-check +import { test, expect } from "@playwright/test"; +import { waitFor } from "@testing-library/react"; + +test("Test de connexion", async ({ page }) => { + await page.goto("/login"); + await page + .locator( + "#layout-container > main > div > form > input[type=text]:nth-child(1)", + ) + .fill("Bilouuuuuuu94!@@"); + + await page + .locator( + "#layout-container > main > div > form > input[type=password]:nth-child(2)", + ) + .fill("Bilouuuuuuu94!@@"); + + await page.locator("#layout-container > main > div > form > button").click({ + button: "left", + }); + + await page.waitForURL("/"); + const title = await page.title(); + console.log(title); +});