|
|
|
|
|
|
|
|
|
describe('streaming xhr integration (real http)', function() { |
|
"use strict"; |
|
|
|
var emittedEvents = [HTTP_START, STREAM_DATA, STREAM_END, FAIL_EVENT, ABORTING]; |
|
|
|
it('completes', function() { |
|
|
|
|
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'GET', |
|
'/testServer/static/json/smallestPossible.json', |
|
null |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus) |
|
}) |
|
|
|
it('can ajax in a small known file', function() { |
|
|
|
|
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'GET', |
|
'/testServer/static/json/smallestPossible.json', |
|
null |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus); |
|
|
|
runs(function(){ |
|
expect(oboeBus).toHaveGivenStreamEventsInCorrectOrder() |
|
expect(streamedContentPassedTo(oboeBus)).toParseTo({}) |
|
}); |
|
}) |
|
|
|
it('fires HTTP_START with status and headers', function() { |
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'GET', |
|
'/testServer/echoBackHeadersAsHeaders', |
|
null, |
|
{'specialheader':'specialValue'} |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus); |
|
|
|
runs(function(){ |
|
expect(oboeBus(HTTP_START).emit) |
|
.toHaveBeenCalledWith( |
|
200, |
|
headerObjectContaining('specialheader', 'specialValue') |
|
); |
|
}); |
|
}) |
|
|
|
it('gives XHR header so server knows this is an xhr request', function() { |
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'GET', |
|
'/testServer/echoBackHeadersAsHeaders' |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus); |
|
|
|
runs(function(){ |
|
expect(oboeBus(HTTP_START).emit) |
|
.toHaveBeenCalledWith( |
|
200, |
|
headerObjectContaining('X-Requested-With', 'XMLHttpRequest') |
|
); |
|
|
|
console.log(oboeBus(HTTP_START).emit.calls[0].args[1]); |
|
}); |
|
|
|
}) |
|
|
|
it('fires HTTP_START, STREAM_DATA and STREAM_END in correct order', function() { |
|
|
|
|
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'GET', |
|
'/testServer/echoBackHeadersAsHeaders', |
|
null, |
|
{'specialheader':'specialValue'} |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus); |
|
|
|
runs(function(){ |
|
expect(oboeBus).toHaveGivenStreamEventsInCorrectOrder() |
|
}); |
|
}) |
|
|
|
it('fires FAIL_EVENT if url does not exist', function () { |
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'GET', |
|
'/testServer/noSuchUrl', |
|
null |
|
); |
|
|
|
waitUntil(FAIL_EVENT).isFiredOn(oboeBus); |
|
|
|
}) |
|
|
|
it('can ajax in a very large file without missing any', function() { |
|
|
|
|
|
|
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'GET', |
|
'/testServer/static/json/twentyThousandRecords.json', |
|
null |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus); |
|
|
|
runs(function(){ |
|
var parsedResult; |
|
|
|
expect(function(){ |
|
|
|
parsedResult = JSON.parse(streamedContentPassedTo(oboeBus)); |
|
|
|
}).not.toThrow(); |
|
|
|
|
|
expect(parsedResult.result.length).toEqual(20000); |
|
}); |
|
}) |
|
|
|
it('can ajax in a streaming file without missing any', function() { |
|
|
|
|
|
|
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'GET', |
|
'/testServer/tenSlowNumbers?withoutMissingAny', |
|
null |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus); |
|
|
|
runs(function(){ |
|
|
|
expect(streamedContentPassedTo(oboeBus)).toParseTo([0,1,2,3,4,5,6,7,8,9]); |
|
expect(oboeBus).toHaveGivenStreamEventsInCorrectOrder() |
|
}); |
|
}) |
|
|
|
it('can make a post request', function() { |
|
|
|
var payload = {'thisWill':'bePosted','andShould':'be','echoed':'back'}; |
|
|
|
|
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'POST', |
|
'/testServer/echoBackBody', |
|
JSON.stringify(payload) |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus); |
|
|
|
runs(function(){ |
|
expect(streamedContentPassedTo(oboeBus)).toParseTo(payload); |
|
expect(oboeBus).toHaveGivenStreamEventsInCorrectOrder() |
|
}); |
|
|
|
}) |
|
|
|
it('can make a put request', function() { |
|
|
|
var payload = {'thisWill':'bePut','andShould':'be','echoed':'back'}; |
|
|
|
|
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'PUT', |
|
'/testServer/echoBackBody', |
|
JSON.stringify(payload) |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus); |
|
|
|
runs(function(){ |
|
expect(streamedContentPassedTo(oboeBus)).toParseTo(payload); |
|
expect(oboeBus).toHaveGivenStreamEventsInCorrectOrder() |
|
}); |
|
|
|
}) |
|
|
|
|
|
it('can make a patch request', function() { |
|
|
|
var payload = {'thisWill':'bePatched','andShould':'be','echoed':'back'}; |
|
|
|
|
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'PATCH', |
|
'/testServer/echoBackBody', |
|
JSON.stringify(payload) |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus); |
|
|
|
runs(function(){ |
|
if( streamedContentPassedTo(oboeBus) == '' && |
|
(Platform.isInternetExplorer || Platform.isPhantom) ) { |
|
console.warn( 'this user agent seems not to support giving content' |
|
+ ' back for of PATCH requests.' |
|
+ ' This happens on PhantomJS and IE < 9'); |
|
} else { |
|
expect(streamedContentPassedTo(oboeBus)).toParseTo(payload); |
|
expect(oboeBus).toHaveGivenStreamEventsInCorrectOrder(); |
|
} |
|
}); |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
if( !Platform.isInternetExplorer || Platform.isInternetExplorer >= 10 ) { |
|
it('gives multiple callbacks when loading a streaming resource', function() { |
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'GET', |
|
|
|
'/testServer/tenSlowNumbers', |
|
null |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus); |
|
|
|
runs(function(){ |
|
|
|
|
|
|
|
expect(oboeBus.callCount[STREAM_DATA]).toBeGreaterThan(3) |
|
expect(oboeBus).toHaveGivenStreamEventsInCorrectOrder() |
|
}); |
|
}) |
|
|
|
it('gives multiple callbacks when loading a gzipped streaming resource', function() { |
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'GET', |
|
|
|
'/testServer/gzippedTwoHundredItems', |
|
null |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus); |
|
|
|
runs(function(){ |
|
|
|
|
|
if( oboeBus.callCount[STREAM_DATA] == 1 && |
|
(Platform.isInternetExplorer || Platform.isPhantom) ) { |
|
console.warn('This user agent seems to give gzipped responses' + |
|
'as a single event, not progressively. This happens on ' + |
|
'PhantomJS and IE < 9'); |
|
} else { |
|
expect(oboeBus.callCount[STREAM_DATA]).toBeGreaterThan(1); |
|
} |
|
|
|
expect(oboeBus).toHaveGivenStreamEventsInCorrectOrder(); |
|
}); |
|
}) |
|
} |
|
|
|
it('does not call back with zero-length bites', function() { |
|
|
|
|
|
var oboeBus = fakePubSub(emittedEvents) |
|
streamingHttp( |
|
oboeBus, |
|
httpTransport(), |
|
'GET', |
|
'/testServer/static/json/oneHundredRecords.json', |
|
null |
|
); |
|
|
|
waitUntil(STREAM_END).isFiredOn(oboeBus) |
|
|
|
runs(function(){ |
|
|
|
var dripsReceived = oboeBus.eventTypesEmitted[STREAM_DATA].map(function( args ){ |
|
return args[0]; |
|
}); |
|
|
|
expect(dripsReceived.length).toBeGreaterThan(0); |
|
|
|
dripsReceived.forEach(function(drip) { |
|
expect(drip.length).not.toEqual(0); |
|
}); |
|
|
|
}) |
|
}) |
|
|
|
function waitUntil(event) { |
|
return {isFiredOn: function (eventBus){ |
|
waitsFor(function(){ |
|
|
|
return !!eventBus(event).emit.calls.length; |
|
|
|
}, 'event ' + event + ' to be fired', ASYNC_TEST_TIMEOUT); |
|
} |
|
} |
|
} |
|
|
|
function streamedContentPassedTo(eventBus){ |
|
|
|
return eventBus.eventTypesEmitted[STREAM_DATA].map(function(args){ |
|
return args[0]; |
|
}).join(''); |
|
} |
|
|
|
beforeEach(function(){ |
|
|
|
function prettyPrintEvent(event){ |
|
|
|
switch(event) { |
|
case HTTP_START: return 'start'; |
|
case STREAM_DATA: return 'data'; |
|
case STREAM_END: return 'end'; |
|
default: return 'unknown(' + event + ')' |
|
} |
|
} |
|
|
|
this.addMatchers({ |
|
toHaveGivenStreamEventsInCorrectOrder: function(){ |
|
|
|
var eventNames = this.actual.eventNames; |
|
|
|
this.message = function(){ |
|
return 'events not in correct order. We have: ' + |
|
JSON.stringify( |
|
eventNames.map(prettyPrintEvent) |
|
) |
|
}; |
|
|
|
return eventNames[0] === HTTP_START |
|
&& eventNames[1] === STREAM_DATA |
|
&& eventNames[eventNames.length-1] === STREAM_END; |
|
}, |
|
|
|
toParseTo:function( expectedObj ){ |
|
|
|
var actual = this.actual; |
|
var normalisedActual; |
|
|
|
if( !actual ) { |
|
this.message = function(){ |
|
return 'no content has been received'; |
|
} |
|
return false; |
|
} |
|
|
|
try{ |
|
normalisedActual = JSON.stringify( JSON.parse(actual) ); |
|
}catch(e){ |
|
|
|
this.message = function(){ |
|
|
|
return "Expected to be able to parse the found " + |
|
"content as json '" + actual + "' but it " + |
|
"could not be parsed"; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
this.message = function(){ |
|
return "The found json parsed but did not match " + JSON.stringify(expectedObj) + |
|
" because found " + this.actual; |
|
} |
|
|
|
return (normalisedActual === JSON.stringify(expectedObj)); |
|
} |
|
}); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
function headerObjectContaining(key, val) { |
|
|
|
|
|
|
|
return { |
|
jasmineMatches: function(obj){ |
|
return obj[key] == val || obj[key.toLowerCase()] == val; |
|
} |
|
} |
|
} |
|
|
|
}); |
|
|