How to stop automatically closing browser when writing protractor test cases - protractor

I am new to writing test cases using protractor for non angular application. I wrote a sample test case.Here the browser closes automatically after running test case.How can I prevent this. Here is my code
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
});
});

I was also struggling with a similar issue where i had a test case flow where we were interacting with multiple application and when using Protractor the browser was closing after executing one conf.js file. Now when I looked into the previous response it was like adding delay which depends on how quick your next action i performed or it was hit or miss case. Even if we think from debugging perspective most of the user would be performing overnight runs and they would want to have browser active for couple of hours before they analyze the issue. So I started looking into the protractor base code and came across a generic solution which can circumvent this issue, independent of any browser. Currently the solution is specific to requirement that browser should not close after one conf.js file is executed, then could be improved if someone could add a config parameter asking the user whether they want to close the browser after their run.
The browser could be reused for future conf.js file run by using tag --seleniumSessionId in command line.
Solution:
Go to ..\AppData\Roaming\npm\node_modules\protractor\built where your
protractor is installed.
Open driverProvider.js file and go to function quitDriver
Replace return driver.quit() by return 0
As far as my current usage there seems to be no side effect of the code change, will update if I came across any other issue due to this change. Snapshot of code snippet below.
Thanks
Gleeson
Snapshot of code snippet:

Add browser.pause() at the end of your it function. Within the function itself.

I found Gleeson's solution is working, and that really helped me. The solution was...
Go to %APPDATA%Roaming\npm\node_modules\protractor\built\driverProviders\
Find driverProviders.js
Open it in notepad or any other text editor
Find and Replace return driver.Quit() to return 0
Save the file
Restart your tests after that.
I am using
node v8.12.0
npm v6.4.1
protractor v5.4.1
This solution will work, only if you installed npm or protractor globally; if you have installed your npm or protractor locally (in your folder) then, you have to go to your local protractor folder and do the same.

I suggest you to use browser.driver.sleep(500); before your click operation.
See this.
browser.driver.sleep(500);
element(by.css('your button')).click();
browser.driver.sleep(500);

Add a callback function in It block and the browser window doesn't close until you call it.
So perform the action that you need and place the callback at your convenience
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function(callback) {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
// Have all the logic you need
// Then invoke callback
callback();
});
});

The best way to make browser NOT to close for some time, Use browser.wait(). Inside the wait function write logic for checking either visibilityOf() or invisibilityOf() of an element, which is not visible or it will take time to become invisible on UI. In this case wait() keep on checking the logic until either condition met or timeout reached. You can increase the timeout if you want browser visible more time.
var EC=protractor.ExpectedConditions;
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
browser.wait(function(){
EC.invisibilityOf(submitBtnElm).call().then(function(isPresent){
if(isPresent){
return true;
}
});
},20000,'error message');
});
});

I'm sure there is a change triggered on your page by the button click. It might be something as subtle as a class change on an element or as obvious as a <p></p> element with the text "Saved" displayed. What I would do is, after the test, explicitly wait for this change.
[...]
return protractor.browser.wait(function() {
return element(by.cssContainingText('p', 'Saved')).isPresent();
}, 10000);
You could add such a wait mechanism to the afterEach() method of your spec file, so that your tests are separated even without the Protractor Angular implicit waits.

var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
});
browser.pause(); // it should leave browser alive after test
});
browser.pause() should leave browser alive until you let it go.
#Edit Another approach is to set browser.ignoreSynchronization = true before browser.get(...). Protractor wouldn't wait for Angular loaded and you could use usual element(...) syntax.

Protractor will close browsers, that it created, so an approach that I am using is to start the browser via the webdriver-reuse-session npm package.
DISCLAIMER: I am the author of this package
It is a new package, so let me know if it solves your problem. I am using it with great success.

Related

assert.async() never fails

I am new to OpenUI5/QUnit testing. Sorry for the newbie question.
I have added a very basic async QUnit test into my OpenUI5 project:
QUnit.test( "Test async", function( assert ) {
var done = assert.async();
setTimeout(function() {
assert.ok(true);
done();
});
});
This test passes without errors as expected.
Then I have commented out everything except for
var done = assert.async();
The test runs indefinitely without failing. I would expect that it fails after some timeout.
Pressing the "Abort" button just changes the label to "Aborting" but does not fail the test.
I have search the QUnit documentation, that suggest adding
assert.timeout( 1000 ); // Timeout of 1 second
that should be an equivalent to global setting
QUnit.config.testTimeout( 1000 );
But using either crash my test with
assert.timeout is not a function
or
QUnit.config.testTimeout is not a function
I have tried running the test in Chrome, Firefox and IE11 with the same results.
Can anyone tell me what I am doing wrong?
I have found the answer myself. The correct syntax is:
QUnit.config.testTimeout = 1000;
It is then valid for all the subsequent tests. Alternatively I can write
assert.timeout(1000);
at the beginning of the test method - must be before assert.async()

Protractor Failed: element not interactable

