diff --git a/jquery.eventsource.js b/jquery.eventsource.js index 51281a9..0a92dd0 100644 --- a/jquery.eventsource.js +++ b/jquery.eventsource.js @@ -35,26 +35,29 @@ pluginFns = { public: { - close: function ( label ) { + close: function( label ) { - var cache = {}; - - if ( label !== "*" ) { + var tmp = {}; - for ( var prop in stream.cache ) { - if ( label !== prop ) { - cache[ prop ] = stream.cache[ prop ]; - } + if ( !label || label === "*" ) { + stream.cache = {}; + + return stream.cache; + } + + for ( var prop in stream.cache ) { + if ( label !== prop ) { + tmp[ prop ] = stream.cache[ prop ]; } } - stream.cache = cache; + stream.cache = tmp; return stream.cache; }, - streams: function ( label ) { + streams: function( label ) { - if ( label === "*" ) { + if ( !label || label === "*" ) { return stream.cache; } @@ -64,10 +67,10 @@ _private: { // Open a host api event source - openEventSource: function ( options ) { + openEventSource: function( options ) { var label = options.label; - stream.cache[ label ].stream.addEventListener("open", function (event) { + stream.cache[ label ].stream.addEventListener("open", function(event) { if ( stream.cache[label] ) { this.label = label; @@ -76,7 +79,7 @@ } }, false); - stream.cache[label].stream.addEventListener("message", function (event) { + stream.cache[label].stream.addEventListener("message", function(event) { var streamData = []; @@ -100,7 +103,7 @@ return stream.cache[label].stream; }, // open fallback event source - openPollingSource: function ( options ) { + openPollingSource: function( options ) { var label = options.label, source; @@ -110,13 +113,13 @@ type: "GET", url: options.url, data: options.data, - beforeSend: function () { + beforeSend: function() { if ( stream.cache[label] ) { this.label = label; stream.cache[label].options.open.call( this ); } }, - success: function ( data ) { + success: function( data ) { var tempdata, label = options.label, @@ -156,7 +159,7 @@ setTimeout( - function () { + function() { pluginFns._private.openPollingSource.call( this, options ); }, // matches speed of host api EventSource @@ -236,5 +239,10 @@ return stream.cache; }; + jQuery.each( [ "close", "streams" ], function( idx, name ) { + jQuery.eventsource[ name ] = function( arg ) { + return jQuery.eventsource( name, arg || "*" ); + }; + }); })(jQuery, window); diff --git a/test/jquery.eventsource.unit.js b/test/jquery.eventsource.unit.js index 3bf8ddd..a205ad2 100644 --- a/test/jquery.eventsource.unit.js +++ b/test/jquery.eventsource.unit.js @@ -8,360 +8,388 @@ function sizeOf(obj) { } -test("$.eventsource is a function", function() { - ok( $.isFunction($.eventsource), "$.eventsource is a function" ); - - equals(sizeOf($.eventsource("streams")), 0, "There are no streams"); - }); - - test("$.eventsource callbacks", function() { - - stop(); - // PLAIN TEXT EXAMPLE - NO CONTENT TYPE GIVEN - $.eventsource({ - label: "text-event-source", - url: "../test-event-sources/event-source-1.php", - open: function () { - ok( true, "#1 $.eventsource fires onopen callback" ); - }, - message: function (data) { - ok( true, "#1 $.eventsource fires onmessage callback" ); - - ok( data, "#1 $.eventsource returns data"); - - ok( typeof $.eventsource("close", "text-event-source") === "object", '$.eventsource("close", "text-event-source") must return an object' ); - } - }); +$(function() { - // PLAIN TEXT EXAMPLE - HAS CONTENT TYPE - $.eventsource({ - label: "text-event-source-ct", - url: "../test-event-sources/event-source-1.php", - dataType: "text", - open: function () { - ok( true, "#2 $.eventsource fires onopen callback" ); - }, - message: function (data) { - ok( true, "#2 $.eventsource fires onmessage callback" ); - - ok( data, "#2 $.eventsource returns data"); - - ok( typeof $.eventsource("close", "text-event-source-ct") === "object", '$.eventsource("close", "text-event-source-ct") must return an object' ); - } - }); - - // PLAIN TEXT EXAMPLE - HAS CONTENT TYPE + var params = location.search.slice( 1 ).split( "&" ), + pairs = {}; - $.eventsource({ - label: "json-event-source", - url: "../test-event-sources/event-source-2.php", - dataType: "json", - open: function () { - ok( true, "#3 $.eventsource fires onopen callback" ); - }, - message: function (data) { - - ok( true, "#3 $.eventsource fires onmessage callback" ); - - ok( data, "#3 $.eventsource returns data"); + params.forEach(function(param) { - ok( typeof $.eventsource("close", "json-event-source") === "object", '$.eventsource("close", "json-event-source") must return an object' ); - } - }); + var tmp = param.split("="); - setTimeout(function(){ - start(); - }, 500); + pairs[ tmp[0] ] = tmp[1]; }); + + //document.querySelectorAll("iframe")[0].style.display = "none"; + + if ( pairs.nospecit ) { + $("iframe").hide(); + } +}); + + +test("jQuery.eventsource is a function", function() { + + expect(7); + ok( jQuery.eventsource, "jQuery.eventsource exists" ); + equal( typeof jQuery.eventsource, "function", "jQuery.eventsource() is a Function" ); + ok( jQuery.eventsource.streams, "jQuery.eventsource.streams exists" ); + equal( typeof jQuery.eventsource.streams, "function", "jQuery.eventsource.streams() is a Function" ); + + ok( jQuery.eventsource.close, "jQuery.eventsource.close exists" ); + equal( typeof jQuery.eventsource.close, "function", "jQuery.eventsource.close() is a Function" ); + + equal( sizeOf( jQuery.eventsource.streams() ), 0, "There are no streams"); +}); +test("jQuery.eventsource callbacks", function() { + + var expects = 12, + count = 0; + + expect( expects ); + + function plus() { + if ( ++count === expects ) { + start(); + } + } + + function okPlus() { + ok.apply(null, arguments); + plus(); + } + + stop(); + // PLAIN TEXT EXAMPLE - NO CONTENT TYPE GIVEN + jQuery.eventsource({ + label: "text-event-source", + url: "../test-event-sources/event-source-1.php", + open: function() { + okPlus( true, "#1 jQuery.eventsource fires onopen callback" ); + }, + message: function(data) { + okPlus( true, "#1 jQuery.eventsource fires onmessage callback" ); + + okPlus( data, "#1 jQuery.eventsource returns data"); + + okPlus( typeof jQuery.eventsource("close", "text-event-source") === "object", 'jQuery.eventsource("close", "text-event-source") must return an object' ); + } + }); + + // PLAIN TEXT EXAMPLE - HAS CONTENT TYPE + jQuery.eventsource({ + label: "text-event-source-ct", + url: "../test-event-sources/event-source-1.php", + dataType: "text", + open: function() { + okPlus( true, "#2 jQuery.eventsource fires onopen callback" ); + }, + message: function(data) { + + okPlus( true, "#2 jQuery.eventsource fires onmessage callback" ); + okPlus( data, "#2 jQuery.eventsource returns data"); + okPlus( typeof jQuery.eventsource("close", "text-event-source-ct") === "object", 'jQuery.eventsource("close", "text-event-source-ct") must return an object' ); + + } + }); + + // PLAIN TEXT EXAMPLE - HAS CONTENT TYPE + + jQuery.eventsource({ + label: "json-event-source", + url: "../test-event-sources/event-source-2.php", + dataType: "json", + open: function() { + okPlus( true, "#3 jQuery.eventsource fires onopen callback" ); + }, + message: function(data) { + + okPlus( true, "#3 jQuery.eventsource fires onmessage callback" ); + okPlus( data, "#3 jQuery.eventsource returns data"); + okPlus( typeof jQuery.eventsource("close", "json-event-source") === "object", 'jQuery.eventsource("close", "json-event-source") must return an object' ); + + } + }); + +}); + +test("jQuery.eventsource open/close", function() { + var expects = 5, + count = 0; + + expect( expects ); + + function plus() { + if ( ++count === expects ) { + start(); + } + } + + stop(); + + jQuery.eventsource({ + label: "json-event-source-stream", + url: "../test-event-sources/event-source-2.php", + dataType: "json", + open: function() { + ok( true, "jQuery.eventsource fires onopen callback" ); + plus(); + }, + message: function(data) { + + ok( true, "jQuery.eventsource fires onmessage callback" ); + plus(); + + ok( data, "jQuery.eventsource returns data"); + plus(); + + equal( typeof jQuery.eventsource.close("json-event-source-stream"), "object", 'jQuery.eventsource.close("json-event-source-stream") must return an object' ); + plus(); + + equal( sizeOf( jQuery.eventsource.streams() ), 0, "there are 0 active streams"); + plus(); + } + }); +}); - test("$.eventsource open/close", function() { - stop(); - - $.eventsource({ - label: "json-event-source-stream", - url: "../test-event-sources/event-source-2.php", - dataType: "json", - open: function () { - ok( true, "#4 $.eventsource fires onopen callback" ); - }, - message: function (data) { - - ok( true, "#4 $.eventsource fires onmessage callback" ); - - ok( data, "#4 $.eventsource returns data"); - - equals(sizeOf($.eventsource("streams")), 1, "there is only 1 active stream"); - - ok( typeof $.eventsource("close", "json-event-source-stream") === "object", '$.eventsource("close", "json-event-source-stream") must return an object' ); - - equals(sizeOf($.eventsource("streams")), 0, "there are 0 active streams"); - } - }); +test("jQuery.eventsource - multiple concurrent sources - scope tests", function() { + var expects = 12, + count = 0, + down = 3; - - setTimeout(function(){ + expect( expects ); + + function plus() { + if ( ++count === expects ) { start(); - }, 1500); - - }); + } + } + stop(); - test("$.eventsource - multiple concurrent sources - scope tests", function() { - stop(); - - $.eventsource({ - label: "event-source-1", - url: "../test-event-sources/event-source-2.php", - dataType: "json", - open: function () { - - ok( true, "event-source-1 fires onopen callback" ); - }, - message: function (data) { - - equals(this.label, "event-source-1", "Correct EventSource returned, looking for `event-source-1`"); - ok( true, "event-source-1 fires onmessage callback" ); - } - }); - - $.eventsource({ - label: "event-source-2", - url: "../test-event-sources/event-source-2.php", + jQuery.each( [ 1, 2, 3 ], function( idx, stream ) { + + jQuery.eventsource({ + label: "event-source-" + stream , + url: "../test-event-sources/event-source-2.php", dataType: "json", - open: function () { - - ok( true, "event-source-2 fires onopen callback" ); + open: function() { + + ok( true, "Stream #" + stream + ", event-source-" + stream + " fires onopen callback" ); + plus(); }, - message: function (data) { - - equals(this.label, "event-source-2", "Correct EventSource returned, looking for `event-source-2`"); - ok( true, "event-source-2 fires onmessage callback" ); + message: function(data) { + + equal(this.label, "event-source-" + stream, "Stream #" + stream + ", Correct EventSource returned, looking for `event-source-" + stream + "`"); + plus(); + + ok( true, "Stream #" + stream + ", event-source-" + stream + " fires onmessage callback" ); + plus(); + + jQuery.eventsource.close( "event-source-" + stream ); + + equal( sizeOf( jQuery.eventsource.streams() ), --down, "Stream #" + stream + " is closed" ); + plus(); } }); + }); +}); - $.eventsource({ - label: "event-source-3", - url: "../test-event-sources/event-source-2.php", - dataType: "json", - open: function () { - ok( true, "event-source-3 fires onopen callback" ); - }, - message: function (data) { - - - equals(this.label, "event-source-3", "Correct EventSource returned, looking for `event-source-3`"); - ok( true, "event-source-3 fires onmessage callback" ); - } - }); +test("jQuery.eventsource - breakage tests", function() { + var expects = 7, + count = 0; - setTimeout(function(){ - start(); - }, 2000); - }); - + expect( expects ); - test("$.eventsource - multiple concurrent sources - scope tests: closing sources one at a time", function() { - stop(); - - - setTimeout(function() { - equals(2, sizeOf($.eventsource("close", "event-source-1")), "Closing `event-source-1`, 2 event sources remaining"); - equals(1, sizeOf($.eventsource("close", "event-source-2")), "Closing `event-source-2`, 1 event sources remaining"); - equals(0, sizeOf($.eventsource("close", "event-source-3")), "Closing `event-source-3`, 0 event sources remaining"); + function plus() { + if ( ++count === expects ) { start(); - }, 500); - }); - + } + } - test("$.eventsource - breakage tests", function() { - - stop(); - - try { - $.eventsource({}); - - } catch(err) { - ok(true, "Caught the error thrown by the instance not having any options set"); - } - - try { - $.eventsource({ - open: function () {}, - message: function (data) {} - }); - } catch(err) { - ok(true, "Caught the error thrown by the instance not being provided a url"); - } - - try { - $.eventsource({ - url: null, - open: function () {}, - message: function (data) {} - }); - } catch(err) { - ok(true, "Caught the error thrown by the instance options.url being `null`"); - } - - - try { - $.eventsource({ - url: undefined, - open: function () {}, - message: function (data) {} - }); - } catch(err) { - ok(true, "Caught the error thrown by the instance options.url being `undefined`"); - } - - - try { - $.eventsource({ - url: "", - open: function () {}, - message: function (data) {} - }); - } catch(err) { - ok(true, "Caught the error thrown by the instance options.url being an empty string"); - } - - - try { - $.eventsource({ - url: false, - open: function () {}, - message: function (data) {} - }); - } catch(err) { - ok(true, "Caught the error thrown by the instance options.url being `false`"); - } - - - try { - $.eventsource({ - url: true, - open: function () {}, - message: function (data) {} - }); - } catch(err) { - ok(true, "Caught the error thrown by the instance options.url being `true`"); - } - - setTimeout(function(){ - start(); - }, 3000); + function okPlus() { + ok.apply(null, arguments); + plus(); + } - }); + stop(); + try { + jQuery.eventsource({}); + } catch(err) { + okPlus(true, "Caught the error thrown by the instance not having any options set"); + } + try { + jQuery.eventsource({ + open: function() {}, + message: function(data) {} + }); + } catch(err) { + okPlus(true, "Caught the error thrown by the instance not being provided a url"); + } + try { + jQuery.eventsource({ + url: null, + open: function() {}, + message: function(data) {} + }); + } catch(err) { + okPlus(true, "Caught the error thrown by the instance options.url being `null`"); + } - test("$.eventsource streams object", function() { + try { + jQuery.eventsource({ + url: undefined, + open: function() {}, + message: function(data) {} + }); + } catch(err) { + okPlus(true, "Caught the error thrown by the instance options.url being `undefined`"); + } - stop(); - setTimeout(function(){ - // labeled stream - $.eventsource({ - label: "labeled-stream", - url: "../test-event-sources/event-source-1.php", - open: function () { - }, - message: function (data) { - } - }); + try { + jQuery.eventsource({ + url: "", + open: function() {}, + message: function(data) {} + }); + } catch(err) { + okPlus(true, "Caught the error thrown by the instance options.url being an empty string"); + } - // unlabeled stream - $.eventsource({ - url: "../test-event-sources/event-source-2.php", - open: function () { - }, - message: function (data) { - } - }); + try { + jQuery.eventsource({ + url: false, + open: function() {}, + message: function(data) {} + }); + } catch(err) { + okPlus(true, "Caught the error thrown by the instance options.url being `false`"); + } - // no callbacks - $.eventsource({ - url: "../test-event-sources/event-source-2.php" - }); - - - var streamsObj = $.eventsource("streams"); + try { + jQuery.eventsource({ + url: true, + open: function() {}, + message: function(data) {} + }); + } catch(err) { + okPlus(true, "Caught the error thrown by the instance options.url being `true`"); + } +}); + +test("jQuery.eventsource streams object", function() { - ok( typeof streamsObj === "object", "$.eventsource("streams") must return an object" ); + var expects = 13, + count = 0; + expect( expects ); - $.each(streamsObj, function (i, obj) { + function plus() { + if ( ++count === expects ) { + start(); + } + } - equals( typeof obj.isHostApi, "boolean", "Stream.isHostApi exists and is a boolean value" ); + // labeled stream + jQuery.eventsource({ + label: "labeled-stream", + url: "../test-event-sources/event-source-1.php", + open: function() { + }, + message: function(data) { + } + }); - equals( typeof obj.lastEventId, "number", "Stream.lastEventId exists and is a boolean value" ); + // unlabeled stream + jQuery.eventsource({ + url: "../test-event-sources/event-source-2.php", + open: function() { + }, + message: function(data) { + } + }); - equals( obj.options.label && obj.options.label !== "", true, "Stream.options.label exists and not an empty string" ); + // no callbacks + jQuery.eventsource({ + url: "../test-event-sources/event-source-2.php" + }); - equals( obj.options.message && $.isFunction(obj.options.message), true, "Stream.options.message exists and is a function" ); + stop(5000); - equals( obj.options.open && $.isFunction(obj.options.open), true, "Stream.options.message exists and is a function" ); + var streamsObj = jQuery.eventsource.streams(); - if ( obj.isHostApi ) { - equals( obj.stream.toString(), "[object EventSource]", "Native Streams are [object EventSource]" ); - } - if ( !obj.isHostApi ) { - if ( window.XMLHttpRequest ) { - equals( obj.stream.toString(), "[object XMLHttpRequest]", "Non-Native Streams are [object XMLHttpRequest]" ); - } - else { - ok( true, "Missing IE Stream type test!!" ); - } - } + ok( typeof streamsObj === "object", "jQuery.eventsource('streams') must return an object" ); + plus(); - }); + jQuery.each( streamsObj, function(i, obj) { - equals( typeof $.eventsource("close"), "object", "$.eventsource("close") must return an object" ); + equal( typeof obj.isHostApi, "boolean", "Stream.isHostApi exists and is a boolean value" ); + plus(); - equals( typeof $.eventsource("streams"), "object", "$.eventsource("streams") must return an object" ); + equal( typeof obj.lastEventId, "number", "Stream.lastEventId exists and is a boolean value" ); + plus(); - start(); + equal( obj.options.label && obj.options.label !== "", true, "Stream.options.label exists and not an empty string" ); + plus(); - }, 4000); + equal( obj.options.message && jQuery.isFunction(obj.options.message), true, "Stream.options.message exists and is a function" ); + plus(); + equal( obj.options.open && jQuery.isFunction(obj.options.open), true, "Stream.options.message exists and is a function" ); + plus(); + if ( obj.isHostApi ) { + equal( obj.stream.toString(), "[object EventSource]", "Native Streams are [object EventSource]" ); + plus(); + } else { + equal( obj.stream.toString(), "[object Object]", "Non-Native Streams are [object Object]" ); + plus(); + } + }); +}); - // ADD TESTING FOR CONTENT TYPES, CHAR ENCODING +test("jQuery.eventsource streams Are Closed", function() { + var expects = 2, + count = 0; - }); + expect( expects ); + function plus() { + if ( ++count === expects ) { + start(); + } + } - test("$.eventsource streams Are Closed", function() { - - stop(); - - equals(sizeOf($.eventsource("streams")), 0, "there are 0 active streams"); - - ok( typeof $.eventsource("streams") === "object", '$.eventsource("streams") must return an object' ); + stop(); + jQuery.eventsource.close(); + + equal(sizeOf(jQuery.eventsource.streams()), 0, "there are 0 active streams"); + plus(); - setTimeout(function(){ - start(); - }, 1000); - - }); + ok( typeof jQuery.eventsource.streams() === "object", 'jQuery.eventsource.streams() must return an object' ); + plus(); +});