frontend: Refactor webhook event storage to use sessionStorage and enhance webhook handling in E2E tests
This commit is contained in:
parent
0368ab83e6
commit
a1acc9ba22
@ -1,9 +1,13 @@
|
||||
import { MeetRoomStatus } from '@openvidu-meet/typings';
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { MEET_TESTAPP_URL } from '../../config.js';
|
||||
import {
|
||||
createTestRoom,
|
||||
deleteAllRecordings,
|
||||
deleteAllRooms,
|
||||
getRecordingFromAPI,
|
||||
getRoomFromAPI,
|
||||
getRoomFromWebhookStorage,
|
||||
joinRoomAs,
|
||||
prepareForJoiningRoom,
|
||||
startStopRecording
|
||||
@ -56,11 +60,25 @@ test.describe('Web Component E2E Tests', () => {
|
||||
const meetingStartedElements = await page.locator('.webhook-meetingStarted').all();
|
||||
expect(meetingStartedElements.length).toBe(1);
|
||||
|
||||
// Get the actual room object from localStorage and compare deeply
|
||||
let [meetingStartedWebhook, actualRoom] = await Promise.all([
|
||||
getRoomFromWebhookStorage(page, roomId, 'meetingStarted'),
|
||||
getRoomFromAPI(roomId)
|
||||
]);
|
||||
|
||||
expect(meetingStartedWebhook.data).toMatchObject(actualRoom);
|
||||
|
||||
// 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);
|
||||
|
||||
// Verify meetingEnded webhook also matches room object
|
||||
const meetingEndedWebhook = await getRoomFromWebhookStorage(page, roomId, 'meetingEnded');
|
||||
// Update actualRoom status to OPEN for comparison
|
||||
actualRoom.status = MeetRoomStatus.OPEN;
|
||||
expect(meetingEndedWebhook.data).toMatchObject(actualRoom);
|
||||
});
|
||||
|
||||
test('should successfully receive recordingStarted, recordingUpdated and recordingEnded webhooks', async ({
|
||||
@ -74,17 +92,53 @@ test.describe('Web Component E2E Tests', () => {
|
||||
const recordingStartedElements = await page.locator('.webhook-recordingStarted').all();
|
||||
expect(recordingStartedElements.length).toBe(1);
|
||||
|
||||
// Verify recordingStarted webhook payload
|
||||
const recordingStartedWebhook = await getRoomFromWebhookStorage(page, roomId, 'recordingStarted');
|
||||
expect(recordingStartedWebhook.event).toBe('recordingStarted');
|
||||
expect(recordingStartedWebhook.data).toBeDefined();
|
||||
expect(recordingStartedWebhook.data.recordingId).toBeDefined();
|
||||
|
||||
const recordingId = recordingStartedWebhook.data.recordingId;
|
||||
|
||||
// Get the actual recording object from API and compare
|
||||
const actualRecording = await getRecordingFromAPI(recordingId);
|
||||
expect(recordingStartedWebhook.data).toMatchObject({
|
||||
...actualRecording,
|
||||
startDate: expect.any(Number),
|
||||
status: expect.stringMatching(/active|starting/)
|
||||
});
|
||||
|
||||
// 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);
|
||||
|
||||
// Verify recordingUpdated webhook payload
|
||||
const recordingUpdatedWebhook = await getRoomFromWebhookStorage(page, roomId, 'recordingUpdated');
|
||||
expect(recordingUpdatedWebhook.event).toBe('recordingUpdated');
|
||||
expect(recordingUpdatedWebhook.data).toBeDefined();
|
||||
expect(recordingUpdatedWebhook.data.recordingId).toBe(recordingId);
|
||||
|
||||
// Get updated recording from API and compare
|
||||
const updatedRecording = await getRecordingFromAPI(recordingId);
|
||||
expect(recordingUpdatedWebhook.data).toMatchObject(updatedRecording);
|
||||
|
||||
// End recording
|
||||
await startStopRecording(page, 'stop');
|
||||
await page.waitForSelector('.webhook-recordingEnded');
|
||||
const recordingEndedElements = await page.locator('.webhook-recordingEnded').all();
|
||||
expect(recordingEndedElements.length).toBe(1);
|
||||
|
||||
// Verify recordingEnded webhook payload
|
||||
const recordingEndedWebhook = await getRoomFromWebhookStorage(page, roomId, 'recordingEnded');
|
||||
expect(recordingEndedWebhook.event).toBe('recordingEnded');
|
||||
expect(recordingEndedWebhook.data).toBeDefined();
|
||||
expect(recordingEndedWebhook.data.recordingId).toBe(recordingId);
|
||||
|
||||
// Get final recording state from API and compare
|
||||
const endedRecording = await getRecordingFromAPI(recordingId);
|
||||
expect(recordingEndedWebhook.data).toMatchObject(endedRecording);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -746,3 +746,94 @@ export const muteAudio = async (page: Page) => {
|
||||
export const sleep = (ms: number): Promise<void> => {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the webhook event object from webhook storage in sessionStorage.
|
||||
* This allows comparing the actual room state with webhook payload data.
|
||||
* @param page - Playwright page object
|
||||
* @param roomId - The room ID to retrieve
|
||||
* @param eventName - The webhook event name (e.g., 'meetingStarted')
|
||||
* @returns The complete webhook event object from sessionStorage (with event, data, creationDate)
|
||||
*/
|
||||
export async function getRoomFromWebhookStorage(page: Page, roomId: string, eventName: string): Promise<any> {
|
||||
// Wait a bit to ensure the webhook is saved to localStorage
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const webhookEvent = await page.evaluate(
|
||||
({ roomId, eventName }) => {
|
||||
const data = sessionStorage.getItem('webhookEventsByRoom');
|
||||
if (!data) {
|
||||
console.log('No webhookEventsByRoom in sessionStorage');
|
||||
return null;
|
||||
}
|
||||
|
||||
const map = JSON.parse(data);
|
||||
const events = map[roomId] || [];
|
||||
|
||||
console.log(`Looking for event '${eventName}' in room '${roomId}'`);
|
||||
console.log('Available events:', events.map((e: any) => e.event));
|
||||
|
||||
// Find the specific event and return the complete event object
|
||||
const event = events.find((e: any) => e.event === eventName);
|
||||
if (!event) {
|
||||
console.log(`Event '${eventName}' not found`);
|
||||
return null;
|
||||
}
|
||||
|
||||
return event; // Return the complete event { event, data, creationDate }
|
||||
},
|
||||
{ roomId, eventName }
|
||||
);
|
||||
|
||||
if (!webhookEvent) {
|
||||
throw new Error(`Webhook event '${eventName}' not found in sessionStorage for room '${roomId}'`);
|
||||
}
|
||||
|
||||
return webhookEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a recording details from the Meet API
|
||||
* @param recordingId - The recording ID to retrieve
|
||||
* @returns The complete recording object from the API
|
||||
*/
|
||||
export async function getRecordingFromAPI(recordingId: string): Promise<any> {
|
||||
const response = await fetch(`${MEET_API_URL}/api/v1/recordings/${recordingId}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': MEET_API_KEY
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorResponse = await response.json();
|
||||
console.error('Error getting recording:', errorResponse);
|
||||
throw new Error(`Failed to get recording: ${response.status}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the room details from the Meet API
|
||||
* @param roomId
|
||||
* @returns
|
||||
*/
|
||||
export async function getRoomFromAPI(roomId: string): Promise<any> {
|
||||
const response = await fetch(`${MEET_API_URL}/api/v1/rooms/${roomId}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': MEET_API_KEY
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorResponse = await response.json();
|
||||
console.error('Error getting room:', errorResponse);
|
||||
throw new Error(`Failed to get room: ${response.status}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ const escapeHtml = (unsafe) => {
|
||||
.replace(/'/g, ''');
|
||||
};
|
||||
const getWebhookEventsFromStorage = (roomId) => {
|
||||
const data = localStorage.getItem('webhookEventsByRoom');
|
||||
const data = sessionStorage.getItem('webhookEventsByRoom');
|
||||
if (!data) {
|
||||
return [];
|
||||
}
|
||||
@ -32,23 +32,13 @@ const getWebhookEventsFromStorage = (roomId) => {
|
||||
return map[roomId] || [];
|
||||
};
|
||||
const saveWebhookEventToStorage = (roomId, event) => {
|
||||
const data = localStorage.getItem('webhookEventsByRoom');
|
||||
const data = sessionStorage.getItem('webhookEventsByRoom');
|
||||
const map = data ? JSON.parse(data) : {};
|
||||
if (!map[roomId]) {
|
||||
map[roomId] = [];
|
||||
}
|
||||
map[roomId].push(event);
|
||||
localStorage.setItem('webhookEventsByRoom', JSON.stringify(map));
|
||||
};
|
||||
const clearWebhookEventsByRoom = (roomId) => {
|
||||
const data = localStorage.getItem('webhookEventsByRoom');
|
||||
if (!data)
|
||||
return;
|
||||
const map = JSON.parse(data);
|
||||
if (map[roomId]) {
|
||||
map[roomId] = [];
|
||||
localStorage.setItem('webhookEventsByRoom', JSON.stringify(map));
|
||||
}
|
||||
sessionStorage.setItem('webhookEventsByRoom', JSON.stringify(map));
|
||||
};
|
||||
const shouldShowWebhook = (event) => {
|
||||
return (showAllWebhooksCheckbox === null || showAllWebhooksCheckbox === void 0 ? void 0 : showAllWebhooksCheckbox.checked) || event.data.roomId === roomId;
|
||||
@ -65,10 +55,6 @@ const listenWebhookServerEvents = () => {
|
||||
return;
|
||||
}
|
||||
addWebhookEventElement(event);
|
||||
// Clean up the previous events
|
||||
const isMeetingEnded = event.event === 'meetingEnded';
|
||||
if (isMeetingEnded)
|
||||
clearWebhookEventsByRoom(webhookRoomId);
|
||||
});
|
||||
};
|
||||
const renderStoredWebhookEvents = (roomId) => {
|
||||
|
||||
@ -31,7 +31,7 @@ const escapeHtml = (unsafe: string): string => {
|
||||
};
|
||||
|
||||
const getWebhookEventsFromStorage = (roomId: string): any[] => {
|
||||
const data = localStorage.getItem('webhookEventsByRoom');
|
||||
const data = sessionStorage.getItem('webhookEventsByRoom');
|
||||
if (!data) {
|
||||
return [];
|
||||
}
|
||||
@ -41,26 +41,16 @@ const getWebhookEventsFromStorage = (roomId: string): any[] => {
|
||||
};
|
||||
|
||||
const saveWebhookEventToStorage = (roomId: string, event: any): void => {
|
||||
const data = localStorage.getItem('webhookEventsByRoom');
|
||||
const data = sessionStorage.getItem('webhookEventsByRoom');
|
||||
const map = data ? JSON.parse(data) : {};
|
||||
if (!map[roomId]) {
|
||||
map[roomId] = [];
|
||||
}
|
||||
|
||||
map[roomId].push(event);
|
||||
localStorage.setItem('webhookEventsByRoom', JSON.stringify(map));
|
||||
sessionStorage.setItem('webhookEventsByRoom', JSON.stringify(map));
|
||||
};
|
||||
|
||||
const clearWebhookEventsByRoom = (roomId: string): void => {
|
||||
const data = localStorage.getItem('webhookEventsByRoom');
|
||||
if (!data) return;
|
||||
|
||||
const map = JSON.parse(data);
|
||||
if (map[roomId]) {
|
||||
map[roomId] = [];
|
||||
localStorage.setItem('webhookEventsByRoom', JSON.stringify(map));
|
||||
}
|
||||
};
|
||||
|
||||
const shouldShowWebhook = (event: any): boolean => {
|
||||
return showAllWebhooksCheckbox?.checked || event.data.roomId === roomId;
|
||||
@ -81,10 +71,6 @@ const listenWebhookServerEvents = () => {
|
||||
}
|
||||
|
||||
addWebhookEventElement(event);
|
||||
|
||||
// Clean up the previous events
|
||||
const isMeetingEnded = event.event === 'meetingEnded';
|
||||
if (isMeetingEnded) clearWebhookEventsByRoom(webhookRoomId);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user