I can't understand why my emberjs test code runs so strange.
I wrote a test which should only select some html elements and give me number of them. This code works:
test('visiting /feedback/my', function(assert) {
visit('/feedback/my');
// if i remove this andThen test becomes failed
andThen(function(){
find(".feedback-item");
});
andThen(function(){
assert.equal(find(".feedback-item").length > 0, true, "There are more than 0 feedback");
});
click(".feedback-item:first a");
andThen(function() {
assert.equal(currentURL(), '/feedback/1', "New URL is /feedback/1");
});
});
But the same code but without (if i delete / comment it) this part andThen(function(){ find(".feedback-item")}); doesn't work. It throw's an exception: Element .feedback-item:first a not found.
Related
I have a bootstrapped Angular (1.2.6) app. This means it doesn't have an explicit ng-app. As such, I've run into all sorts of problems getting Protractor framework'd tests to work (using SauceLabs and grunt-protractor-runner).
The errors vary based on what I try, but generally:
Error: Angular could not be found on the page http://xxx:9000/ :
angular never provided resumeBootstrap
Or...
Error: Error while waiting for Protractor to sync with the page: {}
I've found a few proposed solutions which I've tried. Including those found in this rich thread, as well as here, too. Nothing I do, though, gets things working.
I've tried to use angular.resumeBootstrap in the bootstrapping like so (note I tried multiple variations of this to no avail, including trying to set an ng-app programatically on the document body):
angular.element( document ).ready( function() {
window.name = 'NG_DEFER_BOOTSTRAP!'
angular.bootstrap( document, [ 'app' ] );
setTimeout( angular.resumeBootstrap, 0 );
});
The error for this, as others have found, is weird:
UnknownError: unknown error: [ng:btstrpd] App Already Bootstrapped with this Element
'<body ng-app="" ng-controller="ApplicationController" class=" ng-scope pace-done">'
What's weird/annoying is that, at least looking in Sauce Labs session, it appears that this test is working... it's just weirdly thinking that it's been bootstrapped twice.
I've also tried using various combinations of waitForAngular, wait, and others in the test itself. Here's one variation I've tried:
it( 'should load the home page', function() {
ptor = protractor.getInstance();
ptor.waitForAngular();
ptor.driver.get( 'http://xxx:9000/' );
ptor.driver.wait( function() {
return ptor.getCurrentUrl().then( function() {
return ptor.isElementPresent( by.id( 'signIn' ) ).then( function() {
console.log('we are here!');
return true;
});
});
})
.then( function() {
expect( ptor.isElementPresent( by.id( 'signIn' ) ) ).toBe( true );
});
});
This results in errors like the following:
1) e2e: home should load the home page
Message: timeout: timed out after 20000 msec waiting for spec to complete
Stacktrace: undefined
I've also tried increasing various timeouts in the config file to no avail.
Any help would be much appreciated!
You should separate the test in two 'it'-steps. Like this:
it( 'should load angular', function() {
ptor = protractor.getInstance();
ptor.waitForAngular();
})
it( 'should load the home page', function() {
ptor.driver.get( 'http://xxx:9000/' );
ptor.driver.wait( function() {
return ptor.getCurrentUrl().then( function() {
return ptor.isElementPresent( by.id( 'signIn' ) ).then( function() {
console.log('we are here!');
return true;
});
});
})
.then( function() {
expect( ptor.isElementPresent( by.id( 'signIn' ) ) ).toBe( true );
});
});
The problem with protractor is that every command runs without waiting for the prior step to complete. So, ptor.waitForAngular() and ptor.driver.get( 'http://xxx:9000/' ) are running at almost the same time. If you separate these into two steps, protractor moves on after the first 'it'-step is done.
I develop some UI tests (running with Phantom.js configuration)
The tests themselves are very simple, for example (see some sample code below):
Browse a page - confirm the title expected is correct
Click a button/item to select an item from a list - confirm that the accurate item has been selected.
module.exports = {
'NodeCeller home page': function (test) {
test
.open('http://localhost:3000')
.assert.title().is('Node Cellar', 'Node Cellar is now open')
.done();
},
'NodeCeller Start Browsing Click': function (test) {
test
.click('a[href="#wines"]')
.assert.url('http://localhost:3000/#wines', 'Showing wines selection')
.done();
},
'NodeCellar Browse First Wine': function (test) {
test
.click('#content > div > ul > li > a')
.assert.text('legend','Wine Details', 'Showing Wines Details')
.done();
},
};
My question is this, I'd like to run the same set of tests in a loop for several times.
I have googled for Dalek.JS help and samples but I couldn't find any sample or article of how to do that.
Any help would be highly appreciated
My Protractor e2e tests are inconsistently passing and failing.
It seems this could be due to asynchronous javascript, as discussed here:
Protractor : How to wait for page complete after click a button?.
However, here it's mentioned that Protractor tests automatically execute sequentially / synchronously:
https://github.com/angular/protractor/issues/909
My test script:
describe('Login', function() {
var ptor;
beforeEach(function() {
browser.get('https://127.0.0.1:8443');
ptor = protractor.getInstance();
element(by.id('splash')).click();
browser.ignoreSynchronization = true; // <-- to proceed beyond splash screen
});
describe('with correct email and password', function() {
beforeEach(function() {
element(by.id('email')).sendKeys('admin#email.com');
element(by.id('password')).sendKeys('adminpassword');
element(by.id('loginButton')).click();
});
afterEach(function() {
ptor.findElement(by.id('logout')).then(function(elem) {
elem.click();
});
});
it('does not show alert', function() { // <-- sometimes passes, sometimes fails
expect(browser.isElementPresent(by.css('.alert-danger'))).toBe(false);
});
it('changes route to /admin', function() { // <-- sometimes passes, sometimes fails
expect(browser.getCurrentUrl()).toMatch(/\/admin/);
});
});
});
In the two tests above, either both tests will pass, or one/both of the tests will fail with these messages:
Failures:
1) Login with correct email and password does not show alert
Message:
NoSuchElementError: no such element
...
==== async task ====
WebDriver.findElement(By.id("logout"))
...
or
Failures:
1) Login with correct email and password changes route to /admin
Message:
NoSuchElementError: no such element
...
==== async task ====
WebDriver.findElement(By.id("logout"))
...
Thoughts / help much appreciated.
I was able to resolve the issue based on the following:
Avishay's answer here about adding ptor.waitForAngular():
No element found using locator: by.model() error
Changing browser.get to ptor.get, as in Harri Siirak's answer here:
Protractor times out waiting for sync with page when using $resource
juliemr's comment here about ignoreSynchronization being an instance variable, and changing browser.ignoreSynchronization=true to ptor.ignoreSynchronization=true:
https://github.com/angular/protractor/issues/49
glepretre's answer here about using .then():
Protractor : How to wait for page complete after click a button?
As mentioned by Nguyen Vu Hoang's comment to the original question, I am testing a pure Angular app with what I think is pure Protractor (no webdriver calls). I know ptor.ignoreSynchronization=true should not be required in this case, but for some reason, the tests are not proceeding at button click without this setting.
My new spec:
describe('Login', function() {
var ptor;
beforeEach(function() {
ptor = protractor.getInstance();
ptor.ignoreSynchronization = true;
ptor.waitForAngular();
ptor.get('https://127.0.0.1:8443');
ptor.findElement(by.id('splash')).then(function(elem) {
elem.click();
});
});
describe('with correct email and password', function() {
beforeEach(function() {
ptor.findElement(by.id('email')).then(function(elem) {
elem.sendKeys('admin#email.com');
});
ptor.findElement(by.id('password')).then(function(elem) {
elem.sendKeys('adminpassword');
});
ptor.findElement(by.id('loginButton')).then(function(elem) {
elem.click();
});
});
afterEach(function() {
ptor.findElement(by.id('logout')).then(function(elem) {
elem.click();
});
});
it('does not show alert', function() {
expect(ptor.isElementPresent(by.css('.alert-danger'))).toBe(false);
});
it('changes route to /admin', function() {
expect(ptor.getCurrentUrl()).toMatch(/\/admin/);
});
});
});
There is also an another technique to make your tests more stable: Explicit Waits and Expected Conditions (docs).
I've found using Expected Conditions especially useful when testing against non-angular pages or angular applications that have a lot of animations involved.
For example, you can wait for an element to be clickable before making a click:
var EC = protractor.ExpectedConditions;
var link = element(by.id("mylink"));
browser.wait(EC.elementToBeClickable(link), "10000", "The link is still not clickable");
link.click();
There are also other built-in Expected Conditions, such as:
presenseOf()
visibilityOf()
alertIsPresent()
textToBePresentInElementValue()
etc
And, it is easy to write a custom Expected Condition, example use case:
Testing link style changes
You can also combine Expected Conditions using and, or and not, e.g.:
var urlChanged = function() {
return browser.getCurrentUrl().then(function(url) {
return url != 'http://www.angularjs.org';
});
};
// condition to wait for url to change, title to contain 'foo', and $('abc') element to contain text 'bar'
var condition = EC.and(urlChanged, EC.titleContains('foo'), EC.textToBePresentInElement($('abc'), 'bar'));
$('navButton').click();
browser.wait(condition, 5000); //wait for condition to be true.
browser.ignoreSynchronization = true; has a global effect for all your tests. you may have to set it back to false, so protractor waits for angular to be finished rendering the page. e.g. in or before your second beforeEach function
So here another trouble. I have a script loading svg and waiting for it to appear which randomly fails. Sometimes phantom stay stuck loading svg (even with a waitTimeout at 2min, so the problem isn't here I think). script : http:// r.ccmbg.com/js.php?m=highchart=...
I could still load the page X times in a loop waiting for svg to appear, but I'd prefer another solution. If you have an idea, I'm all ears.
Simple example :
casper.test.begin('\n********* Navigation on directories : ***********', 8,{
setUp: function(test) {
//setLevel("normal");
},
tearDown: function(test) {
//getJSON();
},
test: function(test){
"use strict";
casper.start()
.thenOpen('http://www.linternaute.com/voyage/climat/paris/ville-75056/2013-2008')
.waitForResource(/m=highcharts&/, function(){
this.waitForSelector('svg',function(){
this.test.assertExists("tspan");
});
})
.waitForUrl(/2008/, function(){
this.test.assertSelectorHasText("h2", "maximales");
this.test.assertSelectorHasText("h2", "minimales");
this.test.assertSelectorHasText("h2", "Paris");
this.test.assertSelectorHasText("h2", "Le soleil");
this.test.assertSelectorHasText("h2", "La pluie");
this.test.assertExists("div.marB20");
this.test.assertNotEquals(this.fetchText("div.marB20 > table > thead > tr > th"), " ", "Table first data not empty");
})
.run(function() {
this.test.comment('--- Done ---\n');
test.done();
});
}
});
Well, when I don't know the script called or the API used (so I can't debug myself), I just check the ressource now.
this.waitForResource(/js\.php\?m=highcharts&v/, function(){
this.test.pass("ressource received (js -> API highcharts)");
});
Don't forget this event to get back page document error :
casper.on("page.error", function(msg, trace) {
this.echo("Page Error: " + msg, "ERROR");
});
<script type="text/javascript">
// check the spelling on a textarea
$("#check-textarea").click(function (e) {
e.preventDefault();
$(".loading").show();
$("#text-content")
.spellChecker({
lang: "en",
engine: "google",
suggestBoxPosition: "above"
})
.spellChecker('check', function (result) {
// spell checker has finished checking words
$(".loading").hide();
// if result is true then there are no badly spelt words
if (result) {
alert('There are no incorrectly spelt words.');
}
});
});
</script>
I am getting Error Message Object Does not support this property or method..
I used this link..
http://code.google.com/p/jquery-spellchecker/source/browse/#svn/trunk/css
Looks like you are using the incorrect source.
You should try ==> http://jquery-spellchecker.googlecode.com/svn/trunk/js/jquery.spellchecker.min.js
Not the CSS which you have listed ( http://code.google.com/p/jquery-spellchecker/source/browse/#svn/trunk/css )
Also, as Jakub pointed out it's a lower case c in spellchecker
Check out the example page.