Question

Today I wanted to do something with chaining in a similar way to Jasmine: http://pivotal.github.io/jasmine/

Jasmine has a very fluid style of writing a test conditional, for example:

expect(result).not.toBe(85);

In my test I just wanted to add an and as some sugar coating that did something like:

createRegion('test').and.append()

So that was pretty simple (I am aware the following won't work in IE8<):

Layout.prototype.__defineGetter__('and', function() {
    return this;
});

But that got me interested in how jasmine is:

  • doing no-bracket chaining when I can't find any instance of defineProperty (IE8<) or __defineGetter__
  • cannot find where it has defined not
  • trying to imagine how the method chained after not is aware of it - I am assuming a variable is set like reverse = true in the not method so the proceeding method knows to reverse it's outcome?

How would you implement such behaviour, or otherwise do you know how jasmine has done it?

Was it helpful?

Solution

I took a look at the source, and this implementation of expect:

jasmine.Spec.prototype.expect = function(actual) {
  var positive = new (this.getMatchersClass_())(this.env, actual, this);
  positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
  return positive;
};

So, the property not is the implementation of the same class, receiving this extra parameter to reverse the output:

jasmine.Matchers = function(env, actual, spec, opt_isNot) {
  this.env = env;
  this.actual = actual;
  this.spec = spec;
  this.isNot = opt_isNot || false; // reverse option set
  this.reportWasCalled_ = false;
};

Finally, in jasmine.Matchers.matcherFn_, it uses it to reverse the result:

if (this.isNot) {
    result = !result;
}

OTHER TIPS

here is one way i came up with to pull it off, but if you had lots of methods, you'll want to use getters instead of duplication:

function expect(ob){
  var resp={};

  function not(fn){return function(){return !fn.apply(resp, arguments)}; }

  resp.toBe=function(val){;
      return val==ob; 
  };


  var n=resp.not=function(){};

  for(var i in resp){
     var v=resp[i];
     if(v.call){ n[i]=not(v); }
  }

  return resp;
}

// try it out on a number:
var x=123;

expect(x).not.toBe(123); // false
expect(x).not.toBe(321); // true
expect(x).toBe(123);     // true

please note this is a highly simplified demo; i don't vouch that it's a great performer, and i don't know how jasmine actually works, but is does what you want given the constraints. i think it's neat, but i still like defineProperty better.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top