Utilize WebdriverIO to loop through elements and trigger a click event on a link

I am currently using Javascript and webdriverio (v2.1.2) for data extraction on an internal website. The process involves:

  • Authentication
  • Opening the necessary URL once authenticated
  • Searching for an anchor tag with a specific keyword on the new page
  • Clicking on the found anchor tag

The code snippet below shows what I have attempted so far, which is working for the last two steps. However, in order to achieve this, I had to utilize Q and async. My goal is to use only Q for this task. Could someone assist me in achieving this using only Q?

    var EmployeeAllocationDetails = (function () {
'use strict';
/*jslint nomen: true */
var Q = require('Q'),
    async = require('async'),   
    _ead_name = 'Employee Allocation Details',
    goToEadFromHome;

goToEadFromHome = function (browserClient) {
    browserClient.pause(500);
    var deferred = Q.defer();
    browserClient.elements('table.rmg td.workListTD div.tab2 div.contentDiv>a', function (err, results) {
        if (err) {
            deferred.reject(new Error('Unable to get EAD page. ' + JSON.stringify(err)));
        } else {

        async.each(results.value, function (oneResult, callback) {
                console.log('Processing: ' + JSON.stringify(oneResult));
                browserClient.elementIdText(oneResult.ELEMENT, function (err, result) {
                    if (err) {
                        if (err.message.indexOf('referenced element is no longer attached to the DOM') > -1 ){
                            callback();
                        } else {
                            callback('Error while processing :' + JSON.stringify(oneResult) + '. ' + err);
                        }
                    } else if(!result){
                        console.log('result undefined. Cannot process: ' + JSON.stringify(oneResult));
                        callback();
                    } else if(result.value.trim() === _ead_name){
                        deferred.resolve(oneResult);
                        callback();
                    }
                });
            }, function (err) {
                // if any of the processing produced an error, err would equal that error
            if( err ) {
        // One of the iterations produced an error.
        // All processing will now stop.
            console.log('A processing failed to process. ' + err);
            } else {
            console.log('All results have been processed successfully');
            }
            }); //end of async.each

        }
    });
    return deferred.promise;
};

return {
    launchEad : goToEadFromHome
  }
})();
module.exports = EmployeeAllocationDetails;

For more information, you can refer to the related Github Issue link here

Answer №1

Using the async function is recommended in this case. The code provided is efficient as it executes tasks in parallel and handles errors effectively.

However, if you decide to remove the async function, there are alternative options available:

  • Utilize the Q flow control module
  • Manually replicate async's functionality
  • Create your own implementation

Incorporating Q's flow control may involve a pseudo-code similar to the following:

var getTextActions = [];
function createAction(element){ 
    return function(){
        return element.getText();
    }
}

each(elements, function(element){ getTextActions.push( createAction(element) ) }); 
Q.all(getTextActions).then(function(results) {
    //Iterate through results and resolve promise with corresponding element
} ); 

It is important to note that this approach may have lower performance compared to using async, as it retrieves text from all elements before resolving promises.

Creating a custom implementation, though not recommended, would involve pseudo-code resembling the following:

var elementsCount = elements.length; 
elements.each(function(element){
    element.getText(function(err, result){
        elementsCount --;
        if ( !!err ) { logger.error(err); /** Handle error **/ } 
        if ( isThisTheElement(result) ) { deferred.resolve(result); }
        if ( elementsCount == 0 ){ 
            deferred.resolve(null);
        }
    })
})

If you require further clarification or if the answer does not fully address your question, feel free to let me know so I can enhance the explanation.

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

Angular template src variable issue with no solution in sight

The videoSrc variable is not evaluating correctly images/{{videoSrc}}.mp4 When I write just videoSrc, it works fine. But when I concatenate it with other strings, it doesn't work. Check out this jsfiddle ...

Getting the value of "Page=?" from the href attribute in an HTML tag can be done using Selenium Webdriver and Java

I am looking to extract the value "page = ?" from a specific "href" tag in the HTML code below. I need this value for my Selenium WebDriver script so that my loop can iterate up to page 53. Can someone guide me on how to retrieve the "page =" value mentio ...

Having difficulty in clicking the "load more" button using Selenium

I am in the process of developing a web scraper that will utilize both Selenium and BeautifulSoup. I am encountering difficulties with clicking the load more button using Selenium. While I have been able to detect the button, scroll to it, etc., I am stru ...

