mirror of https://github.com/OpenVidu/openvidu.git
356 lines
13 KiB
TypeScript
356 lines
13 KiB
TypeScript
import { Builder, WebDriver } from 'selenium-webdriver';
|
|
import { TestAppConfig } from './selenium.conf';
|
|
import { OpenViduComponentsPO } from './utils.po.test';
|
|
|
|
const url = TestAppConfig.appUrl;
|
|
|
|
describe('E2E: Screensharing features', () => {
|
|
let browser: WebDriver;
|
|
let utils: OpenViduComponentsPO;
|
|
|
|
async function createChromeBrowser(): Promise<WebDriver> {
|
|
return await new Builder()
|
|
.forBrowser(TestAppConfig.browserName)
|
|
.withCapabilities(TestAppConfig.browserCapabilities)
|
|
.setChromeOptions(TestAppConfig.browserOptions)
|
|
.usingServer(TestAppConfig.seleniumAddress)
|
|
.build();
|
|
}
|
|
|
|
beforeEach(async () => {
|
|
browser = await createChromeBrowser();
|
|
utils = new OpenViduComponentsPO(browser);
|
|
});
|
|
|
|
afterEach(async () => {
|
|
try {
|
|
await utils.leaveRoom();
|
|
} catch (error) {}
|
|
await browser.quit();
|
|
});
|
|
|
|
it('should toggle screensharing on and off twice, updating video count', async () => {
|
|
await browser.get(`${url}&prejoin=false`);
|
|
await utils.checkLayoutPresent();
|
|
|
|
// Enable screensharing
|
|
await utils.waitForElement('#screenshare-btn');
|
|
await utils.clickOn('#screenshare-btn');
|
|
await browser.sleep(500);
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfElements('video')).toEqual(2);
|
|
|
|
// Disable screensharing
|
|
await utils.disableScreenShare();
|
|
expect(await utils.getNumberOfElements('video')).toEqual(1);
|
|
|
|
// Enable again
|
|
await utils.clickOn('#screenshare-btn');
|
|
await browser.sleep(500);
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfElements('video')).toEqual(2);
|
|
|
|
// Disable again
|
|
await utils.disableScreenShare();
|
|
expect(await utils.getNumberOfElements('video')).toEqual(1);
|
|
});
|
|
|
|
it('should show screenshare and muted camera (camera off, screenshare on)', async () => {
|
|
await browser.get(`${url}&prejoin=false`);
|
|
await utils.checkLayoutPresent();
|
|
|
|
// Mute camera
|
|
await utils.waitForElement('#camera-btn');
|
|
await utils.clickOn('#camera-btn');
|
|
|
|
// Enable screensharing
|
|
const screenshareButton = await utils.waitForElement('#screenshare-btn');
|
|
expect(await screenshareButton.isDisplayed()).toBeTrue();
|
|
await screenshareButton.click();
|
|
await browser.sleep(500);
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfElements('video')).toEqual(2);
|
|
|
|
// Disable screensharing
|
|
await utils.disableScreenShare();
|
|
expect(await utils.getNumberOfElements('video')).toEqual(1);
|
|
});
|
|
|
|
it('should display screensharing with a single pinned video', async () => {
|
|
await browser.get(`${url}&prejoin=false`);
|
|
await utils.checkLayoutPresent();
|
|
|
|
// Enable screensharing
|
|
const screenshareButton = await utils.waitForElement('#screenshare-btn');
|
|
expect(await screenshareButton.isDisplayed()).toBeTrue();
|
|
await screenshareButton.click();
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfElements('.OV_big')).toEqual(1);
|
|
});
|
|
|
|
it('should replace pinned video when a second participant starts screensharing', async () => {
|
|
const roomName = 'screensharingE2E';
|
|
const fixedUrl = `${url}&roomName=${roomName}&prejoin=false`;
|
|
await browser.get(fixedUrl);
|
|
await utils.checkLayoutPresent();
|
|
|
|
// First participant screenshares
|
|
await utils.waitForElement('#screenshare-btn');
|
|
await utils.clickOn('#screenshare-btn');
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfElements('.OV_big')).toEqual(1);
|
|
|
|
// Second participant joins and screenshares
|
|
const newTabScript = `window.open("${fixedUrl}")`;
|
|
await browser.executeScript(newTabScript);
|
|
const tabs = await browser.getAllWindowHandles();
|
|
await browser.switchTo().window(tabs[1]);
|
|
await utils.checkLayoutPresent();
|
|
await utils.waitForElement('#screenshare-btn');
|
|
await utils.clickOn('#screenshare-btn');
|
|
await browser.sleep(500);
|
|
expect(await utils.getNumberOfElements('video')).toEqual(4);
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfElements('.OV_big')).toEqual(1);
|
|
|
|
// Switch back to first tab and check
|
|
await browser.switchTo().window(tabs[0]);
|
|
await browser.sleep(500);
|
|
expect(await utils.getNumberOfElements('video')).toEqual(4);
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfElements('.OV_big')).toEqual(1);
|
|
});
|
|
|
|
it('should unpin screensharing and restore previous pinned video when disabled', async () => {
|
|
const roomName = 'screensharingtwoE2E';
|
|
const fixedUrl = `${url}&roomName=${roomName}&prejoin=false`;
|
|
await browser.get(fixedUrl);
|
|
await utils.checkLayoutPresent();
|
|
|
|
// First participant screenshares
|
|
await utils.waitForElement('#screenshare-btn');
|
|
await utils.clickOn('#screenshare-btn');
|
|
await browser.sleep(500);
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfElements('.OV_big')).toEqual(1);
|
|
|
|
// Second participant joins and screenshares
|
|
const tabs = await utils.openTab(fixedUrl);
|
|
await browser.switchTo().window(tabs[1]);
|
|
await utils.checkLayoutPresent();
|
|
await utils.waitForElement('#screenshare-btn');
|
|
await utils.clickOn('#screenshare-btn');
|
|
await browser.sleep(500);
|
|
expect(await utils.getNumberOfElements('video')).toEqual(4);
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfElements('.OV_big')).toEqual(1);
|
|
|
|
// Disable screensharing for second participant
|
|
await utils.disableScreenShare();
|
|
expect(await utils.getNumberOfElements('video')).toEqual(3);
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfElements('.OV_big')).toEqual(1);
|
|
|
|
// Switch back to first tab and check
|
|
await browser.switchTo().window(tabs[0]);
|
|
await browser.sleep(500);
|
|
expect(await utils.getNumberOfElements('video')).toEqual(3);
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfElements('.OV_big')).toEqual(1);
|
|
});
|
|
|
|
it('should correctly share screen with microphone muted and maintain proper track state', async () => {
|
|
// Helper for inspecting stream tracks
|
|
const getMediaTracks = (className: string) => {
|
|
return `
|
|
const tracks = document.getElementsByClassName('${className}')[0].srcObject.getTracks();
|
|
return tracks.map(track => ({
|
|
kind: track.kind,
|
|
enabled: track.enabled,
|
|
id: track.id,
|
|
label: track.label
|
|
}));`;
|
|
};
|
|
|
|
// Setup: Navigate to room and skip prejoin
|
|
await browser.get(`${url}&prejoin=false`);
|
|
await utils.checkLayoutPresent();
|
|
|
|
// Step 1: First mute the microphone
|
|
const micButton = await utils.waitForElement('#mic-btn');
|
|
await micButton.click();
|
|
|
|
// Step 2: Start screen sharing
|
|
await utils.clickOn('#screenshare-btn');
|
|
|
|
// Step 3: Verify both streams are present
|
|
await utils.waitForElement('.screen-type');
|
|
expect(await utils.getNumberOfElements('video')).toEqual(2);
|
|
|
|
// Step 4: Verify screen share track properties
|
|
const screenTracks: any[] = await browser.executeScript(getMediaTracks('screen-type'));
|
|
expect(screenTracks.length).toEqual(1);
|
|
expect(screenTracks[0].kind).toEqual('video');
|
|
expect(screenTracks[0].enabled).toBeTrue();
|
|
|
|
// Step 5: Verify microphone status indicators for both streams
|
|
// await utils.waitForElement('#status-mic');
|
|
// const micStatusCount = await utils.getNumberOfElements('#status-mic');
|
|
// expect(micStatusCount).toEqual(2);
|
|
|
|
// Step 6: Stop screen sharing and verify stream count
|
|
await utils.clickOn('#screenshare-btn');
|
|
await browser.sleep(500);
|
|
await utils.clickOn('#disable-screen-button');
|
|
await browser.sleep(500);
|
|
expect(await utils.getNumberOfElements('video')).toEqual(1);
|
|
});
|
|
|
|
// ==================== PIN/UNPIN TESTS ====================
|
|
// These tests demonstrate bugs in the pin system:
|
|
// 1. Multiple screens can be auto-pinned simultaneously
|
|
// 2. Manual unpins can be overridden by auto-pin logic when participants join
|
|
|
|
it('should NOT have multiple screens pinned when both participants share screen', async () => {
|
|
const roomName = 'pinBugCase1';
|
|
const fixedUrl = `${url}&roomName=${roomName}&prejoin=false`;
|
|
|
|
// Participant A joins and shares screen
|
|
await browser.get(fixedUrl);
|
|
await utils.checkLayoutPresent();
|
|
await utils.waitForElement('#screenshare-btn');
|
|
await utils.clickOn('#screenshare-btn');
|
|
await browser.sleep(500);
|
|
|
|
// Verify A's screen is pinned
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfPinnedStreams()).toEqual(1);
|
|
const pinnedCountA1 = await utils.getNumberOfPinnedStreams();
|
|
console.log(`[Tab A] After A shares: ${pinnedCountA1} pinned stream(s)`);
|
|
|
|
// Participant B joins
|
|
const tabs = await utils.openTab(fixedUrl);
|
|
await browser.switchTo().window(tabs[1]);
|
|
await utils.checkLayoutPresent();
|
|
await browser.sleep(1000);
|
|
|
|
// B should see A's screen pinned
|
|
expect(await utils.getNumberOfElements('video')).toEqual(3); // 2 cameras + 1 screen
|
|
expect(await utils.getNumberOfPinnedStreams()).toEqual(1);
|
|
const pinnedCountB1 = await utils.getNumberOfPinnedStreams();
|
|
console.log(`[Tab B] After B joins: ${pinnedCountB1} pinned stream(s)`);
|
|
|
|
// B shares screen
|
|
await utils.waitForElement('#screenshare-btn');
|
|
await utils.clickOn('#screenshare-btn');
|
|
await browser.sleep(500);
|
|
|
|
// B should see only their own screen pinned (auto-pin + unpin previous)
|
|
expect(await utils.getNumberOfElements('video')).toEqual(4); // 2 cameras + 2 screens
|
|
await utils.waitForElement('.OV_big');
|
|
const pinnedCountB2 = await utils.getNumberOfPinnedStreams();
|
|
console.log(`[Tab B] After B shares: ${pinnedCountB2} pinned stream(s)`);
|
|
expect(pinnedCountB2).toEqual(1); // Should be 1, but implementation might show different
|
|
|
|
// Switch to Tab A and check
|
|
await browser.switchTo().window(tabs[0]);
|
|
await browser.sleep(1000);
|
|
expect(await utils.getNumberOfElements('video')).toEqual(4); // 2 cameras + 2 screens
|
|
|
|
// BUG: In A's view, BOTH screens are pinned
|
|
const pinnedCountA2 = await utils.getNumberOfPinnedStreams();
|
|
console.log(`[Tab A] After B shares: ${pinnedCountA2} pinned stream(s)`);
|
|
|
|
// EXPECTED: Only B's screen should be pinned (the most recent one)
|
|
// ACTUAL: Both A's and B's screens are pinned
|
|
expect(pinnedCountA2).toEqual(1, 'BUG DETECTED: Multiple screens are pinned. Expected only the most recent screen to be pinned.');
|
|
});
|
|
|
|
it('should NOT re-pin manually unpinned screen when new participant joins', async () => {
|
|
const roomName = 'pinBugCase2';
|
|
const fixedUrl = `${url}&roomName=${roomName}&prejoin=false`;
|
|
|
|
// Participant A joins and shares screen
|
|
await browser.get(fixedUrl);
|
|
await utils.checkLayoutPresent();
|
|
await utils.waitForElement('#screenshare-btn');
|
|
await utils.clickOn('#screenshare-btn');
|
|
await browser.sleep(500);
|
|
|
|
// Verify A's screen is auto-pinned
|
|
await utils.waitForElement('.OV_big');
|
|
expect(await utils.getNumberOfPinnedStreams()).toEqual(1);
|
|
|
|
// Participant B joins and shares screen
|
|
const tabs = await utils.openTab(fixedUrl);
|
|
await browser.switchTo().window(tabs[1]);
|
|
await utils.checkLayoutPresent();
|
|
await browser.sleep(1000);
|
|
await utils.waitForElement('#screenshare-btn');
|
|
await utils.clickOn('#screenshare-btn');
|
|
await browser.sleep(500);
|
|
|
|
// B should see their own screen pinned
|
|
expect(await utils.getNumberOfElements('video')).toEqual(4); // 2 cameras + 2 screens
|
|
await utils.waitForElement('.OV_big');
|
|
let pinnedCountB = await utils.getNumberOfPinnedStreams();
|
|
console.log(`[Tab B] After B shares: ${pinnedCountB} pinned stream(s)`);
|
|
|
|
// B manually unpins their own screen
|
|
const screenStreams = await utils.getScreenShareStreams();
|
|
if (screenStreams.length > 0) {
|
|
// Find B's own screen (it should be the pinned one)
|
|
await utils.toggleStreamPin('.OV_big');
|
|
await browser.sleep(500);
|
|
}
|
|
|
|
// Verify B's screen is now unpinned
|
|
pinnedCountB = await utils.getNumberOfPinnedStreams();
|
|
console.log(`[Tab B] After manually unpinning B's screen: ${pinnedCountB} pinned stream(s)`);
|
|
expect(pinnedCountB).toEqual(0, 'B should have no pinned streams after manual unpin');
|
|
|
|
// B manually pins A's screen
|
|
const screenElements = await utils.getScreenShareStreams();
|
|
if (screenElements.length >= 2) {
|
|
// Pin the first screen that is not already pinned (should be A's screen)
|
|
await utils.toggleStreamPin('.OV_stream.remote .screen-type');
|
|
await utils.toggleStreamPin('#pin-btn');
|
|
await browser.sleep(500);
|
|
}
|
|
|
|
// Verify A's screen is now pinned in B's view
|
|
pinnedCountB = await utils.getNumberOfPinnedStreams();
|
|
console.log(`[Tab B] After manually pinning A's screen: ${pinnedCountB} pinned stream(s)`);
|
|
expect(pinnedCountB).toEqual(1, "Only A's screen should be pinned");
|
|
|
|
// Participant C joins the room
|
|
const tab3 = await utils.openTab(fixedUrl);
|
|
await browser.switchTo().window(tab3[2]);
|
|
await utils.checkLayoutPresent();
|
|
await browser.sleep(1500);
|
|
|
|
// Switch back to B's tab
|
|
await browser.switchTo().window(tabs[1]);
|
|
await browser.sleep(1000);
|
|
|
|
// B's screen should still be unpinned, but might get re-pinned automatically
|
|
pinnedCountB = await utils.getNumberOfPinnedStreams();
|
|
console.log(`[Tab B] After C joins: ${pinnedCountB} pinned stream(s)`);
|
|
|
|
// EXPECTED: No screens should be pinned (B manually unpinned everything)
|
|
// ACTUAL: B's screen gets re-pinned automatically
|
|
expect(pinnedCountB).toEqual(1, 'BUG DETECTED: Only one screen should be pinned after C joins.');
|
|
|
|
// Switch back to A's tab to verify
|
|
await browser.switchTo().window(tabs[0]);
|
|
await browser.sleep(500);
|
|
|
|
const pinnedCountA2 = await utils.getNumberOfPinnedStreams();
|
|
console.log(`[Tab A] After C joins: ${pinnedCountA2} pinned stream(s)`);
|
|
|
|
// EXPECTED: Only A's screen should be pinned
|
|
// ACTUAL: A's screen remains pinned
|
|
expect(pinnedCountA2).toEqual(1, "BUG DETECTED: A's screen should remain pinned after C joins.");
|
|
});
|
|
});
|