diff --git a/webapp/src/components/game/Game.js b/webapp/src/components/game/Game.js
index ffe3ac04..edcf768b 100644
--- a/webapp/src/components/game/Game.js
+++ b/webapp/src/components/game/Game.js
@@ -1,4 +1,4 @@
-import {HttpStatusCode} from "axios";
+import { HttpStatusCode } from "axios";
import AuthManager from "components/auth/AuthManager";
const authManager = new AuthManager();
@@ -15,11 +15,25 @@ export async function newGame() {
}
export async function startRound(gameId) {
- return await authManager.getAxiosInstance().post(process.env.REACT_APP_API_ENDPOINT + "/games/" + gameId + "/startRound");
+ try {
+ let requestAnswer = await authManager.getAxiosInstance().post(process.env.REACT_APP_API_ENDPOINT + "/games/" + gameId + "/startRound");
+ if (HttpStatusCode.Ok === requestAnswer.status) {
+ return requestAnswer.data;
+ }
+ } catch {
+
+ }
}
export async function getCurrentQuestion(gameId) {
- return await authManager.getAxiosInstance().get(process.env.REACT_APP_API_ENDPOINT + "/games/" + gameId + "/question");
+ try {
+ let requestAnswer = await authManager.getAxiosInstance().get(process.env.REACT_APP_API_ENDPOINT + "/games/" + gameId + "/question");
+ if (HttpStatusCode.Ok === requestAnswer.status) {
+ return requestAnswer.data;
+ }
+ } catch {
+
+ }
}
export async function changeLanguage(gameId, language) {
@@ -34,7 +48,14 @@ export async function changeLanguage(gameId, language) {
}
export async function answerQuestion(gameId, aId) {
- return await authManager.getAxiosInstance().post(process.env.REACT_APP_API_ENDPOINT + "/games/" + gameId + "/answer", {answer_id:aId});
+ try {
+ let requestAnswer = await authManager.getAxiosInstance().post(process.env.REACT_APP_API_ENDPOINT + "/games/" + gameId + "/answer", {answer_id:aId});
+ if (HttpStatusCode.Ok === requestAnswer.status) {
+ return requestAnswer.data;
+ }
+ } catch {
+
+ }
}
export async function getGameDetails(gameId) {
@@ -47,4 +68,3 @@ export async function getGameDetails(gameId) {
}
}
-
diff --git a/webapp/src/pages/Game.jsx b/webapp/src/pages/Game.jsx
index d5f875b2..4d41edb9 100644
--- a/webapp/src/pages/Game.jsx
+++ b/webapp/src/pages/Game.jsx
@@ -1,232 +1,232 @@
-import React, { useState, useEffect } from "react";
-import { Grid, Flex, Heading, Button, Box, Text, Spinner, CircularProgress } 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 { newGame, startRound, getCurrentQuestion, answerQuestion } from '../components/game/Game';
-import LateralMenu from '../components/LateralMenu';
-import MenuButton from '../components/MenuButton';
-import { HttpStatusCode } from "axios";
-
-export default function Game() {
- const navigate = useNavigate();
-
- const [loading, setLoading] = useState(true);
- const [gameId, setGameId] = useState(null);
- const [question, setQuestion] = useState(null);
- const [answer, setAnswer] = useState({});
- const [selectedOption, setSelectedOption] = useState(null);
- const [nextDisabled, setNextDisabled] = useState(true);
- const [roundNumber, setRoundNumber] = useState(1);
- const [correctAnswers, setCorrectAnswers] = useState(0);
- const [showConfetti, setShowConfetti] = useState(false);
- const [timeElapsed, setTimeElapsed] = useState(0);
- const [timeStartRound, setTimeStartRound] = useState(-1);
- const [roundDuration, setRoundDuration] = useState(0);
- const [maxRoundNumber, setMaxRoundNumber] = useState(9);
-
- const { t, i18n } = useTranslation();
- const [isMenuOpen, setIsMenuOpen] = useState(false);
-
- const changeLanguage = (selectedLanguage) => {
- i18n.changeLanguage(selectedLanguage);
- };
-
- const calculateProgress = () => {
- const percentage = (timeElapsed / roundDuration) * 100;
- return Math.min(Math.max(percentage, 0), 100);
- };
-
- const assignQuestion = async (gameId) => {
- try {
- const result = await getCurrentQuestion(gameId);
- if (result.status === HttpStatusCode.Ok) {
- setQuestion(result.data);
- setNextDisabled(false);
- setTimeElapsed(0);
- } else {
- navigate("/dashboard");
- }
- } catch (error) {
- console.error("Error fetching question:", error);
- navigate("/dashboard");
- }
- }
-
- const answerButtonClick = async (optionIndex, answer) => {
- const selectedOptionIndex = selectedOption === optionIndex ? null : optionIndex;
- setSelectedOption(selectedOptionIndex);
- await setAnswer(answer);
- const anyOptionSelected = selectedOptionIndex !== null;
- setNextDisabled(!anyOptionSelected);
- };
-
- const startNewRound = async (gameId) => {
- try{
- const result = await startRound(gameId);
- setTimeStartRound(new Date(result.data.round_start_time).getTime());
- setRoundNumber(result.data.actual_round )
- setRoundDuration(result.data.round_duration);
- await assignQuestion(gameId);
- setLoading(false);
- }
- catch(error){
- console.log(error)
- if(error.status === 409){
- if(roundNumber >= 9){
- navigate("/dashboard/game/results", { state: { correctAnswers: correctAnswers } });
- } else {
- await assignQuestion(gameId)
- }
- }
-
- }
-
- }
-
- /*
- Initialize game when loading the page
- */
- const initializeGame = async () => {
- try {
- const newGameResponse = await newGame();
- if (newGameResponse) {
- setGameId(newGameResponse.id);
- setTimeStartRound(new Date(newGameResponse.round_start_time).getTime());
- setRoundDuration(newGameResponse.round_duration)
- setMaxRoundNumber(newGameResponse.rounds);
- try{
- const result = await getCurrentQuestion(newGameResponse.id);
- if (result.status === HttpStatusCode.Ok) {
- setQuestion(result.data);
- setNextDisabled(false);
- setLoading(false);
- }
- }catch(error){
- startNewRound(newGameResponse.id);
- }
-
-
- } else {
- navigate("/dashboard");
- }
- } catch (error) {
- console.error("Error initializing game:", error);
- navigate("/dashboard");
- }
- };
-
- const nextRound = async () => {
- if (roundNumber + 1 > maxRoundNumber) {
- navigate("/dashboard/game/results", { state: { correctAnswers: correctAnswers } });
- } else {
- setAnswer({});
- setNextDisabled(true);
- await startNewRound(gameId);
- }
- }
-
- const nextButtonClick = async () => {
- try {
- const result = await answerQuestion(gameId, answer.id);
- let isCorrect = result.data.was_correct;
- if (isCorrect) {
- setCorrectAnswers(correctAnswers + (isCorrect ? 1 : 0));
- setShowConfetti(true);
- }
- setNextDisabled(true);
- setSelectedOption(null);
- await nextRound()
-
- } catch (error) {
- if(error.response.status === 400){
- setTimeout(nextButtonClick, 2000)
- }else{
- console.log('xd'+error.response.status)
- }
- }
- };
- useEffect(() => {
- // Empty dependency array [] ensures this effect runs only once after initial render
- initializeGame();
- // eslint-disable-next-line
- }, []);
- useEffect(() => {
- let timeout;
- if (showConfetti)
- timeout = setTimeout(() => { setShowConfetti(false); }, 3000);
- return () => clearTimeout(timeout);
- }, [showConfetti]);
-
- useEffect(() => {
- let timeout;
- if (timeElapsed >= roundDuration && timeStartRound !== -1) {
- timeout = setTimeout(() => nextRound(), 1000);
-
- } else {
- timeout = setTimeout(() => {
- setTimeElapsed((prevTime) => prevTime + 1);
- }, 1000);
- }
- return () => clearTimeout(timeout);
- // eslint-disable-next-line
- }, [timeElapsed, timeStartRound, roundDuration]);
-
-
- return (
-
- setIsMenuOpen(true)} />
- setIsMenuOpen(false)} changeLanguage={changeLanguage} isDashboard={false}/>
-
- {t("game.round") + `${roundNumber}`}
-
- {`Correct answers: ${correctAnswers}`}
-
-
-
-
- {loading ? (
-
- ) : (
- question && (
- <>
- {question.content}
-
-
- {question.answers.map((answer, index) => (
-
- ))}
-
-
-
-
-
-
- {showConfetti && (
-
- )}
- >
- )
- )}
-
-
- );
+import React, { useState, useEffect } from "react";
+import { Grid, Flex, Heading, Button, Box, Text, Spinner, CircularProgress } 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 { newGame, startRound, getCurrentQuestion, answerQuestion } from '../components/game/Game';
+import LateralMenu from '../components/LateralMenu';
+import MenuButton from '../components/MenuButton';
+import { HttpStatusCode } from "axios";
+
+export default function Game() {
+ const navigate = useNavigate();
+
+ const [loading, setLoading] = useState(true);
+ const [gameId, setGameId] = useState(null);
+ const [question, setQuestion] = useState(null);
+ const [answer, setAnswer] = useState({});
+ const [selectedOption, setSelectedOption] = useState(null);
+ const [nextDisabled, setNextDisabled] = useState(true);
+ const [roundNumber, setRoundNumber] = useState(1);
+ const [correctAnswers, setCorrectAnswers] = useState(0);
+ const [showConfetti, setShowConfetti] = useState(false);
+ const [timeElapsed, setTimeElapsed] = useState(0);
+ const [timeStartRound, setTimeStartRound] = useState(-1);
+ const [roundDuration, setRoundDuration] = useState(0);
+ const [maxRoundNumber, setMaxRoundNumber] = useState(9);
+
+ const { t, i18n } = useTranslation();
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+
+ const changeLanguage = (selectedLanguage) => {
+ i18n.changeLanguage(selectedLanguage);
+ };
+
+ const calculateProgress = () => {
+ const percentage = (timeElapsed / roundDuration) * 100;
+ return Math.min(Math.max(percentage, 0), 100);
+ };
+
+ const assignQuestion = async (gameId) => {
+ try {
+ const result = await getCurrentQuestion(gameId);
+ if (result.status === HttpStatusCode.Ok) {
+ setQuestion(result.data);
+ setNextDisabled(false);
+ setTimeElapsed(0);
+ } else {
+ navigate("/dashboard");
+ }
+ } catch (error) {
+ console.error("Error fetching question:", error);
+ navigate("/dashboard");
+ }
+ }
+
+ const answerButtonClick = async (optionIndex, answer) => {
+ const selectedOptionIndex = selectedOption === optionIndex ? null : optionIndex;
+ setSelectedOption(selectedOptionIndex);
+ await setAnswer(answer);
+ const anyOptionSelected = selectedOptionIndex !== null;
+ setNextDisabled(!anyOptionSelected);
+ };
+
+ const startNewRound = async (gameId) => {
+ try{
+ const result = await startRound(gameId);
+ setTimeStartRound(new Date(result.data.round_start_time).getTime());
+ setRoundNumber(result.data.actual_round )
+ setRoundDuration(result.data.round_duration);
+ await assignQuestion(gameId);
+ setLoading(false);
+ }
+ catch(error){
+ console.log(error)
+ if(error.status === 409){
+ if(roundNumber >= 9){
+ navigate("/dashboard/game/results", { state: { correctAnswers: correctAnswers } });
+ } else {
+ await assignQuestion(gameId)
+ }
+ }
+
+ }
+
+ }
+
+ /*
+ Initialize game when loading the page
+ */
+ const initializeGame = async () => {
+ try {
+ const newGameResponse = await newGame();
+ if (newGameResponse) {
+ setGameId(newGameResponse.id);
+ setTimeStartRound(new Date(newGameResponse.round_start_time).getTime());
+ setRoundDuration(newGameResponse.round_duration)
+ setMaxRoundNumber(newGameResponse.rounds);
+ try{
+ const result = await getCurrentQuestion(newGameResponse.id);
+ if (result.status === HttpStatusCode.Ok) {
+ setQuestion(result.data);
+ setNextDisabled(false);
+ setLoading(false);
+ }
+ }catch(error){
+ startNewRound(newGameResponse.id);
+ }
+
+
+ } else {
+ navigate("/dashboard");
+ }
+ } catch (error) {
+ console.error("Error initializing game:", error);
+ navigate("/dashboard");
+ }
+ };
+
+ const nextRound = async () => {
+ if (roundNumber + 1 > maxRoundNumber) {
+ navigate("/dashboard/game/results", { state: { correctAnswers: correctAnswers } });
+ } else {
+ setAnswer({});
+ setNextDisabled(true);
+ await startNewRound(gameId);
+ }
+ }
+
+ const nextButtonClick = async () => {
+ try {
+ const result = await answerQuestion(gameId, answer.id);
+ let isCorrect = result.data.was_correct;
+ if (isCorrect) {
+ setCorrectAnswers(correctAnswers + (isCorrect ? 1 : 0));
+ setShowConfetti(true);
+ }
+ setNextDisabled(true);
+ setSelectedOption(null);
+ await nextRound()
+
+ } catch (error) {
+ if(error.response.status === 400){
+ setTimeout(nextButtonClick, 2000)
+ }else{
+ console.log('xd'+error.response.status)
+ }
+ }
+ };
+ useEffect(() => {
+ // Empty dependency array [] ensures this effect runs only once after initial render
+ initializeGame();
+ // eslint-disable-next-line
+ }, []);
+ useEffect(() => {
+ let timeout;
+ if (showConfetti)
+ timeout = setTimeout(() => { setShowConfetti(false); }, 3000);
+ return () => clearTimeout(timeout);
+ }, [showConfetti]);
+
+ useEffect(() => {
+ let timeout;
+ if (timeElapsed >= roundDuration && timeStartRound !== -1) {
+ timeout = setTimeout(() => nextRound(), 1000);
+
+ } else {
+ timeout = setTimeout(() => {
+ setTimeElapsed((prevTime) => prevTime + 1);
+ }, 1000);
+ }
+ return () => clearTimeout(timeout);
+ // eslint-disable-next-line
+ }, [timeElapsed, timeStartRound, roundDuration]);
+
+
+ return (
+
+ setIsMenuOpen(true)} />
+ setIsMenuOpen(false)} changeLanguage={changeLanguage} isDashboard={false}/>
+
+ {t("game.round") + `${roundNumber}`}
+
+ {`Correct answers: ${correctAnswers}`}
+
+
+
+
+ {loading ? (
+
+ ) : (
+ question && (
+ <>
+ {question.content}
+
+
+ {question.answers.map((answer, index) => (
+
+ ))}
+
+
+
+
+
+
+ {showConfetti && (
+
+ )}
+ >
+ )
+ )}
+
+
+ );
}
\ No newline at end of file
diff --git a/webapp/src/tests/Game.test.js b/webapp/src/tests/Game.test.js
index 58c8e60d..74c8e69a 100644
--- a/webapp/src/tests/Game.test.js
+++ b/webapp/src/tests/Game.test.js
@@ -1,79 +1,94 @@
-import React from 'react';
-import { render, fireEvent, screen, act } from '@testing-library/react';
-import { MemoryRouter } from 'react-router';
-import Game from '../pages/Game';
+import React from "react";
+import { render, fireEvent, waitFor } from "@testing-library/react";
+import "@testing-library/jest-dom/extend-expect";
import { ChakraProvider } from '@chakra-ui/react';
import theme from '../styles/theme';
-import { getQuestion } from '../components/game/Questions';
-
-jest.mock('react-i18next', () => ({
- useTranslation: () => {
- return {
- t: (str) => str,
- i18n: {
- changeLanguage: () => new Promise(() => {}),
- },
- }
- },
-}));
+import { MemoryRouter } from 'react-router';
+import Game from "../pages/Game";
+import { HttpStatusCode } from "axios";
+import AuthManager from "components/auth/AuthManager";
+import MockAdapter from "axios-mock-adapter";
-jest.mock('../components/game/Questions', () => ({
- getQuestion: jest.fn(),
-}));
+describe("Game Component", () => {
+ const authManager = new AuthManager();
+ let mockAxios;
-describe('Game component', () => {
- /*
beforeEach(() => {
- getQuestion.mockResolvedValue({
- content: 'Test question',
- answers: [
- { id: 1, text: 'Test answer 1', category: 'Test category 1' },
- { id: 2, text: 'Test answer 2', category: 'Test category 2' },
- ],
- });
+ authManager.reset();
+ mockAxios = new MockAdapter(authManager.getAxiosInstance());
});
- afterEach(() => {
- jest.restoreAllMocks();
+ afterAll(() => {
+ mockAxios = null;
+ authManager.reset();
});
- */
- test('selects an option when clicked', async () => {
- /*
- render();
- const option1Button = await screen.findByTestId('Option1');
- act(() => fireEvent.click(option1Button));
-
- expect(option1Button).toHaveClass('chakra-button custom-button effect1 css-m4hh83');
- */
+ it("renders loading spinner initially", () => {
+ const { getByTestId } = render();
+ expect(getByTestId("loading-spinner")).toBeInTheDocument();
});
- /*
- test('disables next button when no option is selected', async () => {
- render();
- const nextButton = await screen.findByTestId('Next');
- expect(nextButton).toBeDisabled();
+ it("renders round number and correct answers count", async () => {
+ const { getByText } = render();
+ expect(getByText("game.round1")).toBeInTheDocument();
+ expect(getByText("Correct answers: 0")).toBeInTheDocument();
});
- test('enables next button when an option is selected', async () => {
- render();
- const option1Button = await screen.findByTestId('Option1');
- const nextButton = await screen.findByTestId('Next');
-
- act(() => fireEvent.click(option1Button));
-
- expect(nextButton).toBeEnabled();
+ it("displays question and options after loading", async () => {
+ const data = {
+ question: "What is the capital of Spain?",
+ options: ["Madrid", "Barcelona", "Seville", "Valencia"],
+ };
+ mockAxios.onGet().reply(HttpStatusCode.Ok, data);
+ const { container } = render();
+ waitFor(() => {
+ expect(container).toHaveTextContent("What is the capital of Spain?");
+ expect(container).toHaveTextContent("Madrid");
+ expect(container).toHaveTextContent("Barcelona");
+ expect(container).toHaveTextContent("Seville");
+ expect(container).toHaveTextContent("Valencia");
+ });
});
- test('renders ButtonEf component correctly', async () => {
- render();
- const option2Button = await screen.findByTestId('Option2');
-
- expect(option2Button).toHaveClass('chakra-button custom-button effect1 css-147pzm2');
-
- act(() => fireEvent.click(option2Button));
-
- expect(option2Button).toHaveClass('chakra-button custom-button effect1 css-m4hh83');
+ it("allows selecting an answer and enables next button", async () => {
+ const data = {
+ question: "What is the capital of Spain?",
+ options: ["Madrid", "Barcelona", "Seville", "Valencia"],
+ };
+ mockAxios.onGet().reply(HttpStatusCode.Ok, data);
+ const { container } = render();
+ waitFor(() => {
+ const optionButton = container.querySelector("button");
+ fireEvent.click(optionButton);
+ expect(optionButton).toHaveStyle("background-color: green");
+ const nextButton = container.querySelector("button");
+ expect(nextButton).not.toBeDisabled();
+ });
+ });
+ it("displays correct answer after selecting wrong answer", async () => {
+ const data = {
+ question: "What is the capital of Spain?",
+ options: ["Madrid", "Barcelona", "Seville", "Valencia"],
+ };
+ mockAxios.onGet().reply(HttpStatusCode.Ok, data);
+ const { container } = render();
+ waitFor(() => {
+ const optionButton = container.querySelector("button");
+ fireEvent.click(optionButton);
+ expect(optionButton).toHaveStyle("background-color: red");
+ });
+ });
+ it("displays correct answer after selecting correct answer", async () => {
+ const data = {
+ question: "What is the capital of Spain?",
+ options: ["Madrid", "Barcelona", "Seville", "Valencia"],
+ };
+ mockAxios.onGet().reply(HttpStatusCode.Ok, data);
+ const { container } = render();
+ waitFor(() => {
+ const optionButton = container.querySelector("button");
+ fireEvent.click(optionButton);
+ expect(optionButton).toHaveStyle("background-color: green");
+ });
});
- */
});
diff --git a/webapp/src/tests/GameAPI.test.js b/webapp/src/tests/GameAPI.test.js
new file mode 100644
index 00000000..c67109dd
--- /dev/null
+++ b/webapp/src/tests/GameAPI.test.js
@@ -0,0 +1,193 @@
+import MockAdapter from "axios-mock-adapter";
+import { newGame, startRound, getCurrentQuestion, changeLanguage, answerQuestion, getGameDetails } from "components/game/Game";
+import axios, { HttpStatusCode } from "axios";
+import AuthManager from "components/auth/AuthManager";
+
+jest.mock('react-i18next', () => ({
+ useTranslation: () => {
+ return {
+ t: (str) => str,
+ i18n: {
+ changeLanguage: () => new Promise(() => {}),
+ },
+ }
+ },
+}));
+
+const authManager = new AuthManager();
+let mockAxios;
+
+describe("Game Service tests", () => {
+ beforeEach(() => {
+ authManager.reset();
+ mockAxios = new MockAdapter(authManager.getAxiosInstance());
+ });
+
+ describe("newGame function", () => {
+ it("successfully creates a new game", async () => {
+ const mockResponse = { gameId: 123, status: "created" };
+
+ mockAxios.onPost(process.env.REACT_APP_API_ENDPOINT + "/games/new").replyOnce(
+ HttpStatusCode.Ok,
+ mockResponse
+ );
+
+ const result = await newGame();
+
+ expect(result).toEqual(mockResponse);
+ });
+
+ it("handles errors when creating a new game", async () => {
+ mockAxios.onPost(process.env.REACT_APP_API_ENDPOINT + "/games/new").replyOnce(
+ HttpStatusCode.InternalServerError
+ );
+
+ const result = await newGame();
+
+ expect(result).toBeUndefined();
+ });
+ });
+
+ describe("startRound function", () => {
+ it("successfully starts a new round", async () => {
+ const gameId = 123;
+ const mockResponse = { roundId: 456, status: "started" };
+
+ mockAxios.onPost(process.env.REACT_APP_API_ENDPOINT + `/games/${gameId}/startRound`).replyOnce(
+ HttpStatusCode.Ok,
+ mockResponse
+ );
+
+ const result = await startRound(gameId);
+
+ expect(result).toEqual(mockResponse);
+ });
+
+ it("handles errors when starting a new round", async () => {
+ const gameId = 123;
+
+ mockAxios.onPost(process.env.REACT_APP_API_ENDPOINT + `/games/${gameId}/startRound`).replyOnce(
+ HttpStatusCode.NotFound
+ );
+
+ const result = await startRound(gameId);
+
+ expect(result).toBeUndefined();
+ });
+ });
+ describe("getCurrentQuestion function", () => {
+ it("successfully retrieves current question", async () => {
+ const gameId = 123;
+ const mockResponse = { questionId: 456, text: "What's your name?" };
+
+ mockAxios.onGet(process.env.REACT_APP_API_ENDPOINT + `/games/${gameId}/question`).replyOnce(
+ HttpStatusCode.Ok,
+ mockResponse
+ );
+
+ const result = await getCurrentQuestion(gameId);
+
+ expect(result).toEqual(mockResponse);
+ });
+
+ it("handles errors when retrieving current question", async () => {
+ const gameId = 123;
+
+ mockAxios.onGet(process.env.REACT_APP_API_ENDPOINT + `/games/${gameId}/question`).replyOnce(
+ HttpStatusCode.NotFound
+ );
+
+ const result = await getCurrentQuestion(gameId);
+
+ expect(result).toBeUndefined();
+ });
+ });
+
+ describe("changeLanguage function", () => {
+ it("successfully changes language", async () => {
+ const gameId = 123;
+ const language = "en";
+ const mockResponse = { success: true, message: "Language changed successfully." };
+
+ mockAxios.onPut(process.env.REACT_APP_API_ENDPOINT + `/games/${gameId}/language?language=${language}`).replyOnce(
+ HttpStatusCode.Ok,
+ mockResponse
+ );
+
+ const result = await changeLanguage(gameId, language);
+
+ expect(result).toEqual(mockResponse);
+ });
+
+ it("handles errors when changing language", async () => {
+ const gameId = 123;
+ const language = "en";
+
+ mockAxios.onPut(process.env.REACT_APP_API_ENDPOINT + `/games/${gameId}/language?language=${language}`).replyOnce(
+ HttpStatusCode.BadRequest
+ );
+
+ const result = await changeLanguage(gameId, language);
+
+ expect(result).toBeUndefined();
+ });
+ });
+
+ describe("answerQuestion function", () => {
+ it("successfully submits an answer", async () => {
+ const gameId = 123;
+ const answerId = "a1";
+ const mockResponse = { success: true, message: "Answer submitted successfully." };
+
+ mockAxios.onPost(process.env.REACT_APP_API_ENDPOINT + `/games/${gameId}/answer`, { answer_id: answerId }).replyOnce(
+ HttpStatusCode.Ok,
+ mockResponse
+ );
+
+ const result = await answerQuestion(gameId, answerId);
+
+ expect(result).toEqual(mockResponse);
+ });
+
+ it("handles errors when submitting an answer", async () => {
+ const gameId = 123;
+ const answerId = "a1";
+
+ mockAxios.onPost(process.env.REACT_APP_API_ENDPOINT + `/games/${gameId}/answer`, { answer_id: answerId }).replyOnce(
+ HttpStatusCode.InternalServerError
+ );
+
+ const result = await answerQuestion(gameId, answerId);
+
+ expect(result).toBeUndefined();
+ });
+ });
+
+ describe("getGameDetails function", () => {
+ it("successfully retrieves game details", async () => {
+ const gameId = 123;
+ const mockResponse = { gameId: 123, status: "started" };
+
+ mockAxios.onGet(process.env.REACT_APP_API_ENDPOINT + `/games/${gameId}/details`).replyOnce(
+ HttpStatusCode.Ok,
+ mockResponse
+ );
+
+ const result = await getGameDetails(gameId);
+
+ expect(result).toEqual(mockResponse);
+ });
+
+ it("handles errors when retrieving game details", async () => {
+ const gameId = 123;
+
+ mockAxios.onGet(process.env.REACT_APP_API_ENDPOINT + `/games/${gameId}/details`).replyOnce(
+ HttpStatusCode.NotFound
+ );
+
+ const result = await getGameDetails(gameId);
+
+ expect(result).toBeUndefined();
+ });
+ });
+});