Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Allow defering e2e tests #375

Closed
vojtajina opened this issue Jun 7, 2011 · 8 comments
Closed

Allow defering e2e tests #375

vojtajina opened this issue Jun 7, 2011 · 8 comments

Comments

@vojtajina
Copy link
Contributor

// in e2e test
beforeEach(function() {
  browser().navigateTo('index.html#any-has');
  waitFor('event-name');
});


// in app under test
if (angular.isDefined(fireEvent)) fireEvent('event-name');

That would be helpful if user wants to use for example async script loading, since window load is fired before async scripts are loaded, so it could happen, that test is started before all scripts are loaded.

@esprehn
Copy link
Contributor

esprehn commented Jun 7, 2011

I'd rather not inject code into the app that's under test. End2End tests should run against your real application as a user would use it. Exposing this information to the page just asks for people to special case the app for test vs prod.

This should be solved with predicate matching. Your user can't see the fireEvent. How does the user know the page is ready? That's what you should verify in the test.

waitFor(function($document, done) {
  done(null, $document.find('div').length);
}, timeout);

@vojtajina
Copy link
Contributor Author

Awesome, like that - the same way how jasmine handle that: https://github.com/pivotal/jasmine/wiki/Asynchronous-specs
Thanks Elliot.

For example this test case should use asynchronous waitFor:

  • api/angular.validator.asynchronous should change color in delayed way

@ovidiusabou
Copy link

Do you have any idea if there is a work-around for this problem? Async script loading isn't that uncommon and I haven't seen e2e testing using angular-scenario documented anywhere.

@mkotsur
Copy link
Contributor

mkotsur commented Mar 25, 2013

Hi @ovidiusabou, I've written a DSL function to do something like that: https://gist.github.com/mkotsur/9e1f5253b86adcfa5a21

And here is how I use it:

        view.loginButton().click();

        waitForCondition("Redirect to albums and ready", function(doc, window) {
            return window.location.href.search("login.html") != -1 && window.document.readyState == 'complete';
        }, 10);

Originally I needed a way in e2e test to wait for the whole page (including images) to finish loading. waitForCondition function works except 2 things:

  • window.onload never seems to happen. Also all child elements don't fire the load event. Is it because of the iframe?
  • it's not possible to use full jquery (only jqLite) although it's available internally in angular-scenario module. May be it makes sense to expose it to make conditions like "waitForElementToAppear".

@vojtajina what do you think?

Does it make sense to write tests and push it into angularJS master? I'm quite sure that such DSL should be provided out-of-box.

@chrismilleruk
Copy link

I have a potential fix for this although it probably needs a bit of a tidy up/discussion before it goes much further.

I was able to demonstrate the issue fairly effectively by modifying the angular-seed project. If you check the top four commits of the following branch then it should be possible to demonstrate the problem by running the included e2e tests.
https://github.com/chrismilleruk/angular-seed/commits/e2e-async

Commits 1 & 3 create the problem (it's a race condition), commits 2 & 4 stop it from happening.

  1. chrismilleruk/angular-seed@bb22821
  2. chrismilleruk/angular-seed@8f3f38d
  3. chrismilleruk/angular-seed@dd547fa
  4. chrismilleruk/angular-seed@641f992

The one area where I believe it might be lacking is the possibility of multiple Angular applications on the same page. I've not seen any examples of e2e tests that cover this scenario so I'm not sure if it's a valid problem but it would be good to get some feedback here.

Thanks in advance.

Note that we have been running a slightly modified version of Angular.js internally containing the following fix for the same problem. The above is my attempt to feed the issue back to the Angular.js source in a clean manner.
blinkbox@959798b

@mkotsur It's also worth noting that like you, we went down the DSL route with a "waitForBootstrap()" function initially but moved away from it as our view of the problem matured.

@mkotsur
Copy link
Contributor

mkotsur commented Mar 26, 2013

@chrismilleruk What I'm trying to do is not wait for bootstrap, but to wait for custom condition. For example, after some user action the page has been altered with some heavy content (think of big image, or video) and you want to continue your test only when the image is loaded, or video is precached.

If I understand correctly, commit 4 triggers some event when angular is initialized (not scalable, doesn't help in situation which I've described), and commit 2 probably needs some explanation.

@chrismilleruk
Copy link

Hi @mkotsur,

Thanks for taking a look. My code changes are for the problem of "async script loading" as per the OP, not for your specific issue. Sorry if there is some confusion here, I'm happy to create a new issue if you think it makes sense.

Note also that my code is nowhere near production ready yet and needs some discussion from seasoned angularites before I go much further.

You are correct though, perhaps it deserves some narrative:

Commit 1 (chrismilleruk/angular-seed@bb22821) is the simplest expression of the problem that I have come across so far in that making the above simple change to the angular-seed project causes the e2e tests to fail.

The underlying issue is that angular-scenario requires a method to link frames and locate the application element in the app iFrame and it uses a local copy of the same angularInit() function used to auto-bootstrap a standard application. The upshot of this is that if the application element has ng:app or class="ng-app" etc. then angular-scenario will be able to find the correct element.

Commit 2 (chrismilleruk/angular-seed@8f3f38d) is essentially just an integrated in version of the solution in this post by @vojtajina a year ago:
https://groups.google.com/forum/#!msg/angular/yslVnZh9Yjk/MLi3VGXZLeMJ

Commit 3 (chrismilleruk/angular-seed@dd547fa) is to demonstrate that the above solution only fixes one half of a race condition. If angular-scenario has already attempted to link frames by the time the application bootstrap happens then the tests will fail again.

Finally Commit 4 (chrismilleruk/angular-seed@641f992) is one solution for the other side of the race condition. There are many others but they all have their positives and negatives. This isn't necessarily my preferred solution, it's just a possibility.

Another solution would be to make angular-scenario repeat the angularInit() call at intervals until it succeeds or fails with a timeout (I'm trying this one right now).

I'm pretty sure there's an elegant way to resolve this issue but I haven't found a solution that I'm happy with just yet.

Any feedback/ideas most appreciated.

c

@btford btford closed this as completed Aug 24, 2013
@btford
Copy link
Contributor

btford commented Aug 24, 2013

As part of our effort to clean out old issues, this issue is being automatically closed since it has been inactivite for over two months.

Please try the newest versions of Angular (1.0.8 and 1.2.0-rc.1), and if the issue persists, comment below so we can discuss it.

Thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants