What's a good way to reuse test code using Jasmine?
Here is an article by a guy at Pivotal Labs that goes into detail about how to wrap a describe call:
DRYing up Jasmine Specs with Shared Behavior
Snippet from the article that shows part of the wrapper function:
function sharedBehaviorForGameOf(context) {
describe("(shared)", function() {
var ball, game;
beforeEach(function() {
ball = context.ball;
game = context.game;
});
});
}
I'm not sure how @starmer's solution works. As I mentioned in the comment, when I use his code, context
is always undefined.
Instead what you have to do (as mentioned by @moefinley) is to pass in a reference to a constructor function instead. I've written a blog post that outlines this approach using an example. Here's the essence of it:
describe('service interface', function(){
function createInstance(){
return /* code to create a new service or pass in an existing reference */
}
executeSharedTests(createInstance);
});
function executeSharedTests(createInstanceFn){
describe('when adding a new menu entry', function(){
var subjectUnderTest;
beforeEach(function(){
//create an instance by invoking the constructor function
subjectUnderTest = createInstanceFn();
});
it('should allow to add new menu entries', function(){
/* assertion code here, verifying subjectUnderTest works properly */
});
});
}
There's a nice article on thoughbot's website: https://robots.thoughtbot.com/jasmine-and-shared-examples
Here's a brief sample:
appNamespace.jasmine.sharedExamples = {
"rectangle": function() {
it("has four sides", function() {
expect(this.subject.sides).toEqual(4);
});
},
};
And with some underscore functions to define itShouldBehaveLike
window.itShouldBehaveLike = function() {
var exampleName = _.first(arguments),
exampleArguments = _.select(_.rest(arguments), function(arg) { return !_.isFunction(arg); }),
innerBlock = _.detect(arguments, function(arg) { return _.isFunction(arg); }),
exampleGroup = appNamespace.jasmine.sharedExamples[exampleName];
if(exampleGroup) {
return describe(exampleName, function() {
exampleGroup.apply(this, exampleArguments);
if(innerBlock) { innerBlock(); }
});
} else {
return it("cannot find shared behavior: '" + exampleName + "'", function() {
expect(false).toEqual(true);
});
}
};