Ways to have a function return a promise from the final "then" in a series of promises

I am delving into the world of test automation with Selenium and JavaScript. As a newcomer to both, along with functional programming and promises, I am facing a challenge in creating a function that performs three essential tasks:

  1. Click on an input
  2. Clear the input
  3. Type text into the input

The current function I have written is not yielding the expected output:

    var clearAndSendKeys = function(driver, elementIdentifier, sendKeys) {
        var returnValue;
        driver.findElement(elementIdentifier).then(function(inputField){
            inputField.click().then(function() {
                inputField.clear().then(function() {
                    returnValue = inputField.sendKeys(sendKeys);
                });                 
            });                 
        });
        return returnValue;
    }

To utilize this function, it should be called as follows:

    clearAndSendKeys(driver, webdriver.By.id('date_field'), '14.09.2015').then(function(){
        //Implement further actions here
    });

My expectation was for the variable returnValue to hold the promise generated by sendKeys. However, the function clearAndSendKeys returns an undefined variable before sendKeys is executed. This indicates that returnValue was never defined as a promise, leading the program to proceed without waiting for sendKeys.

How can I modify my function clearAndSendKeys to properly return the promise from sendKeys? I would prefer to avoid adding a callback to the clearAndSendKeys function.

Edit: I have corrected the typo by removing .then({return data}) from the code snippet.

Answer №1

It is important to ensure that each promise is returned from the .then callback:

var clearAndSendKeys = function(driver, elementIdentifier, sendKeys) {
    return driver.findElement(elementIdentifier).then(function(inputField){
        return inputField.click().then(function() {
            return inputField.clear().then(function() {
                return inputField.sendKeys(sendKeys);
            });                 
        });                 
    });
}

The promise from .then will resolve with the same value as the one returned from the callback.


To understand why your current code is not working, refer to Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference. It explains the asynchronous nature of promises.

Answer №2

It is advisable to avoid nesting promises as it defeats the purpose of eliminating callback hell. Utilizing the then callback allows for the creation of chains of asynchronous operations using a Thenable object.

In this scenario, the key is to store a reference to the input field obtained from the initial asynchronous operation within the main function's scope. This enables the creation of a chain of subsequent async operations that can be returned by the function.

const clearAndSendKeys = function(driver, elementIdentifier, sendKeys) {
    let inputFieldRef;
    return driver.findElement(elementIdentifier)
        .then(function(inputField){
            inputFieldRef = inputField;
            return inputField.click();
        }).then(function() {
            return inputFieldRef.clear();
        }).then(function() {
            return inputFieldRef.sendKeys(sendKeys);
        });
}

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

Transmit the Selected Options from the Checkbox Categories

Here's an intriguing situation for you. I've got a webpage that dynamically generates groups of checkboxes, and their names are unknown until they're created. These groups could be named anything from "type" to "profile", and there's a ...

The outcome of a function within the $.ajax method is transformed into a string

Trying to pass an array of IDs using the $.ajax data variable is proving to be a challenge. The array is generated by a function, and I've noticed that if I define this function outside of the $.ajax call, it works fine. However, when I place the same ...

Checkbox does not trigger onCheck event

