From e1f234d54be679a840633bbfcfef1b62e9caa893 Mon Sep 17 00:00:00 2001 From: Ravinou Date: Sun, 6 Apr 2025 20:48:50 +0200 Subject: [PATCH] =?UTF-8?q?test:=20=E2=9C=85=20adding=20some=20API=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- helpers/functions/auth.ts | 1 - helpers/functions/index.ts | 1 - helpers/functions/timestampConverter.ts | 12 -- pages/api/account/updateEmail.test.ts | 237 +++++++++++---------- pages/api/account/updateEmailAlert.test.ts | 149 +++++++++++++ pages/api/account/updatePasssword.test.ts | 0 pages/api/account/updatePassword.test.ts | 173 +++++++++++++++ pages/api/account/updateUsername.test.ts | 172 +++++++++++++++ 8 files changed, 623 insertions(+), 122 deletions(-) delete mode 100644 helpers/functions/timestampConverter.ts delete mode 100644 pages/api/account/updatePasssword.test.ts create mode 100644 pages/api/account/updatePassword.test.ts diff --git a/helpers/functions/auth.ts b/helpers/functions/auth.ts index 39ca865..497c641 100644 --- a/helpers/functions/auth.ts +++ b/helpers/functions/auth.ts @@ -1,5 +1,4 @@ // This function is used to hash user passwords and to verify them with the bcryptjs library -//Lib import { hash, compare } from 'bcryptjs'; export async function hashPassword(password: string) { diff --git a/helpers/functions/index.ts b/helpers/functions/index.ts index d6cede5..d9487ec 100644 --- a/helpers/functions/index.ts +++ b/helpers/functions/index.ts @@ -3,6 +3,5 @@ export * from './isSshPubKeyDuplicate'; export * from './lanCommandOption'; export * from './nodemailerSMTP'; export * from './repoHistory'; -export * from './timestampConverter'; export * from './tokenController'; export * from './shell.utils'; diff --git a/helpers/functions/timestampConverter.ts b/helpers/functions/timestampConverter.ts deleted file mode 100644 index 6f05239..0000000 --- a/helpers/functions/timestampConverter.ts +++ /dev/null @@ -1,12 +0,0 @@ -// This function is used to parse the date and time into a human readable format from the timestamp. -export function timestampConverter(UNIX_timestamp) { - const a = new Date(UNIX_timestamp * 1000); - const year = a.getFullYear(); - const month = a.getMonth() + 1; - const date = a.getDate(); - const hour = a.getHours(); - const min = (a.getMinutes() < 10 ? '0' : '') + a.getMinutes(); - //const sec = a.getSeconds(); - const time = year + '/' + month + '/' + date + ' ' + hour + ':' + min; - return time; -} diff --git a/pages/api/account/updateEmail.test.ts b/pages/api/account/updateEmail.test.ts index 0b1cb67..fbc881d 100644 --- a/pages/api/account/updateEmail.test.ts +++ b/pages/api/account/updateEmail.test.ts @@ -1,137 +1,158 @@ -import { describe, it, expect, vi } from 'vitest'; -import handler from './updateEmail'; -import { getUsersList, updateUsersList } from '~/services'; +import { createMocks } from 'node-mocks-http'; +import handler from '~/pages/api/account/updateEmail'; import { getServerSession } from 'next-auth/next'; -import { NextApiRequest, NextApiResponse } from 'next'; +import { getUsersList, updateUsersList } from '~/services'; +vi.mock('next-auth/next'); vi.mock('~/services', () => ({ getUsersList: vi.fn(), updateUsersList: vi.fn(), })); -vi.mock('next-auth/next', () => ({ - getServerSession: vi.fn(), -})); - -describe('updateEmail API handler', () => { - const mockReq = { - method: 'PUT', - body: { email: 'newemail@example.com' }, - } as unknown as NextApiRequest; - - const mockRes = { - status: vi.fn().mockReturnThis(), - json: vi.fn(), - } as unknown as NextApiResponse; - - it('should return 405 if method is not PUT', async () => { - mockReq.method = 'GET'; - await handler(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(405); +describe('PUT /api/account/updateEmail', () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.spyOn(console, 'log').mockImplementation(() => {}); }); - it('should return 401 if session is not found', async () => { - vi.mocked(getServerSession).mockResolvedValueOnce(null); - await handler(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(401); + it('should return 401 if not authenticated', async () => { + vi.mocked(getServerSession).mockResolvedValue(null); + + const { req, res } = createMocks({ method: 'PUT' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(401); + }); + + it('should return 405 if method is not PUT', async () => { + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(405); }); it('should return 422 if email is not provided', async () => { - mockReq.body = {}; - vi.mocked(getServerSession).mockResolvedValueOnce({ user: { name: 'testuser' } }); - await handler(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(422); - expect(mockRes.json).toHaveBeenCalledWith({ message: 'Unexpected data' }); + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + const { req, res } = createMocks({ + method: 'PUT', + body: {}, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(422); + expect(res._getJSONData()).toEqual({ message: 'Unexpected data' }); }); - it('should return 400 if user is not found in users list', async () => { - vi.mocked(getServerSession).mockResolvedValueOnce({ user: { name: 'testuser' } }); - vi.mocked(getUsersList).mockResolvedValueOnce([]); - await handler(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(400); - expect(mockRes.json).toHaveBeenCalledWith({ + it('should return 400 if user is not found in the users list', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + vi.mocked(getUsersList).mockResolvedValue([ + { id: 1, username: 'Ada', email: 'ada@example.com', password: '', roles: [] }, + ]); + + const { req, res } = createMocks({ + method: 'PUT', + body: { email: 'new@example.com' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(400); + expect(res._getJSONData()).toEqual({ message: 'User is incorrect. Please, logout to update your session.', }); }); it('should return 400 if email already exists', async () => { - vi.mocked(getServerSession).mockResolvedValueOnce({ user: { name: 'testuser' } }); - vi.mocked(getUsersList).mockResolvedValueOnce([ - { - username: 'testuser', - email: 'oldemail@example.com', - id: 1, - password: 'hashedpassword', - roles: ['user'], - }, - { - username: 'otheruser', - email: 'newemail@example.com', - id: 2, - password: 'hashedpassword', - roles: ['user'], - }, - ]); - await handler(mockReq, mockRes); - expect(mockRes.status).toHaveBeenCalledWith(400); - expect(mockRes.json).toHaveBeenCalledWith({ message: 'Email already exists' }); - }); - - it('should update email and return 200 on success', async () => { - vi.mocked(getServerSession).mockResolvedValueOnce({ user: { name: 'testuser' } }); - vi.mocked(getUsersList).mockResolvedValueOnce([ - { - username: 'testuser', - email: 'oldemail@example.com', - id: 1, - password: 'hashedpassword', - roles: ['user'], - }, - { - username: 'otheruser', - email: 'otheremail@example.com', - id: 2, - password: 'hashedpassword', - roles: ['user'], - }, - ]); - vi.mocked(updateUsersList).mockResolvedValueOnce(undefined); - - await handler(mockReq, mockRes); - - expect(mockRes.status).toHaveBeenCalledWith(200); - expect(mockRes.json).toHaveBeenCalledWith({ message: 'Successful API send' }); - expect(updateUsersList).toHaveBeenCalledWith([ - { username: 'testuser', email: 'newemail@example.com' }, - { username: 'otheruser', email: 'otheremail@example.com' }, - ]); - }); - - it('should return 500 if an unexpected error occurs', async () => { - vi.mocked(getServerSession).mockResolvedValueOnce({ user: { name: 'testuser' } }); - vi.mocked(getUsersList).mockRejectedValueOnce(new Error('Unexpected error')); - - await handler(mockReq, mockRes); - - expect(mockRes.status).toHaveBeenCalledWith(500); - expect(mockRes.json).toHaveBeenCalledWith({ - status: 500, - message: 'API error, contact the administrator', + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, }); + + vi.mocked(getUsersList).mockResolvedValue([ + { id: 1, username: 'Lovelace', email: 'lovelace@example.com', password: '', roles: [] }, + { id: 2, username: 'Ada', email: 'new@example.com', password: '', roles: [] }, + ]); + + const { req, res } = createMocks({ + method: 'PUT', + body: { email: 'new@example.com' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(400); + expect(res._getJSONData()).toEqual({ message: 'Email already exists' }); }); - it('should return 500 with specific message if ENOENT error occurs', async () => { - vi.mocked(getServerSession).mockResolvedValueOnce({ user: { name: 'testuser' } }); - const enoentError = new Error('No such file or directory'); - (enoentError as any).code = 'ENOENT'; - vi.mocked(getUsersList).mockRejectedValueOnce(enoentError); + it('should update the email and return 200 on success', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); - await handler(mockReq, mockRes); + const users = [ + { id: 1, username: 'Lovelace', email: 'lovelace@example.com', password: '', roles: [] }, + ]; - expect(mockRes.status).toHaveBeenCalledWith(500); - expect(mockRes.json).toHaveBeenCalledWith({ + vi.mocked(getUsersList).mockResolvedValue(users); + vi.mocked(updateUsersList).mockResolvedValue(); + + const { req, res } = createMocks({ + method: 'PUT', + body: { email: 'new@example.com' }, + }); + + await handler(req, res); + + expect(updateUsersList).toHaveBeenCalledWith([{ ...users[0], email: 'new@example.com' }]); + expect(res._getStatusCode()).toBe(200); + expect(res._getJSONData()).toEqual({ message: 'Successful API send' }); + }); + + it('should return 500 if there is a file system error', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + vi.mocked(getUsersList).mockRejectedValue({ code: 'ENOENT' }); + + const { req, res } = createMocks({ + method: 'PUT', + body: { email: 'new@example.com' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ status: 500, message: 'No such file or directory', }); }); + + it('should return 500 on unknown error', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + vi.mocked(getUsersList).mockRejectedValue({ code: 'UNKNOWN_ERROR' }); + + const { req, res } = createMocks({ + method: 'PUT', + body: { email: 'new@example.com' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ + status: 500, + message: 'API error, contact the administrator', + }); + }); }); diff --git a/pages/api/account/updateEmailAlert.test.ts b/pages/api/account/updateEmailAlert.test.ts index e69de29..3493f7b 100644 --- a/pages/api/account/updateEmailAlert.test.ts +++ b/pages/api/account/updateEmailAlert.test.ts @@ -0,0 +1,149 @@ +import { createMocks } from 'node-mocks-http'; +import handler from '~/pages/api/account/updateEmailAlert'; +import { getServerSession } from 'next-auth/next'; +import { getUsersList, updateUsersList } from '~/services'; + +vi.mock('next-auth/next'); +vi.mock('~/services', () => ({ + getUsersList: vi.fn(), + updateUsersList: vi.fn(), +})); + +describe('PUT /api/account/updateEmailAlert', () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.spyOn(console, 'log').mockImplementation(() => {}); + }); + + it('should return 401 if not authenticated', async () => { + vi.mocked(getServerSession).mockResolvedValue(null); + + const { req, res } = createMocks({ method: 'PUT' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(401); + }); + + it('should return 405 if method is not PUT', async () => { + const { req, res } = createMocks({ method: 'POST' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(405); + }); + + it('should return 422 if emailAlert is not a boolean', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + const { req, res } = createMocks({ + method: 'PUT', + body: { emailAlert: 'yes' }, // incorrect type + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(422); + expect(res._getJSONData()).toEqual({ message: 'Unexpected data' }); + }); + + it('should return 400 if user is not found in the users list', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + vi.mocked(getUsersList).mockResolvedValue([ + { + id: 2, + username: 'Ada', + email: 'ada@example.com', + emailAlert: false, + password: '', + roles: [], + }, + ]); + + const { req, res } = createMocks({ + method: 'PUT', + body: { emailAlert: true }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(400); + expect(res._getJSONData()).toEqual({ + message: 'User is incorrect. Please, logout to update your session.', + }); + }); + + it('should update emailAlert and return 200 on success', async () => { + const user = { + id: 1, + username: 'Lovelace', + email: 'lovelace@example.com', + emailAlert: false, + password: '', + roles: [], + }; + + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + vi.mocked(getUsersList).mockResolvedValue([user]); + vi.mocked(updateUsersList).mockResolvedValue(); + + const { req, res } = createMocks({ + method: 'PUT', + body: { emailAlert: true }, + }); + + await handler(req, res); + + expect(updateUsersList).toHaveBeenCalledWith([{ ...user, emailAlert: true }]); + expect(res._getStatusCode()).toBe(200); + expect(res._getJSONData()).toEqual({ message: 'Successful API send' }); + }); + + it('should return 500 if there is a file system error (ENOENT)', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + vi.mocked(getUsersList).mockRejectedValue({ code: 'ENOENT' }); + + const { req, res } = createMocks({ + method: 'PUT', + body: { emailAlert: true }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ + status: 500, + message: 'No such file or directory', + }); + }); + + it('should return 500 on unknown error', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + vi.mocked(getUsersList).mockRejectedValue({ code: 'UNKNOWN' }); + + const { req, res } = createMocks({ + method: 'PUT', + body: { emailAlert: true }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ + status: 500, + message: 'API error, contact the administrator', + }); + }); +}); diff --git a/pages/api/account/updatePasssword.test.ts b/pages/api/account/updatePasssword.test.ts deleted file mode 100644 index e69de29..0000000 diff --git a/pages/api/account/updatePassword.test.ts b/pages/api/account/updatePassword.test.ts new file mode 100644 index 0000000..56c5435 --- /dev/null +++ b/pages/api/account/updatePassword.test.ts @@ -0,0 +1,173 @@ +import { createMocks } from 'node-mocks-http'; +import handler from '~/pages/api/account/updatePassword'; +import { getServerSession } from 'next-auth/next'; +import { getUsersList, updateUsersList } from '~/services'; +import { verifyPassword, hashPassword } from '~/helpers/functions'; + +vi.mock('next-auth/next'); +vi.mock('~/services', () => ({ + getUsersList: vi.fn(), + updateUsersList: vi.fn(), +})); +vi.mock('~/helpers/functions', () => ({ + verifyPassword: vi.fn(), + hashPassword: vi.fn(), +})); + +describe('PUT /api/account/updatePassword', () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.spyOn(console, 'log').mockImplementation(() => {}); + }); + + it('should return 401 if not authenticated', async () => { + vi.mocked(getServerSession).mockResolvedValue(null); + + const { req, res } = createMocks({ method: 'PUT' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(401); + }); + + it('should return 405 if method is not PUT', async () => { + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(405); + }); + + it('should return 422 if oldPassword or newPassword are missing or not strings', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + const { req, res } = createMocks({ + method: 'PUT', + body: { oldPassword: 1234, newPassword: true }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(422); + expect(res._getJSONData()).toEqual({ message: 'Unexpected data' }); + }); + + it('should return 400 if user is not found', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + vi.mocked(getUsersList).mockResolvedValue([ + { id: 1, username: 'Ada', password: 'hashedpass', roles: [], email: 'ada@example.com' }, + ]); + + const { req, res } = createMocks({ + method: 'PUT', + body: { oldPassword: 'test', newPassword: 'newpass' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(400); + expect(res._getJSONData()).toEqual({ + message: 'User is incorrect. Please, logout to update your session.', + }); + }); + + it('should return 400 if old password is incorrect', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + vi.mocked(getUsersList).mockResolvedValue([ + { id: 1, username: 'Lovelace', password: 'hashedpass', roles: [], email: 'love@example.com' }, + ]); + + vi.mocked(verifyPassword).mockResolvedValue(false); + + const { req, res } = createMocks({ + method: 'PUT', + body: { oldPassword: 'wrongpass', newPassword: 'newpass' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(400); + expect(res._getJSONData()).toEqual({ message: 'Old password is incorrect.' }); + }); + + it('should update password and return 200 on success', async () => { + const oldUser = { + id: 1, + username: 'Lovelace', + password: 'hashedpass', + roles: [], + email: 'love@example.com', + }; + + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + vi.mocked(getUsersList).mockResolvedValue([oldUser]); + + vi.mocked(verifyPassword).mockResolvedValue(true); + vi.mocked(hashPassword).mockResolvedValue('newHashedPassword'); + vi.mocked(updateUsersList).mockResolvedValue(); + + const { req, res } = createMocks({ + method: 'PUT', + body: { oldPassword: 'oldpass', newPassword: 'newpass' }, + }); + + await handler(req, res); + + expect(verifyPassword).toHaveBeenCalledWith('oldpass', 'hashedpass'); + expect(hashPassword).toHaveBeenCalledWith('newpass'); + expect(updateUsersList).toHaveBeenCalledWith([{ ...oldUser, password: 'newHashedPassword' }]); + expect(res._getStatusCode()).toBe(200); + expect(res._getJSONData()).toEqual({ message: 'Successful API send' }); + }); + + it('should return 500 if there is a file system error (ENOENT)', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + vi.mocked(getUsersList).mockRejectedValue({ code: 'ENOENT' }); + + const { req, res } = createMocks({ + method: 'PUT', + body: { oldPassword: 'test', newPassword: 'new' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ + status: 500, + message: 'No such file or directory', + }); + }); + + it('should return 500 on unknown error', async () => { + vi.mocked(getServerSession).mockResolvedValue({ + user: { name: 'Lovelace' }, + }); + + vi.mocked(getUsersList).mockRejectedValue({ code: 'SOMETHING_ELSE' }); + + const { req, res } = createMocks({ + method: 'PUT', + body: { oldPassword: 'test', newPassword: 'new' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ + status: 500, + message: 'API error, contact the administrator', + }); + }); +}); diff --git a/pages/api/account/updateUsername.test.ts b/pages/api/account/updateUsername.test.ts index e69de29..1731b7c 100644 --- a/pages/api/account/updateUsername.test.ts +++ b/pages/api/account/updateUsername.test.ts @@ -0,0 +1,172 @@ +import { createMocks } from 'node-mocks-http'; +import handler from '~/pages/api/account/updateUsername'; // adapte le chemin si besoin +import { getServerSession } from 'next-auth/next'; +import { getUsersList, updateUsersList } from '~/services'; + +vi.mock('next-auth/next'); +vi.mock('~/services', () => ({ + getUsersList: vi.fn(), + updateUsersList: vi.fn(), +})); + +describe('PUT /api/account/updateUsername', () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.resetModules(); + vi.resetAllMocks(); + vi.spyOn(console, 'log').mockImplementation(() => {}); + }); + + it('should return 401 if not authenticated', async () => { + vi.mocked(getServerSession).mockResolvedValue(null); + + const { req, res } = createMocks({ method: 'PUT' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(401); + }); + + it('should return 405 if method is not PUT', async () => { + const { req, res } = createMocks({ method: 'GET' }); + await handler(req, res); + + expect(res._getStatusCode()).toBe(405); + }); + + it('should return 422 if username is not a string', async () => { + vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'Lovelace' } }); + + const { req, res } = createMocks({ + method: 'PUT', + body: { username: 12345 }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(422); + expect(res._getJSONData()).toEqual({ message: 'Unexpected data' }); + }); + + it('should return 422 if username format is invalid', async () => { + vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'Lovelace' } }); + + const { req, res } = createMocks({ + method: 'PUT', + body: { username: 'Too$hort!' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(422); + expect(res._getJSONData()).toEqual({ + message: 'Only a-z characters are allowed (5 to 15 char.)', + }); + }); + + it('should return 400 if user is not found', async () => { + vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'Lovelace' } }); + + vi.mocked(getUsersList).mockResolvedValue([ + { username: 'Ada', email: 'ada@example.com', password: 'xxx', id: 1, roles: ['user'] }, + ]); + + const { req, res } = createMocks({ + method: 'PUT', + body: { username: 'newname' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(400); + expect(res._getJSONData()).toEqual({ + message: 'User is incorrect. Please, logout to update your session.', + }); + }); + + it('should return 400 if new username already exists', async () => { + vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'Lovelace' } }); + + vi.mocked(getUsersList).mockResolvedValue([ + { username: 'Lovelace', email: 'love@example.com', password: 'xxx', id: 1, roles: ['user'] }, + { + username: 'newname', + email: 'someone@example.com', + password: 'xxx', + id: 2, + roles: ['user'], + }, + ]); + + const { req, res } = createMocks({ + method: 'PUT', + body: { username: 'newname' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(400); + expect(res._getJSONData()).toEqual({ message: 'Username already exists' }); + }); + + it('should return 200 and update the username', async () => { + const originalUser = { + username: 'Lovelace', + email: 'love@example.com', + password: 'xxx', + id: 1, + roles: ['user'], + }; + + vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'Lovelace' } }); + + vi.mocked(getUsersList).mockResolvedValue([originalUser]); + vi.mocked(updateUsersList).mockResolvedValue(); + + const { req, res } = createMocks({ + method: 'PUT', + body: { username: 'newusername' }, + }); + + await handler(req, res); + + expect(updateUsersList).toHaveBeenCalledWith([{ ...originalUser, username: 'newusername' }]); + expect(res._getStatusCode()).toBe(200); + expect(res._getJSONData()).toEqual({ message: 'Successful API send' }); + }); + + it('should return 500 if file not found (ENOENT)', async () => { + vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'Lovelace' } }); + vi.mocked(getUsersList).mockRejectedValue({ code: 'ENOENT' }); + + const { req, res } = createMocks({ + method: 'PUT', + body: { username: 'newname' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ + status: 500, + message: 'No such file or directory', + }); + }); + + it('should return 500 on unknown error', async () => { + vi.mocked(getServerSession).mockResolvedValue({ user: { name: 'Lovelace' } }); + vi.mocked(getUsersList).mockRejectedValue({ code: 'SOMETHING_ELSE' }); + + const { req, res } = createMocks({ + method: 'PUT', + body: { username: 'newname' }, + }); + + await handler(req, res); + + expect(res._getStatusCode()).toBe(500); + expect(res._getJSONData()).toEqual({ + status: 500, + message: 'API error, contact the administrator', + }); + }); +});