diff --git a/spec/core/ExpectationFilterChainSpec.js b/spec/core/ExpectationFilterChainSpec.js index 8c91dd5a..81b3cfc4 100644 --- a/spec/core/ExpectationFilterChainSpec.js +++ b/spec/core/ExpectationFilterChainSpec.js @@ -1,4 +1,32 @@ -describe('ExpectationFilterChainSpec', function() { +describe('ExpectationFilterChain', function() { + describe('#addFilter', function() { + it('returns a new filter chain with the added filter', function() { + var first = jasmine.createSpy('first'), + second = jasmine.createSpy('second'), + orig = new jasmineUnderTest.ExpectationFilterChain({ + modifyFailureMessage: first + }), + added = orig.addFilter({selectComparisonFunc: second}); + + added.modifyFailureMessage(); + expect(first).toHaveBeenCalled(); + debugger; + added.selectComparisonFunc(); + expect(second).toHaveBeenCalled(); + }); + + it('does not modify the original filter chain', function() { + var orig = new jasmineUnderTest.ExpectationFilterChain({}), + f = jasmine.createSpy('f'); + + + orig.addFilter({selectComparisonFunc: f}); + + orig.selectComparisonFunc(); + expect(f).not.toHaveBeenCalled(); + }); + }); + describe('#selectComparisonFunc', function() { describe('When no filters have #selectComparisonFunc', function() { it('returns undefined', function() { @@ -10,14 +38,14 @@ describe('ExpectationFilterChainSpec', function() { describe('When some filters have #selectComparisonFunc', function() { it('calls the first filter that has #selectComparisonFunc', function() { - var chain = new jasmineUnderTest.ExpectationFilterChain(), - first = jasmine.createSpy('first').and.returnValue('first'), + var first = jasmine.createSpy('first').and.returnValue('first'), second = jasmine.createSpy('second').and.returnValue('second'), + chain = new jasmineUnderTest.ExpectationFilterChain() + .addFilter({selectComparisonFunc: first}) + .addFilter({selectComparisonFunc: second}), matcher = {}, result; - chain.addFilter({selectComparisonFunc: first}); - chain.addFilter({selectComparisonFunc: second}); result = chain.selectComparisonFunc(matcher); expect(first).toHaveBeenCalledWith(matcher); @@ -38,17 +66,17 @@ describe('ExpectationFilterChainSpec', function() { describe('When some filters have #buildFailureMessage', function() { it('calls the first filter that has #buildFailureMessage', function() { - var chain = new jasmineUnderTest.ExpectationFilterChain(), - first = jasmine.createSpy('first').and.returnValue('first'), + var first = jasmine.createSpy('first').and.returnValue('first'), second = jasmine.createSpy('second').and.returnValue('second'), + chain = new jasmineUnderTest.ExpectationFilterChain() + .addFilter({buildFailureMessage: first}) + .addFilter({buildFailureMessage: second}), matcherResult = {pass: false}, matcherName = 'foo', args = [], util = {}, result; - chain.addFilter({buildFailureMessage: first}); - chain.addFilter({buildFailureMessage: second}); result = chain.buildFailureMessage(matcherResult, matcherName, args, util); expect(first).toHaveBeenCalledWith(matcherResult, matcherName, args, util); @@ -60,19 +88,20 @@ describe('ExpectationFilterChainSpec', function() { describe('#modifyFailureMessage', function() { it('calls each filter with the return value of the next previously added filter', function() { - var chain = new jasmineUnderTest.ExpectationFilterChain(), - first = jasmine.createSpy('first').and.returnValue('first'), + var first = jasmine.createSpy('first').and.returnValue('first'), third = jasmine.createSpy('third').and.returnValue('third'), + chain = new jasmineUnderTest.ExpectationFilterChain() + .addFilter({modifyFailureMessage: first}) + .addFilter({}) + .addFilter({modifyFailureMessage: third}), result; - chain.addFilter({modifyFailureMessage: first}); - chain.addFilter({}) - chain.addFilter({modifyFailureMessage: third}); + debugger; result = chain.modifyFailureMessage('original'); - expect(third).toHaveBeenCalledWith('original'); - expect(first).toHaveBeenCalledWith('third'); - expect(result).toEqual('first'); + expect(first).toHaveBeenCalledWith('original'); + expect(third).toHaveBeenCalledWith('first'); + expect(result).toEqual('third'); }); }); }); diff --git a/src/core/ExpectationFilterChain.js b/src/core/ExpectationFilterChain.js index 3577ab4c..99cab978 100644 --- a/src/core/ExpectationFilterChain.js +++ b/src/core/ExpectationFilterChain.js @@ -1,42 +1,52 @@ getJasmineRequireObj().ExpectationFilterChain = function() { - function ExpectationFilterChain() { - this.filters_ = []; + function ExpectationFilterChain(maybeFilter, prev) { + this.filter_ = maybeFilter; + this.prev_ = prev; } ExpectationFilterChain.prototype.addFilter = function(filter) { - this.filters_.push(filter); + return new ExpectationFilterChain(filter, this); }; ExpectationFilterChain.prototype.selectComparisonFunc = function(matcher) { - return this.callFirst_('selectComparisonFunc', arguments); + return this.callFirst_('selectComparisonFunc', arguments).result; }; ExpectationFilterChain.prototype.buildFailureMessage = function(result, matcherName, args, util) { - return this.callFirst_('buildFailureMessage', arguments); + return this.callFirst_('buildFailureMessage', arguments).result; }; ExpectationFilterChain.prototype.modifyFailureMessage = function(msg) { - var i; + if (this.prev_) { + msg = this.prev_.modifyFailureMessage(msg); + } - for (i = this.filters_.length - 1; i >= 0; i--) { - if (this.filters_[i].modifyFailureMessage) { - msg = this.filters_[i].modifyFailureMessage(msg); - } + if (this.filter_ && this.filter_.modifyFailureMessage) { + msg = this.filter_.modifyFailureMessage(msg); } return msg; }; ExpectationFilterChain.prototype.callFirst_ = function(fname, args) { - var i, filter; + var prevResult; - for (i = 0; i < this.filters_.length; i++) { - filter = this.filters_[i]; + if (this.prev_) { + prevResult = this.prev_.callFirst_(fname, args); - if (filter[fname]) { - return filter[fname].apply(filter, args); + if (prevResult.found) { + return prevResult; } } + + if (this.filter_ && this.filter_[fname]) { + return { + found: true, + result: this.filter_[fname].apply(this.filter_, args) + }; + } + + return {found: false}; }; return ExpectationFilterChain;