All steps shown as pass before protractor cucumber execution - javascript

While executing my scripts, Immediately all steps shows as pass in console after that my actual scripts getting executed. Even after returning promise in each step.
Feature File:
Feature: Running Cucumber with Protractor
Scenario: To verify the Search result
Given I am on home page
When I enter search value
Then I verify the search page
Step Definition:
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
var expect = chai.expect;
chai.use(chaiAsPromised);
module.exports = function() {
this.Given(/^I am on home page$/, function () {
browser.get(browser.baseUrl);
return browser.driver.getTitle().then(function(pageTitle) {
expect(pageTitle).equal('Online Shopping Site for Mobiles, Fashion, Books, Electronics, Home Appliances and More');
});
});
this.When(/^I enter search value$/, function () {
return element(by.name('q')).sendKeys('iPhone 4s');
});
this.Then(/^I verify the search page$/, function () {
browser.sleep(1000);
return expect(element(by.className('KG9X1FUs7BSJ3tl0huXbH')).isPresent()).to.eventually.equal(true);
});
}
And the Output shows as:

There are marked as green because you don't resolve the promise.You've choosen in your setup not to return a callback but to return a promise. This means that each last line of code should return a promise.
If you transform your code into promises you will get this
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
var expect = chai.expect;
chai.use(chaiAsPromised);
module.exports = function() {
this.Given(/^I am on home page$/, function() {
browser.get(browser.baseUrl);
return expect(browser.driver.getTitle())
.to.eventually.equal('Online Shopping Site for Mobiles, Fashion, Books, Electronics, Home Appliances and More');
});
this.When(/^I enter search value$/, function() {
return element(by.name('q')).sendKeys('iPhone 4s');
});
this.Then(/^I verify the search page$/, function() {
browser.sleep(1000);
return expect(element(by.className('KG9X1FUs7BSJ3tl0huXbH')).isPresent()).to.eventually.equal(true);
});
}

Related

Protractor Cucumber BDD Tests Show Pass before Execution

I have a sample BDD test using Protractor with Cucumber. On executing the code, the console immediately shows the result as passed and the code actually begins executing only after that.
I wish execution status display to be in sync with actual execution.(e.g Console displays - 'Given I launch the protractor demo page' and the code underneath is executed, then console displays next step and so on) I know it has got something to do with Async coding and callbacks, not able to figure out the exact problem though.
Feature file:
Feature: Test
Scenario: Test Scenario
Given I launch the protractor demo page
When I enter two in the first field
And I enter three in the second field
And I click Go button
Then Result should be displayed as Five
Step File:
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
var expect = chai.expect;
module.exports = function () {
this.Given(/^I launch the protractor demo page$/, function (callback) {
browser.driver.manage().window().maximize();
browser.get('http://juliemr.github.io/protractor-demo/');
browser.getTitle().then(function(text){
console.log('title is - ' + text);
expect(text).to.equal('Super Calculator');
});
callback();
});
this.When(/^I enter two in the first field$/, function (callback) {
element(by.model('first')).sendKeys('2');
callback();
});
this.When(/^I enter three in the second field$/, function (callback) {
element(by.model('second')).sendKeys('3');
callback();
});
this.When(/^I click Go button$/, function (callback) {
element(by.id('gobutton')).click();
callback();
});
this.Then(/^Result should be displayed as Five$/, function (callback) {
element(by.repeater('result in memory')).all(by.tagName('td')).get(2).getText().then(function(text){
expect(text).to.equal('5');
});
callback();
});
};
You need to either return a promise or use the done callback in your step definitions. Otherwise cucumber doesn't know when your asynchronous
actions are complete.
I had the same question and above statement was the response from one of the core members of the protractor-cucumber github forum.
I prefer to return promises when I am performing some actions on the results with .then function and use .done callback function when I am not, Also you don't need callbacks now CucumberJS supports promises. So your step file should look like -
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
var expect = chai.expect;
module.exports = function () {
this.Given(/^I launch the protractor demo page$/, function () {
browser.driver.manage().window().maximize();
browser.get('http://juliemr.github.io/protractor-demo/');
return browser.getTitle().then(function(text){
console.log('title is - ' + text);
expect(text).to.equal('Super Calculator');
});
});
this.When(/^I enter two in the first field$/, function () {
return element(by.model('first')).sendKeys('2');
});
this.When(/^I enter three in the second field$/, function () {
return element(by.model('second')).sendKeys('3'); // you can use return also
});
this.When(/^I click Go button$/, function () {
return element(by.id('gobutton')).click();
});
this.Then(/^Result should be displayed as Five$/, function () {
return element(by.repeater('result in memory')).all(by.tagName('td')).get(2).getText().then(function(text){
expect(text).to.equal('5');
});
});
};
I would recommend you to read about Promises http://www.html5rocks.com/en/tutorials/es6/promises/ as it requires some understanding how they behave.They can be sometimes tricky, it took me a while to get an idea still I have lot to learn :)

Nested promises - Mocha - Exceeded timeout

