diff --git a/gatewayservice/gateway-service.test.js b/gatewayservice/gateway-service.test.js
index abe0dac..71e217d 100644
--- a/gatewayservice/gateway-service.test.js
+++ b/gatewayservice/gateway-service.test.js
@@ -82,6 +82,37 @@ describe('Gateway Service', () => {
],
}
});
+ } else if(url.endsWith('getAllUsers')) {
+ return Promise.resolve({
+ status: 200,
+ data: {
+ users:
+ [{
+ "_id":"65e604d6b9b58650687ee809",
+ "username":"tomas",
+ "password":"$2b$10$cD6x4mUOP9Q16SfMpbWXGugPczuYcV/HMaJbVTWJ.guZoy.LmEe6e",
+ "email":"tomas@gmail.com",
+ "questions_answered":500,
+ "correctly_answered_questions":200,
+ "createdAt":"2024-03-03T17:30:54.385Z",
+ "cheeseCount":1
+ }]
+ }
+ });
+ } else if(url.endsWith('/getUser')){
+ return Promise.resolve({
+ status: 200,
+ data: {
+ "_id":"65e604d6b9b58650687ee809",
+ "username":"tomas",
+ "password":"$2b$10$cD6x4mUOP9Q16SfMpbWXGugPczuYcV/HMaJbVTWJ.guZoy.LmEe6e",
+ "email":"tomas@gmail.com",
+ "questions_answered":500,
+ "correctly_answered_questions":200,
+ "createdAt":"2024-03-03T17:30:54.385Z",
+ "cheeseCount":1
+ }
+ });
}
@@ -99,9 +130,11 @@ describe('Gateway Service', () => {
return Promise.resolve({ data: { token: 'mockedToken' } });
} else if (url.endsWith('/adduser')) {
return Promise.resolve({ data: { userId: 'mockedUserId' } });
- } else if(url.endsWith('/edituser')){
+ } else if(url.endsWith('/sumNormalStats')){
return Promise.resolve({ data: { message: 'User updated' } });
- }
+ } else if(url.endsWith('/sumTrivialStats')){
+ return Promise.resolve({ data: { message: 'User updated' } });
+ }
});
// Test health
@@ -198,5 +231,61 @@ describe('Gateway Service', () => {
const response = await request(app).get("/api-doc");
expect(response.status).toBe(301);
});
+
+ // Test /sumStats
+ it('should respond with a successful update operation of normal game mode stats', async () => {
+
+ await sumStats('/sumNormalStats', {
+ username: 'newuser',
+ questions_answered:500,
+ correctly_answered_questions:200
+ });
+ }, 6000);
+
+ it('should respond with a successful update operation of trivial game mode stats', async () => {
+ await sumStats('/sumTrivialStats', {
+ username: 'newuser',
+ cheeseCount:10
+ });
+ }, 6000);
+
+
+ async function sumStats(endpoint, user){
+ const response = await request(app)
+ .post(endpoint)
+ .send(user);
+ expect(response.status).toBe(200);
+ expect(response.body.message).toBe("User updated");
+ }
+
+ // Test getUser(s)
+
+ it('should retrieve the specified user', async () => {
+ const response = await request(app).post('/getUser').send({username: "tomas"});
+ expect(response.status).toBe(200);
+ console.log(response.body);
+ checkCorrectUserFields(response.body);
+
+ }, 6000);
+
+ it('should retrieve all the users', async () => {
+ const response = await request(app).get('/getAllUsers');
+ expect(response.status).toBe(200);
+ expect(response.body.users.length).toBe(1);
+ console.log(response.body);
+ await checkCorrectUserFields(response.body.users[0]);
+
+ }, 6000);
+
+ async function checkCorrectUserFields(user){
+ expect(user).toHaveProperty("_id");
+ expect(user).toHaveProperty("username");
+ expect(user).toHaveProperty("password");
+ expect(user).toHaveProperty("createdAt");
+ expect(user).toHaveProperty("email");
+ expect(user).toHaveProperty("questions_answered");
+ expect(user).toHaveProperty("correctly_answered_questions");
+ expect(user).toHaveProperty("cheeseCount");
+ }
});
\ No newline at end of file
diff --git a/users/authservice/auth-service.js b/users/authservice/auth-service.js
index 488d409..d1b6bfe 100644
--- a/users/authservice/auth-service.js
+++ b/users/authservice/auth-service.js
@@ -27,25 +27,13 @@ router.post('/login', async (req, res) => {
// Check if required fields are present in the request body
validateRequiredFields(req, ['username', 'password']);
- const username = req.body.username.toString();
- const password = req.body.password.toString();
-
-
- // access to the database
- const db = mongoose.connection.useDb("UsersDB");
-
- // access to the collection of the database
- const userCollection = db.collection('User');
-
+ const { username, password } = req.body;
let user;
-
- await userCollection.findOne({ username }, function(err, result) {
- if (err) {
- console.error('Error finding user. There is not user with that username:', err);
- } else {
- user = result;
- }
- });
+ try {
+ user = await User.findOne({ username });
+ } catch (err) {
+ throw new Error('Error finding the user')
+ }
// Check if the user exists and verify the password
if (user && await bcrypt.compare(password, user.password)) {
diff --git a/webapp/src/components/leaderboard/RankingTable.test.tsx b/webapp/src/components/leaderboard/RankingTable.test.tsx
index 2c3e685..9de944f 100644
--- a/webapp/src/components/leaderboard/RankingTable.test.tsx
+++ b/webapp/src/components/leaderboard/RankingTable.test.tsx
@@ -1,46 +1,65 @@
import React from 'react';
-import { render, screen, waitFor } from '@testing-library/react';
-import { act } from 'react-dom/test-utils';
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
import RankingTable, { User } from './RankingTable';
-import { getAllUsers } from '../../services/auth-service';
+import { getAllUsers } from "../../services/auth-service";
+import { act } from 'react-dom/test-utils'; // import act
+
jest.mock('../../services/auth-service');
describe('RankingTable', () => {
- it('true', () => {expect(true).toBe(true);});
- // it('renders users correctly', async () => {
- // const mockUsers: { [key: string]: User } = {
- // '1': { username: 'user1', correctAnswers: 5, totalAnswers: 10 },
- // '2': { username: 'user2', correctAnswers: 7, totalAnswers: 10 },
- // '3': { username: 'user3', correctAnswers: 3, totalAnswers: 10 },
- // };
-
- // (getAllUsers as jest.Mock).mockResolvedValue(mockUsers);
-
- // await act(async () => {
- // render();
- // });
-
- // await waitFor(() => {
- // expect(screen.getByText('user1')).toBeInTheDocument();
- // expect(screen.getByText('user2')).toBeInTheDocument();
- // expect(screen.getByText('user3')).toBeInTheDocument();
- // });
- // });
-
- // it('handles error during fetching users', async () => {
- // const consoleError = jest.spyOn(console, 'error').mockImplementation(() => {});
+ beforeEach(() => {
+ (getAllUsers as jest.Mock).mockResolvedValue({
+ user1: { username: 'user1', correctly_answered_questions: 5, questions_answered: 10 },
+ user2: { username: 'user2', correctly_answered_questions: 3, questions_answered: 10 },
+ user3: { username: 'user3', correctly_answered_questions: 7, questions_answered: 10 },
+ });
+ });
- // (getAllUsers as jest.Mock).mockRejectedValue(new Error('Error during fetching users'));
+ it('renders without crashing', () => {
+ render();
+ });
- // await act(async () => {
- // render();
- // });
+ it('displays users sorted by correct answers', async () => {
+ await act(async () => { // wrap render in act
+ render();
+ });
+
+ // Wait for users to load
+ const userNames = await screen.findAllByRole('cell', { name: /user\d/i });
+ expect(userNames[0]).toHaveTextContent('user3');
+ expect(userNames[1]).toHaveTextContent('user1');
+ expect(userNames[2]).toHaveTextContent('user2');
+ });
- // await waitFor(() => {
- // expect(consoleError).toHaveBeenCalledWith('Error during retrieving all the users', new Error('Error during fetching users'));
- // });
+ it('displays correct answers for each user', async () => {
+ await act(async () => { // wrap render in act
+ render();
+ });
+
+ // Wait for users to load
+ const correctAnswersUser0 = await screen.findByTestId('user-0-correct-answers');
+ const correctAnswersUser1 = await screen.findByTestId('user-1-correct-answers');
+ const correctAnswersUser2 = await screen.findByTestId('user-2-correct-answers');
+
+ expect(correctAnswersUser0).toHaveTextContent('7');
+ expect(correctAnswersUser1).toHaveTextContent('5');
+ expect(correctAnswersUser2).toHaveTextContent('3');
+});
- // consoleError.mockRestore();
- // });
+ it('displays correct percentage of correct answers for each user', async () => {
+ await act(async () => { // wrap render in act
+ render();
+ });
+
+ // Wait for users to load
+ const percentageUser0 = await screen.findByTestId('user-0-percentage');
+ const percentageUser1 = await screen.findByTestId('user-1-percentage');
+ const percentageUser2 = await screen.findByTestId('user-2-percentage');
+
+ expect(percentageUser0).toHaveTextContent('70%');
+ expect(percentageUser1).toHaveTextContent('50%');
+ expect(percentageUser2).toHaveTextContent('30%');
+ });
});
\ No newline at end of file
diff --git a/webapp/src/components/leaderboard/RankingTable.tsx b/webapp/src/components/leaderboard/RankingTable.tsx
index f016831..e9c00b4 100644
--- a/webapp/src/components/leaderboard/RankingTable.tsx
+++ b/webapp/src/components/leaderboard/RankingTable.tsx
@@ -57,32 +57,34 @@ export default function RankingTable() {
- {
- users.map((user, index) => {
- return (
-
-
+ {
+ users.map((user, index) => {
+ return (
+ |
+
- {user.username.toUpperCase().charAt(0)}{user.username.toUpperCase().charAt(1)}
+ {user.username.toUpperCase().charAt(0)}{user.username.toUpperCase().charAt(1)}
{user.username.toLowerCase()}
- |
-
- {index === 0 || index === 1 || index === 2 ? podium[index] : index + 1}
- |
- {user.correctAnswers} |
-
- 0 ? (Math.round(((user.correctAnswers / user.totalAnswers) * 100) * 100) / 100) : 0}
- color='#00A078' thickness='.4rem'
- size={"3.6rem"}>
- {user.totalAnswers > 0 ? (Math.round(((user.correctAnswers / user.totalAnswers) * 100) * 100) / 100).toFixed(0) : 0}%
-
- |
-
- )
- })
- }
+
+
+ {index === 0 || index === 1 || index === 2 ? podium[index] : index + 1}
+ |
+ {user.correctAnswers} |
+
+ 0 ? (Math.round(((user.correctAnswers / user.totalAnswers) * 100) * 100) / 100) : 0}
+ color='#00A078' thickness='.4rem'
+ size={"3.6rem"}>
+
+ {user.totalAnswers > 0 ? (Math.round(((user.correctAnswers / user.totalAnswers) * 100) * 100) / 100).toFixed(0) : 0}%
+
+
+ |
+
+ )
+ })
+ }
)
diff --git a/webapp/src/components/leaderboard/TrivialRankingTable.test.tsx b/webapp/src/components/leaderboard/TrivialRankingTable.test.tsx
new file mode 100644
index 0000000..150e98e
--- /dev/null
+++ b/webapp/src/components/leaderboard/TrivialRankingTable.test.tsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import { render, waitFor, screen } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
+import TrivialRankingTable, { User } from './TrivialRankingTable';
+import { getAllUsers } from '../../services/auth-service';
+import { act } from '@testing-library/react';
+
+jest.mock('../../services/auth-service');
+
+describe('TrivialRankingTable', () => {
+ const mockUsers: User[] = [
+ { username: 'user1', correctAnswers: 10, totalAnswers: 20, cheeseCount: 5 },
+ { username: 'user2', correctAnswers: 15, totalAnswers: 30, cheeseCount: 10 },
+ { username: 'user3', correctAnswers: 5, totalAnswers: 10, cheeseCount: 0 },
+ ];
+
+ beforeEach(() => {
+ (getAllUsers as jest.Mock).mockResolvedValue(mockUsers);
+ });
+
+ it('renders without crashing', async () => {
+ await act(async () => {
+ render();
+ });
+ });
+
+ it('displays users with cheeseCount greater than 0', async () => {
+ await act(async () => {
+ render();
+ });
+ await waitFor(() => expect(getAllUsers).toHaveBeenCalled());
+
+ expect(screen.getByText('user1')).toBeInTheDocument();
+ expect(screen.getByText('user2')).toBeInTheDocument();
+ expect(screen.queryByText('user3')).not.toBeInTheDocument();
+ });
+
+ it('sorts users by cheeseCount in descending order', async () => {
+ await act(async () => {
+ render();
+ });
+ await waitFor(() => expect(getAllUsers).toHaveBeenCalled());
+
+ const users = screen.getAllByTestId('user-row');
+ expect(users[0]).toHaveTextContent('user2');
+ expect(users[1]).toHaveTextContent('user1');
+ });
+});
\ No newline at end of file
diff --git a/webapp/src/components/leaderboard/TrivialRankingTable.tsx b/webapp/src/components/leaderboard/TrivialRankingTable.tsx
index d05086b..0522a6b 100644
--- a/webapp/src/components/leaderboard/TrivialRankingTable.tsx
+++ b/webapp/src/components/leaderboard/TrivialRankingTable.tsx
@@ -58,25 +58,25 @@ export default function TrivialRankingTable() {
- {
- users.map((user, index) => {
- return (
-
-
-
- {user.username.toUpperCase().charAt(0)}{user.username.toUpperCase().charAt(1)}
-
- {user.username.toLowerCase()}
- |
-
- {index === 0 || index === 1 || index === 2 ? podium[index] : index + 1}
- |
- {user.cheeseCount} |
-
-
- )
- })
- }
+ {
+ users.map((user, index) => {
+ return (
+
+
+
+ {user.username.toUpperCase().charAt(0)}{user.username.toUpperCase().charAt(1)}
+
+ {user.username.toLowerCase()}
+ |
+
+ {index === 0 || index === 1 || index === 2 ? podium[index] : index + 1}
+ |
+ {user.cheeseCount} |
+
+
+ )
+ })
+ }
)
diff --git a/webapp/src/components/stats/Statistics.test.tsx b/webapp/src/components/stats/Statistics.test.tsx
new file mode 100644
index 0000000..28f30fc
--- /dev/null
+++ b/webapp/src/components/stats/Statistics.test.tsx
@@ -0,0 +1,17 @@
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import Statistics from './Statistics';
+
+jest.mock('./StatsTable', () => () => Mock StatsTable
);
+
+describe('Statistics component', () => {
+ it('renders without crashing', () => {
+ render();
+ expect(screen.getByText('Statistics page')).toBeInTheDocument();
+ });
+
+ it('renders the StatsTable component', () => {
+ render();
+ expect(screen.getByText('Mock StatsTable')).toBeInTheDocument();
+ });
+});
\ No newline at end of file