angular / protractor

E2E test framework for Angular apps
http://www.protractortest.org
MIT License
8.75k stars 2.31k forks source link

browser.wait() does not work when there is no spinner #4481

Closed gaurabhi1986 closed 7 years ago

gaurabhi1986 commented 7 years ago

Hi there!

I am facing very weird behaviour of browser.wait(). In my test website sometime Spinner appear and sometime it does not appear to handle this situation I am using browser.wait(). But when there is no spinner appears in the page in that condition my code is not working and throwing exception. Can you please help me to resolve this issue. How I can make sure that if there is no spinner execution will continue if there is a spinner it wait for spinner to finish and then move to next step in test.

Below is my code:

this.waitForSpinnerFinished = () => {
       browser.wait(function() {
            return element(by.css('.spinner')).isDisplayed().then(function(result) {
                return !result;
            })
        }, 30000)
    }}

Bug report

Node Version: v6.10.0 Protractor Version: 4.0.9 Angular Version: 1.X Browser(s): Chrome Operating System and Version Windows 10

require('babel-register');

exports.config = {

    directConnect: true,
    // chrome driver location if different than installed with webdriver-manager update, when directConnect: true
    chromeDriver: './4_utilsObjects/chromedriver_2.29.exe',

    allScriptsTimeout: 180000,

    framework: 'jasmine',

        suites: {
        tests: ['1_testLaunchers/*.js'],
        visual: ['visualRegression/*.js'],
    },
     rootElement: '[ng-app="preApp"]',
         capabilities: {
        'browserName': 'chrome',
        'chromeOptions': {
            // needed to disable saving passwords in account creation tests
            'prefs': {
                'credentials_enable_service': false,
                'profile': {
                    'password_manager_enabled': false
                }
            }
        },

           },

           jasmineNodeOpts: {
        silent: true,
        defaultTimeoutInterval: 180000,
        // needed for jasmine-spec-reporter
        print: function () {
        }
    },

        onPrepare: () => {
        // here we're adding real time jasmine reporter that will display test steps
        // see https://github.com/bcaudan/jasmine-spec-reporter
        var SpecReporter = require('jasmine-spec-reporter');
        // add jasmine spec reporter
        jasmine.getEnv().addReporter(new SpecReporter({
            displayStacktrace: 'none',
            displaySuccessfulSpec: true,
            displayFailedSpec: true,
            displaySpecDuration: true,
            displaySuiteNumber: true,
            displayPendingSummary: false,
            displayPendingSpec: false
        }))

        // adding Jasmine JUnit reporter
        var jasmineReporters = require('jasmine-reporters');
        jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({
            consolidateAll: true,
            savePath: 'reports/JUnitReporter',
            filePrefix: 'testresults'
        }))

        // reporter for TeamCity, enabled only in CI
        if (process.env.TEAMCITY_VERSION)
        {
            jasmine.getEnv().addReporter(new jasmineReporters.TeamCityReporter());
        }

        // Disable animations so e2e tests run faster
        var disableNgAnimate = function () {
            angular.module('disableNgAnimate', []).run(['$animate',function ($animate) {
                $animate.enabled(false);
            }]);
        }
        browser.addMockModule('disableNgAnimate', disableNgAnimate);

        // reporter taking screenshots when failed assertion is spotted, comment out to speed up test run
        var Jasmine2HtmlReporter = require('protractor-jasmine2-html-reporter');
        jasmine.getEnv().addReporter(new Jasmine2HtmlReporter({
            savePath: 'reports/screenshotReporter/',
            takeScreenshotsOnlyOnFailures: true,
        }))
    }
}
this.startSignUp = () => {
        element(by.css('#protractorjs')).click();
        this.waitForSpinnerFinished();
    }
wswebcreation commented 7 years ago

Hi there!

Your question is better suited for StackOverflow or Gitter. Please ask a question there with the 'protractor' tag or post in the Gitter Channel to get help.

From the the getting help section of the README:

Please ask usage and debugging questions on StackOverflow (use the "protractor" tag) or in the Angular discussion group. (Please do not ask support questions here on Github.)

Thanks!

cnishina commented 7 years ago

Actually, I saw this on Gitter and it might actually be a bug.

isDisplayed returns a count > 0 https://github.com/angular/protractor/blob/5.1.2/lib/element.ts#L444 count either returns a number or explodes in a bad way. https://github.com/angular/protractor/blob/5.1.2/lib/element.ts#L420

Here's the proposed solution:

  /**
   * Returns true if there are any elements present that match the finder.
   *
   * @alias element.all(locator).isPresent()
   *
   * @example
   * expect($('.item').isPresent()).toBeTruthy();
   *
   * @returns {Promise<boolean>}
   */
  isPresent(): wdpromise.Promise<boolean> {
    return this.count().then((count) => {
      return count > 0;
    }).catch(err => {
      return false;     // THE MAGIC!
    });
  }

By some random chance, the array could be length zero? I doubt that it could be zero. Anyway, we should still check that count > 0.

cnishina commented 7 years ago

@wswebcreation what do you think?

wswebcreation commented 7 years ago

@cnishina

Damn, you are right. Sorry for closing this to soon. Will you add a PR for this?

cnishina commented 7 years ago

Nope, the issue is with isDisplayed which we use the selenium-webdriver API. Anyway, what do you think of my check for isPresent?

cnishina commented 7 years ago

Oh wait, it's late at night. The code already does this in count. Shoot. Closing this issue...and writing a note to myself to get more sleep.

wswebcreation commented 7 years ago

@cnishina

Hmm, you also trigger me, when looking at the code the isDisplayed() is doing a check if the element is present. In the case the spinner is not present it will log this.

In my opinion this is a implementation issue in stead of a code issue.

He could better do 2 checks, first the isPresent, and if present do the isDisplayed check.

What do you think?

cnishina commented 7 years ago

I think isDisplayed already assumes that it is in the DOM and either is displayed or it is in the DOM but currently hidden. My guess is that the reporter to this issue thought that calling isDisplayed will work; however, it appears that it is not part of the DOM. My guess is that they really wanted isPresent since it would check how many elements actually exist on the DOM with the class spinner. So the way I would fix this:

this.waitForSpinnerFinished = () => {
       browser.wait(() => {
            return element(by.css('.spinner')).isPresent().then((result) => {
                return !result;
            })
        }, 30000);
    });
gaurabhi1986 commented 7 years ago

@wswebcreation

Can you please suggest me solution for 2 checks, first the isPresent, and if present do the isDisplayed check.