37

There are plenty of documents that show how to add a matcher to a Jasmine spec (here, for example).

Has anyone found a way to add matchers to the whole environment; I'm wanting to create a set of useful matchers to be called by any and all tests, without copypasta all over my specs.

Currently working to reverse engineer the source, but would prefer a tried and true method, if one exists.

Jesper Rønn-Jensen
  • 106,591
  • 44
  • 118
  • 155
Dancrumb
  • 26,597
  • 10
  • 74
  • 130

4 Answers4

48

Sure, you just call beforeEach() without any spec scoping at all, and add matchers there.

This would globally add a toBeOfType matcher.

beforeEach(function() {
  var matchers = {
    toBeOfType: function(typeString) {
      return typeof this.actual == typeString;
    }
  };

  this.addMatchers(matchers);
});

describe('Thing', function() {
  // matchers available here.
});

I've made a file named spec_helper.js full of things like custom matchers that I just need to load onto the page before I run the rest of the spec suite.

Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
  • 1
    I also found a nice example here: http://tobyho.com/2012/01/30/write-a-jasmine-matcher/ – Dancrumb Aug 13 '12 at 21:13
  • I tried link shared by Dancrumb, ideally its neat and clean approach however it didn't work so I adopted Alex approach. – joy May 07 '14 at 15:42
  • 2
    Here's one for jasmine 2.0+ ````javascript beforeEach(function(){ jasmine.addMatchers({ toEqualData: function() { return { compare: function(actual, expected) { return { pass: angular.equals(actual, expected) } } } } }); }); ```` – mikker Dec 04 '14 at 11:56
  • 1
    @mikker You should edit the answer or post your own rather than leaving that in a comment. http://stackoverflow.com/help/editing – Lexi Apr 22 '15 at 16:44
  • @Dancrumb, there is a problem with defining matcher like that. It adds to `jasmine.Matchers.prototype` well, but it doesn't actually assert statements. I mean following: `expect(false).toBeTruthyCustom()` will execute, but it will not produce a failure. – 18augst Aug 11 '15 at 13:16
14

Here's one for jasmine 2.0+:

beforeEach(function(){
  jasmine.addMatchers({
    toEqualData: function() {
      return {
        compare: function(actual, expected) {
          return { pass: angular.equals(actual, expected) };
        }
      };
    }
  });
});

Note that this uses angular's angular.equals.

mikker
  • 811
  • 7
  • 20
0

Edit: I didn't know it was an internal implementation that may be subjected to change. Use at your own risk.

jasmine.Expectation.addCoreMatchers(matchers)
0

Based on previous answers, I created the following setup for angular-cli. I also need an external module in my matcher (in this case moment.js)

Note In this example I added an equalityTester, but it should work with a customer matcher

Create a file src/spec_helper.ts with the following contents:

// Import module
import { Moment } from 'moment';

export function initSpecHelper() {

  beforeEach(() => {
    // Add your matcher
    jasmine.addCustomEqualityTester((a: Moment, b: Moment) => {
      if (typeof a.isSame === 'function') {
        return a.isSame(b);
      }
    });
  });

}

Then, in src/test.ts import the initSpecHelper() function add execute it. I placed it before Angular's TestBed init, wich seems to work just fine.

import { initSpecHelper } from './spec_helper';

//...

// Prevent Karma from running prematurely.
__karma__.loaded = function () {};

// Init our own spec helper
initSpecHelper();

// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting()
);

//...
Treur
  • 763
  • 4
  • 13