I am facing an issue with a checkbox component from material-ui where the onCheck event is not firing. <Checkbox label="label" onCheck={onCheck} checked={currentDocument.ispublic} /> function onCheck() { currentDocument.ispublic = !current ...

What steps can be taken to ensure a function operates even when the mouse is stationary?

$(document).ready(function() { var score = 0; $("body").mousemove(function() { score++; $("#result").val(score); console.log(score); }); }); As I move my mouse, the score keeps increasing. But, I'm wonde ...

How to access a shadowroot element using R Selenium

Currently, I'm dealing with web scraping where one of the websites presents a 'Accept cookies' button within a shadow root. To address this issue, I sought assistance on how to click this button in discussions found here: Click on accept co ...

What is the best way to maintain the current position in a component while interacting with another component?

I have a component that displays a collection of cards with images. There is a button that toggles between showing another component and returning to the original list of cards. The issue I am encountering is that every time I return to the list of cards, ...

Error encountered: The method WebElement.click of <selenium.webdriver.firefox.webelement.FirefoxWebElement has failed to execute

Recently, I created a Python script that automatically logs into my email account and sends messages. It was working fine after testing, but then I decided to make some changes to simplify it - like adding one-liners and reducing the number of local variab ...

How are jQuery.ajax and XMLHttpRequest different from each other?

My goal is to fetch and run the script contained in a file named "example.js" using an AJAX request. Suppose the content of example.js looks like this: const greetings = { hello: "Hello", goodBye: "Good bye" } console.log(greetings.hello) In anot ...

Latest FF 35 showing alert for blank field in HTML5 email input box

My form includes an email input field with a default value. When the user focuses on the field, it clears out if the value matches the default one. Upon blurring the element, the default value is restored if the field remains empty. In Firefox 35, clickin ...

What are the steps to utilize the driver initialization in the setupModule function?

When using unittest in Python3, I attempted the following code: import unittest from selenium import webdriver def setupModule(): driver = webdriver.Firefox driver.maximize_window() driver.get('www.google.com') def teardownModule() ...

Customizing Material UI tooltip styles with inline CSS formatting

Currently in the process of creating a React component that utilizes the Material UI Tooltip feature. In my component, I have the need to manually reposition the Mui Tooltip by targeting the root popper element (MuiTooltip-popper). However, the Mui Toolti ...

Implementing the MVC pattern in the app.js file for a Node.js and Express web application

After completing several tutorials on nodejs, mongodb, and express, I have gained a solid understanding of the basics such as: The main controller file being app.js. Third party modules stored in their designated node_modules directory. Template files pl ...

Tips for creating a hierarchical multilevel datatable with JavaScript

I am currently working on implementing a multi-level datatable without relying on any external plugins or libraries. My goal is to achieve this using pure JavaScript, JQuery, or AngularJS. I have explored the following resources: Traverse all the Nodes of ...

UI-grid: Triggering a modal window from the filter header template

Is there a way to create a filter that functions as a simple modal window triggered by a click event, but can be displayed on top of a grid when placed within the filterHeaderTemplate? I have encountered an issue where the modal window I created is being ...

When an element is dragged within the mcustomscrollbar container, the scroll does not automatically move downward

I am facing an issue where I have multiple draggable elements inside a Scrollbar using the mcustomscrollbar plugin. When I try to drag one of these elements to a droppable area located below the visible area of the scroller, the scroll does not automatical ...

Unable to dynamically display an HTML5 video using JavaScript

I'm facing an issue with displaying videos in a modal dynamically. Here's the scenario: +------------+---------+ | Name | View | +------------+---------+ | 1.mp4 | X | | 2.mp4 | X | +------------+---------+ The X ...

Jasmine examination fails to progress to the subsequent segment of the promise

I want to test a specific function: function initializeView() { var deferred = $q.defer(); if(this.momentArray) { core.listMoments(constants.BEST_MOMENT_PREFIX, '').then(function(moments) { //Ommit ...

Limit selection choices in select element

Similar Question: Prevent select dropdown from opening in FireFox and Opera In my HTML file, I have a select tag that I want to use to open my own table when clicked. However, the window of the Select tag also opens, which is not desirable. Is there a ...

Simultaneous AJAX, animated page loader

My website takes 3 seconds to load due to multiple Synchronous AJAX requests. To enhance user experience, I would like to implement a loading page with an animated GIF. Once the Ajax requests are completed and the page is fully loaded, the loading page sh ...

I'm struggling to make this script replace the values within the table

I am struggling with a script that I want to use for replacing values in a google doc template with data from a google sheet. The script is able to recognize the variables and generate unique file names based on the information from the google sheet. Howev ...