What is the best way for Protractor to effectively wait for a popover to be displayed and verify that it does not contain an empty string?

Whenever you hover over it, this appears - my popup:

https://i.sstatic.net/Bm9tC.gif

This is what the html looks like before we add the popover to the DOM:

<span 
    tariff-popover="popover.car2go.airport" 
    class="ng-isolate-scope">
    <span ng-transclude="">
        <span class="ng-binding ng-scope">
            Airport Fee
        </span>
    </span>
    &nbsp;
    <span 
        popover-placement="right" 
        uib-popover-html="text" 
        popover-trigger="mouseenter" 
class="fa fa-info-circle">
  </span>
</span>

This is what happens after the popover shows up:

<span 
tariff-popover="popover.car2go.airport" 
class="ng-isolate-scope">
<span ng-transclude="">
<span class="ng-binding ng-scope">
Airport Fee
        </span>
    </span>
&nbsp;
    <span 
        popover-placement="right" 
        uib-popover-html="text" 
        popover-trigger="mouseenter" 
        class="fa fa-info-circle">  
    </span>
    <div 
        tooltip-animation-class="fade" 
        uib-tooltip-classes="" 
        ng-class="{ in: isOpen() }" 
        uib-popover-html-popup="" 
        title="" 
        content-exp="contentExp()" 
        placement="right" 
        popup-class="" 
        animation="animation" 
        is-open="isOpen" 
        origin-scope="origScope" 
style="visibility: visible; display: block; top: -41px; left: 108.984px;" class="ng-isolate-scope right fade popover in">
            <div class="arrow">
        </div>
        <div class="popover-inner">
            <!-- ngIf: title -->
            <div  class="popover-content ng-binding" ng-bind-html="contentExp()">
                4,90€ for all rides to and from the airport
            </div>
        </div>
    </div>
</span>

I aim to verify that the text isn't empty by testing it. In my test, I confirm the presence of a string such as

4,90€ for all rides to and from the airport
. This string must not be devoid.

In Protractor configuration, here's the portion with the regex to validate non-empty elements along with the waiting time set before the validation:

params: {
    regexNotEmpty: '^(?!\s*$).+',
    sleepTimeout: 1000
},

Here is how my Protractor test goes:

describe('car2go test all input fields and checkboxes', function() {
  beforeEach(function() {
    browser.get('http://localhost:9999/#/car2go');
    browser.waitForAngular();
  });

  it('should show the popover-content upon mouseover', function() {
    var path = 'span[tariff-popover="popover.car2go.airport"]';
    var pathIcon =  path + ' > .fa.fa-info-circle';
    var pathPopover = path + ' > .popover.ng-isolate-scope.right.fade.in';

    var popoverIcon = element(by.css(pathIcon));
    browser.actions().mouseMove(popoverIcon).perform();
    var popover = element(by.css(pathPopover));

    expect(popover.isDisplayed()).toBeTruthy();
    browser.sleep(browser.params.sleepTimeout);
    expect(popover.getText()).toMatch(browser.params.regexNotEmpty);
  });
});

I hover over the i icon and ensure the popover displays correctly. All good till now. However, after waiting for 1 second for the popover to load completely, I check if it contains any content.

The downside to this method is its effectiveness in Chrome but not Firefox due to the latter's slower nature. Is there a way for the test to resemble a promise? Can Protractor delay for around 5 seconds and prompt a failure indication if no text is detected?

Answer №1

Is it possible for Protractor to wait 5 seconds and then consider the test as failed if no text is found?

The concept of using browser.wait() aligns with this scenario, promoting it over browser.sleep(). To reinforce this practice, we have implemented a rule prohibiting the use of browser.sleep() through eslint-plugin-protractor.

In your specific case, textToBePresentInElement would be ideal:

var EC = protractor.ExpectedConditions;
browser.wait(EC.textToBePresentInElement(popover, "expected text"), 5000);

Protractor will continuously check for the presence of the specified text within the element for up to 5 seconds. Failure to find the text within that time frame will result in an error and test failure.

Additionally, you can utilize the visibilityOf expected condition to handle the waiting period until the popover appears.


To wait for a test that matches a particular regular expression pattern, you can create a custom Expected Condition:

var EC = protractor.ExpectedConditions;

var patternToBePresentInElement = function(elementFinder, pattern) {
  var matchesPattern = function() {
    return elementFinder.getText().then(function(actualText) {
      return actualText.search(pattern) !== -1;
    });
  };
  return EC.and(EC.presenceOf(elementFinder), matchesPattern);
};

Usage:

browser.wait(patternToBePresentInElement(popover, /\w+/), 5000);

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

Is there a way to sort data by year and month in mongodb?

I'm trying to filter data by year in MongoDB based on a specific year and month. For example, if I pass in the year 2022, I only want to see data from that year. However, when I try using the $gte and $lte tags, it returns empty results. Can someone g ...

Modify the values of several dropdown menus (5 in total) at once using jQuery. The values will be dynamically retrieved from a JSON file

