Expected '' to equal 'Changes you made may not be saved.' - protractor

While running protractor test, getting below error :
✗Login without password(20 s)
Expected '' to equal 'Changes you made may not be saved.'. [stack]
Code is here which I have written in VS Code :
it('Login without password', function () {
browser.sleep(3000);
expect(browser.getCurrentUrl()).toContain('login');
browser.sleep(3000);
loginPage.loginInput.sendKeys('asd');
browser.sleep(3000);
browser.refresh().then(() => null, () => {
return browser.switchTo().alert().then((alert) => {
browser.sleep(3000);
expect(alert.getText()).toEqual('Changes you made may not be saved.');
browser.sleep(3000);
alert.accept();
browser.sleep(3000);
return loginPage.open();
});
});

Related

Protractor/Jasmine send REST Call when a test failed

I am using Protractor and Jasmine to test my hybrid mobile app, which works fine. I'd like to create an incident on my Team Foundation Server (TFS), when a test fails. Therefore, I have to send an REST-Call to the Api, which also works fine in my Angular App. But it does not work, when I am inside my test environment.
My Code:
var BrowsePage = require('./browse.page');
var tfsIncident = require('./tfsIncident_service');
var request = require('request');
describe('Testing the browse state', function () {
var browsePage = new BrowsePage();
var specsArray = [];
var reporterCurrentSpec = {
specDone: function (result) {
if (result.status === 'failed') {
var mappedResult = tfsIncident.create(result);
console.log(mappedResult); //This works so far, but then it crashes
var options = {
method: 'PATCH', //THis Method requiered the API
url: 'MY_COOL_API_ENDPOINT',
headers: {
'Authorization': 'Basic ' + btoa('USERNAME' + ':' + 'PASSWORD'),
'Content-Type': 'application/json-patch+json'
},
body: mappedResult
};
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
var info = JSON.parse(body);
console.log(response);
console.log(info);
}
}
request(options, callback);
}
}
};
jasmine.getEnv().addReporter(reporterCurrentSpec);
//This test passes
it('should be able to take display the heading', function () {
expect(browsePage.headline.isPresent()).toBe(true);
});
// Test is supposed to fail
it('should be able to fail', function () {
expect(browsePage.headline).toBe(1);
});
// Test is supposed to fail as well
it('should be able to fail too', function () {
expect(browsePage.headline).toBe(2);
});
});
So the problem is, that my only console output is (after the console.log(mappedResult)): E/launcher - BUG: launcher exited with 1 tasks remaining
So I have no idea, why this does not work.
Any help appreciated.
Edit
Protractor: 5.0.0
Appium Desktop Client: 1.4.16.1
Chromedriver: 2.27
Windows 10 64 Bit
Jasmine: 2.4.1
I finally got my problem solved. The problem was caused by ignoring the promises by jasmine. I had to add a .controllFlow().wait() to my protractor.promise
The following code works fine:
var BrowsePage = require('./browse.page');
describe('Testing the browse state', function () {
var browsePage = new BrowsePage();
var reporterCurrentSpec = {
specDone: function (result) {
if (result.status === 'failed') {
//Mapping of the result
var incident = [
{
op: 'add',
path: '/fields/System.Title',
value: 'Test: ' + result.fullName + ' failed'
},
{
op: 'add',
path: '/fields/System.Description',
value: result.failedExpectations[0].message
},
{
op: 'add',
path: '/fields/Microsoft.VSTS.Common.Priority',
value: '1'
},
{
op: 'add',
path: '/fields/System.AssignedTo',
value: 'Name Lastname <e#mail.com>'
}
];
protractor.promise.controlFlow().wait(create(incident)).then(function (done) { //The magic happens in this line
console.log("test done from specDone:" + done);
});
}
}
};
jasmine.getEnv().addReporter(reporterCurrentSpec); //Add new Jasmine-Reporter
function create(incident) {
var request = require('request');
var defer = protractor.promise.defer(); //new promise
request({
url: 'https://MY_COOL_ENDPOINT.COM',
method: "PATCH",
json: true, // <--Very important!!!
headers: {
'Authorization': 'Basic ' + new Buffer('USERNAME' + ':' + 'PASSWORD').toString('base64'),
'Content-Type': 'application/json-patch+json'
},
body: incident
}, function (error, response, body) {
console.log(error);
console.log(response.statusCode);
console.log(body.id); //Id of created incident on TFS
defer.fulfill({
statusCode: response.statusCode
}); //resolve the promise
});
return defer.promise; //return promise here
}
it('should be able to display the heading', function () {
expect(browsePage.headline.isPresent()).toBe(true);
});
it('should be able to fail', function () {
expect(browsePage.headline.isPresent()).toBe(false);
});
it('should be able to fail 2', function () {
expect(browsePage.headline.isPresent()).toBe(false);
});
});
Attention
When the test suite is done and the last promise is not resolved at this moment, the last incident is not created. I'll try to work around by adding to the last test a browser.sleep(5000); so that the create(incident) function gets more time to finish.
Thanks to this StackOverflow answer for helping me.

