2

After learning about the differences between the comparison operators === and == in Javascript I was pretty surprised that Jasmines equality concept does not correspond to either one. For example all statements in the following test suite are true:

describe('Jasmine asserted equality of objects', function() {

    it('is different from ===- and ==-equality', function() {
        var x = {};
        var y = {};

        expect(x === y).toBeFalsy();
        expect(x == y).toBeFalsy();
        expect(x).toEqual(y);
    });

    it('seems to imply element-wise equality', function() {
        var x = {'name': 'value'};
        var y1 = {'name': 'values'};
        var y2 = {'names': 'value'};
        var y3 = {'name': 'value'};

        expect(x).not.toEqual(y1);
        expect(x).not.toEqual(y2);
        expect(x).toEqual(y3);
    });

    it('does not imply equality of the respective prototypes', function() {
        var x = {};
        var y = Object.create(x);
        var pr = Object.getPrototypeOf;

        expect(x).toEqual(y);
        expect(pr(pr(x))).not.toEqual(pr(pr(y)));
    });

});

Unfortunately, I was not able to find any official API documentation for Jasmine. The well known introduction page only provides examples, and most other sources I found either discuss the difference of === and == or Jasmines concept of custom matchers.

However, my main question is the following: How is Jasmines function toEqual specified? In addition I'd be interested in the reasoning for introducing this new concept of equality: Why or in which cases is expect(x).toEqual(y) better suited than x === y (or x == y)?

Community
  • 1
  • 1
kremerd
  • 1,496
  • 15
  • 24

1 Answers1

2

The DSL jasmine has this concept of equality because equality in javascript can be confusing and in tests readabilty is important. It seems that when designing jasmine they decided to adopt the underscore.js concept of equality.

To answer how is jasmines toEqual specified you can see in the source on github.

getJasmineRequireObj().toEqual = function() {

  function toEqual(util, customEqualityTesters) {
    customEqualityTesters = customEqualityTesters || [];

    return {
      compare: function(actual, expected) {
        var result = {
          pass: false
        };

        result.pass = util.equals(actual, expected, customEqualityTesters);

        return result;
      }
    };
  }

  return toEqual;
};

As we can see above it using util.equals() which in turn comes from the matchersUtil function which internally uses the eq function.

    getJasmineRequireObj().matchersUtil = function(j$) {
      // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter?

      return {
        equals: function(a, b, customTesters) {
          customTesters = customTesters || [];

          return eq(a, b, [], [], customTesters);
        },
    ...
      // Equality function lovingly adapted from isEqual in
      //   [Underscore](http://underscorejs.org)
      function eq(a, b, aStack, bStack, customTesters) {
        var result = true;
      ...
     }
 };
Nicholas Murray
  • 13,305
  • 14
  • 65
  • 84
  • Thanks for referencing the sources! However sources are naturally subject to change and with more than 100 lines of code the `eq` function is not particularly descriptive. Isn't there something like the [Javascript spec for `==`](http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3) for Jasmines `toEqual()` - or maybe for a related function like Underscores `isEqual()`? – kremerd Apr 15 '15 at 20:17
  • Not that I know of, there are probably not enough resources in a relatively smaller open source project to produce comprehensive documentation that an international organisation like ECMA can produce, so the source can also be drawn on as the documentation. – Nicholas Murray Apr 15 '15 at 21:28