How do I chain Intern Page Object function calls? - javascript

Following the Intern user guide, I wrote a simple page object:
define(function(require) {
function ListPage(remote) {
this.remote = remote;
}
ListPage.prototype = {
constructor: ListPage,
doSomething: function(value) {
return this.remote
.get(require.toUrl('http://localhost:5000/index.html'))
.findByCssSelector("[data-tag-test-id='element-of-interest']")
.click().end();
}
};
return ListPage;
});
In the test, I want to call doSomething twice in a row, like this:
define(function(require) {
var registerSuite = require('intern!object');
var ListPage = require('../support/pages/ListPage');
registerSuite(function() {
var listPage;
return {
name: 'test suite name',
setup: function() {
listPage = new ListPage(this.remote);
},
beforeEach: function() {
return listPage
.doSomething('Value 1')
.doSomething('Value 2');
},
'test function': function() {
// ...
}
};
});
});
However, when I run the test, I get this error:
TypeError: listPage.doSomething(...).doSomething is not a function
I tried some approaches described in this question, to no avail.

A better way to implement page objects with Intern is as helper functions rather than Command wrappers. Groups of related helper functions can then be used to create Page Object modules.
// A helper function can take config parameters and returns a function
// that will be used as a Command chain `then` callback.
function doSomething(value) {
return function () {
return this.parent
.findByCssSelector('whatever')
.click()
}
}
// ...
registerSuite(function () {
name: 'test suite',
'test function': function () {
return this.remote.get('page')
// In a Command chain, a call to the helper is the argument
// to a `then`
.then(doSomething('value 1'))
.then(doSomething('value 2'));
}
}

Related

Nightwatch js Using page objects as variable in all steps

I have some page object document with code:
var gmailItemClicks = {
composeClick: function () {
return this.section.leftToolbarSection.click('#compose');
}
};
module.exports = {
commands: [gmailItemClicks],
sections: {
leftToolbarSection: {
selector: '.nH.oy8Mbf.nn.aeN',
elements: {
compose: { selector: '.T-I.J-J5-Ji.T-I-KE.L3' },
}
},
};
and the test file with many steps, like this:
module.exports = {
'1st step': function (client) {
gmail.composeClick();
},
'2d step': function (client) {
gmail.composeClick();
}
}
i can use 'gmail' variable if it is in every step like this:
module.exports = {
'1st step': function (client) {
var gmail = client.page.gmail();
gmail.composeClick();
},
'2d step': function (client) {
var gmail = client.page.gmail();
gmail.composeClick();
}
}
but i want to separate this var from the test code in the steps. I tried to use
const gmail = require('./../pages/gmail');
in the test before module.exports bloсk, and i tried to use globals.js file with the same syntax, but i get the error " ✖ TypeError: gmail.composeClick is not a function".
Now i have just one big function where are all steps used variable declared once inside the func, but the log of test looks ugly, i cant to see when the one step started and where it was stopped.
What i missed?
you could create the object in the before block. Here is how it would look like in my code:
(function gmailSpec() {
let gmailPage;
function before(client) {
gmailPage = client.page.gmail();
gmailPage.navigate()
}
function after(client) {
client.end();
}
function firstStep() {
gmailPage.composeClick()
}
function secondStep() {
gmailPage.composeClick()
}
module.exports = {
before,
after,
'1st step': firstStep,
'2nd step': secondStep
}
}());
Hope that helps you :)

Testing a method of an object returned by a function

I have a function that returns an object with many methods and I need to check one of the methods inside this returned object. I am using AngularJS and Karma+Jasmine as testing suite. How do I call methods inside the object returned by a function?
function modalOptions() {
.........
return this.$q((resolve) => {
// test accessable here
this.solveModel = {
save: () => {
// test can't call save()
this.saveToDB = this.toSendToDB;
},
cancel: () => { ...
},
delete: () => { ...
}
};
});
}
My test is somewhat like this...
it('should save modal with the data', function() {
scope.$apply();
expect(vm.modalOptions).toBeDefined();
vm.toSendToDB = true; // hard-coded
vm.savedToDB = undefined // default value from other controller
spyOn(vm, 'modalOptions').and.callThrough();
console.log(vm.modalOptions()); // gives weird response: c{$$state: Object{status: 0}} instead of the solveModal object
expect(vm.toSendToDB).toBeTruthy();
expect(vm.savedToDB).toBeTruthy();
});
Sorry, I can not comment yet, but the promise has to be resolved and the solveModel passed to it, in order for solveModel to be returned. Where do you resolve the promise?

Stubbing async.waterfall with Sinon.JS

I am trying to test async.waterfall by stubbing one of my functions using Sinon.js.
// functions.js
module.exports = {
// function I don't want to run
doBigThing: function() {
console.log("[doBigThing] was called");
},
// function I want to stub
myFunction: function(number, callback) {
console.log("[myFunction] was called");
doBigThing();
callback(null, number);
},
// function I want to test
waterfall: function(callback) {
return async.waterfall([
async.constant(5), // 5 just for the demo
myFunction
], callback);
}
}
And my test is:
describe('water', function() {
it ('successfully falls', function() {
// function under test
var waterfall = functions.waterfall;
var callback = function(err, number) {
expect(err).to.be.null;
expect(number).to.equal(5);
};
// I would like this stub to run instead of functions.myFunction
sinon.stub(functions, 'myFunction', function(number, callback) {
console.log("[myFunction] stub was called");
callback(null, number);
});
waterfall(callback);
// I suppose this is happening: myFunction(5, callback)
expect(functions.myFunction.withArgs(5, callback)).to.have.been.called;
expect(callback).to.have.been.called;
});
});
So the test passes, but the stub is ignored, because doBigThing was called:
Water
✓ successfully falls
[myFunction] was called
[doBigThing] was called
Instead I would like to see
Water
✓ successfully falls
[myFunction] stub was called
I am probably missing out on something and I would appreciate your help.
You're stubbing functions object's method myFunction, but in waterfall method you're calling a myFunction function (I actually can't run your code in my environment, I get "ReferenceError: myFunction is not defined"). So this should work:
// functions.js
var functions = {
// function I don't want to run
doBigThing: function() {
console.log("[doBigThing] was called");
},
// function I want to stub
myFunction: function(number, callback) {
console.log("[myFunction] was called");
functions.doBigThing(); // CHANGE HERE
callback(null, number);
},
// function I want to test
waterfall: function(callback) {
return async.waterfall([
async.constant(5), // 5 just for the demo
functions.myFunction // CHANGE HERE
], callback);
}
};
module.exports = functions;

