[Pkg-javascript-commits] [sockjs-client] 100/350: tests for jsonp receiver logic

tonnerre at ancient-solutions.com tonnerre at ancient-solutions.com
Fri Aug 5 01:03:47 UTC 2016


This is an automated email from the git hooks/post-receive script.

tonnerre-guest pushed a commit to branch upstream
in repository sockjs-client.

commit a459b62d194db2be7d8b151f5bdf122419112bce
Author: Bryce Kahle <bkahle at gmail.com>
Date:   Thu Oct 9 19:33:45 2014 -0400

    tests for jsonp receiver logic
---
 .jshintrc                       |   3 +
 lib/main.js                     |   2 +-
 lib/transport/lib/polling.js    |  10 ++--
 lib/transport/receiver/jsonp.js | 100 +++++++++++++++++----------------
 package.json                    |   2 +-
 tests/receivers.js              | 119 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 182 insertions(+), 54 deletions(-)

diff --git a/.jshintrc b/.jshintrc
index b31c343..b70c17c 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -11,5 +11,8 @@
     "ActiveXObject"
   , "XDomainRequest"
   , "EventSource"
+  , "describe"
+  , "it"
+  , "before"
   ]
 }
\ No newline at end of file
diff --git a/lib/main.js b/lib/main.js
index 55fcb64..ddc2d1e 100644
--- a/lib/main.js
+++ b/lib/main.js
@@ -134,7 +134,7 @@ SockJS.prototype._receiveInfo = function(info, rtt) {
   this._rto = utils.countRTO(rtt);
   // allow server to override url used for the actual transport
   this._transUrl = info.base_url ? info.base_url : this.url;
-  info.nullOrigin = !document.domain;
+  info.nullOrigin = global.document && !global.document.domain;
   // determine list of desired and supported transports
   var enabledTransports = transports(this.url, this._transportsWhitelist, info);
   this._transports = enabledTransports.main;
diff --git a/lib/transport/lib/polling.js b/lib/transport/lib/polling.js
index 36d75d8..802ce84 100644
--- a/lib/transport/lib/polling.js
+++ b/lib/transport/lib/polling.js
@@ -25,13 +25,13 @@ Polling.prototype._scheduleReceiver = function() {
   poll.onclose = function(e) {
     self.poll = poll = poll.onmessage = poll.onclose = null;
     if (!self.pollIsClosing) {
-      if (e.reason === 'permanent') {
+      if (e.reason === 'network') {
+        self._scheduleReceiver();
+      } else {
         var ce = new CloseEvent();
-        ce.code = 1006;
-        ce.reason = 'Polling error (' + e.reason + ')';
+        ce.code = e.code || 1000;
+        ce.reason = e.reason;
         self.dispatchEvent(ce);
-      } else {
-        self._scheduleReceiver();
       }
     }
   };
diff --git a/lib/transport/receiver/jsonp.js b/lib/transport/receiver/jsonp.js
index 83a9f61..a6f5a72 100644
--- a/lib/transport/receiver/jsonp.js
+++ b/lib/transport/receiver/jsonp.js
@@ -7,22 +7,39 @@ var utils = require('../../utils')
   ;
 
 function JsonpReceiver(url) {
+  var self = this;
   EventTarget.call(this);
 
   utils.polluteGlobalNamespace();
 
   this.id = 'a' + utils.randomString(6);
-  var urlId = url + '?c=' + encodeURIComponent(utils.WPrefix + '.' + this.id);
+  var urlWithId = url + '?c=' + encodeURIComponent(utils.WPrefix + '.' + this.id);
+
+  global[utils.WPrefix][this.id] = this._callback.bind(this);
+  this._createScript(urlWithId);
 
-  window[utils.WPrefix][this.id] = this.callback.bind(this);
-  this.createScript(urlId);
+  // Fallback mostly for Konqueror - stupid timer, 35 seconds shall be plenty.
+  this.timeoutId = setTimeout(function() {
+    self._abort(new Error('JSONP script loaded abnormally (timeout)'));
+  }, JsonpReceiver.timeout);
 }
 
 util.inherits(JsonpReceiver, EventTarget);
 
-JsonpReceiver.prototype.callback = function (data) {
-  this.deleteScript();
-  delete window[utils.WPrefix][this.id];
+JsonpReceiver.prototype.abort = function () {
+  if (global[utils.WPrefix][this.id]) {
+    var err = new Error('JSONP user aborted read');
+    err.code = 1000;
+    this._abort(err);
+  }
+};
+
+JsonpReceiver.timeout = 35000;
+JsonpReceiver.scriptErrorTimeout = 1000;
+
+JsonpReceiver.prototype._callback = function (data) {
+  this._cleanup();
+  delete global[utils.WPrefix][this.id];
   
   if (this.aborting) {
     return;
@@ -32,32 +49,24 @@ JsonpReceiver.prototype.callback = function (data) {
     this.dispatchEvent(new SimpleEvent('message', { data: data }));
   }
   this.dispatchEvent(new SimpleEvent('close', { reason: 'network' }));
+  this.onmessage = this.onclose = null;
 };
 
-JsonpReceiver.prototype.abort = function () {
-  if (window[utils.WPrefix][this.id]) {
-    var err = new Error('JSONP user aborted read');
-    err.code = 1000;
-    this._abort(err);
-  }
-};
-
-module.exports = JsonpReceiver;
-
 JsonpReceiver.prototype._abort = function (err) {
-  this.deleteScript();
+  this._cleanup();
   this.aborting = true;
-  this.dispatchEvent(new SimpleEvent('close', { reason: 'permanent' }));
+  this.dispatchEvent(new SimpleEvent('close', { code: err.code, reason: err.message }));
+  this.onmessage = this.onclose = null;
 };
 
-JsonpReceiver.prototype.deleteScript = function () {
+JsonpReceiver.prototype._cleanup = function () {
+  clearTimeout(this.timeoutId);
   if (this.script2) {
     this.script2.parentNode.removeChild(this.script2);
     this.script2 = null;
   }
   if (this.script) {
     var script = this.script;
-    clearTimeout(this.tref);
     // Unfortunately, you can't really abort script loading of
     // the script.
     script.parentNode.removeChild(script);
@@ -67,40 +76,40 @@ JsonpReceiver.prototype.deleteScript = function () {
   }
 };
 
-JsonpReceiver.prototype.createScript = function (url) {
+JsonpReceiver.prototype._scriptError = function () {
+  var self = this;
+  if (this.errorTimer) return;
+
+  this.errorTimer = setTimeout(function() {
+    if (!self.loadedOkay) {
+      self._abort(new Error('JSONP script loaded abnormally (onerror)'));
+    }
+  }, JsonpReceiver.scriptErrorTimeout);
+};
+
+JsonpReceiver.prototype._createScript = function (url) {
   var self = this;
   var script = this.script = global.document.createElement('script');
   var script2;  // Opera synchronous load trick.
 
-  // IE9 fires 'error' event after orsc or before, in random order.
-  var loadedOkay = false;
-  var errorTimer = null;
-
   script.id = 'a' + utils.randomString(8);
   script.src = url;
   script.type = 'text/javascript';
   script.charset = 'UTF-8';
-  script.onerror = function() {
-    if (!errorTimer) {
-      // Delay firing closeScript.
-      errorTimer = setTimeout(function() {
-        if (!loadedOkay) {
-          self._abort(new Error('JSONP script loaded abnormally (onerror)'));
-        }
-      }, 1000);
-    }
-  };
+  script.onerror = this._scriptError.bind(this);
   script.onload = function() {
     self._abort(new Error('JSONP script loaded abnormally (onload)'));
   };
 
+  // IE9 fires 'error' event after onreadystatechange or before, in random order.
+  // Use loadedOkay to determine if actually errored
   script.onreadystatechange = function() {
     if (/loaded|closed/.test(script.readyState)) {
       if (script && script.htmlFor && script.onclick) {
-        loadedOkay = true;
+        self.loadedOkay = true;
         try {
-            // In IE, actually execute the script.
-            script.onclick();
+          // In IE, actually execute the script.
+          script.onclick();
         } catch (x) {}
       }
       if (script) {
@@ -118,11 +127,11 @@ JsonpReceiver.prototype.createScript = function (url) {
   //   http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
   // Also, read on that about script ordering:
   //   http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
-  if (typeof script.async === 'undefined' && document.attachEvent) {
+  if (typeof script.async === 'undefined' && global.document.attachEvent) {
     // According to mozilla docs, in recent browsers script.async defaults
     // to 'true', so we may use it to detect a good browser:
     // https://developer.mozilla.org/en/HTML/Element/script
-    if (!/opera/i.test(navigator.userAgent)) {
+    if (!/opera/i.test(global.navigator.userAgent)) {
       // Naively assume we're in IE
       try {
           script.htmlFor = script.id;
@@ -131,7 +140,7 @@ JsonpReceiver.prototype.createScript = function (url) {
       script.async = true;
     } else {
       // Opera, second sync script hack
-      script2 = this.script2 = document.createElement('script');
+      script2 = this.script2 = global.document.createElement('script');
       script2.text = "try{var a = document.getElementById('" + script.id + "'); if(a)a.onerror();}catch(x){};";
       script.async = script2.async = false;
     }
@@ -140,14 +149,11 @@ JsonpReceiver.prototype.createScript = function (url) {
     script.async = true;
   }
 
-  // Fallback mostly for Konqueror - stupid timer, 35 seconds shall be plenty.
-  this.tref = setTimeout(function() {
-    self._abort(new Error('JSONP script loaded abnormally (timeout)'));
-  }, 35000);
-
-  var head = document.getElementsByTagName('head')[0];
+  var head = global.document.getElementsByTagName('head')[0];
   head.insertBefore(script, head.firstChild);
   if (script2) {
     head.insertBefore(script2, head.firstChild);
   }
 };
+
+module.exports = JsonpReceiver;
diff --git a/package.json b/package.json
index f909e3f..30f73c1 100644
--- a/package.json
+++ b/package.json
@@ -53,7 +53,7 @@
     "url": "https://github.com/sockjs/sockjs-client.git"
   },
   "scripts": {
-    "t": "node ./node_modules/mocha/bin/mocha tests/main.js tests/transports.js",
+    "t": "node ./node_modules/mocha/bin/mocha tests/main.js tests/transports.js tests/receivers.js",
     "test": "./node_modules/zuul/bin/zuul --sauce-connect -- tests/html/lib/unittests.js tests/html/lib/domtests.js tests/html/lib/endtoendtests.js tests/html/lib/tests.js",
     "test_ws": "./node_modules/zuul/bin/zuul --sauce-connect -- tests/html/lib/ws_test.js",
     "test_local": "./node_modules/zuul/bin/zuul --local 9090 -- tests/html/lib/unittests.js tests/html/lib/domtests.js tests/html/lib/endtoendtests.js tests/html/lib/tests.js"
diff --git a/tests/receivers.js b/tests/receivers.js
new file mode 100644
index 0000000..4cb8393
--- /dev/null
+++ b/tests/receivers.js
@@ -0,0 +1,119 @@
+'use strict';
+
+var expect = require('expect.js')
+  , JsonpReceiver = require('../lib/transport/receiver/jsonp')
+  , utils = require('../lib/utils')
+  ;
+
+describe('Receivers', function () {
+  describe('jsonp', function () {
+    before(function () {
+      JsonpReceiver.prototype._createScript = function () {};
+      JsonpReceiver.timeout = 300;
+    });
+
+    it('receives data', function (done) {
+      JsonpReceiver.prototype._createScript = function () {
+        var self = this;
+        setTimeout(function () {
+          global[utils.WPrefix][self.id]('datadata');
+        }, 5);
+      };
+      var jpr = new JsonpReceiver('test');
+      jpr.onclose = function (e) {
+        expect(e.reason).to.eql('network');
+        done();
+      };
+      jpr.onmessage = function (e) {
+        expect(e.data).to.eql('datadata');
+      };
+    });
+
+    it('will timeout', function (done) {
+      this.timeout(500);
+      JsonpReceiver.prototype._createScript = function () {
+        var self = this;
+        setTimeout(function () {
+          global[utils.WPrefix][self.id]('datadata');
+        }, 400);
+      };
+
+      var jpr = new JsonpReceiver('test');
+      jpr.onclose = function (e) {
+        expect(e.reason).to.contain('timeout');
+        done();
+      };
+      jpr.onmessage = function () {
+        expect().fail('No message should be sent');
+      };
+    });
+
+    it('will abort without sending a message', function (done) {
+      JsonpReceiver.prototype._createScript = function () {
+        var self = this;
+        setTimeout(function () {
+          global[utils.WPrefix][self.id]('datadata');
+        }, 200);
+      };
+      var jpr = new JsonpReceiver('test');
+      jpr.onclose = function (e) {
+        expect(e.reason).to.contain('aborted');
+        done();
+      };
+      jpr.onmessage = function () {
+        expect().fail('No message should be sent');
+      };
+      jpr.abort();
+    });
+
+    it('will not report error if onerror triggered right before onreadystatechange (IE9)', function (done) {
+      JsonpReceiver.scriptErrorTimeout = 300;
+      JsonpReceiver.prototype._createScript = function () {
+        var self = this;
+        // simulate a normal JSONP response
+        setTimeout(function () {
+          self.loadedOkay = true;
+          global[utils.WPrefix][self.id]('datadata');
+        }, 200);
+      };
+
+      var jpr = new JsonpReceiver('test');
+      jpr.onclose = function (e) {
+        expect(e.reason).to.eql('network');
+        done();
+      };
+      jpr.onmessage = function (e) {
+        expect(e.data).to.eql('datadata');
+      };
+
+      // simulate script error
+      jpr._scriptError();
+    });
+
+    it('will not report error if onerror triggered right after onreadystatechange (IE9)', function (done) {
+      JsonpReceiver.scriptErrorTimeout = 100;
+      JsonpReceiver.prototype._createScript = function () {
+        var self = this;
+        // simulate a normal JSONP response
+        setTimeout(function () {
+          self.loadedOkay = true;
+          global[utils.WPrefix][self.id]('datadata');
+        }, 100);
+      };
+
+      var jpr = new JsonpReceiver('test');
+      jpr.onclose = function (e) {
+        expect(e.reason).to.eql('network');
+        done();
+      };
+      jpr.onmessage = function (e) {
+        expect(e.data).to.eql('datadata');
+      };
+
+      // simulate script error
+      setTimeout(function () {
+        jpr._scriptError();  
+      }, 150);
+    });
+  });
+});

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/sockjs-client.git



More information about the Pkg-javascript-commits mailing list