Access "global" mocha.js functions when using require.js - javascript

I am including Mocha.js with the excellent use shim for a Require.js-based site.
How do I access the define() and it() BDD functions declared by Mocha when using Require.js?
Here is a basic code example:
test.js:
var mocha = require('use!mocha')
, testFile = require('testFile.js')
mocha.setup('bdd');
mocha.run();
testFile.js:
define(function(require) {
// describe() and it() are not available
describe('Book', function() {
it('should have pages', function() {
});
});
});
I get the error Uncaught ReferenceError: describe is not defined when running in the browser.
I have tried window.describe and tried moving the require('testFile.js') to after the mocha.setup('bdd'). I know I am missing something. Probably passing the context to mocha somehow.

The problem is that the global functions such as describe and it are set up by mocha.setup(). You can use shim config's init property to call mocha.setup() before mocha is exported.
requirejs.config({
shim: {
'mocha': {
init: function () {
this.mocha.setup('bdd');
return this.mocha;
}
}
}
});
require(['mocha', 'test/some_test'], function (mocha) {
mocha.run();
});
Test files need to require mocha.
define(['mocha'], function (mocha) {
describe('Something', function () {
// ...
});
});
Shim config's init property was introduced in RequireJS 2.1. You might be able to use exports property instead of init with RequireJS 2.0.

I found the solution in geddski's amd-testing examples project.
Instead of including the test file(s) at the top along with mocha like so:
define(['use!mocha', 'testFile'],
function(Mocha, TestFile) {
mocha.setup('bdd');
mocha.run();
});
The test file(s) should be included as another require call and mocha.run() embedded in the callback:
define(['use!mocha'],
function(Mocha) {
mocha.setup('bdd');
// Include the test files here and call mocha.run() after.
require(['testFile'],
function(TestFile) {
mocha.run();
});
});

Related

Replacing dependencies in AMD module format with testdouble.js

I'm writing tests for a JS application using Jasmine and testdouble.js as a mocking library. I am using AMD format to organize code in modules, and RequreJS as a module loader. I was wondering how to use testdouble.js to replace dependency for the module being tested that is in AMD format and it is loading via RequireJS. The documentation is unclear about this or I am missing something, so if someone could point me in the right direction.
I'll post the example bellow that illustrates my setup and the problem that I am facing.
car.js
define("car", ["engine"], function(engine) {
function drive = {
engine.run();
}
return {
drive: drive
}
});
engine.js
define("engine", function() {
function run() {
console.log("Engine running!");
}
return {
run: run
}
});
car.spec.js
define(["car"], function(car) {
describe("Car", function() {
it("should run the motor when driving", function() {
// I am not sure how to mock the engine's object run method
// and where to place that logic, in beforeEach or...
td.replace(engine, "run");
car.drive();
// How to verify that when car.run() has executed, it calls this mocked method
td.verify(engine.run());
});
});
});
testdouble.js does not have any explicit support for AMD modules. The only module-related tricks it offers are Node.js specific and built on top of Node's CJS module loader.
What you would need to do in this case is require from the test a reference to engine and replace the run property, which it seems like you've done (your example is incomplete).
If you do this, don't forget to run td.reset() in an afterEach to restore the original properties to anything you replace!

before/afterAll() is not defined in jasmine-node

I'm trying to use the methods beforeAll and afterAll of jasmine, to create a suite of tests with frisby.js, because actually, frisby doesn't have a support for this methods. So, this is what I'm trying to do:
var frisby = require('frisby');
describe("setUp and tearDown", function(){
beforeAll(function(){
console.log("test beforeAll");
});
afterAll(function(){
console.log("afterAll");
});
//FRISBY TESTS
}); //end of describe function
If I change the methods before/afterAll to before/afterEach, is working, but when I'm using before/afterAll this error appears on console:
Message:
ReferenceError: beforeAll is not defined
Stacktrace:
ReferenceError: beforeAll is not defined
I have the jasmine version 2.3.2 installed on my project, so, I don't know what I need to do to integrate this method.
Use the jasmine library not the jasmine-node library. The second one does not support beforeAll and afterAll methods.
1- npm install -g jasmine
2- jasmine init
3- write the test in the spec folder:
describe("A spec using beforeAll and afterAll", function() {
var foo;
beforeAll(function() {
foo = 1;
});
afterAll(function() {
foo = 0;
});
it("sets the initial value of foo before specs run", function() {
expect(foo).toEqual(1);
foo += 1;
});
it("does not reset foo between specs", function() {
expect(foo).toEqual(2);
});
});
4- Run the tests --> jasmine
The current version of frisby doesnt suport this kind of setup. The community, like myself is eager to this feature like in this issue describes.
The team is working on this feature, but it will come in version 2 of the package that is in the way for more than a year now. More info at this link.

