JavaScript — Integrating Jasmine with RequireJs (AMD)

How to use RequireJs with Jasmine 2.x

thedotisblack

This article will go through the changes you have to do to migrate your code and the default test runner SpecRunner.html to use RequireJs. We will cover:

  • Changes to the default Jasmine setup
  • RequireJs configuration
  • Changes to our libraries and specs.

Source code available at gsans/jasmine-require-bootstrap (Github).

Follow me on Twitter for latest updates @gerardsans.

RequireJS introduction

RequireJS is a JavaScript file and module loader that implements the Asynchronous module definition (AMD). Mainly it allows you to

  • load resources on demand
  • define dependencies that must load before a module is executed

RequireJS will shine if you are working in large teams or if your dependency tree is complex enough. Besides, you also get other cool features such as: synchronous/asynchronous loading and lazy loading with promises. Once you have done the initial setup you will be able to use intrincate dependencies with ease.

Obviously, if you are already using RequireJS in your application, it also makes sense to use it in your tests.

Jasmine Default Setup

Find the steps to setup Jasmine here. We are going to use this folder structure.

folders setup

Your SpecRunner.html should look similar to this:

This is how my-library.js and my-library.specs.js look like

If you have node installed in your machine you can use http-server to run the SpecRunner.html passing the only spec in our suite.

SpecRunner.html output

RequireJs Setup

In order to use RequireJs we will have to change our previous SpecRunner.html page to the following:

We are telling RequireJS where to find its configuration with the data-main attribute of the script element.

We removed all external scripts files and only left require.js.

Note how we omitted the .js extension for main.js. This is how RequireJs identifies files by default.

RequireJs configuration file — main.js

In main.js we will set the configuration options to load all dependencies and bootstrap Jasmine.

We used jasmine-boot as an alias for boot.js

RequireJs Bootstrap

This setup will start with jasmine-boot identifier. It has two dependencies: jasmine and jasmine-html. As jasmine-html has jasmine as a dependency it will then proceed to load jasmine.js, then jasmine-html.js and finally boot.js as it was doing on our original runner.

We use require() to load dependencies before running our code.

The previous code will load all jasmine-boot dependencies and continue with our specs in my-library.specs.js.

Note that if we had moved my-library.specs to the same level as jasmine-boot it could had been loaded before all jasmine-boot dependencies were done.

Once all script files are loaded we trigger window.onload() as Jasmine hooks into this event to initialise its engine.

Changes to our library

In order to create our library we will wrap it using define. As we don’t have any dependencies it will be empty. Note also how we added a return statement at the end, this is so it can be used on other modules via parameters without polluting the global window object.

We use define() to define our libraries. This can load dependencies and return an instance for others to use.

Changes to our specs

In order to migrate our specs we will repeat the same as we did before. In this case we do have a dependency as we need to load my-library.js in order to run our tests.

The myLibrary parameter will get the instance returned by our library new definition.

We can now run our tests taking advantage of RequireJs helper functions making the testing experience more enjoyable.

Thanks for reading! Have any questions? Ping me on Twitter @gerardsans.

Resources

Angular — Unit Testing with Jasmine