Jasmine / Karma / RequireJS Template

VNGRS
VNGRS
Apr 21, 2015 · 4 min read

I was playing around Jasmine for a project, all basic setup and defining tests are easy as mocha and relatively easy compared to qunit. I needed a structure that can load dependencies, write specs with jasmine, run specs in development environment (also found out that I can use different JavaScript engines to run my specs simultaneously), run specs in continuous integration environment.

So I’ve created this template to provide a boilerplate, which needed in my opinion because there are a lot of not working, not documented or simply bad examples out there.

Template is here https://github.com/vngrs/jasmine-requirejs-template

Setting up base project

mkdir test-project && cd test-project npm init npm install karma bower grunt --save-dev

Then karma will create our base jasmine — karma setup.

./node_modules/karma/bin/karma init

PhantomJS (Choose only PhantomJS *(headless browser with JavaScriptCore, Ecma 5.1) if you’re planning to prepare this setup for continous integration environment)*

src/\*.js (you may use 'src/\*\*/\*.js' to recursively match files) spec/*.spec.js

no (again for CI purposes)

./node_modules/bower/bin/bower init # default answers should do.

And bower install our assets.

./node_modules/bower/bin/bower install requirejs jquery mustache --save

Note the -save argument. This will make bower to write installed modules to bower.json also.

Providing An Entry point

<pre class="wp-block-preformatted"><!-- /index.html -->
<html>
<head>
<title>jasmine-requirejs-template</title>
<script data-main="src/app.config.js" src="bower_components/requirejs/require.js"></script>
</head>
.
.
.
</pre>

Notice the data-main attribute, requirejs is going to read this attribute and load specified file after loading itself.

Requirejs Bootup File

I’m going to use a separate file to configure requirejs and load it with nested require functions.

// src/app.config.js

// Using a common setup file for specs and sources
(function(){
require(['src/requirejs.config'], function(){
require(['moduleA'],function(a){
a.execute_a_cool_function();
});
});
})();
// src/requirejs.config.js

// This is a common config file for all our requirejs setups, we're going to
// use same file while running our specs in browser or in karma.
require.config({
paths: {
// assets installed with bower
jquery: 'bower_components/jquery/dist/jquery',
Mustache: 'bower_components/mustache/mustache',
// our modules
moduleA: 'src/moduleA',
moduleB: 'src/moduleB'
},
shim: {
Mustache: { exports: 'Mustache' }
}
});

Important variables in requirejs config baseUrl

This is for loader paths, you may either use blank or define as src/ and move everything under src folder.

paths

If you’re defining paths for modules, this is the place. Defining jquery for example;

'jquery': 'bower_components/jquery/dist/jquery'

shim

shim: Configure the dependencies, exports, and custom initialization for older, traditional “browser globals” scripts that do not use define() to declare the dependencies and set a module value.

For example, to use Mustache properly;

{
paths: {
'Mustache': 'bower_components/mustache/mustache',
},
shim: {
'Mustache': { exports: 'Mustache' }
}
}

Defining Modules and Dependencies

// src/moduleA.js
define(['dependency1','dependency2','etc..'], function(dep1, dep2){
});
// src/moduleB.js

define(['moduleA'], function(a){
function do_something(){}
function do_something_else(){}

// It's impossible to run specs on private methods, so you need to
// change your interface and export your private methods. But it's
// possible to remove these unwanted lines with grunt tasks while
// generating production ready assets.

return {
do_something: do_something,
do_something_else: do_something_else
}
});

Running local development server

./node_modules/grunt-cli/bin/grunt

Sample Spec Definition

This html file will load jasmine libraries and load our specs with requirejs.

<pre class="wp-block-preformatted"><!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="bower_components/jasmine/lib/jasmine-core/jasmine.css">
<script type="text/javascript" src="bower_components/jasmine/lib/jasmine-core/jasmine.js"></script>
<script type="text/javascript" src="bower_components/jasmine/lib/jasmine-core/jasmine-html.js"></script>
<script type="text/javascript" src="bower_components/jasmine/lib/jasmine-core/boot.js"></script>
<!-- notice data-main attribute, specs/main is another requirejs boot file -->
<script type="text/javascript" data-main="specs/main" src="bower_components/requirejs/require.js"></script>
</head>
<body>
</body>
</html>
</pre>

We will use same nested require approach to use existing requirejs config

// specs/main.js

(function () {
"use strict";

require.config({ baseUrl: '' });
// using same config file
require(['../src/requirejs.config'], function (){
require(["specs/moduleA.spec"], function () {
window.onload(); // Sadly this is a necessary trick to run jasmine specs.
});
});
})();

http://localhost:3000/run_specs.html opening this url in browser will give you test results.

Running Specs in CI

// /test-main.js(function () {
"use strict";
require(['/base/src/requirejs.config.js'],function(){
require.config({ baseUrl: '/base' });
var allTestFiles = [];
Object.keys(window.__karma__.files).forEach(function(file) {
if (file.match(/(.+)\.spec\.js$/)) {
allTestFiles.push(file);
}
});
require(allTestFiles, window.__karma__.start);
});
})();
# This will start and run your tests once, useful in CI environments
./node_modules/karma/bin/karma start
# This will start karma server and browsers
./node_modules/karma/bin/karma start --no-single-run &
# This will run your tests
./node_modules/karma/bin/karma run

Rıfat Çağrı Ekin

Originally published on April 21, 2015.

VNGRS

Globally Providing Digital Solutions Around Software Products

VNGRS

VNGRS provides digital solutions around software products to organizations in an ever-changing and unforeseeable environment while enabling them to figure out undiscovered digitalization needs, giving them a tailor-made digital solution that would boost their business.

VNGRS

Written by

VNGRS

Cloud Native Software Solutions

VNGRS

VNGRS provides digital solutions around software products to organizations in an ever-changing and unforeseeable environment while enabling them to figure out undiscovered digitalization needs, giving them a tailor-made digital solution that would boost their business.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store