I have got a test failing because of a timeout using Mocha.
I do call the "done()" function but it does not seem to work for some reason.
My test currently looks like this:
var express = require('express');
var expect = require('chai').expect;
var mocha = require('mocha');
var calendar = require('./../Server/calendarDatabase');
describe("Calendar", function () {
describe("Database", function () {
it("should get stuff from the database", function (done) {
return calendar.Connect()
.then(function () {
return calendar.getAll();
})
.then(function (returnValue) {
expect(returnValue.count).to.equal(5); //This should fail, my database records are 20+
done();
});
});
});
});
Where my calendar.Connect() and calendar.getAll() are both promises:
var express = require('express');
var sql = require('mssql');
var config = require('./../config');
var calendarDbConnection = {};
calendarDbConnection.Connect = function() {
return sql.connect(config.mssql);
}
calendarDbConnection.getAll = function () {
var promise = new sql.Request()
.query('select * from CalendarTable')
.catch(function (err) {
console.log(err.message);
});
return promise;
}
module.exports = calendarDbConnection;
However while running my test, I get following output:
When I call the done() after my last then(), the function gets resolved but the outcome of my test does not. The number of lines I get from the database are over 20 and I check if they are equal to 5. So, my test should fail, but it does not.
//previous code
.then(function (returnValue) {
expect(returnValue.count).to.equal(5); //This should fail, my database records are 20+
});
done();
//...
So this last outcome passes my test, while it should not.
What am I missing here? I am calling the callback function but then my expected outcome is not correct.
Since You are returning a Promise from the test, you should not pass done as an argument:
Alternately, instead of using the done() callback, you may return a Promise. This is useful if the APIs you are testing return promises instead of taking callbacks.
Although you can pass done to catch call as stated above, it seems more convenient to get rid of done and just return a promise.
it("should get stuff from the database", function () {
return calendar.Connect() // returns Promise, so no `done`
.then(function () {
return calendar.getAll();
})
.then(function (returnValue) {
expect(returnValue.count).to.equal(5);
});
});
Only pass done in the catch.
then(....) { ... done(); }.catch(done);

Mocha test times out when using promises and skips over code, why?

I have been trying to run this test for 2 days straight now and I can't figure what is wrong with it:
/*eslint-env mocha */
// var expect = require('chai').expect;
var chai = require('chai');
var chaiAsPromised = require("chai-as-promised");
var expect = chai.expect;
var Promise = require('bluebird');
var Archive = require('../lib/archive');
var path = require('path');
var fs = Promise.promisifyAll(require('fs-extra'));
var globAsync = Promise.promisify(require('glob'));
var tar = require('tar-fs');
var zlib = Promise.promisifyAll(require('zlib'));
chai.use(chaiAsPromised);
describe('Archive', function() {
var pkg;
var archive_location;
var subject;
beforeEach(function() {
pkg = {
name: 'test_0790feebb1',
recipient_name: 'Test',
files: {
letter: '../documents/letters/test/letter.tex',
resume: '../documents/cover/cover.tex'
},
compiled_files: {
package: '../documents/letters/test/test.pdf'
}
};
archive_location = path.resolve('archives/test_0790feebb1.tar.gz');
subject = new Archive(pkg);
});
after(function() {
return globAsync('archives/test*')
.each(function(filename) {
return fs.removeAsync(filename);
});
});
describe('#make', function() {
it('has the correct directory structure', function() {
// debugger;
var tmp_extract_path = path.resolve('test/.tmp');
var tarPromise = function(data) {
console.log('tarP'); // never run
return new Promise(function(reject, resolve) {
data
.pipe(zlib.Unzip())
.pipe(tar.extract(tmp_extract_path))
.on('error', reject)
.on('end', resolve);
});
};
var verifyDir = function() {
console.log('verD'); // never run
return Promise.all([
'code',
'pdf',
'code/repo',
'code/documents',
'code/documents/letters',
'code/documents/letters/test',
'code/documents/letters/shared',
'code/documents/cover',
'code/documents/letters'
].map(function(subpath) {
return fs.statAsync(path.resolve(tmp_extract_path, subpath));
}));
};
return fs.createReadStreamAsync(archive_location)
.then(function(data) { return tarPromise(data); })
.then(function() { return verifyDir(); })
.then(function(files) {
console.log(files); // never run
return expect(true).to.be.true;
})
.catch(function(e) { console.log(e); });
});
});
});
The various console.log never even get executed and eventually the test times out without any error or stack trace.
I have no idea what I am doing wrong and promises hurt my brain now. When I run the code with node inspector and uncomment the breakpoint, I can see that he value of this._runnable._trace is "done() called multiple times". I have no idea if this is an actual error nor why it doesn't throw an exception if that's an error. I can't explain either why this is even happening since I am not using any done() callbacks anymore with promises and that my test starts with function() and not function(done) like an async test would
Any ideas?
Your problem is that fs.createReadStream is synchronous and returns a ReadableStream that reads data into memory in chunks. PromisifyAll converts callbacks to asynchronous functions into promises, not synchronous functions into asynchronous.
Probably what you want is to use fs.readFileAsync:
var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));
var path = require('path')
var archive_location = path.resolve('example.zip');
var assert = require('assert');
describe('This', function(){
it('should work', function(){
return fs.readFileAsync(archive_location).
then(function(data) {
assert.notEqual(data.length, data.length);
return data;
}).
catch(console.log);
});
});
I have the assertion set to a failing assertion to demonstrate that this actually hits the promise chain.

