diff --git a/server/src/api/helpers/error.js b/server/src/api/helpers/error.js index 2c75efe..9c3af07 100644 --- a/server/src/api/helpers/error.js +++ b/server/src/api/helpers/error.js @@ -1,32 +1,32 @@ -class Error { +class CustomError extends Error { constructor(status, message) { + super(message); this.status = status; - this.message = message; } static invalidRequest(message = 'Invalid request') { - return new Error(400, message); + return new CustomError(400, message); } static invalidCredentials(message = 'Invalid credentials') { - return new Error(401, message); + return new CustomError(401, message); } static accountNotActive(message = 'Account not active') { - return new Error(403, message); + return new CustomError(403, message); } static userNotFound(message = 'User not found') { - return new Error(404, message); + return new CustomError(404, message); } static mongoConflictError(message = 'MongoDB conflict error') { - return new Error(409, message); + return new CustomError(409, message); } static serverError(message = 'Internal server error') { - return new Error(500, message); + return new CustomError(500, message); } } -module.exports = Error; +module.exports = CustomError; diff --git a/server/tests/unit/getAllUsers.test.js b/server/tests/unit/getAllUsers.test.js index e0d27f6..8de41dd 100644 --- a/server/tests/unit/getAllUsers.test.js +++ b/server/tests/unit/getAllUsers.test.js @@ -1,7 +1,7 @@ const { User } = require('../../src/api/models'); -const { userService } = require('../../src/api/services'); +const { getAllUsers } = require('../../src/api/services/user.service'); -jest.mock('../../src/api/models/user.model.js', () => ({ +jest.mock('../../src/api/models/user.model', () => ({ find: jest.fn().mockResolvedValue([]), findById: jest.fn(), })); @@ -15,20 +15,15 @@ describe('userService.getAllUsers', () => { const mockAdminUser = { _id: '123', roles: ['admin'] }; User.findById.mockResolvedValue(mockAdminUser); - const result = await userService.getAllUsers('123'); + const result = await getAllUsers('123'); expect(result).toEqual([]); expect(User.findById).toHaveBeenCalledWith('123'); expect(User.find).toHaveBeenCalled(); }); - it('should return all users if the user is an admin', async () => { - const mockAdminUser = { _id: '123', roles: [] }; - User.findById.mockResolvedValue(mockAdminUser); - - try { - await userService.getAllUsers('123'); - } catch (error) { - expect(error.message).toBe('User is not an admin'); - } + it('should throw an error if the user is not an admin', async () => { + const mockUser = { _id: '123', roles: [] }; + User.findById.mockResolvedValue(mockUser); + await expect(getAllUsers('123')).rejects.toThrow('User is not an admin'); }); -}); \ No newline at end of file +}); diff --git a/server/tests/unit/getUserByUsername.test.js b/server/tests/unit/getUserByUsername.test.js index 6e4e292..502dc24 100644 --- a/server/tests/unit/getUserByUsername.test.js +++ b/server/tests/unit/getUserByUsername.test.js @@ -1,7 +1,7 @@ const { User } = require('../../src/api/models'); -const { userService } = require('../../src/api/services'); +const { getUserByUsername } = require('../../src/api/services/user.service'); -jest.mock('../../src/api/models/user.model.js', () => ({ +jest.mock('../../src/api/models/user.model', () => ({ findOne: jest.fn(), })); @@ -14,7 +14,7 @@ describe('userService.getUserByUsername', () => { const mockUser = { username: 'testUser', email: 'test@example.com' }; User.findOne.mockResolvedValue(mockUser); - const result = await userService.getUserByUsername('testUser'); + const result = await getUserByUsername('testUser'); expect(result).toEqual(mockUser); expect(User.findOne).toHaveBeenCalledWith({ username: 'testUser' }); }); @@ -22,10 +22,6 @@ describe('userService.getUserByUsername', () => { it('should throw an error if the user does not exist', async () => { User.findOne.mockResolvedValue(null); - try { - await userService.getUserByUsername('testUser'); - } catch (error) { - expect(error.message).toBe("User with username 'testUser' not found"); - } + await expect(getUserByUsername('testUser')).rejects.toThrow("User with username 'testUser' not found"); }); -}); \ No newline at end of file +}); diff --git a/server/tests/unit/requestVerification.test.js b/server/tests/unit/requestVerification.test.js index c587a6c..2753b62 100644 --- a/server/tests/unit/requestVerification.test.js +++ b/server/tests/unit/requestVerification.test.js @@ -1,55 +1,43 @@ -const jwt = require('jsonwebtoken'); const { User } = require('../../src/api/models'); -const { userService } = require('../../src/api/services'); +const { requestVerification } = require('../../src/api/services/user.service'); +const sendEmail = require('../../src/api/helpers/sendEmail'); jest.mock('jsonwebtoken', () => ({ sign: jest.fn().mockImplementation(() => 'mockedToken'), })); -jest.mock('../../src/api/models/user.model.js', () => ({ - findByIdAndUpdate: jest.fn(), - findById: jest.fn(), +jest.mock('../../src/api/models/user.model', () => ({ findOne: jest.fn(), })); -const sendEmail = require('../../src/api/helpers/sendEmail'); - jest.mock('../../src/api/helpers/sendEmail', () => jest.fn()); describe('userService.requestVerification', () => { beforeEach(() => { jest.clearAllMocks(); - // Reset the mock implementation to return a controlled value - jwt.sign.mockImplementation(() => 'mockedToken'); - }); - - it('should throw an error if user not found or already verified', async () => { - User.findOne.mockResolvedValueOnce(null); - try { - await userService.requestVerification('test@example.com'); - } catch (error) { - expect(error.message).toBe('User not found'); - } - }); - - it('should throw an error if user is already verified', async () => { - const user = { _id: '123', email: 'test@example.com', active: true }; - User.findOne.mockResolvedValueOnce(user); - try { - await userService.requestVerification('test@example.com') - } catch (error) { - expect(error.message).toBe('User already verified'); - } }); it('should send an email with verification link if user exists and not verified', async () => { - const user = { _id: '123', email: 'test@example.com', active: false }; - User.findOne.mockResolvedValueOnce(user); + const mockedUser = { _id: '123', email: 'test@example.com', active: false }; + User.findOne.mockResolvedValueOnce(mockedUser); const verificationLink = 'http://localhost:4000/api/users/verify?token=mockedToken'; - await userService.requestVerification('test@example.com'); + await requestVerification('test@example.com'); expect(User.findOne).toHaveBeenCalledWith({ email: 'test@example.com' }); expect(sendEmail).toHaveBeenCalledWith('test@example.com', 'Verify your email', verificationLink); }); + + it('should throw an error if user not found', async () => { + User.findOne.mockResolvedValueOnce(null); + + await expect(requestVerification('test@example.com')).rejects.toThrow('User not found'); + }); + + it('should throw an error if user is already verified', async () => { + const mockedUser = { _id: '123', email: 'test@example.com', active: true }; + User.findOne.mockResolvedValueOnce(mockedUser); + + await expect(requestVerification('test@example.com')).rejects.toThrow('User already verified'); + }); }); diff --git a/server/tests/unit/verifyUser.test.js b/server/tests/unit/verifyUser.test.js index f0c6ccd..396f8ba 100644 --- a/server/tests/unit/verifyUser.test.js +++ b/server/tests/unit/verifyUser.test.js @@ -1,15 +1,14 @@ -const jwt = require('jsonwebtoken'); const { User } = require('../../src/api/models'); -const { userService } = require('../../src/api/services'); +const { verifyUser } = require('../../src/api/services/user.service'); +const jwt = require('jsonwebtoken'); jest.mock('jsonwebtoken', () => ({ decode: jest.fn(), })); -jest.mock('../../src/api/models/user.model.js', () => ({ +jest.mock('../../src/api/models/user.model', () => ({ findByIdAndUpdate: jest.fn(), findById: jest.fn(), - findOne: jest.fn(), })); describe('userService.verifyUser', () => { @@ -20,17 +19,17 @@ describe('userService.verifyUser', () => { it('successfully verifies a user with a valid token', async () => { const token = 'validToken'; const userId = '123'; - const userData = { id: userId, name: 'Test User' }; + const mockedUser = { id: userId, active: false }; - jwt.decode.mockReturnValue(userData); - User.findById.mockResolvedValue(userData); - User.findByIdAndUpdate.mockResolvedValue({ ...userData, active: true }); + jwt.decode.mockReturnValue(mockedUser); + User.findById.mockResolvedValue(mockedUser); + User.findByIdAndUpdate.mockResolvedValue({ ...mockedUser, active: true }); - const result = await userService.verifyUser(token); + const result = await verifyUser(token); expect(jwt.decode).toHaveBeenCalledWith(token); expect(User.findByIdAndUpdate).toHaveBeenCalledWith(userId, { $set: { active: true } }, { new: true }); - expect(result).toEqual({ ...userData, active: true }); + expect(result).toEqual({ ...mockedUser, active: true }); }); it('throws an error for an invalid token', async () => { @@ -38,11 +37,7 @@ describe('userService.verifyUser', () => { jwt.decode.mockReturnValue(null); - try { - await userService.verifyUser(token); - } catch (error) { - expect(error.message).toBe('Invalid token'); - } + await expect(verifyUser(token)).rejects.toThrow('Invalid token'); }); it('throws an error when no token is provided', async () => { @@ -50,11 +45,7 @@ describe('userService.verifyUser', () => { jwt.decode.mockReturnValue(null); - try { - await userService.verifyUser(token); - } catch (error) { - expect(error.message).toBe('Invalid token'); - } + await expect(verifyUser(token)).rejects.toThrow('Invalid token'); }); it('throws an error for a non-existent user', async () => { @@ -62,28 +53,19 @@ describe('userService.verifyUser', () => { const userId = '999'; // Assuming this user does not exist jwt.decode.mockReturnValue({ id: userId }); - User.findByIdAndUpdate.mockResolvedValue(null); + User.findById.mockResolvedValue(null); - try { - await userService.verifyUser(token); - } catch (error) { - expect(error.message).toBe('User not found'); - } + await expect(verifyUser(token)).rejects.toThrow('User not found'); }); it('does not change the status of an already verified user', async () => { const token = 'validTokenForVerifiedUser'; - const userId = '123'; - const userData = { id: userId, name: 'Test User', active: true }; + const mockedUser = { id: '123', name: 'Test User', active: true }; - jwt.decode.mockReturnValue(userData); - User.findById.mockResolvedValue(userData); - User.findByIdAndUpdate.mockResolvedValue(userData); // User remains unchanged + jwt.decode.mockReturnValue(mockedUser); + User.findById.mockResolvedValue(mockedUser); + User.findByIdAndUpdate.mockResolvedValue(mockedUser); // User remains unchanged - try { - await userService.verifyUser(token); - } catch (error) { - expect(error.message).toBe('User already verified'); - } + await expect(verifyUser(token)).rejects.toThrow('User already verified'); }); });