From 209b4023fcf85c4d10cda186ac021aab9d76ba2d Mon Sep 17 00:00:00 2001 From: Carlos Santos <4a.santos@gmail.com> Date: Thu, 12 Jun 2025 10:27:51 +0200 Subject: [PATCH] test: add recording access tests and update helper functions for room preferences --- .github/workflows/wc-e2e-test.yaml | 6 +- frontend/webcomponent/package.json | 1 + .../tests/e2e/recording-access.test.ts | 230 ++++++++++++++++++ .../tests/helpers/function-helpers.ts | 13 +- 4 files changed, 244 insertions(+), 6 deletions(-) create mode 100644 frontend/webcomponent/tests/e2e/recording-access.test.ts diff --git a/.github/workflows/wc-e2e-test.yaml b/.github/workflows/wc-e2e-test.yaml index e3632ce..6711c00 100644 --- a/.github/workflows/wc-e2e-test.yaml +++ b/.github/workflows/wc-e2e-test.yaml @@ -80,8 +80,8 @@ jobs: frontend/webcomponent/test-results/*/*.webm retention-days: 2 - webcomponent-e2e-test: - name: WebComponent E2E Tests + e2e-recording-access-test: + name: E2E Recording Access Tests runs-on: ov-actions-runner steps: - name: Setup Node.js @@ -103,7 +103,7 @@ jobs: # Install Playwright browsers mkdir -p /tmp/ms-playwright PLAYWRIGHT_BROWSERS_PATH=/tmp/ms-playwright npx playwright install --with-deps chromium - npm run test:e2e + npm run test:e2e-recording-access env: RUN_MODE: CI PLAYWRIGHT_BROWSERS_PATH: /tmp/ms-playwright diff --git a/frontend/webcomponent/package.json b/frontend/webcomponent/package.json index 67b1f1f..db1989e 100644 --- a/frontend/webcomponent/package.json +++ b/frontend/webcomponent/package.json @@ -9,6 +9,7 @@ "test:e2e": "playwright test", "test:e2e-core": "playwright test tests/e2e/core/", "test:e2e-ui-features": "playwright test tests/e2e/ui-feature-preferences.test.ts", + "test:e2e-recording-access": "playwright test tests/e2e/recording-access.test.ts", "lint": "eslint 'src/**/*.ts'" }, "keywords": [], diff --git a/frontend/webcomponent/tests/e2e/recording-access.test.ts b/frontend/webcomponent/tests/e2e/recording-access.test.ts new file mode 100644 index 0000000..c9a5ba8 --- /dev/null +++ b/frontend/webcomponent/tests/e2e/recording-access.test.ts @@ -0,0 +1,230 @@ +import { test, expect } from '@playwright/test'; +import { + closeMoreOptionsMenu, + createTestRoom, + deleteTestRoom, + interactWithElementInIframe, + joinRoomAs, + leaveRoom, + loginAsAdmin, + openMoreOptionsMenu, + prepareForJoiningRoom, + startStopRecording, + updateRoomPreferences, + viewRecordingsAs, + waitForElementInIframe +} from '../helpers/function-helpers'; +import { MeetRecordingAccess } from '../../../../typings/src/room-preferences'; + +let subscribedToAppErrors = false; +let recordingCreated = false; + +test.describe('Recording Access Tests', () => { + const testAppUrl = 'http://localhost:5080'; + const testRoomPrefix = 'recording-access-test'; + let participantName: string; + let roomId: string; + let adminCookie: string; + + test.beforeAll(async () => { + adminCookie = await loginAsAdmin(); + // Ensure the test room is created before running tests + roomId = await createTestRoom(testRoomPrefix, { + chatPreferences: { enabled: true }, + recordingPreferences: { + enabled: true, + allowAccessTo: MeetRecordingAccess.ADMIN + }, + virtualBackgroundPreferences: { enabled: true } + }); + }); + + test.beforeEach(async ({ page }) => { + if (!subscribedToAppErrors) { + page.on('console', (msg) => { + const type = msg.type(); + const tag = type === 'error' ? 'ERROR' : type === 'warning' ? 'WARNING' : 'LOG'; + console.log('[' + tag + ']', msg.text()); + }); + subscribedToAppErrors = true; + } + participantName = `P-${Math.random().toString(36).substring(2, 9)}`; + if (!recordingCreated) { + await prepareForJoiningRoom(page, testAppUrl, testRoomPrefix); + await joinRoomAs('moderator', participantName, page); + + await startStopRecording(page, 'start'); + + await page.waitForTimeout(2000); + + await startStopRecording(page, 'stop'); + recordingCreated = true; + } + }); + + test('should moderator not be able to access recording when access level is set to admin', async ({ page }) => { + await updateRoomPreferences( + roomId, + { + chatPreferences: { enabled: true }, + recordingPreferences: { + enabled: true, + allowAccessTo: MeetRecordingAccess.ADMIN + }, + virtualBackgroundPreferences: { enabled: true } + }, + adminCookie + ); + + await page.goto(testAppUrl); + await prepareForJoiningRoom(page, testAppUrl, testRoomPrefix); + await viewRecordingsAs('moderator', page); + + await waitForElementInIframe(page, 'ov-error', { state: 'visible' }); + }); + + test('should publisher not be able to access recording when access level is set to admin', async ({ page }) => { + await updateRoomPreferences( + roomId, + { + chatPreferences: { enabled: true }, + recordingPreferences: { + enabled: true, + allowAccessTo: MeetRecordingAccess.ADMIN + }, + virtualBackgroundPreferences: { enabled: true } + }, + adminCookie + ); + + await page.goto(testAppUrl); + await prepareForJoiningRoom(page, testAppUrl, testRoomPrefix); + await viewRecordingsAs('publisher', page); + + await waitForElementInIframe(page, 'ov-error', { state: 'visible' }); + }); + + test('should allow moderator to access recording when access level is set to moderator', async ({ page }) => { + await updateRoomPreferences( + roomId, + { + chatPreferences: { enabled: true }, + recordingPreferences: { + enabled: true, + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR + }, + virtualBackgroundPreferences: { enabled: true } + }, + adminCookie + ); + + await page.goto(testAppUrl); + await prepareForJoiningRoom(page, testAppUrl, testRoomPrefix); + await viewRecordingsAs('moderator', page); + + await waitForElementInIframe(page, 'ov-error', { state: 'hidden' }); + await waitForElementInIframe(page, 'app-room-recordings', { state: 'visible' }); + }); + test('should publisher not be able to access recording when access level is set to moderator', async ({ page }) => { + await updateRoomPreferences( + roomId, + { + chatPreferences: { enabled: true }, + recordingPreferences: { + enabled: true, + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR + }, + virtualBackgroundPreferences: { enabled: true } + }, + adminCookie + ); + + await page.goto(testAppUrl); + await prepareForJoiningRoom(page, testAppUrl, testRoomPrefix); + await viewRecordingsAs('publisher', page); + await waitForElementInIframe(page, 'ov-error', { state: 'visible' }); + }); + + test('should allow moderators to access recording when access level is set to publisher', async ({ page }) => { + await updateRoomPreferences( + roomId, + { + chatPreferences: { enabled: true }, + recordingPreferences: { + enabled: true, + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR + }, + virtualBackgroundPreferences: { enabled: true } + }, + adminCookie + ); + + await page.goto(testAppUrl); + await prepareForJoiningRoom(page, testAppUrl, testRoomPrefix); + await viewRecordingsAs('moderator', page); + await waitForElementInIframe(page, 'ov-error', { state: 'hidden' }); + await waitForElementInIframe(page, 'app-room-recordings', { state: 'visible' }); + }); + + test('should allow publisher to access recording when access level is set to publisher', async ({ page }) => { + await updateRoomPreferences( + roomId, + { + chatPreferences: { enabled: true }, + recordingPreferences: { + enabled: true, + allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER + }, + virtualBackgroundPreferences: { enabled: true } + }, + adminCookie + ); + + await page.goto(testAppUrl); + await prepareForJoiningRoom(page, testAppUrl, testRoomPrefix); + await viewRecordingsAs('publisher', page); + await waitForElementInIframe(page, 'ov-error', { state: 'hidden' }); + await waitForElementInIframe(page, 'app-room-recordings', { state: 'visible' }); + }); + + test('should allow moderators to access recording when access level is set to public', async ({ page }) => { + await updateRoomPreferences( + roomId, + { + chatPreferences: { enabled: true }, + recordingPreferences: { + enabled: true, + allowAccessTo: MeetRecordingAccess.PUBLIC + }, + virtualBackgroundPreferences: { enabled: true } + }, + adminCookie + ); + + await page.goto(testAppUrl); + await prepareForJoiningRoom(page, testAppUrl, testRoomPrefix); + await viewRecordingsAs('moderator', page); + await waitForElementInIframe(page, 'ov-error', { state: 'hidden' }); + await waitForElementInIframe(page, 'app-room-recordings', { state: 'visible' }); + }); + test('should allow publisher to access recording when access level is set to public', async ({ page }) => { + await updateRoomPreferences( + roomId, + { + chatPreferences: { enabled: true }, + recordingPreferences: { + enabled: true, + allowAccessTo: MeetRecordingAccess.PUBLIC + }, + virtualBackgroundPreferences: { enabled: true } + }, + adminCookie + ); + + await page.goto(testAppUrl); + await prepareForJoiningRoom(page, testAppUrl, testRoomPrefix); + await viewRecordingsAs('publisher', page); + await waitForElementInIframe(page, 'ov-error', { state: 'hidden' }); + await waitForElementInIframe(page, 'app-room-recordings', { state: 'visible' }); + }); +}); diff --git a/frontend/webcomponent/tests/helpers/function-helpers.ts b/frontend/webcomponent/tests/helpers/function-helpers.ts index 3230c8c..4939dfb 100644 --- a/frontend/webcomponent/tests/helpers/function-helpers.ts +++ b/frontend/webcomponent/tests/helpers/function-helpers.ts @@ -126,8 +126,7 @@ export const createTestRoom = async ( }; // Helper function to update room preferences via REST API -export const updateRoomPreferences = async (roomId: string, preferences: any) => { - const adminCookie = await loginAsAdmin(); +export const updateRoomPreferences = async (roomId: string, preferences: any, adminCookie: string) => { const response = await fetch(`http://localhost:6080/meet/internal-api/v1/rooms/${roomId}`, { method: 'PUT', headers: { @@ -145,7 +144,7 @@ export const updateRoomPreferences = async (roomId: string, preferences: any) => }; // Helper function to login and get admin cookie -const loginAsAdmin = async () => { +export const loginAsAdmin = async (): Promise => { const response = await fetch(`http://localhost:6080/meet/internal-api/v1/auth/login`, { method: 'POST', headers: { @@ -230,6 +229,14 @@ export const joinRoomAs = async (role: 'moderator' | 'publisher', pName: string, await waitForElementInIframe(page, 'ov-session', { state: 'visible' }); }; +export const viewRecordingsAs = async (role: 'moderator' | 'publisher', page: Page) => { + await page.click('#join-as-' + role); + const component = page.locator('openvidu-meet'); + await expect(component).toBeVisible(); + + await interactWithElementInIframe(page, '#view-recordings-btn', { action: 'click' }); +}; + export const leaveRoom = async (page: Page) => { const button = await waitForElementInIframe(page, '#leave-btn'); await button.click();