I'm working on creating a Mocha unit test based on solution code that was given to me by someone else. (The goal here is to create an online code assessment for students that will be run against my unit test). It's a simple exercise and will not be extensible at all in the future.
I want to get the return value from a jQuery on-submit event and use that for my test case but am unsure how I can do that given the solution code that was given to me to work from.
I've gone through the document here (https://gist.github.com/soheilhy/867f76feea7cab4f8a84) but my particular case is different since we are using jQuery's on document ready and the on-submit.
I've also tried to do something like "export.validate = function(){}" to match an example from the docs but everything I've tried I either get that Mocha doesn't know the function, or Mocha doesn't know the boolean variable references.
solutionCode.js
$(document).ready(function() {
$("#form-submit").on("submit", function () {
var xValid = true;
var yValid = true;
//...Bunch of logic here that could change the boolean values...
return xValid && yValid;
});
});
And here is my Mocha test file.js
this.jsdom = require('jsdom-global')()
global.$ = global.jQuery = require('jquery');
var assert = require('assert');
var work = require('path/to/solutionCode.js');
describe('Validate Form', function() {
it('Form is valid', function(done) {
//Not sure how to get the return value here to do my assertion...
done();
});
});
If the value of both booleans in the return are True, the test should pass, otherwise it should fail.
Related
Let's say you have a simple mocha test:
describe("Suite", function(){
it("test",function(doneCallback){
// here be tests
});
});
In this test I can change the timeout by adding this.timeout(VALUE); anywhere within the describe function.
However, besides the timeout value, there are plenty of other Mocha options that can be exclusively declared either from the command line or from a mocha.opts file that lives in the test folder (./test/mocha.opts).
What I want is to change some of these options at run-time (for example, the reporter) and not in command line / mocha.opts file.
From my research of what's possible, I found that there is an article explaining how you can use mocha programmatically, which would allow changing these options at run-time, but you need to create the Mocha instance yourself, whereas in an ordinary test one doesn't have direct access to the Mocha instance.
So, is there a way to get the Mocha instance from an existent test and change some of these options like reporter at run-time during a test?
I would like to have an option that doesn't require to modify the source code of Mocha in any way (I suppose I could tamper with the Mocha instance to implement a way to get an instance directly in the Mocha constructor).
The best way that you can achieve that is by using Mocha as per the wiki link that you have already referenced, which is using Mocha programmatically.
So to your inquiry on changing the reporter parameter here is a brief example that would do what you want, in order to run the tests against a theoretically already existing file named test-file-a.js that contains your tests:
var Mocha = require('mocha'),
mocha = new Mocha(),
path = require('path');
mocha.addFile(path.join(__dirname, 'test-file-a.js'));
mocha
.reporter('list')
.run();
Besides that there are plenty other options that you can use and also there are some listeners for events, like test that you may want to do something during a test, for example:
mocha
.reporter('list')
.ui('tdd')
.bail()
.timeout(10000)
.run()
.on('test', function(test) {
if (test.title === 'some title that you want here') {
//do something
}
});
Please note that you can define the options per each Mocha instance that will run again a test suite, but not during the runtime of a test suite, so for example if you start your tests for test-file-a.js with the option reporter('list') as above you cannot change it while the tests are running to something else, like you may do for example with the timeout option where you can do this.timeout().
So you would have to instantiate a new Mocha instance as the examples above with different options each time.
No, you cannot. without changing the code.
In short, mocha is created in a scope you cannot access from tests. Without going in details, the objects provided in your scope cannot change the options you want. (You cannot do this: link)
But there is a way to define your own reporter and customize the output for each test:
Create a file called MyCustomReporter.js:
'use strict';
module.exports = MyCustomReporter;
function MyCustomReporter (runner) {
runner.on('start', function () {
var reporter = this.suite.suites["0"].reporter;
process.stdout.write('\n');
});
runner.on('pending', function () {
process.stdout.write('\n ');
});
runner.on('pass', function (test) {
var reporter = this.suite.useReporter;
if(reporter == 'do this') {
}
else if(reporter == 'do that'){
}
process.stdout.write('\n ');
process.stdout.write('passed');
});
runner.on('fail', function () {
var reporter = this.suite.useReporter;
process.stdout.write('\n ');
process.stdout.write('failed ');
});
runner.on('end', function () {
console.log();
});
}
When you run mocha, pass the path of MyCustomReporter.js as reporter parameter(without .js), eg:
mocha --reporter "/home/user/path/to/MyCustomReporter"
The default mocha script actually tries to require a reporter file if it is not found in the default ones(under lib/reporters), github link
Finally, in your tests, you can pass some parameters to customize the output of your reporter:
var assert = require('assert');
describe('Array', function() {
describe('#indexOf()', function() {
this.parent.reporter = 'do this';
it('should return -1 when the value is not present', function() {
this.runnable().parent.useReporter = 'do this';
assert.equal([1,2,3].indexOf(4), -1);
});
});
});
I'm using mocha and trying to build a testing system which reports tests individually. The goal is to have traceability between tests defined in the requirements for the project and unit tests. So, for example, the test 'Must be able to create new widgets' is in the requirements database with id of '43', I want the unit test which tests that criteria to report something like Test 43, Must be able to create new widgets, pass, and then update the corresponding db entry (another service could be responsible for this).
Can this be done in mocha? The only thing I've found so far is to replace text in the it() function with the test id, and use the json reporter to process the results afterwards (but then I don't get the text for what is being tested, unless I combine them and do some kind of parsing). Note: not all tests would have an id.
Here's an example of the kind of functionality I'm hoping for
describe("Widget" function() {
it("should allow creation of widgets", function() {
this.id = 43;
result = widget.create();
expect.result.to.exist;
});
});
And then either a hook, like
afterEach(function(test) {
if (test.hasOwnProperty('id')) {
report(test.result);
}
});
Or a custom reporter, or an adapter of some sort.
runner.on('test end', function(test) {
console.log(test.id); //doesn't exist, but i want it to
report(test);
});
This depends on your assertion library.
With Chai, you havethe optional field for text.
assert.should.exist(result, 'expect Result to exist (Id 43)');
With Jasmine, you can add the test reference to your it():
describe("Widget" function() {
it("should allow creation of widgets (Id 43)", function() {
To use the Mocha custom reporters you could try to define one in your test suite.
module.exports = MyReporter;
function MyReporter(runner) {
var passes = 0;
var failures = 0;
runner.on('pass', function(test){
passes++;
console.log('pass: %s', test.fullTitle());
});
runner.on('fail', function(test, err){
failures++;
console.log('fail: %s -- error: %s', test.fullTitle(), err.message);
});
runner.on('end', function(){
console.log('end: %d/%d', passes, passes + failures);
process.exit(failures);
});
}
There are really 2 suggestions here. The first is the simplest, and is to simply add your id to the description of the it() and then that will show you what has passed and failed. That would be the quickest way to reach your goal.
However, if you wanted to have the fancier method, and could test to ensure things are set, then you could use the custom reporter, which would allow you to fail a test if the ID was not set.
What I wanted and what exists were so close! I was able to solve this using the ctx property of the test in the reporter, e.g. test.ctx.id
test.js
describe("Widget" function() {
it("should allow creation of widgets", function() {
this.id = 43;
result = widget.create();
expect.result.to.exist;
});
});
reporter.js
runner.on('test end', function(test) {
console.log(test.ctx.id);
report(test);
});
I have written a test for a get request, but want to get "full coverage" for this test. Basically, I want to use something like JSON Schema to validate that the JSON return matches my expectations.
My code so far is below:
var winston = require('winston');
//var chai = require('chai');
var request = require('supertest-as-promised');
var testUtils = require('./utils/test_utils');
var API_ROOT = 'http://localhost:8000/mywebsite';
var agent = request(API_ROOT);
describe('/my-profile/', function(){
describe('GET', function() {
var url = '/my-profile/';
it('should return valid payload', function(done) {
agent.
get(url).
set('Content-Type', 'application/json').
expect('Content-Type', /json/).
expect(200).
// then(testUtils.logResponse).
then(function(res) {
done();
}).catch(function(err) {
// winston.log(res).then(done);
done(err);
});
});
});
});
How do I go about using json schema for validate. Any sample links? comment? code?
You might try using Chai json-schema plugin. Which let's you make assertions like the following:
expect(goodApple).to.be.jsonSchema(fruitSchema);
expect(badApple).to.not.be.jsonSchema(fruitSchema)
See the website for full details.
You say you want to use something "like" json schema to validate the returned JSON, well, Chai assertions would suit the task just fine.
Just test for the presence of properties with the property chain, or check that they are of the correct type with the instanceof chain. If you know exactly what the api should return for a given test case, construct a matching object and compare it with the deep chain.
I've been developing with node.js for months but now I'm starting a new project and I'd like to know how to structure the app.
My problem comes when talking about unit testing. I will use nodeunit to write unit tests.
Also I'm using express to define my REST routes.
I was thinking about writing my code that access databases in two "separate" files (They will be more, obviously, but I'm just trying to simplify the code). There will be the routes code.
var mongoose = require('mongoose')
, itemsService = require('./../../lib/services/items-service');
// GET '/items'
exports.list = function(req, res) {
itemsService.findAll({
start: req.query.start,
size: req.query.size,
cb: function(offers) {
res.json(offers);
}
});
};
And, as I'm using there, an item service used just to access data layer. I'm doing this to test only data access layer on unit testing. It'll be something like this:
var mongoose = require('mongoose')
, Item = require('./../mongoose-models').Item;
exports.findAll = function(options) {
var query = Offer
.find({});
if (options.start && options.size) {
query
.limit(size)
.skip(start)
}
query.exec(function(err, offers) {
if (!err) {
options.cb(offers);
}
})
};
This way I can check with unit testing if it works correctly and I can use this code everywhere I want. The only thing I'm not sure if it's been correctly done is the way I pass a callback function to use returned value.
What do you think?
Thanks!
Yes, quite easily!
You can use a unit testing module like mocha and either node's own assert or another such as should.
As an example of a test case for your example model:
var ItemService = require('../../lib/services/items-service');
var should = require('should');
var mongoose = require('mongoose');
// We need a database connection
mongoose.connect('mongodb://localhost/project-db-test');
// Now we write specs using the mocha BDD api
describe('ItemService', function() {
describe('#findAll( options )', function() {
it('"args.size" returns the correct length', function( done ) { // Async test, the lone argument is the complete callback
var _size = Math.round(Math.random() * 420));
ItemService.findAll({
size : _size,
cb : function( result ) {
should.exist(result);
result.length.should.equal(_size);
// etc.
done(); // We call async test complete method
}
},
});
it('does something else...', function() {
});
});
});
And so on, ad nauseum.
Then when you're done writing your tests - assuming you've $ npm install mocha'd - then you'd simply run $ ./node_modules/.bin/mocha or $ mocha if you used npm's -g flag.
Depends how rectal/detailed you want to be really. I've always been advised to, and find it easier to: Write the tests first, to get a clear specification perspective. Then write the implementation against the tests, with any extra insight a freebie.
Just a quick question... I currently have the following jQuery code with a selector in it.
var ID = "idControl"
function doesTreeViewExist()
{
if($('#' + ID).length == 0)
{
return false;
}
else
{
return true;
}
}
I was wondering how do I write the test to test the selector using QUnit? More specifically, I'm having trouble coming up with the syntax/code.
EDIT:
Ok, suppose now I want to mock the selector call instead because I cannot get access to the actual website. I'm using JsTestDriver as my testing tool, which means I cannot touch the browser the tests are running in (else the test runs will stop). What about in such situation? How can I possibly test the code?
Thanks.
The function you post, can be heavily simplified:
var ID = "idControl";
function doesTreeViewExist() {
return !!$('#' + ID).length;
}
Using the !! construct (double bitwise NOT), to convert the length property to Boolean, it will return false only when length is zero.
Speaking about qUnit, you can easily setup a simple test like this:
test("Your selector test", function() {
ok($('#idControl').length > 0, "idControl exists");
// or simply
ok($('#idControl').length, "idControl exists");
});
The ok function does a boolean assertion, equivalent to JUnit's assertTrue.
I test selectors manually, then pass them to code that uses them. I can then unit test the code that uses them. If you want to just test a selector, you need access to the HTML it affects. Your test could include HTML to target, something like:
test("selector works", function() {
var html = $('<input type="select"><option value=0/></input');
var result = $('option', html);
ok(result.count() == 1);
});
But I don't do that... I put my selectors at the edge of the code so I can get to them quickly and step through them under the debugger. I'll have a simple class whose properties are those selectors. Then I'll mock/stub that simple class, so I can write code for everything dependent on those selectors.
The reason I don't test my selectors is because the HTML they target is generated by ASP.NET code, and hard to get to from a javascript test. But I can wrap them in a Humble Object ("http://xunitpatterns.com/Humble Object.html") then test code that depends on that humble object. Here's a simple wrapper class that I can replace with test doubles:
var createSelectWidget = function(rootSelector)
{
return {
userText : $('span', rootSelector),
inputList : $('option', rootSelector),
};
}
Whatever dependency injection pattern you use, you can then stub it like below. Suppose my widget has a select input to read the value of, and a span I want to write some results to:
var createSelectWidgetStub = function()
{
return {
userText : { text = function() {}},
inputList : { val = function() {}},
};
}
I can then pass around this stub in tests where I want to isolate the dependency but don't care about interactions with that dependency. When I want to verify interactions with the dependency, I can mock it with JSMock. Suppose I want to verify interactions with the input list, I would prepare a stub with the one element mock'd:
var selectMock = createSelectWidgetStub();
selectMock.inputList = mc.createMock(selectMock.inputList);
I used Jack and successfully mocked the jquery call and returned a custom length and expected result.
Something like:
jack (function() {
jack.expect("$").exactly("1").withArguments("#" + ID).returnValue( {length:0} );
doesTreeViewExist()
assertEquals(false, result);
});
I have also managed to supply a DOM structure to satisfy the jquery call, as I'm using one of JsTestDriver's built-in function HtmlDoc. Something like:
/*:DOC += <span id="idControl"></span> */
or simply create a DOM sturcture without the specified id to get the false statement.
HTH.