stefan.s
stefan.s

Reputation: 3498

How can I migrate my custom matchers from Jasmine 1 to Jasmine 2

Version 2 of the JavaScript testing framework jasmine unfortunately introduced several breaking changes. One of these changes is the way custom matchers are handled, as is outlined here:

http://jasmine.github.io/2.0/upgrading.html

The addMatchers function is no longer on the spec (this) it is now on the global jasmine object.

 /* was:
     this.addMatchers({
  */
  jasmine.addMatchers({

A matcher is set up a bit different now. The factory receives a util object which contains things like jasmines equality functions, and any registered customEqualityTesters. The factory is expected to return an object with a compare function which will be called with the actual and expected directly, instead of the actual value being on this

   /* was:
       toBeCustom: function(expected) {
         var passed = this.actual == expected;
    */
    toBeCustom: function(util, customEqualityTesters) {
      return {
        compare: function(actual, expected) {
          var passed = actual == expected

The comparison should now return an object with pass and message attributes.

I am looking for an easy way to migrate our existing matchers, so that we can easily switch to the new jasmine version.

Upvotes: 0

Views: 106

Answers (2)

Jamie Mason
Jamie Mason

Reputation: 4196

The add-matchers library lets you write matchers which are compatible with Jasmine v1, Jasmine v2, and Jest.

Upvotes: 0

stefan.s
stefan.s

Reputation: 3498

To ease the transition to the new jasmine version the following special migration object will help.

Instead of adding the matcher on the this object, you add them on the jasmineMigrate object. But this is really all you need to to. The jasmineMigrate object will take care of the rest.

 /* was:
     this.addMatchers({
  */
  jasmineMigrate .addMatchers({

The implementation of the migration object:

var jasmineMigrate = {};

jasmineMigrate.addMatchers = function (matchers) {

    Object.keys(matchers).forEach(function (matcherName) {
        var matcher = matchers[matcherName], 
            migratedMatcher = {};

        migratedMatcher[matcherName] = function (util, customEqualityTesters) {
            return {
                compare: function (actual) {
                    var matcherArguments,
                        thisForMigratedMatcher,
                        matcherResult,
                        passed;

                    //In Jasmine 2 the first parameter of the compare function 
                    //is the actual value.
                    //Whereas with Jasmine 1 the actual value was a property of the matchers this
                    //Therefore modify the given arguments array and remove actual
                    matcherArguments = [].slice.call(arguments)
                    matcherArguments.splice(0, 1);

                    //Add actual to the this object we'll be passing to the matcher
                    thisForMigratedMatcher = {
                        actual: actual
                    };

                    //Now call the original matcher aufgerufen, with the modified
                    //arguments and thisForMigratedMatcher which will be applied to
                    //the matcher
                    passed = matcher.apply(thisForMigratedMatcher, matcherArguments);

                    matcherResult = {
                        pass: passed,
                        message: thisForMigratedMatcher.message
                    };
                    return matcherResult;
                }
            }
        };

        jasmine.addMatchers(migratedMatcher);
    });
}

Upvotes: 0

Related Questions