This commit is contained in:
pro.boooooo 2024-04-01 12:55:40 +02:00
parent 61a3513ef4
commit 7402661aaa
22 changed files with 175 additions and 73 deletions

4
.gitignore vendored
View File

@ -18,3 +18,7 @@ coverage.txt
/playwright-report/
/blob-report/
/playwright/.cache/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

View File

@ -25,6 +25,12 @@
pnpm run dev
```
### Test
```
```
## Membre
Bilal Boudjemline

View File

@ -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 :)

View File

@ -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");
});

View File

@ -1,13 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favico.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

View File

@ -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"
}
}
}

View File

@ -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,
},
});

2
pnpm-lock.yaml generated
View File

@ -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

BIN
public/favico.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
public/favico.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@ -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();
}
});

View File

@ -1,3 +0,0 @@
export default function Stats({ chart = null, datas }) {
return <div>{chart ? chart : null}</div>;
}

View File

@ -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 = () => {

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
});

View File

@ -1,2 +1,2 @@
export * from "./authenticated";
export * from "./home/home";
export * from "./home/Home";

View File

@ -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 <votre_pseudo>.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() {
/>
<StylizedBtn handle={handleSubmitPassword} text="OK" />
</div>
<div className="profile-modifier-container">
<span onClick={handleHelpIE} className="profile-modifier-title ">
Fais voyager tes depenses.
</span>
<StylizedBtn
perso_style={{ width: "100px" }}
handle={null}
text="Exporter"
/>
<StylizedBtn
perso_style={{ width: "100px" }}
handle={null}
text="Importer"
/>
</div>
</div>
);
}

View File

@ -16,6 +16,7 @@ export default function Room() {
useEffect(() => {
getRoom(id).then((res) => {
console.log(res);
document.title = `Piece - ${res.name}`;
setData(res);
});
}, []);

View File

@ -35,6 +35,8 @@ export default function Rooms() {
};
useEffect(() => {
document.title = `Pieces`;
getRooms().then((res) => {
if (res.length === 0) {
setIsLoad(false);

View File

@ -8,6 +8,7 @@ import { Home, Login, Register } from "./pages";
export const Router = () => (
<Routes>
<Route index element={<Home />} />
<Route path="home" element={<Home />} />
<Route path="login" element={<Login />} />
<Route path="register" element={<Register />} />
<Route path="rooms/" element={<Rooms />} />

View File

@ -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);
});