Protractor selector and event issue - angularjs

I'm trying to create some tests for my app, using protractor.
The browser.get is ok, and when my page is loaded and my app bootstraped, the first test is running.
it('should go to the where and when page', function() {
var nextButton = element(by.id('cg_btnValidationQuoi'));
expect(nextButton.getText()).toBe('Suivant');
}
This cause a timedout.
it('should go to the where and when page', function() {
var nextButton = element(by.id('cg_btnValidationQuoi'));
nextButton.click()
}
Cause "Error: No element found using locator: By.id("cg_btnValidationQuoi")"
it('should go to the where and when page', function() {
var nextButton = element(by.id('cg_btnValidationQuoi'));
expect(nextButton.getInnerHtml()).toBe('Suivant');
}
Cause :
Message:
Expected '
Suivant
' to be 'Suivant'.
Does it sound like anything that anybody knows?

toBe() checks to see if its the exact same object (string). I'd suggest using toEqual() and see if it works. More info in this SO Answer

Related

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.

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

How to handle modal-dialog box in Protractor?

I am trying to use sendKeys() on a modal-dialog box on this website. This dialog box appears after clicking Sign In button. I cannot seem to find any way to switch focus on the box. See the gist
I tried using browser.driver.switchTo().activeElement(); in
InvalidLogInUnSuccess: {
get: function () {
this.loginButton.click();
browser.driver.switchTo().activeElement();
this.email.sendKeys("Test");
}
}
with no luck and throws ElementNotVisibleError
Message:
ElementNotVisibleError: element not visible
(Session info: chrome=41.0.2272.101)
(Driver info: chromedriver=2.14.313457 (3d645c400edf2e2c500566c9aa096063e707c9cf),platform=Windows NT 6.3 x86_64)
Stacktrace:
ElementNotVisibleError: element not visible
I've experienced a similar issue while testing an internal application when a popup was being opened with an animation effect (I think it is a culprit here) which had me think about waiting for an element inside the popup to become visible.
visibilityOf expected condition works for me in this case:
var email = element(by.css('.container.login.ng-scope #email'));
browser.wait(EC.visibilityOf(email), 5000);
email.sendKeys('test');
where EC is something I usually define globally in the onPrepare():
onPrepare: function () {
...
global.EC = protractor.ExpectedConditions;
},
Just a side note, I think the locator could be improved here:
ng-scope is not something I would rely on
there is a model defined on the email field, how about:
element(by.model('email'));
FYI, the complete spec I've executed:
"use strict";
describe("gifteng test", function () {
var scope = {};
beforeEach(function () {
browser.get("http://www.gifteng.com/?login");
browser.waitForAngular();
});
describe("Logging in", function () {
it("should send keys to email", function () {
var email = element(by.css('.container.login.ng-scope #email'));
browser.wait(EC.visibilityOf(email), 5000);
email.sendKeys('test');
});
});
});
Protractor works with promises you should write :
InvalidLogInUnSuccess: {
get: async() => {
await this.loginButton.click();
await browser.driver.switchTo().activeElement();
await this.email.sendKeys("Test");
just apply Promises before protractor code. I removed function and write async. so i applied async/await.
reference: Link

Simple protractor test for isElementPresent failing with unsupported locator strategy

My test:
it('should allow login', function() {
browser.get('index.html');
$('#username').sendKeys('administrator');
$('#password').sendKeys('password');
$('#login').click();
var logout = $('#logout');
expect($p.isElementPresent(logout)).to.eventually.be.true;
});
But this errors out with:
Error: Unsupported locator strategy: click
at Error (<anonymous>)
at Function.webdriver.Locator.createFromObj (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/webdriver/locators.js:97:9)
at Function.webdriver.Locator.checkLocator (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/webdriver/locators.js:111:33)
at webdriver.WebDriver.findElements (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/webdriver/webdriver.js:805:31)
at webdriver.WebDriver.isElementPresent (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/webdriver/webdriver.js:787:29)
at Protractor.isElementPresent (/usr/local/lib/node_modules/protractor/lib/protractor.js:476:22)
at /Users/pschuegr/wt/client/e2e/login_test.js:26:15
Strangely, it points to the isElementPresent line, rather than the line with the click. I'm pretty new to webdriver, so apologies if I missed something obvious. I'm running using the mocha framework (which means the canary version of protractor), fwiw.
Any ideas appreciated.
Using the latest Protractor build, you can shorten the above answer to the following:
expect(element(by.css('#logout')).isPresent()).toBeTruthy();
This way you do not have to perform the browser.wait and you reduce the number of calls to isElementPresent.
$('#logout') is a WebElement. isElementPresent takes a locator, like by.css
$('#username').sendKeys('administrator');
$('#password').sendKeys('password');
$('#login').click();
var logout = by.css('#logout');
browser.wait(function() { return $p.isElementPresent(logout); }, 8000);
expect($p.isElementPresent(logout)).toBeTruthy();
The safest approach I would take is depicted in the following code snippet:
it('should return true when element is present', function () {
var logout;
logout = $('#logout');
browser.driver.isElementPresent(logout).then(function (isPresent) {
isPresent = (isPresent) ? true : browser.wait(function () {
return browser.driver.isElementPresent(logout );
}, 15000); //timeout after 15s
expect(isPresent).toBeTruthy();
});
});
Above code starts of with a promise to check if an element exists, and if true then assign it true, otherwise wait and keep pooling for the next 15sec to see if element is present, and in both cases we expect it to be true.
This should work :
var logout = $('#logout');
expect(logout.isPresent()).to.eventually.be.true;

Testing backbone router with jasmine and sinon. Cannot call the pushState.

I was following this question to test the router. My router is really simple:
App.Router = Backbone.Router.extend({
routes:{
"": "index",
"help": "help"
},
help: function() {/* not really needed */ },
index: function(){
// does something
}
});
And this is an apptempted translation of what should be the test using jasmine with sinon:
it('triggers the "index" route', function() {
var router = new App.Router();
Backbone.history.start();
//Not calling navigate it's a problem
router.navigate('help', {
trigger : true, replace: true
});
var index = sinon.spy(router, 'index');
var spyHasPS = sinon.spy(function(
data, title, url) {
expect(url).toEqual('/');
router.index();
});
var spyNoPS = sinon.spy(function(loc, frag) {
expect(frag).toEqual('');
router.index();
});
if (Backbone.history._hasPushState) {
pushStateSpy = sinon.stub(window.history, 'pushState', spyHasPS );
// window.history.pushState();
} else if (Backbone.history._wantsHashChange) {
pushStateSpy = sinon.stub(Backbone.history, '_updateHash', spyNoPS);
//Backbone.history._updateHash(window.location, '');
}
router.navigate('', {
trigger : true, replace: true
});
expect(pushStateSpy.called).toBe(true);
expect(index.called).toBe(true);
});
This test works but I could achieve it because I navigated first on "help". "help" was just something I created to pass the test but the original question didn't do it and was passing. Did I do something wrong? I also run his test but the error I'm getting is:
Expected spy _updateHash to have been called. Error: Expected spy
_updateHash to have been called.
at null.<anonymous> (/src/test/js/spec/wfcRouter.spec.js:65:32) Expected spy index to have been called.
I believe the "problem" is in the navigate function. At a certain point in the navigate: function(fragment, options) we have this control:
fragment = this.getFragment(fragment || '');
if (this.fragment === fragment) return;
So...does it make sense to test the pushState when you just have one route (remember I added "help" just to make this test pass so I don't need it)? If it does make sense, how can I achieve this test?
It seems like what you are testing is Backbone code, but there's no need for you to test that: presumably the Backbone code has been tested plenty by Jeremy Ashkenas (and if you look at the Backbone project on GitHub you will see that he does in fact have a comprehensive test suite). So, rather than re-testing code you didn't write that's already been tested, what you really should be testing is the code you wrote.
If you agree with that principle, then you can simplify your test a great deal, down to just:
it('triggers the "index" route', function() {
var router = new App.Router();
router.index();
expect(thingThatShouldHaveHappenedInIndexRouteDidHappen).toBe(true);
});

Resources