waitForCondition method never returning? - intern

I'm trying to use Intern to author a first functional test, and I can't get around the following problem: when running the following test script
define(["intern!object",
"intern/chai!assert"
], function(registerSuite, assert){
registerSuite({
name: "suite",
"test": function(){
var browser = this.remote;
console.log("HELLO !");
browser.get("http://www.google.com", function() {
console.log("PAGE LOADED !");
browser.waitForCondition("!!window.document.gbqf", 1000, function(err, value){
console.log("LET'S BEGIN... ");
browser.eval("window.document.gbqf", function(err, value){
console.log("BYE BYE !");
browser.quit();
});
});
});
}
});
});
in chrome, using selenium server standalone 2.32.0 and chromedriver 26.0.1383.0 for windows, my test never end and the last message displayed in the console is "PAGE LOADED !".
Does anyone has an idea of how I'm suppose to write this test, or have a link to some proper (real life) functional tests examples ?
Thanks for your help,
Sebastien

The functional interface does not use callback arguments, it uses promises instead. Your code should look like this:
define([
"intern!object",
"intern/chai!assert"
], function (registerSuite, assert) {
registerSuite({
name: "suite",
"test": function () {
var browser = this.remote;
console.log("HELLO !");
return browser
.get("http://www.google.com")
.then(function () {
console.log("PAGE LOADED !");
})
.waitForCondition("!!window.document.gbqf", 1000)
.then(function () {
console.log("LET'S BEGIN... ");
})
.eval("window.document.gbqf")
.then(function (value) {
console.log("BYE BYE !");
});
});
}
});
});
Note in particular:
The last promise chain from this.remote is returned by the test function to indicate to Intern that the test is asynchronous
waitForCondition does not return a value
You should never call quit yourself; this is handled by Intern once the test is complete

Related

How to reuse an element inside of a function in protractor page object model?

