+
+
-
-
Time: {formatTiempo(segundos)}
+ { (gameMode !== "infinite" && gameMode !== "threeLife") ?
+
Time: {formatTiempo(segundos)}
+ : ""}
+ { gameMode === "threeLife" ?
+
{images}
:""}
-
+
{question}
@@ -170,7 +251,7 @@ const Question = ({ goTo, setGameFinished }) => {
handleSubmit(option, index)} key={generateUniqueId()}
sx={{ bgcolor: getBackgroundColor(option, index) }}>
-
+
{option}
@@ -178,19 +259,24 @@ const Question = ({ goTo, setGameFinished }) => {
))}
+
+ { gameMode !== "threeLife" ?
fetchQuestion() : null}
sx={{ justifyContent: 'center', marginTop: 2 }}
className={isSelected ? '' : 'isNotSelected'} >
Next
+ : ""}
+ { gameMode === "infinite" ?
+ handelInfiniteGameFinish( numberCorrect, numberIncorrect, segundosInfinite, goTo, setGameFinished) }
+ sx={{ color: '#f35858', justifyContent: 'center', marginTop: 2 }}>
+ End Game
+
+ : ""}
+
-
+
);
}
-Question.propTypes = {
- goTo: PropTypes.func.isRequired, // Asegura que goTo sea una función y es requerida
- setGameFinished: PropTypes.func.isRequired,
-};
-
export default Question;
diff --git a/webapp/src/components/Start.jsx b/webapp/src/components/Start.jsx
index 5de28494..83db82bf 100644
--- a/webapp/src/components/Start.jsx
+++ b/webapp/src/components/Start.jsx
@@ -1,4 +1,6 @@
+import Divider from '@mui/material/Divider';
+
export const Start = ({ goTo }) => {
return (
@@ -8,9 +10,20 @@ export const Start = ({ goTo }) => {
ASW Quiz - WIQ
goTo(2) }>
- Play
+ Classic Game
+
goTo(3) }>
+ Infinite Mode
+
+
goTo(4) }>
+ Three Lifes Classic
+
+
goTo(5) }>
+ Category Mode
+
+
+
goTo(6) }>
Participation
diff --git a/webapp/src/components/User.jsx b/webapp/src/components/User.jsx
index 3bed0037..44f2d95d 100644
--- a/webapp/src/components/User.jsx
+++ b/webapp/src/components/User.jsx
@@ -16,9 +16,9 @@ function User({ goTo }) {
return (
-
+
-
+
ASW - WIQ Quiz
{showLogin ? goTo(x)} /> : }
diff --git a/webapp/src/css/index.css b/webapp/src/css/index.css
index 0223ada2..0f74eb3e 100644
--- a/webapp/src/css/index.css
+++ b/webapp/src/css/index.css
@@ -22,8 +22,8 @@
}
* {
- font-family: 'Roboto Slab', Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
- margin: 0 auto;
+ font-family: 'Roboto Slab', Inter, system-ui, Avenir, Helvetica, Arial, sans-serif !important;
+ margin: 0;
font-weight: bold;
}
@@ -41,6 +41,11 @@ body {
min-height: 100vh;
}
+.icono {
+ width: 2.5em;
+ margin-right: 20px;
+}
+
main {
display: flex;
flex-direction: column;
@@ -48,6 +53,22 @@ main {
align-items: center;
vertical-align: middle;
height: 100%;
+
+}
+
+.divPreguntas {
+ max-width: 80%;
+}
+
+.botoneraPreguntas {
+ display: flex;
+}
+
+.panelLoginRegister h1,
+.panelLoginRegister h2,
+.panelLoginRegister h3
+.panelLoginRegister button {
+ font-family: 'Roboto Slab', Inter, system-ui, Avenir, Helvetica, Arial, sans-serif !important;
}
header {
@@ -61,11 +82,12 @@ h1 {
button {
border-radius: 8px;
- border: 1px solid transparent;
- padding: 0.6em 1.2em;
+ border: 4px solid transparent;
+ padding: 0.4em 1em;
font-size: 1.3em;
font-family: inherit;
- background-color: #1a1a1a;
+ background-color: #FFF;
+ color: #242424;
cursor: pointer;
transition: border-color 0.25s;
vertical-align: bottom;
@@ -78,6 +100,18 @@ button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
+.buttonLoginRegister {
+ display: block !important;
+ margin: 0 auto !important;
+ background-color: #8f95fd !important;
+ font-weight: bold !important;
+ margin: 20px auto 20px auto !important;
+}
+
+.buttonLoginRegister:hover {
+ background-color: #6367b3 !important;
+}
+
#start {
margin-top: 40px;
display: flex;
@@ -91,6 +125,7 @@ button:focus-visible {
.questionTime {
display: flex;
+ align-items: center;
justify-content: space-between;
}
@@ -143,6 +178,11 @@ button:focus-visible {
vertical-align: middle;
}
+.vidaImg {
+ width: 1.6em;
+ vertical-align: middle;
+}
+
#fotosPerfil {
display: grid;
justify-content: center;
@@ -170,7 +210,30 @@ button:focus-visible {
}
.selectedImg {
- border: 4px solid #FFF !important;
+ border: 5px solid #8f95fd !important;
+}
+
+.questionCategory {
+ flex-wrap: wrap;
+ display: flex;
+ justify-content: center;
+ margin-bottom: 2em;
+}
+
+.questionCategory button {
+ margin: 5px;
+ padding: 1px 3px;
+ font-size: 1em;
+}
+
+.questionCategory button:hover {
+ color: #FFF;
+ background-color: #646cff;
+}
+
+.questionCategoryMarked {
+ color: #FFF;
+ background-color: #646cff;
}
@media (prefers-color-scheme: light) {
diff --git a/webapp/src/test/AddUser.test.js b/webapp/src/test/AddUser.test.js
index 744c0bbe..b3bce758 100644
--- a/webapp/src/test/AddUser.test.js
+++ b/webapp/src/test/AddUser.test.js
@@ -18,7 +18,7 @@ describe('AddUser component', () => {
const usernameInput = screen.getByLabelText(/Username/i);
const passwordInput = screen.getByLabelText("Password");
const passwordConfirmInput = screen.getByLabelText(/Confirm/i);
- const addUserButton = screen.getByRole('button', { name: /Add User/i });
+ const addUserButton = screen.getByRole('button', { name: /SIGN UP/i });
// Mock the axios.post request to simulate a successful response
mockAxios.onPost('http://localhost:8000/adduser').reply(200);
@@ -54,7 +54,7 @@ describe('AddUser component', () => {
const usernameInput = screen.getByLabelText(/Username/i);
const passwordInput = screen.getByLabelText("Password");
const passwordConfirmInput = screen.getByLabelText(/Confirm/i);
- const addUserButton = screen.getByRole('button', { name: /Add User/i });
+ const addUserButton = screen.getByRole('button', { name: /SIGN UP/i });
// Mock the axios.post request to simulate a successful response
mockAxios.onPost('http://localhost:8000/adduser').reply(200);
@@ -79,7 +79,7 @@ describe('AddUser component', () => {
const usernameInput = screen.getByLabelText(/Username/i);
const passwordInput = screen.getByLabelText("Password");
const passwordConfirmInput = screen.getByLabelText(/Confirm/i);
- const addUserButton = screen.getByRole('button', { name: /Add User/i });
+ const addUserButton = screen.getByRole('button', { name: /SIGN UP/i });
// Mock the axios.post request to simulate an error response
mockAxios.onPost('http://localhost:8000/adduser').reply(500, { error: 'Internal Server Error' });
diff --git a/webapp/src/test/App.test.js b/webapp/src/test/App.test.js
index 249e9a96..2b54ed73 100644
--- a/webapp/src/test/App.test.js
+++ b/webapp/src/test/App.test.js
@@ -37,7 +37,7 @@ it('cambia de estado de menú al hacer clic en los botones', async () => {
fireEvent.click(nav);
// Encuentra los botones de navegación
- const gameButton = getByText('Play');
+ const gameButton = getByText('Classic Game');
const participationButton = getByText('Participation');
// Comprueba que solo el componente User está visible inicialmente
diff --git a/webapp/src/test/Game.test.js b/webapp/src/test/Game.test.js
index af9af1e9..4964c813 100644
--- a/webapp/src/test/Game.test.js
+++ b/webapp/src/test/Game.test.js
@@ -86,4 +86,55 @@ describe('Game component', () => {
jest.advanceTimersByTime(MAX_TIME * 1000);
});
});
+
+ test('renders Game component with default category', () => {
+ const { getByText } = render();
+ expect(getByText(/Restart game with a new category/i)).toBeInTheDocument();
+ });
+
+ test('renders Game component with category buttons', () => {
+ const { getByText } = render();
+ expect(getByText(/All Categories/i)).toBeInTheDocument();
+ expect(getByText("Art")).toBeInTheDocument();
+ expect(getByText(/Sports/i)).toBeInTheDocument();
+ expect(getByText(/Entertainment/i)).toBeInTheDocument();
+ expect(getByText(/Geography/i)).toBeInTheDocument();
+ expect(getByText(/Planets/i)).toBeInTheDocument();
+ });
+
+ test('changes category when All Categories category button is clicked', () => {
+ const { getByText } = render();
+ fireEvent.click(getByText(/All Categories/i));
+ expect(getByText(/Restart game with a new category/i)).toBeInTheDocument();
+ });
+
+ test('changes category when Art category button is clicked', () => {
+ const { getByText } = render();
+ fireEvent.click(getByText("Art"));
+ expect(getByText(/Restart game with a new category/i)).toBeInTheDocument();
+ });
+
+ test('changes category when Sports category button is clicked', () => {
+ const { getByText } = render();
+ fireEvent.click(getByText(/Sports/i));
+ expect(getByText(/Restart game with a new category/i)).toBeInTheDocument();
+ });
+
+ test('changes category when Entertainment category button is clicked', () => {
+ const { getByText } = render();
+ fireEvent.click(getByText(/Entertainment/i));
+ expect(getByText(/Restart game with a new category/i)).toBeInTheDocument();
+ });
+
+ test('changes category when Geography category button is clicked', () => {
+ const { getByText } = render();
+ fireEvent.click(getByText(/Geography/i));
+ expect(getByText(/Restart game with a new category/i)).toBeInTheDocument();
+ });
+
+ test('changes category when Planets category button is clicked', () => {
+ const { getByText } = render();
+ fireEvent.click(getByText(/Planets/i));
+ expect(getByText(/Restart game with a new category/i)).toBeInTheDocument();
+ });
});
diff --git a/webapp/src/test/Nav.test.js b/webapp/src/test/Nav.test.js
index c624cd49..6f991fa7 100644
--- a/webapp/src/test/Nav.test.js
+++ b/webapp/src/test/Nav.test.js
@@ -24,21 +24,6 @@ describe('Nav Component', () => {
});
- test('opens and closes user menu on avatar click', async () => {
- const { getByAltText, queryByText } = render(
-
-
-
- );
- const avatar = getByAltText('Remy Sharp');
-
- fireEvent.click(avatar);
- await waitFor(() => {
- expect(queryByText('Profile')).toBeInTheDocument();
- });
-
- });
-
test('calls goTo function when "Menu" is clicked', async () => {
const goToMock = jest.fn();
const { getByText } = render(
diff --git a/webapp/src/test/PostGame.test.js b/webapp/src/test/PostGame.test.js
index b008f763..ae9ced77 100644
--- a/webapp/src/test/PostGame.test.js
+++ b/webapp/src/test/PostGame.test.js
@@ -7,23 +7,23 @@ describe('PostGame component', () => {
render();
// Verifica que el texto "Fin del juego" se renderice correctamente
- expect(screen.getByText('Fin del juego')).toBeInTheDocument();
+ expect(screen.getByText('Game Over')).toBeInTheDocument();
});
test('renders text correctly', () => {
- render();
+ render();
// Verifica que el texto "Preguntas acertadas" se renderice correctamente
- expect(screen.getByText('Preguntas acertadas')).toBeInTheDocument();
+ expect(screen.getByText('Correct answers')).toBeInTheDocument();
// Verifica que el texto "Preguntas falladas" se renderice correctamente
- expect(screen.getByText('Preguntas falladas')).toBeInTheDocument();
+ expect(screen.getByText('Incorrect answers')).toBeInTheDocument();
// Verifica que el texto "Tiempo usado" se renderice correctamente
- expect(screen.getByText('Tiempo usado')).toBeInTheDocument();
+ expect(screen.getByText('Elapsed time')).toBeInTheDocument();
// Verifica que el texto "Tiempo restante" se renderice correctamente
- expect(screen.getByText('Tiempo restante')).toBeInTheDocument();
+ expect(screen.getByText('Time remaining')).toBeInTheDocument();
});
test('formatTiempo devuelve el formato de tiempo correcto', () => {
@@ -35,7 +35,7 @@ describe('PostGame component', () => {
render();
// Obtener el componente que muestra el tiempo usado
- const tiempoUsadoCell = screen.getByText('Tiempo usado').closest('tr').querySelector('td:last-child');
+ const tiempoUsadoCell = screen.getByText('Elapsed time').closest('tr').querySelector('td:last-child');
// Verificar si el texto del componente coincide con el tiempo esperado
expect(tiempoUsadoCell.textContent).toBe(tiempoEsperado);
diff --git a/webapp/src/test/Question.test.js b/webapp/src/test/Question.test.js
index f158ab1a..a9657243 100644
--- a/webapp/src/test/Question.test.js
+++ b/webapp/src/test/Question.test.js
@@ -2,7 +2,8 @@ import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import '@testing-library/jest-dom/extend-expect';
-import Question, { finishByQuestions, finishByTime, handleGameFinish } from '../components/Question';
+import Question, { finishByQuestions, finishByTime, reloadF,
+ handleClassicGameFinish, handleOOLGameFinish, handelInfiniteGameFinish } from '../components/Question';
import { SessionProvider } from '../SessionContext';
// Mock para la respuesta del servicio de preguntas
@@ -82,7 +83,9 @@ describe('Question component', () => {
});
// Hacer clic en el botón "Next"
- fireEvent.click(getByText('Next'));
+ act(() => {
+ fireEvent.click(getByText('Next'));
+ });
// Esperar a que se cargue la siguiente pregunta (en este caso, se simula la carga)
await waitFor(() => {
@@ -164,7 +167,9 @@ describe('Question component', () => {
expect(localStorage.getItem('sonido')).toBe(undefined);
// Simular hacer clic en la imagen de audio para desactivar el sonido
- fireEvent.click(getByRole('img'));
+ act(() => {
+ fireEvent.click(getByRole('img'));
+ });
// Verificar que el estado de sonido se haya actualizado correctamente
expect(localStorage.getItem('sonido')).toBe(undefined);
@@ -176,13 +181,17 @@ describe('Question component', () => {
);
// Simular hacer clic en el botón
- fireEvent.click(getByText('Next'));
+ act(() => {
+ fireEvent.click(getByText('Next'));
+ });
// Verificar si el estado isSelected ha cambiado correctamente a true
expect(localStorage.getItem('isSelected')).toBe(undefined);
// Simular hacer clic en el botón nuevamente
- fireEvent.click(getByText('Next'));
+ act(() => {
+ fireEvent.click(getByText('Next'));
+ });
// Verificar si el estado isSelected ha cambiado correctamente a false
expect(localStorage.getItem('isSelected')).toBe(undefined);
@@ -270,8 +279,8 @@ describe('handleGameFinish function', () => {
finishByQuestions(segundos, MAX_TIME);
// Verificamos que los valores correctos se hayan establecido en el local storage
- expect(localStorage.getItem("tiempoUsado")).toBe(MAX_TIME - segundos);
- expect(localStorage.getItem("tiempoRestante")).toBe(segundos);
+ expect(localStorage.getItem("tiempoUsado").toString()).toBe((MAX_TIME - segundos).toString());
+ expect(localStorage.getItem("tiempoRestante").toString()).toBe(segundos.toString());
// Verificamos que setGameFinished haya sido llamado con true
//expect(setGameFinished).toHaveBeenCalledWith(true);
@@ -287,25 +296,97 @@ describe('handleGameFinish function', () => {
const MAX_TIME = 120;
// Simula que se agota el tiempo
jest.useFakeTimers();
- jest.advanceTimersByTime((MAX_TIME + 1) * 1000); // Asegúrate de que el tiempo se agote
-
- finishByTime(true);
- finishByTime(true);
+ act(() => {
+ jest.advanceTimersByTime((MAX_TIME + 1) * 1000); // Asegúrate de que el tiempo se agote
+ });
+
+ act(() => {
+ finishByTime(true);
+ finishByTime(false);
+ });
// Verifica si finishByTime fue llamado
//expect(finishByTime).toHaveBeenCalledWith(true, goToMock, true); // Verifica si se llamó con los argumentos correctos
});
- it('should call handleGameFinish with the correct arguments', () => {
+ it('should call handleClassicGameFinish with the correct arguments', () => {
render();
// Simula que se alcanza el final del juego
const nQuestion = 10; // Número de preguntas igual al máximo
const numberCorrect = 8; // Supongamos que el jugador acierta 8 preguntas
+ const numberIncorrect = 2;
const segundos = 1; // Simula que se acaba el tiempo
- const MAX_TIME = 120;
const sonido = true; // Supongamos que el sonido está activado
+ const setGameFinished = jest.fn();
+ const goTo = jest.fn();
+
+ act(() => {
+ handleClassicGameFinish(nQuestion, numberCorrect, numberIncorrect, segundos, sonido, goTo, setGameFinished);
+ });
+ });
+
+ it('should call handleOOLGameFinish with the correct arguments', () => {
+ render();
+
+ // Simula que se alcanza el final del juego
+ const numberCorrect = 8; // Supongamos que el jugador acierta 8 preguntas
+ const setGameFinished = jest.fn();
+ const segundosInfinite = 100;
+ const goTo = jest.fn();
+
+ act(() => {
+ handleOOLGameFinish(numberCorrect, segundosInfinite, goTo, setGameFinished);
+ });
+ });
+
+ it('should call handleClassicGameFinish with the correct arguments', () => {
+ render();
+
+ // Simula que se alcanza el final del juego
+ const numberCorrect = 8; // Supongamos que el jugador acierta 8 preguntas
+ const numberIncorrect = 2;
+ const segundosInfinite = 100;
+ const setGameFinished = jest.fn();
+ const goTo = jest.fn();
+
+ act(() => {
+ handelInfiniteGameFinish(numberCorrect, numberIncorrect, segundosInfinite, goTo, setGameFinished);
+ });
+ });
+
+ it('should call handleClassicGameFinish with the correct arguments', () => {
+
+ const MAX_TIME = 240;
+ const mockSetState = jest.fn();
+ const mockContext = {
+ setSegundos: mockSetState,
+ setSegundosInfinite: mockSetState,
+ setNQuestion: mockSetState,
+ setNumberCorrect: mockSetState,
+ setNumberIncorrect: mockSetState,
+ setReload: mockSetState
+ };
+
+ render();
+
+ act(() => {
+ reloadF(
+ mockContext.setSegundos,
+ mockContext.setSegundosInfinite,
+ mockContext.setNQuestion,
+ mockContext.setNumberCorrect,
+ mockContext.setNumberIncorrect,
+ mockContext.setReload
+ );
+ });
- handleGameFinish(nQuestion, numberCorrect, segundos, MAX_TIME, sonido);
+ // Verifica que todas las funciones setState hayan sido llamadas con los valores correctos
+ expect(mockContext.setSegundos).toHaveBeenCalledWith(MAX_TIME);
+ expect(mockContext.setSegundosInfinite).toHaveBeenCalledWith(0);
+ expect(mockContext.setNQuestion).toHaveBeenCalledWith(-1);
+ expect(mockContext.setNumberCorrect).toHaveBeenCalledWith(0);
+ expect(mockContext.setNumberIncorrect).toHaveBeenCalledWith(0);
+ expect(mockContext.setReload).toHaveBeenCalledWith(false);
});
});
diff --git a/webapp/src/test/Start.test.js b/webapp/src/test/Start.test.js
index 9b81ec22..f6f4e74a 100644
--- a/webapp/src/test/Start.test.js
+++ b/webapp/src/test/Start.test.js
@@ -11,7 +11,7 @@ describe('Start component', () => {
expect(titleText).toBeInTheDocument();
// Verificar que el botón "Jugar" se muestra correctamente
- const playButton = screen.getByRole('button', { name: /Play/i });
+ const playButton = screen.getByRole('button', { name: /Classic Game/i });
expect(playButton).toBeInTheDocument();
// Verificar que el botón "Participacion" se muestra correctamente
@@ -24,7 +24,7 @@ describe('Start component', () => {
render(); // Renderizar el componente Start con la función simulada
// Simular clic en el botón "Jugar"
- fireEvent.click(screen.getByText('Play'));
+ fireEvent.click(screen.getByText('Classic Game'));
// Verificar que la función goTo se llamó con el argumento correcto (en este caso, 2)
expect(goToMock).toHaveBeenCalledWith(2);
@@ -37,7 +37,24 @@ describe('Start component', () => {
// Simular clic en el botón "Participación"
fireEvent.click(screen.getByText('Participation'));
- // Verificar que la función goTo se llamó con el argumento correcto (en este caso, 3)
+ // Verificar que la función goTo se llamó con el argumento correcto (en este caso, 6)
+ expect(goToMock).toHaveBeenCalledWith(6);
+ });
+
+ it('should trigger the correct function when a button is clicked', () => {
+ const goToMock = jest.fn();
+ const { getByText } = render();
+
+ // Simular clic en el botón "Infinite Mode"
+ fireEvent.click(getByText('Infinite Mode'));
expect(goToMock).toHaveBeenCalledWith(3);
+
+ // Simular clic en el botón "Three Lifes Classic"
+ fireEvent.click(getByText('Three Lifes Classic'));
+ expect(goToMock).toHaveBeenCalledWith(4);
+
+ // Simular clic en el botón "Category Mode"
+ fireEvent.click(getByText('Category Mode'));
+ expect(goToMock).toHaveBeenCalledWith(5);
});
});
diff --git a/webapp/src/test/User.test.js b/webapp/src/test/User.test.js
index 75ecdff4..424138c5 100644
--- a/webapp/src/test/User.test.js
+++ b/webapp/src/test/User.test.js
@@ -15,7 +15,7 @@ describe('User component', () => {
const welcomeText = screen.getByText(/ASW - WIQ Quiz/i);
expect(welcomeText).toBeInTheDocument();
- const welcomeText2 = screen.getByText(/Login :D/i);
+ const welcomeText2 = screen.getByText(/> Login/i);
expect(welcomeText2).toBeInTheDocument();
// Verificar que el formulario de inicio de sesión se muestra por defecto