30 Advanced WebDriver Tips and Tricks Kotlin Code

30 Advanced WebDriver Tips and Tricks Kotlin Code

This is the next article from the WebDriver Series where I will share with you 30 advanced tips and tricks using Java code. I wrote similar articles separated into 3 parts for C# - part 1, part 2, part 3. And for Java.

NOTE: This is the first post starting a new ERA for Automate The Planet. This is the first article dedicated to Kotlin. All 250+ publications were related to the .NET world. Of course, I will continue to write C#, VB.NET, Java articles, but I will put Kotlin in the mix.

1. Taking a Screenshot

You can use the following method to take a full-screen screenshot of the browser.

fun takeFullScreenshot(fileName: String) {
    val srcFile = (driver as TakesScreenshot).getScreenshotAs(OutputType.FILE)
    val tempDir = System.getProperty("java.io.tmpdir")
    val destFile = File(Paths.get(tempDir, "$fileName.png").toString())
    FileUtils.getFileUtils().copyFile(srcFile, destFile)
}

Sometimes you may need to take a screenshot of a single element.

fun takeScreenshotOfElement(element: WebElement, fileName: String) {
    val screenshotFile = (driver as TakesScreenshot).getScreenshotAs(OutputType.FILE)
    val fullImg = ImageIO.read(screenshotFile)
    val point = element.location
    val elementWidth = element.size.getWidth()
    val elementHeight = element.size.getHeight()
    val eleScreenshot = fullImg.getSubimage(point.getX(), point.getY(), elementWidth, elementHeight)
    ImageIO.write(eleScreenshot, "png", screenshotFile)
    val tempDir = System.getProperty("java.io.tmpdir")
    val destFile = File(Paths.get(tempDir, "$fileName.png").toString())
    FileUtils.getFileUtils().copyFile(screenshotFile, destFile)
}

First, we make a full-screen screenshot then we locate the specified element by its location and size attributes. After that, the found rectangle chunk is saved as a BufferedImage.

Here is how you use both methods in tests.

@Test
fun takeFullScreenshot_test() {
    driver.navigate().to("http://automatetheplanet.com")
    takeFullScreenshot("testImage")
}

@Test
fun takeElementScreenshot_test() {
    driver.navigate().to("http://automatetheplanet.com")
    val element =
        wait.until(
            ExpectedConditions.visibilityOfElementLocated(
                By.xpath("/html/body/div[1]/header/div/div[2]/div/div[2]/nav")
            )
        )
    takeScreenshotOfElement(element, "testElementImage")
}

We create a temp file combining the result from the static class Paths and getting the Windows temp folder through getProperty(“java.io.tmpdir”);

2. Get HTML Source of WebElement

You can use the getAttribute method of the WebElement interface to get the inner HTML of a specific element.

@Test
fun getHtmlSourceOfWebElement() {
    driver.navigate().to("http://automatetheplanet.com")
    val element =
        wait.until(
            ExpectedConditions.visibilityOfElementLocated(
                By.xpath("/html/body/div[1]/header/div/div[2]/div/div[2]/nav")
            )
        )
    val htmlSource = element.getAttribute("innerHTML")
    System.out.println(htmlSource)
}

While ago, when we were working on the first version of our open-source BELLATRIX test automation framework, I did this research, and afterward, we used many of the tricks in lots of the features of our solution.

3. Execute JavaScript

You can use the interface JavaScriptExecutor to execute JavaScript through WebDriver.

@Test
fun executeJavaScript() {
    driver.navigate().to("http://automatetheplanet.com")
    val javascriptExecutor = driver as JavascriptExecutor
    val title = javascriptExecutor.executeScript("return document.title") as String
    println(title)
}

This test will take the current window’s title via JavaScript and print it to the output window.

4. Set Page Load Timeout

There are at least three methods that you can use for the job.

First, you can set the default driver’s page load timeout through the WebDriver’s options class.

driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS)

