diff --git a/webapp/public/locales/en/translation.json b/webapp/public/locales/en/translation.json
index 88a9a527..ac05339f 100644
--- a/webapp/public/locales/en/translation.json
+++ b/webapp/public/locales/en/translation.json
@@ -15,7 +15,10 @@
"rules": "Rules",
"dashboard": "User's Dashboard",
"goBack": "Go Back",
- "finish": "Finish"
+ "finish": "Finish",
+ "english": "English",
+ "spanish": "Spanish",
+ "language": "Language:"
},
"session": {
"username": "Username",
@@ -68,5 +71,15 @@
"personalWrong": "{{wrong, number}} wrong answers",
"personalRate": "{{rate, number}} %"
}
+ },
+ "game": {
+ "round": "Round",
+ "next": "Next"
+ },
+ "about": {
+ "title": "About",
+ "description1": "We are the WIQ_EN2B group and we are delighted that you like 🥝KIWIQ🥝. Enjoy!!!",
+ "table1": "Developers🍌🍌",
+ "table2": "Contact"
}
}
\ No newline at end of file
diff --git a/webapp/public/locales/es/translation.json b/webapp/public/locales/es/translation.json
index 42b37ac6..41085ba4 100644
--- a/webapp/public/locales/es/translation.json
+++ b/webapp/public/locales/es/translation.json
@@ -15,7 +15,10 @@
"rules": "Reglas",
"dashboard": "Panel de Usuario",
"goBack": "Volver",
- "finish": "Finalizar"
+ "finish": "Finalizar",
+ "english": "Inglés",
+ "spanish": "Español",
+ "language": "Idioma:"
},
"session": {
"username": "Nombre de usuario",
@@ -67,5 +70,15 @@
"personalWrong": "{{wrong, number}} respuestas incorrectas",
"personalRate": "{{rate, number}} %"
}
+ },
+ "game": {
+ "round": "Ronda",
+ "next": "Siguiente"
+ },
+ "about": {
+ "title": "Sobre nosotros",
+ "description1": "Somos el grupo WIQ_EN2B y estamos encantados de que te guste 🥝KIWIQ🥝. Disfruta!!!",
+ "table1": "Desarrolladores🍌🍌",
+ "table2": "Contacto"
}
}
\ No newline at end of file
diff --git a/webapp/src/components/LateralMenu.jsx b/webapp/src/components/LateralMenu.jsx
new file mode 100644
index 00000000..dcce5e03
--- /dev/null
+++ b/webapp/src/components/LateralMenu.jsx
@@ -0,0 +1,123 @@
+import React, { useState, useEffect } from 'react';
+import PropTypes from 'prop-types';
+import { useNavigate } from "react-router-dom";
+import { useTranslation } from "react-i18next";
+import { Box, Drawer, DrawerOverlay, DrawerContent, DrawerCloseButton, DrawerHeader, DrawerBody, DrawerFooter, Select, Button, Text, IconButton, Flex, Image } from '@chakra-ui/react';
+import { FaChartBar, FaBook, FaTachometerAlt } from 'react-icons/fa';
+import { InfoIcon, SettingsIcon } from '@chakra-ui/icons';
+
+import AuthManager from "components/auth/AuthManager";
+
+const LateralMenu = ({ isOpen, onClose, changeLanguage, currentLanguage, isDashboard }) => {
+ const navigate = useNavigate();
+ const [selectedLanguage, setSelectedLanguage] = useState(currentLanguage);
+ const [isLoggedIn, setIsLoggedIn] = useState(false);
+ const { t } = useTranslation();
+
+ useEffect(() => {
+ setSelectedLanguage(currentLanguage);
+ checkIsLoggedIn();
+ }, [currentLanguage]);
+
+ const handleChangeLanguage = (e) => {
+ const selectedLanguage = e.target.value;
+ changeLanguage(selectedLanguage);
+ };
+
+ const handleApiClick = () => {
+ window.open("http://localhost:8080/swagger/swagger-ui/index.html#/auth-controller/registerUser", "_blank", "noopener");
+ };
+
+ const handleLogout = async () => {
+ try {
+ await new AuthManager().logout();
+ navigate("/");
+ } catch (error) {
+ console.error("Error al cerrar sesión:", error);
+ }
+ };
+
+ const checkIsLoggedIn = async () => {
+ try {
+ const loggedIn = await new AuthManager().isLoggedIn();
+ setIsLoggedIn(loggedIn);
+ } catch (error) {
+ console.error("Error al verificar el estado de inicio de sesión:", error);
+ }
+ };
+
+ return (
+
+
+
+
+
+
+ KIWIQ
+
+
+
+
+ {t("common.language")}
+
+
+
+ {isLoggedIn && (
+ <>
+ {!isDashboard && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+ >
+ )}
+
+
+
+
+
+ {isLoggedIn && (
+
+ )}
+ } className={"custom-button effect1"} onClick={() => {navigate("/about");}} margin={"10px"}>
+
+
+
+
+
+ );
+};
+
+LateralMenu.propTypes = {
+ isOpen: PropTypes.bool.isRequired,
+ onClose: PropTypes.func.isRequired,
+ changeLanguage: PropTypes.func.isRequired,
+ currentLanguage: PropTypes.string.isRequired,
+ isDashboard: PropTypes.bool.isRequired
+};
+
+export default LateralMenu;
diff --git a/webapp/src/components/MenuButton.jsx b/webapp/src/components/MenuButton.jsx
new file mode 100644
index 00000000..73e5a3e7
--- /dev/null
+++ b/webapp/src/components/MenuButton.jsx
@@ -0,0 +1,44 @@
+import React, { useState, useEffect } from "react";
+import PropTypes from 'prop-types';
+import { FaBars } from "react-icons/fa";
+import { chakra, Box, IconButton } from "@chakra-ui/react";
+
+const MenuButton = ({ onClick }) => {
+ const [isFixed, setIsFixed] = useState(false);
+
+ useEffect(() => {
+ const handleScroll = () => {
+ if (window.scrollY > 0) {
+ setIsFixed(true);
+ } else {
+ setIsFixed(false);
+ }
+ };
+
+ window.addEventListener("scroll", handleScroll);
+ return () => {
+ window.removeEventListener("scroll", handleScroll);
+ };
+ }, []);
+
+ return (
+
+ }
+ onClick={onClick}
+ />
+
+ );
+}
+
+MenuButton.propTypes = {
+ onClick: PropTypes.func.isRequired
+};
+
+export default MenuButton;
\ No newline at end of file
diff --git a/webapp/src/components/Router.jsx b/webapp/src/components/Router.jsx
index 8769eb25..435928f7 100644
--- a/webapp/src/components/Router.jsx
+++ b/webapp/src/components/Router.jsx
@@ -11,6 +11,7 @@ import Results from "../pages/Results";
import Statistics from "pages/Statistics";
import ProtectedRoute from "./utils/ProtectedRoute";
import Logout from "pages/Logout";
+import About from "pages/About";
export default createRoutesFromElements(
@@ -18,6 +19,7 @@ export default createRoutesFromElements(
} />
} />
}/>
+ } />
}>
}/>
}/>
diff --git a/webapp/src/i18n.js b/webapp/src/i18n.js
index a9a6fdb1..84bc133d 100644
--- a/webapp/src/i18n.js
+++ b/webapp/src/i18n.js
@@ -8,6 +8,9 @@ export default i18n.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
+ backend: {
+ loadPath: '/locales/{{lng}}/translation.json'
+ },
fallbackLng: "en",
debug: false
})
\ No newline at end of file
diff --git a/webapp/src/pages/About.jsx b/webapp/src/pages/About.jsx
new file mode 100644
index 00000000..af99bb39
--- /dev/null
+++ b/webapp/src/pages/About.jsx
@@ -0,0 +1,74 @@
+import React, { useState } from "react";
+import { useTranslation } from 'react-i18next';
+import { Center, Heading, Stack, Box, Text, Table, Thead, Tr, Td, Th, Tbody, Container } from '@chakra-ui/react';
+import { InfoIcon } from '@chakra-ui/icons';
+
+import LateralMenu from '../components/LateralMenu';
+import MenuButton from '../components/MenuButton';
+import GoBack from "components/GoBack";
+
+export default function About() {
+ const { t, i18n } = useTranslation();
+ const currentLanguage = i18n.language;
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+
+ const changeLanguage = (selectedLanguage) => {
+ i18n.changeLanguage(selectedLanguage);
+ };
+
+ return (
+
+ setIsMenuOpen(true)} />
+ setIsMenuOpen(false)} changeLanguage={changeLanguage} currentLanguage={currentLanguage} isDashboard={false}/>
+
+
+
+ {t('about.title')}
+
+
+ {t("about.description1")}
+
+
+
+
+ {t("about.table1")} |
+ {t("about.table2")} |
+
+
+
+
+ Gonzalo Alonso Fernández |
+ UO282104 |
+
+
+ Sergio Rodríguez García |
+ UO282598 |
+
+
+ Jorge Joaquín Gancedo Fernández |
+ UO282161 |
+
+
+ Darío Gutiérrez Mori |
+ UO282435 |
+
+
+ Sergio Quintana Fernández |
+ UO288090 |
+
+
+ Diego Villanueva Berros |
+ UO283615 |
+
+
+ Gonzalo Suárez Losada |
+ UO283928 |
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/webapp/src/pages/Dashboard.jsx b/webapp/src/pages/Dashboard.jsx
index 8e346ffe..a7ba0ee4 100644
--- a/webapp/src/pages/Dashboard.jsx
+++ b/webapp/src/pages/Dashboard.jsx
@@ -1,14 +1,17 @@
-import React from "react";
-import { Grid, Flex, Heading, Button, Box } from "@chakra-ui/react";
+import React, { useState } from "react";
+import { Heading, Button, Box, Stack } from "@chakra-ui/react";
import { Center } from "@chakra-ui/layout";
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
-import ButtonEf from '../components/ButtonEf';
+import { FaTachometerAlt } from 'react-icons/fa';
+
import AuthManager from "components/auth/AuthManager";
+import LateralMenu from '../components/LateralMenu';
+import MenuButton from '../components/MenuButton';
export default function Dashboard() {
const navigate = useNavigate();
- const { t } = useTranslation();
+ const { t, i18n } = useTranslation();
const handleLogout = async () => {
try {
@@ -19,22 +22,24 @@ export default function Dashboard() {
}
};
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+ const currentLanguage = i18n.language;
+ const changeLanguage = (selectedLanguage) => {
+ i18n.changeLanguage(selectedLanguage);
+ };
+
return (
+ setIsMenuOpen(true)} />
+ setIsMenuOpen(false)} changeLanguage={changeLanguage} currentLanguage={currentLanguage} isDashboard={true}/>
+
{t("common.dashboard")}
-
-
- navigate("/dashboard/rules")}/>
- navigate("/dashboard/game")}/>
- navigate("/dashboard/statistics")}/>
-
-
-
-
-
+
+
+
+
+
);
diff --git a/webapp/src/pages/Game.jsx b/webapp/src/pages/Game.jsx
index 957c0e55..19f4afb7 100644
--- a/webapp/src/pages/Game.jsx
+++ b/webapp/src/pages/Game.jsx
@@ -2,17 +2,21 @@ import React, { useState, useEffect, useCallback } from "react";
import { Grid, Flex, Heading, Button, Box, Text, Spinner } from "@chakra-ui/react";
import { Center } from "@chakra-ui/layout";
import { useNavigate } from "react-router-dom";
+import { useTranslation } from "react-i18next";
import Confetti from "react-confetti";
+import axios from "axios";
+
import ButtonEf from '../components/ButtonEf';
import {getQuestion, answerQuestion} from '../components/game/Questions';
-import axios from "axios";
+import LateralMenu from '../components/LateralMenu';
+import MenuButton from '../components/MenuButton';
export default function Game() {
const navigate = useNavigate();
const [question, setQuestion] = useState(null);
const [loading, setLoading] = useState(true);
-
+
const generateQuestion = useCallback(async () => {
const result = await getQuestion();
if (result !== undefined) {
@@ -73,9 +77,20 @@ export default function Game() {
return () => clearTimeout(timeout);
}, [showConfetti]);
+ const { t, i18n } = useTranslation();
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+
+ const currentLanguage = i18n.language;
+ const changeLanguage = (selectedLanguage) => {
+ i18n.changeLanguage(selectedLanguage);
+ };
+
return (
- {`Round ${roundNumber}`}
+ setIsMenuOpen(true)} />
+ setIsMenuOpen(false)} changeLanguage={changeLanguage} currentLanguage={currentLanguage} isDashboard={false}/>
+
+ {t("game.round") + `${roundNumber}`}
{`Correct answers: ${correctAnswers}`}
@@ -98,8 +113,8 @@ export default function Game() {
-
diff --git a/webapp/src/pages/Login.jsx b/webapp/src/pages/Login.jsx
index c3d82b42..61f80bb1 100644
--- a/webapp/src/pages/Login.jsx
+++ b/webapp/src/pages/Login.jsx
@@ -3,14 +3,15 @@ import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { FaLock, FaAddressCard } from "react-icons/fa";
import { Center } from "@chakra-ui/layout";
-import { Heading, Input, InputGroup, Stack, InputLeftElement, chakra, Box, Avatar, FormControl, InputRightElement, IconButton} from "@chakra-ui/react";
+import { Heading, Input, InputGroup, Stack, InputLeftElement, chakra, Box, Avatar, FormControl, InputRightElement, IconButton, Flex, Button} from "@chakra-ui/react";
import { ViewIcon, ViewOffIcon } from '@chakra-ui/icons';
-import ButtonEf from '../components/ButtonEf';
-import ErrorMessageAlert from "../components/ErrorMessageAlert";
+
+import ErrorMessageAlert from "components/ErrorMessageAlert";
import AuthManager from "components/auth/AuthManager";
+import LateralMenu from 'components/LateralMenu';
+import MenuButton from 'components/MenuButton';
export default function Login() {
-
const navigate = useNavigate();
const navigateToDashboard = async () => {
if (await new AuthManager().isLoggedIn()) {
@@ -19,7 +20,7 @@ export default function Login() {
}
const [errorMessage, setErrorMessage] = useState(null);
- const { t } = useTranslation();
+ const { t, i18n } = useTranslation();
const [showPassword, setShowPassword] = useState(false);
const changeShowP = () => setShowPassword(!showPassword);
@@ -60,9 +61,20 @@ export default function Login() {
navigateToDashboard();
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+
+ const currentLanguage = i18n.language;
+ const changeLanguage = (selectedLanguage) => {
+ i18n.changeLanguage(selectedLanguage);
+ };
+
return (
+
+ setIsMenuOpen(true)} />
+ setIsMenuOpen(false)} changeLanguage={changeLanguage} currentLanguage={currentLanguage} isDashboard={false}/>
+
{t("common.login")}
@@ -100,7 +112,10 @@ export default function Login() {
-
+
+ navigate("/")} flex="1">{t("common.goBack")}
+ {t("common.login")}
+
diff --git a/webapp/src/pages/Root.jsx b/webapp/src/pages/Root.jsx
index 5de99b7d..349551e9 100644
--- a/webapp/src/pages/Root.jsx
+++ b/webapp/src/pages/Root.jsx
@@ -1,15 +1,19 @@
-import React from "react";
+import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { Center } from "@chakra-ui/layout";
import { Text, Heading, Stack, Link, Image, Box } from "@chakra-ui/react";
+import MenuButton from '../components/MenuButton';
+import LateralMenu from '../components/LateralMenu';
import ButtonEf from '../components/ButtonEf';
import AuthManager from "components/auth/AuthManager";
export default function Root() {
const navigate = useNavigate();
- const { t } = useTranslation();
+ const { t, i18n } = useTranslation();
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+ const currentLanguage = i18n.language;
const navigateToDashboard = async () => {
if (await new AuthManager().isLoggedIn()) {
@@ -18,19 +22,28 @@ export default function Root() {
}
navigateToDashboard();
+ const changeLanguage = (selectedLanguage) => {
+ i18n.changeLanguage(selectedLanguage);
+ };
+
return (
-
-
-
-
- {"KIWIQ"}
- {t("session.welcome")}
- navigate("/login")}/>
- {t("session.account")} navigate("/signup")}>{t("session.clickHere")}
-
-
-
+ setIsMenuOpen(true)} />
+ setIsMenuOpen(false)} changeLanguage={changeLanguage} currentLanguage={currentLanguage} isDashboard={false}/>
+
+
+
+
+
+
+ {"KIWIQ"}
+ {t("session.welcome")}
+ navigate("/login")}/>
+ {t("session.account")} navigate("/signup")}>{t("session.clickHere")}
+
+
+
+
);
}
\ No newline at end of file
diff --git a/webapp/src/pages/Rules.jsx b/webapp/src/pages/Rules.jsx
index 01302b31..9e3c2855 100644
--- a/webapp/src/pages/Rules.jsx
+++ b/webapp/src/pages/Rules.jsx
@@ -1,14 +1,28 @@
-import React from "react";
+import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { Center } from "@chakra-ui/layout";
import { Text, Heading, Box } from "@chakra-ui/react";
+import { FaBook } from 'react-icons/fa';
+
import GoBack from "components/GoBack";
+import LateralMenu from '../components/LateralMenu';
+import MenuButton from '../components/MenuButton';
export default function Rules() {
- const { t } = useTranslation();
+ const { t, i18n } = useTranslation();
+
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+
+ const currentLanguage = i18n.language;
+ const changeLanguage = (selectedLanguage) => {
+ i18n.changeLanguage(selectedLanguage);
+ };
return (
+ setIsMenuOpen(true)} />
+ setIsMenuOpen(false)} changeLanguage={changeLanguage} currentLanguage={currentLanguage} isDashboard={false}/>
+
{t("common.rules")}
diff --git a/webapp/src/pages/Signup.jsx b/webapp/src/pages/Signup.jsx
index 4a4a0890..6ebf5c1d 100644
--- a/webapp/src/pages/Signup.jsx
+++ b/webapp/src/pages/Signup.jsx
@@ -1,13 +1,15 @@
import { Center } from "@chakra-ui/layout";
-import { Heading, Input, InputGroup, Stack, InputLeftElement, chakra, Box, Avatar, FormControl, InputRightElement, FormHelperText, IconButton} from "@chakra-ui/react";
+import { Heading, Input, InputGroup, Stack, InputLeftElement, chakra, Box, Avatar, FormControl, InputRightElement, FormHelperText, IconButton, Flex, Button} from "@chakra-ui/react";
import { ViewIcon, ViewOffIcon } from '@chakra-ui/icons'
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { FaUserAlt, FaLock, FaAddressCard } from "react-icons/fa";
-import ButtonEf from '../components/ButtonEf';
-import ErrorMessageAlert from "../components/ErrorMessageAlert";
+
+import ErrorMessageAlert from "components/ErrorMessageAlert";
import AuthManager from "components/auth/AuthManager";
+import LateralMenu from 'components/LateralMenu';
+import MenuButton from 'components/MenuButton';
export default function Signup() {
const [email, setEmail] = useState("");
@@ -19,7 +21,7 @@ export default function Signup() {
const [errorMessage, setErrorMessage] = useState(null);
const navigate = useNavigate();
- const { t } = useTranslation();
+ const { t, i18n } = useTranslation();
const ChakraFaCardAlt = chakra(FaAddressCard);
const ChakraFaUserAlt = chakra(FaUserAlt);
@@ -86,8 +88,18 @@ export default function Signup() {
navigateToDashboard();
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+
+ const currentLanguage = i18n.language;
+ const changeLanguage = (selectedLanguage) => {
+ i18n.changeLanguage(selectedLanguage);
+ };
+
return (
+ setIsMenuOpen(true)} />
+ setIsMenuOpen(false)} changeLanguage={changeLanguage} currentLanguage={currentLanguage} isDashboard={false}/>
+
@@ -160,7 +172,10 @@ export default function Signup() {
Las contraseñas no coinciden
)}
-
+
+ navigate("/")} flex="1">{t("common.goBack")}
+ {t("common.register")}
+
diff --git a/webapp/src/pages/Statistics.jsx b/webapp/src/pages/Statistics.jsx
index 1bb1899a..a386e23c 100644
--- a/webapp/src/pages/Statistics.jsx
+++ b/webapp/src/pages/Statistics.jsx
@@ -7,9 +7,13 @@ import { useTranslation } from "react-i18next";
import GoBack from "components/GoBack";
import AuthManager from "components/auth/AuthManager";
import { HttpStatusCode } from "axios";
+import { FaChartBar } from 'react-icons/fa';
+
+import LateralMenu from '../components/LateralMenu';
+import MenuButton from '../components/MenuButton';
const UserVisual = (props) => {
- const {t} = useTranslation();
+ const { t } = useTranslation();
const topTen = props.topTen;
const userData = props.userData;
const [tooSmall] = useMediaQuery("(max-width: 800px)");
@@ -107,7 +111,7 @@ const UserVisual = (props) => {
}
export default function Statistics() {
- const {t} = useTranslation();
+ const { t, i18n } = useTranslation();
const [retrievedData, setRetrievedData] = useState(false);
const [topTen, setTopTen] = useState([]);
const [userData, setUserData] = useState({
@@ -146,9 +150,20 @@ export default function Statistics() {
}
}
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+
+ const currentLanguage = i18n.language;
+ const changeLanguage = (selectedLanguage) => {
+ i18n.changeLanguage(selectedLanguage);
+ };
+
+
return (
+ setIsMenuOpen(true)} />
+ setIsMenuOpen(false)} changeLanguage={changeLanguage} currentLanguage={currentLanguage} isDashboard={false}/>
+
{t("common.statistics.title")}
} minW="30vw" minH="50vh"
p="1rem" backgroundColor="whiteAlpha.900" shadow="2xl"
diff --git a/webapp/src/tests/About.test.js b/webapp/src/tests/About.test.js
new file mode 100644
index 00000000..86cc766e
--- /dev/null
+++ b/webapp/src/tests/About.test.js
@@ -0,0 +1,32 @@
+import React from 'react';
+import { render, fireEvent, waitFor } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
+import { MemoryRouter } from 'react-router-dom';
+import About from '../pages/About';
+import theme from '../styles/theme';
+import { ChakraProvider } from '@chakra-ui/react';
+
+jest.mock('react-i18next', () => ({
+ useTranslation: () => ({
+ t: key => key,
+ i18n: {
+ changeLanguage: () => new Promise(() => {}),
+ },
+ }),
+}));
+
+describe('About Component', () => {
+ it('renders title and description correctly', () => {
+ const { getByText } = render();
+
+ expect(getByText('about.title')).toBeInTheDocument();
+ expect(getByText('about.description1')).toBeInTheDocument();
+ });
+
+ it('renders table rows with correct data', () => {
+ const { getByText } = render();
+
+ expect(getByText('Gonzalo Alonso Fernández')).toBeInTheDocument();
+ expect(getByText('UO282104')).toBeInTheDocument();
+ });
+});
diff --git a/webapp/src/tests/Dashboard.test.js b/webapp/src/tests/Dashboard.test.js
index bf56f45e..0116c55c 100644
--- a/webapp/src/tests/Dashboard.test.js
+++ b/webapp/src/tests/Dashboard.test.js
@@ -34,31 +34,11 @@ describe('Dashboard component', () => {
expect(getByText("common.dashboard")).toBeInTheDocument();
- expect(screen.getByTestId('Rules')).toBeInTheDocument();
expect(screen.getByTestId('Play')).toBeInTheDocument();
- expect(screen.getByTestId('Statistics')).toBeInTheDocument();
expect(screen.getByText(/logout/i)).toBeInTheDocument();
});
- it('navigates to the rules route on button click', () => {
- render();
-
- const rulesButton = screen.getByTestId('Rules');
- fireEvent.click(rulesButton);
-
- expect(screen.getByText("common.rules")).toBeInTheDocument();
- });
-
- it('do not navigates to the statistics route on button click', () => {
- render();
-
- const statisticsButton = screen.getByTestId('Statistics');
- fireEvent.click(statisticsButton);
-
- expect(screen.getByText("common.dashboard")).toBeInTheDocument();
- });
-
it('navigates to the game route on "Play" button click', () => {
render();
@@ -68,15 +48,6 @@ describe('Dashboard component', () => {
expect(screen.getByText("common.play")).toBeInTheDocument();
});
- it('does not navigate to the statistics route on button click', () => {
- render();
-
- const statisticsButton = screen.getByTestId('Statistics');
- fireEvent.click(statisticsButton);
-
- expect(screen.getByText("common.dashboard")).toBeInTheDocument();
- });
-
it('handles logout successfully', async () => {
render();
mockAxios.onGet().replyOnce(HttpStatusCode.Ok);
@@ -89,13 +60,4 @@ describe('Dashboard component', () => {
expect(mockAxios.history.get.length).toBe(1);
expect(screen.getByText("common.dashboard")).toBeInTheDocument();
});
-
- it('does not navigate to the statistics route on disabled button click', () => {
- render();
-
- const statisticsButton = screen.getByTestId('Statistics');
- fireEvent.click(statisticsButton);
-
- expect(screen.getByText("common.dashboard")).toBeInTheDocument();
- });
});
diff --git a/webapp/src/tests/Game.test.js b/webapp/src/tests/Game.test.js
index fada5791..07d4a293 100644
--- a/webapp/src/tests/Game.test.js
+++ b/webapp/src/tests/Game.test.js
@@ -47,7 +47,7 @@ describe('Game component', () => {
test('disables next button when no option is selected', async () => {
render();
- const nextButton = await screen.findByText('Next');
+ const nextButton = await screen.findByTestId('Next');
expect(nextButton).toBeDisabled();
});
@@ -55,7 +55,7 @@ describe('Game component', () => {
test('enables next button when an option is selected', async () => {
render();
const option1Button = await screen.findByTestId('Option1');
- const nextButton = await screen.findByText('Next');
+ const nextButton = await screen.findByTestId('Next');
act(() => fireEvent.click(option1Button));
diff --git a/webapp/src/tests/LateralMenu.test.js b/webapp/src/tests/LateralMenu.test.js
new file mode 100644
index 00000000..24f6ef78
--- /dev/null
+++ b/webapp/src/tests/LateralMenu.test.js
@@ -0,0 +1,132 @@
+import React from 'react';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
+import { MemoryRouter } from 'react-router';
+import { ChakraProvider } from '@chakra-ui/react';
+import theme from '../styles/theme';
+import AuthManager from '../components/auth/AuthManager';
+import LateralMenu from '../components/LateralMenu';
+
+jest.mock('react-i18next', () => ({
+ useTranslation: () => {
+ return {
+ t: (str) => str,
+ i18n: {
+ changeLanguage: () => new Promise(() => {}),
+ },
+ }
+ },
+}));
+
+jest.mock('react-router-dom', () => ({
+ ...jest.requireActual('react-router-dom'),
+ useNavigate: jest.fn(),
+}));
+
+ const authManager = new AuthManager();
+
+describe('LateralMenu component', () => {
+ beforeEach(() => {
+ authManager.reset();
+ jest.clearAllMocks();
+ });
+
+ const props = {
+ isOpen: true,
+ onClose: jest.fn(),
+ changeLanguage: jest.fn(),
+ currentLanguage: 'es',
+ isLoggedIn: true,
+ isDashboard: false,
+ };
+
+ it('renders KIWIQ heading', () => {
+ render();
+ const headingElement = screen.getByText('KIWIQ');
+ expect(headingElement).toBeInTheDocument();
+ });
+
+ it('renders language select', () => {
+ render();
+ const languageSelect = screen.getByText('common.language');
+ expect(languageSelect).toBeInTheDocument();
+ });
+
+ it('changes language when select value is changed', () => {
+ render();
+ const selectElement = screen.getByTestId('language-select');
+ fireEvent.change(selectElement, { target: { value: 'en' } });
+ expect(props.changeLanguage).toHaveBeenCalledWith('en');
+ });
+
+ it('does not render dashboard button when isLoggedIn is false', () => {
+ const newProps = { ...props, isLoggedIn: false };
+ render();
+ const dashboardButton = screen.queryByText('common.dashboard');
+ expect(dashboardButton).toBeNull();
+ });
+
+ it('does not render dashboard button when isLoggedIn is false', () => {
+ const newProps = { ...props, isLoggedIn: false };
+ render();
+ const dashboardButton = screen.queryByText('common.dashboard');
+ expect(dashboardButton).toBeNull();
+ });
+
+ it('renders API button when isLoggedIn is true', async () => {
+ authManager.setLoggedIn(true);
+ const { getByText } = render();
+ await waitFor(() => {
+ expect(getByText('API')).toBeInTheDocument();
+ });
+ });
+
+ it('does not render API button when isLoggedIn is false', () => {
+ const newProps = { ...props, isLoggedIn: false };
+ render();
+ const apiButton = screen.queryByText('API');
+ expect(apiButton).toBeNull();
+ });
+
+ it('renders statistics button when isLoggedIn is true', async () => {
+ authManager.setLoggedIn(true);
+ const { getByText } = render();
+ await waitFor(() => {
+ expect(getByText('common.statistics.title')).toBeInTheDocument();
+ });
+ });
+
+ it('does not render statistics button when isLoggedIn is false', () => {
+ const newProps = { ...props, isLoggedIn: false };
+ render();
+ const statisticsButton = screen.queryByText('common.statistics.title');
+ expect(statisticsButton).toBeNull();
+ });
+
+ it('renders rules button when isLoggedIn is true', async () => {
+ authManager.setLoggedIn(true);
+ const { getByText } = render();
+ await waitFor(() => {
+ expect(getByText('common.rules')).toBeInTheDocument();
+ });
+ });
+
+ it('does not render rules button when isLoggedIn is false', () => {
+ const newProps = { ...props, isLoggedIn: false };
+ render();
+ const rulesButton = screen.queryByText('common.rules');
+ expect(rulesButton).toBeNull();
+ });
+
+ it('does not render logout button when isLoggedIn is false', () => {
+ const newProps = { ...props, isLoggedIn: false };
+ render();
+ const logoutButton = screen.queryByText('common.logout');
+ expect(logoutButton).toBeNull();
+ });
+
+ it('renders about button', () => {
+ render();
+ const aboutButton = screen.getByLabelText('About');
+ expect(aboutButton).toBeInTheDocument();
+ });
+});
diff --git a/webapp/src/tests/Signup.test.js b/webapp/src/tests/Signup.test.js
index 11cdde4e..edb28544 100644
--- a/webapp/src/tests/Signup.test.js
+++ b/webapp/src/tests/Signup.test.js
@@ -1,5 +1,5 @@
import React from 'react';
-import { render, fireEvent, getByTestId, getAllByTestId, waitFor, act } from '@testing-library/react';
+import { render, fireEvent, getByTestId, getAllByTestId } from '@testing-library/react';
import { MemoryRouter } from 'react-router';
import Signup from '../pages/Signup';
import { ChakraProvider } from '@chakra-ui/react';