|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function givenAnOboeInstance(jsonFileName) { |
|
|
|
function OboeAsserter() { |
|
|
|
var asserter = this, |
|
oboeInstance, |
|
|
|
expectingErrors = false, |
|
|
|
givenErrors = [], |
|
|
|
completeJson, |
|
|
|
spiedCallback; |
|
|
|
|
|
jsonFileName = jsonFileName || 'invalid://xhr_should_be_stubbed.org/if/not/thats/bad'; |
|
|
|
function requestComplete(completeJsonFromJsonCompleteCall){ |
|
completeJson = completeJsonFromJsonCompleteCall; |
|
|
|
asserter.isComplete = true; |
|
} |
|
|
|
oboeInstance = oboe( jsonFileName |
|
).done(requestComplete); |
|
|
|
oboeInstance.fail(function(e) { |
|
|
|
|
|
expect(expectingErrors).toBeTruthy(); |
|
}); |
|
|
|
|
|
|
|
this.toComplete = function() { |
|
return function() { |
|
return asserter.isComplete; |
|
} |
|
} |
|
|
|
this.andWeAreListeningForNodes = function(pattern, callback, scope) { |
|
spiedCallback = callback ? sinon.spy(callback) : sinon.stub(); |
|
|
|
oboeInstance.node(pattern, argumentClone(spiedCallback), scope); |
|
return this; |
|
}; |
|
|
|
this.andWeAreListeningForPaths = function(pattern, callback, scope) { |
|
spiedCallback = callback ? sinon.spy(callback) : sinon.stub(); |
|
|
|
oboeInstance.path(pattern, argumentClone(spiedCallback), scope); |
|
return this; |
|
}; |
|
|
|
this.andWeHaveAFaultyCallbackListeningFor = function(pattern) { |
|
spiedCallback = sinon.stub().throws(); |
|
|
|
oboeInstance.path(pattern, argumentClone(spiedCallback)); |
|
return this; |
|
}; |
|
|
|
this.andWeAreExpectingSomeErrors = function() { |
|
expectingErrors = true; |
|
|
|
spiedCallback = sinon.stub(); |
|
|
|
oboeInstance.fail(argumentClone(spiedCallback)); |
|
return this; |
|
}; |
|
|
|
this.andWeAbortTheRequest = function() { |
|
oboeInstance.abort(); |
|
return this; |
|
}; |
|
|
|
this.whenGivenInput = function(json) { |
|
if( typeof json != 'string' ) { |
|
json = JSON.stringify(json); |
|
} |
|
|
|
|
|
|
|
for( var i = 0; i< json.length; i++) { |
|
oboeInstance.emit(STREAM_DATA, json.charAt(i) ); |
|
} |
|
|
|
return this; |
|
}; |
|
|
|
this.whenInputFinishes = function() { |
|
|
|
oboeInstance.emit(STREAM_END); |
|
|
|
return this; |
|
}; |
|
|
|
function noop(){} |
|
|
|
|
|
|
|
|
|
this.thenTheInstance = function( ){ |
|
|
|
if( givenErrors.length > 0 ) { |
|
throw new Error('error found during previous stages\n' + givenErrors[0].stack); |
|
} |
|
|
|
for (var i = 0; i < arguments.length; i++) { |
|
var assertion = arguments[i]; |
|
assertion.testAgainst(spiedCallback, oboeInstance, completeJson); |
|
} |
|
|
|
return this; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function argumentClone(delegateCallback) { |
|
return function(){ |
|
|
|
function clone(original){ |
|
|
|
|
|
|
|
|
|
|
|
return window.eval( '(' + JSON.stringify( original ) + ')' ); |
|
} |
|
function toArray(args) { |
|
return Array.prototype.slice.call(args); |
|
} |
|
|
|
var cloneArguments = toArray(arguments).map(clone); |
|
|
|
delegateCallback.apply( this, cloneArguments ); |
|
}; |
|
} |
|
} |
|
return new OboeAsserter(); |
|
} |
|
|
|
|
|
var wasPassedAnErrorObject = { |
|
testAgainst: function failIfNotPassedAnError(callback, oboeInstance) { |
|
|
|
if( !callback.args[0][0] instanceof Error ) { |
|
throw new Error("Callback should have been given an error but was given" + callback.constructor.name); |
|
} |
|
|
|
} |
|
}; |
|
|
|
|
|
|
|
|
|
function foundNMatches(n){ |
|
return { |
|
testAgainst: |
|
function(callback, oboeInstance) { |
|
if( n != callback.callCount ) { |
|
throw new Error('expected to have been called ' + n + ' times but has been called ' + |
|
callback.callCount + ' times. \n' + |
|
"all calls were with:" + |
|
reportArgumentsToCallback(callback.args) |
|
) |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
function hasRootJson(expected){ |
|
return { |
|
testAgainst: |
|
function(callback, oboeInstance) { |
|
|
|
expect(oboeInstance.root()).toEqual(expected); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
function gaveFinalCallbackWithRootJson(expected) { |
|
return { |
|
testAgainst: |
|
function(callback, oboeInstance, completeJson) { |
|
expect(completeJson).toEqual(expected); |
|
} |
|
} |
|
} |
|
|
|
var foundOneMatch = foundNMatches(1), |
|
calledCallbackOnce = foundNMatches(1), |
|
foundNoMatches = foundNMatches(0); |
|
|
|
function wasCalledbackWithContext(callbackScope) { |
|
return { |
|
testAgainst: |
|
function(callbackStub, oboeInstance) { |
|
if(!callbackStub.calledOn(callbackScope)){ |
|
|
|
if( !callbackStub.called ) { |
|
throw new Error('Expected to be called with context ' + callbackScope + ' but has not been called at all'); |
|
} |
|
|
|
throw new Error('was not called in the expected context. Expected ' + callbackScope + ' but got ' + |
|
callbackStub.getCall(0).thisValue); |
|
} |
|
} |
|
}; |
|
} |
|
|
|
function wasGivenTheOboeAsContext() { |
|
return { |
|
testAgainst: |
|
function(callbackStub, oboeInstance) { |
|
return wasCalledbackWithContext(oboeInstance).testAgainst(callbackStub, oboeInstance); |
|
} |
|
}; |
|
} |
|
|
|
function lastOf(array){ |
|
return array[array.length-1]; |
|
} |
|
function penultimateOf(array){ |
|
return array[array.length-2]; |
|
} |
|
function prepenultimateOf(array){ |
|
return array[array.length-3]; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function reportArgumentsToCallback(callbackArgs) { |
|
|
|
return "\n" + callbackArgs.map( function( args, i ){ |
|
|
|
var ancestors = args[2]; |
|
|
|
return "Call number " + i + " was: \n" + |
|
"\tnode: " + JSON.stringify( args[0] ) + "\n" + |
|
"\tpath: " + JSON.stringify( args[1] ) + "\n" + |
|
"\tparent: " + JSON.stringify( lastOf(ancestors) ) + "\n" + |
|
"\tgrandparent: " + JSON.stringify( penultimateOf(ancestors) ) + "\n" + |
|
"\tancestors: " + JSON.stringify( ancestors ); |
|
|
|
}).join("\n\n"); |
|
|
|
} |
|
|
|
|
|
function matched(obj) { |
|
|
|
return { |
|
testAgainst: function assertMatchedRightObject( callbackStub ) { |
|
|
|
if(!callbackStub.calledWith(obj)) { |
|
|
|
var objectPassedToCall = function(callArgs){return callArgs[0]}; |
|
|
|
throw new Error( "was not called with the object " + JSON.stringify(obj) + "\n" + |
|
"objects that I got are:" + |
|
JSON.stringify(callbackStub.args.map(objectPassedToCall) ) + "\n" + |
|
"all calls were with:" + |
|
reportArgumentsToCallback(callbackStub.args)); |
|
|
|
} |
|
} |
|
|
|
, atPath: function assertAtRightPath(path) { |
|
var oldAssertion = this.testAgainst; |
|
|
|
this.testAgainst = function( callbackStub ){ |
|
oldAssertion.apply(this, arguments); |
|
|
|
if(!callbackStub.calledWithMatch(sinon.match.any, path)) { |
|
throw new Error( "was not called with the path " + JSON.stringify(path) + "\n" + |
|
"paths that I have are:\n" + |
|
callbackStub.args.map(function(callArgs){ |
|
return "\t" + JSON.stringify(callArgs[1]) + "\n"; |
|
}) + "\n" + |
|
"all calls were with:" + |
|
reportArgumentsToCallback(callbackStub.args)); |
|
} |
|
}; |
|
|
|
return this; |
|
} |
|
|
|
, withParent: function( expectedParent ) { |
|
var oldAssertion = this.testAgainst; |
|
|
|
this.testAgainst = function( callbackStub ){ |
|
oldAssertion.apply(this, arguments); |
|
|
|
var parentMatcher = sinon.match(function (array) { |
|
|
|
var foundParent = penultimateOf(array); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return JSON.stringify(foundParent) == JSON.stringify(expectedParent) |
|
|
|
}, "had the right parent"); |
|
|
|
if(!callbackStub.calledWithMatch(obj, sinon.match.any, parentMatcher)) { |
|
throw new Error( "was not called with the object" + JSON.stringify(obj) + |
|
" and parent object " + JSON.stringify(expectedParent) + |
|
"all calls were with:" + |
|
reportArgumentsToCallback(callbackStub.args)); |
|
} |
|
}; |
|
|
|
return this; |
|
} |
|
|
|
, withGrandparent: function( expectedGrandparent ) { |
|
var oldAssertion = this.testAgainst; |
|
|
|
this.testAgainst = function( callbackStub ){ |
|
oldAssertion.apply(this, arguments); |
|
|
|
var grandparentMatcher = sinon.match(function (array) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var foundGrandparent = prepenultimateOf(array); |
|
|
|
return JSON.stringify(foundGrandparent) == JSON.stringify(expectedGrandparent); |
|
|
|
}, "had the right grandparent"); |
|
|
|
if(!callbackStub.calledWithMatch(obj, sinon.match.any, grandparentMatcher)) { |
|
throw new Error( "was not called with the object" + JSON.stringify(obj) + |
|
" and garndparent object " + JSON.stringify(expectedGrandparent) + |
|
"all calls were with:" + |
|
reportArgumentsToCallback(callbackStub.args)); |
|
} |
|
}; |
|
|
|
return this; |
|
} |
|
|
|
, atRootOfJson: function assertAtRootOfJson() { |
|
this.atPath([]); |
|
return this; |
|
} |
|
}; |
|
} |