I am running an E2E test for an Angular 7.x app. The test runs straight forward on my local machine. But when I push it on the repo (GitLab), then pipeline fails and throws following error:
USER PROFILE - Check and change PROFILE
- Failed: element not interactable
(Session info: chrome=71.0.3578.80)
(Driver info: chromedriver=2.45.615279 (12b89733300bd268cff3b78fc76cb8f3a7cc44e5),platform=Linux 4.14.74-coreos x86_64)
Test Case:
it('USER PROFILE - Check and change PROFILE', () => {
page.navigateTo();
browser.sleep(1000);
expect(page.getProfileEditTagName()).toMatch('app-edit-profile');
expect(element(by.className('logged-as')).getText()).toBe( testEmail );
browser.actions().mouseMove( element.all( by.id('editIcon-salutation') ).get(0)).click().perform().then(function () {
browser.sleep(4000);
element( by.className('mat-select-arrow') ).click().then(function () {
browser.actions().mouseMove( element.all(by.className('option-value mat-option')).get(0)).click().perform();
browser.sleep(1000);
browser.actions().mouseMove( element.all( by.id('saveButton-salutation') ).get(0)).click().perform();
browser.sleep(1000);
});
});
});
navigateTo() is just a method in profile.po.ts:
navigateTo() {
browser.get('/profileComponentUrl');
}
What's confusing me and where I even can't localize the bug or what's wrong, is that it works fine locally. But once I push to repo, then it fails exactly at that test case. Any Hint please?
The reason element is not interactable could be - performing an action on hidden or obscured element.
You can try -
1. add sleep after by.className('mat-select-arrow') ).click(), as I can see you have not added any waits there.
2. Try to check if you running the test on your local and Jenkins machine with same screen resolution. (this could be the reason of obscured element)
I'd recommend to:
Enable the stacktrace in protractor config: new SpecReporter({ spec: { displayStacktrace: true } }) so you can see exactly what element is throwing the error. This won't solve it but at least should point you in the right direction.
Then if you're using tabs, buttons or other elements that hide/show/disable/enable or change the DOM view, you add a browser.sleep(100) after calling a .click()
I had a same kind of problem and I found this.
I copy pasted that (and some other minor tweaks for example force clicking on previous page in for-loop) and it worked. I believe that the browser.driver.manage().window().maximize(); was part of the solution.
One reason which i figure out is the scroll issue. You need to check the element is displaying properly or not. It may be hidden. So use scrollToTop/scrollToElement/scrollToElementView etc. You can write different scroll methods which suites the condition better.
Another reason is the locator. Try to change the locator, do not trim the locator too much. Just try with full body css locator, if it works then trim properly. Some time in chrome console it may work but not with the test case.

How to make Protractor's browser.wait() more verbose?

In Protractor tests I call many times browser.wait method for example to wait once the particular element will appear on the screen or it will be clickable.
In many cases tests passes on my local machine, but does not on other.
I receive very generic information about the timeout which doesn't help me a lot to debug / find a source of issue.
Is it possible to make a browser.wait more verbose, for example:
if at least defaultTimeoutInterval will elapse when waiting for particular element, will it be possible to console.log information about the element that it tried to wait for,
take a screenshot when the timeout error occurs,
provide full call stack when timeout appears in browser.wait
If the main issue is that you don't know for which element the wait timed out, I would suggest writing a helper function for wait and use it instead of wait, something like:
wait = function(variable, variableName,waitingTime){
console.log('Waiting for ' + variableName);
browser.wait(protractor.ExpectedConditions.elementToBeClickable(variablename),waitingTime);
console.log('Success');
}
Because protractor stops executing test after first fail, if wait timed out, console won't print success message after failing to load a certain element.
For screenshots I suggest trying out protractor-jasmine2-screenshot-reporter, it generates an easily readable html report with screenshots and debug information on failed tests (for example, in which code line the failure occured).
Look into using protractor's Expected Condition, you can specify what to wait for and how long to wait for it.
For screenshots there are npm modules out there that can take a screenshot when a test fails. This might help.
browser.wait returns a promise, so catch the error and print/throw something meaningful like:
await browser.wait(ExpectedConditions.visibilityOf(css), waitingTime).catch((error) =>
{
throw new CustomError(`Could not find ${css} ${error.message}`)
});

How to wait for element not to be present anymore

I have a protractor test that navigates to another url, which cannot be found/resolved in my test environment, so I check if the title is not the previous title.
The test is as follows:
it('should navigate to another site in case of click on cancel link', function () {
page.navigate();
page.submit();
protractor.getInstance().ignoreSynchronization = true;
browser.wait(function(){
return element(by.id('submit')).isPresent();
});
page.closePage();
// the title of a 404, dns issue etc is at least different from the previous site:
expect(browser.getTitle()).not.toEqual('MyDummyTitle')
protractor.getInstance().ignoreSynchronization = false;
});
This works in most browsers, but in Internet Explorer I find that it often is not ready navigating to the non-existing page when the expect is fired.
Can I somehow wait for the 'submit' element to be gone, similar to what I do before firing the closePage?
What I do in this cases is an active wait of an element to disappear:
Using a custom waitAbsent() helper function that actively waits for an element to disappear either by becoming invisible or by not being present.
That helper waits up to specTimeoutMs ignoring useless webdriver errors like StaleElementError.
Usage: add require('./waitAbsent.js'); in your onPrepare block or file.
Example to wait for #submit to be gone:
expect(element(by.id('submit')).waitAbsent()).toBeTruthy();

How do you make the Chrome Developer Tools only show your console.log?

It adds logs when plugins say something. It adds logs when it gets anything from the cache manifest. It logs HTTP information sometimes.
My 1 little log gets flooded by 10,000 logs I don't need or want.
Use only in development:
(function(){
var originalConsole = window.console;
window.console = {};
window.console.log = window.console.debug = window.console.error = function(){};
window.myLog = function() {
originalConsole.log.apply(originalConsole, arguments);
};
}());
This will save a local copy of the original window.console object.
It will change the original window.console object to use empty functions.
And finally it will define a global myLog function which will use the local copy of the original window.console to actually log stuff.
This way all the other code will use the useless console.log() and your code could use myLog().
on the Console tab select No info on the left Hand I have attached a screenshot here
You should update to the google chrome latest version