gradio / node_modules /oboe /test /libs /oboeAsserter.js
reisarod's picture
Upload folder using huggingface_hub
5fae594 verified
/*
Assertion helpers for testing the interface exposed as window.oboe
These assertions mostly rely on everything that sits behind there as well (so they aren't
true unit testing assertions, more of a suite of component testing helpers).
*/
function givenAnOboeInstance(jsonFileName) {
function OboeAsserter() {
var asserter = this,
oboeInstance,
expectingErrors = false,
givenErrors = [],
completeJson, // assigned in the requestCompleteCallback
spiedCallback; //erk: only one callback stub per Asserter right now :-s
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) {
// Unless set up to expect them, the test isn't expecting errors.
// Fail the test on getting an error:
expect(expectingErrors).toBeTruthy();
});
// designed for use with jasmine's waitsFor, ie:
// waitsFor(asserter.toComplete())
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);
}
// giving the content one char at a time makes debugging easier when
// wanting to know how much has been written into the stream.
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(){}
/**
* Assert any number of conditions were met on the spied callback
*/
this.thenTheInstance = function( /* ... functions ... */ ){
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;
};
/** sinon stub is only really used to record arguments given.
* However, we want to preserve the arguments given at the time of calling, because they might subsequently
* be changed inside the parser so everything gets cloned before going to the stub
*/
function argumentClone(delegateCallback) {
return function(){
function clone(original){
// Note: window.eval being used here instead of JSON.parse because
// eval can handle 'undefined' in the string but JSON.parse cannot.
// This isn't wholy ideal since this means we're relying on JSON.
// stringify to create invalid JSON. But at least there are no
// security concerns with this being a test.
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);
}
}
};
// higher-order function to create assertions. Pass output to Asserter#thenTheInstance.
// test how many matches were found
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)
)
}
}
}
}
// To test the json at oboe#json() is as expected.
function hasRootJson(expected){
return {
testAgainst:
function(callback, oboeInstance) {
expect(oboeInstance.root()).toEqual(expected);
}
}
}
// To test the json given as the call .onGet(url, callback(completeJson))
// is correct
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];
}
/**
* Make a string version of the callback arguments given from oboe
* @param {[[*]]} callbackArgs
*/
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");
}
// higher-level function to create assertions which will be used by the asserter.
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);
// since this is a matcher, we can't ues expect().toEqual()
// because then the test would fail on the first non-match
// under jasmine. Using stringify is slightly brittle and
// if this breaks we need to work out how to plug into Jasmine's
// inner equals(a,b) function
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) {
// since this is a matcher, we can't ues expect().toEqual()
// because then the test would fail on the first non-match
// under jasmine. Using stringify is slightly brittle and
// if this breaks we need to work out how to plug into Jasmine's
// inner equals(a,b) function
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;
}
};
}