Page reloading for every "it" statement in protractor and printing "." - angularjs

Have anyone found fix for this. I am new to protractor and got some script running. I have a login page and once logged in search for a user. My spec.js has the following structure.
describe('Smoke', function() {
//sum stuff
beforeEach(function () {
browser.get('https://login/');
});
it('should have a title', function() {
expect(browser.getTitle()).toEqual('title');
browser.pause()
});
it('and Login to MSIX', function () {
login.login(username);
});
it('search for a user', function () {
searchUser.searchForUser();
});
it ('print test result', function () {
var userN = loginName.getText().then((text) => {
return text;
})
// at this point data is still a managed promise!
userN.then((text) => {
console.log("Logged in user is: "+text);
console.log("User " +username+" logged in successfully"); // your text would be printed!
})
})
});
For every "it" statement the page reloads and I am losing the content on the page. Also if you notice the last "it" statement to print test result I am noticing "." before the output in console
**..**[12:55:55] W/element - more than one element found for locator by.model("query.identifier") - the first result will be used
**.**Logged in user is: sample user
User abc logged in successfully
**.**

You are telling it to reload the page for every it by using beforeEach:
beforeEach(function () {
browser.get('https://login/');
});
Use beforeAll instead:
beforeAll(function () {
browser.get('https://login/');
});

Related

Data Driven Test - Protractor

I want is to edit a profile details with passing data from a json file.
Data Form having:
-First Name
-Last Name
-Current Password
-New Password
-Confirm Password, etc....
I need to change only Last Name. How can I do?
--Edited--
"This is the form which I have to edit."
I need to change Only the Last name, First name should be the same. I'm passing values through json file.
[
{
"fname":"" ,
"lname":"",
"currentpassword":"",
"newpassword":"",
"confirmpassword":""
}
]
And this is the code :
//import login details
var testData = require('./login_details.json');
//import editprofiledata
var editData = require('./editprofiledata.json');
describe ('Edit Profile Test', function(){
//browser.driver.manage().window().maximize();
browser.get("http://example");
testData.forEach (function (data) {
it ('Login to the system, and redirect to the dashboard', function() {
element(by.name('email')).clear().sendKeys(data.Email);
element(by.name('password')).clear().sendKeys(data.Password);
//**click on Login button**//
element(by.css('[ng-disabled="register.$invalid"]')).click();
//**popup message click**//
element(by.css('[ng-click="tapToast()"]')).click();
});
});
it("redirect to the Edit Profile",function () {
element(by.css('[ng-click="profileView()"]')).click();
element(by.css('[ng-click = "goToEditView(2)"]')).click();
browser.sleep(500);
});
editData.forEach (function (data) {
it("changing details", function () {
element(by.name('fname')).clear().sendKeys(data.fname);
element(by.name('lname')).clear().sendKeys(data.lname);
browser.sleep(1000);
element(by.model('userEdit.currentPassword')).clear().sendKeys(data.currentpassword);
browser.sleep(1000);
element(by.model('userEdit.password')).clear().sendKeys(data.newpassword);
browser.sleep(1000);
element(by.model('userEdit.confirmPassword')).clear().sendKeys(data.confirmpassword);
browser.sleep(1000);
element(by.css('[ng-click="editUserProfile(userEdit)"]')).click();
browser.sleep(2000);
});
});
});
How can I do this?
Not so clear question but I guess you are thinking about some data provider like:
jasmine-data-provider

protractor get url after click()

i'm new with protractor.. i need you'r help..
my code go like this..
describe('Protractor Demo Charts', function () {
var url = 'https://angularjs.org/';
it('should get the value of attribute d', function () {
browser.get(url);
element(by.css('.btn-warning')).click().then(function(text){
expect(browser.getCurrentUrl()).toContain('0BxgtL8yFJbacQmpCc1NMV3d5dnM');
}
);
});
});
my problem is that browser.getCurrentUrl() still return me the base url (the page that i came from 'https://angularjs.org/' )
how can i get the new Url (the URL AFTER the click )?
May you should wait until the page has been loaded.
Try this way :
describe('Protractor Demo Charts', function () {
var url = 'https://angularjs.org/';
it('should get the value of attribute d', function () {
browser.get(url);
browser.sleep(2000);
$('.btn-warning').click();
expect(browser.getCurrentUrl()).toContain('0BxgtL8yFJbacQmpCc1NMV3d5dnM');
});
});
From the doc:
Protractor will ensure that commands will automatically run in sync. For example, in the following code, element(by.model(...)).click() will run before browser2.$('.css').click():
browser.get('http://www.angularjs.org');
browser2.get('http://localhost:1234');
browser.sleep(5000);
element(by.model(...)).click();
browser2.$('.css').click();

click() doesn't work in IE 11 but works in Chrome on the same elements

I have two clickable elements on my webpage, which is a login page. One is a remember-me checkbox, and the other is a login button. The code below executes successfully on chrome. However, when I run the test against IE 11, the tests actually pass! But the buttons are never clicked. Only the 'will recieve a login error' test fails with IE because the error message is never presented since the login button is never clicked.
Here is the code:
//run test
describe('Test my Login webpage', function () {
var usernameInput = element(by.id('UserName'));
var passwordInput = element(by.id('Password'));
var loginButton = element(by.tagName('button'));
it('will open the login webpage', function () {
browser.get('http://<my website>/Account/Login');
});
it('will click the remember-me checkbox', function () {
expect(element(by.id('RememberMe')).isSelected()).not.toBeTruthy();
element(by.id('RememberMe')).click();
});
it('will type a username', function () {
expect(element(by.id('UserName')).isDisplayed()).toBe(true);
usernameInput.sendKeys('testing...').then(function () {
expect(element(by.id('UserName')).getText()).toBe('');
});
});
it ('will type a password', function () {
expect(element(by.id('UserName')).isDisplayed()).toBe(true);
passwordInput.sendKeys('fakePassword').then(function () {
expect(element(by.id('Password')).getText()).toContain('');
});
});
it('will click login button', function () {
expect(loginButton.isDisplayed()).toBe(true);
loginButton.click();
browser.waitForAngular();
usernameInput.clear();
usernameInput.sendKeys('my second attempt');
});
it('will recieve a login error', function () {
expect(element(by.css('.error-msg')).isDisplayed()).toBe(true);
//expect(element(by.class('error-msg')).getText()).toMatch('Username or password was invalid, please retry');
});
});
You could try putting an explicit wait in before you .click(). IE is notorious for being slower to load objects, and thus more synchronization is needed.

How to run an ordered test

I want to
fill out name and password input fields
click login button
wait for page to load
click a button
How can I accomplish this? I realize promises are going to be involved. This is what I have tried:
conf.js
var env = require('./environment.js');
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['test/e2e/app/test-spec.js'],
baseUrl: env.baseUrl,
onPrepare: function() {
console.log("base url is: " + env.baseUrl);
browser.driver.get(env.baseUrl + '#/login');
element(by.model('my.username')).sendKeys('username');
element(by.model('my.password')).sendKeys('password');
console.log("clicking login button...");
element(by.css('button.md-primary.md-button.md-default-theme')).click();
// Login takes some time, so wait until it's done.
// For the test app's login, we know it's done when it redirects to
// /#/home.html.
browser.driver.wait(function() {
return browser.driver.getCurrentUrl().then(function(url) {
console.log("read current url as" + url);
console.log("returning...");
return /\/#\/home\//.test(url);
});
}, 10000);
}
};
Then a test.
test-spec.js
describe('Click button on home page', function() {
it('should click the button', function() {
console.log("looking for button on home page")
element(by.css('button.md-fab.md-accent.md-primary.md-button.md-default-theme')).click();
});
});
And for reference
environment.js
// Common configuration files with defaults plus overrides from environment vars
var webServerDefaultPort = 9002;
module.exports = {
// The address of a running selenium server.
seleniumAddress:
(process.env.SELENIUM_URL || 'http://localhost:4444/wd/hub'),
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName':
(process.env.TEST_BROWSER_NAME || 'chrome'),
'version':
(process.env.TEST_BROWSER_VERSION || 'ANY')
},
// Default http port to host the web server
webServerDefaultPort: webServerDefaultPort,
// A base URL for your application under test.
baseUrl:
'http://' + (process.env.HTTP_HOST || 'localhost') +
':' + (process.env.HTTP_PORT || webServerDefaultPort)
};
Outputs
Using the selenium server at http://localhost:4444/wd/hub
[launcher] Running 1 instances of WebDriver
base url is: http://localhost:9002
clicking login button...
looking for button on home page
I never see "read current url as" which tells me the promise is not executing and my test executes too early.
So the Error I get makes sense because the test ran too early:
NoSuchElementError: No element found using locator: By.cssSelector("button.md-> fab.md-accent.md-primary.md-button.md-default-theme")
Put the wait() call into beforeEach():
describe('Click button on home page', function() {
beforeEach(function () {
browser.wait(function() {
return browser.getCurrentUrl().then(function(url) {
console.log("read current url as" + url);
console.log("returning...");
return /\/#\/home\//.test(url);
});
}, 10000);
});
it('should click the button', function() {
console.log("looking for button on home page")
element(by.css('button.md-fab.md-accent.md-primary.md-button.md-default-theme')).click();
});
});
Or, you can wait for the element on the home page to become visible:
describe('Click button on home page', function() {
var scope = {};
beforeEach(function () {
var EC = protractor.ExpectedConditions;
scope.defaultTheme = element(by.css('button.md-fab.md-accent.md-primary.md-button.md-default-theme'));
browser.wait(EC.visibilityOf(scope.defaultTheme), 10000);
});
it('should click the button', function() {
console.log("looking for button on home page");
scope.defaultTheme.click();
});
});
After tinkering around I had the most success with the following setup:
beforeAll() used to login
sendkeys() failed to function for me inside of OnPrepare(). I shortened OnPrepare() down to a simple redirect to login page.
I set config.js to use firefox because I had problems getting click() to function in chrome.
Use Jasmine2 (jasmine1 is default)
Use a series of browser.wait to workout the timing. You can wait for an element to exist (one that only exists on page2 per-se)
browser.waitForAngular() performs similar duties. I had less success with this feature
Protractor configuration file documentation
test-spec.js
describe('Click button on home page', function() {
beforeAll(function () {
element(by.model('my.username')).sendKeys('username');
element(by.model('my.password')).sendKeys('password');
element(by.id('loginButton')).click();
browser.wait(function() {
return browser.driver.getCurrentUrl().then(function(url) {
var result = url.indexOf("/#/home") > -1;//wait for url to change to this
return result;
});
}, 10000);
});
it('should click the button', function() {
console.log("executing test...");
browser.ignoreSynchronization = true;//Yea I had to use this here too...I dunno why this is required
element(by.id('someButton')).click();
browser.wait(function() {
console.log('inside wait for vm.firstName');
return browser.isElementPresent(by.model('vm.firstName'));
}, 10000).then(function(){
//rinse and repeat with more waits as pages change
});
expect(true).toBe(true);
});
});
conf.js
var env = require('./environment.js');
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['test/e2e/app/test-spec.js'],
baseUrl: env.baseUrl,
capabilities: {
browserName: 'firefox'
},
framework: 'jasmine2',
onPrepare: function() {
browser.driver.get(env.baseUrl + '#/login');
}
};
environment.js
no change

