I'm struggling dealing with Protractor's asynchronous nature.
On different connections or browsers, it seems that elements are sometimes found, sometimes not, depending on my connection speed.
Short of using .then() callbacks, what options are available to me within Protractor to deal with it's Async issues to make sure elements are fully loaded before moving onto the next action?
Thanks!
I had many problems like that.. to resolve it, if a element depends of a asynchronous call to be showed, I always put a browser wait before.
browser.wait(protractor.ExpectedConditions.elementToBeClickable(element(by.id('elementId'))), 3000);
element(by.id('elementId').click()
Based on your other question, it would seem you're testing a non-angular application. Hence, you will want to use ignoreSynchronization.
And thus, you'll need to handle async and all it's quirks yourself. Eg. using then() callbacks, and ExpectedConditions and the like.
Related
End users in our react application have the ability to make payments to loans via a pop up. The initial problem that we encountered is that users could click the pay button twice (or heaven forbid more than twice) and this would create multiple payments throwing our accounting into disarray. We thus implemented a sort of lock state that, when triggered to true, shows a loading gif displayed in a div with a simple tweak of the z-index. The state is passed down to the pop up from 2 components above. Every now and then I get an error message displaying that there is a possible memory leak. I assume this has something to do with my fix.
I'm just wondering, is there best practice on how to handle this sort of "locking" situation with react while waiting on some other external system to respond? I've tried to do this via the front-end but I'm not 100% convinced that it's the best and/or only solution.
If you need some code to better illustrate the scenario then let me know and I'll work on adding some examples.
Thanks in advance for your advice!
There's plenty of ways of doing this. You could even had multiple layers to the process. On top of layering the page using a z-indexed loading screen, you could also disable the button depending on some form of state change.
Also, the memory leak could be from you not disposing everything after the life cycle of a particular hook ends. I would suggest you look at using useEffect as a starting point. There's a good chance that either your modal or loading indicator is causing this. Often times, this can be fixed by adding a dependency array to useEffect. Obviously, I am making a lot of assumptions here.
I want to move appart from the selenium control flow in my Protractor tests.
Here are the steps and problems I went through so far:
1. Disable it test by test
My first idea was to use SELENIUM_PROMISE_MANAGER in order to move from selenium promises to async/await code.
Unfortunately, I found no way to put one test to SELENIUM_PROMISE_MANAGER=0 while keeping others to SELENIUM_PROMISE_MANAGER=1 in order to do the migration smoothly.
2. Keep it but use async/await too
So I thought about a code using async/await while keeping SELENIUM_PROMISE_MANAGER=1.
Unfortunately it seems not to be compatible: https://github.com/angular/protractor/tree/master/exampleTypescript/asyncAwait
There is nothing about such issue on Selenium side so I am wondering if this is an advice or a real it always fails.
3. Override promise.USE_PROMISE_MANAGER
Using protractor.promise.USE_PROMISE_MANAGER=false does not work for me (in beforeEach).
4. Call the control flow on async code
protractor.promise.controlFlow().execute(/* my async code*/);
For me it seems to mix async/await to control flow...
What is the right strategy?
I am wondering, what is the right strategy to move to async/await in Protractor tests?
I don't want to put everything in async/await in one change but to spread the change in multiple small changes
Incompatible, because
Read all about in this issue here.
As it's very technical, the way I (as relatively untechnical guy) understood it, is that jasminewd2, protractor and webDriver incl. ControlFlow are not designed to handle a mix of native promises and managed promises. It handle only managed promises and such are created by many jasminewd2-commands. However, async/await creates native promises and pushes it into the ControlFlow, which ends in a mix of both promises type and it all ends up with heavy timing issues. It can't be resolved as the ControlFlow works as expected and as it was designed for. The situation with async/await was never part of the ControlFlow design.
Switching off the ControlFlow to me means, managed promises get ignored. But because of async/await any managed promise would be wrapped inside a native promise and therefore it doesn't matter, that managed promises get ignored as you keep track of all asynchronous tasks already by tracking native promises only.
How to test both, migrated and not yet migrated test cases
Create two separate conf.js (or whatever your config file is named) and keep them separated. If you have common parts, i.e. helper functions, also migrate those and potentially keep the un-migrated as a duplicate as well. (create to .js-files or use a boolean-indicator to execute either or)
#DubZzz found a possible trick to move smoothly to async / await. His trick is to convert helpers using async / await and call them in protractor.promise.controlFlow().execute. Then move test by test and finally remove controlFlow execute and flag.
For Migration these links I can provide:
The official introduction and migration guide
A similar question witha well documented answer
A good blog about async/await and promises
The official thread about deprecate promise Manager. It also contains helpful information in how to make async/await work.
I have a get request in angular that returns a streaming response. The request is made through the oboe library. The streaming response basically returns json values and my angular front end adds each of these streams to the scope on receiving each json object. Since oboe is not a part of angular itself, I am using $scope.$digest to update my scope. This is cause a huge memory leak for larger requests. I have figured that I have to use $destroy at some point. Can someone please tell me on which event I should use the $destroy for optimal performance?
I would have to think a little more about the angular internals to give a good answer. However, have you considered using https://github.com/RonB/angular-oboe, or talking a look at how that project deals with updates? They don't seem to use either $digest or $destoy
I am using angular translate version 1.x for quite a while.
The use of the $translate service is really easy.
In a controller, you can simply write:
$scope.whatever = $translate('WHATEVER');
But in angular translate 2.x that has changed.
Now the service works async.
The simple and fast to write above statement has now become:
$translate('WHATEVER').then(function (whatever) {
$scope.whatever= whatever;
});
This makes things more complicated.
I don't really understand the need for this.
In most scenario's (?) the translation files will be downloaded once and then getting a translation value should be really fast. Why the need of handling this async?
Can anyone explain why this change was made?
Thanks
You should think the way around:
Who guarantees you, that all language files are loaded in time or at all. And as you're in a browser environment, everything retrieved from somewhere is asynchronous in terms of network speed etc.
So in case one "loading" process hangs, the whole application will be unusable because it is waiting for a correct reply/answer. So, if you do it synchronous, you'll have to wait until everything is loaded - just think of big images or translation files in our case here and maybe these are even unneeded translation files, because you're just using some languages out of the language stack as your personal preference.
Async loading speeds up the whole process of rendering the DOM and giving your "application" already a final state that you can work with, no matter, how many promises haven't been resolved yet.
This is one of the "big" natures of the Web Applications and yes, might cause headaches sometimes. Sometimes you'll ask yourself "why not wait this 500ms until everything is there?", but it could be the case, that one of the webservers is down or just overloaded and then you'll have to wait and wait and wait as a user. Do you always want this?
I'm attempting to write some UI tests for a RequireJS-based Backbone application, utilizing FluentAutomation.SeleniumWebDriver and NUnit. The HTML page in question contains a typical data-main attribute for loading the RequireJS module for the application. My struggle is in properly detecting when the application is fully loaded with these tools; the only thing I've gotten to work consistently so far is using an explicit wait in seconds, like so:
I.Open("http://myapp")
.Wait(5)
.Enter("foo").In("input[name=username]")
.Enter("bar").In("input[name=password]")
.Click("button")
.Wait(5)
.Expect.Text("Welcome").In("#welcome");
This is less than ideal -- my test as written above will always take at least 10 seconds to run, when in reality the app might be "ready" much faster than that. What I'd like to be able to do is something like this:
I.Open("http://myapp")
.WaitUntil(() => I.Assert.Exists("input[name=username]"))
.Enter("foo").In("input[name=username]")
.Enter("bar").In("input[name=password]")
.Click("button")
.WaitUntil(() => I.Assert.Exists("#welcome"))
.Expect.Text("Welcome").In("#welcome");
However, this doesn't work -- using WaitUntil here actually seems to prevent the app from loading, for reasons unclear to me, as I simply receive timeout exceptions after the default wait period (30 seconds), stating that it was unable to locate the element in question within that timeframe.
I see that Selenium 2 provides a WebDriverWait for this kind of scenario, and possibly that would work here, but am unsure how I would use this within FluentAutomation (and a quick search of the FluentAutomation code on GitHub doesn't seem to indicate it's in use within the library).
What can I use in FluentAutomation to properly wait for a RequireJS module (or DOM loaded by it) to be ready?
Additional details:
This might not be a RequireJS compatibility problem at all. I've looked further into the app and found that what's happening after the Click("button") is actually a window.location.replace -- not a RequireJS async module load. It's the one place in the app that this is occurring, apparently. So, is a window.location redirect a known scenario that would cause problems with WaitUntil, and is there an alternate approach (aside from a simple Wait(5)) that would properly handle this?