Only run tests if previous tests haven't failed - protractor

TL:DR; I have an list. You can: Add, Remove, Edit and Search/Filter items.
I want to run my tests only if the first test it('shall delete a new item', ..) was successful.
Is there a way I can do this?

I am looking for a better way to do this, but this is a hacky way I would do it.
Use afterEach to set a conditional
Return from test if that conditional is false;
var firstPassed = true;
it ('first test', function() {
....
});
it('second test', function(){
if (!firstPassed) return;
....
});
afterEach(function() {
if(this.results_.description === 'first test'){
if(this.results_.failedCount !== 0){
firstPassed = false;
}
}
}

You can tell protractor to "failfast". That is it should stop running subsequent tests as soon as one test fails. Not quite what you're asking for but technically accomplishes what you want in this case.
This is really a (missing) feature of the test runner (Jasmine, Jasmine2, etc), so the specific solution might be different. If you're using the default, Jasmine, see How to stop protractor from running further testcases on failure?

Related

Protractor Tests passing without performing the operation on WebPage

I want my Protractor test to open https://www.jetblue.com/ and click on Round Trip. Below is the piece of code I have written for the same :
describe('This test suite will validate booking related features', function(){
beforeAll(function(){
browser.driver.manage().window().maximize();
browser.ignoreSynchronization=true;
browser.waitForAngularEnabled(false);
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
})
beforeEach(function(){
browser.get('https://www.jetblue.com/');
browser.getTitle().then(function(text){
console.log("Title of the page is : " +text);
});
});
it('Customer can search for Flights for One Way Trip', function(){
var AllElements = element.all(by.xpath("//label[text()=' One-way ']/parent::jb-radio"));
AllElements.each(function(ele){
ele.click();
browser.sleep(10000);
});
});
});
The test is successfully passing without selecting the radio button. I used the same locators using Selenium-Java and test is actually performing the operation and passing. Makes me think which is actually better as Selenium-Java is equally effective on Angular applications as well.
The 'Roundtrip' radio button appears to be this element
<div _ngcontent-c47="" class="marker ba b--transparent bg-core-blue t-vfast"></div>
So I would try to use this locator:
element(by.css('.marker.ba.b--transparent.bg-core-blue.t-vfast'));

Protractor tests are inconsistent even with browser.wait and helper functions

I am looking for some advice. I have been using protractor for a few weeks and just cannot get my tests to be consistent unless I use browser.sleep. I have tried helper functions as well as browser.wait(expectedCondition). I have reduced browser.sleep immensely, but protractor still just goes way to fast. I can never successfully run multiple tests unless I have a few browser.sleeps just so protractor can relax for a second. Here is an example:
The Test I need to select a user, delete that user and wait for a success message. Then I click the same user and click the activate button.
Outcome: Unless I have browser.sleep, my success messages do not even appear after deletion/activation. The tests fail because protractor is moving way too fast. Even with the expected conditions. My main problem is that protractor moves to fast for the angular web page. I have tried ifCLickable or isDisplayed but they do not fix the issue entirely. Here is the code:
async deleteUser() {
await sendClick(this.getNewUser());
await sendClick(this.getDelete());
await waitTillPresent(this.getDeleteConfirm());
await sendClick(this.getDeleteConfirm());
await waitTillPresent(this.getSuccessMsg())
expect(await page.getSuccessMsg().isDisplayed()).toBeTruthy();
}
async activateUser() {
await sendClick(this.getNewUser());
await waitTillPresent(this.getEditBtn())
await sendClick(this.getActive());
await waitTillPresent(this.getSuccessMsg())
expect(await page.getSuccessMsg().isDisplayed()).toBeTruthy();
}
Functions:
export async function sendClick(element: ElementFinder): Promise<boolean> {
try {
if(!await element.isDisplayed()) {
return false;
}
await browser.executeScript('arguments[0].click();', await element.getWebElement());
return true;
}
catch (err) {
return false;
}
}`
export async function waitTillPresent (element: ElementFinder, timeout: number = 10000) {
return browser.wait(() => {
return element.isPresent();
}, timeout);
}
My Question: Am I handling this correctly? Is there a better to ensure my tests are consistent? Before these tests, I visit a non-angular webpage. So I have to include the line browser.waitForAngularEnabled(false)
Does this mess with the async nature of angular? Thank you.
I worked the last few months on our e2e test suite to make it stable. I did not believe it's possible but I made it using correct wait functions and sometimes browser.sleep() as a last resort.
You have a correct approach for waiting for elements. But there are 2 problems regarding your implementation:
1) The function waitTillPresent() does exactly what its name stands for. But if you only wait until the element is present on the page it does not mean it's clickable or displayed. An element can be hidden and at the same time still be present. Please rename waitTillPresent() to waitTillDisplayed() and change it as follows:
export async function waitTillDisplayed(element: ElementFinder, timeout: number = 20000): Promise<boolean> {
let result = await browser.wait(() => element.isPresent(), timeout);
if(!result) {
return false;
}
return await browser.wait(element.isDisplayed(), timeout);
}
2) You should exceed the default timeout. Set it a bit higher like 20 to 25 seconds. Just play with it.
Unfortunately, I don't know how browser.waitForAngularEnabled(false) changes test behavior. We do not use it :)
Note:
These functions are all exactly the same:
function foo() { return 'hello world'; }
var foo = () => { return 'hello world'; };
var foo = () => 'hello world';
Play with arrow functions, it's syntactic sugar.
Cheers and gl!

Protractor Timing Issues

I currently have the following code in one of my test specs for Protractor:
.then(function() {
return button.click();
})
.then(function() {
return element(otherButton).isDisplayed();
})
.then(function(otherButtonIsPresent) {
if(otherButtonIsPresent) {
return browser.wait(EC.elementToBeClickable(element(otherButton)), getWaitTime())
.then(function() {
element(otherButton).click();
return element(continueButton).isPresent();
})
}
})
When I use Chrome to debug using the --debug-brk and --inspect flags, I am able to pass these checks and resume as normal. When I run the same test without the flags, the test fails and stalls during looking for otherButton before trying to click on it.
I'm wondering if this is because during debugging, I set breakpoints and wait for the buttons to show up on the screen before attempting to click on them.
I need to make sure that this element is visible on the page before trying to click it and was wondering if there were another way if accomplishing this?
Thanks
I'm using Answer as I can't comment yet.
You're basically mention it yourself: after you clicked a button you just want to wait until a next button is clickable.
Therefore your .then()-functions should start from the button it depends on. To me it seems, the three lined-up .then()-functions depend on the same condition, so after you .click() the first button, the second .then() gets immediately executed, not waiting the previous .click() to finish.
Therefore putting the .then() directly behind the relevant .click() and inside the preceding .then()-function, this should work:
.then(function() {
element(button).click().then(function(){
element(otherButton).click().then(function(){
return element(continueButton).isPresent();
});
});
});
Or if you go with ExpectedConitions, you shouldn't need .then()-functions. Because Protractor should manage the ControlFlow, allowing you to write it without chained .then()-functions:
.then(function() {
browser.wait(EC.elementToBeClickable(element(button)), getWaitTime());
element(button).click();
browser.wait(EC.elementToBeClickable(element(otherButton)), getWaitTime());
element(otherButton).click();
browser.wait(EC.elementToBeClickable(element(continueButton)), getWaitTime());
return element(continueButton).isPresent();
});
This nice post elaborates a bit on asynchronous writing, but thanks to Protractor synchronous execution.
As alternative an example combining my both inputs, kind of double-securing the test:
.then(function() {
browser.wait(EC.elementToBeClickable(element(button)), getWaitTime());
element(button).click().then(function(){
browser.wait(EC.elementToBeClickable(element(otherButton)), getWaitTime());
element(otherButton).click().then(function(){
browser.wait(EC.elementToBeClickable(element(continueButton)), getWaitTime());
return element(continueButton).isPresent();
});
});
});

wait for http request to complete in protractor

I am trying to wait for spinner to disappear and then for my steps to execute but nothing is working for me.
browser.wait(function () {
return this.spinner.isDisplayed().then(function (result) {
return !result;});}, 20000);
and i even tried with
browser.wait(function () {
return !browser.isElementPresent(this.spinner);}, 20000);
even with below method
browser.sleep(1000);
this.spinner.isPresent().then(function (result) {
if (result === true) {
var EC = protractor.ExpectedConditions;
browser.wait(EC.invisibilityOf(this.spinner), 10000);}});
then only thing that works is
browse.sleep(10000);
i don't want to use sleep in my code. can anyone help me with how to wait for complete http request to complete and then process with testing
you should consider using Expected Conditions since they return true/false based on current conditions
http://www.protractortest.org/#/api?view=ProtractorExpectedConditions.prototype.invisibilityOf
so your test case would become:
browser.wait(EC.invisibilityOf(this.spinner),20000).then(function(){
...continue test, spinner gone
});
UPDATE
in order to use done, you would generally pass this cb into your it() function. This means your test could look like
describe("example describe",function(){
it("should be an example only", function(done){
request.get("www.google.com",function(res){
//done with async request, now call done
done();
})
})
});
Since your entire code isn't posted up here, you should have something similar to:
it("should wait for spinner to go bye-bye",function(done){
browser.wait(EC.invisibilityOf(this.spinner),20000).then(function(){
done()
});
});

Protractor - Ignore Synchronisation flag

I have started doing a POC on Protractor as our e2e automation testing tool.
Our application is designed in angular which makes it a perfect fit.
However, I need to login via google which is a non-angular website and therefore at the start of my test I state
browser.ignoreSynchronization = true;
Then I go to
'https://accounts.google.com/ServiceLogin'
Enter my google credentials and click on signin
At this point I try to go to my application's URL, which is an angular application so I was hoping to turn
browser.ignoreSynchronization = false;
All the the above steps are part of a beforeEach so that I can login before each test
But when I turn ignoreSynchronization to false, all my tests start failing.
On the other hand, if I don't turn it to false, I am compelled to use a lot of browser.sleeps as Protractor is still treating it as a non-angular app and does not wait for angular to load fully
I have also tried to put the ignoreSynchronization = false in each individual test as opposed to beforeEach but even then all my tests start failing.
Below is my beforeEach code
browser.ignoreSynchronization = true;
browser.driver.manage().window().setSize(1280, 1024);
browser.get(googlelogin);
email.sendKeys('username');
next.click();
browser.wait(EC.visibilityOf(pwd), 5000);
pwd.sendKeys('pwd');
signin.click();
browser.ignoreSynchronization = false;
browser.driver.get(tdurl);
Few things to fix:
wait for the "click" to go through
use browser.get() on the Angular Page
Here are the modifications:
signin.click().then(function () {
browser.ignoreSynchronization = false;
browser.get(tdurl);
browser.waitForAngular(); // might not be necessary
});
You may also add a wait with an Expected Condition to wait for the login step to be completed - say, wait for a specific URL, or page title, or an element on the page.
Reconciliation_verifyExapanedDatainExpanedRow: function (HeaderName, texttobepresent) {
browser.waitForAngular().then(function () {
var EC = protractor.ExpectedConditions;
var columnHeaderActive = GUtils.$locatorXpath('//p-datatable//span[contains(text(),"' + HeaderName + '")]/..//span[#class="ui-cell-data"][contains(.,\'' + texttobepresent + '\')]');
browser.wait(EC.presenceOf(GUtils.$element(columnHeaderActive)), GUtils.shortDynamicWait()).then(function () {
console.log('PASS');
}, function (err) {
console.log('FAIL');
});
});
},