Should the Locators have awaits and is that causing flaky tests? - protractor

We're testing JS apps with protractor and sometimes we get some randomly unstable tests. Sometimes the errors are Failed: stale element reference: element is not attached to the page document
Just a hunch but sometimes developers write the code like this
await element(await by.css('.pager-next')).click();
And sometimes like this
await element(by.css('.pager-next')).click();
Is either of these "more" correct? Is there any need for the inner await or does it make no difference? Could this be causing stale element reference errors?

await is only useful for functions that return a Promise. Of the three functions in your snippet, only one of them returns a Promise. (You can check what each of them returns in the Protractor api).
ElementFinder.click() returns a Promise.
element() returns an ElementFinder.
by.css() returns a ProtractorLocator.
Therefore, the only call that should have await on it is click(), which you have done correctly in your second snippet.
StaleElementReferenceException is typically caused when you keep a reference to an object that has been removed from the page, e.g. using ElementFinder.getWebElement(). This removal can be subtle sometimes. For example, Angular will sometimes invisibly remove an element from the DOM and quickly replace it with an identical-looking one. It's hard to tell that anything even changed, but from Webdriver's perspective, the element it had a reference to has disappeared.

I think a better practice would be not to be write locators like that. I'd leave awaits for functions involving the element.
I would have a locator written like this:
const myElement = element(by.css('.pager-next'));
And then using async/await in a function:
let clickMyElement = async function(){
await myElement.click();
};

Related

Specific issue with reading data

I am not sure why the data is not loading in?? It was working fine before, then all of a sudden any file I try to read in just returns async
INPUT: data = FileAttachment("cincinnati_store.json").json
OUTPUT FROM CELL: data = async ƒ(…)
It looks like you need parentheses after .json. So, the input of the cell should look like:
data = FileAttachment("cincinnati_store.json").json()
You need the parentheses because json is a method on the FileAttachment (i.e. a function you have to call). That’s as opposed to something like the length of a JavaScript array, which is a property of the object, so you can just call myArray.length without parentheses. It’s fair to be confused by this — different objects do it differently, so you sort of just have to know (or look up) what’s what!
You get a hint there in the output of the cell (the “inspector”) because it’s telling you that the value of what you’ve put in is an asynchronous function. It’s showing you the function itself, as opposed to the return value of calling the function, so you can tell that you have to call it to get the Promise that resolves to your cincinnati_store.json data.
If that doesn’t work, if you post a link to your notebook I’d be happy to take a look.

I am having a problem with Flutter/Dart Async code execution, as in how does it work

