As developers, we always look for ways to make our work easier so we can focus on more exciting projects or learn new things. A big part of this is finding ways to quickly test our work, like new features or bug fixes, to ensure everything runs smoothly. This is where Selenium WebDriver comes in handy. It’s a great tool for testing web pages. In this article, we’ll explore how to execute JavaScript on a website when using Selenium Webdriver in C# to test web pages.

To download the source code for this article, you can visit our GitHub repository.

Let’s start.

What Is Selenium

Selenium WebDriver is a handy toolbox for automating the testing of web applications. It’s an open-source API allowing us to create and execute test cases across browsers.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

Here are some of the key features that we can leverage:

  • Cross-Browser Testing
  • Handling Dynamic Web Elements
  • Integration with Testing Frameworks
  • Support for Page Object Model
  • Alerts and Popups Handling
  • JavaScript Code Execution
  • Simulating Keyboard and Mouse Events
  • Screenshot Capability

For a deeper dive into implementing Selenium WebDriver for UI testing in ASP.NET Core applications, check out Automated UI Tests with Selenium and ASP.NET Core.

Let’s explore the JavaScript capabilities of Selenium for a simple webpage.

Creating the Project With Webdriver

The first step is to set up our project. We’ll start by installing the necessary packages and setting up our testing environment. This involves choosing the right testing framework that suits our needs like xUnit, setting up the Selenium WebDriver, and configuring our project to run the tests.

Now we are going to open the NuGet Package Manager window and install the required libraries, Selenium.WebDriverand Selenium.WebDriver.ChromeDriver for manipulation with web pages, DotNetSeleniumExtras.WaitHelpers for enhancing synchronization capabilities, and FluentAssertions for providing easier-to-understand and clearer checks in tests:

PM> NuGet\Install-Package Selenium.WebDriver 
PM> NuGet\Install-Package Selenium.WebDriver.ChromeDriver
PM> NuGet\Install-Package DotNetSeleniumExtras.WaitHelpers
PM> NuGet\Install-Package FluentAssertions

That’s everything needed. Now, we are ready to create automated UI tests.

Direct DOM Manipulation Using Javascript With Selenium Webdriver

Sometimes, standard methods fall short when we need to interact with certain web elements. That’s where Direct DOM Manipulation steps in, with the strengths of Selenium WebDriver and JavaScript. This technique allows to reach and modify elements on a webpage that are otherwise hard to access, providing a more versatile approach to web interaction:

_driver.Navigate().GoToUrl(_webUrl + "/Home/Index");

var jsExecutor = (IJavaScriptExecutor)_driver;
var hiddenElement = _driver.FindElement(By.Id("hidden-element"));
hiddenElement.GetCssValue("display").Should().Be("none");

jsExecutor.ExecuteScript("document.getElementById('hidden-element').style.display='block';");

var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(5));
wait.Until(ExpectedConditions.ElementIsVisible(By.Id("hidden-element")));

hiddenElement.GetCssValue("display").Should().Be("block");

We begin by accessing a URL using _driver.Navigate().GoToUrl(_webUrl + "/Home/Index"). Then, we use IJavaScriptExecutor to help us find and change parts of the webpage that are usually hidden.

First, we find a hidden element and ensure that it’s initially not displayed with Should() and Be("none") methods. We then execute the JavaScript to make the hidden element visible.

Following this, we wait for a maximum of 5 seconds. During this pause, the webpage updates and reveals the hidden element. We employ WebDriverWait to manage this waiting period. Then, we perform another check. If the 'display' property is 'block', it means the hidden element has become visible.

This approach lets us interact with and check hidden parts of a webpage.

Workarounds for Limitations When Executing JavaScript

Let’s write another test to address challenges often encountered in web automation, particularly those related to element interaction.

We will consider a scenario where standard Selenium methods fail due to specific browser behaviors or complex web page structures:

_driver.Navigate().GoToUrl(_webUrl + "/Home/Index");

var button = _driver.FindElement(By.Id("testButton"));

var js = (IJavaScriptExecutor)_driver;
js.ExecuteScript("arguments[0].click();", button);

Here, we target a button with the ID testButton via _driver.FindElement(By.Id("testButton")). However, instead of using Selenium’s usual click method, we use IJavaScriptExecutor. We can make the button click happen directly:

js.ExecuteScript("arguments[0].click();", button)

Using Selenium WebDriver to execute javascript in this example allows us to avoid any problems that might come up with the usual methods. This approach not only enhances the robustness of our testing strategies but also shows the flexibility of Selenium in handling complex web interactions.

Custom Synchronization Using JavaScript

In cases where content is dynamically loaded, some elements on a webpage may not be immediately visible after page load, leading to potential script failures. To handle this we use WebDriverWait and JavaScript execution capabilities can be used to ensure elements are fully loaded and ready for interaction:

_driver.Navigate().GoToUrl(_webUrl + "/Home/Sync");

var js = (IJavaScriptExecutor)_driver;
var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(10));
wait.Until(d => (bool)js.ExecuteScript("return document.readyState === 'complete';"));

wait.Until(ExpectedConditions.TextToBePresentInElementLocated(By.Id("dynamicContent"), "Content Loaded"));

var dynamicContent = _driver.FindElement(By.Id("dynamicContent"));
dynamicContent.Text.Should().Be("Content Loaded");

We initiate navigation to the specified URL "/Home/Sync", and then establish a JavaScriptExecutor instance. We create a WebDriverWait object, setting a maximum wait time of 10 seconds. The script then actively waits until the entire document is ready, which is a key step to ensure that the page has fully loaded, including any dynamically generated content.

Next, we implement an additional wait condition to specifically check for the presence of the text "Content Loaded" within an element identified by the ID "dynamicContent". This step is crucial as it confirms that the dynamically loaded content is now rendered and visible on the page.

Finally, we retrieve the dynamic content from the element and validate its text, verifying that the dynamic content has been loaded correctly. This validation step is essential to ensure robust and accurate synchronization with the web page’s dynamic behavior, particularly in scenarios involving asynchronous content loading.

Conclusion

We’ve seen how Selenium WebDriver is a powerful tool for anyone working with web automation. From simple tasks like changing how elements look on a page to more complex ones like dealing with pages that load content differently, Selenium helps us manage it all. It’s especially useful for making sure our automation scripts work well with web pages that don’t load all their content immediately. Using Selenium WebDriver to execute JavaScript, we can make our testing more effective and less of a headache. Selenium offers handy solutions for a wide range of web testing needs for new and experienced engineers. It’s a great resource that makes web automation simpler and more efficient. So, let’s keep learning and experimenting!

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!