test: enhance E2E tests with room and webhook functionality, add specific test scripts

This commit is contained in:
Carlos Santos 2025-06-12 16:08:06 +02:00
parent eb9de7e9de
commit fac7ed2636
5 changed files with 218 additions and 44 deletions

View File

@ -6,8 +6,8 @@ on:
jobs:
e2e-test-core:
name: E2E Tests Core
e2e-room-functionality-test:
name: E2E Room Functionality Tests
runs-on: ov-actions-runner
steps:
- name: Setup Node.js
@ -28,7 +28,83 @@ 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-core
npm run test:e2e-core-room
env:
RUN_MODE: CI
PLAYWRIGHT_BROWSERS_PATH: /tmp/ms-playwright
- name: Upload failed test videos
if: always()
uses: actions/upload-artifact@v4
with:
name: test-videos
path: |
frontend/webcomponent/test-results/*/*.webm
retention-days: 2
- name: Clean up
if: always()
uses: OpenVidu/actions/cleanup@main
e2e-events-functionality-test:
name: E2E Events Functionality Tests
runs-on: ov-actions-runner
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.13'
- name: Setup OpenVidu Local Deployment
uses: OpenVidu/actions/start-openvidu-local-deployment@main
- name: Setup OpenVidu Meet
uses: OpenVidu/actions/start-openvidu-meet@main
env:
MEET_WEBHOOK_ENABLED: true
- name: Start OpenVidu Meet Testapp
uses: OpenVidu/actions/start-openvidu-meet-testapp@main
- name: Run tests
run: |
cd frontend/webcomponent
# Install Playwright browsers
mkdir -p /tmp/ms-playwright
PLAYWRIGHT_BROWSERS_PATH=/tmp/ms-playwright npx playwright install --with-deps chromium
npm run test:e2e-core-events
env:
RUN_MODE: CI
PLAYWRIGHT_BROWSERS_PATH: /tmp/ms-playwright
- name: Upload failed test videos
if: always()
uses: actions/upload-artifact@v4
with:
name: test-videos
path: |
frontend/webcomponent/test-results/*/*.webm
retention-days: 2
- name: Clean up
if: always()
uses: OpenVidu/actions/cleanup@main
e2e-webhooks-functionality-test:
name: E2E Webhooks Functionality Tests
runs-on: ov-actions-runner
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.13'
- name: Setup OpenVidu Local Deployment
uses: OpenVidu/actions/start-openvidu-local-deployment@main
- name: Setup OpenVidu Meet
uses: OpenVidu/actions/start-openvidu-meet@main
env:
MEET_WEBHOOK_ENABLED: true
- name: Start OpenVidu Meet Testapp
uses: OpenVidu/actions/start-openvidu-meet-testapp@main
- name: Run tests
run: |
cd frontend/webcomponent
# Install Playwright browsers
mkdir -p /tmp/ms-playwright
PLAYWRIGHT_BROWSERS_PATH=/tmp/ms-playwright npx playwright install --with-deps chromium
npm run test:e2e-core-webhooks
env:
RUN_MODE: CI
PLAYWRIGHT_BROWSERS_PATH: /tmp/ms-playwright
@ -79,6 +155,9 @@ jobs:
path: |
frontend/webcomponent/test-results/*/*.webm
retention-days: 2
- name: Clean up
if: always()
uses: OpenVidu/actions/cleanup@main
e2e-recording-access-test:
name: E2E Recording Access Tests

View File

@ -8,6 +8,9 @@
"test:unit": "jest --forceExit --testPathPattern \"tests/unit\" --ci",
"test:e2e": "playwright test",
"test:e2e-core": "playwright test tests/e2e/core/",
"test:e2e-core-room": "playwright test tests/e2e/core/room.test.ts",
"test:e2e-core-events": "playwright test tests/e2e/core/events.test.ts",
"test:e2e-core-webhooks": "playwright test tests/e2e/core/webhooks.test.ts",
"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'"

View File

@ -1,5 +1,10 @@
import { test, expect } from '@playwright/test';
import { waitForElementInIframe } from '../helpers/function-helpers';
import {
deleteAllRecordings,
deleteAllRooms,
joinRoomAs,
waitForElementInIframe
} from '../../helpers/function-helpers';
let subscribedToAppErrors = false;
@ -41,40 +46,34 @@ test.describe('Web Component E2E Tests', () => {
await context.storageState({ path: 'test_localstorage_state.json' });
});
test.describe('Component Rendering', () => {
test('should load the web component with proper iframe', async ({ page }) => {
await page.click('#join-as-moderator');
const component = page.locator('openvidu-meet');
await expect(component).toBeVisible();
test.afterAll(async ({ browser }) => {
const tempContext = await browser.newContext();
const tempPage = await tempContext.newPage();
await deleteAllRooms(tempPage);
await deleteAllRecordings(tempPage);
const hasIframe = await page.evaluate(() => {
const component = document.querySelector('openvidu-meet');
return !!component?.shadowRoot?.querySelector('iframe');
});
expect(hasIframe).toBeTruthy();
});
await tempContext.close();
await tempPage.close();
});
test.describe('Event Handling', () => {
test('should successfully join as moderator and receive JOIN event', async ({ page }) => {
await page.click('#join-as-moderator');
await waitForElementInIframe(page, 'ov-session');
await joinRoomAs('moderator', `P-${Math.random().toString(36).substring(2, 9)}`, page);
await page.waitForSelector('.event-JOIN');
const joinElements = await page.locator('.event-JOIN').all();
expect(joinElements.length).toBe(1);
});
test('should successfully join as publisher and receive JOIN event', async ({ page }) => {
await page.click('#join-as-publisher');
await waitForElementInIframe(page, 'ov-session');
await joinRoomAs('publisher', `P-${Math.random().toString(36).substring(2, 9)}`, page);
await page.waitForSelector('.event-JOIN');
const joinElements = await page.locator('.event-JOIN').all();
expect(joinElements.length).toBe(1);
});
test('should successfully join to room and receive LEFT event when using leave command', async ({ page }) => {
await page.click('#join-as-moderator');
await waitForElementInIframe(page, 'ov-session');
await joinRoomAs('moderator', `P-${Math.random().toString(36).substring(2, 9)}`, page);
await page.click('#leave-room-btn');
await page.waitForSelector('.event-LEFT');
const leftElements = await page.locator('.event-LEFT').all();
@ -84,8 +83,8 @@ test.describe('Web Component E2E Tests', () => {
test('should successfully join to room and receive LEFT event when using disconnect button', async ({
page
}) => {
await page.click('#join-as-moderator');
await waitForElementInIframe(page, 'ov-session');
await joinRoomAs('moderator', `P-${Math.random().toString(36).substring(2, 9)}`, page);
const button = await waitForElementInIframe(page, '#leave-btn');
await button.click();
await page.waitForSelector('.event-LEFT');
@ -96,8 +95,8 @@ test.describe('Web Component E2E Tests', () => {
test('should successfully join to room and receive MEETING_ENDED event when using end meeting command', async ({
page
}) => {
await page.click('#join-as-moderator');
await waitForElementInIframe(page, 'ov-session');
await joinRoomAs('moderator', `P-${Math.random().toString(36).substring(2, 9)}`, page);
await page.click('#end-meeting-btn');
await page.waitForSelector('.event-MEETING_ENDED');
const meetingEndedElements = await page.locator('.event-MEETING_ENDED').all();
@ -108,23 +107,4 @@ test.describe('Web Component E2E Tests', () => {
expect(leftEventElements.length).toBe(0);
});
});
test.describe('Webhook Handling', () => {
test('should successfully receive meetingStarted and meetingEnded webhooks', async ({ page }) => {
await page.click('#join-as-moderator');
await page.waitForTimeout(1000); // Wait for 1 second to ensure the meeting has started
await page.screenshot({ path: 'screenshot.png' });
await waitForElementInIframe(page, 'ov-session');
await page.waitForSelector('.webhook-meetingStarted');
const meetingStartedElements = await page.locator('.webhook-meetingStarted').all();
expect(meetingStartedElements.length).toBe(1);
// End the meeting
await page.click('#end-meeting-btn');
await page.waitForSelector('.webhook-meetingEnded');
const meetingEndedElements = await page.locator('.webhook-meetingEnded').all();
expect(meetingEndedElements.length).toBe(1);
});
});
});

View File

@ -19,6 +19,7 @@ import {
let subscribedToAppErrors = false;
// Test suite for room functionality in OpenVidu Meet
test.describe('Room Functionality Tests', () => {
const testAppUrl = 'http://localhost:5080';
const testRoomPrefix = 'testing-room';
@ -69,6 +70,24 @@ test.describe('Room Functionality Tests', () => {
await tempPage.close();
});
// ==========================================
// COMPONENT RENDERING TESTS
// ==========================================
test.describe('Component Rendering', () => {
test('should load the web component with proper iframe', async ({ page }) => {
await joinRoomAs('moderator', `P-${Math.random().toString(36).substring(2, 9)}`, page);
const component = page.locator('openvidu-meet');
await expect(component).toBeVisible();
const hasIframe = await page.evaluate(() => {
const component = document.querySelector('openvidu-meet');
return !!component?.shadowRoot?.querySelector('iframe');
});
expect(hasIframe).toBeTruthy();
});
});
// ==========================================
// BASIC FUNCTIONALITY TESTS
// ==========================================

View File

@ -0,0 +1,93 @@
import { test, expect } from '@playwright/test';
import { deleteAllRecordings, deleteAllRooms, joinRoomAs, startStopRecording } from '../../helpers/function-helpers';
let subscribedToAppErrors = false;
test.describe('Web Component E2E Tests', () => {
const testAppUrl = 'http://localhost:5080';
const testRoomPrefix = 'test-room';
test.beforeAll(async ({ browser }) => {
// Create a test room before all tests
const tempContext = await browser.newContext();
const tempPage = await tempContext.newPage();
await tempPage.goto(testAppUrl);
await tempPage.waitForSelector('.create-room');
await tempPage.fill('#room-id-prefix', testRoomPrefix);
await tempPage.click('.create-room-btn');
await tempPage.waitForSelector(`#${testRoomPrefix}`);
await tempPage.close();
await tempContext.close();
});
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;
}
await page.goto(testAppUrl);
await page.waitForSelector('.rooms-container');
await page.waitForSelector(`#${testRoomPrefix}`);
await page.click('.dropdown-button');
await page.waitForSelector('#join-as-moderator');
await page.waitForSelector('#join-as-publisher');
});
test.afterEach(async ({ context }) => {
await context.storageState({ path: 'test_localstorage_state.json' });
});
test.afterAll(async ({ browser }) => {
const tempContext = await browser.newContext();
const tempPage = await tempContext.newPage();
await deleteAllRooms(tempPage);
await deleteAllRecordings(tempPage);
await tempContext.close();
await tempPage.close();
});
test.describe('Webhook Handling', () => {
test('should successfully receive meetingStarted and meetingEnded webhooks', async ({ page }) => {
await joinRoomAs('moderator', `P-${Math.random().toString(36).substring(2, 9)}`, page);
await page.waitForSelector('.webhook-meetingStarted');
const meetingStartedElements = await page.locator('.webhook-meetingStarted').all();
expect(meetingStartedElements.length).toBe(1);
// End the meeting
await page.click('#end-meeting-btn');
await page.waitForSelector('.webhook-meetingEnded');
const meetingEndedElements = await page.locator('.webhook-meetingEnded').all();
expect(meetingEndedElements.length).toBe(1);
});
test('should successfully receive recordingStarted, recordingUpdated and recordingEnded webhooks', async ({
page
}) => {
await joinRoomAs('moderator', `P-${Math.random().toString(36).substring(2, 9)}`, page);
// Start recording
await startStopRecording(page, 'start');
await page.waitForSelector('.webhook-recordingStarted');
const recordingStartedElements = await page.locator('.webhook-recordingStarted').all();
expect(recordingStartedElements.length).toBe(1);
// Update recording
await page.waitForTimeout(2000); // Wait for a bit before updating
await page.waitForSelector('.webhook-recordingUpdated');
const recordingUpdatedElements = await page.locator('.webhook-recordingUpdated').all();
expect(recordingUpdatedElements.length).toBe(1);
// End recording
await startStopRecording(page, 'stop');
await page.waitForSelector('.webhook-recordingEnded');
const recordingEndedElements = await page.locator('.webhook-recordingEnded').all();
expect(recordingEndedElements.length).toBe(1);
});
});
});