Protractor Tutorial: Handling Timeouts With Selenium
A lot of times while performing Selenium test automation, you’ll come across certain scenarios when your test fails due to the fact that the webpage or the web element takes some time to load completely. In such scenarios, the best approach is to wait for the page or the web elements to load completely in order to avoid any errors due to timeout. These errors can be easily resolved if you know how to handle timeouts in Protractor with Selenium, as they help to set an interval of time before the next action is carried out.
To make it even simpler let’s say you visit Amazon’s website, you find a special deals button, you click on it and it brings out a popup with the offer, which further takes you to the deals page. These different elements like the button and pop-up takes some time to load and become interactive. But when we run our test scripts without any instruction to wait, it’ll end up throwing an error. To deal with this, we need to handle timeouts in Protractor with Selenium so that we give ample amount of time for the particular element to load.
So, in order to help you tackle this problem, I’ll show you how to handle timeouts in this Protractor tutorial. If you’re new to Protractor you can visit this Protractor tutorial on running your first test script for Protractor testing.
Timeout While Waiting For The Page To Load
While performing Selenium test automation to navigate a page on the browser, you’ll instruct the Selenium WebDriver to load the web page using the browser.get() command. Under the hood, the Protractor framework waits for the page to load completely.
So let’s take a test case to handle timeouts in Selenium Protractor, where we set the timeout as 5000 ms or 5 secs, the browser will wait for the page to load until 5 sec and returns an error if the page takes more time to load.
For this, you’ll have to add getPageTimeout (timeout in milliseconds) to your protractor configuration file, to reflect the change in timeout globally. But in case you want to provide the timeout for individual test cases, you’ll have to pass an additional parameter when calling the browser.get() i.e. browser.get ( address, the timeout in milliseconds ).
test_config.js
specs: ['test_timeout.js'], // overriding default value of getPageTimeout parameter // getPageTimeout: 10000, jasmineNodeOpts: { // overriding default value of defaultTimeoutInterval parameter // defaultTimeoutInterval: 10000 }, onPrepare: function () { browser.manage().window().maximize(); browser.manage().timeouts().implicitlyWait(3000); } }; // launches the URL in the browser // browser.get("http://the-internet.herokuapp.com");
Alternatively specifying the value as an argument to handle timeouts in Protractor with Selenium:
// launches the URL in the browser and specifying the timeout as a parameter // browser.get(http://the-internet.herokuapp.com,10000);
Timeout During Activity After Loading The Page
While performing any browser action on a page while performing Selenium test automation for Protractor testing, the javascript framework waits before proceeding with any action until there are no remaining asynchronous tasks in the application. It indicates that all the timeout along with the HTTP requests has been completed.
So let’s take a use case to handle timeouts in Protractor with Selenium where we set the default timeout as 6000 ms or 6 secs, the browser will wait after the page load before proceeding with any activity until 6 sec and then error out stating that it timed out waiting for asynchronous tasks to finish after 6000 ms.
For this, you’ll have to add allScriptsTimeout (timeout in ms) to the Protractor configuration file and this will reflect the change in timeout globally.
test_config.js
specs: ['test_timeout.js'], // overriding default value of getPageTimeout parameter // getPageTimeout: 10000, // overriding default value of allScriptsTimeout parameter for Protractor testing// allScriptsTimeout: 10000, jasmineNodeOpts: { // overriding default value of defaultTimeoutInterval parameter // defaultTimeoutInterval: 10000 }, onPrepare: function () { browser.manage().window().maximize(); browser.manage().timeouts().implicitlyWait(3000); }
You can also fix this by making a change in the web applications for Protractor testing. Protractor waits indefinitely and then time out if the AngularJS application continuously checks $timeout or $http. You can use the $interval for any continuous polling as introduced in Angular 1.2. For Angular applications, Protractor must wait until the Angular Zone is stabilized.
This means that long-running asynchronous operations would prevent your test from continuing. Hence, you’ll need to execute such tasks outside the Angular zone to have a workaround for this fix in this Protractor tutorial. For example:
this.ngZone.runOutsideAngular(() => { setTimeout(() => { // Any changes that are made inside this will not be reflected in the view of our application for Protractor testing // this.ngZone.run(() => { // if we run inside this block then it will detect the changes. // }); }, REALLY_LONG_DELAY); });
Timeout When Waiting For The Variable To Be Initialized
When launching any URL in the browser for Protractor testing, the protractor waits for the angular variable to be present while loading a new page.
Let’s take a use case to handle timeouts in Protractor with Selenium, where you set the default timeout as 8000 ms or 8 secs, the browser will wait for the angular variable on the page load before proceeding with any activity until 8 sec and return an error stating that angular could not be found on the page, retries looking for the angular exceeded.
For this, you’ll have to add getPageTimeout (timeout in millis) to your protractor configuration file to reflect the change in timeout globally. But in case if you want to provide the timeout individually during each loading of the web page in the browser, you’ll need to pass an additional parameter when calling the browser.get() i.e. browser.get ( address, the timeout in milliseconds ).
test_config.js
specs: ['test_timeout.js'], // overriding default value of getPageTimeout parameter to handle timeouts in Protractor with Selenium// getPageTimeout: 10000, jasmineNodeOpts: { // overriding default value of defaultTimeoutInterval parameter // defaultTimeoutInterval: 10000 }, onPrepare: function () { browser.manage().window().maximize(); browser.manage().timeouts().implicitlyWait(3000); } }; // launches the URL in the browser // browser.get("http://the-internet.herokuapp.com");
Alternatively specifying the value as an argument to handle timeouts in Protractor with Selenium.
// launches the URL in the browser and specifying the timeout as a parameter // browser.get(http://the-internet.herokuapp.com,10000);
Test Specification Timeout in Protractor
The test specification i.e. the ‘it block’ of the Protractor testing case that defines the test case to be executed. In case the test case takes a long time to execute, for any reason like the processing of the test case, then ‘it’ block will fail and result in an error.
If we consider an example to handle timeouts in Protractor with Selenium, where the default timeout is set as 15000 ms or 15 secs, the browser will wait for the spec to complete execution until 15 sec and then results in a failure in the test results.
You need to add jasmineNodeOpts (timeout in millis) to the protractor configuration file to reflect the change in timeout globally. But in case we would like to provide the timeout individually for each test specification, we can achieve this by passing the third parameter in the ‘it’ block i.e. it(description, testFunc, a timeout in milliseconds).
test_config.js
specs: ['test_timeout.js'], // overriding default value of getPageTimeout parameter to handle timeouts in Protractor Selenium // getPageTimeout: 10000, // overriding default value of allScriptsTimeout parameter // allScriptsTimeout: 10000, jasmineNodeOpts: { // overriding default value of defaultTimeoutInterval parameter // defaultTimeoutInterval: 30000 }, onPrepare: function () { browser.manage().window().maximize(); browser.manage().timeouts().implicitlyWait(3000); }
Alternatively, by passing as an argument:
// describing the test for the timeout example // describe(' Timeout Demonstration in Protractor ', function() { // tests to handle timeouts in Protractor Selenium// it('Tests to handle timeouts in protractor', function() { // launch the url in the browser // browser.get("http://the-internet.herokuapp.com "); }, 30000); });
Asynchronous Script Timeout in Protractor
The asynchronous script timeout is used to indicate the script to wait until the specified timeout limit so that it can complete its execution before the error is thrown to handle timeouts in Protractor Selenium.
So let us take a use case to handle timeouts in Protractor with Selenium where we set the default timeout as 7000 ms or 7 secs, the browser will wait for any asynchronous task to complete its execution to handle timeouts in Protractor Selenium, before proceeding with its throwing an error until 7 sec and then results into a ScriptTimeoutError out stating that it timed out waiting for asynchronous tasks.
In order to modify this behavior to handle timeouts in Protractor Selenium, you need to add allScriptsTimeout (timeout in millis) to the protractor configuration file and this will reflect the change in timeout globally.
test_config.js
specs: ['test_timeout.js'], // overriding default value of getPageTimeout parameter for Protractor testing // getPageTimeout: 10000, // overriding default value of allScriptsTimeout parameter // allScriptsTimeout: 10000, jasmineNodeOpts: { // overriding default value of defaultTimeoutInterval parameter // defaultTimeoutInterval: 30000 }, onPrepare: function () { browser.manage().window().maximize(); browser.manage().timeouts().implicitlyWait(3000); }
Ways To Toggle The Waiting Feature In Protractor
Whenever you want navigation or open a page in the browser that does not use Angular, we can disable this feature of waiting for timeout by passing the argument as false when calling the function i.e. browser.waitForAngularEnabled(false).
browser.waitForAngularEnabled(false); browser.get('/my_non_angular_page.html'); element(by.id('username')).sendKeys('myusername'); element(by.id('password')).sendKeys('mypassword'); element(by.id('clickButton')).click(); browser.waitForAngularEnabled(true); browser.get('/my_page-containing-angular.html');
But it might happen that we can get the Asynchronous Script TimeOut Exception from the WaitForAngular method. In such a case the first important thing would be to check on the timeout of our webdriver for scripts that have been set to something around 5 seconds for heavy and slowly loading websites.
Below is the complete code that demonstrates the behavior of handling timeouts in protractor.
// setting required config parameters // exports.config = { directConnect: true, // Desired Capabilities that are passed as an argument to the web driver instance. capabilities: { 'browserName': 'chrome' // name of the browser used to test // }, // Flavor of the framework to be used for our test case // framework: 'jasmine', // The patterns which are relative to the current working directory when protractor methods are invoked // specs: ['test_timeout.js'], // overriding default value of getPageTimeout parameter // getPageTimeout: 10000, // overriding default value of allScriptsTimeout parameter // allScriptsTimeout: 10000, jasmineNodeOpts: { // overriding default value of defaultTimeoutInterval parameter // defaultTimeoutInterval: 30000 }, onPrepare: function () { browser.manage().window().maximize(); browser.manage().timeouts().implicitlyWait(5000); } };
test_timeout.js
// import all the required modules from selenium web driver and protractor import 'selenium-webdriver'; import { browser, element, by, ExpectedConditions, protractor} from 'protractor' // describing the test for the timeout demonstration // describe('Timeout Demonstration in Protractor', function() { browser.ignoreSynchronization = true; // disable synchronization for non angular websites // // tests to handle timeouts in protractor // it('Tests to handle timeouts in protractor', function() { // launch the url in the browser // browser.get(http://the-internet.herokuapp.com , 10000); browser.manage().timeouts().implicitlyWait(5000); // locate the element // element(by.xpath(" // label/ span ")).getAttribute("innerTextValue").then(function(textValue){ // the value saved is assigned to the value of the text box element(by.xpath("//input[@type='text']")).sendKeys(textValue); }) },30000); });
Handle Timeouts In Protractor Selenium On Cloud Selenium Grid
We can run the same Selenium test automation script to handle timeouts in Protractor Selenium on a cloud Selenium grid that provides the capability to run the tests across various real-time browsers and devices. In order to run Selenium test automation scripts for this Protractor tutorial, we just require configuration changes i.e. for building a driver to connect with the LambdaTest hub. Below is our revised script with the appropriate modifications for this Protractor tutorial to handle timeouts in Protractor Selenium.
// test_config.js // // The test_config.js file serves as a configuration file for out Selenium test Automation case for this Protractor tutorial// LT_USERNAME = process.env.LT_USERNAME || "irohitgoyal"; // LambdaTest User name LT_ACCESS_KEY = process.env.LT_ACCESS_KEY || "r9JhziRaOvd5T4KCJ9ac4fPXEVYlOTealBrADuhdkhbiqVGdBg"; // LambdaTest Access key exports.capabilities = { 'build': ' Automation Selenium Webdriver Test Script ', // Build Name to be display in the test logs 'name': ' Protractor Selenium Timeout Test on Chrome', // The name of the test to distinguish amongst test cases // 'platform':'Windows 10', // Name of the Operating System 'browserName': 'chrome', // Name of the browser 'version': '79.0', // browser version to be used 'console':false, // flag to check whether to capture console logs. 'tunnel': false // flag to check if it is required to run the localhost through the tunnel 'visual': false, // flag to check whether to take step by step screenshot 'network':false, // flag to check whether to capture network logs }; // setting required config parameters // exports.config = { directConnect: true, // Desired Capabilities that are passed as an argument to the web driver instance for Selenium test automation. capabilities: { 'browserName': 'chrome' // name of the browser used to test // }, // Flavour of the framework to be used for our test case // framework: 'jasmine', // The patterns which are relative to the current working directory when protractor methods are invoked // specs: ['test_timeout.js'], // overriding default value of getPageTimeout parameter // getPageTimeout: 10000, // overriding default value of allScriptsTimeout parameter // allScriptsTimeout: 10000, jasmineNodeOpts: { // overriding default value of defaultTimeoutInterval parameter // defaultTimeoutInterval: 30000 }, onPrepare: function () { browser.manage().window().maximize(); browser.manage().timeouts().implicitlyWait(5000); } }; // test_script.js // // import all the required modules from selenium web driver and protractor import { browser, element, by, ExpectedConditions, protractor} from 'protractor' import 'selenium-webdriver'; var script = require (‘protractor’) ; var webdriver = require (‘selenium-webdriver’) ; // Build the web driver that we will be using in LambdaTest for this protractor tutorial var buildDriver = function(caps) { return new webdriver.Builder() .usingServer( "http://" + LT_USERNAME + ":" + LT_ACCESS_KEY + "@hub.lambdatest.com/wd/hub" ) .withCapabilities(caps) .build(); }; // describing the test for the timeout demonstration // describe(' Timeout Demonstration in Protractor ', function() { // disable synchronization for non angular websites // browser.ignoreSynchronization = true; // adding the before an event that builds the driver and triggers before the test execution beforeEach(function(done) { caps.name = this.currentTest.title; driver = buildDriver(caps); done(); }); // tests to handle timeout in Protractor Selenium// it(' Tests to handle timeout in protractor ', function() { browser.manage().timeouts().implicitlyWait(5000); // locate the element for Protractor testing // element(by.xpath(" // label/ span ")).getAttribute("innerTextValue").then(function(textValue){ // the value saved is assigned to the value of the text box element(by.xpath("//input[@type='text']")).sendKeys(textValue); }) },30000); }); browser.manage().timeouts().implicitlyWait(5000) // launch the url in the browser // browser.get(http://the-internet.herokuapp.com , 10000); // locate the element // // Store the value in a web element WebElement ele1 = element(by.id("ele1")).getWebElement(); // navigate to the next desired element i.e. ele1 browser.switchTo().frame(ele1); // locate the new element i.e. element 3 // WebElement ele3 = element(by.xpath("[@id='ele3']")).getWebElement(); // using the switchTo method to navigate to ele 3 browser.switchTo().frame(ele3); // search the element for the checkbox element by xpath locator WebElement checkbox = element(by.xpath("//input[@type='checkbox']")); // if checkbox is not selected then click the checkbox checkbox.isSelected().then(function(checked){ // if checkbox is not selected then click the checkbox if(! checked){ checkbox.click(); } }) } }); },30000); });
As we saw in our example for this Protractor tutorial, that just by appending a few lines of code, we can connect to the LambdaTest Platform and run our Selenium test automation script on the Cloud Selenium grid. In order to have this setup, we are required to generate the desired capability matrix.
You can visit LambdaTest Selenium desired capabilities generator to generate the required configuration through which we can specify the environment in which we would like to perform our tests. Also, we just need to pass our LambdaTest username and access key in the configuration file that will uniquely identify us on the LambdaTest platform.
Below is the output on running the Selenium test automation script on LambdaTest for this Protractor tutorial:
Also Read: How To Handle Alerts And Popups In Protractor With Selenium?
Wrapping It Up!
This brings us to the conclusion of this Protractor tutorial on how to handle timeout in Protractor Selenium. Throughout this article, I explored how to handle timeout and explored different approaches for it. After implementing this in our test scripts you’ll realize that it makes Selenium test automation scripts more effective. This helps to perform automated browser testing of websites that have multiple asynchronous tasks and might take some time to render on the browser windows.
Moreover, adding a timeout to our web page allows components on our web page to have enough time to load. This makes Protractor one of the best frameworks to test timeout for Selenium test automation. Also, since we know that protractor is based on selenium and used primarily for automated browser testing, it inherits many of its properties. Finally, there are many other functionalities of the framework available which I’ll discuss in the future Protractor tutorial.
I’d love to hear your opinion on this article in the comment section down below. Also, feel free to share this article with your friends on LinkedIn, Twitter, or any other social media platform. That’s all for now. Happy Testing!!!😄
Published on Java Code Geeks with permission by Praveen Mishra, partner at our JCG program. See the original article here: Protractor Tutorial: Handling Timeouts With Selenium Opinions expressed by Java Code Geeks contributors are their own. |