Skip to content

Commit

Permalink
Allow WebDriver to use different Selenium drivers (#2225)
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitry-zaitsev authored Jan 5, 2025
1 parent 5c57e6e commit 4c71c7b
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 38 deletions.
56 changes: 20 additions & 36 deletions maestro-client/src/main/java/maestro/drivers/WebDriver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,15 @@ import maestro.ViewHierarchy
import maestro.utils.ScreenshotUtils
import maestro.web.record.JcodecVideoEncoder
import maestro.web.record.WebScreenRecorder
import maestro.web.selenium.ChromeSeleniumFactory
import maestro.web.selenium.SeleniumFactory
import okio.Sink
import okio.buffer
import org.openqa.selenium.By
import org.openqa.selenium.JavascriptExecutor
import org.openqa.selenium.Keys
import org.openqa.selenium.OutputType
import org.openqa.selenium.TakesScreenshot
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeDriverService
import org.openqa.selenium.chrome.ChromeOptions
import org.openqa.selenium.chromium.ChromiumDriverLogLevel
import org.openqa.selenium.devtools.HasDevTools
import org.openqa.selenium.devtools.v130.emulation.Emulation
import org.openqa.selenium.interactions.Actions
Expand All @@ -35,11 +33,12 @@ import org.slf4j.LoggerFactory
import java.io.File
import java.time.Duration
import java.util.*
import java.util.logging.Level
import java.util.logging.Logger


class WebDriver(val isStudio: Boolean) : Driver {
class WebDriver(
val isStudio: Boolean,
private val seleniumFactory: SeleniumFactory = ChromeSeleniumFactory()
) : Driver {

private var seleniumDriver: org.openqa.selenium.WebDriver? = null
private var maestroWebScript: String? = null
Expand All @@ -61,33 +60,18 @@ class WebDriver(val isStudio: Boolean) : Driver {
}

override fun open() {
System.setProperty("webdriver.chrome.silentOutput", "true")
System.setProperty(ChromeDriverService.CHROME_DRIVER_SILENT_OUTPUT_PROPERTY, "true")
Logger.getLogger("org.openqa.selenium").level = Level.OFF
Logger.getLogger("org.openqa.selenium.devtools.CdpVersionFinder").level = Level.OFF

val driverService = ChromeDriverService.Builder()
.withLogLevel(ChromiumDriverLogLevel.OFF)
.build()

seleniumDriver = ChromeDriver(
driverService,
ChromeOptions().apply {
addArguments("--remote-allow-origins=*")
addArguments("--disable-search-engine-choice-screen")
addArguments("--lang=en")
if (isStudio) {
addArguments("--headless=new")
addArguments("--window-size=1024,768")
setExperimentalOption("detach", true)
}
}
)
seleniumDriver = seleniumFactory.create(isStudio)

seleniumDriver
?.let { it as? HasDevTools }
?.devTools
?.createSessionIfThereIsNotOne()
try {
seleniumDriver
?.let { it as? HasDevTools }
?.devTools
?.createSessionIfThereIsNotOne()
} catch (e: Exception) {
// Swallow the exception to avoid crashing the whole process.
// Some implementations of Selenium do not support DevTools
// and do not fail gracefully.
}

if (isStudio) {
seleniumDriver?.get("https://maestro.mobile.dev")
Expand Down Expand Up @@ -190,9 +174,9 @@ class WebDriver(val isStudio: Boolean) : Driver {
}

override fun stopApp(appId: String) {
val driver = ensureOpen()

driver.close()
// Not supported at the moment.
// Simply calling driver.close() can kill the Selenium session, rendering
// the driver inoperable.
}

override fun killApp(appId: String) {
Expand Down
4 changes: 2 additions & 2 deletions maestro-web/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ plugins {
dependencies {
implementation(libs.square.okio)

implementation(libs.selenium)
implementation(libs.selenium.devtools)
api(libs.selenium)
api(libs.selenium.devtools)
implementation(libs.jcodec)
implementation(libs.jcodec.awt)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package maestro.web.selenium

import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeDriverService
import org.openqa.selenium.chrome.ChromeOptions
import org.openqa.selenium.chromium.ChromiumDriverLogLevel
import java.util.logging.Level
import java.util.logging.Logger

class ChromeSeleniumFactory : SeleniumFactory {

override fun create(
isStudio: Boolean
): WebDriver {
System.setProperty("webdriver.chrome.silentOutput", "true")
System.setProperty(ChromeDriverService.CHROME_DRIVER_SILENT_OUTPUT_PROPERTY, "true")
Logger.getLogger("org.openqa.selenium").level = Level.OFF
Logger.getLogger("org.openqa.selenium.devtools.CdpVersionFinder").level = Level.OFF

val driverService = ChromeDriverService.Builder()
.withLogLevel(ChromiumDriverLogLevel.OFF)
.build()

return ChromeDriver(
driverService,
ChromeOptions().apply {
addArguments("--remote-allow-origins=*")
addArguments("--disable-search-engine-choice-screen")
addArguments("--lang=en")
if (isStudio) {
addArguments("--headless=new")
addArguments("--window-size=1024,768")
setExperimentalOption("detach", true)
}
}
)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package maestro.web.selenium

import org.openqa.selenium.WebDriver

interface SeleniumFactory {

fun create(
isStudio: Boolean = false
): WebDriver

}

0 comments on commit 4c71c7b

Please sign in to comment.