How to correctly step through tests on different pages in Protractor e2e test?

We want to use protractor to visit a page, run some tests, and then go to another page for more tests. But the later navigation appears to interfere the tests on the previous page.
Here is the structure:
describe('When user is an admin', function () {
browser.get(browser.baseUrl + 'login');
loginAs(roles.admin);
wait();
describe('After log in', function () {
it('should redirect to the home page', function () {
expect(browser.getCurrentUrl()).toBe(browser.baseUrl + 'home');
expect(true).toBeTruthy();
});
it('should contain a "Locations" tab', function () {
var tabLocations = element(by.id('tabLocations'));
expect(tabLocations.isPresent()).toBeTruthy();
});
it('should contain a link to location list', function () {
var linkLocation = element(by.linkText('Manage Locations'));
expect(linkLocation.isPresent()).toBeTruthy();
});
});
});
Pasted above is the tests on the first page.
Then we want to run the tests on another page: (full coded pasted below)
describe('When user is an admin', function () {
browser.get(browser.baseUrl + 'login');
loginAs(roles.admin);
wait();
describe('After log in', function () {
it('should redirect to the home page', function () {
expect(browser.getCurrentUrl()).toBe(browser.baseUrl + 'home');
expect(true).toBeTruthy();
});
it('should contain a "Locations" tab', function () {
var tabLocations = element(by.id('tabLocations'));
expect(tabLocations.isPresent()).toBeTruthy();
});
it('should contain a link to location list', function () {
var linkLocation = element(by.linkText('Manage Locations'));
expect(linkLocation.isPresent()).toBeTruthy();
});
});
describe('at location manage page', function () {
var listPage = new ListPage();
listPage.visit('Manage Locations');
wait();
it('should be at the location list page', function () {
expect(browser.getCurrentUrl()).toBe(browser.baseUrl + 'locations/list');
expect(true).toBeTruthy();
});
});
});
It appears the navigation in my second describe runs before the execution of it statements in the first describe, therefore my tests on the first page failed.
I've tried placing the second describe ("at location manage page") inside the first describe ("After log in"), but still got the same problem.
So my question is, what is the correct way to arrange the tests in protractor, so as the navigation in later tests will be held until the previous tests are completed?
Do not put code inside a describe. Put it inside a beforeAll(function(){}) (jasmine 2) or a beforeEach(function() {})
That should fix your problem.

Resources