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

jQuery form validation issue, unresponsive behavior

<!DOCTYPE html> <html> <head> <title> jquery validation </title> </head> <body> <script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.0/jquery.validate.min.js" type="text/javascript"> ...

What are the steps to troubleshoot Node Package Manager errors specifically linked to the node-gyp package?

Although this question has already been addressed in various instances, I am still struggling to resolve the issue using the suggested method. Following an npm install, I encountered errors while attempting to rebuild the node-gyp without any success. Node ...

Tips for improving the speed of loading infinite scroll pages

I am currently working on scraping over 100k rows from the provided URL. The data goes back approximately a month, loading in batches of 7-8 rows at a time. My current approach involves using a macro to scroll down the page slowly, which is effective but ...

What is the process for integrating a library into karma tests?

During my tests, I encountered an issue with using external libraries. I have added all the necessary links in karma.conf.js and some libraries were included successfully. However, for certain libraries, Karma seems to set "undefined" instead of "this" whe ...

Vue3 is struggling to apply dynamic styling exclusively to certain buttons

Currently, I am diving into the world of vue and facing a challenge in styling buttons dynamically when clicked individually. These buttons serve as filters for a list of products, and my goal is to apply one style when the filter is 'on' and ano ...

JavaScript form validation issue unresolved

When I attempt to validate form fields using Javascript functions, they seem to not load or check the field upon clicking the submit button. <html> <body> <?php require_once('logic.php'); ?> <h1>New Region/Entit ...

Having trouble with npm install, unable to successfully install any node modules after cloning my project from git

I recently pulled my project from a git repository and encountered issues while attempting to run npm install. Despite trying different solutions like running npm install --save core-js@^3 to address the core-js error, I keep receiving the same message pr ...

What is the best way to activate an event listener only after a button has been clicked?

Currently, I am developing a game that includes a timer and an event listener that notifies the user not to switch tabs. However, I am facing an issue where the event listener triggers before the game's start button is clicked. Is there a way in JavaS ...

What is the best way to access a particular property of an object?

Currently, I am successfully sending data to Mongo and storing user input information in the backend. In the console, an interceptor message confirms that the data is received from MongoDB. However, I am struggling to extract specific properties such as th ...

Deactivate the date when it reaches 8 in the current date count using ajax, php, and mysql

I want to prevent users from selecting a specific date after it has been chosen 8 times. Currently, when the date is selected for the 9th time, an alert box pops up. Instead of the alert box, I would like to disable that particular date selection altogethe ...

Insert the <span> element within the <a> element with the help of Jquery

I am attempting to insert a span tag inside .block-leftnav ul li .parent a, however, instead of adding the tag after only the .parent a, jQuery is adding the span tag after every href tag on my page. Below is the code I am using to achieve my desired outc ...

Having trouble accessing the Chrome browser with Selenium Webdriver. The admin has disabled the option to load unpacked extensions

I'm in the process of automating my application using Selenium Webdriver, C#, Visual Studio, and the Chrome browser. When Selenium attempts to open the Chrome browser, I encounter the following popup message: Failed to load extension from: C:\U ...

Endless loop JSON vulnerability

I recently came across a discussion on Stack Overflow about Google's practice of prepending while(1); to their JSON responses. Can anyone provide guidance on what type of PHP script would be suitable for this situation? I attempted the following: $ ...

Loading local JSON data using Select2 with multiple keys can greatly enhance the functionality

Comparing the select2 examples, it is evident that the "loading remote data" example contains more information in the response json compared to the "loading array data" example. I am interested in knowing if it is feasible to load a local json file with a ...

Hover to stop menu movement

Can someone help me achieve a similar menu hover effect like this one? I'm trying to create a menu with a hold/pause effect on hover, specifically in the section titled "A programme for every vision". The goal is to navigate through the sub menus smo ...

Using jQuery to iterate through an array and reverse its order

Is there a way to loop through an array and change the CSS background color chronologically rather than randomly? Additionally, is it possible to reverse through the same array when the back button is clicked? http://jsfiddle.net/qK2Dk/ $('#right&a ...

Create type definitions for React components in JavaScript that utilize the `prop-types` library

Exploring a component structure, we have: import PropTypes from 'prop-types'; import React from 'react'; export default class Tooltip extends React.Component { static propTypes = { /** * Some children components */ ...

Navigating between different route groups using redirection: a step-by-step guide

My project folder structure is organized like this: app (app) dashboard page.tsx page.tsx layout.tsx (auth) login ...

Utilizing server-side caching middleware with tRPC version 10

Currently, I am working on a Next.js project and exploring the possibility of incorporating in-memory caching for tRPC results. Each tRPC procedure should have the option to set a custom TTL for caching purposes. My initial thought is that utilizing tRPC&a ...

Initiate a CSS animation only when a different animation has completed

I am trying to create a sequence of animations using 2 squares. I want the animation for the red square to start only after the blue square's animation is complete. How can I achieve this cycle of animations? .box { width: 100px; height: 1 ...