diff --git a/openvidu-test-browsers/pom.xml b/openvidu-test-browsers/pom.xml index 77e2d039..83915a44 100644 --- a/openvidu-test-browsers/pom.xml +++ b/openvidu-test-browsers/pom.xml @@ -102,6 +102,17 @@ junit ${version.junit} + + io.appium + java-client + ${version.appium} + + + org.springframework + spring-context + + + diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/AndroidAppUser.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/AndroidAppUser.java new file mode 100644 index 00000000..ef44de1c --- /dev/null +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/AndroidAppUser.java @@ -0,0 +1,37 @@ +package io.openvidu.test.browsers; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.openqa.selenium.WebElement; + +import io.appium.java_client.AppiumDriver; +import io.appium.java_client.android.AndroidOptions; +import io.appium.java_client.remote.MobilePlatform; + +public class AndroidAppUser extends BrowserUser { + + public AndroidAppUser(String userName, int timeOfWaitInSeconds, String appPath) { + super(userName, timeOfWaitInSeconds); + + AndroidOptions options = new AndroidOptions(); + options.setAutomationName("UiAutomator2"); + options.setPlatformVersion("12.0"); + options.setPlatformName(MobilePlatform.ANDROID); + options.setAutomationName("UiAutomator2"); + options.setDeviceName("Android device"); + options.setAutoWebview(true); + options.setApp(appPath); + + URL url = null; + try { + url = new URL("http://172.17.0.1:4723/wd/hub"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + this.driver = new AppiumDriver(url, options); + + this.configureDriver(); + } + +} \ No newline at end of file diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/AndroidChromeUser.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/AndroidChromeUser.java new file mode 100644 index 00000000..5b6dd8bc --- /dev/null +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/AndroidChromeUser.java @@ -0,0 +1,44 @@ +package io.openvidu.test.browsers; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.openqa.selenium.chrome.ChromeOptions; +import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.remote.RemoteWebDriver; + +import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.remote.MobilePlatform; + +// docker run --privileged --rm --name android-chrome -p 6080:6080 -p 5554:5554 -p 5555:5555 -p 4723:4723 -e DEVICE="Samsung Galaxy S10" -e APPIUM=true -e APPIUM_HOST=172.17.0.1 -e APPIUM_PORT=4723 -e MOBILE_WEB_TEST=true -e RELAXED_SECURITY=true budtmo/docker-android-x86-12.0 +// docker exec android-chrome 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" +public class AndroidChromeUser extends BrowserUser { + + public AndroidChromeUser(String userName, int timeOfWaitInSeconds) { + super(userName, timeOfWaitInSeconds); + + ChromeOptions options = new ChromeOptions(); + options.addArguments("no-first-run", "disable-infobars", "use-fake-ui-for-media-stream", + "use-fake-device-for-media-stream", "ignore-certificate-errors", + "autoplay-policy=no-user-gesture-required"); + + DesiredCapabilities capabilities = new DesiredCapabilities(); + capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "12.0"); + capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android device"); + capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID); + capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "UiAutomator2"); + capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "Chrome"); + capabilities.setCapability(ChromeOptions.CAPABILITY, options); + + URL url = null; + try { + url = new URL("http://172.17.0.1:4723/wd/hub"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + this.driver = new RemoteWebDriver(url, capabilities); + + this.configureDriver(); + } + +} diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/AndroidFirefoxUser.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/AndroidFirefoxUser.java new file mode 100644 index 00000000..678d6082 --- /dev/null +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/AndroidFirefoxUser.java @@ -0,0 +1,83 @@ +package io.openvidu.test.browsers; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.openqa.selenium.UnexpectedAlertBehaviour; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.firefox.FirefoxProfile; +import org.openqa.selenium.remote.CapabilityType; +import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.remote.RemoteWebDriver; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.remote.MobilePlatform; + +public class AndroidFirefoxUser extends BrowserUser { + + public AndroidFirefoxUser(String userName, int timeOfWaitInSeconds) { + super(userName, timeOfWaitInSeconds); + + DesiredCapabilities capabilities = new DesiredCapabilities(); + capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "12.0"); + capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android device"); + capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID); + capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "Appium"); + + URL url = null; + try { + url = new URL("http://172.17.0.1:4723/wd/hub"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + + AndroidDriver driver = new AndroidDriver<>(url, capabilities); + driver.installApp("/opt/openvidu-cache/firefox-91-4-0.apk"); + driver.quit(); + + capabilities = DesiredCapabilities.firefox(); + capabilities.setAcceptInsecureCerts(true); + capabilities.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE); + + FirefoxProfile profile = new FirefoxProfile(); + // This flag avoids granting the access to the camera + profile.setPreference("media.navigator.permission.disabled", true); + // This flag force to use fake user media (synthetic video of multiple color) + profile.setPreference("media.navigator.streams.fake", true); + // These flags allows controlling Firefox remotely + profile.setPreference("devtools.debugger.remote-enabled", true); + capabilities.setCapability(FirefoxDriver.PROFILE, profile); + + capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android device"); + capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "firefox"); + capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "linux"); + capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "Gecko"); + + capabilities.setCapability("appium:automationName", "Gecko"); + capabilities.setCapability("marionette", true); + capabilities.setCapability("appium:marionette", true); + capabilities.setCapability("androidStorage", "app"); + capabilities.setCapability("appium:androidStorage", "app"); + + Map mozFirefoxOptions = new HashMap<>(); + mozFirefoxOptions.put("androidPackage", "org.mozilla.firefox"); + mozFirefoxOptions.put("androidDeviceSerial", "emulator-5554"); + mozFirefoxOptions.put("binary", "/Applications/Firefox.app"); + capabilities.setCapability("moz:firefoxOptions", mozFirefoxOptions); + + long initTime = System.currentTimeMillis(); + try { + this.driver = new RemoteWebDriver(url, capabilities); + } catch (Exception e) { + log.error("{}", e); + } + log.info("Remote web driver for Firefox Android initialized after {} ms", + System.currentTimeMillis() - initTime); + + this.configureDriver(); + } + +} diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/BrowserUser.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/BrowserUser.java index dfb339f4..24316394 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/BrowserUser.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/BrowserUser.java @@ -57,11 +57,11 @@ public class BrowserUser { } protected void newWaiter(int timeOfWait) { - this.waiter = new WebDriverWait(this.driver, Duration.ofSeconds(timeOfWait)); + this.waiter = new WebDriverWait(this.driver, timeOfWait); } protected void configureDriver() { - this.waiter = new WebDriverWait(this.driver, Duration.ofSeconds(timeOfWaitInSeconds)); + this.waiter = new WebDriverWait(this.driver, timeOfWaitInSeconds); } protected void configureDriver(Dimension windowDimensions) { diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/ChromeUser.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/ChromeUser.java index 0fefdc11..6842eb5c 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/ChromeUser.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/ChromeUser.java @@ -21,9 +21,9 @@ import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; -import java.time.Duration; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; import org.openqa.selenium.UnexpectedAlertBehaviour; import org.openqa.selenium.chrome.ChromeDriver; @@ -71,7 +71,7 @@ public class ChromeUser extends BrowserUser { this.driver = new ChromeDriver(options); } - this.driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(timeOfWaitInSeconds)); + this.driver.manage().timeouts().setScriptTimeout(timeOfWaitInSeconds, TimeUnit.SECONDS); this.configureDriver(new org.openqa.selenium.Dimension(1920, 1080)); } diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/EdgeUser.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/EdgeUser.java index 12fe6884..4c42b03d 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/EdgeUser.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/EdgeUser.java @@ -2,7 +2,11 @@ package io.openvidu.test.browsers; import java.net.MalformedURLException; import java.net.URL; -import java.time.Duration; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; import org.openqa.selenium.UnexpectedAlertBehaviour; import org.openqa.selenium.edge.EdgeDriver; @@ -16,12 +20,13 @@ public class EdgeUser extends BrowserUser { super(userName, timeOfWaitInSeconds); EdgeOptions options = new EdgeOptions(); - options.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE); - options.setAcceptInsecureCerts(true); - options.addArguments("allow-file-access-from-files"); - options.addArguments("use-fake-device-for-media-stream"); - options.addArguments("use-fake-ui-for-media-stream"); + options.setCapability(CapabilityType.ACCEPT_INSECURE_CERTS, true); + // When upgrading to selenium 4.0.0 options.addArguments will make this easier + List args = Arrays.asList("use-fake-ui-for-media-stream", "use-fake-device-for-media-stream"); + Map map = new HashMap<>(); + map.put("args", args); + options.setCapability("ms:edgeOptions", map); String REMOTE_URL = System.getProperty("REMOTE_URL_EDGE"); if (REMOTE_URL != null) { @@ -36,7 +41,7 @@ public class EdgeUser extends BrowserUser { this.driver = new EdgeDriver(options); } - this.driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(timeOfWaitInSeconds)); + this.driver.manage().timeouts().setScriptTimeout(timeOfWaitInSeconds, TimeUnit.SECONDS); this.configureDriver(new org.openqa.selenium.Dimension(1920, 1080)); } diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/FirefoxUser.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/FirefoxUser.java index ebce261f..eff4e27b 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/FirefoxUser.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/FirefoxUser.java @@ -19,13 +19,14 @@ package io.openvidu.test.browsers; import java.net.MalformedURLException; import java.net.URL; -import java.time.Duration; +import java.util.concurrent.TimeUnit; import org.openqa.selenium.UnexpectedAlertBehaviour; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; import org.openqa.selenium.firefox.FirefoxProfile; import org.openqa.selenium.remote.CapabilityType; +import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.RemoteWebDriver; public class FirefoxUser extends BrowserUser { @@ -33,13 +34,9 @@ public class FirefoxUser extends BrowserUser { public FirefoxUser(String userName, int timeOfWaitInSeconds, boolean disableOpenH264) { super(userName, timeOfWaitInSeconds); - FirefoxOptions options = new FirefoxOptions(); - - options.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE); - options.setAcceptInsecureCerts(true); - options.addArguments("allow-file-access-from-files"); - options.addArguments("use-fake-device-for-media-stream"); - options.addArguments("use-fake-ui-for-media-stream"); + DesiredCapabilities capabilities = DesiredCapabilities.firefox(); + capabilities.setAcceptInsecureCerts(true); + capabilities.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE); FirefoxProfile profile = new FirefoxProfile(); @@ -52,22 +49,22 @@ public class FirefoxUser extends BrowserUser { profile.setPreference("media.gmp-gmpopenh264.enabled", false); } - options.setCapability(FirefoxDriver.Capability.PROFILE, profile); + capabilities.setCapability(FirefoxDriver.PROFILE, profile); String REMOTE_URL = System.getProperty("REMOTE_URL_FIREFOX"); if (REMOTE_URL != null) { log.info("Using URL {} to connect to remote web driver", REMOTE_URL); try { - this.driver = new RemoteWebDriver(new URL(REMOTE_URL), options); + this.driver = new RemoteWebDriver(new URL(REMOTE_URL), capabilities); } catch (MalformedURLException e) { e.printStackTrace(); } } else { log.info("Using local web driver"); - this.driver = new FirefoxDriver(options); + this.driver = new FirefoxDriver(new FirefoxOptions(capabilities)); } - this.driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(timeOfWaitInSeconds)); + this.driver.manage().timeouts().setScriptTimeout(timeOfWaitInSeconds, TimeUnit.SECONDS); this.configureDriver(new org.openqa.selenium.Dimension(1920, 1080)); } diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/OperaUser.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/OperaUser.java index b68f89c1..d683377e 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/OperaUser.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/OperaUser.java @@ -2,12 +2,11 @@ package io.openvidu.test.browsers; import java.net.MalformedURLException; import java.net.URL; -import java.time.Duration; +import java.util.concurrent.TimeUnit; -import org.openqa.selenium.UnexpectedAlertBehaviour; import org.openqa.selenium.opera.OperaDriver; import org.openqa.selenium.opera.OperaOptions; -import org.openqa.selenium.remote.CapabilityType; +import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.RemoteWebDriver; public class OperaUser extends BrowserUser { @@ -15,13 +14,16 @@ public class OperaUser extends BrowserUser { public OperaUser(String userName, int timeOfWaitInSeconds) { super(userName, timeOfWaitInSeconds); + DesiredCapabilities capabilities = DesiredCapabilities.operaBlink(); + capabilities.setAcceptInsecureCerts(true); OperaOptions options = new OperaOptions(); - - options.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE); - options.setAcceptInsecureCerts(true); - options.addArguments("allow-file-access-from-files"); - options.addArguments("use-fake-device-for-media-stream"); - options.addArguments("use-fake-ui-for-media-stream"); + // This flag avoids to grant the user media + options.addArguments("--use-fake-ui-for-media-stream"); + // This flag fakes user media with synthetic video + options.addArguments("--use-fake-device-for-media-stream"); + // This flag selects the entire screen as video source when screen sharing + options.addArguments("--auto-select-desktop-capture-source=Entire screen"); + options.merge(capabilities); String REMOTE_URL = System.getProperty("REMOTE_URL_OPERA"); if (REMOTE_URL != null) { @@ -36,7 +38,7 @@ public class OperaUser extends BrowserUser { this.driver = new OperaDriver(options); } - this.driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(timeOfWaitInSeconds)); + this.driver.manage().timeouts().setScriptTimeout(timeOfWaitInSeconds, TimeUnit.SECONDS); this.configureDriver(new org.openqa.selenium.Dimension(1920, 1080)); } diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/BrowserNames.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/BrowserNames.java index 92d67413..f7e3a2eb 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/BrowserNames.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/BrowserNames.java @@ -2,6 +2,6 @@ package io.openvidu.test.browsers.utils; public enum BrowserNames { - CHROME, FIREFOX, OPERA, EDGE + CHROME, FIREFOX, OPERA, EDGE, ANDROID } diff --git a/openvidu-test-e2e/jenkins/commonFunctions.groovy b/openvidu-test-e2e/jenkins/commonFunctions.groovy index e4b244e5..f7c292d0 100644 --- a/openvidu-test-e2e/jenkins/commonFunctions.groovy +++ b/openvidu-test-e2e/jenkins/commonFunctions.groovy @@ -65,6 +65,9 @@ def prepareTestingEnvironment() { docker.image('selenium/standalone-edge:latest').pull() } }, + 'Pull budtmo/docker-android-x86-12.0': { + docker.image('budtmo/docker-android-x86-12.0:latest').pull() + }, 'Pull openvidu/mediasoup-controller': { if (env.MEDIASOUP_CONTROLLER_VERSION) { docker.image("openvidu/mediasoup-controller:${MEDIASOUP_CONTROLLER_VERSION}").pull() @@ -112,6 +115,7 @@ def removeStrandedContainers(removeTestingContainers) { "selenium/standalone-firefox:" "selenium/standalone-opera:" "selenium/standalone-edge:" + "budtmo/docker-android" "openvidu/mediasoup-controller:" "openvidu/openvidu-server-pro:" "openvidu/openvidu-redis:" 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 index 8df1affd..80fe1e67 100644 --- 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 @@ -7,11 +7,14 @@ 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; @@ -31,6 +34,7 @@ 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; @@ -42,6 +46,9 @@ 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; @@ -66,6 +73,12 @@ public class AbstractOpenViduTestAppE2eTest { @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(300)); + // Media server variables final protected static String KURENTO_IMAGE = "kurento/kurento-media-server"; final protected static String MEDIASOUP_IMAGE = "openvidu/mediasoup-controller"; @@ -101,7 +114,7 @@ public class AbstractOpenViduTestAppE2eTest { protected static final CommandLineExecutor commandLine = new CommandLineExecutor(); protected static final String RECORDING_IMAGE = "openvidu/openvidu-recording"; - private Collection users = new HashSet<>(); + protected Collection users = new HashSet<>(); protected volatile static boolean isRecordingTest; protected volatile static boolean isKurentoRestartTest; @@ -124,38 +137,56 @@ public class AbstractOpenViduTestAppE2eTest { } @SuppressWarnings("resource") - protected static void prepareBrowsers() { - if (isRemote(BrowserNames.CHROME)) { - chrome = new GenericContainer<>(DockerImageName.parse("selenium/standalone-chrome:" + CHROME_VERSION)) - .withSharedMemorySize(2147483648L).withFileSystemBind("/opt/openvidu", "/opt/openvidu"); - chrome.setPortBindings(Arrays.asList("6666:4444")); - chrome.withExposedPorts(4444); - } else { - WebDriverManager.chromedriver().setup(); + 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 (isRemote(BrowserNames.FIREFOX)) { - firefox = new GenericContainer<>(DockerImageName.parse("selenium/standalone-firefox:" + FIREFOX_VERSION)) - .withSharedMemorySize(2147483648L).withFileSystemBind("/opt/openvidu", "/opt/openvidu"); - firefox.setPortBindings(Arrays.asList("6667:4444")); - firefox.withExposedPorts(4444); - } else { - WebDriverManager.firefoxdriver().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 (isRemote(BrowserNames.OPERA)) { - opera = new GenericContainer<>(DockerImageName.parse("selenium/standalone-opera:" + OPERA_VERSION)) - .withSharedMemorySize(2147483648L).withFileSystemBind("/opt/openvidu", "/opt/openvidu"); - opera.setPortBindings(Arrays.asList("6668:4444")); - opera.withExposedPorts(4444); - } else { - WebDriverManager.operadriver().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 (isRemote(BrowserNames.EDGE)) { - edge = new GenericContainer<>(DockerImageName.parse("selenium/standalone-edge:" + EDGE_VERSION)) - .withSharedMemorySize(2147483648L).withFileSystemBind("/opt/openvidu", "/opt/openvidu"); - edge.setPortBindings(Arrays.asList("6669:4444")); - edge.withExposedPorts(4444); - } else { - WebDriverManager.edgedriver().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")) + .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")); } } @@ -265,67 +296,102 @@ public class AbstractOpenViduTestAppE2eTest { protected MyUser setupBrowser(String browser) { BrowserUser browserUser; + boolean isOpenViduTestApp = true; switch (browser) { case "chrome": - setupBrowserAux(BrowserNames.CHROME, CHROME_VERSION, chrome, WebDriverManager.chromedriver(), false); + setupBrowserAux(BrowserNames.CHROME, chrome, false); browserUser = new ChromeUser("TestUser", 50, false); break; case "firefox": - setupBrowserAux(BrowserNames.FIREFOX, FIREFOX_VERSION, firefox, WebDriverManager.firefoxdriver(), false); + setupBrowserAux(BrowserNames.FIREFOX, firefox, false); browserUser = new FirefoxUser("TestUser", 50, false); break; case "firefoxDisabledOpenH264": - setupBrowserAux(BrowserNames.FIREFOX, FIREFOX_VERSION, firefox, WebDriverManager.firefoxdriver(), false); + setupBrowserAux(BrowserNames.FIREFOX, firefox, false); browserUser = new FirefoxUser("TestUser", 50, true); break; case "opera": - setupBrowserAux(BrowserNames.OPERA, OPERA_VERSION, opera, WebDriverManager.operadriver(), false); + setupBrowserAux(BrowserNames.OPERA, opera, false); browserUser = new OperaUser("TestUser", 50); break; case "edge": - setupBrowserAux(BrowserNames.EDGE, EDGE_VERSION, edge, WebDriverManager.edgedriver(), false); + setupBrowserAux(BrowserNames.EDGE, edge, false); browserUser = new EdgeUser("TestUser", 50); break; case "chromeAlternateScreenShare": - setupBrowserAux(BrowserNames.CHROME, CHROME_VERSION, chrome, WebDriverManager.chromedriver(), false); + setupBrowserAux(BrowserNames.CHROME, chrome, false); browserUser = new ChromeUser("TestUser", 50, "OpenVidu TestApp", false); break; case "chromeAsRoot": - setupBrowserAux(BrowserNames.CHROME, CHROME_VERSION, chrome, WebDriverManager.chromedriver(), false); + 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"); + isOpenViduTestApp = false; + break; default: - setupBrowserAux(BrowserNames.CHROME, CHROME_VERSION, chrome, WebDriverManager.chromedriver(), false); + setupBrowserAux(BrowserNames.CHROME, chrome, false); browserUser = new ChromeUser("TestUser", 50, false); } MyUser user = new MyUser(browserUser); - 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(); + if (isOpenViduTestApp) { + 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; } - private void setupBrowserAux(BrowserNames browser, String version, GenericContainer container, - WebDriverManager webDriverManager, boolean forceRestart) { + private void setupBrowserAux(BrowserNames browser, GenericContainer container, boolean forceRestart) { if (isRemote(browser)) { if (forceRestart && container.isRunning()) { container.stop(); } if (!container.isRunning()) { container.start(); - container.waitingFor(Wait.forHttp("/wd/hub/status").forStatusCode(200)); } } } @@ -345,6 +411,8 @@ public class AbstractOpenViduTestAppE2eTest { case EDGE: remoteUrl = System.getProperty("REMOTE_URL_EDGE"); break; + case ANDROID: + return true; } return remoteUrl != null; } @@ -352,7 +420,7 @@ public class AbstractOpenViduTestAppE2eTest { protected MyUser setupChromeWithFakeVideo(String absolutePathToVideoFile) { if (isRemote(BrowserNames.CHROME)) { - setupBrowserAux(BrowserNames.CHROME, CHROME_VERSION, chrome, WebDriverManager.chromedriver(), true); + setupBrowserAux(BrowserNames.CHROME, chrome, true); } MyUser user = new MyUser(new ChromeUser("TestUser", 50, Paths.get(absolutePathToVideoFile))); @@ -402,6 +470,7 @@ public class AbstractOpenViduTestAppE2eTest { stopContainerIfPossible(firefox); stopContainerIfPossible(opera); stopContainerIfPossible(edge); + stopContainerIfPossible(android); // Reset REST client OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); } 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 c5cfd6fd..1f64cbce 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 @@ -4,6 +4,8 @@ import static org.junit.Assert.fail; import java.io.File; import java.io.FileReader; +import java.util.Arrays; +import java.util.HashSet; import java.util.Iterator; import java.util.Queue; import java.util.Set; @@ -43,6 +45,7 @@ import io.openvidu.java.client.OpenViduHttpException; import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.Recording; import io.openvidu.java.client.Session; +import io.openvidu.test.browsers.utils.BrowserNames; import io.openvidu.test.browsers.utils.CustomHttpClient; import io.openvidu.test.browsers.utils.Unzipper; @@ -54,7 +57,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { protected static void setupAll() { checkFfmpegInstallation(); loadEnvironmentVariables(); - prepareBrowsers(); + prepareBrowsers(new HashSet<>(Arrays.asList(BrowserNames.CHROME))); cleanFoldersAndSetUpOpenViduJavaClient(); } 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 78a8133c..49183a2e 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 @@ -23,6 +23,7 @@ import java.io.File; import java.util.Arrays; import java.util.Base64; import java.util.Collection; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -37,6 +38,7 @@ import java.util.stream.Collectors; import org.apache.http.HttpStatus; import org.junit.Assert; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -57,6 +59,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.mashape.unirest.http.HttpMethod; +import io.appium.java_client.AppiumDriver; import io.openvidu.java.client.Connection; import io.openvidu.java.client.ConnectionProperties; import io.openvidu.java.client.ConnectionType; @@ -75,6 +78,7 @@ import io.openvidu.java.client.RecordingProperties; import io.openvidu.java.client.Session; import io.openvidu.java.client.SessionProperties; import io.openvidu.java.client.VideoCodec; +import io.openvidu.test.browsers.utils.BrowserNames; import io.openvidu.test.browsers.utils.CustomHttpClient; import io.openvidu.test.browsers.utils.RecordingUtils; import io.openvidu.test.browsers.utils.layout.CustomLayoutHandler; @@ -96,7 +100,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { protected static void setupAll() throws Exception { checkFfmpegInstallation(); loadEnvironmentVariables(); - prepareBrowsers(); + prepareBrowsers(new HashSet<>(Arrays.asList(BrowserNames.CHROME, BrowserNames.FIREFOX, BrowserNames.OPERA, + BrowserNames.EDGE, BrowserNames.ANDROID))); cleanFoldersAndSetUpOpenViduJavaClient(); getDefaultTranscodingValues(); } @@ -133,6 +138,51 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { oneToOneAux(user); } + @Test + @DisplayName("One2One Chrome Android") + void oneToOneChromeAndroid() throws Exception { + long initTime = System.currentTimeMillis(); + MyUser user = setupBrowser("androidChrome"); + log.info("Android emulator ready after {} seconds", (System.currentTimeMillis() - initTime) / 1000); + log.info("One2One Android Chrome"); + onePublisherOneSubscriber(user); + } + + @Test + @DisplayName("One2One Firefox Android") + @Disabled + void oneToOneFirefoxAndroid() throws Exception { + long initTime = System.currentTimeMillis(); + MyUser user = setupBrowser("androidFirefox"); + log.info("Android emulator ready after {} seconds", (System.currentTimeMillis() - initTime) / 1000); + log.info("One2One Android Firefox"); + onePublisherOneSubscriber(user); + } + + @Test + @DisplayName("One2One Ionic Android") + @Disabled + void oneToOneIonicAndroid() throws Exception { + long initTime = System.currentTimeMillis(); + MyUser user = setupBrowser("androidApp"); + log.info("Android emulator ready after {} seconds", (System.currentTimeMillis() - initTime) / 1000); + log.info("One2One Ionic Android"); + + AppiumDriver appiumDriver = (AppiumDriver) user.getDriver(); + appiumDriver.findElement(By.cssSelector("#settings-button")).click(); + Thread.sleep(500); + WebElement urlInput = appiumDriver.findElement(By.cssSelector("#openvidu-url")); + urlInput.clear(); + urlInput.sendKeys(OPENVIDU_URL); + urlInput = appiumDriver.findElement(By.cssSelector("#openvidu-secret")); + urlInput.clear(); + urlInput.sendKeys(OPENVIDU_SECRET); + appiumDriver.findElement(By.cssSelector(".ok-btn")).click(); + Thread.sleep(500); + // Self signed cert over 172.17.0.1 problem + appiumDriver.findElement(By.cssSelector("#join-button")).click(); + } + private void oneToOneAux(MyUser user) throws Exception { user.getDriver().findElement(By.id("auto-join-checkbox")).click(); user.getDriver().findElement(By.id("one2one-btn")).click(); @@ -147,6 +197,24 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { gracefullyLeaveParticipants(user, 2); } + private void onePublisherOneSubscriber(MyUser 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(); + user.getDriver().findElements(By.className("join-btn")).forEach(el -> el.sendKeys(Keys.ENTER)); + + user.getEventManager().waitUntilEventReaches("connectionCreated", 4); + user.getEventManager().waitUntilEventReaches("accessAllowed", 1); + user.getEventManager().waitUntilEventReaches("streamCreated", 2); + user.getEventManager().waitUntilEventReaches("streamPlaying", 2); + + final int numberOfVideos = user.getDriver().findElements(By.tagName("video")).size(); + Assert.assertEquals("Wrong number of videos", 2, numberOfVideos); + Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager() + .assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true)); + gracefullyLeaveParticipants(user, 2); + } + @Test @DisplayName("One2One only audio") void oneToOneOnlyAudioSession() throws Exception { diff --git a/pom.xml b/pom.xml index f2100071..5f836c9d 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,7 @@ 4.13.1 5.7.0 1.7.0 - 4.0.0 + 3.141.59 3.6.0 2.0.9 2.2