Creating synchronous automation in Selenium: A step-by-step guide

I am feeling increasingly frustrated at the moment and I am hoping to seek assistance on stackexchange.

First and foremost, I must admit that I am not a seasoned Javascript developer, probably not even an experienced developer overall, but I do have some knowledge of basic scripting languages like C# and Java. For my current web automation script, I decided to venture into writing in Javascript, but now I am seriously contemplating starting over with a less confusing language.

Could someone please advise me on how I can ensure that my code is executed synchronously from top to bottom?

After spending countless hours googling, here are some attempts I have made:

  • Added #! /usr/bin/env node at the beginning of line 1 and started it in the terminal using ./app.js
  • Converted every function to an async function
  • Used await on all methods

Despite these efforts, when I run the script, I encounter multiple instances of

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'isDisplayed' of undefined
and similar issues, indicating that Node is running some of my methods/functions asynchronously. These exceptions appear in the console long before the browser window is loaded.

The tools and versions I am using include: * selenium-webdriver 3.6.0 * Firefox 60.0.2 * node 8.10.0

This is a snippet of what my code looks like:

// JavaScript code goes here...
// More code sample provided...

In essence, as far as my understanding goes, I initiate the webdriver and Firefox with my async init() function. Within this function, I utilize await for all the methods. Following the initiation of the webdriver/Firefox, I assign the Object variables to the locations (which I want to happen once the browser is fully loaded).

However, for some reason unknown to me, the script appears to execute all functions and code it encounters immediately after starting. It seems to wait until the browser has fully loaded last. Prior to the complete loading, I receive several UnhandledPromiseRejectionWarning messages..

  • UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'sendKeys' of undefined
  • UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'click' of undefined
  • UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'isDisplayed' of undefined

Any help or guidance on this matter would be greatly appreciated.

Answer №1

To achieve purely synchronous execution in async/await functions, it appears that only one function should be allowed to run at a time.

Instead of calling init(); for browser initialization and then later running run(); for automation, it is recommended to create a small function called main() that calls both functions:

async main(){
  await init;
  await run();
}
main();

This approach seems to resolve the issue with asynchronous runs. However, there may still be complications with await driver.sleep(1000);, as it does not work as intended.

Further research led me to references about explicit waits and webdriver-sync. Though the latter is considered outdated, I plan to explore its capabilities.

If anyone has insights on resolving issues like the ineffective use of await driver.sleep(1000); within a loop structure, such as:

array.forEach(async function(entry){
  for(){
    for(){
      await driver.sleep(1000);
    }
  }
}

I would greatly appreciate any advice or suggestions.

Answer №2

Your implementation of the await keyword is on the right track, but you need to adjust how you use the .then method. In this case, .then expects a function (or two) as an argument. You are currently making function calls inside then() which results in passing the result of that function call rather than the function itself.

async function setup(){
    let options = await new firefox.Options()
    .setProfile('/home/ruphus/.mozilla/firefox/selenium_profile.backtesting');

    let driver = await new webdriver.Builder()
        .forBrowser('firefox')
        .setFirefoxOptions(options)
        .build();
    await driver.get('https://www.someurl.com/')
        .then(openStrategySettings)  // <-- Pass the function instead
        .then(() => btnStrategySettings.click());  // <-- Arrow functions come handy when the argument isn't just a plain function name 

// ... Define webelements/locations for the previously created objects using xpath

inputPeriod = await driver.findElement(By.xpath("//div[@id='header-toolbar-intervals']/div/div/div"));
}


async function openStrategySettings() {
    if (! await someWebelement.isDisplayed()){  // <-- Ensure to await the settlement of isDisplayed(), which returns a Promise
        return await tabStrategyTester.click();  // <-- Always handle Promises appropriately
    }
}
async function inputValue(element, value) {
    return await element.sendKeys(Key.BACK_SPACE + Key.BACK_SPACE + value.toString());  // <-- Never ignore a Promise
}

When returning the result of an asynchronous function within another async function, you can omit the await keyword since a Promise inside a Promise is automatically unwrapped. Therefore, using return element.sendKeys( will yield the same result, but relying on await may enhance clarity.

Answer №3

async function executeCode(){
    for(value of array){
        for(){
            for(){
                await driver.pause(1000);
            }
        }
    }
}

driver.pause() is a method that returns a Promise object which is resolved after the specified time has passed. The use of await in JavaScript stops the execution of code until the Promise is settled. This allows other tasks to be executed while waiting for the Promise to resolve. While ignoring the value of the await statement might be acceptable, it does not disregard the Promise itself. It's important to note that async functions return Promises. When using the .forEach method, the return value from the callback function is ignored, including any Promises it may create, leading to potentially unexpected behavior. By not using await, tasks are executed in an unpredictable order, highlighting the importance of asynchronous programming.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Getting the content inside a div tag with selenium in python

Is there a way to retrieve the content within the specified div tag? I attempted copying and pasting the xpath, but when attempting to print the contents of the div, it did not work. div = driver.find_element_by_xpath('//div[@class="sold_out_tag"]&ap ...

Ways to automatically update React.js state when localStorage changes occur

Is it possible to automatically update the data on the cart page whenever there are changes made to the myCart array in localStorage? Below is the code that I am currently using: const [cart, setCart] = React.useState([]) React.useEffect(() => { se ...

Adjusting color with the .on method in Event Listener

What's wrong with this code? html <!DOCTYPE html> <html> <head> <title>Ending Project</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> &l ...

My current objective is to extract the information from a specific item within a combobox by implementing the following code

alert($("select[name="+this.name+"] option:selected").text()); However, I am not receiving any output unless I explicitly specify the name of the combobox instead of using this.name. This issue may be related to the way quotes are being handled. ...

Is it possible to extract information from a form's POST request without relying on the traditional "action" attribute within form elements?

Last night, I was experimenting with ExpressJS and discovered something interesting when working with a simple code snippet: app.post('/contact', function(req, res, next) { res.send('Congratulations! You have submitted the form'); }) ...

Access Denied: BrowserStack Requires Authorization

Recently, I took on a project that utilizes BrowserStack for mobile testing within its automation framework. The proxy we were using experienced an outage, prompting me to switch the system's proxy to a functional one. While I'm uncertain if the ...

Identify the currently active subitem within the item-active class in a PHP carousel slider

I am working on creating an image carousel slider with 4 items and 4 slides each. These images will act as radio buttons, and I want to highlight the slide corresponding to the selected radio button. So, when the carousel loads, the selected slide should b ...

The connection to the firebase callback

Upon examining this function, it appears that there may be an issue with a null value causing the error message to display: (node:16232) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'groupPages' of null async setTriggers() { ...

formik does not support using the "new Date" function as an initial value

I have been trying to set the initial value of a date in my component like this, but when it renders I am encountering an error. const formik = useFormik ({ initialValues: { dob: new Date () } }) During this process, I'm facing the follow ...

What factors determine how a React component should be re-rendered based on a specific file?

I am facing a challenge with a file that stores an array of objects. There is a component responsible for fetching data from this file and rendering the list. The issue arises when the file gets updated externally, as I need the component to reflect these ...

Making API calls using JavaScript

I'm struggling with understanding how to approach this problem in javascript. Here is the question along with the details. I would appreciate any assistance. QUERY We have a server backend that provides two endpoints: /GetLocalPressReleases and /Get ...

What is the best way to end a table row after every group of four items?

I am working with a Handlebars template to display an array of movies in a table with four columns. Currently, I have set up a HBS helper in my code: app.engine('handlebars',exphbs({ defaultLayout: 'main', helpers: { n ...

Selenium IDE could not locate the specified ID span

Running into a challenge while using Selenium IDE and trying to save the value of a span id: <span id="ustData" data-itemId="2130078"></span> <div class="clear"></div> </div> The goal is to capture the value "2130078", ...

Emphasizing the date variable within a spreadsheet

Hey there! I'm struggling with the code below: <html> <head> <title>highlight date</title> <style> .row { background-color: Yellow; color:blue; } </style> <script type="text/javascript"> </script> &l ...

Sending data from TextBox as json format

JavaScript Code: var latitude = document.getElementById("<%=txt_Lat.ClientID %>").value; var longitude = document.getElementById("<%=txt_Long.ClientID %>").value; var jsonData = {latitude: latitude, longitude: longitude}; var jsonString = JSO ...

Troubleshooting Images in a React Application Integrated with WordPress API

I am struggling to understand why this GET request is consistently returning a 404 error. I have thoroughly tested the URL using Postman and everything seems to be in working order for the title and excerpt, but the images are causing some issues. Does a ...

The browser is opting to download the HTML file rather than displaying it

Recently, I set up a server using Node.JS express where I specified the location of an HTML file in the public folder. app.use(express.static(__dirname + '/public')); app.listen(8080); In previous projects, this setup worked seamlessly. However ...

Finding the file in a separate directory within the src path

In my projects directory, I have a folder named projects which contains both a game folder and an engine folder. Inside the engine folder, there is an engine.js file. My issue is that I want to access this engine.js file from my game.html file located in a ...

What is the best way to access the local Express server that is located in the same directory as the frontend project

This is the structure of my project - backend > node_modules > .env package-lock.json package.json server.js frontend > index.html style.css script.js server.js import dotenv from 'dotenv'; dotenv.config(); import express from &apo ...

Ways to access UserProfile in a different Dialogio

For the implementation of a chatbot, I am utilizing Microsoft's Bot Builder framework. However, upon implementing an alternative path to the dialog flow, I noticed that the user's Profile references are getting lost. Here is the code snippet fr ...