mirror of https://github.com/OpenVidu/openvidu.git
openvidu-testapp: keep remote media elements when participants or publications change (stable @for keys)
parent
146e09a7b0
commit
8594da8c49
|
|
@ -154,11 +154,6 @@ public class OpenViduTestAppE2eServerSdkTest extends AbstractOpenViduTestappE2eT
|
||||||
|
|
||||||
log.info("{} SDK {} {}-layer publisher to Chrome and Firefox subscribers", sdk, codec, layers);
|
log.info("{} SDK {} {}-layer publisher to Chrome and Firefox subscribers", sdk, codec, layers);
|
||||||
|
|
||||||
// Both browsers join the room as subscriber-only participants with
|
|
||||||
// adaptiveStream disabled (the received layer only changes through the
|
|
||||||
// testapp's max-video-quality selector), each with its own identity (a
|
|
||||||
// second join with the testapp's default identity would kick the first
|
|
||||||
// browser out of the room)
|
|
||||||
for (OpenViduTestappUser user : subscribers) {
|
for (OpenViduTestappUser user : subscribers) {
|
||||||
this.addSubscriber(user, false);
|
this.addSubscriber(user, false);
|
||||||
WebElement participantNameInput = user.getDriver().findElement(By.id("participant-name-input-0"));
|
WebElement participantNameInput = user.getDriver().findElement(By.id("participant-name-input-0"));
|
||||||
|
|
@ -167,6 +162,9 @@ public class OpenViduTestAppE2eServerSdkTest extends AbstractOpenViduTestappE2eT
|
||||||
user.getDriver().findElements(By.className("connect-btn")).forEach(el -> el.sendKeys(Keys.ENTER));
|
user.getDriver().findElements(By.className("connect-btn")).forEach(el -> el.sendKeys(Keys.ENTER));
|
||||||
user.getEventManager().waitUntilEventReaches("connected", "RoomEvent", 1);
|
user.getEventManager().waitUntilEventReaches("connected", "RoomEvent", 1);
|
||||||
}
|
}
|
||||||
|
for (OpenViduTestappUser user : subscribers) {
|
||||||
|
user.getEventManager().waitUntilEventReaches("active", "ParticipantEvent", 1);
|
||||||
|
}
|
||||||
|
|
||||||
this.startServerSdkPublisher(sdk, "TestRoom", codec, multiLayer);
|
this.startServerSdkPublisher(sdk, "TestRoom", codec, multiLayer);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.JavascriptExecutor;
|
import org.openqa.selenium.JavascriptExecutor;
|
||||||
import org.openqa.selenium.Keys;
|
import org.openqa.selenium.Keys;
|
||||||
|
import org.openqa.selenium.StaleElementReferenceException;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||||
|
|
@ -4740,4 +4741,73 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
||||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 1920);
|
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 1920);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Remote video element survives participant changes")
|
||||||
|
void remoteVideoElementSurvivesParticipantChangesTest() throws Exception {
|
||||||
|
// openvidu-testapp test: it must keep the DOM elements of the remote tracks
|
||||||
|
// already rendered when the remote participant list changes
|
||||||
|
OpenViduTestappUser publisher = setupBrowserAndConnectToOpenViduTestapp("chrome");
|
||||||
|
OpenViduTestappUser subscriber = setupBrowserAndConnectToOpenViduTestapp("chrome");
|
||||||
|
OpenViduTestappUser newcomer = setupBrowserAndConnectToOpenViduTestapp("chrome");
|
||||||
|
|
||||||
|
log.info("Remote video element survives participant changes");
|
||||||
|
|
||||||
|
this.addOnlyPublisherVideo(publisher, false, false, false);
|
||||||
|
this.joinRoomAs(publisher, "publisher");
|
||||||
|
publisher.getEventManager().waitUntilEventReaches("localTrackPublished", "RoomEvent", 1);
|
||||||
|
|
||||||
|
this.addSubscriber(subscriber, false);
|
||||||
|
this.joinRoomAs(subscriber, "subscriber");
|
||||||
|
subscriber.getEventManager().waitUntilEventReaches("trackSubscribed", "RoomEvent", 1);
|
||||||
|
subscriber.getWaiter().until(ExpectedConditions.numberOfElementsToBe(By.tagName("video"), 1));
|
||||||
|
WebElement remoteVideo = subscriber.getDriver()
|
||||||
|
.findElement(By.cssSelector("#openvidu-instance-0 video.remote"));
|
||||||
|
this.waitUntilSubscriberFramesPerSecondNotZero(subscriber, remoteVideo);
|
||||||
|
|
||||||
|
// A participant joins: the subscriber's remote participant list grows
|
||||||
|
this.addSubscriber(newcomer, false);
|
||||||
|
this.joinRoomAs(newcomer, "newcomer");
|
||||||
|
subscriber.getEventManager().waitUntilEventReaches("participantConnected", "RoomEvent", 1);
|
||||||
|
this.assertRemoteVideoElementKept(subscriber, remoteVideo, 1, "a participant joined");
|
||||||
|
|
||||||
|
// The publisher publishes a second video track: its publication list grows
|
||||||
|
publisher.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .add-video-btn")).click();
|
||||||
|
publisher.getEventManager().waitUntilEventReaches("localTrackPublished", "RoomEvent", 2);
|
||||||
|
subscriber.getEventManager().waitUntilEventReaches("trackSubscribed", "RoomEvent", 2);
|
||||||
|
subscriber.getWaiter().until(ExpectedConditions.numberOfElementsToBe(By.tagName("video"), 2));
|
||||||
|
this.assertRemoteVideoElementKept(subscriber, remoteVideo, 2, "the publisher published a second track");
|
||||||
|
|
||||||
|
// A participant leaves: the subscriber's remote participant list shrinks
|
||||||
|
gracefullyLeaveParticipants(newcomer, 1);
|
||||||
|
subscriber.getEventManager().waitUntilEventReaches("participantDisconnected", "RoomEvent", 1);
|
||||||
|
this.assertRemoteVideoElementKept(subscriber, remoteVideo, 2, "a participant left");
|
||||||
|
|
||||||
|
// And the kept element is still a playing video
|
||||||
|
this.waitUntilSubscriberFramesPerSecondNotZero(subscriber, remoteVideo);
|
||||||
|
|
||||||
|
gracefullyLeaveParticipants(subscriber, 1);
|
||||||
|
gracefullyLeaveParticipants(publisher, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void joinRoomAs(OpenViduTestappUser user, String identity) throws Exception {
|
||||||
|
WebElement participantNameInput = user.getDriver().findElement(By.id("participant-name-input-0"));
|
||||||
|
participantNameInput.clear();
|
||||||
|
participantNameInput.sendKeys(identity);
|
||||||
|
user.getDriver().findElements(By.className("connect-btn")).forEach(el -> el.sendKeys(Keys.ENTER));
|
||||||
|
user.getEventManager().waitUntilEventReaches("connected", "RoomEvent", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertRemoteVideoElementKept(OpenViduTestappUser user, WebElement remoteVideo, int expectedVideos,
|
||||||
|
String change) {
|
||||||
|
try {
|
||||||
|
Assertions.assertTrue(remoteVideo.isDisplayed(),
|
||||||
|
"The remote video element is no longer displayed after " + change);
|
||||||
|
} catch (StaleElementReferenceException e) {
|
||||||
|
Assertions.fail("The remote video element was re-created after " + change
|
||||||
|
+ ": the WebElement located before is stale", e);
|
||||||
|
}
|
||||||
|
Assertions.assertEquals(expectedVideos, user.getDriver().findElements(By.tagName("video")).size(),
|
||||||
|
"Wrong number of videos after " + change);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@
|
||||||
[index]="index" [participantEvents]="participantEvents" [trackEvents]="trackEvents"
|
[index]="index" [participantEvents]="participantEvents" [trackEvents]="trackEvents"
|
||||||
[earlyParticipantEvents]="earlyParticipantEvents" [earlyParticipantListeners]="earlyParticipantListeners"
|
[earlyParticipantEvents]="earlyParticipantEvents" [earlyParticipantListeners]="earlyParticipantListeners"
|
||||||
[earlyTrackEvents]="earlyTrackEvents" [earlyTrackListeners]="earlyTrackListeners"></app-participant>
|
[earlyTrackEvents]="earlyTrackEvents" [earlyTrackListeners]="earlyTrackListeners"></app-participant>
|
||||||
@for (participant of room.remoteParticipants | keyvalue; track participant) {
|
@for (participant of room.remoteParticipants | keyvalue; track participant.value.sid) {
|
||||||
<app-participant class="remote-participant"
|
<app-participant class="remote-participant"
|
||||||
[participant]="participant.value" [room]="room" [index]="index"
|
[participant]="participant.value" [room]="room" [index]="index"
|
||||||
[participantEvents]="participantEvents" [trackEvents]="trackEvents"
|
[participantEvents]="participantEvents" [trackEvents]="trackEvents"
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="audio-tracks-container">
|
<div class="audio-tracks-container">
|
||||||
@for (trackPublication of participant.audioTrackPublications| keyvalue; track trackPublication) {
|
@for (trackPublication of participant.audioTrackPublications | keyvalue; track trackPublication.key) {
|
||||||
<app-audio-track
|
<app-audio-track
|
||||||
[index]="index" [trackPublication]="trackPublication.value" [track]="trackPublication.value.audioTrack"
|
[index]="index" [trackPublication]="trackPublication.value" [track]="trackPublication.value.audioTrack"
|
||||||
[localParticipant]="localParticipant"
|
[localParticipant]="localParticipant"
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
(newTrackEvent)="onTrackEvent($event)"></app-audio-track>
|
(newTrackEvent)="onTrackEvent($event)"></app-audio-track>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@for (trackPublication of participant.videoTrackPublications | keyvalue; track trackPublication) {
|
@for (trackPublication of participant.videoTrackPublications | keyvalue; track trackPublication.key) {
|
||||||
<app-video-track
|
<app-video-track
|
||||||
[index]="index" [trackPublication]="trackPublication.value" [track]="trackPublication.value.videoTrack"
|
[index]="index" [trackPublication]="trackPublication.value" [track]="trackPublication.value.videoTrack"
|
||||||
[localParticipant]="localParticipant"
|
[localParticipant]="localParticipant"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue