Shareds Behavior Jasmine + Protractor - angularjs

I'm new with Protractor and jasmine framework to test an AngularJS Application.
I whould like to reuse some of my scenarios, like Login feature can call in all scenarios of my suite.
This is my login_test.js
module.exports = function(testName, testFn) {
const loginPage = pages.login;
const mainPage = pages.main;
var protractor;
describe('common Login suite', function() {
browser.ignoreSynchronization = true;
beforeEach(function() {
});
afterAll(function() {
browser.manage().deleteAllCookies();
});
it(testName, function() {
browser.get('http://localhost:9000/');
loginPage.typeUserName('bxxxxx');
loginPage.typePassword('xxxxxx');
loginPage.clickLogin();
});
});
}
And here I have the remote_terminal feature, here I need call Login feature to perfom login in my scenario.
var loginSuite = require('./login_test.js');
loginSuite('login Suite terminal feature', function(browser) {
describe('description', function() {
console.log('describe');
it('it', function() {
console.log('it');
});
});
});
But when this spec (remote_terminal) is called to run I got this message on my console
Started
Spec started
.
common Login suite
✓ login Suite terminal feature
As you can see the describe and IT in the remote_terminal spec aren't ran.
Demo:
http://pavelbogomolenko.github.io/dry-principles-with-protractor.html

You can use pageObjects to achieve reusable code accross your test,
Let us create a new js file for login page as login_page.js as below,
var login_page = function(){
this.performLogin = function(){
//add code for performing login operation.
}
}
module.exports = new login_page();
Now you can import the login_page.js in all 'specs' and can call the performLogin() method whenever required.
Look at the example spec.js below,
describe("Test pageobject code",function(){
var login_page = require("login_page.js");
beforeAll(function(){
login_page.performLogin();
})
it("simple test to perform after login action is performed",function()
//do whatever you want to test
})
})

Related

Jasmine - Restart browser between tests (it blocks)