I am using protractor with Jasmine in windows 10 OS. This is my page for stack over flow login .May I know how to access txt_username inside of clearme: function().
pgstackover.js
//pgstackover.js
'use strict';
module.exports = {
txt_username: element(by.id('email')),
txt_password: element(by.id('password')),
btn_submit: element(by.id('submit-button')),
clearme: function() {
txt_username.isDisplayed();
txt_username.clear();
txt_password.clear()
} ,
go: function() {
browser.driver.ignoreSynchronization = true;
browser.waitForAngularEnabled(false);
browser.driver.manage().window().maximize();
browser.driver.get('https://stackoverflow.com/users/login'); //overrides baseURL
}
This is my spec.js file and it works until clear me function and fails with error Failed: txt_username is not defined
var toDoPage = require('../../../../pages/pgstackover.js');
describe('My first non angular class', function() {
it('should navigate to stack overflow login page', function() {
toDoPage.go();
});
it ('My function', function() {
// browser.driver.get('https://stackoverflow.com/users/login');
toDoPage.txt_username.sendKeys('6');
toDoPage.txt_password.sendKeys('winchester');
var value=toDoPage.btn_submit.getText();
expect(value).toEqual("Log in");
});
it('clear me', function() {
toDoPage.clearme();
});
})
Too make long story short your code does not know what is txt_username so you need to point it out. You are missing .this in your clearme function.
I haven't used a promise manager for ages (since it is obsolete) so here is a working example using async/await:
async clearme() {
await this.txt_username.isDisplayed();
await this.txt_username.clear();
await this.txt_password.clear();
}

Why won't these chai tests fail?

We have some simple "is this really working" chai tests of an electron app using spectron and WebdriverIO. The example code we started with is from
https://github.com/jwood803/ElectronSpectronDemo as reported in https://github.com/jwood803/ElectronSpectronDemo/issues/2, the chai-as-promised tests are not catching mismatches, so I thought I would add some additional tests to find out why Chai is not failing tests where the electron app has text that doesn't match the expected unit test text.
Let's start with something really simple, the rest of the code is at https://github.com/drjasonharrison/ElectronSpectronDemo
describe('Test Example', function () {
beforeEach(function (done) {
app.start().then(function() { done(); } );
});
afterEach(function (done) {
app.stop().then(function() { done(); });
});
it('yes == no should fail', function () {
chai.expect("yes").to.equal("no");
});
it('yes == yes should succeed', function () {
chai.expect("yes").to.equal("yes");
});
The first unit test fails, the second succeeds.
And when we put the assertion into a function this still detects the failure:
it('should fail, but succeeds!?', function () {
function fn() {
var yes = 'yes';
yes.should.equal('no');
};
fn();
});
So now into the world of electron, webdriverio, and spectron, the application title is supposed to be "Hello World!", so this should fail, but it passes:
it('tests the page title', function () {
page.getApplicationTitle().should.eventually.equal("NO WAY");
});
Hmm, let's try a more familiar test:
it('should fail, waitUntilWindowLoaded, yes != no', function () {
app.client.waitUntilWindowLoaded().getTitle().then(
function (txt) {
console.log('txt = ' + txt);
var yes = 'yes';
yes.should.equal('no');
}
);
});
Output:
✓ should fail, waitUntilWindowLoaded, yes != no
txt = Hello World!
It succeeds? What? Why? How?
Found it! If you look at https://github.com/webdriverio/webdriverio/blob/master/examples/standalone/webdriverio.with.mocha.and.chai.js
you will see that you need to return the promise from each of the tests. This is typical for async chai/mocha tests:
it('tests the page title', function () {
return page.getApplicationTitle().should.eventually.equal("NO WAY");
});
If you do that, then the chai test is actually correctly evaluated.

Testing: Mocha and node differ re fs.exists

First, while I'm an experienced programmer, I'm relatively new to node, and very new to mocha, so my issue may be ME! In which case, I'll be happy to find that out too!
Some code I'm writing makes use of an npm module which contains a call to fs.exists. I get different results when I run a test with fs.exists when run via node vs when run vs mocha; in my opinion, I should be receiving the same answer; the file does exists, so the result should be true in both cases, but instead, it's true when invoked via node, and false when invoked via mocha. Well, it's not functioning correctly.
I'm aware that fs.exists is deprecated, but that's in the npm module I'm using, so unless I modify the module, that's what I'm using.
The difference is associated with how I invoke mocha.
Per some site recommendations, I edited my package.json file to include, in the 'scripts' section, the following statement: "test": "mocha test", and I have placed my tests in this 'test' directory. This is invoked via npm test.
After experiencing problems, I also installed did npm install -g mocha.
My test file is testVersion.js
The result is that I get different answers when I invoke one of the following three ways when invoking fs.exists via node, npm test, and mocha testVersion.js; I'm expecting 'true':
- node testVersion.js returns true - it finds the file.
- mocha testVersion.js returns true - it finds the file.
- npm test returns false - it does not find the file.
I'm suspecting that maybe different versions of mocha or node are being invoked on me, but don't have enough experience to be able to determine this on my own.
So my question is: why am I getting different results?
Here's my code for testVersion.js
var expect = require('chai').expect;
var assert = expect.assert;
var fs = require("fs");
var isInTest = typeof global.it === 'function'; //exe via mocha or node
console.log('isInTest mode: ', isInTest);
if(!isInTest) {
console.log('NOT TEST MODE: invoking fs.exists');
fs.exists("testVersion.js", function(info) {
console.log('NOT TEST MODE: fs.exists callback RAN.');
console.log('NOT TEST MODE: fs.exists: should be true and is: ', info);
})
}
if(isInTest) {
describe("Test Mocha and fs.exists issue", function() {
it("Test that file self exists.", function() {
console.log('TEST MODE: invoking fs.exists');
expect(fs.exists("testVersion.js", function(result) {
console.log('TEST MODE: fs.exists callback RAN.');
console.log('TEST MODE: fs.exists: should be true, and is: ', result);
return true;
})).to.equal(true);
});
});
};
After a lot of testing work, I believe my problem was because of async calls associated with fs.exists. At any rate, the following is working for me, and I wanted to document it in case it helps anyone else.
var assert = require('assert');
var fs = require('fs');
fs.existsSync("bbq.js", function(result) {
console.log('False: fs.exists(bbq.js) says: ', result);
})
fs.existsSync("test2.js", function(result) {
console.log('True: fs.exists(test2.js) says: ', result);
})
describe('Testing Synch fs.existsSync() ===', function() {
describe('False: fs.exists(bbq.js)', function() {
it("This assertion should pass, as we are asserting false on file that doesn't exist.", function() {
assert.equal(false, fs.existsSync(__dirname + "/bbq.js", function(result) { return result;}))
});
});
describe('Testing Synch fs.existsSync(test2.js method A)', function() {
it("This assertions should pass as we are asserting true on file that does exist", function() {
assert.equal(true, fs.existsSync(__dirname + "/test2.js", function(result) {
return result;
}));
});
});
describe('Testing Synch fs.existsSync(test2.js method B)', function() {
it("This assertions should pass as we are are asserting true on file that does exist using callback", function() {
fs.existsSync(__dirname + "/test2.js", function(result) {
assert.equal(true, result);
});
});
});
});
////////////////////
describe('Asynch test of fs.exists() === some results are UNDEFINED because of async', function() {
describe('False: fs.exists(bbq.js)', function() {
it("This assertion should pass as we are expecting undefined result due to async.", function() {
assert.equal(undefined, fs.exists(__dirname + "/bbq.js", function(result) { return result;}))
});
});
describe('True: fs.exists(test2.js method A)', function() {
it("This assertion should pass as we are expecting undefined result due to async.", function() {
assert.equal(undefined, fs.exists(__dirname + "/test2.js", function(result) {
return result;
}));
});
});
describe('True: fs.exists(test2.js method B)', function() {
it("This equal assertion passes, because of use of callback waits for response.", function() {
fs.exists(__dirname + "/test2.js", function(result) {
assert.equal(true, result);
});
});
});
});

Protractor in Node: How do I order my tests to run synchronously?

I'm wondering how to execute multiple "describe" blocks in synchronous order?
describe('Go To Home Page', function () {
browser.ignoreSynchronization = true;
it("Url should be on Login Page", function () {
browser.get(HomePageUrl).then(function () {
browser.wait(urlChanged(loginPageUrl), 2000).then(
function (newurl){
var url = browser.getCurrentUrl().then(function (url) {
expect(url).tobe(loginPageUrl);
//I know I'm at Login page url... how do I kick off next test?
});
}
)
});
});
});
This test goes to Home page, then if it is redirected to Login page I want to execute all my Login Tests using new Describe blocks. Problem is that if I put the next Describe block at same level as the first, node executes all of them in parallel.
I'd prefer not to get into callback-hell... code above is already getting too deep in my opinion.
Jasmine has Asyncronous support exacly for that.
describe('Go To Home Page', function () {
browser.ignoreSynchronization = true;
it("Url should be on Login Page", function (done) {
browser.get(HomePageUrl).then(function () {
browser.wait(urlChanged(loginPageUrl), 2000).then(
function (newurl){
var url = browser.getCurrentUrl().then(function (url) {
expect(url).tobe(loginPageUrl);
done();
});
}
)
});
});
it("next", function () {
//will start this block after previous done callback has been called
});
});
PS Promises can and should be chained in a single line to avoid nesting:
it("Url should be on Login Page", function (done) {
browser
.get(HomePageUrl)
.then(function () {
return browser.wait(urlChanged(loginPageUrl), 2000);
})
.then(function () {
return browser.getCurrentUrl();
})
.then(function (currentUrl){
expect(currentUrl).tobe(loginPageUrl);
done();
});
});

How to test stubbed database queries

I have a Sails.Js controller that looks like this
module.exports = {
confirmID: function(req,res) {
var uid = req.params.id;
User.findOne({id:uid}).exec(function(err,user) {
// ...
});
}
}
where User is a sails-postgres model. I have tried testing it with mocha, sinon and supertest with a test like this
describe('Controller', function() {
var sandbox;
before(function() {
sandbox = sinon.sandbox.create();
sandbox.stub(User, 'findOne');
});
after(function() {
sandbox.restore();
});
describe('GET /confirmid/:id', function() {
it('should do something', function(done) {
request(sails.hooks.http.app)
.get('/confirmid/123')
.expect(200)
.end(function(err,res) {
sandbox.fakes[0].called.should.be.true;
done();
});
});
});
If I leave it at that it errors out because exec is called on undefined, but I can't seem to stub the nested exec method without either errors or the test hanging. Is there a way to stub a series of method calls such as .find().exec()? Or am I best to just leave this to integration tests where I can test it with an actual database?
Assuming that you really want to stub (not just spy) - you want to control what the query resolves to as opposed to simply knowing whether the query was executed. Here's what I'm using to stub sails/waterline query methods. Something like...
var stubQueryMethod = require('stubQueryMethod');
describe('Controller', function() {
before(function() {
stubQueryMethod(User, 'findOne', {
id: 123,
name: 'Fred Fakes'
});
});
after(function() {
User.findOne.restore();
});
describe('GET /confirmid/:id', function() {
it('should do something', function(done) {
request(sails.hooks.http.app)
.get('/confirmid/123')
.expect(200)
.end(function(err,user) {
user.should.have.property('name', 'Fred Fakes');
done();
});
});
});
});
Source: https://gist.github.com/wxactly/f2258078d802923a1a0d
For people looking for other options to stub or mock waterline models, I've found the following four options:
stubQueryMethod.js gist - https://gist.github.com/wxactly/f2258078d802923a1a0d
model mock gist - https://gist.github.com/campbellwmorgan/e305cc36365fa2d052a7
weaselpecker - https://github.com/ottogiron/weaselpecker
sails-mock-models - https://github.com/ryanwilliamquinn/sails-mock-models
After evaluating each one, I've decided on sails-mock-models because it is easy to understand and seems the most used sails mocking library according to npm: https://www.npmjs.com/package/sails-mock-models
Hope this helps someone!
Update: I'm still using sails-mock-models, and it is quite easy, but there are a few drawbacks such as it fails to return promises that are taken into a q.all(promiseArray).then() call. If I get around to investigating the other options or find a workaround, I will post it here.
This will only work for queries that use exec and it overloads all exec calls so if you try to return an error and you have, say, a controller with a policy out front, and the policy does a database lookup, you'll likely go into error there prior to hitting the controller code you intended to test.... that can be fixed with stub.onCall(x), but it is still a bit precarious.
Warnings aside, here's how I've done this in the past:
var path = require('path');
var sinon = require('sinon');
var Deferred = require(path.join(
process.cwd(),
'node_modules/sails',
'node_modules/waterline',
'lib/waterline/query/deferred'
));
module.exports = function () {
return sinon.stub(Deferred.prototype, 'exec');
};
Assuming you have the following service, MyService:
module.exports.dbCall = function (id, cb) {
Model.findOne(id).exec(function (err, result) {
if (err) {
sails.log.error('db calls suck, man');
return cb(err, null);
}
cb(null, result);
});
};
You can test the error case like so:
before(function () {
stub = databaseStub();
});
afterEach(function () {
stub.reset();
});
after(function () {
stub.restore();
});
it('should return errors', function (done) {
stub.onCall(0).callsArgWith(0, 'error');
MyService.dbCall(1, function (err, results) {
assert.equal(err, 'error');
assert.equal(results, null);
done();
});
});

Resources