diff --git a/meet-ce/backend/tests/helpers/request-helpers.ts b/meet-ce/backend/tests/helpers/request-helpers.ts index 27056893..5bbe2a03 100644 --- a/meet-ce/backend/tests/helpers/request-helpers.ts +++ b/meet-ce/backend/tests/helpers/request-helpers.ts @@ -180,6 +180,12 @@ export const restoreDefaultGlobalConfig = async () => { // AUTH HELPERS +export const loginReq = async (body: { userId: string; password: string }) => { + checkAppIsRunning(); + + return await request(app).post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/auth/login`).send(body); +}; + /** * Logs in a user and returns the access and refresh (if available) tokens in the format "Bearer " */ @@ -187,16 +193,8 @@ export const loginUser = async ( userId: string, password: string ): Promise<{ accessToken: string; refreshToken?: string }> => { - checkAppIsRunning(); - - const response = await request(app) - .post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/auth/login`) - .send({ - userId, - password - }) - .expect(200); - + const response = await loginReq({ userId, password }); + expect(response.status).toBe(200); expect(response.body).toHaveProperty('accessToken'); const accessToken = `Bearer ${response.body.accessToken}`; const refreshToken = response.body.refreshToken ? `Bearer ${response.body.refreshToken}` : undefined; @@ -211,6 +209,14 @@ export const loginRootAdmin = async (): Promise<{ accessToken: string; refreshTo return { accessToken, refreshToken: refreshToken! }; }; +export const refreshTokenReq = async (refreshToken: string) => { + checkAppIsRunning(); + + return await request(app) + .post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/auth/refresh`) + .set(INTERNAL_CONFIG.REFRESH_TOKEN_HEADER, refreshToken); +}; + // USER HELPERS export const createUser = async (options: MeetUserOptions) => { @@ -252,32 +258,38 @@ export const getMe = async (accessToken: string) => { .send(); }; -export const changePassword = async (currentPassword: string, newPassword: string, accessToken: string) => { +export const changePasswordReq = async ( + body: { currentPassword: string; newPassword: string }, + accessToken: string +) => { checkAppIsRunning(); return await request(app) .post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users/change-password`) .set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken) - .send({ currentPassword, newPassword }); + .send(body); }; /** - * Changes the password for the authenticated user after first login - * and returns the access and refresh tokens in the format "Bearer " + * Changes the password for the authenticated user and + * returns the access and refresh tokens in the format "Bearer " if provided. + * If the user does not require password change, no tokens are returned */ -export const changePasswordAfterFirstLogin = async ( +export const changePassword = async ( currentPassword: string, newPassword: string, - accessTokenTmp: string -): Promise<{ accessToken: string; refreshToken: string }> => { - const response = await changePassword(currentPassword, newPassword, accessTokenTmp); + accessToken: string +): Promise<{ accessToken?: string; refreshToken?: string }> => { + const response = await changePasswordReq({ currentPassword, newPassword }, accessToken); expect(response.status).toBe(200); - expect(response.body).toHaveProperty('accessToken'); - expect(response.body).toHaveProperty('refreshToken'); - const accessToken = `Bearer ${response.body.accessToken}`; - const refreshToken = `Bearer ${response.body.refreshToken}`; - return { accessToken, refreshToken }; + const newAccessToken = response.body.accessToken; + const newRefreshToken = response.body.refreshToken; + + return { + accessToken: newAccessToken ? `Bearer ${newAccessToken}` : undefined, + refreshToken: newRefreshToken ? `Bearer ${newRefreshToken}` : undefined + }; }; export const resetUserPassword = async (userId: string, newPassword: string) => { diff --git a/meet-ce/backend/tests/helpers/test-scenarios.ts b/meet-ce/backend/tests/helpers/test-scenarios.ts index cb225c9c..60ee5f94 100644 --- a/meet-ce/backend/tests/helpers/test-scenarios.ts +++ b/meet-ce/backend/tests/helpers/test-scenarios.ts @@ -17,7 +17,7 @@ import { RoomRepository } from '../../src/repositories/room.repository'; import { RoomData, RoomMemberData, RoomTestUsers, TestContext, TestUsers, UserData } from '../interfaces/scenarios'; import { expectValidStartRecordingResponse } from './assertion-helpers'; import { - changePasswordAfterFirstLogin, + changePassword, createRoom, createRoomMember, createUser, @@ -264,17 +264,13 @@ export const setupUser = async (userOptions: MeetUserOptions): Promise // Change password and get final access token const newPassword = userOptions.password + '_2'; - const { accessToken, refreshToken } = await changePasswordAfterFirstLogin( - userOptions.password, - newPassword, - accessTokenTmp - ); + const { accessToken, refreshToken } = await changePassword(userOptions.password, newPassword, accessTokenTmp); return { user, password: newPassword, - accessToken, - refreshToken + accessToken: accessToken!, + refreshToken: refreshToken! }; }; diff --git a/meet-ce/backend/tests/integration/api/auth/login.test.ts b/meet-ce/backend/tests/integration/api/auth/login.test.ts index 6dbceed0..0e306a72 100644 --- a/meet-ce/backend/tests/integration/api/auth/login.test.ts +++ b/meet-ce/backend/tests/integration/api/auth/login.test.ts @@ -1,22 +1,16 @@ import { afterAll, beforeAll, describe, expect, it } from '@jest/globals'; import { MeetUserRole } from '@openvidu-meet/typings'; -import { Express } from 'express'; -import request from 'supertest'; -import { INTERNAL_CONFIG } from '../../../../src/config/internal-config.js'; import { MEET_ENV } from '../../../../src/environment.js'; import { expectValidationError } from '../../../helpers/assertion-helpers.js'; -import { createUser, deleteAllUsers, startTestServer } from '../../../helpers/request-helpers.js'; +import { createUser, deleteAllUsers, loginReq, startTestServer } from '../../../helpers/request-helpers.js'; import { setupTestUsers } from '../../../helpers/test-scenarios.js'; import { TestUsers } from '../../../interfaces/scenarios.js'; -const AUTH_PATH = `${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/auth`; - describe('Authentication API Tests', () => { - let app: Express; let testUsers: TestUsers; beforeAll(async () => { - app = await startTestServer(); + await startTestServer(); testUsers = await setupTestUsers(); }); @@ -26,7 +20,7 @@ describe('Authentication API Tests', () => { describe('Login Tests', () => { it('should succeed with valid root admin credentials', async () => { - const response = await request(app).post(`${AUTH_PATH}/login`).send({ + const response = await loginReq({ userId: MEET_ENV.INITIAL_ADMIN_USER, password: MEET_ENV.INITIAL_ADMIN_PASSWORD }); @@ -41,7 +35,7 @@ describe('Authentication API Tests', () => { }); it('should succeed with valid ADMIN user credentials', async () => { - const response = await request(app).post(`${AUTH_PATH}/login`).send({ + const response = await loginReq({ userId: testUsers.admin.user.userId, password: testUsers.admin.password }); @@ -56,7 +50,7 @@ describe('Authentication API Tests', () => { }); it('should succeed with valid USER user credentials', async () => { - const response = await request(app).post(`${AUTH_PATH}/login`).send({ + const response = await loginReq({ userId: testUsers.user.user.userId, password: testUsers.user.password }); @@ -71,7 +65,7 @@ describe('Authentication API Tests', () => { }); it('should succeed with valid ROOM_MEMBER user credentials', async () => { - const response = await request(app).post(`${AUTH_PATH}/login`).send({ + const response = await loginReq({ userId: testUsers.roomMember.user.userId, password: testUsers.roomMember.password }); @@ -97,7 +91,7 @@ describe('Authentication API Tests', () => { }); // Attempt login - const response = await request(app).post(`${AUTH_PATH}/login`).send({ + const response = await loginReq({ userId, password }); @@ -112,7 +106,7 @@ describe('Authentication API Tests', () => { }); it('should fail with 404 when user ID does not exist', async () => { - const response = await request(app).post(`${AUTH_PATH}/login`).send({ + const response = await loginReq({ userId: 'nonexistent_user', password: testUsers.user.password }); @@ -122,7 +116,7 @@ describe('Authentication API Tests', () => { }); it('should fail with 404 when password is incorrect', async () => { - const response = await request(app).post(`${AUTH_PATH}/login`).send({ + const response = await loginReq({ userId: testUsers.user.user.userId, password: 'wrongpassword' }); @@ -134,32 +128,32 @@ describe('Authentication API Tests', () => { describe('Login Validation Tests', () => { it('should fail when userId is missing', async () => { - const response = await request(app).post(`${AUTH_PATH}/login`).send({ + const response = await loginReq({ password: 'adminpass' - }); + } as { userId: string; password: string }); expectValidationError(response, 'userId', 'Required'); }); it('should fail when password is missing', async () => { - const response = await request(app).post(`${AUTH_PATH}/login`).send({ + const response = await loginReq({ userId: 'admin' - }); + } as { userId: string; password: string }); expectValidationError(response, 'password', 'Required'); }); it('should fail when userId is too short', async () => { - const response = await request(app).post(`${AUTH_PATH}/login`).send({ + const response = await loginReq({ userId: 'admi', password: 'adminpass' - }); + } as { userId: string; password: string }); expectValidationError(response, 'userId', 'userId must be at least 5 characters long'); }); it('should fail when password is too short', async () => { - const response = await request(app).post(`${AUTH_PATH}/login`).send({ + const response = await loginReq({ userId: 'admin', password: 'pass' - }); + } as { userId: string; password: string }); expectValidationError(response, 'password', 'password must be at least 5 characters long'); }); }); diff --git a/meet-ce/backend/tests/integration/api/auth/refresh-token.test.ts b/meet-ce/backend/tests/integration/api/auth/refresh-token.test.ts index 87ab8262..0a4bf5f5 100644 --- a/meet-ce/backend/tests/integration/api/auth/refresh-token.test.ts +++ b/meet-ce/backend/tests/integration/api/auth/refresh-token.test.ts @@ -1,25 +1,19 @@ import { beforeAll, describe, expect, it } from '@jest/globals'; import { MeetUserRole } from '@openvidu-meet/typings'; -import { Express } from 'express'; -import request from 'supertest'; -import { INTERNAL_CONFIG } from '../../../../src/config/internal-config.js'; import { deleteAllRooms, deleteAllUsers, deleteUser, loginRootAdmin, + refreshTokenReq, resetUserPassword, startTestServer } from '../../../helpers/request-helpers.js'; import { setupSingleRoom, setupUser } from '../../../helpers/test-scenarios.js'; -const AUTH_PATH = `${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/auth`; - describe('Authentication API Tests', () => { - let app: Express; - beforeAll(async () => { - app = await startTestServer(); + await startTestServer(); }); afterAll(async () => { @@ -37,9 +31,7 @@ describe('Authentication API Tests', () => { }); it('should succeed when providing valid refresh token', async () => { - const response = await request(app) - .post(`${AUTH_PATH}/refresh`) - .set(INTERNAL_CONFIG.REFRESH_TOKEN_HEADER, refreshToken); + const response = await refreshTokenReq(refreshToken); expect(response.status).toBe(200); expect(response.body).toHaveProperty('message'); expect(response.body.message).toContain('successfully refreshed'); @@ -48,25 +40,21 @@ describe('Authentication API Tests', () => { }); it('should fail when refresh token is missing', async () => { - const response = await request(app).post(`${AUTH_PATH}/refresh`); + const response = await refreshTokenReq(''); expect(response.status).toBe(400); expect(response.body).toHaveProperty('message'); expect(response.body.message).toContain('No refresh token provided'); }); it('should fail when refresh token is invalid', async () => { - const response = await request(app) - .post(`${AUTH_PATH}/refresh`) - .set(INTERNAL_CONFIG.REFRESH_TOKEN_HEADER, 'Bearer invalidtoken'); + const response = await refreshTokenReq('Bearer invalidtoken'); expect(response.status).toBe(400); expect(response.body).toHaveProperty('message'); expect(response.body.message).toContain('Invalid refresh token'); }); it('should fail when using access token instead of refresh token', async () => { - const response = await request(app) - .post(`${AUTH_PATH}/refresh`) - .set(INTERNAL_CONFIG.REFRESH_TOKEN_HEADER, accessToken); + const response = await refreshTokenReq(accessToken); expect(response.status).toBe(400); expect(response.body).toHaveProperty('message'); expect(response.body.message).toContain('Invalid refresh token'); @@ -74,9 +62,7 @@ describe('Authentication API Tests', () => { it('should fail when using room member token instead of refresh token', async () => { const { moderatorToken } = await setupSingleRoom(); - const response = await request(app) - .post(`${AUTH_PATH}/refresh`) - .set(INTERNAL_CONFIG.REFRESH_TOKEN_HEADER, moderatorToken); + const response = await refreshTokenReq(moderatorToken); expect(response.status).toBe(400); expect(response.body).toHaveProperty('message'); expect(response.body.message).toContain('Invalid refresh token'); @@ -95,9 +81,7 @@ describe('Authentication API Tests', () => { await deleteUser(userData.user.userId); // Attempt to refresh token - const response = await request(app) - .post(`${AUTH_PATH}/refresh`) - .set(INTERNAL_CONFIG.REFRESH_TOKEN_HEADER, userData.refreshToken); + const response = await refreshTokenReq(userData.refreshToken); expect(response.status).toBe(403); expect(response.body).toHaveProperty('message'); expect(response.body.message).toContain('Invalid token subject'); @@ -116,9 +100,7 @@ describe('Authentication API Tests', () => { await resetUserPassword(userData.user.userId, 'NewPassword1!'); // Attempt to refresh token - const response = await request(app) - .post(`${AUTH_PATH}/refresh`) - .set(INTERNAL_CONFIG.REFRESH_TOKEN_HEADER, userData.refreshToken); + const response = await refreshTokenReq(userData.refreshToken); expect(response.status).toBe(403); expect(response.body).toHaveProperty('message'); expect(response.body.message).toContain('Password change required');