Migrating from Jasmine 1.3 to Jasmine 2.0

Migrating from Jasmine 1.3 to Jasmine 2.0

If you just started a new JavaScript project with Jasmine, you likely started using Jasmine 2. But if you’re working on an existing project, it’s highly possible you’re using Jasmine 1.3 and maybe want, like me, migrate to Jasmine 2. Here are a few tips how to do it.

Spies
The way spies are used has slightly changed in Jasmine 2.

JavaScript

1

2

3

4

5

6

7

spyOn(foo,'bar').andReturn(0);

spyOn(foo,'bar').andThrow('Oops');

foo.bar(true);

expect(foo.bar.callCount).toEqual(1);

expect(foo.bar.calls[0].args).toEqual([true]);

expect(foo.bar.mostRecentCall.args.length).toBe(1);

becomes:

JavaScript

1

2

3

4

5

6

7

spyOn(foo,'bar').and.returnValue(0);

spyOn(foo,'bar').and.throwError('Oops');

foo.bar(true);

expect(foo.bar.calls.count()).toEqual(1);

expect(foo.bar.calls.argsFor(0)).toEqual([true]);

expect(foo.bar.calls.mostRecent().args.length).toBe(1);

Async tests
In Jasmine 1.3, if you wanted to test methods that are asynchronous, you had to use a lach coupled with waitFor and runs. Otherwise your test wouldn’t wait for the async call to return and could break into another test, with no direct relation. You could for example have something like this:

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

it('my test',function(){

vardone=false;

// async test

runs(function(){

asyncStuff.done(function(success){

expect(success).toEqual('yes');

}).fail(function(err){

expect(err).toEqual('no');

}).always(function(){

// this will make the test end

done=true;

});

});

waitsFor(function(){

done=true;

});

});

Jasmine 2.0 opted for a new async syntax that is similar to Mocha, and much easier to use than the older method. You don’t have to add to call any runs() or waitFor() functions. The only thing you have to do is to use the extra done parameter that is now available to beforeEach(), it() and afterEach(). The above code could be written like this:

JavaScript

1

2

3

4

5

6

7

it('my test',function(done){

asyncStuff.done(function(success){

expect(success).toEqual('yes');

}).fail(function(err){

expect(err).toEqual('no');

}).always(done);

});

As you can see it’s way more simple and straightforward. Note that test will fail if done method isn’t called before jasmine.getEnv().defaultTimeoutInterval.

new Clock

JavaScript

1

2

3

4

5

6

7

8

beforeEach(function(){

jasmine.Clock.useMock();

});

it('mock test',function(){

jasmine.Clock.tick(1);

// ...

});

becomes:

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

beforeEach(function(){

jasmine.clock().install();

});

afterEach(function(){

jasmine.clock().uninstall();

});

it('mock test',function(){

jasmine.clock().tick(1);

// ...

});

using karma-jasmine-html-reporter with AngularJS
If you are using Jasmine with AngularJS to test directives, you may have an helper file that gets loaded by Karma with the following code:

JavaScript

1

2

3

beforeEach(function(){

angular.element(document.body).empty().removeData();

});

The problem is that this will empty the whole body of your page before running each test, and as a result it breaks the jasmine-html reporter. In order to fix this you may change the above line to something like:

JavaScript

1

2

3

4

5

6

7

8

9

beforeEach(function(){

angular.element('body > [class!="html-reporter"]').each(function(){

if(this.tagName!=='LINK'){

angular.element(this).remove();

}

});

angular.element(document.body).removeData();

});

This isn’t optimized at all, but at least it doesn’t break the plugin anymore.

I think that the new async stuff is enough to migrate to Jasmine 2 if you are still using Jasmine 1.3. And as you can see, migrating isn’t that complicated so there’s no reason to stick with an outdated Jasmine 1.3.