When that happens you need to update your RequireJS configuration to wrap the code in a shim or you need to update the code. In our experience, you typically update code you own, but shim code you don't. This can lead to some decent-sized RequireJS configurations. And it's the configuration that is central to the aforementioned thwarted nature of this post.
More work than necessary
Much to our dismay getting the first Jasmine spec was a whole lot more work than we expected. We either needed to embrace RequireJS in our tests or be good with the decision to avoid it entirely. It seemed appropriate to embrace RequireJS.
We looked into incorporating RequireJS with Jasmine and found that the suggestions for integrating the two left us a bit wanting. Here are the three top suggestions we encountered:
- Copy your RequireJS configuration into your spec/ directory and change what you need for your test environment
- Copy your RequireJS configuration into your Gruntfile and change what you need for your test environment
- Update your RequireJS configuration to include a lot of conditional statements to do one thing if you were running in a test environment and another thing for running the app for real
None of these solutions are very good. The reason they aren't good is that they require you to expend a lot of effort managing unnecessary duplication and/or configuration complexity over time. We wanted to use the majority of the RequireJS configuration from within our app and only change the parts that needed to be changed.
During our earlier search for incorporating Jasmine and RequireJS we had found the grunt-template-jasmine-requirejs project. It supported the three solutions mentioned a few paragraphs above, but that was it.
We asked ourselves the question "What if we could merge full or partial RequireJS configurations together?"
After some investigation into how Grunt and
grunt-template-jasmine-requirejs worked we decided to fork and patch the project, get our changes working, and then submit a pull request back to the project.
Here's how our changes work. First, the traditional
In the above
jasmine grunt task
requireConfigFile points at
src/main.js. When you run
grunt jasmine it will generate a
SpecRunner.html that pulls in the configuration from
Now, let's say you wanted to override the
foo shim for your test. Maybe you want to provide a fake "Foo" module throughout your tests instead of using the real thing. Maybe it's an interface to a third party library that you don't actually want to use in your tests.
Here's the updated grunt task showing how you can do that with an inline
This specifies both
requireConfig. This works by loading
requireConfigFile first and then merging any
requireConfig directive onto it.
This also works in the case where you don't want to inline your RequireJS configuration in your grunt task:
In this third and final example you see that
requireConfigFile specifies an array of files. It will load the left-most file first,
src/main.js, and then merge onto it any files that come after that in left to right order (
We did submit a pull request and it indeed was incorporated back into
grunt-template-jasmine-requirejs. You can use this functionality in versions 0.1.3 and above.
If you're a RequireJS and Jasmine user you should definitely check this out grunt-template-jasmine-requirejs and say goodbye to copy and pasting your RequireJS configurations.