You can wait until the page is completely loaded via JavaScript.

private fun waitUntilLoaded() {
    wait.until { x: WebDriver ->
        val javascriptExecutor = driver as JavascriptExecutor
        val isReady = javascriptExecutor.executeScript("return document.readyState") as String
        isReady == "complete"
    }
}

Your third option is to wait for a specific element(s) to be visible on the page.

wait.until(
    ExpectedConditions.visibilityOfAllElements(
        driver.findElements(By.xpath("//\*[@id='tve_editor']/div[2]/div[2]/div/div"))
    )
)

5. Execute Tests in a Headless Browser

You can use the ChromeOptions class and set a few arguments to set up Chrome to run without its UI in the so-called headless mode. You can do the same for Firefox and Edge Chromium.

val chromeOptions = ChromeOptions()

chromeOptions.addArguments(
    "--headless",
    "--disable-gpu",
    "--window-size=1920,1200",
    "--ignore-certificate-errors"
)

driver = ChromeDriver(chromeOptions)

6. Check If an Element Is Visible

You can use the isDisplayed method of the WebElement interface.

@Test
fun checkIfElementIsVisible() {
    driver.navigate().to("http://automatetheplanet.com")
    val element = driver.findElement(By.xpath("/html/body/div[1]/header/div/div[2]/div/div[2]/nav"))
    Assert.assertTrue(element.isDisplayed)
}

7. Use Specific Profile

By default, WebDriver always assigns a new ‘clean’ profile if you use the FirefoxDriver default constructor. However, sometimes you may want to fine-tune the profile e.g., add extensions, turn off the JavaScript, etc.

val profile = ProfilesIni()
val firefoxProfile = profile.getProfile("xyzProfile")
val firefoxOptions = FirefoxOptions()

firefoxOptions.setProfile(firefoxProfile)

val firefoxDriver: WebDriver = FirefoxDriver(firefoxOptions)

You can do some similar configurations for the ChromeDriver.

val chromeOptions = ChromeOptions()

chromeOptions.addArguments("user-data-dri=C:UsersYour path to userRoamingGoogleChromeUser Data")

driver = ChromeDriver(chromeOptions)ß

8. Turn Off JavaScript

You can use the code from point 7 to set up a new Firefox profile. Then you need to set the ‘javascript.enabled’ preference to false.

val profile = ProfilesIni()
val firefoxProfile = profile.getProfile("xyzProfile")
val firefoxOptions = FirefoxOptions()

firefoxProfile.setPreference("javascript.enabled", false)

firefoxOptions.setProfile(firefoxProfile)

val firefoxDriver: WebDriver = FirefoxDriver(firefoxOptions

9. Manage Cookies

Before you can work with the cookies of a site, you need to navigate to some of its pages.

@Test
fun manageCookies() {
    driver.navigate().to("http://automatetheplanet.com")
    // get all cookies
    val cookies = driver.manage().cookies
    for (cookie in cookies) {
        println(cookie.name)
    }
    // get a cookie by name
    val fbPixelCookie = driver.manage().getCookieNamed("\_fbp")
    // create a new cookie by name
    val newCookie = Cookie("customName", "customValue")
    driver.manage().addCookie(newCookie)
    // delete a cookie
    driver.manage().deleteCookie(fbPixelCookie)
    // delete a cookie by name
    driver.manage().deleteCookieNamed("customName")
    // delete all cookies
    driver.manage().deleteAllCookies()
}

10. Maximize Window

Use the maximize method of the Window interface.

driver.manage().window().maximize()

11. Drag and Drop

You can use the special Actions WebDriver class to perform complex UI interactions. Through its method dragAndDropBy, you can drag and drop. You only need to set the desired X and Y offsets.

@Test
fun dragAndDrop() {
    driver.navigate().to("http://loopj.com/jquery-simple-slider/")
    val element = driver.findElement(By.xpath("//\*[@id='project']/p[1]/div/div[2]"))
    val action = Actions(driver)
    action.dragAndDropBy(element, 30, 0).build().perform()
}

12. Upload a File

It is a straightforward task to upload a file using WebDriver. You need to locate the file element and use the WebElement’s sendKeys method to set the path to your file.

@Test
fun fileUpload() {
    driver
        .navigate()
        .to(
            "https://demos.telerik.com/aspnet-ajax/ajaxpanel/application-scenarios/file-upload/defaultcs.aspx"
        )
    val element = driver.findElement(By.id("ctl00_ContentPlaceholder1_RadUpload1file0"))
    val filePath = Paths.get(System.getProperty("java.io.tmpdir"), "debugWebDriver.xml").toString()
    val destFile = File(filePath)
    destFile.createNewFile()
    element.sendKeys(filePath)
}

13. Handle JavaScript Pop-ups

You can use the accept and dismiss methods of the Alert interface to handle JavaScript pop-ups. First, you need to use the switchTo method to switch to the alert.

@Test
fun handleJavaScripPopUps() {
    driver.navigate().to("http://www.w3schools.com/js/tryit.asp?filename=tryjs_confirm")
    driver.switchTo().frame("iframeResult")
    val button = driver.findElement(By.xpath("/html/body/button"))
    button.click()
    val alert = driver.switchTo().alert()
    if (alert.text == "Press a button!") {
        alert.accept()
    } else {
        alert.dismiss()
    }
}

14. Switch Between Browser Windows or Tabs

WebDriver drives the browser within a scope of one browser window. However, we can use its switchTo method to change the target window or tab.

@Test
fun movingBetweenTabs() {
    driver.navigate().to("https://www.automatetheplanet.com/")
    val firstLink = driver.findElement(By.xpath("//_[@id='menu-item-11362']/a"))
    val secondLink = driver.findElement(By.xpath("//_[@id='menu-item-6']/a"))
    val selectLinkOpenninNewTab = Keys.chord(Keys.CONTROL, Keys.RETURN)
    firstLink.sendKeys(selectLinkOpenninNewTab)
    secondLink.sendKeys(selectLinkOpenninNewTab)
    val windows = driver.windowHandles
    val firstTab = windows.toTypedArray()[1] as String
    val lastTab = windows.toTypedArray()[2] as String
    driver.switchTo().window(lastTab)
    Assert.assertEquals("Resources - Automate The Planet", driver.title)
    driver.switchTo().window(firstTab)
    Assert.assertEquals("Blog - Automate The Planet", driver.title)
}

The getWindowHandles method returns all open browser windows. You can pass the name of the desired tab/window to the window method of the TargetLocator interface (returned by the switchTo method) to change the current target.

You can also notice that we use one more trick to open the link in a new tab using the Keys.chord method, and then instead of clicking, we use the sendKeys method to perform CTRL + return sequence.

15. Navigation History

WebDriver Navigation interface contains handy methods for going forward and backward. Also, you can refresh the current page.

@Test
fun navigationHistory() {
    driver
        .navigate()
        .to("https://www.codeproject.com/Articles/1078541/Advanced-WebDriver-Tips-and-Tricks-Part")
    driver
        .navigate()
        .to(
            "http://www.codeproject.com/Articles/1017816/Speed-up-Selenium-Tests-through-RAM-Facts-and-Myth"
        )
    driver.navigate().back()
    Assert.assertEquals(
        "10 Advanced WebDriver Tips and Tricks - Part 1 - CodeProject",
        driver.title
    )
    driver.navigate().refresh()
    Assert.assertEquals(
        "10 Advanced WebDriver Tips and Tricks - Part 1 - CodeProject",
        driver.title
    )
    driver.navigate().forward()
    Assert.assertEquals(
        "Speed up Selenium Tests through RAM Facts and Myths - CodeProject",
        driver.title
    )
}

16. Change User Agent

After you create a new custom Firefox profile, you can set its argument ‘general.useragent.override’ to the desired user agent string.

val profile = ProfilesIni()
val firefoxProfile = profile.getProfile("xyzProfile")
val firefoxOptions = FirefoxOptions()

firefoxProfile.setPreference(
    "general.useragent.override",
    "Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.346 Mobile Safari/534.11+"
)

firefoxOptions.setProfile(firefoxProfile)

val firefoxDriver: WebDriver = FirefoxDriver(firefoxOptions)

17. Set HTTP Proxy for Browser

Similar to the user agent configuration, to set a proxy for Firefox, you only need to set a few arguments of the Firefox’ profile.

val profile = ProfilesIni()
val firefoxProfile = profile.getProfile("xyzProfile")

firefoxProfile.setPreference("network.proxy.type", 1)

firefoxProfile.setPreference("network.proxy.http", "myproxy.com")

firefoxProfile.setPreference("network.proxy.http_port", 3239)

val firefoxOptions = FirefoxOptions()

firefoxOptions.setProfile(firefoxProfile)

val firefoxDriver: WebDriver = FirefoxDriver(firefoxOptions)

18. Handle SSL Certificate Error

8.1. Handle SSL Certificate Error FirefoxDriver

val profile = ProfilesIni()
val firefoxProfile = profile.getProfile("xyzProfile")

firefoxProfile.setAcceptUntrustedCertificates(true)

firefoxProfile.setAssumeUntrustedCertificateIssuer(false)

val firefoxOptions = FirefoxOptions()

firefoxOptions.setProfile(firefoxProfile)
val firefoxDriver: WebDriver = FirefoxDriver(firefoxOptions);

8.2. Handle SSL Certificate Error ChromeDriver

val chromeOptions = ChromeOptions()

chromeOptions.addArguments("--ignore-certificate-errors")

driver = ChromeDriver(chromeOptions)ß

19. Scroll Focus to Control

There isn’t a built-in mechanism in WebDriver to scroll focus to a control. However, you can use the JavaScript’s method window.scroll. You only need to pass the getY location of the desired element.

@Test
fun scrollFocusToControl() {
    driver.navigate().to("http://automatetheplanet.com/")
    val ourMissionLink = driver.findElement(By.xpath("//\*[@id='panel-6435-0-0-4']/div"))
    val jsToBeExecuted = "window.scroll(0, ${ourMissionLink.location.getY()});"
    val javascriptExecutor = driver as JavascriptExecutor
    javascriptExecutor.executeScript(jsToBeExecuted)
}

20. Focus on a Control

To do the trick, we use again the special Actions class, which has a method called moveToElement.

@Test
fun focusOnControl() {
    driver.navigate().to("http://automatetheplanet.com/")
    waitUntilLoaded()
    val ourMissionLink = driver.findElement(By.xpath("//\*[@id='panel-6435-0-0-4']/div"))
    val action = Actions(driver)
    action.moveToElement(ourMissionLink).build().perform()
}

21. Start FirefoxDriver with Plugins

Just use the addExtension of the FirefoxProfile class to load the desired extension.

val profile = ProfilesIni()
val firefoxProfile = profile.getProfile("xyzProfile")

firefoxProfile.addExtension(File("C:extensionsLocationextension.xpi"))

val firefoxOptions = FirefoxOptions()

firefoxOptions.setProfile(firefoxProfile)

val firefoxDriver: WebDriver = FirefoxDriver(firefoxOptions)

22. Set HTTP Proxy ChromeDriver

The configuration of a proxy for ChromeDriver is a little bit different from the one for  FirefoxDriver. You need to use the special Proxy class in combination with ChromeOptions.

val chromeOptions = ChromeOptions()

val proxy = Proxy()

proxy.proxyType = Proxy.ProxyType.MANUAL

proxy.isAutodetect = false

proxy.sslProxy = "127.0.0.1:3239"

chromeOptions.setProxy(proxy)

driver = ChromeDriver(chromeOptions)

23. Set HTTP Proxy with Authentication ChromeDriver

The only difference from the previous example is the configuration of the —proxy-server argument.

var proxy = new Proxy();
proxy.setProxyType(Proxy.ProxyType.MANUAL);
proxy.setAutodetect(false);
proxy.setSslProxy("127.0.0.1:3239");
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setProxy(proxy);
chromeOptions.addArguments("--proxy-server=http://user:password@127.0.0.1:3239");
driver = new ChromeDriver(chromeOptions);

24. Start ChromeDriver with an Unpacked Extension

Chrome extensions can be either packed or unpacked. Packed extensions are a single file with a .crx extension. Unpacked Extensions are a directory containing the extension, including a manifest.json file. To load an unpacked extension you need to set the load-extension argument.

val chromeOptions = ChromeOptions()

chromeOptions.addArguments("load-extension=/pathTo/extension")

driver = ChromeDriver(chromeOptions)

25. Start ChromeDriver with an Packed Extension

Instead of setting the load-extension argument, you need to use the addExtension method of the ChromeOptions class to set the path to your packed extension.

val chromeOptions = ChromeOptions()

chromeOptions.addArguments("load-extension=/pathTo/extension")

driver = ChromeDriver(chromeOptions)

26. Assert a Button Enabled or Disabled

You can check if an element is disabled through the isEnabled method of the WebElement interface.

@Test
fun assertButtonEnabledDisabled() {
    driver.navigate().to("http://www.w3schools.com/tags/tryit.asp?filename=tryhtml_button_disabled")
    driver.switchTo().frame("iframeResult")
    val button = driver.findElement(By.xpath("/html/body/button"))
    Assert.assertFalse(button.isEnabled)
}

27. Set and Assert the Value of a Hidden Field

You can get the value of a hidden field through the getAttribute method, part of the WebElement interface. Get the value attribute of the element. You can set the same attribute with a little bit of a JavaScript code.

@Test
fun setHiddenField() {
    // <input type="hidden" name="country" value="Bulgaria"/>
    val theHiddenElem = driver.findElement(By.name("country"))
    val javascriptExecutor = driver as JavascriptExecutor?
    javascriptExecutor!!.executeScript("arguments[0].value='Germany';", theHiddenElem)
    val hiddenFieldValue = theHiddenElem.getAttribute("value")
    Assert.assertEquals("Germany", hiddenFieldValue)
}

28. Wait AJAX Call to Complete Using JQuery

jQuery.active is a variable JQuery uses internally to track the number of simultaneous AJAX requests. Wait until the value of jQuery.active is zero. Then continue with the next operation.

private fun waitForAjaxComplete() {
    wait.until { x: WebDriver ->
        val javascriptExecutor = driver as JavascriptExecutor
        val isAjaxCallComplete =
            javascriptExecutor.executeScript(
                "return window.jQuery != undefined && jQuery.active == 0"
            ) as Boolean
        isAjaxCallComplete
    }
}

29. Verify File Downloaded ChromeDriver

To change the default download directory of the current Chrome instance set the download.default_directory argument. When we initiate the file download, we use the WebDriverWait to wait until the file exists on the file system. Finally, we assert the file size. The whole code is surrounded with a try-finally block. In the finally we delete the downloaded file so that our test to be consistent every time.

val chromePrefs = HashMap<String, Any>()

chromePrefs["profile.default_content_settings.popups"] = 0

chromePrefs["download.default_directory"] = "downloadFilepath"

chromeOptions.setExperimentalOption("prefs", chromePrefs)

chromeOptions.addArguments("--test-type")

chromeOptions.addArguments("start-maximized", "disable-popup-blocking")

val chromeOptions = ChromeOptions()

driver = ChromeDriver(chromeOptions)

@Test
fun VerifyFileDownloadChrome() {
    val expectedFilePath = Paths.get("c:tempTesting_Framework_2015_3_1314_2_Free.exe")
    try {
        driver
            .navigate()
            .to("https://www.telerik.com/download-trial-file/v2/telerik-testing-framework")
        wait.until { x: WebDriver -> Files.exists(expectedFilePath) }
        val bytes = Files.size(expectedFilePath)
        Assert.assertEquals(4326192, bytes)
    } finally {
        if (Files.exists(expectedFilePath)) Files.delete(expectedFilePath)
    }
}

30. Verify File Downloaded FirefoxDriver

The code for FirefoxDriver is similar to the one for ChromeDriver. We need to set a few arguments so that the browser not to ask us every time where to save the specified file.

val downloadFilepath = "c:temp"
val profile = ProfilesIni()
val firefoxProfile = profile.getProfile("xyzProfile")

firefoxProfile.setPreference("browser.download.folderList", 2)

firefoxProfile.setPreference("browser.download.dir", downloadFilepath)

firefoxProfile.setPreference("browser.download.manager.alertOnEXEOpen", false)

firefoxProfile.setPreference(
    "browser.helperApps.neverAsk.saveToDisk",
    "application/msword, application/binary, application/ris, text/csv, image/png, application/pdf, text/html, text/plain, application/zip, application/x-zip, application/x-zip-compressed, application/download, application/octet-stream"
)

firefoxOptions.setProfile(firefoxProfile)

val firefoxOptions = FirefoxOptions()

firefoxOptions.setProfile(firefoxProfile)

val firefoxDriver: WebDriver = FirefoxDriver(firefoxOptions)

Related Articles

Web Automation Java

Design Grid Control Automated Tests with Java Part 1

In the previous article, I showed you how to automate complex custom-tuned controls like a grid. In my article Automate Telerik Kendo Grid with WebDriver and Ja

Design Grid Control Automated Tests with Java Part 1

Resources, Web Automation Java

Most Complete Selenium WebDriver Java Cheat Sheet

As you know, I am a big fan of Selenium WebDriver. You can find tonnes of useful Java code in my Web Automation Java Series. I lead automated testing courses an

Most Complete Selenium WebDriver Java Cheat Sheet

Java, Kotlin, Mobile Automation Java

Getting Started with Appium for Android Kotlin on macOS in 10 Minutes

The third article from the Appium Series is going to be about testing Android apps on macOS machine. I am going to show you how to configure your macOS machine

Getting Started with Appium for Android Kotlin on macOS in 10 Minutes

Design Architecture Java, Design Patterns Java, Java

Advanced Strategy Design Pattern in Automated Testing Java Code

In this part of the Design Pattern Series, I’m going to extend my ideas about the application of the Strategy Design Pattern in automation tests. In my previous

Advanced Strategy Design Pattern in Automated Testing Java Code

Design Architecture Java, Design Patterns Java, Java

Page Object Pattern in Automated Testing Java Code

In the series of articles Design Patterns in Automated Testing, I am presenting the most useful techniques for structuring the code of your automation tests. On

Page Object Pattern in Automated Testing Java Code

Resources, Web Automation Java

Most Complete Selenium WebDriver Kotlin Cheat Sheet

As you know, I am a big fan of Selenium WebDriver. You can find tones of useful Kotlin/Java code in my Web Automation Java Series. I lead automated testing cour

Most Complete Selenium WebDriver Kotlin Cheat Sheet
Anton Angelov

About the author

Anton Angelov is Managing Director, Co-Founder, and Chief Test Automation Architect at Automate The Planet — a boutique consulting firm specializing in AI-augmented test automation strategy, implementation, and enablement. He is the creator of BELLATRIX, a cross-platform framework for web, mobile, desktop, and API testing, and the author of 8 bestselling books on test automation. A speaker at 60+ international conferences and researcher in AI-driven testing and LLM-based automation, he has been recognized as QA of the Decade and Webit Changemaker 2025.