Using asynchronous commands in nightwatch e2e tests

I have a following e2e scenario written using Nightwatch:
var Q = require('q');
module.exports = {
afterEach: function (browser, done) {
browser.end(function() {
done();
});
},
'should display same data on second page as on first page': function (browser) {
//Given
var firstPage = bowser.pages.first()
//When
Q.all([
firstPage.getTextPromise('#element1'),
firstPage.getTextPromise('#element2'),
firstPage.getTextPromise('#element3')]
).then( function(values) {
users.click('#linkToSecondPage');
//Then
var secondPage = browser.page.secondPage();
secondPage.expect.element('#dataElement1').text.to.equal(values[0]).before(5000);
secondPage.expect.element('#dataElemnet2').contains.text(values[1]);
secondPage.expect.element('#dataElement3').contains.text(values[2]);
});
} }
The getTextPromise command is defined by me in following way:
commands: [{
getTextPromise: function(selector) {
var self = this;
return Q.Promise(function (resolve, reject) {
self.getText(selector, function(result) {resolve(result.value); });
});
} }]
The rationale behind this scenarion is to remember some values on one page before clicking on link to second page
and then checking that on second page the same content is displayed (for example, you click on one item in a table
and go to page displaying details of this particular item).
Unfortunately, I observed that this test sometimes does not check things inside the then callback.
I think this is caused by the test finishing (calling done in afterEach()) before he callback returns.
I thought there was a done() callback passed to the test (much like in nightwatch async unit tests) that I could use but apparently there is not.
Is there a proper way to do this in Nightwatch? Perhaps I am using commands in wrong way?
Nightwatch will keep track of command run order itself if the command runs a method on 'this', and returns 'this'.
Try a command like this, adapted as a page command if you prefer:
exports.command = function() {
var self = this;
var globals = self.globals;
if (!globals.values) { globals.values = []; }
var link = 'some_xpath';
self.getText('selector', function(result) {
if(result.status !== -1){
self.globals.values.push = result.value;
}
});
return self;
};
Because the command returns this. It can be chained and you could be sure the commands run in order without manually writing promises.
example:
var firstPage = bowser.pages.first()
var secondPage = browser.page.secondPage();
firstPage.getTextPromise('#element1')
.getTextPromise('#element2')
.getTextPromise('#element3');
secondPage.expect.element('#dataElement1').text.to.equal(global.values[0]).before(5000)
.expect.element('#dataElemnet2').contains.text(global.values[1])
.expect.element('#dataElement3').contains.text(global.values[2]);
I haven't tested this out so it may need a slight tweak. Hopefully it gives a rough idea of how to chain your commands the nightwatch way. If you run into a problem let me know.

How to use async mocha before() initialization without setTimeout?

I am using Mocha to test out some database queries I created. I need my before block to create the appropriate foreign keys so the unit tests can focus on testing out the raw create/delete functionality of my Node ORM.
My problem is that I am inserting db entries in my before block and the unit tests are running before the before block is finished executing.
I read that promises should be used to deal with this kind of thing, so I refactored my codebase to use promises but I still can't get around the fact that I need a setTimeout.
How can I perform async before block without needing to wrap my first it block in a setTimeout?
var chai = require('chai');
var expect = chai.expect;
var db = require('../server/db/config');
var models = require('../server/db/models');
describe('scoring', function() {
var testMessage = {
x: 37.783599,
y: -122.408974,
z: 69,
message: 'Brooks was here'
};
var messageId = 1;
before(function() {
var token = '' + Math.random();
models.createUser(token).then(function() {
testMessage.userToken = token;
models.insert(testMessage)
});
});
it('should have votes created in db when createVote is called', function(done) {
setTimeout(function(done) {
models.createVote(messageId, token, function(err, res) {
expect(res.insertId).to.be.a('number');
done();
});
}.bind(this, done), 1000);
});
});
You could do it like joews suggests. However, Mocha supports using promises for synchronization. You have to return your promise:
before(function() {
var token = '' + Math.random();
return models.createUser(token).then(function() {
testMessage.userToken = token;
models.insert(testMessage)
});
});
Mocha won't continue to the test until it is able to execute .then on the promise returned by your code.
The function you pass to before, like the other Mocha API methods, can accept a done callback. You should call this when your before actions have completed:
before(function(done) {
var token = '' + Math.random();
models.createUser(token).then(function() {
testMessage.userToken = token;
return models.insert(testMessage)
}).then(function() {
done();
})
});
Mocha docs - asynchronous code

Categories

Resources