Dropdown values for the first dropdown are 1, 2, 3, 4, 5. Dropdown values for the second dropdown are 25, 26, 27, 28, 29. Dropdown values for the third dropdown are 35, 36, 37, 38, 39. The goal is to have each dropdown loaded with its respective data dyn ...

Transfer the information on the onClick event to the loop's function

When creating my component within the parent component, I follow this approach: renderRow(row){ var Buttons = new Array(this.props.w) for (var i = 0; i < this.props.w; i++) { var thisButton=<FieldButton handler={this.actionFunction} key={&ap ...

Identifying when the mouse cursor changes on a website

Is there a way to detect when the mouse cursor changes as it hovers over different page elements? An event similar to this would be ideal: window.onmousecursorchange = function(e) { // e would provide information about the cursor // for example, ...

Creating a clickable map for a PNG image: Step-by-step tutorial

My goal is to create a interactive map similar to this one. Click here for the image ...

Ways to pass Angular variables to JavaScript while utilizing the $scope() function

This is my process for receiving input: extracting data from an sql table, passing it through php slim, integrating it into angularjs, and displaying it on a website. I am looking to retrieve a variable in javascript that has been passed from php slim to ...

Conceal the div element if the screen size drops below a certain threshold

Is it possible to hide a div element when the browser width is less than or equal to 1026px using CSS, like this: @media only screen and (min-width: 1140px) {}? If not, what are some alternative solutions? Additional information: When hiding the div eleme ...

Issue with the AngularJS build in Yeoman

After setting up Yeoman and Bootstrap for an AngularJS project, I utilized the grunt server command for debugging and coding. However, when I tried using the 'grunt build' command, it generated a dist folder. Unfortunately, when I attempted to ru ...

Trouble with executing simple code in a new project (binding, input, ng model) across different browsers

I am encountering an issue with this code snippet. It's a simple one - I want to display the input text in my view, but nothing is showing up. The code runs fine in an online simulator, but when I try it in my browser, it doesn't work at all. I&a ...

What is the best way to retrieve attributes from a through table using a query?

I am in the process of creating a straightforward shopping cart system. My structure includes a Cart model, a Product model, and a connection table called CartItems. Here are the associations: models.Cart.belongsToMany(models.Product, { through: 'Car ...

Managing a directive in Angular using a service: A guide

I'm currently working on a Service that manages a directive. The main goal is to utilize the Service within a Controller to instruct the Directive to perform certain actions. For example, calling SomeService.tellSomething('ok'); will activ ...

I have implemented a button in PHP and now I am looking to invoke a function when that button is clicked

I have a PHP-generated HTML button and I'm having trouble calling the mybtn3() function when it is clicked. The button code looks like this: echo"<td width=14% align=center><input type=button value=Export onclick=mybtn3() /></td>"; ...

Managing repeated calls to a specific get function in nodejs

Utilizing an Ajax call, I am invoking the following GET function every 10 seconds to monitor the status of various URLs. app.get('/getUrl', function(req, res) { var response = {}; var keyArr = []; var urlData ...

Switch the displayed image(s) based on the radio button selection made by the user

I need help implementing a feature on my website where users can change an image by selecting radio buttons. For example, there are three options: 1) Fox 2) Cat 3) Dog When the user chooses "Fox," I want an image of a fox to be displayed. If they then sw ...

What are the benefits of using Bower.js when npm is already functioning well?

When working in the main project directory, running the command npm init will create a file called "package.json". If I need to install dependencies such as angular, jQuery and bootstrap, I can use the following commands: npm install angular --save-de ...

Creating a private variable to perform a select_sum query

I have defined private variables in my CodeIgniter code like this: private $table = 'phone'; private $column_order = array(null, 'name', 'price'); private $type = array('type'); private $battery_consumption = array ...

The breeze is puzzled by the altered being, unable to identify it

I am currently working on a breeze implementation that involves displaying properties from a location object on the UI. However, when I make changes to some properties and attempt to save them, breeze does not recognize the entity as being changed. Here is ...

I am currently struggling with the mapquest GeoJson integration within my Node/Express application. I keep encountering an error message that reads "body used already."

I attempted to utilize the mapquest API by following the provided documentation, however I encountered an error message: HttpError: body used already for: Below is my geoCoder.js configuration: const NodeGeocoder = require('node-geocoder'); con ...

Guide: "Changing an HTML element's class by utilizing its id attribute"

This is the HTML code snippet I am working with: <li class="treeview" id="account_management"> I need to select the element with the id of "account_management" and update its class from "treeview" to "treeview active" in order to ...

Grunt is throwing an error message of "Cannot GET/", and unfortunately ModRewrite is not functioning properly

I've recently started using Grunt (just began last Friday). Whenever I run Grunt Serve, it displays a page with the message "cannot GET/" on it. I tried implementing the ModRewrite fix but the error persists. Any assistance would be highly appreciat ...