From 09b3bbda62651e14f04503f81ddaaaa8a4fc7bb0 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 10 Nov 2021 11:20:13 +0100 Subject: [PATCH] openvidu-test-e2e: OpenViduTestappUser refactoring --- .../e2e/AbstractOpenViduTestAppE2eTest.java | 691 ------------------ .../test/e2e/OpenViduEventManager.java | 2 +- .../io/openvidu/test/e2e/OpenViduTestE2e.java | 640 ++++++++++++++++ .../e2e/AbstractOpenViduTestappE2eTest.java | 83 +++ .../test/e2e/OpenViduProTestAppE2eTest.java | 8 +- .../test/e2e/OpenViduTestAppE2eTest.java | 117 +-- .../test/e2e/OpenViduTestappUser.java} | 8 +- 7 files changed, 794 insertions(+), 755 deletions(-) create mode 100644 openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/OpenViduTestE2e.java create mode 100644 openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestappE2eTest.java rename openvidu-test-e2e/src/{main/java/io/openvidu/test/e2e/MyUser.java => test/java/io/openvidu/test/e2e/OpenViduTestappUser.java} (87%) diff --git a/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java index f07e34fd..e69de29b 100644 --- a/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java @@ -1,691 +0,0 @@ -package io.openvidu.test.e2e; - -import static org.openqa.selenium.OutputType.BASE64; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.time.Duration; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.apache.commons.io.FileUtils; -import org.apache.http.HttpStatus; -import org.junit.Assert; -import org.junit.ClassRule; -import org.junit.jupiter.api.AfterEach; -import org.openqa.selenium.By; -import org.openqa.selenium.Keys; -import org.openqa.selenium.TakesScreenshot; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.ui.ExpectedCondition; -import org.openqa.selenium.support.ui.ExpectedConditions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.wait.strategy.Wait; -import org.testcontainers.containers.wait.strategy.WaitStrategy; -import org.testcontainers.utility.DockerImageName; - -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.mashape.unirest.http.HttpMethod; - -import io.github.bonigarcia.wdm.WebDriverManager; -import io.openvidu.java.client.OpenVidu; -import io.openvidu.java.client.OpenViduHttpException; -import io.openvidu.java.client.OpenViduJavaClientException; -import io.openvidu.java.client.VideoCodec; -import io.openvidu.test.browsers.AndroidAppUser; -import io.openvidu.test.browsers.AndroidChromeUser; -import io.openvidu.test.browsers.AndroidFirefoxUser; -import io.openvidu.test.browsers.BrowserUser; -import io.openvidu.test.browsers.ChromeUser; -import io.openvidu.test.browsers.EdgeUser; -import io.openvidu.test.browsers.FirefoxUser; -import io.openvidu.test.browsers.OperaUser; -import io.openvidu.test.browsers.utils.BrowserNames; -import io.openvidu.test.browsers.utils.CommandLineExecutor; -import io.openvidu.test.browsers.utils.CustomHttpClient; -import io.openvidu.test.browsers.utils.RecordingUtils; - -public class AbstractOpenViduTestAppE2eTest { - - @ClassRule - public static GenericContainer chrome; - - @ClassRule - public static GenericContainer firefox; - - @ClassRule - public static GenericContainer opera; - - @ClassRule - public static GenericContainer edge; - - @ClassRule - public static GenericContainer android; - - private final static WaitStrategy waitBrowser = Wait.forHttp("/wd/hub/status").forStatusCode(200); - private final static WaitStrategy waitAndroid = Wait.forHealthcheck().withStartupTimeout(Duration.ofSeconds(600)); - - // Media server variables - final protected static String KURENTO_IMAGE = "kurento/kurento-media-server"; - final protected static String MEDIASOUP_IMAGE = "openvidu/mediasoup-controller"; - protected static String MEDIA_SERVER_IMAGE = KURENTO_IMAGE + ":6.16.0"; - - final protected String DEFAULT_JSON_SESSION = "{'id':'STR','object':'session','sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultRecordingProperties':{'hasVideo':true,'frameRate':25,'hasAudio':true,'shmSize':536870912,'name':'','outputMode':'COMPOSED','resolution':'1280x720','recordingLayout':'BEST_FIT'},'customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false,'forcedVideoCodec':'STR','allowTranscoding':false}"; - final protected String DEFAULT_JSON_PENDING_CONNECTION = "{'id':'STR','object':'connection','type':'WEBRTC','status':'pending','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':null,'location':null,'ip':null,'platform':null,'token':'STR','serverData':'STR','record':true,'role':'STR','kurentoOptions':null,'rtspUri':null,'adaptativeBitrate':null,'onlyPlayWithSubscribers':null,'networkCache':null,'clientData':null,'publishers':null,'subscribers':null}"; - final protected String DEFAULT_JSON_ACTIVE_CONNECTION = "{'id':'STR','object':'connection','type':'WEBRTC','status':'active','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','ip':'STR','platform':'STR','token':'STR','serverData':'STR','record':true,'role':'STR','kurentoOptions':null,'rtspUri':null,'adaptativeBitrate':null,'onlyPlayWithSubscribers':null,'networkCache':null,'clientData':'STR','publishers':[],'subscribers':[]}"; - final protected String DEFAULT_JSON_IPCAM_CONNECTION = "{'id':'STR','object':'connection','type':'IPCAM','status':'active','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','ip':'STR','platform':'IPCAM','token':null,'serverData':'STR','record':true,'role':null,'kurentoOptions':null,'rtspUri':'STR','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':2000,'clientData':null,'publishers':[],'subscribers':[]}"; - final protected String DEFAULT_JSON_TOKEN = "{'id':'STR','token':'STR','connectionId':'STR','createdAt':0,'session':'STR','role':'STR','data':'STR','kurentoOptions':{}}"; - - protected static String OPENVIDU_SECRET = "MY_SECRET"; - protected static String OPENVIDU_URL = "https://localhost:4443/"; - protected static String APP_URL = "http://localhost:4200/"; - protected static String EXTERNAL_CUSTOM_LAYOUT_URL = "http://localhost:4114"; - protected static String OPENVIDU_PRO_LICENSE = "not_valid"; - protected static String OPENVIDU_PRO_LICENSE_API = "not_valid"; - protected static String EXTERNAL_CUSTOM_LAYOUT_PARAMS = "sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET"; - - // https://hub.docker.com/r/selenium/standalone-chrome/tags - protected static String CHROME_VERSION = "latest"; - // https://hub.docker.com/r/selenium/standalone-firefox/tags - protected static String FIREFOX_VERSION = "latest"; - // https://hub.docker.com/r/selenium/standalone-opera/tags - protected static String OPERA_VERSION = "latest"; - // https://hub.docker.com/r/selenium/standalone-edge/tags - protected static String EDGE_VERSION = "latest"; - - protected static Exception ex = null; - protected final Object lock = new Object(); - - protected static final Logger log = LoggerFactory.getLogger(AbstractOpenViduTestAppE2eTest.class); - protected static final CommandLineExecutor commandLine = new CommandLineExecutor(); - protected static final String RECORDING_IMAGE = "openvidu/openvidu-recording"; - - protected Collection users = new HashSet<>(); - protected volatile static boolean isRecordingTest; - protected volatile static boolean isKurentoRestartTest; - - protected static VideoCodec defaultForcedVideoCodec; - protected static boolean defaultAllowTranscoding; - - protected static OpenVidu OV; - - protected RecordingUtils recordingUtils = new RecordingUtils(); - - protected static void checkFfmpegInstallation() { - String ffmpegOutput = commandLine.executeCommand("which ffmpeg"); - if (ffmpegOutput == null || ffmpegOutput.isEmpty()) { - log.error("ffmpeg package is not installed in the host machine"); - Assert.fail(); - return; - } else { - log.info("ffmpeg is installed and accesible"); - } - } - - @SuppressWarnings("resource") - protected static void prepareBrowsers(Set browsers) { - if (browsers.contains(BrowserNames.CHROME)) { - if (isRemote(BrowserNames.CHROME)) { - chrome = new GenericContainer<>(DockerImageName.parse("selenium/standalone-chrome:" + CHROME_VERSION)) - .withSharedMemorySize(2147483648L).withFileSystemBind("/opt/openvidu", "/opt/openvidu") - .withExposedPorts(4444).waitingFor(waitBrowser); - chrome.setPortBindings(Arrays.asList("6666:4444")); - } else { - WebDriverManager.chromedriver().setup(); - } - } - if (browsers.contains(BrowserNames.FIREFOX)) { - if (isRemote(BrowserNames.FIREFOX)) { - firefox = new GenericContainer<>( - DockerImageName.parse("selenium/standalone-firefox:" + FIREFOX_VERSION)) - .withSharedMemorySize(2147483648L).withFileSystemBind("/opt/openvidu", "/opt/openvidu") - .withExposedPorts(4444).waitingFor(waitBrowser); - firefox.setPortBindings(Arrays.asList("6667:4444")); - } else { - WebDriverManager.firefoxdriver().setup(); - } - } - if (browsers.contains(BrowserNames.OPERA)) { - if (isRemote(BrowserNames.OPERA)) { - opera = new GenericContainer<>(DockerImageName.parse("selenium/standalone-opera:" + OPERA_VERSION)) - .withSharedMemorySize(2147483648L).withFileSystemBind("/opt/openvidu", "/opt/openvidu") - .withExposedPorts(4444).waitingFor(waitBrowser); - opera.setPortBindings(Arrays.asList("6668:4444")); - } else { - WebDriverManager.operadriver().setup(); - } - } - if (browsers.contains(BrowserNames.EDGE)) { - if (isRemote(BrowserNames.EDGE)) { - edge = new GenericContainer<>(DockerImageName.parse("selenium/standalone-edge:" + EDGE_VERSION)) - .withSharedMemorySize(2147483648L).withFileSystemBind("/opt/openvidu", "/opt/openvidu") - .withExposedPorts(4444).waitingFor(waitBrowser); - edge.setPortBindings(Arrays.asList("6669:4444")); - } else { - WebDriverManager.edgedriver().setup(); - } - } - if (browsers.contains(BrowserNames.ANDROID)) { - android = new GenericContainer<>(DockerImageName.parse("budtmo/docker-android-x86-12.0:latest")) - .withPrivilegedMode(true) - .withEnv(Map.of("DEVICE", "Samsung Galaxy S10", "APPIUM", "true", "APPIUM_HOST", "172.17.0.1", - "APPIUM_PORT", "4723", "MOBILE_WEB_TEST", "true", "RELAXED_SECURITY", "true")) - .withSharedMemorySize(4294967296L).withExposedPorts(6080, 5554, 5555, 4723).waitingFor(waitAndroid) - .withFileSystemBind("/opt/openvidu-cache", "/opt/openvidu-cache"); - android.setPortBindings(Arrays.asList("6080:6080", "5554:5554", "5555:5555", "4723:4723")); - } - } - - protected static void cleanFoldersAndSetUpOpenViduJavaClient() { - try { - log.info("Cleaning folder /opt/openvidu/recordings"); - FileUtils.cleanDirectory(new File("/opt/openvidu/recordings")); - } catch (IOException e) { - log.error(e.getMessage()); - } - OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); - } - - protected static void loadEnvironmentVariables() { - String appUrl = System.getProperty("APP_URL"); - if (appUrl != null) { - APP_URL = appUrl; - } - log.info("Using URL {} to connect to openvidu-testapp", APP_URL); - - String externalCustomLayoutUrl = System.getProperty("EXTERNAL_CUSTOM_LAYOUT_URL"); - if (externalCustomLayoutUrl != null) { - EXTERNAL_CUSTOM_LAYOUT_URL = externalCustomLayoutUrl; - } - log.info("Using URL {} to connect to external custom layout", EXTERNAL_CUSTOM_LAYOUT_URL); - - String externalCustomLayoutParams = System.getProperty("EXTERNAL_CUSTOM_LAYOUT_PARAMS"); - if (externalCustomLayoutParams != null) { - // Parse external layout parameters and build a URL formatted params string - List params = Stream.of(externalCustomLayoutParams.split(",", -1)).collect(Collectors.toList()); - if (params.size() % 2 != 0) { - log.error( - "Wrong configuration property EXTERNAL_CUSTOM_LAYOUT_PARAMS. Must be a comma separated list with an even number of elements. e.g: EXTERNAL_CUSTOM_LAYOUT_PARAMS=param1,value1,param2,value2"); - Assert.fail(); - return; - } else { - EXTERNAL_CUSTOM_LAYOUT_PARAMS = ""; - for (int i = 0; i < params.size(); i++) { - if (i % 2 == 0) { - // Param name - EXTERNAL_CUSTOM_LAYOUT_PARAMS += params.get(i) + "="; - } else { - // Param value - EXTERNAL_CUSTOM_LAYOUT_PARAMS += params.get(i); - if (i < params.size() - 1) { - EXTERNAL_CUSTOM_LAYOUT_PARAMS += "&"; - } - } - } - } - } - log.info("Using URL {} to connect to external custom layout", EXTERNAL_CUSTOM_LAYOUT_PARAMS); - - String openviduUrl = System.getProperty("OPENVIDU_URL"); - if (openviduUrl != null) { - OPENVIDU_URL = openviduUrl; - } - log.info("Using URL {} to connect to openvidu-server", OPENVIDU_URL); - - String openvidusecret = System.getProperty("OPENVIDU_SECRET"); - if (openvidusecret != null) { - OPENVIDU_SECRET = openvidusecret; - } - log.info("Using secret {} to connect to openvidu-server", OPENVIDU_SECRET); - - String mediaServerImage = System.getProperty("MEDIA_SERVER_IMAGE"); - if (mediaServerImage != null) { - MEDIA_SERVER_IMAGE = mediaServerImage; - } - log.info("Using media server {} for e2e tests", MEDIA_SERVER_IMAGE); - - String chromeVersion = System.getProperty("CHROME_VERSION"); - if (chromeVersion != null && !chromeVersion.isBlank()) { - CHROME_VERSION = chromeVersion; - } - log.info("Using Chrome {}", CHROME_VERSION); - - String firefoxVersion = System.getProperty("FIREFOX_VERSION"); - if (firefoxVersion != null && !firefoxVersion.isBlank()) { - FIREFOX_VERSION = firefoxVersion; - } - log.info("Using Firefox {}", FIREFOX_VERSION); - - String operaVersion = System.getProperty("OPERA_VERSION"); - if (operaVersion != null && !operaVersion.isBlank()) { - OPERA_VERSION = operaVersion; - } - log.info("Using Opera {}", OPERA_VERSION); - - String edgeVersion = System.getProperty("EDGE_VERSION"); - if (edgeVersion != null && !edgeVersion.isBlank()) { - EDGE_VERSION = edgeVersion; - } - log.info("Using Edge {}", EDGE_VERSION); - - String openviduProLicense = System.getProperty("OPENVIDU_PRO_LICENSE"); - if (openviduProLicense != null) { - OPENVIDU_PRO_LICENSE = openviduProLicense; - } - - String openviduProLicenseApi = System.getProperty("OPENVIDU_PRO_LICENSE_API"); - if (openviduProLicenseApi != null) { - OPENVIDU_PRO_LICENSE_API = openviduProLicenseApi; - } - } - - protected MyUser setupBrowserAndConnectToOpenViduTestapp(String browser) { - MyUser user = this.setupBrowserAndConnectToOpenViduTestapp(browser); - this.connectToOpenViduTestApp(user); - return user; - } - - protected MyUser setupBrowser(String browser) { - - BrowserUser browserUser; - - switch (browser) { - case "chrome": - setupBrowserAux(BrowserNames.CHROME, chrome, false); - browserUser = new ChromeUser("TestUser", 50, false); - break; - case "firefox": - setupBrowserAux(BrowserNames.FIREFOX, firefox, false); - browserUser = new FirefoxUser("TestUser", 50, false); - break; - case "firefoxDisabledOpenH264": - setupBrowserAux(BrowserNames.FIREFOX, firefox, false); - browserUser = new FirefoxUser("TestUser", 50, true); - break; - case "opera": - setupBrowserAux(BrowserNames.OPERA, opera, false); - browserUser = new OperaUser("TestUser", 50); - break; - case "edge": - setupBrowserAux(BrowserNames.EDGE, edge, false); - browserUser = new EdgeUser("TestUser", 50); - break; - case "chromeAlternateScreenShare": - setupBrowserAux(BrowserNames.CHROME, chrome, false); - browserUser = new ChromeUser("TestUser", 50, "OpenVidu TestApp", false); - break; - case "chromeAsRoot": - setupBrowserAux(BrowserNames.CHROME, chrome, false); - browserUser = new ChromeUser("TestUser", 50, true); - break; - case "androidChrome": - setupBrowserAux(BrowserNames.ANDROID, android, false); - try { - // TODO: remove this try-catch when possible. Fixes - // https://github.com/budtmo/docker-android/issues/309 - android.execInContainer("bash", "-c", - "rm chromedriver && wget https://chromedriver.storage.googleapis.com/91.0.4472.101/chromedriver_linux64.zip && unzip chromedriver_linux64.zip && rm chromedriver_linux64.zip"); - } catch (UnsupportedOperationException | IOException | InterruptedException e) { - log.error("Error running command in Android container"); - } - browserUser = new AndroidChromeUser("TestUser", 50); - break; - case "androidFirefox": - setupBrowserAux(BrowserNames.ANDROID, android, false); - try { - // Download geckodriver and place in PATH at /usr/bin/ - android.execInContainer("bash", "-c", - "wget https://github.com/mozilla/geckodriver/releases/download/v0.30.0/geckodriver-v0.30.0-linux64.tar.gz && tar -xf geckodriver*.tar.gz && rm geckodriver*.tar.gz && mv geckodriver /usr/bin/."); - } catch (UnsupportedOperationException | IOException | InterruptedException e) { - log.error("Error running command in Android container"); - } - browserUser = new AndroidFirefoxUser("TestUser", 50); - break; - case "androidApp": - setupBrowserAux(BrowserNames.ANDROID, android, false); - try { - // TODO: remove this try-catch when possible. Fixes - // https://github.com/budtmo/docker-android/issues/309 - android.execInContainer("bash", "-c", - "rm chromedriver && wget https://chromedriver.storage.googleapis.com/91.0.4472.101/chromedriver_linux64.zip && unzip chromedriver_linux64.zip && rm chromedriver_linux64.zip"); - } catch (UnsupportedOperationException | IOException | InterruptedException e) { - log.error("Error running command in Android container"); - } - browserUser = new AndroidAppUser("TestUser", 50, "/opt/openvidu-cache/app-debug.apk"); - break; - default: - setupBrowserAux(BrowserNames.CHROME, chrome, false); - browserUser = new ChromeUser("TestUser", 50, false); - } - - MyUser user = new MyUser(browserUser); - - this.users.add(user); - return user; - } - - private void setupBrowserAux(BrowserNames browser, GenericContainer container, boolean forceRestart) { - if (isRemote(browser)) { - if (forceRestart && container.isRunning()) { - container.stop(); - } - if (!container.isRunning()) { - container.start(); - } - } - } - - private static boolean isRemote(BrowserNames browser) { - String remoteUrl = null; - switch (browser) { - case CHROME: - remoteUrl = System.getProperty("REMOTE_URL_CHROME"); - break; - case FIREFOX: - remoteUrl = System.getProperty("REMOTE_URL_FIREFOX"); - break; - case OPERA: - remoteUrl = System.getProperty("REMOTE_URL_OPERA"); - break; - case EDGE: - remoteUrl = System.getProperty("REMOTE_URL_EDGE"); - break; - case ANDROID: - return true; - } - return remoteUrl != null; - } - - private void connectToOpenViduTestApp(MyUser user) { - user.getDriver().get(APP_URL); - WebElement urlInput = user.getDriver().findElement(By.id("openvidu-url")); - urlInput.clear(); - urlInput.sendKeys(OPENVIDU_URL); - WebElement secretInput = user.getDriver().findElement(By.id("openvidu-secret")); - secretInput.clear(); - secretInput.sendKeys(OPENVIDU_SECRET); - user.getEventManager().startPolling(); - } - - protected MyUser setupChromeWithFakeVideo(String absolutePathToVideoFile) { - - if (isRemote(BrowserNames.CHROME)) { - setupBrowserAux(BrowserNames.CHROME, chrome, true); - } - - MyUser user = new MyUser(new ChromeUser("TestUser", 50, Paths.get(absolutePathToVideoFile))); - user.getDriver().get(APP_URL); - WebElement urlInput = user.getDriver().findElement(By.id("openvidu-url")); - urlInput.clear(); - urlInput.sendKeys(OPENVIDU_URL); - WebElement secretInput = user.getDriver().findElement(By.id("openvidu-secret")); - secretInput.clear(); - secretInput.sendKeys(OPENVIDU_SECRET); - user.getEventManager().startPolling(); - this.users.add(user); - return user; - } - - protected static void getDefaultTranscodingValues() throws Exception { - CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); - JsonObject ovConfig = restClient.rest(HttpMethod.GET, "/openvidu/api/config", HttpStatus.SC_OK); - defaultForcedVideoCodec = VideoCodec.valueOf(ovConfig.get("OPENVIDU_STREAMS_FORCED_VIDEO_CODEC").getAsString()); - defaultAllowTranscoding = ovConfig.get("OPENVIDU_STREAMS_ALLOW_TRANSCODING").getAsBoolean(); - } - - @AfterEach - protected void dispose() { - // Close all remaining OpenVidu sessions - this.closeAllSessions(OV); - // Remove all recordings - if (isRecordingTest) { - deleteAllRecordings(OV); - isRecordingTest = false; - } - // Reset Media Server - if (isKurentoRestartTest) { - this.stopMediaServer(false); - this.startMediaServer(true); - isKurentoRestartTest = false; - } - // Dispose all browsers - Iterator it = users.iterator(); - while (it.hasNext()) { - MyUser u = it.next(); - u.dispose(); - it.remove(); - } - // Stop and remove all browser containers if necessary - stopContainerIfPossible(chrome); - stopContainerIfPossible(firefox); - stopContainerIfPossible(opera); - stopContainerIfPossible(edge); - stopContainerIfPossible(android); - // Reset REST client - OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); - } - - private void stopContainerIfPossible(GenericContainer container) { - if (container != null && container.isRunning()) { - container.stop(); - } - } - - protected void closeAllSessions(OpenVidu client) { - try { - client.fetch(); - } catch (OpenViduJavaClientException | OpenViduHttpException e) { - log.error("Error fetching sessions: {}", e.getMessage()); - } - client.getActiveSessions().forEach(session -> { - try { - session.close(); - log.info("Session {} successfully closed", session.getSessionId()); - } catch (OpenViduJavaClientException | OpenViduHttpException e) { - log.error("Error closing session: {}", e.getMessage()); - } - }); - } - - protected void deleteAllRecordings(OpenVidu client) { - try { - client.listRecordings().forEach(recording -> { - try { - client.deleteRecording(recording.getId()); - log.info("Recording {} successfully deleted", recording.getId()); - } catch (OpenViduJavaClientException | OpenViduHttpException e) { - log.error("Error deleting recording: {}", e.getMessage()); - } - }); - } catch (OpenViduJavaClientException | OpenViduHttpException e) { - log.error("Error listing recordings: {}", e.getMessage()); - } - removeAllRecordingContiners(); - try { - FileUtils.cleanDirectory(new File("/opt/openvidu/recordings")); - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - protected void listEmptyRecordings(MyUser user) { - // List existing recordings (empty) - user.getDriver().findElement(By.id("list-recording-btn")).click(); - user.getWaiter() - .until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Recording list []")); - } - - protected ExpectedCondition waitForVideoDuration(WebElement element, int durationInSeconds) { - return new ExpectedCondition() { - @Override - public Boolean apply(WebDriver input) { - return element.getAttribute("duration").matches( - durationInSeconds - 1 + "\\.[5-9][0-9]{0,5}|" + durationInSeconds + "\\.[0-5][0-9]{0,5}"); - } - }; - } - - protected void gracefullyLeaveParticipants(MyUser user, int numberOfParticipants) throws Exception { - int accumulatedConnectionDestroyed = 0; - for (int j = 1; j <= numberOfParticipants; j++) { - user.getDriver().findElement(By.id("remove-user-btn")).sendKeys(Keys.ENTER); - user.getEventManager().waitUntilEventReaches("sessionDisconnected", j); - accumulatedConnectionDestroyed = (j != numberOfParticipants) - ? (accumulatedConnectionDestroyed + numberOfParticipants - j) - : (accumulatedConnectionDestroyed); - user.getEventManager().waitUntilEventReaches("connectionDestroyed", accumulatedConnectionDestroyed); - } - } - - protected String getBase64Screenshot(MyUser user) throws Exception { - String screenshotBase64 = ((TakesScreenshot) user.getDriver()).getScreenshotAs(BASE64); - return "data:image/png;base64," + screenshotBase64; - } - - protected void startMediaServer(boolean waitUntilKurentoClientReconnection) { - String command = null; - if (MEDIA_SERVER_IMAGE.startsWith(KURENTO_IMAGE)) { - log.info("Starting kurento"); - command = "docker run -e KMS_UID=$(id -u) --network=host --detach=true" - + " --volume=/opt/openvidu/recordings:/opt/openvidu/recordings " + MEDIA_SERVER_IMAGE; - } else if (MEDIA_SERVER_IMAGE.startsWith(MEDIASOUP_IMAGE)) { - log.info("Starting mediaSoup"); - command = "docker run --network=host --restart=always --detach=true --env=KMS_MIN_PORT=40000 --env=KMS_MAX_PORT=65535" - + " --env=OPENVIDU_PRO_LICENSE=" + OPENVIDU_PRO_LICENSE + " --env=OPENVIDU_PRO_LICENSE_API=" - + OPENVIDU_PRO_LICENSE_API - + " --env=WEBRTC_LISTENIPS_0_ANNOUNCEDIP=172.17.0.1 --env=WEBRTC_LISTENIPS_0_IP=172.17.0.1" - + " --volume=/opt/openvidu/recordings:/opt/openvidu/recordings " + MEDIA_SERVER_IMAGE; - } else { - log.error("Unrecognized MEDIA_SERVER_IMAGE: {}", MEDIA_SERVER_IMAGE); - System.exit(1); - } - commandLine.executeCommand(command); - if (waitUntilKurentoClientReconnection) { - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - protected void stopMediaServer(boolean waitUntilNodeCrashedEvent) { - final String dockerRemoveCmd = "docker ps -a | awk '{ print $1,$2 }' | grep GREP_PARAMETER | awk '{ print $1 }' | xargs -I {} docker rm -f {}"; - String grep = null; - if (MEDIA_SERVER_IMAGE.startsWith(KURENTO_IMAGE)) { - log.info("Stopping kurento"); - grep = KURENTO_IMAGE + ":"; - } else if (MEDIA_SERVER_IMAGE.startsWith(MEDIASOUP_IMAGE)) { - log.info("Stopping mediasoup"); - grep = MEDIASOUP_IMAGE + ":"; - } else { - log.error("Unrecognized MEDIA_SERVER_IMAGE: {}", MEDIA_SERVER_IMAGE); - System.exit(1); - } - commandLine.executeCommand(dockerRemoveCmd.replaceFirst("GREP_PARAMETER", grep)); - if (waitUntilNodeCrashedEvent) { - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - protected void checkDockerContainerRunning(String imageName, int amount) { - int number = Integer.parseInt(commandLine.executeCommand("docker ps | grep " + imageName + " | wc -l")); - Assert.assertEquals("Wrong number of Docker containers for image " + imageName + " running", amount, number); - } - - protected void removeAllRecordingContiners() { - commandLine.executeCommand("docker ps -a | awk '{ print $1,$2 }' | grep " + RECORDING_IMAGE - + " | awk '{print $1 }' | xargs -I {} docker rm -f {}"); - } - - protected String mergeJson(String json, String newProperties, String[] removeProperties) { - JsonObject jsonObj = JsonParser.parseString(json.replaceAll("'", "\"")).getAsJsonObject(); - JsonObject newJsonObj = JsonParser.parseString(newProperties.replaceAll("'", "\"")).getAsJsonObject(); - newJsonObj.entrySet().forEach(entry -> { - jsonObj.remove(entry.getKey()); - jsonObj.add(entry.getKey(), entry.getValue()); - }); - for (String prop : removeProperties) { - jsonObj.remove(prop); - } - return jsonObj.toString().replaceAll("\"", "'"); - } - - protected String getIndividualRecordingExtension() throws Exception { - if (MEDIA_SERVER_IMAGE.contains(KURENTO_IMAGE)) { - return "webm"; - } - if (MEDIA_SERVER_IMAGE.contains(MEDIASOUP_IMAGE)) { - return "mkv"; - } else { - throw new Exception("Unknown media server"); - } - } - - protected void waitUntilFileExistsAndIsBiggerThan(String absolutePath, int kbs, int maxSecondsWait) - throws Exception { - - long startTime = System.currentTimeMillis(); - - int interval = 100; - int maxLoops = (maxSecondsWait * 1000) / interval; - int loop = 0; - long bytes = 0; - - boolean bigger = false; - Path path = Paths.get(absolutePath); - - while (!bigger && loop < maxLoops) { - bigger = Files.exists(path) && Files.isReadable(path); - if (bigger) { - try { - bytes = Files.size(path); - } catch (IOException e) { - System.err.println("Error getting file size from " + path + ": " + e.getMessage()); - } - bigger = (bytes / 1024) > kbs; - } - loop++; - Thread.sleep(interval); - } - - if (!bigger && loop >= maxLoops) { - String errorMessage; - if (!Files.exists(path)) { - errorMessage = "File " + absolutePath + " does not exist and has not been created in " + maxSecondsWait - + " seconds"; - } else if (!Files.isReadable(path)) { - errorMessage = "File " + absolutePath - + " exists but is not readable, and read permissions have not been granted in " + maxSecondsWait - + " seconds"; - } else { - errorMessage = "File " + absolutePath + " did not reach a size of at least " + kbs + " KBs in " - + maxSecondsWait + " seconds. Last check was " + (bytes / 1024) + " KBs"; - } - throw new Exception(errorMessage); - } else { - log.info("File " + absolutePath + " did reach a size of at least " + kbs + " KBs in " - + (System.currentTimeMillis() - startTime) + " ms (last checked size was " + (bytes / 1024) - + " KBs)"); - } - } - -} diff --git a/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/OpenViduEventManager.java b/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/OpenViduEventManager.java index 0afc2b9f..d4fc6359 100644 --- a/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/OpenViduEventManager.java +++ b/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/OpenViduEventManager.java @@ -101,7 +101,7 @@ public class OpenViduEventManager { public void uncaughtException(Thread th, Throwable ex) { if (ex.getClass().getSimpleName().equals("UnhandledAlertException") && ex.getMessage().contains("unexpected alert open")) { - stopPolling(false, false); + stopPolling(true, false); System.err .println("Alert opened (" + ex.getMessage() + "). Waiting 1 second and restarting polling"); try { diff --git a/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/OpenViduTestE2e.java b/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/OpenViduTestE2e.java new file mode 100644 index 00000000..1991651e --- /dev/null +++ b/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/OpenViduTestE2e.java @@ -0,0 +1,640 @@ +package io.openvidu.test.e2e; + +import static org.openqa.selenium.OutputType.BASE64; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Duration; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.io.FileUtils; +import org.apache.http.HttpStatus; +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.jupiter.api.AfterEach; +import org.openqa.selenium.TakesScreenshot; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.utility.DockerImageName; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.mashape.unirest.http.HttpMethod; + +import io.github.bonigarcia.wdm.WebDriverManager; +import io.openvidu.java.client.OpenVidu; +import io.openvidu.java.client.OpenViduHttpException; +import io.openvidu.java.client.OpenViduJavaClientException; +import io.openvidu.java.client.VideoCodec; +import io.openvidu.test.browsers.AndroidAppUser; +import io.openvidu.test.browsers.AndroidChromeUser; +import io.openvidu.test.browsers.AndroidFirefoxUser; +import io.openvidu.test.browsers.BrowserUser; +import io.openvidu.test.browsers.ChromeUser; +import io.openvidu.test.browsers.EdgeUser; +import io.openvidu.test.browsers.FirefoxUser; +import io.openvidu.test.browsers.OperaUser; +import io.openvidu.test.browsers.utils.BrowserNames; +import io.openvidu.test.browsers.utils.CommandLineExecutor; +import io.openvidu.test.browsers.utils.CustomHttpClient; +import io.openvidu.test.browsers.utils.RecordingUtils; + +public class OpenViduTestE2e { + + @ClassRule + public static GenericContainer chrome; + + @ClassRule + public static GenericContainer firefox; + + @ClassRule + public static GenericContainer opera; + + @ClassRule + public static GenericContainer edge; + + @ClassRule + public static GenericContainer android; + + private final static WaitStrategy waitBrowser = Wait.forHttp("/wd/hub/status").forStatusCode(200); + private final static WaitStrategy waitAndroid = Wait.forHealthcheck().withStartupTimeout(Duration.ofSeconds(600)); + + // Media server variables + final protected static String KURENTO_IMAGE = "kurento/kurento-media-server"; + final protected static String MEDIASOUP_IMAGE = "openvidu/mediasoup-controller"; + protected static String MEDIA_SERVER_IMAGE = KURENTO_IMAGE + ":6.16.0"; + + final protected String DEFAULT_JSON_SESSION = "{'id':'STR','object':'session','sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultRecordingProperties':{'hasVideo':true,'frameRate':25,'hasAudio':true,'shmSize':536870912,'name':'','outputMode':'COMPOSED','resolution':'1280x720','recordingLayout':'BEST_FIT'},'customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false,'forcedVideoCodec':'STR','allowTranscoding':false}"; + final protected String DEFAULT_JSON_PENDING_CONNECTION = "{'id':'STR','object':'connection','type':'WEBRTC','status':'pending','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':null,'location':null,'ip':null,'platform':null,'token':'STR','serverData':'STR','record':true,'role':'STR','kurentoOptions':null,'rtspUri':null,'adaptativeBitrate':null,'onlyPlayWithSubscribers':null,'networkCache':null,'clientData':null,'publishers':null,'subscribers':null}"; + final protected String DEFAULT_JSON_ACTIVE_CONNECTION = "{'id':'STR','object':'connection','type':'WEBRTC','status':'active','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','ip':'STR','platform':'STR','token':'STR','serverData':'STR','record':true,'role':'STR','kurentoOptions':null,'rtspUri':null,'adaptativeBitrate':null,'onlyPlayWithSubscribers':null,'networkCache':null,'clientData':'STR','publishers':[],'subscribers':[]}"; + final protected String DEFAULT_JSON_IPCAM_CONNECTION = "{'id':'STR','object':'connection','type':'IPCAM','status':'active','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','ip':'STR','platform':'IPCAM','token':null,'serverData':'STR','record':true,'role':null,'kurentoOptions':null,'rtspUri':'STR','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':2000,'clientData':null,'publishers':[],'subscribers':[]}"; + final protected String DEFAULT_JSON_TOKEN = "{'id':'STR','token':'STR','connectionId':'STR','createdAt':0,'session':'STR','role':'STR','data':'STR','kurentoOptions':{}}"; + + protected static String OPENVIDU_SECRET = "MY_SECRET"; + protected static String OPENVIDU_URL = "https://localhost:4443/"; + protected static String APP_URL = "http://localhost:4200/"; + protected static String EXTERNAL_CUSTOM_LAYOUT_URL = "http://localhost:4114"; + protected static String OPENVIDU_PRO_LICENSE = "not_valid"; + protected static String OPENVIDU_PRO_LICENSE_API = "not_valid"; + protected static String EXTERNAL_CUSTOM_LAYOUT_PARAMS = "sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET"; + + // https://hub.docker.com/r/selenium/standalone-chrome/tags + protected static String CHROME_VERSION = "latest"; + // https://hub.docker.com/r/selenium/standalone-firefox/tags + protected static String FIREFOX_VERSION = "latest"; + // https://hub.docker.com/r/selenium/standalone-opera/tags + protected static String OPERA_VERSION = "latest"; + // https://hub.docker.com/r/selenium/standalone-edge/tags + protected static String EDGE_VERSION = "latest"; + + protected static Exception ex = null; + protected final Object lock = new Object(); + + protected static final Logger log = LoggerFactory.getLogger(OpenViduTestE2e.class); + protected static final CommandLineExecutor commandLine = new CommandLineExecutor(); + protected static final String RECORDING_IMAGE = "openvidu/openvidu-recording"; + + protected Collection browserUsers = new HashSet<>(); + protected volatile static boolean isRecordingTest; + protected volatile static boolean isKurentoRestartTest; + + protected static VideoCodec defaultForcedVideoCodec; + protected static boolean defaultAllowTranscoding; + + protected static OpenVidu OV; + + protected RecordingUtils recordingUtils = new RecordingUtils(); + + protected static void checkFfmpegInstallation() { + String ffmpegOutput = commandLine.executeCommand("which ffmpeg"); + if (ffmpegOutput == null || ffmpegOutput.isEmpty()) { + log.error("ffmpeg package is not installed in the host machine"); + Assert.fail(); + return; + } else { + log.info("ffmpeg is installed and accesible"); + } + } + + @SuppressWarnings("resource") + protected static void prepareBrowsers(Set browsers) { + if (browsers.contains(BrowserNames.CHROME)) { + if (isRemote(BrowserNames.CHROME)) { + chrome = new GenericContainer<>(DockerImageName.parse("selenium/standalone-chrome:" + CHROME_VERSION)) + .withSharedMemorySize(2147483648L).withFileSystemBind("/opt/openvidu", "/opt/openvidu") + .withExposedPorts(4444).waitingFor(waitBrowser); + chrome.setPortBindings(Arrays.asList("6666:4444")); + } else { + WebDriverManager.chromedriver().setup(); + } + } + if (browsers.contains(BrowserNames.FIREFOX)) { + if (isRemote(BrowserNames.FIREFOX)) { + firefox = new GenericContainer<>( + DockerImageName.parse("selenium/standalone-firefox:" + FIREFOX_VERSION)) + .withSharedMemorySize(2147483648L).withFileSystemBind("/opt/openvidu", "/opt/openvidu") + .withExposedPorts(4444).waitingFor(waitBrowser); + firefox.setPortBindings(Arrays.asList("6667:4444")); + } else { + WebDriverManager.firefoxdriver().setup(); + } + } + if (browsers.contains(BrowserNames.OPERA)) { + if (isRemote(BrowserNames.OPERA)) { + opera = new GenericContainer<>(DockerImageName.parse("selenium/standalone-opera:" + OPERA_VERSION)) + .withSharedMemorySize(2147483648L).withFileSystemBind("/opt/openvidu", "/opt/openvidu") + .withExposedPorts(4444).waitingFor(waitBrowser); + opera.setPortBindings(Arrays.asList("6668:4444")); + } else { + WebDriverManager.operadriver().setup(); + } + } + if (browsers.contains(BrowserNames.EDGE)) { + if (isRemote(BrowserNames.EDGE)) { + edge = new GenericContainer<>(DockerImageName.parse("selenium/standalone-edge:" + EDGE_VERSION)) + .withSharedMemorySize(2147483648L).withFileSystemBind("/opt/openvidu", "/opt/openvidu") + .withExposedPorts(4444).waitingFor(waitBrowser); + edge.setPortBindings(Arrays.asList("6669:4444")); + } else { + WebDriverManager.edgedriver().setup(); + } + } + if (browsers.contains(BrowserNames.ANDROID)) { + android = new GenericContainer<>(DockerImageName.parse("budtmo/docker-android-x86-12.0:latest")) + .withPrivilegedMode(true) + .withEnv(Map.of("DEVICE", "Samsung Galaxy S10", "APPIUM", "true", "APPIUM_HOST", "172.17.0.1", + "APPIUM_PORT", "4723", "MOBILE_WEB_TEST", "true", "RELAXED_SECURITY", "true")) + .withSharedMemorySize(4294967296L).withExposedPorts(6080, 5554, 5555, 4723).waitingFor(waitAndroid) + .withFileSystemBind("/opt/openvidu-cache", "/opt/openvidu-cache"); + android.setPortBindings(Arrays.asList("6080:6080", "5554:5554", "5555:5555", "4723:4723")); + } + } + + protected static void cleanFoldersAndSetUpOpenViduJavaClient() { + try { + log.info("Cleaning folder /opt/openvidu/recordings"); + FileUtils.cleanDirectory(new File("/opt/openvidu/recordings")); + } catch (IOException e) { + log.error(e.getMessage()); + } + OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); + } + + protected static void loadEnvironmentVariables() { + String appUrl = System.getProperty("APP_URL"); + if (appUrl != null) { + APP_URL = appUrl; + } + log.info("Using URL {} to connect to openvidu-testapp", APP_URL); + + String externalCustomLayoutUrl = System.getProperty("EXTERNAL_CUSTOM_LAYOUT_URL"); + if (externalCustomLayoutUrl != null) { + EXTERNAL_CUSTOM_LAYOUT_URL = externalCustomLayoutUrl; + } + log.info("Using URL {} to connect to external custom layout", EXTERNAL_CUSTOM_LAYOUT_URL); + + String externalCustomLayoutParams = System.getProperty("EXTERNAL_CUSTOM_LAYOUT_PARAMS"); + if (externalCustomLayoutParams != null) { + // Parse external layout parameters and build a URL formatted params string + List params = Stream.of(externalCustomLayoutParams.split(",", -1)).collect(Collectors.toList()); + if (params.size() % 2 != 0) { + log.error( + "Wrong configuration property EXTERNAL_CUSTOM_LAYOUT_PARAMS. Must be a comma separated list with an even number of elements. e.g: EXTERNAL_CUSTOM_LAYOUT_PARAMS=param1,value1,param2,value2"); + Assert.fail(); + return; + } else { + EXTERNAL_CUSTOM_LAYOUT_PARAMS = ""; + for (int i = 0; i < params.size(); i++) { + if (i % 2 == 0) { + // Param name + EXTERNAL_CUSTOM_LAYOUT_PARAMS += params.get(i) + "="; + } else { + // Param value + EXTERNAL_CUSTOM_LAYOUT_PARAMS += params.get(i); + if (i < params.size() - 1) { + EXTERNAL_CUSTOM_LAYOUT_PARAMS += "&"; + } + } + } + } + } + log.info("Using URL {} to connect to external custom layout", EXTERNAL_CUSTOM_LAYOUT_PARAMS); + + String openviduUrl = System.getProperty("OPENVIDU_URL"); + if (openviduUrl != null) { + OPENVIDU_URL = openviduUrl; + } + log.info("Using URL {} to connect to openvidu-server", OPENVIDU_URL); + + String openvidusecret = System.getProperty("OPENVIDU_SECRET"); + if (openvidusecret != null) { + OPENVIDU_SECRET = openvidusecret; + } + log.info("Using secret {} to connect to openvidu-server", OPENVIDU_SECRET); + + String mediaServerImage = System.getProperty("MEDIA_SERVER_IMAGE"); + if (mediaServerImage != null) { + MEDIA_SERVER_IMAGE = mediaServerImage; + } + log.info("Using media server {} for e2e tests", MEDIA_SERVER_IMAGE); + + String chromeVersion = System.getProperty("CHROME_VERSION"); + if (chromeVersion != null && !chromeVersion.isBlank()) { + CHROME_VERSION = chromeVersion; + } + log.info("Using Chrome {}", CHROME_VERSION); + + String firefoxVersion = System.getProperty("FIREFOX_VERSION"); + if (firefoxVersion != null && !firefoxVersion.isBlank()) { + FIREFOX_VERSION = firefoxVersion; + } + log.info("Using Firefox {}", FIREFOX_VERSION); + + String operaVersion = System.getProperty("OPERA_VERSION"); + if (operaVersion != null && !operaVersion.isBlank()) { + OPERA_VERSION = operaVersion; + } + log.info("Using Opera {}", OPERA_VERSION); + + String edgeVersion = System.getProperty("EDGE_VERSION"); + if (edgeVersion != null && !edgeVersion.isBlank()) { + EDGE_VERSION = edgeVersion; + } + log.info("Using Edge {}", EDGE_VERSION); + + String openviduProLicense = System.getProperty("OPENVIDU_PRO_LICENSE"); + if (openviduProLicense != null) { + OPENVIDU_PRO_LICENSE = openviduProLicense; + } + + String openviduProLicenseApi = System.getProperty("OPENVIDU_PRO_LICENSE_API"); + if (openviduProLicenseApi != null) { + OPENVIDU_PRO_LICENSE_API = openviduProLicenseApi; + } + } + + protected BrowserUser setupBrowser(String browser) { + + BrowserUser browserUser; + + switch (browser) { + case "chrome": + setupBrowserAux(BrowserNames.CHROME, chrome, false); + browserUser = new ChromeUser("TestUser", 50, false); + break; + case "firefox": + setupBrowserAux(BrowserNames.FIREFOX, firefox, false); + browserUser = new FirefoxUser("TestUser", 50, false); + break; + case "firefoxDisabledOpenH264": + setupBrowserAux(BrowserNames.FIREFOX, firefox, false); + browserUser = new FirefoxUser("TestUser", 50, true); + break; + case "opera": + setupBrowserAux(BrowserNames.OPERA, opera, false); + browserUser = new OperaUser("TestUser", 50); + break; + case "edge": + setupBrowserAux(BrowserNames.EDGE, edge, false); + browserUser = new EdgeUser("TestUser", 50); + break; + case "chromeAlternateScreenShare": + setupBrowserAux(BrowserNames.CHROME, chrome, false); + browserUser = new ChromeUser("TestUser", 50, "OpenVidu TestApp", false); + break; + case "chromeAsRoot": + setupBrowserAux(BrowserNames.CHROME, chrome, false); + browserUser = new ChromeUser("TestUser", 50, true); + break; + case "androidChrome": + setupBrowserAux(BrowserNames.ANDROID, android, false); + try { + // TODO: remove this try-catch when possible. Fixes + // https://github.com/budtmo/docker-android/issues/309 + android.execInContainer("bash", "-c", + "rm chromedriver && wget https://chromedriver.storage.googleapis.com/91.0.4472.101/chromedriver_linux64.zip && unzip chromedriver_linux64.zip && rm chromedriver_linux64.zip"); + } catch (UnsupportedOperationException | IOException | InterruptedException e) { + log.error("Error running command in Android container"); + } + browserUser = new AndroidChromeUser("TestUser", 50); + break; + case "androidFirefox": + setupBrowserAux(BrowserNames.ANDROID, android, false); + try { + // Download geckodriver and place in PATH at /usr/bin/ + android.execInContainer("bash", "-c", + "wget https://github.com/mozilla/geckodriver/releases/download/v0.30.0/geckodriver-v0.30.0-linux64.tar.gz && tar -xf geckodriver*.tar.gz && rm geckodriver*.tar.gz && mv geckodriver /usr/bin/."); + } catch (UnsupportedOperationException | IOException | InterruptedException e) { + log.error("Error running command in Android container"); + } + browserUser = new AndroidFirefoxUser("TestUser", 50); + break; + case "androidApp": + setupBrowserAux(BrowserNames.ANDROID, android, false); + try { + // TODO: remove this try-catch when possible. Fixes + // https://github.com/budtmo/docker-android/issues/309 + android.execInContainer("bash", "-c", + "rm chromedriver && wget https://chromedriver.storage.googleapis.com/91.0.4472.101/chromedriver_linux64.zip && unzip chromedriver_linux64.zip && rm chromedriver_linux64.zip"); + } catch (UnsupportedOperationException | IOException | InterruptedException e) { + log.error("Error running command in Android container"); + } + browserUser = new AndroidAppUser("TestUser", 50, "/opt/openvidu-cache/app-debug.apk"); + break; + default: + setupBrowserAux(BrowserNames.CHROME, chrome, false); + browserUser = new ChromeUser("TestUser", 50, false); + } + + this.browserUsers.add(browserUser); + return browserUser; + } + + protected BrowserUser setupChromeWithFakeVideo(String absolutePathToVideoFile) { + if (isRemote(BrowserNames.CHROME)) { + setupBrowserAux(BrowserNames.CHROME, chrome, true); + } + BrowserUser browserUser = new ChromeUser("TestUser", 50, Paths.get(absolutePathToVideoFile)); + this.browserUsers.add(browserUser); + return browserUser; + } + + private void setupBrowserAux(BrowserNames browser, GenericContainer container, boolean forceRestart) { + if (isRemote(browser)) { + if (forceRestart && container.isRunning()) { + container.stop(); + } + if (!container.isRunning()) { + container.start(); + } + } + } + + private static boolean isRemote(BrowserNames browser) { + String remoteUrl = null; + switch (browser) { + case CHROME: + remoteUrl = System.getProperty("REMOTE_URL_CHROME"); + break; + case FIREFOX: + remoteUrl = System.getProperty("REMOTE_URL_FIREFOX"); + break; + case OPERA: + remoteUrl = System.getProperty("REMOTE_URL_OPERA"); + break; + case EDGE: + remoteUrl = System.getProperty("REMOTE_URL_EDGE"); + break; + case ANDROID: + return true; + } + return remoteUrl != null; + } + + protected static void getDefaultTranscodingValues() throws Exception { + CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); + JsonObject ovConfig = restClient.rest(HttpMethod.GET, "/openvidu/api/config", HttpStatus.SC_OK); + defaultForcedVideoCodec = VideoCodec.valueOf(ovConfig.get("OPENVIDU_STREAMS_FORCED_VIDEO_CODEC").getAsString()); + defaultAllowTranscoding = ovConfig.get("OPENVIDU_STREAMS_ALLOW_TRANSCODING").getAsBoolean(); + } + + @AfterEach + protected void dispose() { + // Close all remaining OpenVidu sessions + this.closeAllSessions(OV); + // Remove all recordings + if (isRecordingTest) { + deleteAllRecordings(OV); + isRecordingTest = false; + } + // Reset Media Server + if (isKurentoRestartTest) { + this.stopMediaServer(false); + this.startMediaServer(true); + isKurentoRestartTest = false; + } + // Dispose all browsers users + Iterator it1 = browserUsers.iterator(); + while (it1.hasNext()) { + BrowserUser u = it1.next(); + u.dispose(); + it1.remove(); + } + // Stop and remove all browser containers if necessary + stopContainerIfPossible(chrome); + stopContainerIfPossible(firefox); + stopContainerIfPossible(opera); + stopContainerIfPossible(edge); + stopContainerIfPossible(android); + // Reset REST client + OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); + } + + private void stopContainerIfPossible(GenericContainer container) { + if (container != null && container.isRunning()) { + container.stop(); + } + } + + protected void closeAllSessions(OpenVidu client) { + try { + client.fetch(); + } catch (OpenViduJavaClientException | OpenViduHttpException e) { + log.error("Error fetching sessions: {}", e.getMessage()); + } + client.getActiveSessions().forEach(session -> { + try { + session.close(); + log.info("Session {} successfully closed", session.getSessionId()); + } catch (OpenViduJavaClientException | OpenViduHttpException e) { + log.error("Error closing session: {}", e.getMessage()); + } + }); + } + + protected void deleteAllRecordings(OpenVidu client) { + try { + client.listRecordings().forEach(recording -> { + try { + client.deleteRecording(recording.getId()); + log.info("Recording {} successfully deleted", recording.getId()); + } catch (OpenViduJavaClientException | OpenViduHttpException e) { + log.error("Error deleting recording: {}", e.getMessage()); + } + }); + } catch (OpenViduJavaClientException | OpenViduHttpException e) { + log.error("Error listing recordings: {}", e.getMessage()); + } + removeAllRecordingContiners(); + try { + FileUtils.cleanDirectory(new File("/opt/openvidu/recordings")); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + + protected ExpectedCondition waitForVideoDuration(WebElement element, int durationInSeconds) { + return new ExpectedCondition() { + @Override + public Boolean apply(WebDriver input) { + return element.getAttribute("duration").matches( + durationInSeconds - 1 + "\\.[5-9][0-9]{0,5}|" + durationInSeconds + "\\.[0-5][0-9]{0,5}"); + } + }; + } + + protected String getBase64Screenshot(BrowserUser user) throws Exception { + String screenshotBase64 = ((TakesScreenshot) user.getDriver()).getScreenshotAs(BASE64); + return "data:image/png;base64," + screenshotBase64; + } + + protected void startMediaServer(boolean waitUntilKurentoClientReconnection) { + String command = null; + if (MEDIA_SERVER_IMAGE.startsWith(KURENTO_IMAGE)) { + log.info("Starting kurento"); + command = "docker run -e KMS_UID=$(id -u) --network=host --detach=true" + + " --volume=/opt/openvidu/recordings:/opt/openvidu/recordings " + MEDIA_SERVER_IMAGE; + } else if (MEDIA_SERVER_IMAGE.startsWith(MEDIASOUP_IMAGE)) { + log.info("Starting mediaSoup"); + command = "docker run --network=host --restart=always --detach=true --env=KMS_MIN_PORT=40000 --env=KMS_MAX_PORT=65535" + + " --env=OPENVIDU_PRO_LICENSE=" + OPENVIDU_PRO_LICENSE + " --env=OPENVIDU_PRO_LICENSE_API=" + + OPENVIDU_PRO_LICENSE_API + + " --env=WEBRTC_LISTENIPS_0_ANNOUNCEDIP=172.17.0.1 --env=WEBRTC_LISTENIPS_0_IP=172.17.0.1" + + " --volume=/opt/openvidu/recordings:/opt/openvidu/recordings " + MEDIA_SERVER_IMAGE; + } else { + log.error("Unrecognized MEDIA_SERVER_IMAGE: {}", MEDIA_SERVER_IMAGE); + System.exit(1); + } + commandLine.executeCommand(command); + if (waitUntilKurentoClientReconnection) { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + protected void stopMediaServer(boolean waitUntilNodeCrashedEvent) { + final String dockerRemoveCmd = "docker ps -a | awk '{ print $1,$2 }' | grep GREP_PARAMETER | awk '{ print $1 }' | xargs -I {} docker rm -f {}"; + String grep = null; + if (MEDIA_SERVER_IMAGE.startsWith(KURENTO_IMAGE)) { + log.info("Stopping kurento"); + grep = KURENTO_IMAGE + ":"; + } else if (MEDIA_SERVER_IMAGE.startsWith(MEDIASOUP_IMAGE)) { + log.info("Stopping mediasoup"); + grep = MEDIASOUP_IMAGE + ":"; + } else { + log.error("Unrecognized MEDIA_SERVER_IMAGE: {}", MEDIA_SERVER_IMAGE); + System.exit(1); + } + commandLine.executeCommand(dockerRemoveCmd.replaceFirst("GREP_PARAMETER", grep)); + if (waitUntilNodeCrashedEvent) { + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + protected void checkDockerContainerRunning(String imageName, int amount) { + int number = Integer.parseInt(commandLine.executeCommand("docker ps | grep " + imageName + " | wc -l")); + Assert.assertEquals("Wrong number of Docker containers for image " + imageName + " running", amount, number); + } + + protected void removeAllRecordingContiners() { + commandLine.executeCommand("docker ps -a | awk '{ print $1,$2 }' | grep " + RECORDING_IMAGE + + " | awk '{print $1 }' | xargs -I {} docker rm -f {}"); + } + + protected String mergeJson(String json, String newProperties, String[] removeProperties) { + JsonObject jsonObj = JsonParser.parseString(json.replaceAll("'", "\"")).getAsJsonObject(); + JsonObject newJsonObj = JsonParser.parseString(newProperties.replaceAll("'", "\"")).getAsJsonObject(); + newJsonObj.entrySet().forEach(entry -> { + jsonObj.remove(entry.getKey()); + jsonObj.add(entry.getKey(), entry.getValue()); + }); + for (String prop : removeProperties) { + jsonObj.remove(prop); + } + return jsonObj.toString().replaceAll("\"", "'"); + } + + protected String getIndividualRecordingExtension() throws Exception { + if (MEDIA_SERVER_IMAGE.contains(KURENTO_IMAGE)) { + return "webm"; + } + if (MEDIA_SERVER_IMAGE.contains(MEDIASOUP_IMAGE)) { + return "mkv"; + } else { + throw new Exception("Unknown media server"); + } + } + + protected void waitUntilFileExistsAndIsBiggerThan(String absolutePath, int kbs, int maxSecondsWait) + throws Exception { + + long startTime = System.currentTimeMillis(); + + int interval = 100; + int maxLoops = (maxSecondsWait * 1000) / interval; + int loop = 0; + long bytes = 0; + + boolean bigger = false; + Path path = Paths.get(absolutePath); + + while (!bigger && loop < maxLoops) { + bigger = Files.exists(path) && Files.isReadable(path); + if (bigger) { + try { + bytes = Files.size(path); + } catch (IOException e) { + System.err.println("Error getting file size from " + path + ": " + e.getMessage()); + } + bigger = (bytes / 1024) > kbs; + } + loop++; + Thread.sleep(interval); + } + + if (!bigger && loop >= maxLoops) { + String errorMessage; + if (!Files.exists(path)) { + errorMessage = "File " + absolutePath + " does not exist and has not been created in " + maxSecondsWait + + " seconds"; + } else if (!Files.isReadable(path)) { + errorMessage = "File " + absolutePath + + " exists but is not readable, and read permissions have not been granted in " + maxSecondsWait + + " seconds"; + } else { + errorMessage = "File " + absolutePath + " did not reach a size of at least " + kbs + " KBs in " + + maxSecondsWait + " seconds. Last check was " + (bytes / 1024) + " KBs"; + } + throw new Exception(errorMessage); + } else { + log.info("File " + absolutePath + " did reach a size of at least " + kbs + " KBs in " + + (System.currentTimeMillis() - startTime) + " ms (last checked size was " + (bytes / 1024) + + " KBs)"); + } + } + +} diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestappE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestappE2eTest.java new file mode 100644 index 00000000..e79718d8 --- /dev/null +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestappE2eTest.java @@ -0,0 +1,83 @@ +package io.openvidu.test.e2e; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; + +import org.junit.jupiter.api.AfterEach; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedConditions; + +import io.openvidu.test.browsers.BrowserUser; + +public class AbstractOpenViduTestappE2eTest extends OpenViduTestE2e { + + protected Collection testappUsers = new HashSet<>(); + + private void connectToOpenViduTestApp(OpenViduTestappUser user) { + user.getDriver().get(APP_URL); + WebElement urlInput = user.getDriver().findElement(By.id("openvidu-url")); + urlInput.clear(); + urlInput.sendKeys(OPENVIDU_URL); + WebElement secretInput = user.getDriver().findElement(By.id("openvidu-secret")); + secretInput.clear(); + secretInput.sendKeys(OPENVIDU_SECRET); + user.getEventManager().startPolling(); + } + + protected OpenViduTestappUser setupBrowserAndConnectToOpenViduTestapp(String browser) { + BrowserUser browserUser = this.setupBrowser(browser); + OpenViduTestappUser testappUser = new OpenViduTestappUser(browserUser); + this.testappUsers.add(testappUser); + this.connectToOpenViduTestApp(testappUser); + return testappUser; + } + + protected OpenViduTestappUser setupChromeWithFakeVideoAndConnectToOpenViduTestApp(String absolutePathToVideoFile) { + BrowserUser browserUser = this.setupChromeWithFakeVideo(absolutePathToVideoFile); + OpenViduTestappUser testappUser = new OpenViduTestappUser(browserUser); + testappUser.getDriver().get(APP_URL); + WebElement urlInput = testappUser.getDriver().findElement(By.id("openvidu-url")); + urlInput.clear(); + urlInput.sendKeys(OPENVIDU_URL); + WebElement secretInput = testappUser.getDriver().findElement(By.id("openvidu-secret")); + secretInput.clear(); + secretInput.sendKeys(OPENVIDU_SECRET); + testappUser.getEventManager().startPolling(); + return testappUser; + } + + protected void listEmptyRecordings(OpenViduTestappUser user) { + // List existing recordings (empty) + user.getDriver().findElement(By.id("list-recording-btn")).click(); + user.getWaiter() + .until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Recording list []")); + } + + protected void gracefullyLeaveParticipants(OpenViduTestappUser user, int numberOfParticipants) throws Exception { + int accumulatedConnectionDestroyed = 0; + for (int j = 1; j <= numberOfParticipants; j++) { + user.getDriver().findElement(By.id("remove-user-btn")).sendKeys(Keys.ENTER); + user.getEventManager().waitUntilEventReaches("sessionDisconnected", j); + accumulatedConnectionDestroyed = (j != numberOfParticipants) + ? (accumulatedConnectionDestroyed + numberOfParticipants - j) + : (accumulatedConnectionDestroyed); + user.getEventManager().waitUntilEventReaches("connectionDestroyed", accumulatedConnectionDestroyed); + } + } + + @AfterEach + protected void dispose() { + // Dispose all testapp users + Iterator it2 = testappUsers.iterator(); + while (it2.hasNext()) { + OpenViduTestappUser u = it2.next(); + u.dispose(); + it2.remove(); + } + super.dispose(); + } + +} diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index 893c5d43..1f15c2ab 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -49,7 +49,7 @@ import io.openvidu.test.browsers.utils.BrowserNames; import io.openvidu.test.browsers.utils.CustomHttpClient; import io.openvidu.test.browsers.utils.Unzipper; -public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { +public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest { protected volatile static boolean isNetworkQualityTest; @@ -89,7 +89,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void individualDynamicRecordTest() throws Exception { isRecordingTest = true; - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Individual dynamic record"); @@ -310,7 +310,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertFalse("Wrong record Connection property", connection.record()); Assert.assertEquals("Wrong data Connection property", "MY_SERVER_PRO_DATA", connection.getServerData()); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); user.getDriver().findElement(By.id("add-user-btn")).click(); user.getDriver().findElement(By.id("session-settings-btn-0")).click(); @@ -570,7 +570,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.POST, "/openvidu/api/restart", body, 200); waitUntilOpenViduRestarted(30); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); user.getDriver().findElement(By.id("add-user-btn")).click(); user.getDriver().findElement(By.className("join-btn")).click(); diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 6f71331f..afa7273e 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -94,7 +94,7 @@ import io.openvidu.test.e2e.annotations.OnlyKurento; @Tag("e2e") @DisplayName("E2E tests for OpenVidu TestApp") @ExtendWith(SpringExtension.class) -public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { +public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest { @BeforeAll() protected static void setupAll() throws Exception { @@ -109,7 +109,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @Test @DisplayName("One2One Chrome") void oneToOneChrome() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("One2One Chrome"); oneToOneAux(user); } @@ -117,7 +117,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @Test @DisplayName("One2One Firefox") void oneToOneFirefox() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("firefox"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("firefox"); log.info("One2One Firefox"); oneToOneAux(user); } @@ -125,7 +125,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @Test @DisplayName("One2One Opera") void oneToOneOpera() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("opera"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("opera"); log.info("One2One Opera"); oneToOneAux(user); } @@ -133,7 +133,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @Test @DisplayName("One2One Edge") void oneToOneEdge() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("edge"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("edge"); log.info("One2One Edge"); oneToOneAux(user); } @@ -143,7 +143,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("One2One Chrome Android") void oneToOneChromeAndroid() throws Exception { long initTime = System.currentTimeMillis(); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("androidChrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("androidChrome"); log.info("Android emulator ready after {} seconds", (System.currentTimeMillis() - initTime) / 1000); log.info("One2One Android Chrome"); onePublisherOneSubscriber(user); @@ -154,7 +154,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @Disabled void oneToOneFirefoxAndroid() throws Exception { long initTime = System.currentTimeMillis(); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("androidFirefox"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("androidFirefox"); log.info("Android emulator ready after {} seconds", (System.currentTimeMillis() - initTime) / 1000); log.info("One2One Android Firefox"); onePublisherOneSubscriber(user); @@ -165,7 +165,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @Disabled void oneToOneIonicAndroid() throws Exception { long initTime = System.currentTimeMillis(); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("androidApp"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("androidApp"); log.info("Android emulator ready after {} seconds", (System.currentTimeMillis() - initTime) / 1000); log.info("One2One Ionic Android"); @@ -184,7 +184,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { appiumDriver.findElement(By.cssSelector("#join-button")).click(); } - private void oneToOneAux(MyUser user) throws Exception { + private void oneToOneAux(OpenViduTestappUser user) throws Exception { user.getDriver().findElement(By.id("auto-join-checkbox")).click(); user.getDriver().findElement(By.id("one2one-btn")).click(); user.getEventManager().waitUntilEventReaches("connectionCreated", 4); @@ -198,7 +198,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { gracefullyLeaveParticipants(user, 2); } - private void onePublisherOneSubscriber(MyUser user) throws Exception { + private void onePublisherOneSubscriber(OpenViduTestappUser user) throws Exception { user.getDriver().findElement(By.id("add-user-btn")).click(); user.getDriver().findElement(By.id("add-user-btn")).click(); user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .publish-checkbox")).click(); @@ -220,7 +220,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("One2One only audio") void oneToOneOnlyAudioSession() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("One2One only audio"); @@ -246,7 +246,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("One2One only video") void oneToOneOnlyVideoSession() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("One2One only video"); @@ -272,7 +272,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("One2Many [Video + Audio]") void oneToManyVideoAudioSession() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("One2Many [Video + Audio]"); @@ -297,7 +297,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Unique user remote subscription [Video + Audio]") void oneRemoteSubscription() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Unique user remote subscription [Video + Audio]"); @@ -323,7 +323,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Unique user remote subscription Firefox [Video + Audio]") void oneRemoteSubscriptionFirefox() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("firefox"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("firefox"); log.info("Unique user remote subscription Firefox [Video + Audio]"); @@ -349,7 +349,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Unique user remote subscription [ScreenShare + Audio]") void oneRemoteSubscriptionScreen() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Unique user remote subscription [ScreenShare + Audio]"); @@ -375,7 +375,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Many2Many [Video + Audio]") void manyToManyVideoAudioSession() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Many2Many [Video + Audio]"); @@ -416,7 +416,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { final CountDownLatch latch = new CountDownLatch(4); - final BiFunction browserTest = (user, browserName) -> { + final BiFunction browserTest = (user, browserName) -> { user.getDriver().findElement(By.id("add-user-btn")).click(); user.getDriver().findElement(By.className("join-btn")).click(); @@ -487,7 +487,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Signal message") void oneToManySignalMessage() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Signal message"); @@ -510,7 +510,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("ExceptionEvent test") void exceptionEventTest() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("ExceptionEvent test"); @@ -542,7 +542,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Subscribe Unsubscribe") void subscribeUnsubscribeTest() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Subscribe Unsubscribe"); @@ -610,7 +610,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Publish Unpublish") void publishUnpublishTest() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Publisher unpublish"); @@ -658,7 +658,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Queue threadAssertions = new ConcurrentLinkedQueue(); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Change publisher dynamically"); @@ -777,7 +777,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Moderator capabilities") void moderatorCapabilitiesTest() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Moderator capabilities"); @@ -846,7 +846,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Queue threadAssertions = new ConcurrentLinkedQueue(); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chromeAlternateScreenShare"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chromeAlternateScreenShare"); log.info("Stream property changed event"); @@ -976,7 +976,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Queue threadAssertions = new ConcurrentLinkedQueue(); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chromeAlternateScreenShare"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chromeAlternateScreenShare"); log.info("Stream property changed event"); @@ -1043,7 +1043,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Local browser record") void localBrowserRecordTest() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Local browser record"); @@ -1085,7 +1085,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { user.getWaiter().until( waitForVideoDuration(user.getDriver().findElement(By.cssSelector("#recorder-preview video")), 4)); } catch (Exception e) { - System.out.println(getBase64Screenshot(user)); + System.out.println(getBase64Screenshot(user.getBrowserUser())); Assert.fail(); } @@ -1101,7 +1101,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void composedRecordTest() throws Exception { isRecordingTest = true; - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Composed record"); @@ -1261,7 +1261,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void composedQuickStartRecordTest() throws Exception { isRecordingTest = true; - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Composed quick start record"); @@ -1436,7 +1436,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void individualRecordTest() throws Exception { isRecordingTest = true; - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Individual record"); @@ -1546,7 +1546,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void audioOnlyVideoOnlyRecordTest() throws Exception { isRecordingTest = true; - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chromeAlternateScreenShare"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chromeAlternateScreenShare"); log.info("Record cross-browser audio-only and video-only"); @@ -1566,7 +1566,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { }; Thread t = new Thread(() -> { - MyUser user2 = setupBrowserAndConnectToOpenViduTestapp("firefox"); + OpenViduTestappUser user2 = setupBrowserAndConnectToOpenViduTestapp("firefox"); user2.getDriver().get(APP_URL); WebElement urlInput = user2.getDriver().findElement(By.id("openvidu-url")); urlInput.clear(); @@ -1746,7 +1746,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void audioOnlyComposedRecordTest() throws Exception { isRecordingTest = true; - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chromeAlternateScreenShare"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chromeAlternateScreenShare"); log.info("Record audio-only COMPOSED"); @@ -1819,7 +1819,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void customLayoutRecordTest() throws Exception { isRecordingTest = true; - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Custom layout recording"); @@ -1941,7 +1941,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("REST API: Fetch all, fetch one, force disconnect, force unpublish, close session") void restApiFetchForce() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("REST API: Fetch all, fetch one, force disconnect, force unpublish, close session"); @@ -2058,7 +2058,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Video filter test") void videoFilterTest() throws Exception { - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Video filter test"); @@ -2202,7 +2202,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Video filter events test") void videoFilterEventsTest() throws Exception { - MyUser user = setupChromeWithFakeVideo("/opt/openvidu/barcode.y4m"); + OpenViduTestappUser user = setupChromeWithFakeVideoAndConnectToOpenViduTestApp("/opt/openvidu/barcode.y4m"); log.info("Video filter events test"); @@ -2327,7 +2327,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void openViduJavaClientTest() throws Exception { isRecordingTest = true; - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chromeAlternateScreenShare"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chromeAlternateScreenShare"); user.getDriver().manage().window().setSize(new Dimension(1000, 800)); @@ -3065,7 +3065,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { HttpStatus.SC_NO_CONTENT); // Start session - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); user.getDriver().findElement(By.id("one2one-btn")).click(); user.getDriver().findElement(By.id("session-settings-btn-0")).click(); Thread.sleep(1000); @@ -3441,7 +3441,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { return; } - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); // TOTAL DISCONNECTION // Session should be destroyed with reason nodeCrashed @@ -3517,6 +3517,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { this.stopMediaServer(false); this.startMediaServer(true); + user.getEventManager().resetEventThread(); user.getDriver().findElement(By.id("add-user-btn")).click(); user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).click(); user.getEventManager().waitUntilEventReaches("streamCreated", 2); @@ -3546,7 +3547,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { return; } - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); // TOTAL DISCONNECTION // Streams, Connections and Session should be destroyed with reason @@ -3720,7 +3721,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void webhookTest() throws Exception { isRecordingTest = true; - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("Webhook test"); @@ -3895,7 +3896,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void webhookFilterEventTest() throws Exception { isRecordingTest = true; - MyUser user = setupChromeWithFakeVideo("/opt/openvidu/barcode.y4m"); + OpenViduTestappUser user = setupChromeWithFakeVideoAndConnectToOpenViduTestApp("/opt/openvidu/barcode.y4m"); log.info("Webhook test"); @@ -4052,7 +4053,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { response.get("reason").getAsString()); CustomWebhook.waitForEvent("sessionDestroyed", 1); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); // Record a session to get an MP4 file @@ -4237,7 +4238,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void openviduSdkFetchTest() throws Exception { isRecordingTest = true; - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); log.info("OpenVidu SDK fetch test"); @@ -4473,7 +4474,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Force codec default config") void forceDefaultCodec() throws Exception { log.info("Force codec default config"); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); this.forceCodecGenericE2eTest(user); } @@ -4482,7 +4483,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Force valid codec VP8 - Not Allow Transcoding") void forceValidCodecNotAllowTranscodingVP8Test() throws Exception { log.info("Force codec Chrome - Force VP8 - Not Allow Transcoding"); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); this.forceCodecGenericE2eTest(user, VideoCodec.VP8, false); user.getDriver().close(); } @@ -4492,7 +4493,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Force valid codec H264 - Not Allow Transcoding") void forceValidCodecNotAllowTranscodingH264Test() throws Exception { log.info("Force codec Chrome - Force H264 - Not Allow Transcoding"); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); this.forceCodecGenericE2eTest(user, VideoCodec.H264, false); user.getDriver().close(); } @@ -4502,7 +4503,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Force valid codec VP8 - Allow Transcoding") void forceValidCodecAllowTranscodingVP8Test() throws Exception { log.info("Force codec Chrome - Force VP8 - Allow Transcoding"); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); this.forceCodecGenericE2eTest(user, VideoCodec.VP8, true); user.getDriver().close(); } @@ -4512,7 +4513,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Force valid codec H264 - Allow Transcoding") void forceValidCodecAllowTranscodingH264Test() throws Exception { log.info("Force codec Chrome - Force H264 - Allow Transcoding"); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome"); this.forceCodecGenericE2eTest(user, VideoCodec.H264, true); user.getDriver().close(); } @@ -4523,7 +4524,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void forceCodecNotValidCodecNotAllowTranscoding() throws Exception { // Start firefox with OpenH264 disabled to check not supported codecs log.info("Force codec Firefox - Force H264 - Allow Transcoding - Disabled H264 in Firefox"); - MyUser user = setupBrowserAndConnectToOpenViduTestapp("firefoxDisabledOpenH264"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("firefoxDisabledOpenH264"); this.forceNotSupportedCodec(user, VideoCodec.H264, false); } @@ -4531,12 +4532,12 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("Force not valid codec - Allow Transcoding") void forceCodecNotValidCodecAllowTranscoding() throws Exception { // Start firefox with OpenH264 disabled to check not supported codecs - MyUser user = setupBrowserAndConnectToOpenViduTestapp("firefoxDisabledOpenH264"); + OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("firefoxDisabledOpenH264"); log.info("Force codec Firefox - Force H264 - Allow Transcoding - Disabled H264 in Firefox"); this.forceNotSupportedCodec(user, VideoCodec.H264, true); } - private void checkNodeFetchChanged(MyUser user, boolean global, boolean hasChanged) { + private void checkNodeFetchChanged(OpenViduTestappUser user, boolean global, boolean hasChanged) { user.getDriver().findElement(By.id(global ? "list-sessions-btn" : "get-session-btn")).click(); user.getWaiter().until(new NodeFetchHasChanged(hasChanged)); } @@ -4559,7 +4560,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { /** * Test default config of forced codec and allowTranscoding */ - private void forceCodecGenericE2eTest(MyUser user) throws Exception { + private void forceCodecGenericE2eTest(OpenViduTestappUser user) throws Exception { forceCodecGenericE2eTest(user, null, null); } @@ -4571,7 +4572,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { * @param allowTranscoding If true, allow transcoding. If null, default value in * openvidu config will be used. */ - private void forceCodecGenericE2eTest(MyUser user, VideoCodec codec, Boolean allowTranscoding) throws Exception { + private void forceCodecGenericE2eTest(OpenViduTestappUser user, VideoCodec codec, Boolean allowTranscoding) + throws Exception { CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); String sessionName = "CUSTOM_SESSION_" + ((codec != null) ? codec.name() : "DEFAULT_FORCE_CODEC"); @@ -4661,7 +4663,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { * * @throws Exception */ - private void forceNotSupportedCodec(MyUser user, VideoCodec codec, boolean allowTranscoding) throws Exception { + private void forceNotSupportedCodec(OpenViduTestappUser user, VideoCodec codec, boolean allowTranscoding) + throws Exception { CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); String sessionName = "CUSTOM_SESSION_CODEC_NOT_SUPPORTED"; diff --git a/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/MyUser.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestappUser.java similarity index 87% rename from openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/MyUser.java rename to openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestappUser.java index 4533c054..7538b45b 100644 --- a/openvidu-test-e2e/src/main/java/io/openvidu/test/e2e/MyUser.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestappUser.java @@ -9,16 +9,20 @@ import org.openqa.selenium.support.ui.WebDriverWait; import io.openvidu.test.browsers.BrowserUser; -public class MyUser { +public class OpenViduTestappUser { private BrowserUser browserUser; private OpenViduEventManager eventManager; - public MyUser(BrowserUser browserUser) { + public OpenViduTestappUser(BrowserUser browserUser) { this.browserUser = browserUser; this.eventManager = new OpenViduEventManager(this.browserUser.getDriver(), this.browserUser.getTimeOfWait()); } + public BrowserUser getBrowserUser() { + return this.browserUser; + } + public WebDriver getDriver() { return this.browserUser.getDriver(); }