Index out of bounds when using element.all(by.binding)

User flow: Search for a case >> Search for an item within that case >> expect returned number of results matches value
describe('Search', function () {
beforeEach(function () {
loginPage.signIn();
loginPage.login(username, password);
});
afterEach(function () {
homePage.logOut();
});
it('alecxes suggestion code', function () {
var presenceOfAll = function(elementArrayFinder) {
return elementArrayFinder.count().then(function (count) {
return count > 0;
});
};
homePage.searchForCase(test_case);
filterSearchMenu.searchWithinCase(search_argument);
var hits = element.all(by.binding('response.hits.total'));
browser.wait(presenceOfAll(hits), TIMEOUT);
expect(element.all(by.binding('response.hits.total')).count()).toEqual(4);
});
});
This fails with expected 4 but was 0
describe('Search', function () {
searchResultTotal = element(by.binding('response.hits.total'));
beforeEach(function () {
loginPage.signIn();
loginPage.login(username, password);
});
afterEach(function () {
homePage.logOut();
});
it('should be able to search', function () {
homePage.searchForCase(test_case);
filterSearchMenu.searchWithinCase(search_argument);
browser.wait(EC.visibilityOf(searchResultTotal), TIMEOUT).then(function () {
expect(element.all(by.binding('response.hits.total')).count()).toEqual(4);
});
});
});
This works but comes back with a warning that more then one element found for locator by.binding('response.hits.total').
describe('Search', function () {
beforeEach(function () {
loginPage.signIn();
loginPage.login(username, password);
});
afterEach(function () {
homePage.logOut();
});
it('should be able to search', function () {
homePage.searchForCase(test_case);
filterSearchMenu.searchWithinCase(search_argument);
browser.wait(EC.visibilityOf(element.all(by.binding('response.hits.total')).first()), TIMEOUT).then(function () {
expect(element.all(by.binding('response.hits.total')).count()).toEqual(4);
});
});
});
This Fails and throws an index out of bounds.
Second set of eyes and any help would be appreciated.
You can also solve it with a custom Expected Condition that would check if there are more than 0 elements matching a locator found:
var presenceOfAll = function(elementArrayFinder) {
return elementArrayFinder.count().then(function (count) {
return count > 0;
});
};
var hits = element.all(by.binding('response.hits.total'));
browser.wait(presenceOfAll(hits), TIMEOUT);
expect(element.all(by.binding('response.hits.total')).count()).toEqual(4);
I'm thinking visibilityOf doesn't like multiple elements. Try:
browser.wait(EC.visibilityOf(element.all(by.binding('response.hits.total')).first()), TIMEOUT);

Protractor test: browser.get clears sessionStorage

I'm having a really weird issue with my protractor test. I'm trying to set the right credentials directly on the sessionStorage, but the authentication service doesn't pick up on it. I've isolated it to the following script:
describe('The search', () => {
beforeAll(() => {
browser.executeScript(() => {
window.sessionStorage.setItem('something', JSON.stringify({"test":"test"}));
});
});
it('works when changing URL', () => {
var result1 = browser.executeScript('return window.sessionStorage.getItem(\'something\')');
browser.get('/');
var result2 = browser.executeScript('return window.sessionStorage.getItem(\'something\')');
expect(result1).toBe(result2);
});
});
The output:
1) The search works when changing URL
Message:
Expected '{"test":"test"}' to be null.
Stack:
Error: Failed expectation
at Object.<anonymous> (/source/search.spec.ts:12:25)
at process._tickCallback (node.js:368:9)
So as you can see, as soon as browser.get() is called, the sessionStorage is cleared. Does anyone have any idea on why this could be happening?
Navigating to the URL and then setting the local storage item worked for me:
describe('The search', function () {
var value = JSON.stringify({"test":"test"});
beforeAll(function () {
browser.get('/');
browser.executeScript(function (value) {
window.sessionStorage['something'] = value;
}, value);
});
it('works when changing URL', function () {
var result = browser.executeScript('return window.sessionStorage.getItem(\'something\');');
expect(value).toEqual(result);
});
});

Test resolution is blocked when the expected condition fails