How can I mock RequireJs loader plugin responses in unit tests

The code I'm trying to test relies on RequireJs loader plugins. Example with requirejs/text:
require(['text!templates/foo'], function (data) {
// handle loaded data
});
For a specific unit test, I'm trying to mock the response for text!templates/foo and override with one relevant for the test:
it('should load a template', function (done) {
// TODO: mock 'text!templates/foo' here to return 'mock_data'
// templateViewer uses the text plugin internally to do the actual loading
templateViewer.templateFor('foo', function (error, templateData) {
expect(templateData).toEqual('mock_data');
done();
});
});
I've looked at RequireJs dependency mock solutions, especially Squire.js but it seems they are all suited for mocking regular dependencies and not plugin responses.
I've also looked at stub libraries like sinon to maybe replace the actual require call but that seems problematic.
What's the recommended practice? I prefer not to replace the entire text plugin with a mock one in my requirejs configuration, just override some of its responses in specific tests.
My setup is node+mocha+requirejs
Edit
Please see this example fiddle project to see my issue with Squire:
http://runnable.com/VUBoI0ex6v9Gs-BJ/squirejs-with-plugins-for-node-js-and-hello-world
This will mock what you'd get from requiring text!foo/x.html. Plugins are not special, you just need to mock the entire path, including the plugin name.
var requirejs = require("requirejs");
var assert = require("assert");
requirejs.config({
baseUrl: __dirname,
packages: [
{
name: "squire",
location: "node_modules/squirejs",
main: "src/Squire"
}
]
});
var x;
before(function (done) {
requirejs(["squire"], function (Squire) {
var injector = new Squire();
injector.mock("text!foo/x.html", "foo").require(["text!foo/x.html"],
function (_x) {
x = _x;
done();
});
});
});
it("foo", function () {
assert.equal(x, "foo");
});
The problem you run into with the example code you added to your question is that you use the global require instead of using a require passed by your loader. You should add require as a dependency:
define(['require', ....], function (require, ....) {
The require module is special and reserved by RequireJS. It returns a reference to the require function. You must use it, for instance, when you use RequireJS's contexts so that a module loaded in a specific context uses a require function that is bound to that context. SquireJS also needs you to do this so that it can trap your calls to require. The global require bypasses SquireJS.

Mocha + RequireJS = AMD testing

I have a hard time connecting Mocha to RequireJS based application, may be You'll be able to come up with something :). After many hours when I've been trying to load AMD modules and simply console.log some 'fired' info that the module has been loaded... nothing happend had happened - the program just ended and printed out some mocha info.
var facade = requirejs(['../../public/js/scripts/widgets/widgets/article/main.js'],
function(mod) {
console.log('fired')
});
// run with: $ mocha -u tdd test.js --reporter spec
and than I've come up with the idea to fire just this to test callbacks:
setTimeout((function() {
console.log('fired');
}), 5000);
// run with: $ mocha -u tdd test.js --reporter spec
also didn't work. So finally I've run both with
$ node test.js
and finally it worked. So question is than: How to run Mocha test with callbacks handling, as those are essential for AMD testing?
The way you are doing it, mocha is not going to do anything with your file because it does not see a test suite in it. RequireJS is scheduled to call the callback but mocha exits before this has a chance to happen. Same with your timeout example.
The following gives you an example.
File test.js:
'use strict';
var requirejs = require("requirejs");
requirejs.config({
baseUrl: '.',
nodeRequire: require
});
suite('Something', function(){
var foo;
suiteSetup(function (done){
// This saves the module foo for use in tests. You have to use
// the done callback because this is asynchronous.
requirejs(['foo'],
function(mod) {
console.log("fired!");
foo = mod;
done();
});
});
suite('blah', function(){
test('blah', function(){
if (foo.test !== "test")
throw new Error("failed!");
});
});
});
File foo.js:
define(function () {
return {test: "test"};
});
When you run:
mocha -u tdd test.js
You'll see that the callback is fired and the test passes.
For the benefit of people reading this question and confused by the use of suite, suiteSetup, test... Mocha supports multiple interfaces. The code here is using the TDD interface (the OP invokes Mocha with -u tdd), which exports suite, suiteSetup, test, etc. In the default BDD interface, the equivalents are describe, before and it, respectively.
I have configured related boilerplate for using mocha in environment of RequireJS. It may be not exact what you want, but it may be helpful.
https://github.com/x2es/boilerplate-karma-mocha-chai-requirejs
One more note - assuming that your script placed in "/public" it makes sense to test it in browser environment instead nodejs. For this purposes you should to look at some test-runner like JsTestDriver (https://code.google.com/p/js-test-driver/) or karma-runner (http://karma-runner.github.io/). Or another...
In snipped provided in karma documentation (http://karma-runner.github.io/0.8/plus/RequireJS.html)
var tests = [];
for (var file in window.__karma__.files) {
if (window.__karma__.files.hasOwnProperty(file)) {
if (/Spec\.js$/.test(file)) {
tests.push(file);
}
}
}
requirejs.config({
// Karma serves files from '/base'
baseUrl: '/base/src',
paths: {
'jquery': '../lib/jquery',
'underscore': '../lib/underscore',
},
shim: {
'underscore': {
exports: '_'
}
},
// ask Require.js to load these files (all our tests)
deps: tests,
// start test run, once Require.js is done
callback: window.__karma__.start
});
introduced way when we force requirejs to preload all necessary spec-files using
require.config({
deps: ['array', 'of', 'our', 'spec', 'files']
})
In this environment each spec-file should be a regular RequireJS module.
Example of test spec for such environment:
define(['chai'], function(chai) {
var expect = chai.expect;
describe('bootstrap', function() {
it('should...', function() {
expect('a').to.equal('a');
});
});
});

Testing a Node Module with Intern Js- Can't resolve 'require'

I am trying to test a simple node Module with intern.The module is an AMD module. I am running into a couple of issues
If the module is defined as below, I get the error "moduleName" has
no method 'map' "
define('moduleName',[]function(require){ var r= require('request');
})
If the module is defined as below without a moduleName, I see this
error "undefined is not a function" - I guess its not able to resolve 'require'
define([]function(require){ var r= require('request'); })
Here is how my Test Looks
define([
'intern!object',
'intern/chai!assert',
'/src/api/nameApi'
], function (registerSuite, assert,nameApi) {
registerSuite({
name: 'GetName Test',
getName: function () {
var nameFromApi = nameApi.getName();
assert( nameFromApi!= null,'name is not null');
}
});
});
Providing an explicit module ID as the first argument to define destroys module portability and shouldn’t be done. It is not currently supported by the loader used by the master branch because it is such a bad idea. It is supported by the geezer branch, but again, I strongly advise you to never use this pattern.
The second module definition you have provided is just wrong; you need to put 'require' in your dependencies array if you expect to load the special require function. You also can’t use a variable to pass a module ID to the require function if you are expecting it to be pre-loaded as a dependency. So, it should look like this:
define(['require', 'foo'], function (require) {
var foo = require('foo');
});
or, using the CommonJS compatibility wrapper syntax, where require is implicitly provided:
define(function (require) {
var r = require('foo');
});
EDIT: Also, now that you have added the test module: within your test’s define, '/src/api/nameApi' is not a valid AMD module identifier.

Categories