Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More tests for frontend #217

Merged
merged 5 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 91 additions & 2 deletions gatewayservice/gateway-service.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
});
}


Expand All @@ -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
Expand Down Expand Up @@ -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");
}

});
24 changes: 6 additions & 18 deletions users/authservice/auth-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
89 changes: 54 additions & 35 deletions webapp/src/components/leaderboard/RankingTable.test.tsx
Original file line number Diff line number Diff line change
@@ -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(<RankingTable />);
// });

// 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(<RankingTable />);
});

// await act(async () => {
// render(<RankingTable />);
// });
it('displays users sorted by correct answers', async () => {
await act(async () => { // wrap render in act
render(<RankingTable />);
});

// 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(<RankingTable />);
});

// 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(<RankingTable />);
});

// 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%');
});
});
48 changes: 25 additions & 23 deletions webapp/src/components/leaderboard/RankingTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,32 +57,34 @@ export default function RankingTable() {
</tr>
</thead>
<tbody>
{
users.map((user, index) => {
return (
<tr key={index} className="body-row">
<td className="avatar">
{
users.map((user, index) => {
return (
<tr key={index} className="body-row">
<td className="avatar">
<Avatar.Root className="AvatarRoot">
<Avatar.Fallback className="AvatarFallback">{user.username.toUpperCase().charAt(0)}{user.username.toUpperCase().charAt(1)}</Avatar.Fallback>
<Avatar.Fallback className="AvatarFallback">{user.username.toUpperCase().charAt(0)}{user.username.toUpperCase().charAt(1)}</Avatar.Fallback>
</Avatar.Root>
{user.username.toLowerCase()}
</td>
<td className="ranking">
{index === 0 || index === 1 || index === 2 ? podium[index] : index + 1}
</td>
<td className="correct-answers">{user.correctAnswers}</td>
<td className="progress">
<CircularProgress
value={ user.totalAnswers > 0 ? (Math.round(((user.correctAnswers / user.totalAnswers) * 100) * 100) / 100) : 0}
color='#00A078' thickness='.4rem'
size={"3.6rem"}>
<CircularProgressLabel>{user.totalAnswers > 0 ? (Math.round(((user.correctAnswers / user.totalAnswers) * 100) * 100) / 100).toFixed(0) : 0}%</CircularProgressLabel>
</CircularProgress>
</td>
</tr>
)
})
}
</td>
<td className="ranking" data-testid="ranking-cell">
{index === 0 || index === 1 || index === 2 ? podium[index] : index + 1}
</td>
<td className="correct-answers" data-testid={`user-${index}-correct-answers`}>{user.correctAnswers}</td>
<td className="progress">
<CircularProgress
value={ user.totalAnswers > 0 ? (Math.round(((user.correctAnswers / user.totalAnswers) * 100) * 100) / 100) : 0}
color='#00A078' thickness='.4rem'
size={"3.6rem"}>
<CircularProgressLabel data-testid={`user-${index}-percentage`}>
{user.totalAnswers > 0 ? (Math.round(((user.correctAnswers / user.totalAnswers) * 100) * 100) / 100).toFixed(0) : 0}%
</CircularProgressLabel>
</CircularProgress>
</td>
</tr>
)
})
}
</tbody>
</table>
)
Expand Down
48 changes: 48 additions & 0 deletions webapp/src/components/leaderboard/TrivialRankingTable.test.tsx
Original file line number Diff line number Diff line change
@@ -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(<TrivialRankingTable />);
});
});

it('displays users with cheeseCount greater than 0', async () => {
await act(async () => {
render(<TrivialRankingTable />);
});
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(<TrivialRankingTable />);
});
await waitFor(() => expect(getAllUsers).toHaveBeenCalled());

const users = screen.getAllByTestId('user-row');
expect(users[0]).toHaveTextContent('user2');
expect(users[1]).toHaveTextContent('user1');
});
});
Loading
Loading