In our Protractor+Jasmine framework trying to restart browser between tests for different login user. As we have non-angular login page and after login its navigate to angular page. Following is my main test spec file
describe('User Permissions', function() {
var docsLoginPage = require('../pages/CLM_Page.js');
var projectsPage = require('../pages/Projects_Page.js');
var contentPage = require('../pages/Content_Page.js');
beforeEach(function() {
browser.ignoreSynchronization = true;
browser.get('http://be-docs-dev.xyz.local/');
});
it('Verify permissions for Non Admin and Read only permission group user', function() {
docsLoginPage.loginToDocs("sipqa4#xyz.com","Yahoo#123");
expect(browser.getTitle()).toEqual('abc');
browser.ignoreSynchronization = false;
expect(projectsPage.checkElementExistsById('headers_nav_projects')).toBe(false);
expect(contentPage.checkElementExistsById("content_browse_options_folder_settings")).toBe(false);
expect(contentPage.checkElementExistsById('content_browse_options_new_menu')).toBe(false);
});
it('Verify permissions for Project collaborator Non Admin and Read only permission group user', function() {
/*browser.restart().then(function(){
console.log("-----------Restarted the browser---------------");
});*/
docsLoginPage.loginToDocs("sipqa2#xyz.com","Yahoo#123");
expect(browser.getTitle()).toEqual('abc');
browser.ignoreSynchronization = false;
expect(projectsPage.checkElementExistsById('headers_nav_content')).toBe(false);
expect(contentPage.checkElementExistsById("projects_browse_options_folder_settings")).toBe(false);
expect(contentPage.checkElementExistsById('projects_browse_options_new_menu')).toBe(false);
});
});
And CLM_Page.js
var CLM_page = function() {
this.userName = element(By.id('userName'));
this.password = element(By.id('password'));
this.signIn = element(By.className('btn btn-primary'));
this.loginToDocs = function(userName, password) {
browser.driver.manage().window().maximize();
browser.driver.manage().timeouts().implicitlyWait(10000);
this.userName.sendKeys(userName);
this.signIn.click();
this.password.sendKeys(password);
return this.signIn.click();
};
};
module.exports = new CLM_page();
In conf file set to
restartBrowserBetweenTests: true
First it block is executing correctly. However while executing second it block browser restarting and closing immediately. Showing following error
Failures:
1) User Permissions Verify permissions for Project collaborator Non Admin and Read only permission group user
Message:
Failed: This driver instance does not have a valid session ID (did you call WebDriver.quit()?) and may no longer be used.
Stack:
NoSuchSessionError: This driver instance does not have a valid session ID (did you call WebDriver.quit()?) and may no longer be used.
The problem here is the webdriver session is closed after starting the test.
There is no problem with restartBrowserBetweenTests: true, Since your browser is restarted after the first test.
Since you are moving from non angular to angular application. Follow as below
browser.driver.get('http://localhost:8000/login.html');
browser.driver.findElement(by.id('username')).sendKeys('Jane');
browser.driver.findElement(by.id('password')).sendKeys('1234');
browser.driver.findElement(by.id('clickme')).click();
You are using browser.ignoreSynchronization = true; which is deprectaed. Try usingwaitForAngularEnabled(true).
make the BeforEach() as
beforeEach(function() {
browser.waitForAngularEnabled(false); // to tell protractor that this is a non- anularg page
browser.get('http://be-docs-dev.xyz.local/');
});
After moving to angular page make it as browser.waitForAngularEnabled(true);.
Hope the above answer helps you...
Based on your test case design, you can achieve the same by setting restartBrowserBetweenTests: false in conf.js file
And also clear the browser cookies and session from the browser after each it block run. Please modify your existing test script by adding afterEach
add the below snippet with existing code
afterEach(function () {
browser.manage().deleteAllCookies();
browser.executeScript('window.sessionStorage.clear();window.localStorage.clear();');
});
beforeEach function should be like
beforeEach(function() {
browser.waitForAngularEnabled(false);
browser.get('http://be-docs-dev.xyz.local/');
});
In conf.js.
Note: Default value is false. So it is not mandatory to set it as false
exports.config = {
...
restartBrowserBetweenTests: false,
...
}
If you are setting restartBrowserBetweenTests: true, This will cause your tests to slow down drastically. Please refer this

How do I wait until an element is visible with Protractor when Angular is not available?

I have a login function that I'm using for a Protractor test, it looks like this:
var config = require("../helpers/config.js");
var login = function() {
browser.driver.get(config.dsp.url);
browser.driver.findElement(by.name("userName")).sendKeys(config.dsp.user);
browser.driver.findElement(by.name("password")).sendKeys(config.dsp.password);
return browser.driver.findElement(by.name("submit")).click().then(function() {
return browser.driver.wait(function() {
return browser.driver.isElementPresent(browser.driver.findElement(by.className("sample-class-name")));
}, 360000);
});
}
module.exports = login;
I can't use any of the protractor specific hooks because Angular is not used on this page, so I have to use the underlying webdriver API. The problem is, I can't seem to figure out how to wait until an element is visible using this wrapped webdriver object. Any help would be appreciated.
Try with the expected conditions from the underlying driver:
var config = require("../helpers/config.js");
var until = require('selenium-webdriver').until;
var login = function() {
var driver = browser.driver;
driver.get(config.dsp.url);
driver.findElement(by.name("userName")).sendKeys(config.dsp.user);
driver.findElement(by.name("password")).sendKeys(config.dsp.password);
driver.findElement(by.name("submit")).click();
return driver.wait(until.elementLocated(by.css(".sample-class-name")), 10000)
.then(e => driver.wait(until.elementIsVisible(e)), 10000);
}
module.exports = login;

Use protractor on an non angular page

