This question is likely based in my lack of previous experience with node.js, but I was hoping jasmine-node would just let me run my jasmine specs from the command line.
TestHelper.js:
var helper_func = function() {
console.log("IN HELPER FUNC");
};
my_test.spec.js:
describe ('Example Test', function() {
it ('should use the helper function', function() {
helper_func();
expect(true).toBe(true);
});
});
Those are the only two files in the directory. Then, when I do:
jasmine-node .
I get
ReferenceError: helper_func is not defined
I'm sure the answer to this is easy, but I didn't find any super-simple intros, or anything obvious on github. Any advice or help would be greatly appreciated!
Thanks!
In node, everything is namespaced to it's js file. To make the function callable by other files, change TestHelper.js to look like this:
var helper_func = function() {
console.log("IN HELPER FUNC");
};
// exports is the "magic" variable that other files can read
exports.helper_func = helper_func;
And then change your my_test.spec.js to look like this:
// include the helpers and get a reference to it's exports variable
var helpers = require('./TestHelpers');
describe ('Example Test', function() {
it ('should use the helper function', function() {
helpers.helper_func(); // note the change here too
expect(true).toBe(true);
});
});
and, lastly, I believe jasmine-node . will run every file in the directory sequentially - but you don't need to run the helpers. Instead you could move them to a different directory (and change the ./ in the require() to the correct path), or you could just run jasmine-node *.spec.js.
you do not necessarily need to include your helper script in the spec (testing) file if you have the jasmine config as:
{
"spec_dir": "spec",
"spec_files": [
"**/*[sS]pec.js"
],
"helpers": [
"helpers/**/*.js"
],
"stopSpecOnExpectationFailure": false,
"random": false
}
Everything in the helpers/ folder will run before the Spec files. In the helpers files have something like this to include your function.
beforeAll(function(){
this.helper_func = function() {
console.log("IN HELPER FUNC");
};
});
you will then be able to make references to it in your spec files
Related
I have such a code:
requirejs.config({
urlArgs: "bust=" + (new Date()).getTime(),
paths: {
mods: 'default',
myFriend: 'myFriend',
myCoworker: 'myCoworker'
},
shim: {
mods: ['myFriend', 'myCoworker']
}
});
require(['mods'], function (mods) {
// something to do
});
and modules which are the dependencies:
myFriend.js
var mess = `<a really huge text, almost 200 Kbytes>`
console.log('This code is ran in the myFriend module...', {mess:mess});
myCoworker.js
console.log('This code is ran in the myCoworker module...');
var wrk = {
name: 'John'
};
So I hope, that accordingly to shim is should always load myFriend.js (that is checked by console.output) before myCoworker.js. But it doesn't. The console output shows:
This code is run in the myCoworker module...
and then
This code is run in the myFriend module...
Probably I have missed something, but what?
The entire code is here: http://embed.plnkr.co/zjQhBdOJCgg8QuPZ5Q8A/
Your dealing with a fundamental misconception in how RequireJS works. We use shim for files that do not call define. Using shim makes it so that RequireJS will, so to speak, add a kind of "virtual define" to those files. The shim you show is equivalent to:
define(['myFriend', 'myCoworker'], function (...) {...});
The dependency list passed to a define or require call does not, in and of itself, specifies a loading order among the modules listed in the dependency list. The only thing the dependency list does is specify that the modules in the list must be loaded before calling the callback. That's all.
If you want myFriend to load first, you need to make myCoworker dependent on it:
shim: {
mods: ['myFriend', 'myCoworker'],
myCoworker: ['myFriend'],
}
By the way, shim is really meant to be used for code you do not control. For your own code you should be using define in your code instead of setting a shim in the configuration.
When using JUnit and Maven in Java, one can have separate property files for src/main and src/test. This allows different configuration for code and tests, having Maven to manage the resources by using Java classpath.
Is there a similar way in Javascript code run by Node.js? I use Mocha for unit-testing and Grunt for task management.
Code example for script.js:
var config = require('./config/dev/app.js');
exports.getFileName = function() {
return config.fileName; // returns 'code.txt'
}
What I need is to make the script.js use different config file when being required in a test.js unit test like this:
var assert = require('assert');
var s = require('./script.js');
describe('Test', function () {
it('should use different config file', function() {
assert.equal('test.txt', s.getFileName());
});
});
Is there a way to use different configuration ./config/test/app.js in the script.js without having to alter the code of script.js? What I really try to avoid is to adjust the code to support unit tests. Instead, I want to achieve similar functionality such as mentioned Java classpath.
Please try this code.
Script.js
var config;
if(process.env.dev===true){
config = require('./config/dev/config.js');
}
if(process.env.prod===true){
config = require('./config/prod/config.js');
}
exports.getFileName = function() {
return config.fileName; // returns 'code.txt'
}
test.js
//set the environment here
process.env.dev = true;
var assert = require('assert');
var s = require('./script.js');
describe('Test', function () {
it('should use different config file', function() {
assert.equal('test.txt', s.getFileName());
});
});
I have not found any elegant solution out there on the web so I have implemented and published my own.
Check it out here: https://npmjs.org/package/app-config
Using the app-config plugin, only the script.js needs to get changed this way:
var config = require('app-config').app;
exports.getFileName = function() {
return config.fileName; // returns 'code.txt'
}
The app needs to be run this way for example
NODE_ENV=dev node script.js
NODE_ENV=unitTest mocha test.js
Depending on the NODE_ENV environmental variable, the right set of configuration files will be loaded by the app-config plugin.
I'm trying to get started with Buster.js, and I installed both buster and buster-amd, but even so my use of Require.js is causing problems. My buster.js file looks like this:
var config = module.exports;
config["My tests"] = {
autoRun: false,
environment: "browser", // as opposed to "node"
extensions: [require("buster-amd")],
rootPath: "../",
sources: ['ext/require/require.js'],
tests: ["buster-test/*-test.js"]
};
and my test like this:
define(['buster-test/buster'
], function(buster) {
buster.spec.expose(); // Make some functions global
describe("A Fake Test", function () {
it("can be instantiated", function () {
console.log('test')
});
});
buster.run()
});
But when I try to run the above, I get:
Uncaught exception: ./buster/load-all.js:1 Uncaught ReferenceError: require is not defined
TypeError: uncaughtException listener threw error: Cannot read property 'id' of undefined
at Object.module.exports.uncaughtException (/usr/lib/node_modules/buster/node_modules/buster-test-cli/lib/runners/browser/progress-reporter.js:42:50)
at notifyListener (/usr/lib/node_modules/buster/node_modules/buster-test-cli/node_modules/bane/lib/bane.js:49:35)
at Object.object.emit (/usr/lib/node_modules/buster/node_modules/buster-test-cli/node_modules/bane/lib/bane.js:127:17)
at Object.module.exports.bane.createEventEmitter.emitCustom (/usr/lib/node_modules/buster/node_modules/buster-test-cli/lib/runners/browser/remote-runner.js:289:14)
at /usr/lib/node_modules/buster/node_modules/buster-test-cli/lib/runners/browser/remote-runner.js:92:16
at PubSubClient.on._handler (/usr/lib/node_modules/buster/node_modules/buster-test-cli/node_modules/ramp/lib/pubsub-client.js:73:43)
at Object.Faye.Publisher.trigger (/usr/lib/node_modules/buster/node_modules/buster-test-cli/node_modules/ramp/node_modules/faye/node/faye-node.js:385:19)
at Object.Faye.extend.Set.Faye.Class.distributeMessage (/usr/lib/node_modules/buster/node_modules/buster-test-cli/node_modules/ramp/node_modules/faye/node/faye-node.js:668:30)
at Object.Faye.Client.Faye.Class._deliverMessage (/usr/lib/node_modules/buster/node_modules/buster-test-cli/node_modules/ramp/node_modules/faye/node/faye-node.js:1070:20)
at Object.Faye.Client.Faye.Class.receiveMessage (/usr/lib/node_modules/buster/node_modules/buster-test-cli/node_modules/ramp/node_modules/faye/node/faye-node.js:1007:12)
Has anyone seen anything like this before, and if so do you have any suggestions as to what I'm doing wrong?
P.S. If I remove the extensions: line I get a similar error, except that it complains about define instead of require. So it seems like the failure to find require is happening inside the plug-in ... but I have no idea how to provide Require to the plug-in.
Have you tried adding the require.js to libs instead of sources on your buster config? So the config would look like this:
var config = module.exports;
config["My tests"] = {
autoRun: false,
environment: "browser", // as opposed to "node"
libs: [ 'ext/require/require.js' ],
extensions: [require("buster-amd")],
rootPath: "../",
tests: ["buster-test/*-test.js"]
};
I take a different approach. I don't disable autorun, but instead use Buster's async test case format where you define the test case as a function that's passed a run callback. Use the (not well documented) resources: config setting to allow require to load your source code.
config["Browser tests"] = {
environment: "browser",
libs: [ 'test/require_config.js','require.js' ],
rootPath: "../",
resources: ["your_source_code/**/*.js"],
tests: ["buster-test/*-test.js"]
};
Then use require() in your tests, and when you've loaded your code call the run callback with the tests:
buster.testCase("AppCode",function(run) {
require(["appCode"],function(appCode) {
run({
"it works": function() { assert(true) }
})
});
});
I've created an example project showing this method require.js with buster.js. It has a small helper function to do both the testCase and require call simultaneously.
I am trying to understand how to develop stand-alone Javascript code. I want to write Javscript code with tests and modules, running from the command line. So I have installed node.js and npm along with the libraries requirejs, underscore, and mocha.
My directory structure looks like this:
> tree .
.
├── node_modules
├── src
│ └── utils.js
└── test
└── utils.js
where src/utils.js is a little module that I am writing, with the following code:
> cat src/utils.js
define(['underscore'], function () {
"use strict";
if ('function' !== typeof Object.beget) {
Object.beget = function (o) {
var f = function () {
};
f.prototype = o;
return new f();
};
}
});
and test/utils.js is the test:
> cat test/utils.js
var requirejs = require('requirejs');
requirejs.config({nodeRequire: require});
requirejs(['../src/utils'], function(utils) {
suite('utils', function() {
test('should always work', function() {
assert.equal(1, 1);
})
})
});
which I then try to run from the top level directory (so mocha sees the test directory):
> mocha
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Calling node's require("../src/utils") failed with error: ReferenceError: define is not defined
at /.../node_modules/requirejs/bin/r.js:2276:27
at Function.execCb (/.../node_modules/requirejs/bin/r.js:1872:25)
at execManager (/.../node_modules/requirejs/bin/r.js:541:31)
...
So my questions are:
Is this the correct way to structure code?
Why is my test not running?
What is the best way to learn this kind of thing? I am having a hard time finding good examples with Google.
Thanks...
[sorry - momentarily posted results from wrong code; fixed now]
PS I am using requirejs because I also want to run this code (or some of it) from a browser, later.
Update / Solution
Something that is not in the answers below is that I needed to use mocha -u tdd for the test style above. Here is the final test (which also requires assert) and its use:
> cat test/utils.js
var requirejs = require('requirejs');
requirejs.config({nodeRequire: require});
requirejs(['../src/utils', 'assert'], function(utils, assert) {
suite('utils', function() {
test('should always work', function() {
assert.equal(1, 1);
})
})
});
> mocha -u tdd
.
✔ 1 tests complete (1ms)
The reason your test isn't running is because src/utils.js is not a valid Node.js library.
According to the RequireJS documentation, in order to co-exist with Node.js and the CommonJS require standard, you need to add a bit of boilerplate to the top of your src/utils.js file so RequireJS's define function is loaded.
However, since RequireJS was designed to be able to require "classic" web browser-oriented source code, I tend to use the following pattern with my Node.js libraries that I also want running in the browser:
if(typeof require != 'undefined') {
// Require server-side-specific modules
}
// Insert code here
if(typeof module != 'undefined') {
module.exports = whateverImExporting;
}
This has the advantage of not requiring an extra library for other Node.js users and generally works well with RequireJS on the client.
Once you get your code running in Node.js, you can start testing. I personally still prefer expresso over mocha, even though its the successor test framework.
The Mocha documentation is lacking on how to set this stuff up, and it's perplexing to figure out because of all the magic tricks it does under the hood.
I found the keys to getting browser files using require.js to work in Mocha under Node: Mocha has to have the files added to its suites with addFile:
mocha.addFile('lib/tests/Main_spec_node');
And second, use beforeEach with the optional callback to load your modules asynchronously:
describe('Testing "Other"', function(done){
var Other;
beforeEach(function(done){
requirejs(['lib/Other'], function(_File){
Other = _File;
done(); // #1 Other Suite will run after this is called
});
});
describe('#1 Other Suite:', function(){
it('Other.test', function(){
chai.expect(Other.test).to.equal(true);
});
});
});
I created a bootstrap for how to get this all working: https://github.com/clubajax/mocha-bootstrap
You are trying to run JS modules designed for browsers (AMD), but in the backend it might not work (as modules are loaded the commonjs way). Because of this, you will face two issues:
define is not defined
0 tests run
In the browserdefine will be defined. It will be set when you require something with requirejs. But nodejs loads modules the commonjs way. define in this case is not defined. But it will be defined when we require with requirejs!
This means that now we are requiring code asynchronously, and it brings the second problem, a problem with async execution.
https://github.com/mochajs/mocha/issues/362
Here is a full working example.
Look that I had to configure requirejs (amd) to load the modules, we are not using require (node/commonjs) to load our modules.
> cat $PROJECT_HOME/test/test.js
var requirejs = require('requirejs');
var path = require('path')
var project_directory = path.resolve(__dirname, '..')
requirejs.config({
nodeRequire: require,
paths: {
'widget': project_directory + '/src/js/some/widget'
}
});
describe("Mocha needs one test in order to wait on requirejs tests", function() {
it('should wait for other tests', function(){
require('assert').ok(true);
});
});
requirejs(['widget/viewModel', 'assert'], function(model, assert){
describe('MyViewModel', function() {
it("should be 4 when 2", function () {
assert.equal(model.square(2),4)
})
});
})
And for the module that you want to test:
> cat $PROJECT_HOME/src/js/some/widget/viewModel.js
define(["knockout"], function (ko) {
function VideModel() {
var self = this;
self.square = function(n){
return n*n;
}
}
return new VideModel();
})
Just in case David's answer was not clear enough, I just needed to add this:
if (typeof define !== 'function') {
var define = require('amdefine')(module);
}
To the top of the js file where I use define, as described in RequireJS docs ("Building node modules with AMD or RequireJS") and in the same folder add the amdefine package:
npm install amdefine
This creates the node_modules folder with the amdefine module inside.
I don't use requirejs so I'm not sure what that syntax looks like, but this is what I do to run code both within node and the browser:
For imports, determine if we are running in node or the browser:
var root = typeof exports !== "undefined" && exports !== null ? exports : window;
Then we can grab any dependencies correctly (they will either be available already if in the browser or we use require):
var foo = root.foo;
if (!foo && (typeof require !== 'undefined')) {
foo = require('./foo');
}
var Bar = function() {
// do something with foo
}
And then any functionality that needs to be used by other files, we export it to root:
root.bar = Bar;
As for examples, GitHub is a great source. Just go and check out the code for your favorite library to see how they did it :) I used mocha to test a javascript library that can be used in both the browser and node. The code is available at https://github.com/bunkat/later.
Is it possible to "require" an entire folder using requireJS.
For example, I have a behaviors folder with a ton of behavior js files. I'd really like to be able to simply use require(['behaviors/*'], function() {...}); to load everything in that folder rather than having to keep that list up to date. Once compressed and optimized I'd have all those files lump together, but for development it's easier to work with them individually.
javascript in browser has no filesystem access and so it can't scan a directory for files. If you are building your app in a scripting language like php or ruby you could write a script that scans the directory and adds the file names to the require() call.
I don't know if I can recommend this approach anymore. I think the more explicit way to do this is by manually "requiring"/"exporting" the functionality you need. The exception I think is if you have a "namespace" of files that you want exported see below "Babel and ES6 Module Import Declarations (export-namespace-from) or see below "Babel and ES6 Module Import Declarations.
These solutions also assume that you have a meaningful file structure - where file names become part of that "require" * definition.
However, if you still need to do this there are a few existing tools and methods that might provide the behavior that you're looking for.
Possible Solutions
Babel and ES6 Module Import Declarations (plugin-export-namespace-from)
Have a setup that is ES6 compliant.
You need to update your .babelrc file to include babel-plugin-proposal-export-namespace-from.
Use export namespace plugin by writing syntax like the following:
common/index.js
export * from './common/a'; // export const a = false;
export * from './common/b'; // export const b = true;
main.js
import { a, b } from './common';
console.log(a); // false
console.log(b); // true
Babel and ES6 Module Import Declarations (plugin-wildcard)
Have a setup that is ES6 compliant.
You need to update your .babelrc file to include babel-plugin-wildcard.
Use wildcard namespace plugin by writing syntax like the following:
main.js
import { a, b } from './common/*'; // imports './common/a.js' and './common/b.js'
console.log(a); // false
console.log(b); // true
RequireJS (Now Outdated)
Download and install require-wild npm install require-wild
Configure the declaration as follows
grunt.initConfig({
requireWild: {
app: {
// Input files to look for wildcards (require|define)
src: ["./**/*.js"],
// Output file contains generated namespace modules
dest: "./namespaces.js",
// Load your require config file used to find baseUrl - optional
options: { requireConfigFile: "./main.js" }
}
}
});
grunt.loadNpmTasks("require-wild");
grunt.registerTask('default', ['requireWild']);
Then run the grunt task. Your file will be generated. Modify your setup to load namespaces.js
require(['namespaces'], function () { ... });
This now allows modules under src to use dependencies glob pattern matching.
require(['behaviors/**/*'], function (behaviors) { }
I know this is old, but I'd like to share my solution:
For this solution you need JQuery
1) Create a bash script that will list all the js files in
"MyDirectory/", and save it to "directoryContents.txt":
#!/bin/bash
#Find all the files in that directory...
for file in $( find MyDirectory/ -type f -name "*.js" )
do
fileClean=${file%.js} #Must remove .js from the end!
echo -n "$fileClean " >> MyDirectory/directoryContents.txt
done
File will look like this:
MyDirectory/FirstJavascriptFile MyDirectory/SecondJavascriptFile
MyDirectory/ThirdJavascriptFile
Problem with my script! Puts an extra " " at the end, that messes things up! Make sure to remove the excess space at the end of directoryContents.txt
2) Then in your Client side JS code:
do a "GET" request to retrieve the text file
For each entry (split by the space), 'require' that file:
.
$.get( "MyDirectory/directoryContents.txt", {}, function( data ) {
var allJsFilesInFolder = data.split(" ");
for(var a=0; a<allJsFilesInFolder.length; a++)
{
require([allJsFilesInFolder[a]], function(jsConfig)
{
//Done loading this one file
});
}
}, "text");
I was having a problem with this code not finishing before my other code, so Here's my extended answer:
define([''], function() {
return {
createTestMenu: function()
{
this.loadAllJSFiles(function(){
//Here ALL those files you need are loaded!
});
},
loadAllJSFiles: function(callback)
{
$.get( "MyDirectory/directoryContents.txt", {}, function( data ) {
var allJsFilesInFolder = data.split(" ");
var currentFileNum = 0;
for(var a=0; a<allJsFilesInFolder.length; a++)
{
require([allJsFilesInFolder[a]], function(jsConfig)
{
currentFileNum++;
//If it's the last file that needs to be loaded, run the callback.
if (currentFileNum==allJsFilesInFolder.length)
{
console.log("Done loading all configuration files.");
if (typeof callback != "undefined"){callback();}
}
});
}
}, "text");
}
}
});
What I ended up doing was everytime my Node server boots, it will run the bash script, populating directoryContents.txt. Then My client side just reads directoryContents.txt for the list of files, and requires each in that list.
Hope this helps!
There isn't really a way to do this conceptually on the fly (that I know of).
There's a few work arounds though:
Use grunt and concat and then just require that behemoth...I know, kinda sucky.
What I think is a better solution... use a require hierarchy like so:
require('/js/controllers/init', function(ctrls){
ctrls(app, globals);
});
// /js/controllers/init.js
define('js/controllers/index', 'js/controllers/posts', function(index, posts){
return function protagonist(app, globals){
var indexModule = index(app, globals);
var indexModule = posts(app, globals);
return app || someModule;
};
});
// /js/controllers/index.js
define('js/controllers/index', 'js/controllers/posts', function(index, posts){
return function protagonist(app, globals){
function method1(){}
function method2(){}
return {
m1: method1,
m2: method2
};
};
});
Note that "protagonist" function. That allows you to initialize modules before their use, so now you can pass in a 'sandbox' -- in this case app and globals.
Realistically, you wouldn't have /js/controllers/index.js... It should probably be something like /js/controllers/index/main.js or /js/controllers/index/init.js so that there is a directory adjacent to (sibling of) /js/controllers/init.js called "index". This will make your modules scalable to a given interface -- you can simply swap modules out and keep your interface the same.
Hope this helps! Happy coding!
I wrote a library to solve this problem. Eventually someone else came along and improved my library, here it is:
https://github.com/smartprocure/directory-metagen
You can use my lib with Gulp or whatever - it generates metadata for your project and RequireJS can use that metadata to require the desired files from the filesystem.
Using this lib will produce a RequireJS module that looks something like this:
define(
[
"text!app/templates/dashboardTemplate.ejs",
"text!app/templates/fluxCartTemplate.ejs",
"text!app/templates/footerTemplate.ejs",
"text!app/templates/getAllTemplate.ejs",
"text!app/templates/headerTemplate.ejs",
"text!app/templates/homeTemplate.ejs",
"text!app/templates/indexTemplate.ejs",
"text!app/templates/jobsTemplate.ejs",
"text!app/templates/loginTemplate.ejs",
"text!app/templates/overviewTemplate.ejs",
"text!app/templates/pictureTemplate.ejs",
"text!app/templates/portalTemplate.ejs",
"text!app/templates/registeredUsersTemplate.ejs",
"text!app/templates/userProfileTemplate.ejs"
],
function(){
return {
"templates/dashboardTemplate.ejs": arguments[0],
"templates/fluxCartTemplate.ejs": arguments[1],
"templates/footerTemplate.ejs": arguments[2],
"templates/getAllTemplate.ejs": arguments[3],
"templates/headerTemplate.ejs": arguments[4],
"templates/homeTemplate.ejs": arguments[5],
"templates/indexTemplate.ejs": arguments[6],
"templates/jobsTemplate.ejs": arguments[7],
"templates/loginTemplate.ejs": arguments[8],
"templates/overviewTemplate.ejs": arguments[9],
"templates/pictureTemplate.ejs": arguments[10],
"templates/portalTemplate.ejs": arguments[11],
"templates/registeredUsersTemplate.ejs": arguments[12],
"templates/userProfileTemplate.ejs": arguments[13]
}
});
You can then require modules in your front-end like so:
var footerView = require("app/js/jsx/standardViews/footerView");
however, as you can see this is too verbose, so the magic way is like so:
name the dependency above as allViews!
now you can do:
var allViews = require('allViews');
var footerView = allViews['standardViews/footerView'];
There are two advantages to requiring directories whole:
(1) in production, with the r.js optimizer, you can point to one dependency (module A) and it can then easily trace all of A's dependencies that represent a entire directory
(2) in development, you can require whole directories up front and then use synchronous syntax to require dependencies because you know they have already been loaded
enjoy "RequireJS-Metagen"
https://github.com/smartprocure/directory-metagen
https://www.npmjs.com/package/requirejs-metagen
https://github.com/ORESoftware/requirejs-metagen