How can I test that a function has not been called?

I'm testing router and have two functions, and I need to test if first function was called and second was not. There is method toHaveBeenCalled but there is no method to test if function was not called. How can I test that?
I have code like this:
var args, controller, router;
beforeEach(function() {
controller = {
foo: function(name, id) {
args = [].slice.call(arguments);
},
bar: function(name) {
}
};
spyOn(controller, "foo").and.callThrough();
spyOn(controller, "bar").and.callThrough();
router = new route();
router.match('/foo/bar/{{id}}--{{name}}', controller.foo);
router.match('/foo/baz/{{id}}--{{name}}', controller.bar);
router.exec('/foo/bar/10--hello');
});
it('foo route shuld be called', function() {
expect(controller.foo).toHaveBeenCalled();
});
it('bar route shoud not be called', function() {
// how to test if bar was not called?
});
Use the not operator:
expect(controller.bar).not.toHaveBeenCalled();

RequireJS and Prototypal Inheritance

I'm running into an issue with using RequireJS and Prototypal inheritance. Here's my module:
define(function () {
function Module(data) {
this.data = data;
}
Module.prototype.getData = function () {
return this.data;
};
Module.prototype.doSomething = function () {
console.log(this.data);
console.log(this.getData());
};
return Module;
Module.prototype.callFunction = function (fn) {
if (this[fn]) {
console.log('call');
Module.prototype[fn]();
}
};
});
Then I instantiate the module, like so:
var module = new Module({ name: 'Marty' });
module.getData(); // returns { name: 'Marty' }
module.data; // returns { name: 'Marty' }
module.callFunction('doSomething') // returns undefined on the first (and second) console log
The console.logs in the module.doSomething() always return undefined. Am I misunderstanding how prototypal inheritance works with RequireJS?
As it turns out, I had written the callFunction method incorrectly. The correct way is:
Module.prototype.callFunction = function (fn) {
if (this[fn] && typeof this[fn] === "function") {
this[fn]();
}
};
The problem was using Module.prototype instead of this. Whoops.

Categories

Resources