Accessing synchronous behavior via a Protractor instance - testing

I would like to inject a protractor instance into my tests, and then use this to perform navigation and element selection, but it appears that the functionality hanging off the Protractor object is all asynchronous, and the functionality on browser and element is synchronous.
Is there a way to access the synchronous behavior via the Protractor object?
Also: I have seen tests that invoke the following at the start:
protractor.getInstance()
...and I have seen tests that use the globally available browser and element objects directly.
What are the important differences between these two approaches?

Nothing in protractor is synchronous. It just looks that way before jasmine has been patched (by jasminewd) to wait for the async code so that it's easier to work with.
Please read https://code.google.com/p/selenium/wiki/WebDriverJs to see how controlflow makes everything in webdriver look synchronous. Then read https://github.com/angular/protractor/blob/master/docs/control-flow.md to see how protractor did it with jasminewd.
The link shared by #glepretre (stackoverflow.com/q/25496379/3049002) tells you the difference between ptor.get and browser.get. In short, use browser.get()

Related

How to interact with network tab in chrome using karate DSL when doing web automation

I am writing UI automation script using karate DSL. In this at certain point I need to get value from network call in chrome. I want to interact with one of the webservice call in chrome devtools network tab and get the json response of that webservice.
I need this because I have to extract the value from that particular call and pass it on to the next step in my automation script.
I have seen the question related to sessionStorage(Is there a way of getting a sessionStorage using Karate DSL?) but I wonder how to do the same for network call using script command or any other way?
The first thing I would recommend is don't forget that Karate is an API testing tool at its core. Maybe all you need to do is manually make that call and get the response. You should be able to scrape the HTML and get the host and parameters needed.
That said - there's a new feature (only for Chrome) which is documented here: https://github.com/intuit/karate/tree/develop/karate-core#intercepting-http-requests - and is available in 0.9.6.RC2
It may not directly solve for what you want, but in a Karate mock, you should be able to set a value for use later e.g. by using a Java singleton or writing to a temp-file.
If there is something oddly more specific you need, please contribute code to Karate. Finally, there is an experimental way in which you can actually make raw requests to the Chrome DevTools session: https://github.com/intuit/karate/tree/develop/examples/ui-test#devtools-protocol-tips - it is for advanced users, but maybe you are one :)

DOM Element Load Time Benchmarking

I'd like to benchmark my web application. Specifically I'd like to measure the load time of a particular DOM element.
I can use webdriver's wait for visible to measure how long a an element took to load and save the result somewhere. However I'd also like to measure concurrency and other factors.
Is there a standard way to do this?
While I love WebdriverIO, I would recommend using a tool other than it for benchmarking. WebdriverIO uses HTTP requests to send commands to Selenium, and because of that isn't the most performant thing. Your stats could be way off simply because the request from WebdriverIO to Selenium takes longer than usual.
I'd suggest using a tool a little "closer to the metal", possibly CasperJS

Protractor flakiness

I maintain a complex Angular (1.5.x) application that is being E2E tested using Protractor (2.5.x). I am experiencing a problem with this approach, which presents primarily in the way the tests seem flaky. Tests that worked perfectly well in one pull request fail in another. This concerns simple locators, such as by.linkTest(...). I debugged the failing tests and the app is on the correct page, the links are present and accessible.
Has anyone else experienced these consistency problems? Knows of a cause or workaround?
Just Say No to More End-to-End Tests!
That said, here are the few things you can do to tackle our mutual merciless "flakiness" enemy:
update to the latest Protractor (currently 4.0.0) which also brings latest selenium and chromedriver with it
turn off Angular animations
use dragons browser.wait() with a set of built-in or custom Expected Conditions. This is probably by far the most reliable way to approach the problem. Unfortunately, this is use-case and problem specific, you would need to modify your actual tests in the problematic places. For example, if you need to click an element, wait for it to be clickable:
var EC = protractor.ExpectedConditions;
var elm = $("#myid");
browser.wait(EC.elementToBeClickable(elm), 5000);
elm.click();
maximize the browser window (to avoid random element not visible or not clickable errors). Put this to onPrepare():
browser.driver.manage().window().maximize();
increase the Protractor and Jasmine timeouts
slow Protractor down by tweaking the Control Flow (not sure if it works for 4.0.0, please test)
manually call browser.waitForAngular(); in problematic places. I am not sure why this helps but I've seen reports where it definitely helped to fix a flaky test.
use the jasmine done() callback in your specs. This may help to, for example, not to start the it() block until done is called in beforeEach()
return a promise from the onPrepare() function. This usually helps to make sure things are prepared for the test run
use protractor-flake package that would automatically re-run failed tests. More like a quick workaround to the problem
There are also other problem-specific "tricks" like slow typing into the text box, clicking via JavaScript etc.
Yes, I think all of us experienced such flakiness issue.
Actually, the flakiness is quite common issue with any browser automation tool. However, this is supposed to be less in case of Protractor as Protractor has built-in wait consideration which performs actions only after loading the dom properly. But, in few cases you might have to use some explicit waits if you see intermittent failures.
I prefer to use few intelligent wait methods like:
function waitForElementToClickable(locator) {
var domElement = element(by.css(locator)),
isClickable = protractor.ExpectedConditions.elementToBeClickable(domElement);
return browser.wait(isClickable, 2000)
.then(function () {
return domElement;
});
}
Where 2000 ms is used as timeout, you can make it configurable using a variable.Sometimes I also go with browser.sleep() when none of my intelligent wait works.
It's been my experience that some methods (eg. sendKeys()) do not always fire at the expected time, within the controlFlow() queue, and will cause tests to be flakey. I work around this by specifically adding them to the controlFlow(). Eg:
this.enterText = function(input, text) {
return browser.controlFlow().execute(function() {
input.sendKeys(text);
});
};
A workaround that my team has been using is to re-run only failed tests using the plugin protractor-errors. Using this tool, we can identify real failures versus flakey tests within 2-3 runs. To add the plugin, just add a require statement to the bottom of the Protractor config's onPrepare function:
exports.config = {
...
onPrepare: function() {
require('protractor-errors');
}
}
You will need to pass these additional parameters when to run your tests with the plugin:
protractor config.js --params.errorsPath 'jasmineReports' --params.currentTime (timestamp) --params.errorRun (true or false)
There is also a cli tool that will handle generating the currentTime if you don't have an easy way to pass in a timestamp.

