From 6b316d7f0968ef60243cec18cccc186610a56272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fern=C3=A1ndez=20Noriega?= Date: Thu, 25 Apr 2024 15:57:39 +0200 Subject: [PATCH 1/4] Gateway service tests extended, now including ranking and health endpoints --- gatewayservice/gateway-service.test.js | 43 ++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/gatewayservice/gateway-service.test.js b/gatewayservice/gateway-service.test.js index f206033..26a1cf8 100644 --- a/gatewayservice/gateway-service.test.js +++ b/gatewayservice/gateway-service.test.js @@ -59,7 +59,7 @@ describe('Gateway Service', () => { } }); - axios.get.mockImplementation((url) => { + axios.get.mockImplementation((url,data) => { if (url.endsWith('/imgs/flags/question')) { return generateMockResponse(url, [ { item: 'Flag0', itemLabel: 'Country0', image: 'flag0.jpg' }, @@ -87,8 +87,16 @@ describe('Gateway Service', () => { ]); } else if (url.endsWith('/rankings/category1')) { return Promise.resolve({ data: mockUserData }); + } else if (url.endsWith('/ranking/user')) { + return Promise.resolve({data:{ + username: data.params.username, + category: data.params.category, + points: 5, + questions: 7, + correct: 5, + wrong: 2 + }}); } - }); // Test /login endpoint @@ -263,6 +271,37 @@ it('should forward get Foods request to question service', async () => { }); + // Test /health endpoint + it('should inform that the health is OK if the service is operative', async () => { + + // Send POST request to gateway endpoint + const response = await request(app) + .get('/health') + + // Verify response body + expect(response.body.status).toEqual('OK'); + }); + + // Test /ranking/user + it('should inform that the health is OK if the service is operative', async () => { + + // Send POST request to gateway endpoint + const response = await request(app) + .get('/ranking/user') + .query({ + username: "username", + category: "category" + }) + // Verify response body + expect(response.body).toEqual({ + username: "username", + category: "category", + points: 5, + questions: 7, + correct: 5, + wrong: 2 + }); + }); }); \ No newline at end of file From db8ff22eaa8e1d28e5c8ba7e55dbb6310c3a64e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fern=C3=A1ndez=20Noriega?= Date: Thu, 25 Apr 2024 17:13:29 +0200 Subject: [PATCH 2/4] AddUser test now includes error snackbar --- gatewayservice/gateway-service.test.js | 2 +- webapp/src/components/AddUser.test.js | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/gatewayservice/gateway-service.test.js b/gatewayservice/gateway-service.test.js index 26a1cf8..9a1ba0c 100644 --- a/gatewayservice/gateway-service.test.js +++ b/gatewayservice/gateway-service.test.js @@ -283,7 +283,7 @@ it('should forward get Foods request to question service', async () => { }); // Test /ranking/user - it('should inform that the health is OK if the service is operative', async () => { + it('should respond with the ranking info of the given user', async () => { // Send POST request to gateway endpoint const response = await request(app) diff --git a/webapp/src/components/AddUser.test.js b/webapp/src/components/AddUser.test.js index e6e6817..1c82124 100644 --- a/webapp/src/components/AddUser.test.js +++ b/webapp/src/components/AddUser.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { fireEvent, screen, waitFor } from '@testing-library/react'; +import { fireEvent, act, screen, waitFor } from '@testing-library/react'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import AddUser from './AddUser'; @@ -108,5 +108,15 @@ describe('AddUser component', () => { await waitFor(() => { expect(screen.getByText("Error: Passwords do not match")).toBeInTheDocument(); }); + + //Close the snackbar by clicking outside + await act(async ()=>{ + fireEvent.click(screen.getAllByText("Username")[1]) + }) + + //Snackbar has to have been closed + await waitFor(() => { + expect(screen.queryByText("Error: Passwords do not match")).not.toBeInTheDocument(); + }); }); }); From c11760e73ace04b5494751ab55e69ff4411dc480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fern=C3=A1ndez=20Noriega?= Date: Thu, 25 Apr 2024 18:03:43 +0200 Subject: [PATCH 3/4] Game tests include checking if the question categories render when clicked and the case in which user is not authenticated --- webapp/src/components/Game.test.js | 45 ++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/Game.test.js b/webapp/src/components/Game.test.js index 1255a21..4b98fe2 100644 --- a/webapp/src/components/Game.test.js +++ b/webapp/src/components/Game.test.js @@ -1,9 +1,12 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { fireEvent, act, render, screen, waitFor } from '@testing-library/react'; import Game from './Game'; import { jest } from '@jest/globals'; import useIsAuthenticated from 'react-auth-kit/hooks/useIsAuthenticated'; import useAuthUser from 'react-auth-kit/hooks/useAuthUser'; +import axios from 'axios'; +import MockAdapter from 'axios-mock-adapter'; +const mockAxios = new MockAdapter(axios); const mock = jest.fn(); @@ -13,6 +16,14 @@ jest.mock('react-router-dom', () => ({ useNavigate: () => mock, })); +mockAxios.onGet(/\/imgs\/([^\/]+)\/question/).reply(config => { + const category = config.url.match(/\/imgs\/([^\/]+)\/question/)[1]; + return [200, { + question: `${category} question`, + images: ["img1", "img2", "img3", "img4"] + }]; +}); + describe('Game page', () => { it('should render play message for authenticated user', async () => { useIsAuthenticated.mockReturnValue(() => true); @@ -31,5 +42,35 @@ describe('Game page', () => { throw new Error('Unauthenticated user was able to see Game page'); } catch (err) {} }); - + + it('should render the corresponding question depending on the option clicked', async () => { + useIsAuthenticated.mockReturnValue(() => true); + useAuthUser.mockReturnValue({ username: 'testUser' }); + + let gameOptions = ["Flag","City","Monument","Tourist attraction","Food"] + let gameCategories = ["flags","cities","monuments","tourist_attractions","foods"] + + for(let i=0;i); + //Click game option + await act(async ()=>{ + fireEvent.click(screen.getByText(gameOptions[i])) + }) + + //Should have rendered question category + await waitFor(()=>{ + expect(screen.getByText(gameCategories[i]+" question")).toBeInTheDocument() + }) + } + }); + + it('should navigate out of the game if the user is not authenticated', async () => { + useIsAuthenticated.mockReturnValue(() => false); + useAuthUser.mockReturnValue({ username: 'testUser' }); + + render(); + await waitFor(()=>{ + expect(screen.queryByText("Let's Play!")).not.toBeInTheDocument(); + }) + }); }); \ No newline at end of file From 6908f7483d0771035be21da223d5112d37247722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fern=C3=A1ndez=20Noriega?= Date: Thu, 25 Apr 2024 18:43:21 +0200 Subject: [PATCH 4/4] Question test extended to check Report transition (Also restart from it) --- webapp/src/components/Question.test.js | 82 +++++++++++++++++++++----- 1 file changed, 67 insertions(+), 15 deletions(-) diff --git a/webapp/src/components/Question.test.js b/webapp/src/components/Question.test.js index 4ce0480..14378a3 100644 --- a/webapp/src/components/Question.test.js +++ b/webapp/src/components/Question.test.js @@ -13,6 +13,25 @@ jest.mock('react-router-dom', () => ({ useNavigate: () => mock, })); +async function loadImages(){ + await act(async () => { + fireEvent.load(screen.getAllByRole("img")[0]) + fireEvent.load(screen.getAllByRole("img")[1]) + fireEvent.load(screen.getAllByRole("img")[2]) + fireEvent.load(screen.getAllByRole("img")[3]) + }); +} + +async function waitForTimeBarStart(){ + await waitFor(() => { + const time_bar = screen.getByTestId('time-bar'); + expect(time_bar).toBeInTheDocument(); + const widthStyle = time_bar.style.width; + const widthValue = parseFloat(widthStyle); + expect(widthValue).toBeGreaterThan(0); + }); +} + describe('Question page', () => { beforeEach(() => { mockAxios.reset(); @@ -95,21 +114,8 @@ describe('Question page', () => { expect(screen.getByText(/Which of the following/i)).toBeInTheDocument(); }); - await act(async () => { - fireEvent.load(screen.getAllByRole("img")[0]) - fireEvent.load(screen.getAllByRole("img")[1]) - fireEvent.load(screen.getAllByRole("img")[2]) - fireEvent.load(screen.getAllByRole("img")[3]) - }); - - // Wait for the component to render - await waitFor(() => { - const time_bar = screen.getByTestId('time-bar'); - expect(time_bar).toBeInTheDocument(); - const widthStyle = time_bar.style.width; - const widthValue = parseFloat(widthStyle); - expect(widthValue).toBeGreaterThan(0); - }); + await loadImages() + await waitForTimeBarStart() await act(async () => { fireEvent.click(screen.getAllByRole("img")[0]); @@ -153,6 +159,52 @@ describe('Question page', () => { expect(screen.getByText(/Score/i).textContent).toBe("Score: 0") }) }); + + it('should finish the game and render the report, from which game can be restarted', async () => { + useAuthUser.mockReturnValue({ username: 'testUser' }); + + mockAxios.onGet('http://localhost:8000/imgs/flags/question').reply(200, + { + question: "Which of the following flags belongs to Spain?", + images:["https://commons.wikimedia.org/wiki/File:Flag_of_Spain.svg" + ,"https://commons.wikimedia.org/wiki/File:Flag_of_England.svg" + ,"https://commons.wikimedia.org/wiki/File:Flag_of_Poland.svg" + ,"https://commons.wikimedia.org/wiki/File:Flag_of_Germany.svg"] + }); + + mockAxios.onPost('http://localhost:8000/imgs/answer').reply(200, + { + correct: "false", + correctImg: "https://commons.wikimedia.org/wiki/File:Flag_of_Spain.svg" + }); + + render(); + + await waitFor(() => { + expect(screen.getByText(/Which of the following/i)).toBeInTheDocument(); + }); + + const questionsPerGame = 10; + for(let i=0;i { + fireEvent.click(screen.getAllByRole("img")[2]); + }); + } + + await waitFor(() => { + expect(screen.queryByText("Game Over!")).toBeInTheDocument() + }) + + await act(async ()=>{ + fireEvent.click(screen.getByText("Restart Game")) + }) + + await waitFor(() => { + expect(screen.queryByText(/Which of the following/i)).toBeInTheDocument() + }) + }); });