简体   繁体   中英

How do I make Protractor wait for animations that use $timeout?

tldr: How do I make a Protractor test wait for animations to complete when those animations are implemented in an Angular directive using $timeout?

Using a Protractor test, I'm trying to verify that an Angular directive has successfully displayed its contents, but there are a few steps necessary to trigger it. The directive animates itself, and it doesn't render its data until the Bootstrap accordion group it's in has expanded.

Here's the template (it's Jade that compiles to HTML, and I've taken out some complexity for illustrative purposes):

uib-accordion(close-others='oneAtATime')
        uib-accordion-group.featureGroup(ng-repeat='feature in results.features', is-open='featureHistogramVisibility[$index]')
            uib-accordion-heading {{feature.title}}
            histogram.featureSizeHistogram(histogram='feature.getHistogram()', is-visible='featureHistogramVisibility[$index]')

When the is-visible attribute changes to true (when the accordion group is expanded), it uses $timeout to wait 100 milliseconds for the accordion animation to complete, then displays a chart. Here's the relevant part of the link function in the directive:

scope.$watch('isVisible', function(newValue) {
          if(newValue && scope.chartConfig) {
            $timeout(function () {
              // timeout is necessary so that the chart is the proper size
              // after animations are finished
              displayChart(scope);
            }, 100);
          }
        });

The $timeout is necessary because, without it, the chart has the wrong dimensions. It automatically adjusts its dimensions to its container once, when it is initially rendered inside displayChart(). The dimensions will be incorrect if this happens before the accordion group is expanded.

The goal of my Protractor test is to verify the directive got some data in the histogram attribute from feature.getHistogram() and rendered itself. When it doesn't get any data, the height is zero. When I'm using this directive directly on a page (not contained in an accordion), I verify the height and width are non-zero.

Here's code from my Protractor test against this directive when it is directly on a page (not within an accordion):

var verifyNonZeroSize = function (element) {
  element.getSize().then(function (size) {
    expect(size.width).to.not.equal(0);
    expect(size.height).to.not.equal(0);
  });
};
// ...
element.all(by.css('.featureSizeThumbnailHistogram')).map(verifyNonZeroSize);

That works because there is no animation in this case.

When I get an accordion group and click() it in the Protractor test, then call verifyNonZeroSize on the directive within, it gets the size immediately and fails verification.

Two questions:

  • Is there a more idiomatic way in Protractor to verify an attribute of a directive got something non-null (I have plenty of unit and integration tests, but Protractor seems to be the only way to catch issues caused by mistakes in the template)?
  • In Protractor, how do I click something and wait for animations, including the $timeout call in the directive, before verifying height and width (I've seen other SO answers that handle CSS animations, but not animations that use $timeout)?

Try using implicitlyWait by Protractor.

browser.driver.manage().timeouts().implicitlyWait(150).then(function () {
  // expect code
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM