Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can protractor wait for a popover to appear and check if it does not have an empty string?

This is my popover that pops up once you hover over it:

enter image description here

This is how the html looks before the popover is added 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 after the popover is visible:

<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 want to test if the text is not empty. In my test I'm checking that there is a string like 4,90€ for all rides to and from the airport. This string must not be empty.

This is part of my protractor-conf with the regex to check if the element is not empty and how long the browser should wait before the check:

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

This is my protractor test:

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

  it('should display the popover-content on 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'm hovering over the i icon and checking if the popover appears. No problem. Then I have to wait for 1 second until the popover is fully loaded and I can check if it is not empty.

The problem with this approach is it works mostly in Chrome, but not in Firefox which is slower. How can the test be done similar to a promise? Can protractor wait for like 5 seconds and if there is no text, mark the test as failure?

like image 742
mles Avatar asked Mar 21 '16 23:03

mles


1 Answers

Can protractor wait for like 5 seconds and if there is no text, mark the test as failure?

This is what the browser.wait() is all about. It is also generally recommended as opposed to using browser.sleep(). We've even enforced the "not use browser.sleep()" rule with the help of eslint-plugin-protractor.

In your case, textToBePresentInElement fits perfectly:

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

Protractor would wait up to 5 seconds constantly checking if the text is present in element. If after the 5 seconds the text would not be there - you will get an error and the test would fail.

If needed, you may also use the visibilityOf expected condition for the "wait until the popover appears" part.


If you need to wait for a test that matches a specific regular expression pattern, you can make 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);
like image 142
alecxe Avatar answered Oct 13 '22 16:10

alecxe