In Flutter we use async await and Future, can someone explain that if we don't use another thread (which we can't in dart) and run the job on main UIThread only won't the app become choppy because even if we are waiting for the job to execute it will ultimately execute on UIThread only.
I somewhere read about isolates also. But cannot paint the exact picture. If someone can explain in detail.
I think you missed something when it comes to asynchronous methods in Dart.
Dart is a single-threaded programming language, Java or C# are multi-threaded programming languages, forget async as a new thread, it doesn't happen in Dart.
Dart is a single-threaded programming language. This means is that Dart can only run one instruction at a time, while Java could run multiple instructions concurrently.
As a rule, everything you do in Dart will start in UI-Thread. Whatever method you call in Dart, whether using sync, async, then, they will be running on UI-Thread, since Dart is a single thread.
In single-threaded languages ​​like Javascript and Dart, an async method is NOT executed in parallel but following the regular sequence of events, handled by the Event Loop. There are some problems (I would give some approaches, as we will see below) if you run the following code in a multithreaded language where fetch will take some time to execute:
String user = new Database.fetch(David);
String personalData = new Database.fetch(user);
You will receive David's data in user, and after that, you will receive your data.
This will lock your UI, unlike languages ​​like Java which have Threads, where you can perform this task in the background, on another thread, and the UI-Thread will run smoothly.
If you do this at Dart
String user = new Database.fetch(David);
String personalData = new Database.fetch(user);
user will be null in personalData, because the fetch event is a Future.
How to solve this in Dart?
String user = await Database.fetch(David);
String personalData = await Database.fetch(user);
For those who like a more functional paradigm (I don't like it) you can use then.
Database.fetch(David).then((user){
Database.fetch(user).then((personal){
String personalData = personal;
});
});
However, imagine that you have billions of data in that database, this heavy task will probably cause the animations on your screen to freeze, and you will see a jank in the user's UI, for that purpose isolates were invented.
Dart Isolates give you a way to perform real multi-threading in Dart. They have their own separate heaps(memory), and run the code in the background, just like the Threads of multi-threaded languages. I could explain how isolates work, but it would make this response very long, and the goal is just to differentiate asynchronous from multi-threaded methods.
A simple way to solve the problem above using isolates would be using compute.
Compute was created to facilitate the creation of isolates, you just pass the function and the data that this function will execute, and that's it!
Important to remember that compute is a Future, so you have to use await or then to get its result.
In our example, we could create a new thread and get its result when we finish by just calling compute like this:
String user = await compute(Database.fetch,David);
String personalData = await compute(Database.fetch,user);
Very simple, isn't it?
In summary:
Everything that waits some time to be completed, in Dart is called a "Future".
To wait for the result of a future to be assigned to a variable, use await or then.
The asynchronous methods (await and then) can be used to obtain a result from a Future, and are executed ON THE MAIN THREAD because Dart is single-thread.
If you want to run any function on a new thread, you can create an isolate. Dart offers an easy-to-use isolate wrapper called compute, where you only need to pass one method that will be processed and the data that will be processed, and it will return its result in the future.
NOTE: if you are going to use compute make sure you are using a static or top-level method (see that in the example I used Database.fetch it was no accident if you need to call Database().fetch or need to create an instance of it, means it is not a static method and will not work with isolates).
English is not my first language and I didn't want to write so much because of that, but I hope I helped differentiate between multi-threaded asynchronous programming from single-threaded asynchronous programming.

Is .indexWhere() async?

As indexWhere() searches through potentially large Lists to find the matching index, is this an async operation?
And if so is there some way to await it? e.g. similar to Future.forEach
Since the method does not return a Future but an int, then the method is synchronous:
https://api.dart.dev/stable/2.7.1/dart-core/List/indexWhere.html
I also want to point out that asynchronous code in Dart are not the same as the code is running in another thread. Since we are talking about finding a index inside a List, then you can be fairly sure that this operation can only be done in a single thread since we need to prevent modifications of the List when we are making the search.

Should a function returning a boolean be used in an if statement?

If I have a function call that returns true or false as the condition of an if statement, do I have to worry about Swift forking my code for efficiency?
For example,
if (resourceIsAvailable()) { //execute code }
If checking for the resource is computationally expensive, will Xcode wait or attempt to continue on with the code?
Is this worth using a completion handler?
What if the resource check must make a database call?
Good question.
First off... can a function be used? Absolutely.
Second... should it be used?
A lot of that depends on the implementation of the function. If the function is known (to the person who wrote it) to take a long time to complete then I would expect that person to deal with that accordingly.
Thankfully with a lot of iOS things like that are taken out of the hands of the developer (mostly). CoreData and Network requests normally come with a completion handler. So any function that uses them would also need to be async and have a completion handler.
There is no fixed rule for this. My best advice would be...
If you can see the implementation of the function then try to work out what it’s doing.
If you can’t then give it a go. You could even use the time profiler in Xcode profiler to determine how long it is taking to complete.
The worst that could happen is you find it is slow and then change it for something else.

Will inserting the same `<script>` into the DOM twice cause a second request in any browsers?

I've been working on a bit of JavaScript code that, under certain conditions, lazy-loads a couple of different libraries (Clicky Web Analytics and the Sizzle selector engine).
This script is downloaded millions of times per day, so performance optimization is a major concern. To date, I've employed a couple of flags like script_loading and script_loaded to try to ensure that I don't load either library more than once (by "load," I mean requesting the scripts after page load by inserting a <script> element into the DOM).
My question is: Rather than rely on these flags, which have gotten a little unwieldy and hard to follow in my code (think callbacks and all of the pitfalls of asynchronous code), is it cross-browser safe (i.e., back to IE 6) and not detrimental to performance to just call a simple function to insert a <script> element whenever I reach a code branch that needs one of these libraries?
The latter would still ensure that I only load either library when I need it, and would also simplify and reduce the weight of my code base, but I need to be absolutely sure that this won't result in additional, unnecessary browser requests.
My hunch is that appending a <script> element multiple times won't be harmful, as I assume browsers should recognize a duplicate src URL and rely on a local cached copy. But, you know what happens when we assume...
I'm hoping that someone is familiar enough with the behavior of various modern (and not-so-modern, such as IE 6) browsers to be able to speak to what will happen in this case.
In the meantime, I'll write a test to try to answer this first-hand. My hesitation is just that this may be difficult and cumbersome to verify with certainty in every browser that my script is expected to support.
Thanks in advance for any help and/or input!
Got an alternative solution.
At the point where you insert the new script element in the DOM, could you not do a quick scan of existing script elements to see if there is another one with the same src? If there is, don't insert another?
Javascript code on the same page can't run multithreaded, so you won't get any race conditions in the middle of this or anything.
Otherwise you are just relying on the caching behaviour of current browsers (and HTTP proxies).
The page is processed as a stream. If you load the same script multiple times, it will be run every time it is included. Obviously, due to the browser cache, it will be requested from the server only once.
I would stay away from this approach of inserting script tags for the same script multiple times.
The way I solve this problem is to have a "test" function for every script to see if it is loaded. E.g. for sizzle this would be "function() { return !!window['Sizzle']; }". The script tag is only inserted if the test function returns false.
Each time you add a script to your page,even if it has the same src the browser may found it on the local cache or ask the server if the content is changed.
Using a variable to check if the script is included is a good way to reduce loading and it's very simple:
for example this may works for you:
var LOADED_JS=Object();
function js_isIncluded(name){//returns true if the js is already loaded
return LOADED_JS[name]!==undefined;
}
function include_js(name){
if(!js_isIncluded(name)){
YOUR_LAZY_LOADING_FUNCTION(name);
LOADED_JS[name]=true;
}
}
you can also get all script elements and check the src,my solution is better because it hase the speed and simplicity of an hash array and the script src has an absolute path even if you set it with a relative path.
you may also want to init the array with the scripts normally loaded(without lazy loading)on the page init to avoid double request.
For what it's worth, if you define the scripts as type="module", they will only be loaded and executed once.