angular / protractor

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

Protractor tests , Jasmine and asynchronous solution #716

Closed marcelijanowski closed 10 years ago

marcelijanowski commented 10 years ago

I using in my work protractor with jasmine . What found annoying and disturbing is ways I have to write always tests. I really don't like to do this waitsFor for promise from getCssValue. Can someone can show me better solution for asynchronous tests then this. At moment using Jasmine 2.0:

describe('And I see a “Burger Menu” option on the  Header section', function () {
it('And the Left Hand Navigation is not visible When I access a Burger menu option on the ' +
'Header section Then I want to see the Left Hand Navigation menu', function () {
  runs(function () {
    Homepage.burger.click();
  });

  waits(500);

  runs(function () {
    Homepage.leftHandNav.getCssValue('display').then(function (item) {
      displayStatus = item;
    });
  });

  waitsFor(function () {
    return displayStatus;
  }, 200);

  runs(function () {
    expect(displayStatus).toBe('block');
  });
});

It seems like very complicated code for such functionality.

juliemr commented 10 years ago

Why are you using Jasmine 2.0 yourself instead of using Protractor directly?

marcelijanowski commented 10 years ago

Because I need more functionality. What would this change if I user only protractor ? Test would change and I wouldn't have such nonsense with asynchronous tests ? Can you show me how it should look like base on example above?

juliemr commented 10 years ago

Protractor patches jasmine so that it is automatically asynchronous, and a test case finishes when the webdriver queue of commands is finished. You can see this behavior in any of Protractor's own suite of tests or example tests: https://github.com/angular/protractor/blob/master/example/example_spec.js

marcelijanowski commented 10 years ago

OK . So expect() effectively unwraps promises, waiting on their resolution to run any associated assertion. But is seems in my case that this doesn't work so good because

expect(Homepage.leftHandNav.getCssValue('display')).toBe(true);

is failing because page this haven't been loaded and putting before

waits(500);

doesn't help.

juliemr commented 10 years ago

You should just be able to do:

it('...', function () {
    Homepage.burger.click();
    expect(Homepage.leftHandNav.getCssValue('display')).toBe(true);
});
marcelijanowski commented 10 years ago

In my case when I run what you put 3 time it will pass and on 4 in row its going to fail.... I cannot trust if something is flickering and time dependent.

juliemr commented 10 years ago

Protractor tries to sync with your application by waiting for any Angular $http requests, rendering, and $timeouts to finish. Maybe your app is doing something asynchronous outside of Angular?

On Wed, Apr 16, 2014 at 4:02 PM, Marceli Janowski notifications@github.comwrote:

In my case when I run what you put 3 time it will pass and on 4 in row its going to fail.... I cannot trust if something is flickering and time dependent.

— Reply to this email directly or view it on GitHubhttps://github.com/angular/protractor/issues/716#issuecomment-40662953 .

marcelijanowski commented 10 years ago

What about I have 4 request after them I hidding masking loading layer and burger menu elements fade in after clicking. Should I put after click waits for 500 but protractor doesn't seem to wait 500 and go straight to check element visibility. What is proper solution for such behaviour. Should I use in before each waits and then also waits inside it statment to wait for click action to finish and element is visible. Cheers for help because I really want to understand stuff and I don't have any additional call outside angular.

marcelijanowski commented 10 years ago

Maybe this is also worth of mentioning that I'm using requirejs for loading angular and all modules.

juliemr commented 10 years ago

You should not use Jasmine's wait/run infrastructure at all, it will interfere with Protractor's asynchronous management. The best way to do this is to use browser.wait to check for some condition which will tell Protractor that the application is ready to begin tests. Here's an example: https://github.com/angular/protractor/blob/master/spec/withLoginConf.js#L24

hankduan commented 10 years ago

@marcelijanowski Were you able to get it working?

haniehrossel commented 9 years ago

Hello juliemr, I have exactly the same issue. I tried your solution with browser.wait, but seems that protractor executes the part of the test which comes after the wait, just before the wait. How can I really block tests in my "it" part until the condition in browser.wait is true? Please help. I saw lot of issues related to my problem that you advise people to use expect or browser.wait and I tried them all, but protractor is not waiting for my condition. This is an example of my test:

it 'should be possible for a user to open the configuration panel, choose scala and write code', ->

  #click on a canvas diagram
  EipDiagram.clickAtPosition(328,34)
  #browser.sleep 2000

  #this is supposed to replace my above browser.sleep 2000 
  browser.driver.wait( (->
    ptor.isElementPresent(By.css('#routedesignConfiguration')).then (present) ->
      expect(present).toBe(true))
    ,10000, 'config panel should appear')

  #choose scala
  ConfigurationPanel.chooseLanguage(0)
  ConfigurationPanel.closePanel()

I use coffeescript. Also I tried your solution with "return !present" in wait function, but no result

juliemr commented 9 years ago

Please post questions like this on Stack Overflow, the issue tracker is a poor format to deal with them. On SO your answer can be shared and searched for. Feel free to edit your comment above to link to your question on SO.