in my recent test I need to first login and take some actions on an non angular page (https://www.qa.dealertrack.com/default1.aspx)
then switch to an angular page and finish the test.
In conf I have
global.driver = browser.driver;
My page object looks like:
var LogInPage = function() {
this.loginUrl = 'https://www.qa.dealertrack.com/default1.aspx';
this.id = browser.driver.findElement(by.name('username'));
this.password = browser.driver.findElement(by.name('password'));
this.loginButton = browser.driver.findElement(by.name('login'));
this.logIn = function(id, password) {
// maximize window
driver.manage().window().maximize();
// log in
driver.get('https://www.qa.dealertrack.com/default1.aspx');
this.id.sendKeys(id);
this.password.sendKeys(password);
this.loginButton.click();
}
};
My test looks like:
describe('Sample Test - Log In', function() {
var loginPage = require('../pages/LogInPage.js');
/**
* Disable waiting for AngularJS for none Angular page
*/
beforeEach(function() {
isAngularSite(false);
});
it('logging in', function() {
loginPage.logIn('xxx', 'xxx');
})
})
However, even before getting to the site, protractor throws error NoSuchElementError: no such element: Unable to locate element:{'method':'name','selector':'username'}
But when I commented out all the element variables and related lines, only left
driver.get(this/loginUrl);
It worked. Why would browser.driver.get works but browser.driver.findElement does not?
This is my first question on Stackoverflow. Thank everyone!!
Before login you need to set
browser.driver.ignoreSynchronization=true;
So it shold be like
browser.driver.ignoreSynchronization=true;
login();
browser.driver.ignoreSynchronization=false;
I tried to removed all the elements I declared outside my functions in page object. Instead of that, I just hard code the elements in the function. And it worked.

How To Test route.navigate on Backbone View

I'm currently developing a Backbone.js application which uses the Mocha, Chai, and Sinon libraries for testing. I'm struggling to code the following test: When a user clicks a button it should redirect the user to home.
Here's how the view looks like:
events: {
'click #navigate-home': 'goHome'
},
initialize: function(options) {
this.router = options.router;
},
goHome: function(event) {
event.preventDefault();
this.router.navigate('home', { trigger: true });
}
And here's the test:
beforeEach(function() {
this.router = new Backbone.Router();
this.myView = new MyView({
router: this.router
});
this.myView.render();
});
afterEach(function() {
this.router = null;
this.myView = null;
});
it('redirects to home', sinon.test(function() {
var spy = sinon.spy();
this.router.on({
'home': spy
});
this.myView.$el.find('#navigate-home').trigger('click');
expect(spy.called).to.be.true;
}));
The code works as expected on the browser, but I can't get the test to pass. I would highly appreciate any help.
Based on my limited experience with Backbone and Unit Testing, I consider this kind of test as an invalid test case.
What you are trying to test in not actually your code but you are trying to add a test case for Backbone library. Similar test cases should actually be part of your Automation (Read about Selenium).
I think the correct way to write a Unit Test in your case would be:
it('should redirect to home', sinon.test(function() {
var spy = sinon.spy();
this.router.on({
'home': spy
});
// This is the difference
this.myView.goHome({preventDefault: function() { } });
expect(spy.called).to.be.true;
});

How to run a protractor tests with different input parameters

I am testing an angular application and I would like to feed my search tests with different parameters and run the test for all parameters.
In my case I have a search test:
require("./myconfig.js");
describe('change number of items displayed by page', function () {
var loginPage = require("./Pages/login-page.js");
var searchPage = require("./Pages/search-page.js");
var ptor;
ptor = protractor.getInstance();
it('should display 20 items per page', function () {
searchPage.home.click();
searchPage.searchTxt.sendKeys(Parameter);
searchPage.searchBtn.click();
var result = ptor.findElements(protractor.By.repeater('object in objects'));
result.then(function (arr) {
expect(arr.length).toEqual(20);
});
}, 50000);
});
is there a way using Jasmine and protractor to call parmaeter from an XML file? Tahnks for your help
Try xml2js xml parser in Node and use in your test.
> npm install xml2js

Resources