Guide to making an object with a value sourced from the redux store

I am looking to develop an object with custom getters and a key representing language. Depending on the language key, different values should be returned by the getters. This is specifically for a customizable language selection feature. As an example, one ...

Ways to retrieve information when text is modified and a dropdown is selected within an input field

I have an input field with a text box and a dropdown. My goal is to trigger data based on text changes in one method, while using another method for the dropdown. Check out the code below. const allList = [ { id: "1", value: "Fruits" ...

What is the best way to add borders to the cities on interactive SVG maps?

I'm currently developing Interactive SVG Maps showcasing Turkey. The map consists of 81 cities, each represented by <g> elements, and their respective districts, created as child elements within the city elements. It's worth noting that the ...

How should res.render() and res.redirect() be properly utilized within Express framework?

I am struggling to understand the difference between res.render('viewname', {msg: 'Message' }) and res.redirect('route') The render function allows you to pass a "message", but the redirect function does not. However, ther ...

The onValue event in Firebase is not triggering, and I am unable to determine the cause

I am currently working on a web3 application using Next/Js and Firebase. The concept is for users to connect with their Solana wallet, list their NFTs, and choose one to connect in a game-container. My challenge lies in retrieving information from all con ...

Refresh the page when the parameter in the URL changes

I'm encountering a small issue that I can't seem to resolve. Currently, I am on the following page: http://example.com:8080/#/user/5ad142e8063ebb0537c5343e There is a link on this page that points to the URL below: http://example.com:8080/#/u ...

Uncovering the origin of a problematic included file

When using Sencha Touch, it is common to encounter issues related to missing files. In most cases, simply including the file resolves the issue. However, there are instances where the problem lies in a faulty include, requiring you to locate where the file ...

Hide the div when hovering occurs

I need a way to hide the 'sample' div when hovering over it and then show it again when the mouse moves away $('.secmenu').hover(function() { $('.sample').css('opacity', '0'); if ($('.secmenu&a ...

Encountering an unfamiliar property in JSX dynamic component

I am attempting to display components after dynamically determining their name, but I keep encountering this issue: Unknown property ent on the <resultComponent> tag. Please remove this property from the element. The problematic code is located w ...

positioning the cursor at the end of a content-editable div

When working with a contenteditable div, I encountered several issues specific to FireFox. To address these problems, I found that appending a br tag to the end of the div was necessary. <div id="testDiv" contentEditable="true"> Hey, click the butt ...

Execute a self-invoking JavaScript function with dynamic code

I'm facing a challenging problem that I just can't seem to solve... There's a function on another website that I need to use, but unfortunately, I can't modify it The code in question is: Now, I am looking to add a prototype "aaa" to ...

Is there a way to pre-load images from component B within component A using Vue?

In a scenario where I have two Vue files, A.vue and B.vue, the issue arises when navigating from A to B. B contains numerous images fetched from Firebase realtime database, resulting in slow loading times upon first visit. To address this, I aim to preload ...

Can anyone offer me advice on troubleshooting a failed Capifony deployment caused by a time out during the assetic:dump process?

$ cap deploy Unfortunately, the deployment process is failing and I am receiving the following error message: * executing "cd /var/www/site/prod/releases/20120831164520 && php app/console assetic:dump web --env=prod --no-debug" servers: ["site ...

Dropdown menu featuring a customizable input field

Is it possible to have a drop-down list with an input textbox field for creating new items in the same dropdown menu? ...

React.Js custom form validation issue in Next.Js - troubleshooting required

My attempt at validating a form is causing some issues. After refreshing the page and clicking on the submit button, only the last input's error is generated instead of errors for every input according to the validation rules. Here is a screenshot o ...

Node.js web server operating on port 3000 is running a script

I have developed a Node.js script that extracts data from a database and saves it in a file. Additionally, I have set up a Node.js web server listening on port 3000 using forever to keep it running constantly. However, the script currently lacks a web inte ...

Easily transfer files without the need to refresh the page by utilizing the power of AJAX

In my page file-upload.jsp, I have the following code snippet: <form action="" id="frmupload" name="frmupload" method="post" enctype="multipart/form-data"> <input type="file" id="upload_file" name="upload_file" multiple="" /> <in ...