openvidu-test-e2e: add new tests (speaker detection, simulcast, dynacast, adaptive stream)

pull/848/head
pabloFuente 2024-10-02 01:17:02 +02:00
parent 88baf99368
commit 4354561d5a
2 changed files with 464 additions and 137 deletions

View File

@ -87,13 +87,6 @@ public class BrowserUser {
this.driver.quit(); this.driver.quit();
} }
public boolean hasMediaStream(WebElement videoElement, String parentSelector) {
boolean hasMediaStream = (boolean) ((JavascriptExecutor) driver).executeScript(
"return (!!(document.querySelector('" + parentSelector + (parentSelector.isEmpty() ? "" : " ") + "#"
+ videoElement.getAttribute("id") + "').srcObject))");
return hasMediaStream;
}
public Map<String, Long> getAverageRgbFromVideo(WebElement videoElement) { public Map<String, Long> getAverageRgbFromVideo(WebElement videoElement) {
String script = "var callback = arguments[arguments.length - 1];" + "var video = document.getElementById('" String script = "var callback = arguments[arguments.length - 1];" + "var video = document.getElementById('"
+ videoElement.getAttribute("id") + "');" + "var canvas = document.createElement('canvas');" + videoElement.getAttribute("id") + "');" + "var canvas = document.createElement('canvas');"
@ -150,19 +143,6 @@ public class BrowserUser {
return (Map<String, Long>) averageRgb; return (Map<String, Long>) averageRgb;
} }
public String getDimensionOfViewport() {
String dimension = (String) ((JavascriptExecutor) driver)
.executeScript("return (JSON.stringify({width: window.innerWidth, height: window.innerHeight - 1}))");
return dimension;
}
public void stopVideoTracksOfVideoElement(WebElement videoElement, String parentSelector) {
String script = "return (document.querySelector('" + parentSelector + (parentSelector.isEmpty() ? "" : " ")
+ "#" + videoElement.getAttribute("id")
+ "').srcObject.getVideoTracks().forEach(track => track.stop()))";
((JavascriptExecutor) driver).executeScript(script);
}
public boolean assertAllElementsHaveTracks(String querySelector, boolean hasAudio, boolean hasVideo) { public boolean assertAllElementsHaveTracks(String querySelector, boolean hasAudio, boolean hasVideo) {
String calculateReturnValue = "returnValue && "; String calculateReturnValue = "returnValue && ";
if (hasAudio) { if (hasAudio) {
@ -182,12 +162,6 @@ public class BrowserUser {
return tracks; return tracks;
} }
public int getVideoTrackWidth(WebElement videoElement) {
String script = "return document.querySelector('#" + videoElement.getAttribute("id")
+ "').srcObject.getVideoTracks()[0].getSettings().width";
return Math.toIntExact((long) ((JavascriptExecutor) driver).executeScript(script));
}
public void changeElementSize(WebElement videoElement, Integer newWidthInPixels, Integer newHeightInPixels) { public void changeElementSize(WebElement videoElement, Integer newWidthInPixels, Integer newHeightInPixels) {
String script = "var htmlelement = document.querySelector('#" + videoElement.getAttribute("id") + "');"; String script = "var htmlelement = document.querySelector('#" + videoElement.getAttribute("id") + "');";
if (newWidthInPixels != null) { if (newWidthInPixels != null) {

View File

@ -20,6 +20,8 @@ package io.openvidu.test.e2e;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction; import java.util.function.BiFunction;
@ -40,11 +42,10 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import io.openvidu.test.browsers.BrowserUser;
/** /**
* E2E tests for openvidu-testapp. * E2E tests for openvidu-testapp.
* *
@ -501,75 +502,11 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
} }
@Test @Test
@DisplayName("Adaptive stream enabled") @DisplayName("Simulcast enabled")
void aptiveStreamEnabledTest() throws Exception { void simulcastEnabledTest() throws Exception {
OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
log.info("Adaptive stream enabled"); log.info("Simulcast enabled");
user.getDriver().findElement(By.id("one2one-btn")).click();
// Only video publisher
user.getDriver().findElement(By.id("room-options-btn-0")).click();
Thread.sleep(300);
user.getDriver().findElement(By.id("audio-capture-false")).click();
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(300);
// Only subscriber
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .publisher-checkbox")).click();
user.getDriver().findElements(By.className("connect-btn")).forEach(el -> el.sendKeys(Keys.ENTER));
user.getEventManager().waitUntilEventReaches("signalConnected", "RoomEvent", 2);
user.getEventManager().waitUntilEventReaches("connected", "RoomEvent", 2);
user.getEventManager().waitUntilEventReaches("connectionStateChanged", "RoomEvent", 4);
user.getEventManager().waitUntilEventReaches("localTrackPublished", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches("localTrackSubscribed", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches("trackSubscribed", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches("trackSubscriptionStatusChanged", "RoomEvent", 2);
final int numberOfVideos = user.getDriver().findElements(By.tagName("video")).size();
Assertions.assertEquals(2, numberOfVideos, "Wrong number of videos");
final int numberOfAudios = user.getDriver().findElements(By.tagName("audio")).size();
Assertions.assertEquals(0, numberOfAudios, "Wrong number of audios");
Assertions.assertTrue(user.getBrowserUser().assertAllElementsHaveTracks("video", false, true),
"HTMLVideoElements were expected to have only one audio track");
Thread.sleep(1500);
WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote"));
int oldTrackWidth = user.getBrowserUser().getVideoTrackWidth(subscriberVideo);
user.getBrowserUser().changeElementSize(subscriberVideo, 500, 300);
oldTrackWidth = this.waitForVideoTrackResolutionChange(user.getBrowserUser(), subscriberVideo, oldTrackWidth,
true);
user.getBrowserUser().changeElementSize(subscriberVideo, 80, 40);
oldTrackWidth = this.waitForVideoTrackResolutionChange(user.getBrowserUser(), subscriberVideo, oldTrackWidth,
false);
user.getBrowserUser().changeElementSize(subscriberVideo, 1000, 700);
oldTrackWidth = this.waitForVideoTrackResolutionChange(user.getBrowserUser(), subscriberVideo, oldTrackWidth,
true);
user.getBrowserUser().changeElementSize(subscriberVideo, 120, 80);
oldTrackWidth = this.waitForVideoTrackResolutionChange(user.getBrowserUser(), subscriberVideo, oldTrackWidth,
false);
gracefullyLeaveParticipants(user, 2);
}
@Test
@DisplayName("Adaptive stream disabled")
void aptiveStreamDisabledTest() throws Exception {
OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
log.info("Adaptive stream disabled");
user.getDriver().findElement(By.id("one2one-btn")).click(); user.getDriver().findElement(By.id("one2one-btn")).click();
@ -578,6 +515,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
Thread.sleep(300); Thread.sleep(300);
user.getDriver().findElement(By.id("audio-capture-false")).click(); user.getDriver().findElement(By.id("audio-capture-false")).click();
user.getDriver().findElement(By.id("room-adaptiveStream")).click(); user.getDriver().findElement(By.id("room-adaptiveStream")).click();
user.getDriver().findElement(By.id("room-dynacast")).click();
this.setPublisherCustomVideoProperties(user, 1920, 1080, "L1T3");
user.getDriver().findElement(By.id("close-dialog-btn")).click(); user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(300); Thread.sleep(300);
@ -586,6 +525,79 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
user.getDriver().findElement(By.id("room-options-btn-1")).click(); user.getDriver().findElement(By.id("room-options-btn-1")).click();
Thread.sleep(300); Thread.sleep(300);
user.getDriver().findElement(By.id("room-adaptiveStream")).click(); user.getDriver().findElement(By.id("room-adaptiveStream")).click();
user.getDriver().findElement(By.id("room-dynacast")).click();
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(300);
user.getDriver().findElements(By.className("connect-btn")).forEach(el -> el.sendKeys(Keys.ENTER));
user.getEventManager().waitUntilEventReaches("localTrackSubscribed", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches("trackSubscribed", "RoomEvent", 1);
user.getEventManager().clearAllCurrentEvents();
final int numberOfVideos = user.getDriver().findElements(By.tagName("video")).size();
Assertions.assertEquals(2, numberOfVideos, "Wrong number of videos");
final int numberOfAudios = user.getDriver().findElements(By.tagName("audio")).size();
Assertions.assertEquals(0, numberOfAudios, "Wrong number of audios");
Assertions.assertTrue(user.getBrowserUser().assertAllElementsHaveTracks("video", false, true),
"HTMLVideoElements were expected to have only one audio track");
WebElement publisherVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 video.local"));
Assertions.assertEquals(3, countNumberOfPublishedLayers(user, publisherVideo),
"Wrong number of published layers");
int f = Integer.parseInt(getPublisherVideoLayerAttribute(user, publisherVideo, "f", "frameWidth"));
int h = Integer.parseInt(getPublisherVideoLayerAttribute(user, publisherVideo, "h", "frameWidth"));
int q = Integer.parseInt(getPublisherVideoLayerAttribute(user, publisherVideo, "q", "frameWidth"));
WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote"));
// Video quality of subscriber should be by default f
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, f);
// Manually change video quality of subscriber to h
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 #max-video-quality")).click();
user.getDriver().findElement(By.cssSelector("mat-option.mode-MEDIUM")).click();
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, h);
// Manually change video quality of subscriber to q
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 #max-video-quality")).click();
user.getDriver().findElement(By.cssSelector("mat-option.mode-LOW")).click();
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, q);
}
@Test
@DisplayName("Simulcast disabled")
void simulcastDisabledTest() throws Exception {
}
@Test
@DisplayName("Adaptive stream disabled Dynacast disabled")
void adaptiveStreamDisabledDynacastDisabledTest() throws Exception {
OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
log.info("Adaptive stream disabled Dynacast disabled");
user.getDriver().findElement(By.id("one2one-btn")).click();
// Only video publisher
user.getDriver().findElement(By.id("room-options-btn-0")).click();
Thread.sleep(300);
user.getDriver().findElement(By.id("video-capture-true")).click();
user.getDriver().findElement(By.id("audio-capture-false")).click();
user.getDriver().findElement(By.id("room-adaptiveStream")).click();
user.getDriver().findElement(By.id("room-dynacast")).click();
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(300);
// Only subscriber
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .publisher-checkbox")).click();
user.getDriver().findElement(By.id("room-options-btn-1")).click();
Thread.sleep(300);
user.getDriver().findElement(By.id("room-adaptiveStream")).click();
user.getDriver().findElement(By.id("room-dynacast")).click();
user.getDriver().findElement(By.id("close-dialog-btn")).click(); user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(300); Thread.sleep(300);
@ -607,67 +619,408 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
Assertions.assertTrue(user.getBrowserUser().assertAllElementsHaveTracks("video", false, true), Assertions.assertTrue(user.getBrowserUser().assertAllElementsHaveTracks("video", false, true),
"HTMLVideoElements were expected to have only one audio track"); "HTMLVideoElements were expected to have only one audio track");
Thread.sleep(1500); Thread.sleep(3000);
WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote")); WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote"));
int oldTrackWidth = user.getBrowserUser().getVideoTrackWidth(subscriberVideo); int oldFrameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
user.getBrowserUser().changeElementSize(subscriberVideo, 1000, 700); user.getBrowserUser().changeElementSize(subscriberVideo, 1000, 700);
Thread.sleep(2000); Thread.sleep(2300);
int newTrackWidth = user.getBrowserUser().getVideoTrackWidth(subscriberVideo); int newFrameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
Assertions.assertEquals(oldTrackWidth, newTrackWidth, Assertions.assertEquals(oldFrameWidth, newFrameWidth,
"With adaptive stream disabled subscriber's track resolution should NOT change"); "With adaptive stream disabled subscriber's track resolution should NOT change");
oldTrackWidth = newTrackWidth; oldFrameWidth = newFrameWidth;
user.getBrowserUser().changeElementSize(subscriberVideo, 100, 30); user.getBrowserUser().changeElementSize(subscriberVideo, 100, 30);
Thread.sleep(2000); Thread.sleep(3000);
newTrackWidth = user.getBrowserUser().getVideoTrackWidth(subscriberVideo); newFrameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
Assertions.assertEquals(oldTrackWidth, newTrackWidth, Assertions.assertEquals(oldFrameWidth, newFrameWidth,
"With adaptive stream disabled subscriber's track resolution should NOT change");
oldFrameWidth = newFrameWidth;
oldFrameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
user.getBrowserUser().changeElementSize(subscriberVideo, 1000, 700);
Thread.sleep(3000);
newFrameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
Assertions.assertEquals(oldFrameWidth, newFrameWidth,
"With adaptive stream disabled subscriber's track resolution should NOT change"); "With adaptive stream disabled subscriber's track resolution should NOT change");
gracefullyLeaveParticipants(user, 2); gracefullyLeaveParticipants(user, 2);
} }
private int waitForVideoTrackResolutionChange(BrowserUser user, WebElement videoElement, int oldTrackWidth, @Test
boolean shouldBeHigher) { @DisplayName("Adaptive stream enabled Dynacast disabled")
final int maxWaitMillis = 6000; void adaptiveStreamEnabledDynacastDisabledTest() throws Exception {
final int intervalWait = 250;
final int MAX_ITERATIONS = maxWaitMillis / intervalWait; OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
int iteration = 0;
boolean changed = false; log.info("Adaptive stream enabled Dynacast disabled");
int newTrackWidth = -1;
while (!changed && iteration < MAX_ITERATIONS) { user.getDriver().findElement(By.id("one2one-btn")).click();
iteration++;
newTrackWidth = user.getVideoTrackWidth(videoElement); // Only video publisher
changed = oldTrackWidth != newTrackWidth; user.getDriver().findElement(By.id("room-options-btn-0")).click();
if (changed) { Thread.sleep(300);
break; user.getDriver().findElement(By.id("audio-capture-false")).click();
} else { user.getDriver().findElement(By.id("room-dynacast")).click();
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(300);
// Only subscriber
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .publisher-checkbox")).click();
user.getDriver().findElement(By.id("room-options-btn-1")).click();
Thread.sleep(300);
user.getDriver().findElement(By.id("room-dynacast")).click();
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(300);
user.getDriver().findElements(By.className("connect-btn")).forEach(el -> el.sendKeys(Keys.ENTER));
user.getEventManager().waitUntilEventReaches("signalConnected", "RoomEvent", 2);
user.getEventManager().waitUntilEventReaches("connected", "RoomEvent", 2);
user.getEventManager().waitUntilEventReaches("connectionStateChanged", "RoomEvent", 4);
user.getEventManager().waitUntilEventReaches("localTrackPublished", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches("localTrackSubscribed", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches("trackSubscribed", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches("trackSubscriptionStatusChanged", "RoomEvent", 2);
final int numberOfVideos = user.getDriver().findElements(By.tagName("video")).size();
Assertions.assertEquals(2, numberOfVideos, "Wrong number of videos");
final int numberOfAudios = user.getDriver().findElements(By.tagName("audio")).size();
Assertions.assertEquals(0, numberOfAudios, "Wrong number of audios");
// Some time to let subscriber's video stabilize its first resolution
Thread.sleep(2000);
Assertions.assertTrue(user.getBrowserUser().assertAllElementsHaveTracks("video", false, true),
"HTMLVideoElements were expected to have only one audio track");
WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote"));
int frameWidth;
frameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
user.getBrowserUser().changeElementSize(subscriberVideo, 500, 300);
this.waitUntilSubscriberFrameWidthChanges(user, subscriberVideo, frameWidth, true);
frameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
user.getBrowserUser().changeElementSize(subscriberVideo, 80, 40);
this.waitUntilSubscriberFrameWidthChanges(user, subscriberVideo, frameWidth, false);
frameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
user.getBrowserUser().changeElementSize(subscriberVideo, 1000, 700);
this.waitUntilSubscriberFrameWidthChanges(user, subscriberVideo, frameWidth, true);
frameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
user.getBrowserUser().changeElementSize(subscriberVideo, 120, 80);
this.waitUntilSubscriberFrameWidthChanges(user, subscriberVideo, frameWidth, false);
gracefullyLeaveParticipants(user, 2);
}
@Test
@DisplayName("Dynacast enabled adaptive stream disabled")
void dynacastEnabledAdaptiveStreamDisabledTest() throws Exception {
OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
log.info("Dynacast enabled adaptive stream disabled");
user.getDriver().findElement(By.id("add-user-btn")).click();
// Only video publisher
user.getDriver().findElement(By.id("room-options-btn-0")).click();
Thread.sleep(300);
user.getDriver().findElement(By.id("audio-capture-false")).click();
user.getDriver().findElement(By.id("room-adaptiveStream")).click();
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(300);
user.getDriver().findElement(By.className("connect-btn")).sendKeys(Keys.ENTER);
user.getEventManager().waitUntilEventReaches("signalConnected", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches("connected", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches("connectionStateChanged", "RoomEvent", 2);
user.getEventManager().waitUntilEventReaches("localTrackPublished", "RoomEvent", 1);
user.getEventManager().clearAllCurrentEvents();
WebElement publisherVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 video.local"));
// With no subscribers and dynacast enabled, all published layers should finally
// reach inactive state
this.waitUntilPublisherLayerActive(user, publisherVideo, "q", false);
this.waitUntilPublisherLayerActive(user, publisherVideo, "h", false);
// Add only subscriber
user.getDriver().findElement(By.id("add-user-btn")).click();
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .publisher-checkbox")).click();
user.getDriver().findElement(By.id("room-options-btn-1")).click();
Thread.sleep(300);
user.getDriver().findElement(By.id("room-adaptiveStream")).click();
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(300);
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .connect-btn")).sendKeys(Keys.ENTER);
user.getEventManager().waitUntilEventReaches(0, "localTrackSubscribed", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches(1, "trackSubscribed", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches(1, "trackSubscriptionStatusChanged", "RoomEvent", 2);
user.getEventManager().clearAllCurrentEvents();
// After subscription all layers should be active
this.waitUntilPublisherLayerActive(user, publisherVideo, "q", true);
this.waitUntilPublisherLayerActive(user, publisherVideo, "h", true);
// With adaptive stream disabled, it doesn't matter the subscription video is
// small. All layers will remain active
WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote"));
user.getBrowserUser().changeElementSize(subscriberVideo, 100, 30);
Thread.sleep(4000);
this.waitUntilPublisherLayerActive(user, publisherVideo, "q", true);
this.waitUntilPublisherLayerActive(user, publisherVideo, "h", true);
// After unsubscription, all layers will be paused in publisher
WebElement toggleSubscriptionBtn = user.getDriver()
.findElement(By.cssSelector("#openvidu-instance-1 .toggle-video-subscribed"));
toggleSubscriptionBtn.click();
user.getEventManager().waitUntilEventReaches(1, "trackSubscribed", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches(1, "trackSubscriptionStatusChanged", "RoomEvent", 1);
user.getEventManager().clearAllCurrentEvents();
this.waitUntilPublisherLayerActive(user, publisherVideo, "q", false);
this.waitUntilPublisherLayerActive(user, publisherVideo, "h", false);
// After re-subscription, all layers will be active in publisher
toggleSubscriptionBtn.click();
user.getEventManager().waitUntilEventReaches(1, "trackSubscribed", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches(1, "trackSubscriptionStatusChanged", "RoomEvent", 2);
user.getEventManager().clearAllCurrentEvents();
this.waitUntilPublisherLayerActive(user, publisherVideo, "q", true);
this.waitUntilPublisherLayerActive(user, publisherVideo, "h", true);
gracefullyLeaveParticipants(user, 2);
}
@Test
@DisplayName("Dynacast enabled adaptive stream enabled")
void dynacastEnabledAdaptiveStreamEnabledTest() throws Exception {
OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
log.info("Dynacast enabled adaptive stream enabled");
user.getDriver().findElement(By.id("add-user-btn")).click();
// Only video publisher with 1 spatial layer and 3 temporal layers (L1T3)
user.getDriver().findElement(By.id("room-options-btn-0")).click();
Thread.sleep(300);
user.getDriver().findElement(By.id("audio-capture-false")).click();
this.setPublisherCustomVideoProperties(user, 1920, 1080, "L1T3");
user.getDriver().findElement(By.id("close-dialog-btn")).click();
Thread.sleep(300);
user.getDriver().findElement(By.className("connect-btn")).sendKeys(Keys.ENTER);
user.getEventManager().waitUntilEventReaches("signalConnected", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches("connected", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches("connectionStateChanged", "RoomEvent", 2);
user.getEventManager().waitUntilEventReaches("localTrackPublished", "RoomEvent", 1);
user.getEventManager().clearAllCurrentEvents();
// Add only subscriber
user.getDriver().findElement(By.id("add-user-btn")).click();
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .publisher-checkbox")).click();
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .connect-btn")).sendKeys(Keys.ENTER);
user.getEventManager().waitUntilEventReaches(0, "localTrackSubscribed", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches(1, "trackSubscribed", "RoomEvent", 1);
user.getEventManager().waitUntilEventReaches(1, "trackSubscriptionStatusChanged", "RoomEvent", 2);
user.getEventManager().clearAllCurrentEvents();
// Half and full video layers should reach disabled status with a small video in
// the subscriber side
WebElement publisherVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 video.local"));
WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote"));
user.getBrowserUser().changeElementSize(subscriberVideo, 100, 30);
this.waitUntilPublisherLayerActive(user, publisherVideo, "q", true);
this.waitUntilPublisherLayerActive(user, publisherVideo, "h", false);
this.waitUntilPublisherLayerActive(user, publisherVideo, "f", false);
int publisherActiveFrameWidth = Integer
.parseInt(this.getPublisherVideoLayerAttribute(user, publisherVideo, "q", "frameWidth"));
int subscriberFrameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
Assertions.assertEquals(publisherActiveFrameWidth, subscriberFrameWidth,
"Wrong publisher and subscriber video frameWidth");
// All video layers should reach enabled status with a big video in the
// subscriber side
user.getBrowserUser().changeElementSize(subscriberVideo, 1000, 500);
this.waitUntilPublisherLayerActive(user, publisherVideo, "q", true);
this.waitUntilPublisherLayerActive(user, publisherVideo, "h", true);
this.waitUntilPublisherLayerActive(user, publisherVideo, "f", true);
publisherActiveFrameWidth = Integer
.parseInt(this.getPublisherVideoLayerAttribute(user, publisherVideo, "f", "frameWidth"));
subscriberFrameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
Assertions.assertEquals(publisherActiveFrameWidth, subscriberFrameWidth,
"Wrong publisher and subscriber video frameWidth");
// Half and quarter video layers should reach enabled status with a medium video
// in the subscriber side
user.getBrowserUser().changeElementSize(subscriberVideo, 500, 300);
this.waitUntilPublisherLayerActive(user, publisherVideo, "q", true);
this.waitUntilPublisherLayerActive(user, publisherVideo, "h", true);
this.waitUntilPublisherLayerActive(user, publisherVideo, "f", false);
publisherActiveFrameWidth = Integer
.parseInt(this.getPublisherVideoLayerAttribute(user, publisherVideo, "h", "frameWidth"));
subscriberFrameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
Assertions.assertEquals(publisherActiveFrameWidth, subscriberFrameWidth,
"Wrong publisher and subscriber video frameWidth");
gracefullyLeaveParticipants(user, 2);
}
private int countNumberOfPublishedLayers(OpenViduTestappUser user, WebElement publisherVideo) {
JsonArray json = this.getLayersAsJsonArray(user, publisherVideo);
return json.size();
}
private int getSubscriberVideoFrameWidth(OpenViduTestappUser user, WebElement subscriberVideo) {
JsonArray json = this.getLayersAsJsonArray(user, subscriberVideo);
return json.get(0).getAsJsonObject().get("frameWidth").getAsInt();
}
private String getPublisherVideoLayerAttribute(OpenViduTestappUser user, WebElement publisherVideo, String rid,
String attribute) {
JsonArray json = this.getLayersAsJsonArray(user, publisherVideo);
Optional<JsonElement> result = json.asList().stream().parallel()
.filter(jsonElement -> rid.equals(jsonElement.getAsJsonObject().get("rid").getAsString())).findAny();
return result.get().getAsJsonObject().get(attribute).toString();
}
private JsonArray getLayersAsJsonArray(OpenViduTestappUser user, WebElement video) {
this.openInfoDialog(user, video);
user.getDriver().findElement(By.cssSelector("#update-value-btn")).click();
WebElement textarea = user.getDriver().findElement(By.id("info-text-area"));
String value = textarea.getAttribute("value");
return JsonParser.parseString(value).getAsJsonArray();
}
private void waitUntilSubscriberFrameWidthIs(OpenViduTestappUser user, WebElement videoElement,
final int expectedFrameWidth) {
this.waitUntilAux(user, videoElement, () -> {
return this.getSubscriberVideoFrameWidth(user, videoElement) == expectedFrameWidth;
}, "Timeout waiting for video track to have a frameWidth of " + expectedFrameWidth);
}
private void waitUntilSubscriberFrameWidthChanges(OpenViduTestappUser user, WebElement videoElement,
final int oldFrameWidth, final boolean shouldBeHigher) {
this.waitUntilAux(user, videoElement, () -> {
return this.getSubscriberVideoFrameWidth(user, videoElement) != oldFrameWidth;
}, "Timeout waiting for video track to reach a " + (shouldBeHigher ? "higher" : "lower") + " resolution");
int newFrameWidth = this.getSubscriberVideoFrameWidth(user, videoElement);
if (shouldBeHigher) {
Assertions.assertTrue(newFrameWidth > oldFrameWidth,
"Video track should have now a higher resolution, but it is not. Old width: " + oldFrameWidth
+ ". New width: " + newFrameWidth);
} else {
Assertions.assertTrue(newFrameWidth < oldFrameWidth,
"Video track should have now a lower resolution, but it is not. Old width: " + oldFrameWidth
+ ". New width: " + newFrameWidth);
}
}
private void waitUntilPublisherLayerActive(OpenViduTestappUser user, WebElement publisherVideo, String rid,
final boolean active) {
this.waitUntilAux(user, publisherVideo, () -> {
boolean currentlyActive = Boolean
.parseBoolean(this.getPublisherVideoLayerAttribute(user, publisherVideo, rid, "active"));
return currentlyActive == active;
}, "Timeout waiting for video track layer to be " + (active ? "active" : "inactive"));
}
private void waitUntilAux(OpenViduTestappUser user, WebElement videoElement,
Callable<Boolean> breakFromLoopFunction, String errMsg) {
try {
final int maxWaitMillis = 6000;
final int intervalWait = 250;
final int MAX_ITERATIONS = maxWaitMillis / intervalWait;
int iteration = 0;
boolean breakFromLoop = false;
while (!breakFromLoop && iteration < MAX_ITERATIONS) {
iteration++;
try { try {
Thread.sleep(intervalWait); breakFromLoop = breakFromLoopFunction.call();
} catch (InterruptedException e) { } catch (Exception e1) {
e.printStackTrace(); e1.printStackTrace();
}
if (breakFromLoop) {
break;
} else {
try {
Thread.sleep(intervalWait);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
} }
} if (!breakFromLoop) {
if (!changed) { Assertions.fail(errMsg);
Assertions.fail("Timeout waiting for video track to reach a " + (shouldBeHigher ? "higher" : "lower") }
+ " resolution"); } finally {
} else { // Close dialog
if (shouldBeHigher) { user.getWaiter().until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#close-dialog-btn")));
Assertions.assertTrue(newTrackWidth > oldTrackWidth, user.getDriver().findElement(By.cssSelector("#close-dialog-btn")).click();
"Video track should have now a higher resolution, but it is not. Old width: " + oldTrackWidth try {
+ ". New width: " + newTrackWidth); Thread.sleep(500);
} else { } catch (InterruptedException e) {
Assertions.assertTrue(newTrackWidth < oldTrackWidth, e.printStackTrace();
"Video track should have now a lower resolution, but it is not. Old width: " + oldTrackWidth
+ ". New width: " + newTrackWidth);
} }
} }
return newTrackWidth; }
private void openInfoDialog(OpenViduTestappUser user, WebElement video) {
String videoId = video.getAttribute("id");
// Open the track info dialog if required
if (!user.getDriver().findElements(By.cssSelector("app-info-dialog")).isEmpty()) {
// Dialog already opened
if (!user.getDriver().findElement(By.cssSelector("#subtitle")).getText().equals(videoId)) {
// Wrong dialog
user.getDriver().findElement(By.cssSelector("#close-dialog-btn")).click();
user.getDriver().findElement(By.cssSelector("#" + videoId + " ~ .bottom-div .video-track-info"))
.click();
}
} else {
// Dialog is not opened
user.getDriver().findElement(By.cssSelector("#" + videoId + " ~ .bottom-div .video-track-info")).click();
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void setPublisherCustomVideoProperties(OpenViduTestappUser user, Integer width, Integer height,
String scalabilityMode) {
user.getDriver().findElement(By.id("video-capture-custom")).click();
if (width != null) {
WebElement trackWidth = user.getDriver().findElement(By.id("resolution-video-capture-options-width"));
trackWidth.clear();
trackWidth.sendKeys(width.toString());
}
if (height != null) {
WebElement trackHeight = user.getDriver().findElement(By.id("resolution-video-capture-options-height"));
trackHeight.clear();
trackHeight.sendKeys(height.toString());
}
if (scalabilityMode != null) {
user.getDriver().findElement(By.id("trackPublish-scalabilityMode")).click();
user.getDriver().findElement(By.className("mode-" + scalabilityMode)).click();
}
} }
} }