diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1167a28f..3b79addb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,7 @@ name: Build on: push: - branches: [master, develop, develop-deploy, develop-teresa] + branches: [master, develop, develop-deploy, develop-teresa, develop_samuel] pull_request: types: [opened, synchronize, reopened] diff --git a/webapp/e2e/features/theChallangeGame.feauture b/webapp/e2e/features/theChallangeGame.feauture new file mode 100644 index 00000000..6a63bd96 --- /dev/null +++ b/webapp/e2e/features/theChallangeGame.feauture @@ -0,0 +1,11 @@ +Feature: Answer a question + +Scenario: Answering a question correctly + Given A question + When I click on the correct answer button + Then The button turns green + +Scenario: Answering a question incorrectly + Given A question + When I click on an incorrect answer button + Then The button turns red \ No newline at end of file diff --git a/webapp/e2e/steps/theCallange.steps.js b/webapp/e2e/steps/theCallange.steps.js new file mode 100644 index 00000000..8b3d7d59 --- /dev/null +++ b/webapp/e2e/steps/theCallange.steps.js @@ -0,0 +1,139 @@ +const puppeteer = require('puppeteer'); +const { defineFeature, loadFeature }=require('jest-cucumber'); +const setDefaultOptions = require('expect-puppeteer').setDefaultOptions +const feature = loadFeature('./features/theChallangeGame.feauture'); + +let page; +let browser; + +defineFeature(feature, test => { + + beforeAll(async () => { + + browser = process.env.GITHUB_ACTIONS + ? await puppeteer.launch() + : await puppeteer.launch({ headless: false, slowMo: 40 }); + page = await browser.newPage(); + + await page.setRequestInterception(true); + + page.on('request', (req) => { + if(req.url().endsWith('/Geography')) { + req.respond({ + status: 200, + headers: { + 'Access-Control-Allow-Origin': '*' + }, + contentType: 'application/json', + body: JSON.stringify([{ + question: 'Which is the capital of Spain?', + options: ['Madrid', 'Barcelona', 'Paris', 'London'], + correctAnswer: 'Madrid', + categories: ['Geography'], + language: 'en' + }]) + }); + } else { + req.continue(); + } + }); + //Way of setting up the timeout + setDefaultOptions({ timeout: 10000 }) + + + }); + + beforeEach(async () => { + await page + .goto("http://localhost:3000/theChallengeGame", { + waitUntil: "networkidle0", + }) + .catch(() => {}); + + //"mock" login + await page.evaluate(() => { + localStorage.clear(); + localStorage.setItem('sessionId', 'fictitiousSessionId12345'); + }); + + await page + .goto("http://localhost:3000/theChallengeGame", { + waitUntil: "networkidle0", + }) + .catch(() => {}); + }); + + + test('Answering a question correctly', ({given,when,then}) => { + + given('A question', async () => { + const button = await page.$('[data-testid="start-button"]'); + await button.click(); + + //await expect(page.findByText('Which is the capital of Spain?')); + const question = await page.$['data-testid="question"']; + await expect(page).toMatchElement("div", { text: 'Which is the capital of Spain?'.toUpperCase()}); + expect(question).not.toBeNull(); + + const answers = await page.$x('//*[contains(@data-testid, "success") or contains(@data-testid, "failure") or contains(@data-testid, "answer")]'); + expect(answers.length).toBe(4); + }); + + when('I click on the correct answer button', async () => { + const answers = await page.$x('//*[contains(@data-testid, "success") or contains(@data-testid, "failure") or contains(@data-testid, "answer")]'); + await answers[0].click(); + + }); + + then('The button turns green', async () => { + /*const answerButton = await page.$x('(//*[@data-testid="answer"])[1]'); + const textoBoton1 = await page.evaluate(button => button.innerText, answerButton[0]); + const textoBoton2 = await page.evaluate(button => button.innerText, answerButton[1]); + if(textoBoton1 === "Madrid") { + await expect(textoBoton1).toMatch(/Madrid/i); + } else { + await expect(textoBoton2).toMatch(/Madrid/i); + }*/ + await expect(page).toMatchElement("button", { style: { color: 'green' } }); + }); + }) + + test('Answering a question incorrectly', ({given,when,then}) => { + + given('A question', async () => { + const button = await page.$('[data-testid="start-button"]'); + await button.click(); + + //await expect(page.findByText('Which is the capital of Spain?')); + const question = await page.$['data-testid="question"']; + await expect(page).toMatchElement("div", { text: 'Which is the capital of Spain?'.toUpperCase()}); + expect(question).not.toBeNull(); + + const answers = await page.$x('//*[contains(@data-testid, "success") or contains(@data-testid, "failure") or contains(@data-testid, "answer")]'); + expect(answers.length).toBe(4); + }); + + when('I click on an incorrect answer button', async () => { + const answers = await page.$x('//*[contains(@data-testid, "success") or contains(@data-testid, "failure") or contains(@data-testid, "answer")]'); + await answers[1].click(); + }); + + then('The button turns red', async () => { + /*const answerButton = await page.$x('(//*[@data-testid="answer"])[2]'); + const textoBoton1 = await page.evaluate(button => button.innerText, answerButton[0]); + const textoBoton2 = await page.evaluate(button => button.innerText, answerButton[1]); + if(textoBoton1 !== "Madrid") { + await expect(textoBoton1).not.toMatch(/Madrid/i); + } else { + await expect(textoBoton2).toMatch(/Madrid/i); + }*/ + await expect(page).toMatchElement("button", { style: { color: 'red' } }); + await expect(page).toMatchElement("button", { style: { color: 'green' } }); + }); + }) + + afterAll(async ()=>{ + browser.close() + }) + +}); \ No newline at end of file diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 9eb7d31b..b85d1ed4 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -31,7 +31,7 @@ "react-i18next": "^14.1.0", "react-router-dom": "^6.22.1", "react-scripts": "5.0.1", - "sequelize": "^6.37.2", + "sequelize": "^6.37.3", "socket.io-client": "^4.7.5", "sqlite3": "^5.1.7", "web-vitals": "^3.5.1" @@ -25545,9 +25545,9 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/sequelize": { - "version": "6.37.2", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.2.tgz", - "integrity": "sha512-bnb7swGANONXCTrVyebpOOZssLwQrVkYX2tcC6qOIvH+P+OhsoMBi7c3GXI5bC+Z4b4tOl+kQy6yeqLCZ1YQAQ==", + "version": "6.37.3", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.3.tgz", + "integrity": "sha512-V2FTqYpdZjPy3VQrZvjTPnOoLm0KudCRXfGWp48QwhyPPp2yW8z0p0sCYZd/em847Tl2dVxJJ1DR+hF+O77T7A==", "funding": [ { "type": "opencollective", @@ -47930,9 +47930,9 @@ } }, "sequelize": { - "version": "6.37.2", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.2.tgz", - "integrity": "sha512-bnb7swGANONXCTrVyebpOOZssLwQrVkYX2tcC6qOIvH+P+OhsoMBi7c3GXI5bC+Z4b4tOl+kQy6yeqLCZ1YQAQ==", + "version": "6.37.3", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.3.tgz", + "integrity": "sha512-V2FTqYpdZjPy3VQrZvjTPnOoLm0KudCRXfGWp48QwhyPPp2yW8z0p0sCYZd/em847Tl2dVxJJ1DR+hF+O77T7A==", "requires": { "@types/debug": "^4.1.8", "@types/validator": "^13.7.17", diff --git a/webapp/package.json b/webapp/package.json index 6f600353..3ccc8398 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -26,7 +26,7 @@ "react-i18next": "^14.1.0", "react-router-dom": "^6.22.1", "react-scripts": "5.0.1", - "sequelize": "^6.37.2", + "sequelize": "^6.37.3", "socket.io-client": "^4.7.5", "sqlite3": "^5.1.7", "web-vitals": "^3.5.1" diff --git a/webapp/src/__tests__/pages/Home.test.js b/webapp/src/__tests__/pages/Home.test.js index 21fe3cfc..2e6dd511 100644 --- a/webapp/src/__tests__/pages/Home.test.js +++ b/webapp/src/__tests__/pages/Home.test.js @@ -1,6 +1,7 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import Home from '../../pages/Home'; +import '../../localize/i18n'; // Hacemos un mock del módulo '@mui/material' y su hook useMediaQuery jest.mock('@mui/material/useMediaQuery', () => ({ diff --git a/webapp/src/__tests__/pages/Homepage.test.js b/webapp/src/__tests__/pages/Homepage.test.js index c9f4992b..b607699c 100644 --- a/webapp/src/__tests__/pages/Homepage.test.js +++ b/webapp/src/__tests__/pages/Homepage.test.js @@ -1,6 +1,7 @@ import React from 'react'; import { render, fireEvent, screen } from '@testing-library/react'; import Homepage from '../../pages/Homepage'; +import '../../localize/i18n'; // Hacemos un mock del módulo '@mui/material' y su hook useMediaQuery jest.mock('@mui/material/useMediaQuery', () => ({ @@ -16,7 +17,7 @@ describe('Homepage', () => { it('renders video and play button', () => { render(); expect(screen.getByTestId('video')).toBeInTheDocument(); - expect(screen.getByText('PLAY')).toBeInTheDocument(); + expect(screen.getByText("PLAY")).toBeInTheDocument(); }); it('loads game buttons dynamically based on data', async () => { diff --git a/webapp/src/__tests__/pages/Instructions.test.js b/webapp/src/__tests__/pages/Instructions.test.js index e217269f..c5d779c5 100644 --- a/webapp/src/__tests__/pages/Instructions.test.js +++ b/webapp/src/__tests__/pages/Instructions.test.js @@ -2,32 +2,33 @@ import React from 'react'; import { render, fireEvent, screen, waitFor } from '@testing-library/react'; import Instructions from '../../pages/Instructions'; import { BrowserRouter as Router } from 'react-router-dom'; +import '../../localize/i18n'; jest.mock('../../data/gameInfo.json', () => ({ __esModule: true, default: [ { - nombre: "WISE MEN STACK", + nombre: "Wise Men Stack", descripcion: "The player chooses a topic from five available options and must answer a battery of questions related to it within 60 seconds. For each question, the host provides two options. If the contestant guesses correctly, they win €20; otherwise, they move on to the next question (as the correct answer would be the other option). If the time runs out before the question is fully asked and both possible answers are provided, the contestant may still answer it; however, if the statement hasn't been completed (or the options weren't provided), they cannot answer.", foto: "../gameImg/foto0.png" }, { - nombre: "WARM QUESTION", + nombre: "Warm Question", descripcion: "It consists of ten topics of varied themes. For each correct answer, €100 is earned, and €10 are lost if the contestant passes, does not respond, or answers incorrectly.", foto: "../gameImg/foto1.jpg" }, { - nombre: "DISCOVERING CITIES", + nombre: "Discovering Cities", descripcion: "In the 'Discovering Cities' game mode, the contestant will face a challenge where they will be repeatedly asked questions referring to different cities around the world. To successfully overcome the challenge, the contestant must answer as many questions as possible correctly throughout the test.", foto: "../gameImg/foto2.png" }, { - nombre: "THE CHALLENGE", + nombre: "Challenge", descripcion: "The 'Challenge' game mode is the quintessential game mode, as it allows you to customize the match to your liking. This game mode is tailored for those who wish to practice certain game formats before engaging in our various other game modes.", foto: "../gameImg/foto3.jpg" }, { - nombre: "ONLINE MODE", + nombre: "Multiplayer", descripcion: "Create a room for other player to join and play 1vs1", foto: "../gameImg/foto3.jpg" } @@ -55,10 +56,10 @@ describe('Instructions component', () => { fireEvent.click(screen.getAllByRole('button')[0]); // Click the first game button - const gameNames = await screen.findAllByText("WISE MEN STACK"); //Look for the text "WISE MEN STACK" + const gameNames = await screen.findAllByText("Wise Men Stack"); //Look for the text "WISE MEN STACK" expect(gameNames).toHaveLength(2); // Check the expected number of matches - expect(gameNames[0]).toHaveTextContent("WISE MEN STACK"); + expect(gameNames[0]).toHaveTextContent("Wise Men Stack"); }); it('Hides game information when the same game button is clicked again', async () => { @@ -71,12 +72,12 @@ describe('Instructions component', () => { const gameButton = screen.getAllByRole('button')[0]; //Selecciona el primer boton fireEvent.click(gameButton); // Hace click en el boton indicado - const gameNames = await screen.findAllByText("WISE MEN STACK"); //Finds all components that have the indicated text + const gameNames = await screen.findAllByText("Wise Men Stack"); //Finds all components that have the indicated text expect(gameNames).toHaveLength(2); // Check the expected number of matches fireEvent.click(gameButton); // Hide info - const gameNames2 = await screen.findAllByText("WISE MEN STACK"); //Finds all components that have the indicated text + const gameNames2 = await screen.findAllByText("Wise Men Stack"); //Finds all components that have the indicated text expect(gameNames2).toHaveLength(1); // Check the expected number of matches await waitFor(() => { @@ -93,12 +94,12 @@ describe('Instructions component', () => { fireEvent.click(screen.getAllByRole('button')[0]); // Display first game info - const gameNames = await screen.findAllByText("WISE MEN STACK"); //Finds all components that have the indicated text + const gameNames = await screen.findAllByText("Wise Men Stack"); //Finds all components that have the indicated text expect(gameNames).toHaveLength(2); // Check the expected number of matches fireEvent.click(screen.getAllByRole('button')[1]); // Switch to second game info - const gameName = await screen.findAllByText("WARM QUESTION"); //Finds all components that have the indicated text + const gameName = await screen.findAllByText("Warm Question"); //Finds all components that have the indicated text expect(gameName).toHaveLength(2); // Check the expected number of matches await waitFor(() => { @@ -109,27 +110,27 @@ describe('Instructions component', () => { const mockGameData = [ { - nombre: "WISE MEN STACK", + nombre: "Wise Men Stack", descripcion: "The player chooses a topic from five available options and must answer a battery of questions related to it within 60 seconds. For each question, the host provides two options. If the contestant guesses correctly, they win €20; otherwise, they move on to the next question (as the correct answer would be the other option). If the time runs out before the question is fully asked and both possible answers are provided, the contestant may still answer it; however, if the statement hasn't been completed (or the options weren't provided), they cannot answer.", foto: "../gameImg/foto0.png" }, { - nombre: "WARM QUESTION", + nombre: "Warm Question", descripcion: "It consists of ten topics of varied themes. For each correct answer, €100 is earned, and €10 are lost if the contestant passes, does not respond, or answers incorrectly.", foto: "../gameImg/foto1.jpg" }, { - nombre: "DISCOVERING CITIES", + nombre: "Discovering Cities", descripcion: "In the 'Discovering Cities' game mode, the contestant will face a challenge where they will be repeatedly asked questions referring to different cities around the world. To successfully overcome the challenge, the contestant must answer as many questions as possible correctly throughout the test.", foto: "../gameImg/foto2.png" }, { - nombre: "THE CHALLENGE", + nombre: "Challenge", descripcion: "The 'Challenge' game mode is the quintessential game mode, as it allows you to customize the match to your liking. This game mode is tailored for those who wish to practice certain game formats before engaging in our various other game modes.", foto: "../gameImg/foto3.jpg" }, { - nombre: "ONLINE MODE", + nombre: "Multiplayer", descripcion: "Create a room for other player to join and play 1vs1", foto: "../gameImg/foto3.jpg" } @@ -142,6 +143,7 @@ describe('Instructions component', () => { // Click in the game button fireEvent.click(screen.getAllByRole('button')[index]); + console.log(game.descripcion); // Verify that the game name and description are in the document const gameName = await screen.findAllByText(game.nombre); expect(gameName).toHaveLength(2); // Check the expected number of matches diff --git a/webapp/src/__tests__/pages/Statistics.test.js b/webapp/src/__tests__/pages/Statistics.test.js index ec49a0e9..ed24cbd5 100644 --- a/webapp/src/__tests__/pages/Statistics.test.js +++ b/webapp/src/__tests__/pages/Statistics.test.js @@ -239,9 +239,9 @@ describe('Statistics component', () => { await screen.findByText('STATISTICS'); - fireEvent.click(screen.getByText('Online Mode')); + fireEvent.click(screen.getByText('Multiplayer')); - expect(screen.getByText('Online Mode')).toBeInTheDocument(); + expect(screen.getByText('Multiplayer')).toBeInTheDocument(); expect(screen.getByText('Total Points:')).toBeInTheDocument(); expect(screen.getByText('15')).toBeInTheDocument(); expect(screen.getByText('Correctly Answered Questions:')).toBeInTheDocument(); @@ -253,7 +253,7 @@ describe('Statistics component', () => { expect(screen.getByText('Games Played:')).toBeInTheDocument(); expect(screen.getAllByText('12')); - fireEvent.click(screen.getByText('Show Questions Record')); + fireEvent.click(screen.getByText("Show Questions Record")); await screen.findByText('Game 04/11/2024, 14:00'); expect(screen.getByText('What is 1 + 1?')).toBeInTheDocument(); diff --git a/webapp/src/__tests__/pages/TheChallengeGame.test.js b/webapp/src/__tests__/pages/TheChallengeGame.test.js index 2b8296d8..9627bba8 100644 --- a/webapp/src/__tests__/pages/TheChallengeGame.test.js +++ b/webapp/src/__tests__/pages/TheChallengeGame.test.js @@ -50,13 +50,10 @@ describe('Game component', () => { fireEvent.click(screen.getByRole('button', { name: 'Start game' })); // Espera a que aparezca la pregunta - await waitFor(() => screen.getByText('Which is the capital of Spain?')); - - expect(screen.findByText('1')); - //expect(screen.findByText('1/4')); + await waitFor(() => screen.getByText('Which is the capital of Spain?'.toUpperCase())); // Verifica que el juego haya comenzado correctamente mostrando la pregunta y las opciones - expect(screen.getByText('Which is the capital of Spain?')).toBeInTheDocument(); + expect(screen.getByText('Which is the capital of Spain?'.toUpperCase())).toBeInTheDocument(); expect(screen.getByText('Madrid')).toBeInTheDocument(); expect(screen.getByText('Barcelona')).toBeInTheDocument(); expect(screen.getByText('Paris')).toBeInTheDocument(); @@ -83,17 +80,13 @@ describe('Game component', () => { fireEvent.click(screen.getByRole('button', { name: 'Start game' })); // waits for the question to appear - await waitFor(() => screen.getByText('Which is the capital of Spain?')); + await waitFor(() => screen.getByText('Which is the capital of Spain?'.toUpperCase())); const correctAnswer = screen.getByRole('button', { name: 'Madrid' }); - expect(correctAnswer).not.toHaveStyle({ backgroundColor: 'green' }); - + expect(screen.findByTestId("anwer0")); //selects correct answer fireEvent.click(correctAnswer); - - //expect(screen.findByText('1')).toHaveStyle({ backgroundColor: 'lightgreen' }); - - expect(correctAnswer).toHaveStyle({ backgroundColor: 'green' }); + expect(screen.findByTestId("succes0")); }); @@ -118,16 +111,13 @@ describe('Game component', () => { fireEvent.click(screen.getByRole('button', { name: 'Start game' })); // waits for the question to appear - await waitFor(() => screen.getByText('Which is the capital of Spain?')); + await waitFor(() => screen.getByText('Which is the capital of Spain?'.toUpperCase())); const incorrectAnswer = screen.getByRole('button', { name: 'Barcelona' }); - expect(incorrectAnswer).not.toHaveStyle({ backgroundColor: 'red' }); - + expect(screen.findByTestId("anwer1")); //selects correct answer fireEvent.click(incorrectAnswer); - - expect(incorrectAnswer).toHaveStyle({ backgroundColor: 'red' }); - //expect(screen.findByText('1')).toHaveStyle({ backgroundColor: 'salmon' }); + expect(screen.findByTestId("failure1")); }); @@ -151,7 +141,7 @@ describe('Game component', () => { fireEvent.click(screen.getByRole('button', { name: 'Start game' })); // waits for the question to appear - await waitFor(() => screen.getByText('Which is the capital of Spain?')); + await waitFor(() => screen.getByText('Which is the capital of Spain?'.toUpperCase())); setTimeout(() => { // Comprobamos que el callback ha sido llamado después del tiempo especificado diff --git a/webapp/src/data/gameInfo.json b/webapp/src/data/gameInfo.json index 388ef71f..012e3110 100644 --- a/webapp/src/data/gameInfo.json +++ b/webapp/src/data/gameInfo.json @@ -1,6 +1,6 @@ [ { - "nombre": "WISE MEN STACK", + "nombre": "Wise Men Stack", "descripcion": "The player chooses a topic from five available options and must answer a battery of questions related to it within 60 seconds. For each question, the host provides two options. If the contestant guesses correctly, they move on to the next question.", "foto": "../instructions/foto0.png", @@ -8,21 +8,21 @@ "cardFoto": "../homePage/foto0.png" }, { - "nombre": "WARM QUESTION", - "descripcion": "It consists of ten topics of varied themes. For each correct answer, 100 points are earned, and 10 are lost if the contestant passes, does not respond, or answers incorrectly.", + "nombre": "Warm Question", + "descripcion": "It consists of ten topics of varied themes. For each correct answer, €100 is earned, and €10 are lost if the contestant passes, does not respond, or answers incorrectly.", "foto": "../instructions/foto1.jpg", "card":"It consists of ten topics of varied themes.", "cardFoto": "../homePage/foto1.jpg" }, { - "nombre": "DISCOVERING CITIES", - "descripcion": "In the 'Discovering Cities' game mode, the contestant will face a challenge where they will be repeatedly asked questions referring to different cities around the world. To successfully overcome the challenge, the contestant must answer as many questions as possible correctly throughout the test..", + "nombre": "Discovering Cities", + "descripcion": "In the 'Discovering Cities' game mode, the contestant will face a challenge where they will be repeatedly asked questions referring to different cities around the world. To successfully overcome the challenge, the contestant must answer as many questions as possible correctly throughout the test.", "foto": "../instructions/foto2.png", "card":"The contestant will face a challenge where they will be repeatedly asked questions referring to different cities around the world.", "cardFoto": "../homePage/foto2.png" }, { - "nombre": "THE CHALLENGE", + "nombre": "Challenge", "descripcion": "The 'Challenge' game mode is the quintessential game mode, as it allows you to customize the match to your liking. This game mode is tailored for those who wish to practice certain game formats before engaging in our various other game modes.", "foto": "../instructions/foto3.jpg", "card":"The 'Challenge' game mode is the quintessential game mode, as it allows you to customize the match to your liking.", @@ -30,7 +30,7 @@ }, { - "nombre": "MULTIPLAYER MODE", + "nombre": "Multiplayer", "descripcion": "Create a room and share the room code with other players to play. It also has a room chat.", "foto": "../instructions/online-photo.jpg", "card":"Create a room and share the room code with other players to play. It also has a room chat.", diff --git a/webapp/src/localize/en.json b/webapp/src/localize/en.json index 0d534d67..ad821a35 100644 --- a/webapp/src/localize/en.json +++ b/webapp/src/localize/en.json @@ -29,27 +29,26 @@ }, "Games": { - "wise_men": { + "Wise Men Stack": { "name": "Wise Men Stack", "desc": "The player chooses a topic from five available options and must answer a battery of questions related to it within 60 seconds. For each question, the host provides two options. If the contestant guesses correctly, they win €20; otherwise, they move on to the next question (as the correct answer would be the other option). If the time runs out before the question is fully asked and both possible answers are provided, the contestant may still answer it; however, if the statement hasn't been completed (or the options weren't provided), they cannot answer." }, - "warm_quest": { + "Warm Question": { "name": "Warm Question", "desc": "It consists of ten topics of varied themes. For each correct answer, €100 is earned, and €10 are lost if the contestant passes, does not respond, or answers incorrectly." }, - "discover": { + "Discovering Cities": { "name": "Discovering Cities", - "desc": "In the 'Discovering Cities' game mode, the contestant will face a challenge where they will be repeatedly asked questions referring to different cities around the world. To successfully overcome the challenge, the contestant must answer as many questions as possible correctly throughout the test.." + "desc": "In the 'Discovering Cities' game mode, the contestant will face a challenge where they will be repeatedly asked questions referring to different cities around the world. To successfully overcome the challenge, the contestant must answer as many questions as possible correctly throughout the test." }, - "challenge": { + "Challenge": { "name": "Challenge", "desc": "The 'Challenge' game mode is the quintessential game mode, as it allows you to customize the match to your liking. This game mode is tailored for those who wish to practice certain game formats before engaging in our various other game modes." }, - "multiplayer": { + "Multiplayer": { "name": "Multiplayer", "desc": "Create a room for other player to join and play 1vs1" } - }, "Game": { @@ -113,6 +112,7 @@ "Statistics": { "title": "STATISTICS", + "game": "Game", "table": { "money": "Total Points", "questions_corr": "Correctly Answered Questions", @@ -122,6 +122,10 @@ "total_time": "Total Time Played", "cities_corr": "Correctly Answered Cities", "cities_incorr": "Incorrectly Answered Cities" + }, + "button": { + "hide_record": "Hide Questions Record", + "show_record": "Show Questions Record" } }, @@ -164,7 +168,7 @@ "users":"Users", "groups": "Groups", - "total_money": "MONEY", + "total_money": "POINTS", "correct_answers": "CORRECT ANSWERS", "incorrect_answers": "INCORRECT ANSWERS", "total_games": "GAMES PLAYED" diff --git a/webapp/src/localize/es.json b/webapp/src/localize/es.json index d17881c1..5b51732b 100644 --- a/webapp/src/localize/es.json +++ b/webapp/src/localize/es.json @@ -29,24 +29,24 @@ }, "Games": { - "wise_men": { - "name": "Hombres Sabiondos", + "Wise Men Stack": { + "name": "Wise Men Stack", "desc": "El jugador elige un tema entre cinco opciones disponibles y debe responder una batería de preguntas relacionadas con él en un plazo de 60 segundos. Para cada pregunta, el presentador proporciona dos opciones. Si el concursante acierta, gana €20; de lo contrario, pasa a la siguiente pregunta (ya que la respuesta correcta sería la otra opción). Si el tiempo se agota antes de que se formule por completo la pregunta y se proporcionen ambas posibles respuestas, el concursante aún puede responderla; sin embargo, si la afirmación no se ha completado (o las opciones no se proporcionaron), no pueden responder." }, - "warm_quest": { - "name": "Pregunta Calentorra", + "Warm Question": { + "name": "Warm Question", "desc": "Consta de diez temas de diferentes temáticas. Por cada respuesta correcta, se ganan €100, y se pierden €10 si el concursante pasa, no responde o responde incorrectamente." }, - "discover": { - "name": "Descubriendo Ciudades", + "Discovering Cities": { + "name": "Discovering Cities", "desc": "En el modo de juego 'Descubriendo Ciudades', el concursante enfrentará un desafío donde se le harán preguntas repetidas referentes a diferentes ciudades de todo el mundo. Para superar con éxito el desafío, el concursante debe responder tantas preguntas como sea posible correctamente a lo largo de la prueba." }, - "challenge": { - "name": "Desafío", + "Challenge": { + "name": "Challenge", "desc": "El modo de juego 'Desafío' es el modo de juego por excelencia, ya que te permite personalizar el enfrentamiento a tu gusto. Este modo de juego está diseñado para aquellos que deseen practicar ciertos formatos de juego antes de participar en nuestros diversos otros modos de juego." }, - "multiplayer": { - "name": "Multijugador", + "Multiplayer": { + "name": "Multiplayer", "desc": "Crea una sala para que otros jugadores se unan y jueguen 1 contra 1." } }, @@ -112,6 +112,7 @@ "Statistics": { "title": "ESTADÍSTICAS", + "game": "Partida", "table": { "money": "Puntos Ganado", "questions_corr": "Preguntas Respondidas Correctamente", @@ -121,6 +122,10 @@ "total_time": "Tiempo Total Jugado", "cities_corr": "Ciudades Respondidas Correctamente", "cities_incorr": "Ciudades Respondidas Incorrectamente" + }, + "button": { + "hide_record": "Ocultar registro de preguntas", + "show_record": "Mostrar registro de preguntas" } }, @@ -164,7 +169,7 @@ "users":"Usuarios", "groups": "Grupos", "name":"NOMBRE", - "total_money": "DINERO", + "total_money": "PUNTOS", "correct_answers": "RESPUESTAS CORRECTAS", "incorrect_answers": "RESPUESTAS INCORRECTAS", "total_games": "PARTIDAS JUGADAS" diff --git a/webapp/src/localize/fr.json b/webapp/src/localize/fr.json index 8715a69e..6ae2d1e5 100644 --- a/webapp/src/localize/fr.json +++ b/webapp/src/localize/fr.json @@ -29,24 +29,24 @@ }, "Games": { - "wise_men": { - "name": "Pile de Sages", + "Wise Men Stack": { + "name": "Wise Men Stack", "desc": "Le joueur choisit un sujet parmi cinq options disponibles et doit répondre à une batterie de questions qui y sont liées dans un délai de 60 secondes. Pour chaque question, l'hôte fournit deux options. Si le participant devine correctement, il gagne 20 € ; sinon, il passe à la question suivante (car la bonne réponse serait l'autre option). Si le temps s'écoule avant que la question ne soit entièrement posée et que les deux réponses possibles soient fournies, le participant peut toujours y répondre ; cependant, si l'énoncé n'a pas été complété (ou si les options n'ont pas été fournies), il ne peut pas répondre." }, - "warm_quest": { - "name": "Question Chaleureuse", + "Warm Question": { + "name": "Warm Question", "desc": "Il se compose de dix sujets de thèmes variés. Pour chaque réponse correcte, 100 € sont gagnés, et 10 € sont perdus si le participant passe, ne répond pas ou répond incorrectement." }, - "discover": { - "name": "Découverte des Villes", + "Discovering Cities": { + "name": "Discovering Cities", "desc": "Dans le mode de jeu 'Découverte des Villes', le participant sera confronté à un défi où il lui sera posé à plusieurs reprises des questions se référant à différentes villes du monde entier. Pour surmonter avec succès le défi, le participant doit répondre correctement à autant de questions que possible tout au long du test." }, - "challenge": { - "name": "Défi", + "Challenge": { + "name": "Challenge", "desc": "Le mode de jeu 'Défi' est le mode de jeu par excellence, car il vous permet de personnaliser le match à votre guise. Ce mode de jeu est adapté à ceux qui souhaitent s'entraîner à certains formats de jeu avant de s'engager dans nos divers autres modes de jeu." }, - "multiplayer": { - "name": "Multijoueur", + "Multiplayer": { + "name": "Multiplayer", "desc": "Créez une salle pour que d'autres joueurs se joignent et jouent en 1 contre 1." } @@ -114,6 +114,7 @@ "Statistics": { "title": "STATISTIQUES", + "game": "Partie", "table": { "money": "Points gagnés", "questions_corr": "Questions Correctement Répondues", @@ -123,6 +124,10 @@ "total_time": "Temps Total Joué", "cities_corr": "Villes Répondus Correctement", "cities_incorr": "Villes Répondus Incorrectement" + }, + "button": { + "hide_record": "Masquer l'historique des questions", + "show_record": "Afficher l'historique des questions" } }, @@ -161,7 +166,7 @@ "Ranking": { "users": "Utilisateurs", "groups": "Groupes", - "total_money": "MONEY", + "total_money": "POINTS", "correct_answers": "CORRECT ANSWERS", "incorrect_answers": "INCORRECT ANSWERS", "total_games": "GAMES PLAYED" diff --git a/webapp/src/pages/Home.js b/webapp/src/pages/Home.js index 381a6c74..fcfa9336 100644 --- a/webapp/src/pages/Home.js +++ b/webapp/src/pages/Home.js @@ -1,10 +1,11 @@ import * as React from "react"; import {Box, Button} from "@mui/material"; import useMediaQuery from '@mui/material/useMediaQuery'; - +import { useTranslation } from 'react-i18next'; const Home = () => { const xxl = useMediaQuery('(min-width:1920px)'); + const { t } = useTranslation(); const styles = { logo:{ @@ -96,7 +97,7 @@ const Home = () => { Logo - + { t("Homepage.title") } {games} - + ); }; diff --git a/webapp/src/pages/Instructions.js b/webapp/src/pages/Instructions.js index 209b030b..0308bef6 100644 --- a/webapp/src/pages/Instructions.js +++ b/webapp/src/pages/Instructions.js @@ -1,12 +1,15 @@ import * as React from "react"; import { useTheme, Button, Typography, Grid, Box , CssBaseline, useMediaQuery } from "@mui/material"; import data from "../data/gameInfo.json"; +import { useTranslation } from 'react-i18next'; const Instructions = () => { const lg = useMediaQuery('(min-width: 1200px)'); + const { t } = useTranslation(); const theme = useTheme(); + const styles = { button:{ @@ -144,7 +147,8 @@ const Instructions = () => { Foto del minijuego {info[index].nombre} - {info[index].descripcion} + {t("Games." + + info[index].nombre +".desc")} ); diff --git a/webapp/src/pages/Statistics.js b/webapp/src/pages/Statistics.js index f1a9f082..79b90b51 100644 --- a/webapp/src/pages/Statistics.js +++ b/webapp/src/pages/Statistics.js @@ -228,7 +228,7 @@ const Statistics = () => { {currentItems.map((record, index) => (
- Game {formatCreatedAt(record.createdAt)} + {t("Statistics.game")} {formatCreatedAt(record.createdAt)} @@ -286,19 +286,19 @@ const Statistics = () => {
{renderStatistics()} @@ -307,7 +307,7 @@ const Statistics = () => { variant="contained" sx={{ marginBottom: '0.5em', marginTop: '0.5em', backgroundColor: 'green', color: theme.palette.secondary.main, borderColor: theme.palette.primary.main, '&:hover': { backgroundColor: theme.palette.secondary.main, color: theme.palette.primary.main, borderColor: theme.palette.primary.main } }} > - {showQuestionsRecord ? 'Hide Questions Record' : 'Show Questions Record'} + {showQuestionsRecord ? t("Statistics.button.hide_record") : t("Statistics.button.show_record")} {renderQuestions()}
diff --git a/webapp/src/pages/TheChallengeGame.js b/webapp/src/pages/TheChallengeGame.js index 9a5126e2..7299b1aa 100644 --- a/webapp/src/pages/TheChallengeGame.js +++ b/webapp/src/pages/TheChallengeGame.js @@ -10,9 +10,9 @@ import { useContext } from 'react'; import Confetti from 'react-confetti'; import { CountdownCircleTimer } from "react-countdown-circle-timer"; import Card from '@mui/material/Card'; -import CardContent from '@mui/material/CardContent'; import { useTranslation } from 'react-i18next'; import i18n from '../localize/i18n'; +import { PlayArrow, Pause } from '@mui/icons-material'; const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; @@ -51,6 +51,8 @@ const Game = () => { const [questionCountdownRunning, setQuestionCountdownRunning] = React.useState(false); //property to start and stop question timer const [userResponses, setUserResponses] = React.useState([]); const [language, setCurrentLanguage] = React.useState(i18n.language); + const [paused, setPaused] = React.useState(false); + const [passNewRound, setPassNewRound] = React.useState(false); const [questionHistorial, setQuestionHistorial] = React.useState(Array(numRounds).fill(null)); @@ -89,16 +91,25 @@ const Game = () => { setShowConfetti(false); } }, [correctlyAnsweredQuestions, incorrectlyAnsweredQuestions]); + + React.useEffect(() => { + if (passNewRound && !paused) { + setRound(prevRound => { + return prevRound + 1; + }); + setButtonStates([]); + } + }, [paused, passNewRound]); const startGame = () => { setConfigModalOpen(false); startNewRound(); }; - - // gets a random question from the database and initializes button states to null + const startNewRound = async () => { setAnswered(false); + setPassNewRound(false); // It works deploying using git repo from machine with: axios.get(`http://20.80.235.188:8000/questions`) setCurrentLanguage(i18n.language); axios.get(`${apiEndpoint}/questions/${language}/${category}`) @@ -211,28 +222,11 @@ const Game = () => { setButtonStates(newButtonStates); setTimeout(async() => { - setRound(round + 1); - setButtonStates([]); + setPassNewRound(true); setCurrentLanguage(i18n.language); }, 4000); }; - const questionHistorialBar = () => { - return questionHistorial.map((isCorrect, index) => ( - - {index + 1} - - )); - }; - // Render the configuration window before starting the game if (configModalOpen) { @@ -269,6 +263,7 @@ const Game = () => {
+ : + // Cronómetro selectResponse(0, "FAILED")} //when time ends always fail question - > - {({ remainingTime }) => { - return ( -
-
{remainingTime}
-
- ); - }} + data-testid="circleTimer" + key={questionCountdownKey} + isPlaying = {questionCountdownRunning} + duration={timerConfig} + colors={[theme.palette.success.main, "#F7B801", "#f50707", theme.palette.error.main]} + size={100} + colorsTime={[10, 6, 3, 0]} + onComplete={() => selectResponse(-1, "FAILED")} //when time ends always fail question + > + {({ remainingTime }) => { + return ( +
+
{remainingTime}
+
+ ); + }}
+ } + + + + + {questionData.question.toUpperCase()} {questionData.options.map((option, index) => (