Explicit selenium waits in intern

How can I use explicit waits using intern's leadfoot API for functional testing in intern?
There are multiple scenarios where I want to explicitly poll until a condition is met. For example, I want to wait until two or more elements exist in the DOM. Using findAllByCssSelector locks the execution for the whole implicit wait time instead of returning immediately after the condition is true.
All I can see that will help me is the pollUntil helper function, but it looks like this does not have access to any of the module dependencies defined in the test module.
How can I use something like jQuery within pollUntil?
findAllByCssSelector only waits for the implicit wait if no elements are found. If elements exist, the method finishes immediately with whatever it finds, so it's not ideal if you need to wait for a specific number of elements to appear.
pollUntil is the way to go for conditional waits. You are correct, though, that it doesn't have access to your module dependencies. Your dependencies are loaded in the context of Intern's test runner, while the pollUntil condition is going to run in the context of the browser. There are a couple ways to get the code you need into the browser. If you control the test page, you could just modify it to load whatever modules you need before the tests run. If you can't modify the test page, you could use an executeAsync call after loading the page in your test to inject whatever modules you need into the page context.

PhantomJS, but not headless?

Is there a way to get a realtime view of what PhantomJS (or similar) is rendering?
I would like to develop my automation script while interacting with (or at least seeing a screencap of) the page it's targeted to.
No, there is no such thing. SlimerJS has the same API as PhantomJS, but runs the Gecko engine. You can see directly what is going on and run it headlessly with xvfb-run.
You will not be able to interact with it. You may want to use a screengrabber to record a video of the interaction when the tests are long and you don't want to run the test suite again if you didn't catch the problem in the test case.
The obvious way to debug PhantomJS scripts is to render many screenshots using page.render() and logging some objects to the console with
console.log(JSON.stringify(yourObj, undefined, 4));
with nice formatting.
Solution we use is an automatic screenshoting in case of exceptions, phantomJs will render the current page into a file that you can exam later .
That's for test execution phase.
When you writing the tests, just keep additional window open ("normal browser") with the application you trying to test and design the test according to it.
When the design is done, execute the test with phantomJS.
My Suggestion is to use logging alongside.
http://casperjs.org/
CasperJS is an open source navigation scripting & testing utility written in Javascript for the PhantomJS WebKit headless browser and SlimerJS (Gecko). It eases the process of defining a full navigation scenario and provides useful high-level functions, methods & syntactic sugar for doing common tasks such as:
defining & ordering browsing navigation steps
filling & submitting forms
clicking & following links
capturing screenshots of a page (or part of it)
testing remote DOM
logging events
downloading resources, including binary ones
writing functional test suites, saving results as JUnit XML
scraping Web contents
The solution to this problem is using the remote debugger:
--remote-debugger-port=9000
Using slimerjs for testing scripts with a browser is not advisable since it is based on gecko, which means the script might work on slimerjs and not on phantomjs or viceversa.
take a look at this guide for more info...
https://drupalize.me/blog/201410/using-remote-debugger-casperjs-and-phantomjs