With Protractor, and using Mocha framework, I am comparing two arrays of values, one from a bar chart, one from text fields.
The code looks like this:
it("Each bar should have a value equal to its percentage", () => {
var identicalValue: boolean = false;
helper.getFirstValues(textLocator).then((textValue) => {
helper.getBarValues(barLocator).then((barValue) => {
identicalValue = helper.compareArray(textValue, barValue);
//compareArray returns a boolean, true if the arrays have the same values
expect(identicalValue).to.equal(true);
});
});
});
the functions are coded this way:
public getFirstValues(factsheetTab: protractor.ElementFinder): webdriver.promise.Promise<{}> {
var deferred = protractor.promise.defer();
factsheetTab.all(by.tagName("tr")).map((ele, index) => {
return {
index: index,
text: ele.all(by.tagName("td")).first().getText()
}
}).then((topValue) => {
deferred.fulfill(topValue);
},
(reason) => { deferred.reject(reason) });
return deferred.promise;
};
public getBarValues(factsheetTab: protractor.ElementFinder): webdriver.promise.Promise<{}> {
var deferred = protractor.promise.defer();
factsheetTab.all(by.tagName("tr")).map((ele, index) => {
return {
index: index,
text: ele.all(by.tagName("td")).last().element(by.tagName("div")).getAttribute("data-value")
}
}).then((barValue) => {
deferred.fulfill(barValue);
},
(reason) => { deferred.reject(reason) });
return deferred.promise;
};
My problem is that when the comparison returns false, so when the two arrays have differences, the test is blocked. It doesn't fail, the browser remains opened on that step, and the process stops, ignoring the remaining tasks.
Note: the function helper.compareArray returns a correct value. I could also write "expect(false).to.equal(true)" and get blocked too.
Am I doing something wrong in this test? Do you see a reason why this test is not finished?
edit: I found a workaround, to not get stuck in case of the test failing:
it("Each bar should have a value equal to its percentage", () => {
var identicalValue: boolean = false;
var textValue = null;
helper.getFirstValues(textLocator).then((value) => {
textValue = value;
});
helper.getBarValues(barLocator).then((barValue) => {
chai.assert.deepEqual(barValue, textValue);
});
});
(using #Brine's suggestion, for the deepEqual)
This seems to work, the other tests are ran if this one fails.
I'm still curious to know what was wrong with the first version though.
Not sure if this is a bug in your helper.compareArray or Mocha... but why not compare the arrays directly? I don't use Mocha but it seems something like this would work:
expect(textValue).deepEqual(barValue);

afterEach happening before it

I'm trying to use protractor to make e2e tests for one of our pages.
The pages are run in an iframe of a surrounding system.
So to be able to test my page I have to do all the things before "it ('Overview opened...". I'm not saying I have to do them in the way I have done. If there is a better way, please tell me.
Now my problem is that "errandClose is run before the tests in "Overview opened".
Have I done something wrong or misunderstood how protractor works.
describe('toplevel test', function() {
var login = new loginPage();
var role = new roleSelectionPage();
var errand = new overViewAndErrand(login.getBaseUrl());
beforeEach(function() {
login.getPage(); //Goes to login page and logs in
});
it('should log in', function () {
expect(element(by.model("therole")).isDisplayed());
describe('Select role', function() {
beforeEach(function () {
role.selectRole(); //Selects role on page after login and ends up at next page
});
it('Role selected', function() {
expect(element(by.css('a[href*="/OverviewNext"]')) !== undefined);
describe('Open overview', function() {
beforeAll(function() {
errand.open('name of errand'); //Selects errand and clicks on button, iframe i opened
});
afterEach(function() {
errand.close(); // Leaves the iframe and clicks on remove errand
});
it ('Overview opened', function() {
describe('Test form', function() {
browser.sleep(5000);
it ('test', function() {
browser.sleep(500);
element(by.model("modelvalue")).sendKeys('Ture Trana').then(function() {console.log('Ture Trana')});
});
});
});
});
});
});
});
});
As a response to the flat question.
How I would like to be able to run my tests is something like this
login.getPage();
role.select('role1');
errand.create();
begin
test 1
...
test n
end
errand.save();
role.select(role 2);
errand.open(previous errand);
begin
test 1
...
test n
end
login.logout();
Where all the selectRole, createErrand, openErrand involves going to at least one page and clicking on some buttons and selecting in lists.
You shouldn't nest describe() within it().
You should close this test before you start a new one
Example: This should be closed before you start a new describe.
it('Role selected', function() {
expect(element(by.css('a[href*="/OverviewNext"]')) !== undefined);
Here is an example with nested describes, that works for me.
describe('overview page', () => {
let hostUrl = configMock[0].response.data.URL;
beforeAll(() => {
//do magic
});
describe('all statement cards', () => {
beforeAll(() => {
browser.get(`${hostUrl}/z/y/1/g`);
browser.waitForAngular();
});
describe('Campaign overview', () => {
beforeEach(() => {
//before each magic
});
it('has correct data for Delivered', () => {
expect(delivered.getText()).toEqual('1.6k');
});
});
});
});
Starting from this, I think you can adapt it to your needs.