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:

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

How can you conceal an element once the ngHide animation has completed in Angular's ngAnimate?

Is there a way for the display to be set to "none" after the ng-hide animation has completed, instead of immediately when the element is hidden? ...

I am looking to incorporate automatic scrolling functionality into my RSS Feed

I'm in the process of developing an RSS feed for my website. My expertise in JS/jQuery is limited, so any assistance would be greatly appreciated. After utilizing Google's Feed API and creating my own RSS Reader Widget, I realized that it lacked ...

Updating the Highcharts chart when new data is available

Utilizing Highcharts, I am looking to have this chart update every second. Here's my current setup: JSFiddle I've implemented a timer with window.setInterval(updateChart, 1000); which successfully updates data each second. However, I'm uns ...

What exactly is the function of registerServiceWorker in React JS?

Just starting out with React and I have a question about the function of registerServiceWorker() in this code snippet: import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import registerServi ...

Switch the style sheets after the content

How can I create a toggle effect on the :after property, switching between + and - each time the link is clicked? I've attempted to achieve this using JavaScript, CSS, and HTML, but the code only changes + to - and doesn't switch back when the l ...

Personalizing MaterialUI's autocomplete functionality

Trying to implement the material-UI Autocomplete component in my react app and looking for a way to display a div when hovering over an option from the list, similar to what is shown in this reference image. View example If anyone has any tips or suggest ...

Guide to updating passwords with passport-local-mongoose

After successfully importing the passport-local-mongoose to my code and being able to register and log in users, I now face the challenge of changing the password for a specific user. How can I achieve this? According to the documentation of passport-local ...

Tips for marking a textarea as mandatory when a choice is made

I'm creating an .html document for conducting a complete system check and confirming various aspects of its functionality. In this page, there is a table within a form structure where each row represents a step in the system verification process (e.g. ...

Tips on sorting JSON data with Angular

Trying to categorize JSON Data into online and offline users with errors. The criteria are based on the presence of a 'stream' object (online), absence of a 'stream' object (offline), and the presence of an 'error' property. ...

Is it possible for an AngularJS directive to compile a fresh element that has a second directive assigned to it?

UPDATE: All directives listed below will now require ng-model bindings to be applied in the elements they generate, targeting the controller assigned to the page. The code has been modified to reflect this. I am exploring the creation of dynamic HTML usin ...

How to efficiently retrieve a form's data from multiple forms with identical ids in JavaScript

I am facing a challenge with multiple forms on the html page that have the same ID. I need to send each form's information to the server based on user selection, but I haven't been able to find a relevant solution. For my Authorization polic ...

How to link AngularJS controller from a different module in routing

My current project involves creating a complex app with a structured design: Each module is organized in its own folder structure, including controllers, directives, and more. Within each folder, there is an index.js file along with other files for separ ...

Issues with Mega Menu functionality preventing items from being clickable and links from properly navigating

Recently, I encountered a strange issue related to the integration of a mega menu found at . Unfortunately, despite integrating the mega menu, the Category and sub category links seem unresponsive - they are not directing me to the desired links. I suspec ...

Tips for maintaining a user's session post-login with Passport and Express JS

I recently set up a node backend using express and integrated Passport for authentication purposes. My application has a route called /login for logging in and another route called /me to retrieve information about the currently logged in user. Below is t ...

The application threw an error stating that Angular JS is not a function, causing it to be

I've encountered an issue where including angular scripts (such as Controller.js) in the angular view does not work - resulting in a "not a function, got undefined" error. However, when I add these scripts in the main view, it works perfectly fine. Do ...

Attempting to utilize ng-click on an element that has been added using element.append() in the postlink phase?

I have been working on customizing a particular angular library to incorporate some new features. https://github.com/southdesign/angular-coverflow/blob/master/coverflow.js As part of this process, I am looking to attach click events to the elements being g ...

Steps to update the value of an object stored within an array

I have a collection of items stored in an array. Each item is represented by an object with properties. I want to update the value of a specific property within each object: var array=[{a:1, b:false}, {a:2, b:true}, {a:3, b:false}] My goal is to set the p ...

React application experiencing issues with MQTT and Mosquitto broker connectivity

Upon installing the Mosquitto broker, I successfully tested it in my command prompt. However, when I attempted to establish a connection with my React application, I encountered the error message: "WebSocket connection to 'ws://localhost:1883/' f ...

Error 500 in WordPress Child Theme due to AJAX Internal Issue

I have encountered an issue with my Ajax code in the Js/Jq block (/buscador/menuLateral/menu-libros.php): $.ajax({ url: '<?= get_stylesheet_directory_uri(); ?>' + '/buscador/buscador-functions.php', type: 'POST' ...

Using jQuery, learn how to successfully call a selector from dynamic content

I am currently facing a challenge with a table that is generated server-side and then appended to the view page (client-side). Since the table is not directly included in the DOM, I am using the StickyTableHeaders jQuery plugin to create a sticky header fo ...