afterEach happening before it - protractor

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.

Related

How to stop functions when leaving the page in Ionic 4

I am working in my Ionic 4 app and I want to stop the functions when the page will leave.
This is my tab4.page.ts:
async getUserDetail(){
this.dataexists = false;
this.userActiveChallanges = [];
let me=this;
const loading = await this.loadingController.create({
message: '',
// duration: 2200,
translucent: true,
spinner: 'crescent',
showBackdrop: false,
cssClass: 'my-loading-class'
});
await loading.present();
this.userActiveChallanges=[];
this.storage.get('USERPROFILE').then(userObj => {
// console.log('User Profile :',userObj);
me.userprofile = userObj;
me.sendFitDatafunction(userObj);
me.myapi.apiCall('userActiveChallenges/'+userObj.id,'GET','').subscribe((data) => {
// console.log(data);
me.response=data;
loading.dismiss();
if(me.response.status === 'success'){
if(me.response && me.response.data && me.response.data.length>0){
this.userActiveChallanges=me.response.data;
this.flip(this.userActiveChallanges[0].challenge_id);
}
this.dataexists = true;
} else{
this.userActiveChallanges = '';
this.dataexists = true;
}
}, error => { loading.dismiss(); console.log(error); });
});
}
ionViewWillLeave() {
}
I want to stop this function when the page will leave because when I am not getting any response nor any error from the api the loader keeps running and when I move to the other page, it is showing there.
So, I want to stop the function when the page will leave.
Any help is much appreciated.
instead of local const loading, declare it as a property of your ts class (tab4).
now change your code and assign loader to it:
replace: const loading
with:
this.loading
Now inside ionViewWillLeave call:
ionViewWillLeave() {
if (this.loading) { this.loading.dismiss() }
}
Well, I don't know the function to stop your function, but to make something when you leave a page, you make it in IonViewDidLeave()

Protractor ignoring specs passed in a callback function

I'm running into an issue and need your help.
I have a list of products and I want to run some it blocks for each product.
The function getProducts is an asynchronous function. Here is my code.
jsonLoader = new Promise(function(resolve, reject) {
beforeAll(function(done) {
getProducts(function(loadedProducts) {
resolve(loadedProducts);
done();
});
});
});
describe('product-maintenance', function() {
jsonLoader.then(function(products) {
productsList = products;
//productsList contains the desired products
_.forOwn(productsList, function(product) {
//execute it-blocks
});
});
it('some test', function() {
expect(1).toBe(1);
});
});
He is only executing the it 'some test' and simply ignoring the it blocks in the _.forOwn loop.
Thanks !!! :)
I solved this by using promises in the onPrepare function.
onPrepare: function() {
var deferred = protractor.promise.defer();
getProducts(function(products) {
if (!products) {
deferred.reject(new Error('An error occured while loading products'));
} else {
productsModule.setProducts(products);
deferred.fulfill();
}
});
return deferred.promise;
}

Protractor & Cucumberjs after hook doesn't work as expected

I have written a basic after hook in cucumberjs for some reason , it is not working as expected.It is supposed to attached screenshot and write browser console log , when scenario fails. But it attaches the screen shot after the feature in html report and prints the browser console log at after in between the second scenarioenter image description here.Any clue what's wrong??
this.After(function(scenario, callback) {
if (scenario.isFailed()) {
global.browser.takeScreenshot().then(function(base64png) {
var decodedImage = new Buffer(base64png,'base64').toString('binary');
scenario.attach(decodedImage, 'image/png');
});
global.browser.manage().logs().get('browser').then(function (browserlog){
browserlog.forEach(function (log) {
if (log.level.value > 900) {
console.error(log.message.substring(log.message.indexOf('Error'),log.message.indexOf('\n')))
}
})
});
callback();
} else {
callback();
}
});
According to the cucumberjs github page https://github.com/cucumber/cucumber-js#attachments
Images and other binary data can be attached using a stream.Readable. In that case, passing a callback to attach() becomes mandatory:
You could split the single after hook into two separate hooks:
this.After(function(scenario, next) {
browser.takeScreenshot().then(function(png) {
var decodedImage = new Buffer(png, 'base64').toString('binary');
scenario.attach(decodedImage, 'image/png', next);
}, function(err) {
next(err);
});
});
this.After(function(scenario, next) {
global.browser.manage().logs().get('browser').then(function (browserlog){
browserlog.forEach(function (log) {
if (log.level.value > 900) {
console.error(log.message.substring(log.message.indexOf('Error'),log.message.indexOf('\n')))
}
});
});
});

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);
});
});

When I isolate a test it passes, but when run sequentially with other tests it fails with NoSuchElementError

I was making some changes to the page objects we use for running our Protractor tests to run on Sauce Labs i.e., calling a utility method to get browser and platform so we can use the appropriate test user, and after making the change I kept getting a NoSuchElementError when running the test suite.
When I isolate the logout test, it passes, but when run in conjunction with any other files, it fails. Currently, I'm only running the login test and logout test on Chrome to limit the possible causes.
We use page objects to navigate to a testable state, in this case a login page object and a dashboard page object (logging in takes you to the dashboard).
The login page object:
'use strict';
var TestUtils = require('../../util/test-utils.js');
var HeaderPageElement = require('../page_elements/header-page-element.js');
var LoginPage = function () {
var self = this;
this.get = function () {
browser.get('http://localhost:9000/index.html');
this.header = new HeaderPageElement();
this.loginForm = element(by.name('loginForm'));
this.usernameInput = element(by.model('credentials.username'));
this.passwordInput = element(by.model('credentials.password'));
this.loginButton = element(by.name('loginButton'));
this.signupLink = element(by.xpath('//a[#ui-sref="signup"]'));
};
this.setCredentials = function (username, password) {
var deferred = protractor.promise.defer();
var testUtils = new TestUtils();
testUtils.getCapabilities().then(function (capabilities) {
return testUtils.getTestUser(capabilities.browserName, capabilities.platform);
}).then(function (testUser) {
username = username || testUser.username;
password = password || testUser.password;
self.usernameInput.sendKeys(username);
self.passwordInput.sendKeys(password);
deferred.fulfill();
});
return deferred.promise;
};
this.login = function (username, password) {
return this.setCredentials(username, password).then(function () {
return self.loginButton.click();
});
};
this.signup = function () {
return this.signupLink.click();
};
this.get();
};
module.exports = LoginPage;
The dashboard page object:
'use strict';
var LoginPage = require('./login-page.js');
var HeaderPageElement = require('../page_elements/header-page-element.js');
var ProjectCreateModalPageElement = require('../page_elements/project-create-modal-page-element.js');
var DashboardPage = function () {
var self = this;
this.get = function () {
var loginPage = new LoginPage();
loginPage.login();
this.header = new HeaderPageElement();
this.newProjectButton = element(by.name('newProjectButton'));
this.projectFilterInput = element(by.name('projectFilterInput'));
};
this.createNewProject = function (projectTitle, projectTypes) {
var deferred = protractor.promise.defer();
this.newProjectButton.click().then(function () {
var modalPage = new ProjectCreateModalPageElement();
modalPage.createNewProject(projectTitle, projectTypes);
deferred.fulfill();
});
return deferred.promise;
};
this.get();
};
module.exports = DashboardPage;
These are the tests that are being run.
The login test:
'use strict';
var LoginPage = require('./pages/login-page.js');
describe('login test', function () {
var page;
beforeEach(function () {
page = new LoginPage();
});
it('should be directed to login', function () {
expect(page.loginForm.isPresent()).toBe(true);
});
it('Login button should be disabled', function () {
expect(page.loginButton.getAttribute('disabled')).toEqual('true');
page.setCredentials('wrong', 'user').then(function () {
expect(page.loginButton.getAttribute('disabled')).toEqual(null);
});
});
it('login should fail and remain at login screen', function () {
page.login('wrong', 'user').then(function () {
expect(page.loginForm.isPresent()).toBe(true);
});
});
it('login success should redirect to dashboard', function () {
page.login().then(function () {
browser.wait(function () {
return $('#dashboard').isPresent();
});
expect($('#dashboard').isDisplayed()).toBe(true);
});
});
});
The logout test:
'use strict';
var DashboardPage = require('./pages/dashboard-page.js');
describe('logout test', function () {
var page;
beforeEach(function () {
page = new DashboardPage();
});
it('logout success should redirect to login page', function () {
page.header.logout().then(function() {
browser.wait(function () {
return $('#login').isPresent();
});
expect($('#login').isDisplayed()).toBe(true);
});
});
});
The error I get when running these tests sequentially is as follows:
NoSuchElementError: No element found using locator: by.model("credentials.username")
The line it specifies is the get method inside the DashboardPage object, whereby it instantiates a LoginPage object and calls the login method so as to navigate to the dashboard:
this.get = function () {
var loginPage = new LoginPage();
loginPage.login();
this.header = new HeaderPageElement();
this.newProjectButton = element(by.name('newProjectButton'));
this.projectFilterInput = element(by.name('projectFilterInput'));
};
For whatever reason, the usernameInput of the login page hasn't been set by the time the login method is called.
I'm quite sure it's got something to do with not having coded promises correctly, but I've been bashing my head against it for days without any success. Any help would be greatly appreciated.