From 0cdcd97e5dbf91cd71af2f329a847fecc8f834f5 Mon Sep 17 00:00:00 2001 From: scottinet Date: Fri, 25 Oct 2019 15:55:41 +0200 Subject: [PATCH 1/3] [protocol] do not try to reconnect if the browser is offline --- package-lock.json | 144 ++++++++++++++++------------- package.json | 1 + src/protocols/abstract/realtime.js | 23 ++++- test/mocks/window.mock.js | 36 ++++++++ test/protocol/socketio.test.js | 14 ++- test/protocol/websocket.test.js | 71 ++++++++++++-- 6 files changed, 204 insertions(+), 85 deletions(-) create mode 100644 test/mocks/window.mock.js diff --git a/package-lock.json b/package-lock.json index 59851a256..d3c091af6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1163,7 +1163,7 @@ }, "ansi-styles": { "version": "2.2.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, @@ -1213,7 +1213,7 @@ }, "argv": { "version": "0.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz", "integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=", "dev": true }, @@ -1962,13 +1962,13 @@ }, "commander": { "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, "commondir": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, "component-emitter": { @@ -1978,7 +1978,7 @@ }, "concat-map": { "version": "0.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { @@ -2055,7 +2055,7 @@ }, "core-util-is": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cp-file": { @@ -2228,7 +2228,7 @@ }, "deep-is": { "version": "0.1.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, @@ -2404,7 +2404,7 @@ }, "emojis-list": { "version": "2.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" }, "end-of-stream": { @@ -2531,7 +2531,7 @@ }, "escape-string-regexp": { "version": "1.0.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { @@ -2847,7 +2847,7 @@ }, "esutils": { "version": "2.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" }, "events": { @@ -3038,7 +3038,7 @@ }, "fast-levenshtein": { "version": "2.0.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, @@ -3068,7 +3068,7 @@ }, "fill-keys": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", "dev": true, "requires": { @@ -3216,7 +3216,7 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { @@ -3808,9 +3808,9 @@ "dev": true }, "handlebars": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", - "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.5.tgz", + "integrity": "sha512-0Ce31oWVB7YidkaTq33ZxEbN+UDxMMgThvCe8ptgQViymL5DPis9uLdTA13MiRPhgvqyxIegugrP97iK3JeBHg==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -3838,7 +3838,7 @@ }, "has-ansi": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { @@ -3939,9 +3939,9 @@ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, "https-proxy-agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", - "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.3.tgz", + "integrity": "sha512-Ytgnz23gm2DVftnzqRRz2dOXZbGd2uiajSw/95bPp6v53zPRspQjLm/AfBgqbJ2qfeRXWIOMVLpp86+/5yX39Q==", "dev": true, "requires": { "agent-base": "^4.3.0", @@ -4029,7 +4029,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { "once": "^1.3.0", @@ -4038,7 +4038,7 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "inquirer": { @@ -4262,7 +4262,7 @@ }, "is-object": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", "dev": true }, @@ -4547,7 +4547,7 @@ }, "levn": { "version": "0.3.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { @@ -4679,7 +4679,7 @@ "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "requires": { "chalk": "^2.0.1" }, @@ -4687,7 +4687,7 @@ "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { "color-convert": "^1.9.0" } @@ -4713,9 +4713,9 @@ } }, "lolex": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", - "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.1.tgz", + "integrity": "sha512-dEwHz1CJ8DsdgfpiimgQQEhEJYOEiJ69a0s4aJDNHajaTqOJuF34vBAWVa/sS0V8aQvt72p+KgQ3pRmEVJM+iA==", "dev": true }, "loose-envify": { @@ -4818,7 +4818,7 @@ }, "merge-descriptors": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", "dev": true }, @@ -4898,7 +4898,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mississippi": { @@ -4939,7 +4939,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -5024,7 +5024,7 @@ }, "module-not-found-error": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", "dev": true }, @@ -5127,6 +5127,14 @@ "just-extend": "^4.0.2", "lolex": "^4.1.0", "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "lolex": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", + "dev": true + } } }, "no-case": { @@ -5396,7 +5404,7 @@ }, "once": { "version": "1.4.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" @@ -5430,7 +5438,7 @@ }, "optionator": { "version": "0.8.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { @@ -5669,7 +5677,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { @@ -5742,13 +5750,13 @@ }, "pinkie": { "version": "2.0.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true }, "pinkie-promise": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { @@ -5776,7 +5784,7 @@ }, "prelude-ls": { "version": "1.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, @@ -5937,7 +5945,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -6135,7 +6143,7 @@ "dependencies": { "acorn-jsx": { "version": "3.0.1", - "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { @@ -6144,7 +6152,7 @@ "dependencies": { "acorn": { "version": "3.3.0", - "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true } @@ -6204,7 +6212,7 @@ }, "eslint": { "version": "4.19.1", - "resolved": "http://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, "requires": { @@ -6568,7 +6576,7 @@ "should-equal": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", - "integrity": "sha1-YHLPgwRzYIZ+aOmLCdcRQ9BO4MM=", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", "dev": true, "requires": { "should-type": "^1.4.0" @@ -6576,7 +6584,7 @@ }, "should-format": { "version": "3.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", "dev": true, "requires": { @@ -6587,19 +6595,19 @@ "should-sinon": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/should-sinon/-/should-sinon-0.0.6.tgz", - "integrity": "sha1-vgQafJKPRKycz13AQtAyYYzin4Q=", + "integrity": "sha512-ScBOH5uW5QVFaONmUnIXANSR6z5B8IKzEmBP3HE5sPOCDuZ88oTMdUdnKoCVQdLcCIrRrhRLPS5YT+7H40a04g==", "dev": true }, "should-type": { "version": "1.4.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", "dev": true }, "should-type-adaptors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", - "integrity": "sha1-QB5/M7VTMDOUTVzYvytlAneS4no=", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", "dev": true, "requires": { "should-type": "^1.3.0", @@ -6608,13 +6616,13 @@ }, "should-util": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.0.tgz", "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=", "dev": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "sinon": { @@ -6632,6 +6640,12 @@ "supports-color": "^5.5.0" }, "dependencies": { + "lolex": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", + "dev": true + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -7020,7 +7034,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { @@ -7047,7 +7061,7 @@ }, "supports-color": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, @@ -7210,7 +7224,7 @@ }, "text-table": { "version": "0.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, @@ -7339,7 +7353,7 @@ }, "type-check": { "version": "0.3.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { @@ -7349,7 +7363,7 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw=", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, "typedarray": { @@ -7358,20 +7372,20 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "uglify-js": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", - "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.4.tgz", + "integrity": "sha512-9Yc2i881pF4BPGhjteCXQNaXx1DCwm3dtOyBaG2hitHjLWOczw/ki8vD1bqyT3u6K0Ms/FpCShkmfg+FtlOfYA==", "dev": true, "optional": true, "requires": { - "commander": "~2.20.0", + "commander": "~2.20.3", "source-map": "~0.6.1" }, "dependencies": { "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, "optional": true }, @@ -7513,7 +7527,7 @@ }, "urlgrey": { "version": "0.4.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz", "integrity": "sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8=", "dev": true }, @@ -7696,7 +7710,7 @@ }, "wordwrap": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, @@ -7742,7 +7756,7 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { diff --git a/package.json b/package.json index 495cdd606..10908c09e 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "eslint": "^5.16.0", "eslint-friendly-formatter": "^4.0.1", "eslint-loader": "^2.2.1", + "lolex": "^5.1.1", "mocha": "6.2.0", "mock-require": "^3.0.3", "nyc": "^14.1.1", diff --git a/src/protocols/abstract/realtime.js b/src/protocols/abstract/realtime.js index 30d9203de..e1c6d0d6a 100644 --- a/src/protocols/abstract/realtime.js +++ b/src/protocols/abstract/realtime.js @@ -4,7 +4,6 @@ const KuzzleAbstractProtocol = require('./common'); class RTWrapper extends KuzzleAbstractProtocol { - constructor (host, options = {}) { super(host, options); @@ -52,7 +51,7 @@ class RTWrapper extends KuzzleAbstractProtocol { * * @param {Error} error */ - clientNetworkError(error) { + clientNetworkError (error) { this.state = 'offline'; this.clear(); @@ -60,19 +59,35 @@ class RTWrapper extends KuzzleAbstractProtocol { connectionError.internal = error; this.emit('networkError', connectionError); + if (this.autoReconnect && !this.retrying && !this.stopRetryingToConnect) { this.retrying = true; + if ( typeof window === 'object' + && typeof window.navigator === 'object' + && window.navigator.onLine === false + ) { + window.addEventListener( + 'online', + () => { + this.retrying = false; + this.connect(this.host).catch(err => this.clientNetworkError(err)); + }, + { once: true }); + return; + } + setTimeout(() => { this.retrying = false; this.connect(this.host).catch(err => this.clientNetworkError(err)); }, this.reconnectionDelay); - } else { + } + else { this.emit('disconnect'); } } - isReady() { + isReady () { return this.state === 'connected'; } } diff --git a/test/mocks/window.mock.js b/test/mocks/window.mock.js new file mode 100644 index 000000000..b1bd8f5ea --- /dev/null +++ b/test/mocks/window.mock.js @@ -0,0 +1,36 @@ +const + sinon = require('sinon'), + KuzzleEventEmitter = require('../../src/eventEmitter'); + +// A class to mock the global window object +class WindowMock extends KuzzleEventEmitter { + constructor () { + super(); + + if (typeof window !== 'undefined') { + throw new Error('Cannot mock add a global "window" object: already defined'); + } + + this.navigator = { + onLine: true + }; + + this.addEventListener = this.addListener; + sinon.spy(this, 'addEventListener'); + } + + static restore () { + delete global.window; + } + + static inject () { + Object.defineProperty(global, 'window', { + value: new this(), + enumerable: false, + writable: false, + configurable: true + }); + } +} + +module.exports = WindowMock; diff --git a/test/protocol/socketio.test.js b/test/protocol/socketio.test.js index 33dceb257..5ea75c8ed 100644 --- a/test/protocol/socketio.test.js +++ b/test/protocol/socketio.test.js @@ -1,11 +1,8 @@ const should = require('should'), sinon = require('sinon'), - SocketIO = require('../../src/protocols/socketio'); - -/** - * @global window - */ + SocketIO = require('../../src/protocols/socketio'), + windowMock = require('../mocks/window.mock'); describe('SocketIO networking module', () => { let @@ -15,6 +12,7 @@ describe('SocketIO networking module', () => { beforeEach(() => { clock = sinon.useFakeTimers(); + socketStub = { events: {}, eventOnce: {}, @@ -74,11 +72,13 @@ describe('SocketIO networking module', () => { }); socketIO.socket = socketStub; - window = {io: sinon.stub().returns(socketStub)}; // eslint-disable-line + windowMock.inject(); + window.io = sinon.stub().returns(socketStub); }); afterEach(() => { clock.restore(); + windowMock.restore(); }); it('should expose an unique identifier', () => { @@ -225,8 +225,6 @@ describe('SocketIO exposed methods', () => { socketIO = new SocketIO('address'); socketIO.socket = socketStub; - - window = {io: sinon.stub().returns(socketStub)}; // eslint-disable-line }); it('should be able to listen to an event just once', () => { diff --git a/test/protocol/websocket.test.js b/test/protocol/websocket.test.js index 84f5ac9f6..0bf8adb02 100644 --- a/test/protocol/websocket.test.js +++ b/test/protocol/websocket.test.js @@ -1,8 +1,10 @@ const should = require('should'), sinon = require('sinon'), + lolex = require('lolex'), NodeWS = require('ws'), - WS = require('../../src/protocols/websocket'); + WS = require('../../src/protocols/websocket'), + windowMock = require('../mocks/window.mock'); describe('WebSocket networking module', () => { let @@ -12,13 +14,13 @@ describe('WebSocket networking module', () => { clientStub; beforeEach(() => { - clock = sinon.useFakeTimers(); + clock = lolex.install(); clientStub = { send: sinon.stub(), close: sinon.stub() }; - window = 'foobar'; // eslint-disable-line + windowMock.inject(); WebSocket = function (...args) { // eslint-disable-line wsargs = args; return clientStub; @@ -32,9 +34,9 @@ describe('WebSocket networking module', () => { }); afterEach(() => { - clock.restore(); + clock.uninstall(); WebSocket = undefined; // eslint-disable-line - window = undefined; // eslint-disable-line + windowMock.restore(); }); it('should expose an unique identifier', () => { @@ -156,6 +158,59 @@ describe('WebSocket networking module', () => { return should(promise).be.rejectedWith('foobar'); }); + it('should stop reconnecting if the browser goes offline', () => { + const cb = sinon.stub(); + + websocket.retrying = false; + websocket.addListener('networkError', cb); + should(websocket.listeners('networkError').length).be.eql(1); + + websocket.connect(); + websocket.connect = sinon.stub().rejects(); + clientStub.onopen(); + clientStub.onerror(); + + should(websocket.retrying).be.true(); + should(cb).be.calledOnce(); + should(websocket.connect).not.be.called(); + + window.navigator.onLine = false; + + return clock.tickAsync(100) + .then(() => { + should(websocket.retrying).be.true(); + should(cb).be.calledTwice(); + should(websocket.connect).be.calledOnce(); + + should(window.addEventListener).calledWith( + 'online', + sinon.match.func, + { once: true }); + + return clock.tickAsync(100); + }) + .then(() => { + // the important bit is there: cb hasn't been called since the last + // tick because the SDK does not try to connect if the browser is + // marked offline + should(cb).be.calledTwice(); + + should(websocket.retrying).be.true(); + should(websocket.connect).be.calledOnce(); + + window.emit('online'); + return clock.tickAsync(100); + }) + .then(() => { + // And it started retrying to connect again now that the browser is + // "online" + should(cb).be.calledThrice(); + + should(websocket.retrying).be.true(); + should(websocket.connect).be.calledTwice(); + }); + }); + it('should call listeners on a "disconnect" event', () => { const cb = sinon.stub(); @@ -371,7 +426,7 @@ describe('WebSocket networking module', () => { it('should fallback to the ws module if there is no global WebSocket API', () => { WebSocket = undefined; // eslint-disable-line - window = undefined; // eslint-disable-line + windowMock.restore(); const client = new WS('foobar'); @@ -391,7 +446,7 @@ describe('WebSocket networking module', () => { it('should initialize pass allowed options to the ws ctor when using it', () => { WebSocket = undefined; // eslint-disable-line - window = undefined; // eslint-disable-line + windowMock.restore(); let client = new WS('foobar'); @@ -413,7 +468,7 @@ describe('WebSocket networking module', () => { it('should throw if invalid options are provided', () => { WebSocket = undefined; // eslint-disable-line - window = undefined; // eslint-disable-line + windowMock.restore(); const invalidHeaders = ['foo', 'false', 'true', 123, []]; From d86f08e9d8a0b9745ba9e424e395518be62abc0b Mon Sep 17 00:00:00 2001 From: scottinet Date: Mon, 4 Nov 2019 11:57:25 +0100 Subject: [PATCH 2/3] [fix] remove useless parameter passed to this.connect --- src/protocols/abstract/realtime.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/abstract/realtime.js b/src/protocols/abstract/realtime.js index e1c6d0d6a..08d499dac 100644 --- a/src/protocols/abstract/realtime.js +++ b/src/protocols/abstract/realtime.js @@ -71,7 +71,7 @@ class RTWrapper extends KuzzleAbstractProtocol { 'online', () => { this.retrying = false; - this.connect(this.host).catch(err => this.clientNetworkError(err)); + this.connect().catch(err => this.clientNetworkError(err)); }, { once: true }); return; @@ -79,7 +79,7 @@ class RTWrapper extends KuzzleAbstractProtocol { setTimeout(() => { this.retrying = false; - this.connect(this.host).catch(err => this.clientNetworkError(err)); + this.connect().catch(err => this.clientNetworkError(err)); }, this.reconnectionDelay); } else { From 56b6c224775983284ca83f06749b9e2e5bdb161e Mon Sep 17 00:00:00 2001 From: scottinet Date: Mon, 4 Nov 2019 16:25:36 +0100 Subject: [PATCH 3/3] [codecov] disable patch and change reports --- codecov.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/codecov.yml b/codecov.yml index 6da146875..a4d6a68dc 100644 --- a/codecov.yml +++ b/codecov.yml @@ -6,7 +6,5 @@ coverage: default: threshold: 1 - patch: - default: - branches: - - master \ No newline at end of file + patch: false + changes: false