mirror of
https://github.com/socketio/socket.io.git
synced 2026-01-10 23:48:02 -05:00
ci: migrate from zuul to webdriver.io
zuul is now archived [1] and does not support the new W3C WebDriver protocol, since it relies on the wd package [2] under the hood, which uses the (now deprecated) JSON Wire Protocol. We will now use the webdriver.io test framework, which allows to run our tests in local and on Sauce Labs (cross-browser and mobile tests). This allows us to run our tests on latest versions of Android and iOS, since Sauce Labs only supports the W3C WebDriver protocol for these platforms ([3]). [1]: https://github.com/defunctzombie/zuul [2]: https://github.com/admc/wd [3]: https://docs.saucelabs.com/dev/w3c-webdriver-capabilities/
This commit is contained in:
38
.github/workflows/ci.yml
vendored
38
.github/workflows/ci.yml
vendored
@@ -6,40 +6,52 @@ on:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test-node:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14, 16]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
env:
|
||||
CI: true
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run tests
|
||||
run: npm test
|
||||
|
||||
test-browser:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js 16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '10.x'
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
node-version: 16
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run tests
|
||||
run: npm test
|
||||
env:
|
||||
CI: true
|
||||
BROWSERS: 1
|
||||
NGROK_AUTH_TOKEN: ${{ secrets.NGROK_AUTH_TOKEN }}
|
||||
SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
|
||||
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
|
||||
timeout-minutes: 20
|
||||
|
||||
3
babel.config.js
Normal file
3
babel.config.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: [["@babel/preset-env"]],
|
||||
};
|
||||
27545
package-lock.json
generated
27545
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
@@ -41,6 +41,7 @@
|
||||
"@babel/core": "^7.15.0",
|
||||
"@babel/plugin-transform-object-assign": "^7.14.5",
|
||||
"@babel/preset-env": "^7.15.0",
|
||||
"@babel/register": "^7.18.9",
|
||||
"@rollup/plugin-alias": "^3.1.5",
|
||||
"@rollup/plugin-babel": "^5.3.0",
|
||||
"@rollup/plugin-commonjs": "^21.0.0",
|
||||
@@ -49,42 +50,39 @@
|
||||
"@types/mocha": "^9.0.0",
|
||||
"@types/node": "^16.7.6",
|
||||
"@types/sinonjs__fake-timers": "^6.0.3",
|
||||
"@wdio/cli": "^7.26.0",
|
||||
"@wdio/local-runner": "^7.26.0",
|
||||
"@wdio/mocha-framework": "^7.26.0",
|
||||
"@wdio/sauce-service": "^7.26.0",
|
||||
"@wdio/spec-reporter": "^7.26.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.1.0",
|
||||
"babel-preset-es2015": "6.24.1",
|
||||
"base64-arraybuffer": "^0.1.5",
|
||||
"expect.js": "0.3.1",
|
||||
"has-cors": "^1.1.0",
|
||||
"istanbul": "^0.4.5",
|
||||
"mocha": "^3.3.0",
|
||||
"mocha": "^10.1.0",
|
||||
"prettier": "^2.3.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "^2.58.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"socket.io": "3.0.0",
|
||||
"socket.io-browsers": "^1.0.0",
|
||||
"socket.io": "^4.5.3",
|
||||
"socket.io-msgpack-parser": "^3.0.0",
|
||||
"text-blob-builder": "0.0.1",
|
||||
"ts-loader": "^8.3.0",
|
||||
"ts-node": "^10.2.1",
|
||||
"tsd": "^0.17.0",
|
||||
"typescript": "^4.4.2",
|
||||
"webpack": "^4.44.2",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"webpack-remove-debug": "^0.1.0",
|
||||
"zuul": "~3.11.1",
|
||||
"zuul-builder-webpack": "^1.2.0",
|
||||
"zuul-ngrok": "4.0.0"
|
||||
"typescript": "^4.4.2"
|
||||
},
|
||||
"scripts": {
|
||||
"compile": "rimraf ./build && tsc && tsc -p tsconfig.esm.json && ./postcompile.sh",
|
||||
"test": "npm run format:check && npm run compile && if test \"$BROWSERS\" = \"1\" ; then npm run test:browser; else npm run test:node; fi",
|
||||
"test:node": "mocha --require ts-node/register --reporter dot --require test/support/server.js test/index.js",
|
||||
"test:browser": "zuul test/index.js",
|
||||
"test:node": "mocha --require ts-node/register --reporter dot --require test/support/hooks.ts --timeout 5000 --exit test/index.ts",
|
||||
"test:browser": "ts-node test/browser-runner.ts",
|
||||
"test:types": "tsd",
|
||||
"build": "rollup -c support/rollup.config.umd.js && rollup -c support/rollup.config.esm.js && rollup -c support/rollup.config.umd.msgpack.js",
|
||||
"format:check": "prettier --check \"lib/**/*.ts\" \"test/**/*.js\" \"test/**/*.ts\" \"support/**/*.js\"",
|
||||
"format:fix": "prettier --write \"lib/**/*.ts\" \"test/**/*.js\" \"test/**/*.ts\" \"support/**/*.js\"",
|
||||
"format:check": "prettier --check \"*.js\" \"lib/**/*.ts\" \"test/**/*.ts\" \"support/**/*.js\"",
|
||||
"format:fix": "prettier --write \"*.js\" \"lib/**/*.ts\" \"test/**/*.ts\" \"support/**/*.js\"",
|
||||
"prepack": "npm run compile"
|
||||
},
|
||||
"contributors": [
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
const { NormalModuleReplacementPlugin } = require("webpack");
|
||||
const config = require("./prod.config");
|
||||
|
||||
module.exports = {
|
||||
...config,
|
||||
output: {
|
||||
...config.output,
|
||||
filename: "socket.io.msgpack.min.js",
|
||||
},
|
||||
plugins: [
|
||||
...config.plugins,
|
||||
new NormalModuleReplacementPlugin(
|
||||
/^socket.io-parser$/,
|
||||
"socket.io-msgpack-parser"
|
||||
),
|
||||
],
|
||||
};
|
||||
@@ -1,19 +0,0 @@
|
||||
const config = require("./webpack.config");
|
||||
|
||||
module.exports = {
|
||||
...config,
|
||||
output: {
|
||||
...config.output,
|
||||
filename: "socket.io.min.js",
|
||||
},
|
||||
mode: "production",
|
||||
module: {
|
||||
rules: [
|
||||
...config.module.rules,
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: "webpack-remove-debug",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -1,34 +0,0 @@
|
||||
const { BannerPlugin } = require("webpack");
|
||||
const version = require("../package.json").version;
|
||||
|
||||
const banner = `Socket.IO v${version}
|
||||
(c) 2014-${new Date().getFullYear()} Guillermo Rauch
|
||||
Released under the MIT License.`;
|
||||
|
||||
module.exports = {
|
||||
entry: "./build/esm/index.js",
|
||||
output: {
|
||||
filename: "socket.io.js",
|
||||
library: "io",
|
||||
libraryTarget: "umd",
|
||||
globalObject: "self",
|
||||
},
|
||||
mode: "development",
|
||||
devtool: "source-map",
|
||||
node: false,
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.m?js$/,
|
||||
use: {
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
presets: ["@babel/preset-env"],
|
||||
plugins: ["@babel/plugin-transform-object-assign"],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [new BannerPlugin(banner)],
|
||||
};
|
||||
19
test/browser-runner.ts
Normal file
19
test/browser-runner.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import Launcher from "@wdio/cli";
|
||||
import { createServer } from "./support/server";
|
||||
|
||||
const launcher = new Launcher("./wdio.conf.js");
|
||||
|
||||
async function run() {
|
||||
const server = createServer();
|
||||
|
||||
try {
|
||||
const exitCode = await launcher.run();
|
||||
server.close();
|
||||
process.exit(exitCode);
|
||||
} catch (e) {
|
||||
console.error("Launcher failed to start the test", e.stacktrace);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
1150
test/connection.ts
1150
test/connection.ts
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
||||
const { browser } = require("./support/env");
|
||||
|
||||
// whitelist some globals to avoid warnings
|
||||
if (browser) {
|
||||
window.mocha.globals(["___eio", "eio_iframe_*"]);
|
||||
} else {
|
||||
require("./node.ts");
|
||||
}
|
||||
|
||||
require("./url.ts");
|
||||
|
||||
// browser only tests
|
||||
require("./connection.ts");
|
||||
require("./socket.ts");
|
||||
4
test/index.ts
Normal file
4
test/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import "./url";
|
||||
import "./connection";
|
||||
import "./socket";
|
||||
import "./node";
|
||||
@@ -1,7 +1,13 @@
|
||||
const path = require("path");
|
||||
const { exec } = require("child_process");
|
||||
|
||||
describe("autoRef option", () => {
|
||||
describe("autoUnref option", function () {
|
||||
before(function () {
|
||||
if (process.env.WDIO_WORKER !== undefined) {
|
||||
return this.skip();
|
||||
}
|
||||
});
|
||||
|
||||
const fixture = (filename) =>
|
||||
process.execPath + " " + path.join(__dirname, "fixtures", filename);
|
||||
|
||||
|
||||
879
test/socket.ts
879
test/socket.ts
@@ -1,457 +1,295 @@
|
||||
import expect from "expect.js";
|
||||
import { io } from "..";
|
||||
import { wrap, BASE_URL, success } from "./support/util";
|
||||
|
||||
const success = (done, socket) => {
|
||||
socket.disconnect();
|
||||
done();
|
||||
};
|
||||
describe("socket", () => {
|
||||
it("should have an accessible socket id equal to the server-side socket id (default namespace)", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL, { forceNew: true });
|
||||
|
||||
describe("socket", function () {
|
||||
this.timeout(70000);
|
||||
|
||||
it("should have an accessible socket id equal to the server-side socket id (default namespace)", (done) => {
|
||||
const socket = io({ forceNew: true });
|
||||
|
||||
socket.emit("getId", (id) => {
|
||||
expect(socket.id).to.be.ok();
|
||||
expect(socket.id).to.be.eql(id);
|
||||
expect(socket.id).to.not.eql(socket.io.engine.id);
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should have an accessible socket id equal to the server-side socket id (custom namespace)", (done) => {
|
||||
const socket = io("/foo", { forceNew: true });
|
||||
socket.emit("getId", (id) => {
|
||||
expect(socket.id).to.be.ok();
|
||||
expect(socket.id).to.be.eql(id);
|
||||
expect(socket.id).to.not.eql(socket.io.engine.id);
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("clears socket.id upon disconnection", (done) => {
|
||||
const socket = io({ forceNew: true });
|
||||
socket.on("connect", () => {
|
||||
socket.on("disconnect", () => {
|
||||
expect(socket.id).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
|
||||
socket.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
it("doesn't fire an error event if we force disconnect in opening state", (done) => {
|
||||
const socket = io({ forceNew: true, timeout: 100 });
|
||||
socket.disconnect();
|
||||
socket.io.on("error", () => {
|
||||
throw new Error("Unexpected");
|
||||
});
|
||||
setTimeout(() => {
|
||||
done();
|
||||
}, 300);
|
||||
});
|
||||
|
||||
it("fire a connect_error event when the connection cannot be established", (done) => {
|
||||
const socket = io("http://localhost:9823", {
|
||||
forceNew: true,
|
||||
timeout: 100,
|
||||
});
|
||||
socket.on("connect_error", () => {
|
||||
socket.close();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("doesn't fire a connect_error event when the connection is already established", (done) => {
|
||||
const socket = io({ forceNew: true });
|
||||
socket.on("connect", () => {
|
||||
socket.io.engine.close();
|
||||
});
|
||||
socket.on("connect_error", () => {
|
||||
done(new Error("should not happen"));
|
||||
});
|
||||
setTimeout(() => {
|
||||
socket.close();
|
||||
done();
|
||||
}, 300);
|
||||
});
|
||||
|
||||
it("should change socket.id upon reconnection", (done) => {
|
||||
const socket = io({ forceNew: true });
|
||||
socket.on("connect", () => {
|
||||
const id = socket.id;
|
||||
|
||||
socket.io.on("reconnect_attempt", () => {
|
||||
expect(socket.id).to.not.be.ok();
|
||||
});
|
||||
|
||||
socket.io.on("reconnect", () => {
|
||||
expect(socket.id).to.not.eql(id);
|
||||
socket.emit("getId", (id) => {
|
||||
expect(socket.id).to.be.ok();
|
||||
expect(socket.id).to.be.eql(id);
|
||||
expect(socket.id).to.not.eql(socket.io.engine.id);
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
|
||||
socket.io.engine.close();
|
||||
});
|
||||
});
|
||||
|
||||
it("should enable compression by default", (done) => {
|
||||
const socket = io({ forceNew: true });
|
||||
socket.on("connect", () => {
|
||||
socket.io.engine.once("packetCreate", (packet) => {
|
||||
expect(packet.options.compress).to.be(true);
|
||||
it("should have an accessible socket id equal to the server-side socket id (custom namespace)", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/foo", { forceNew: true });
|
||||
socket.emit("getId", (id) => {
|
||||
expect(socket.id).to.be.ok();
|
||||
expect(socket.id).to.be.eql(id);
|
||||
expect(socket.id).to.not.eql(socket.io.engine.id);
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
socket.emit("hi");
|
||||
});
|
||||
});
|
||||
|
||||
it("should disable compression", (done) => {
|
||||
const socket = io({ forceNew: true });
|
||||
socket.on("connect", () => {
|
||||
socket.io.engine.once("packetCreate", (packet) => {
|
||||
expect(packet.options.compress).to.be(false);
|
||||
it("clears socket.id upon disconnection", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL, { forceNew: true });
|
||||
socket.on("connect", () => {
|
||||
socket.on("disconnect", () => {
|
||||
expect(socket.id).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
|
||||
socket.disconnect();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("doesn't fire an error event if we force disconnect in opening state", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL, { forceNew: true, timeout: 100 });
|
||||
socket.disconnect();
|
||||
socket.io.on("error", () => {
|
||||
throw new Error("Unexpected");
|
||||
});
|
||||
setTimeout(() => {
|
||||
done();
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
|
||||
it("fire a connect_error event when the connection cannot be established", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io("http://localhost:9823", {
|
||||
forceNew: true,
|
||||
timeout: 100,
|
||||
});
|
||||
socket.on("connect_error", () => {
|
||||
socket.close();
|
||||
done();
|
||||
});
|
||||
socket.compress(false).emit("hi");
|
||||
});
|
||||
});
|
||||
|
||||
it("doesn't fire a connect_error event when the connection is already established", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL, { forceNew: true });
|
||||
socket.on("connect", () => {
|
||||
socket.io.engine.close();
|
||||
});
|
||||
socket.on("connect_error", () => {
|
||||
done(new Error("should not happen"));
|
||||
});
|
||||
setTimeout(() => {
|
||||
socket.close();
|
||||
done();
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
|
||||
it("should change socket.id upon reconnection", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL, { forceNew: true });
|
||||
socket.on("connect", () => {
|
||||
const id = socket.id;
|
||||
|
||||
socket.io.on("reconnect_attempt", () => {
|
||||
expect(socket.id).to.not.be.ok();
|
||||
});
|
||||
|
||||
socket.io.on("reconnect", () => {
|
||||
expect(socket.id).to.not.eql(id);
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
|
||||
socket.io.engine.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should enable compression by default", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL, { forceNew: true });
|
||||
socket.on("connect", () => {
|
||||
socket.io.engine.once("packetCreate", (packet) => {
|
||||
expect(packet.options.compress).to.be(true);
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
socket.emit("hi");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should disable compression", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL, { forceNew: true });
|
||||
socket.on("connect", () => {
|
||||
socket.io.engine.once("packetCreate", (packet) => {
|
||||
expect(packet.options.compress).to.be(false);
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
socket.compress(false).emit("hi");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("query option", () => {
|
||||
it("should accept an object (default namespace)", (done) => {
|
||||
const socket = io("/", { forceNew: true, query: { e: "f" } });
|
||||
it("should accept an object (default namespace)", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/", {
|
||||
forceNew: true,
|
||||
query: { e: "f" },
|
||||
});
|
||||
|
||||
socket.emit("getHandshake", (handshake) => {
|
||||
expect(handshake.query.e).to.be("f");
|
||||
socket.disconnect();
|
||||
done();
|
||||
socket.emit("getHandshake", (handshake) => {
|
||||
expect(handshake.query.e).to.be("f");
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should accept a query string (default namespace)", (done) => {
|
||||
const socket = io("/?c=d", { forceNew: true });
|
||||
it("should accept a query string (default namespace)", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/?c=d", { forceNew: true });
|
||||
|
||||
socket.emit("getHandshake", (handshake) => {
|
||||
expect(handshake.query.c).to.be("d");
|
||||
socket.disconnect();
|
||||
done();
|
||||
socket.emit("getHandshake", (handshake) => {
|
||||
expect(handshake.query.c).to.be("d");
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should accept an object", (done) => {
|
||||
const socket = io("/abc", { forceNew: true, query: { a: "b" } });
|
||||
it("should accept an object", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/abc", {
|
||||
forceNew: true,
|
||||
query: { a: "b" },
|
||||
});
|
||||
|
||||
socket.on("handshake", (handshake) => {
|
||||
expect(handshake.query.a).to.be("b");
|
||||
socket.disconnect();
|
||||
done();
|
||||
socket.on("handshake", (handshake) => {
|
||||
expect(handshake.query.a).to.be("b");
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should accept a query string", (done) => {
|
||||
const socket = io("/abc?b=c&d=e", { forceNew: true });
|
||||
it("should accept a query string", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/abc?b=c&d=e", { forceNew: true });
|
||||
|
||||
socket.on("handshake", (handshake) => {
|
||||
expect(handshake.query.b).to.be("c");
|
||||
expect(handshake.query.d).to.be("e");
|
||||
socket.disconnect();
|
||||
done();
|
||||
socket.on("handshake", (handshake) => {
|
||||
expect(handshake.query.b).to.be("c");
|
||||
expect(handshake.query.d).to.be("e");
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should properly encode the parameters", (done) => {
|
||||
const socket = io("/abc", { forceNew: true, query: { "&a": "&=?a" } });
|
||||
it("should properly encode the parameters", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/abc", {
|
||||
forceNew: true,
|
||||
query: { "&a": "&=?a" },
|
||||
});
|
||||
|
||||
socket.on("handshake", (handshake) => {
|
||||
expect(handshake.query["&a"]).to.be("&=?a");
|
||||
socket.disconnect();
|
||||
done();
|
||||
socket.on("handshake", (handshake) => {
|
||||
expect(handshake.query["&a"]).to.be("&=?a");
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("auth option", () => {
|
||||
it("should accept an object", (done) => {
|
||||
const socket = io("/abc", { forceNew: true, auth: { a: "b", c: "d" } });
|
||||
it("should accept an object", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/abc", {
|
||||
forceNew: true,
|
||||
auth: { a: "b", c: "d" },
|
||||
});
|
||||
|
||||
socket.on("handshake", (handshake) => {
|
||||
expect(handshake.auth.a).to.be("b");
|
||||
expect(handshake.auth.c).to.be("d");
|
||||
expect(handshake.query.a).to.be(undefined);
|
||||
socket.on("handshake", (handshake) => {
|
||||
expect(handshake.auth.a).to.be("b");
|
||||
expect(handshake.auth.c).to.be("d");
|
||||
expect(handshake.query.a).to.be(undefined);
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should accept an function", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/abc", {
|
||||
forceNew: true,
|
||||
auth: (cb) => cb({ e: "f" }),
|
||||
});
|
||||
|
||||
socket.on("handshake", (handshake) => {
|
||||
expect(handshake.auth.e).to.be("f");
|
||||
expect(handshake.query.e).to.be(undefined);
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should fire an error event on middleware failure from custom namespace", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/no", { forceNew: true });
|
||||
socket.on("connect_error", (err) => {
|
||||
expect(err).to.be.an(Error);
|
||||
expect(err.message).to.eql("Auth failed (custom namespace)");
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should accept an function", (done) => {
|
||||
const socket = io("/abc", {
|
||||
it("should not try to reconnect after a middleware failure", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/no", {
|
||||
forceNew: true,
|
||||
auth: (cb) => cb({ e: "f" }),
|
||||
reconnectionDelay: 10,
|
||||
});
|
||||
|
||||
socket.on("handshake", (handshake) => {
|
||||
expect(handshake.auth.e).to.be("f");
|
||||
expect(handshake.query.e).to.be(undefined);
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should fire an error event on middleware failure from custom namespace", (done) => {
|
||||
const socket = io("/no", { forceNew: true });
|
||||
socket.on("connect_error", (err) => {
|
||||
expect(err).to.be.an(Error);
|
||||
expect(err.message).to.eql("Auth failed (custom namespace)");
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should not try to reconnect after a middleware failure", (done) => {
|
||||
const socket = io("/no", { forceNew: true, reconnectionDelay: 10 });
|
||||
|
||||
let count = 0;
|
||||
|
||||
socket.on("connect_error", () => {
|
||||
count++;
|
||||
// force reconnection
|
||||
socket.io.engine.close();
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(count).to.eql(1);
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
it("should properly disconnect then reconnect", (done) => {
|
||||
const socket = io("/", { forceNew: true, transports: ["websocket"] });
|
||||
|
||||
let count = 0;
|
||||
|
||||
socket.once("connect", () => {
|
||||
socket.disconnect().connect();
|
||||
});
|
||||
|
||||
socket.on("disconnect", () => {
|
||||
count++;
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(count).to.eql(1);
|
||||
success(done, socket);
|
||||
}, 200);
|
||||
});
|
||||
|
||||
it("should throw on reserved event", () => {
|
||||
const socket = io("/no", { forceNew: true });
|
||||
|
||||
expect(() => socket.emit("disconnecting", "goodbye")).to.throwException(
|
||||
/"disconnecting" is a reserved event name/
|
||||
);
|
||||
});
|
||||
|
||||
it("should emit events in order", (done) => {
|
||||
const socket = io("/", { autoConnect: false });
|
||||
let i = 0;
|
||||
|
||||
socket.on("connect", () => {
|
||||
socket.emit("echo", "second", () => {
|
||||
expect(++i).to.eql(2);
|
||||
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
socket.emit("echo", "first", () => {
|
||||
expect(++i).to.eql(1);
|
||||
});
|
||||
|
||||
socket.connect();
|
||||
});
|
||||
|
||||
describe("volatile packets", () => {
|
||||
it("should discard a volatile packet when the socket is not connected", (done) => {
|
||||
const socket = io({ forceNew: true, autoConnect: false });
|
||||
|
||||
socket.volatile.emit("getId", () => {
|
||||
done(new Error("should not happen"));
|
||||
});
|
||||
|
||||
socket.emit("getId", () => {
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
|
||||
socket.connect();
|
||||
});
|
||||
|
||||
it("should discard a volatile packet when the pipe is not ready", (done) => {
|
||||
const socket = io({ forceNew: true });
|
||||
|
||||
socket.on("connect", () => {
|
||||
socket.emit("getId", () => {
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
|
||||
socket.volatile.emit("getId", () => {
|
||||
done(new Error("should not happen"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should send a volatile packet when the socket is connected and the pipe is ready", (done) => {
|
||||
const socket = io({ forceNew: true });
|
||||
|
||||
const interval = setInterval(() => {
|
||||
socket.volatile.emit("getId", () => {
|
||||
clearInterval(interval);
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
}, 200);
|
||||
});
|
||||
});
|
||||
|
||||
describe("onAny", () => {
|
||||
it("should call listener", (done) => {
|
||||
const socket = io("/abc");
|
||||
|
||||
socket.onAny((event, arg1) => {
|
||||
expect(event).to.be("handshake");
|
||||
expect(arg1).to.be.an(Object);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should prepend listener", (done) => {
|
||||
const socket = io("/abc");
|
||||
|
||||
let count = 0;
|
||||
|
||||
socket.onAny((event, arg1) => {
|
||||
expect(count).to.be(2);
|
||||
socket.on("connect_error", () => {
|
||||
count++;
|
||||
// force reconnection
|
||||
socket.io.engine.close();
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(count).to.eql(1);
|
||||
done();
|
||||
});
|
||||
|
||||
socket.prependAny(() => {
|
||||
expect(count++).to.be(1);
|
||||
});
|
||||
|
||||
socket.prependAny(() => {
|
||||
expect(count++).to.be(0);
|
||||
});
|
||||
});
|
||||
|
||||
it("should remove listener", (done) => {
|
||||
const socket = io("/abc");
|
||||
|
||||
let count = 0;
|
||||
|
||||
const fail = () => done(new Error("fail"));
|
||||
|
||||
socket.onAny(fail);
|
||||
socket.offAny(fail);
|
||||
expect(socket.listenersAny.length).to.be(0);
|
||||
|
||||
socket.onAny(() => {
|
||||
done();
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
|
||||
describe("onAnyOutgoing", () => {
|
||||
it("should call listener", (done) => {
|
||||
const socket = io("/abc");
|
||||
|
||||
socket.on("connect", () => {
|
||||
socket.onAnyOutgoing((event, arg1) => {
|
||||
expect(event).to.be("my-event");
|
||||
expect(arg1).to.be("123");
|
||||
|
||||
success(done, socket);
|
||||
});
|
||||
|
||||
socket.emit("my-event", "123");
|
||||
it("should properly disconnect then reconnect", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/", {
|
||||
forceNew: true,
|
||||
transports: ["websocket"],
|
||||
});
|
||||
});
|
||||
|
||||
it("should prepend listener", (done) => {
|
||||
const socket = io("/abc");
|
||||
|
||||
let count = 0;
|
||||
|
||||
socket.onAnyOutgoing(() => {
|
||||
expect(count).to.be(2);
|
||||
|
||||
success(done, socket);
|
||||
socket.once("connect", () => {
|
||||
socket.disconnect().connect();
|
||||
});
|
||||
|
||||
socket.prependAnyOutgoing(() => {
|
||||
expect(count++).to.be(1);
|
||||
});
|
||||
|
||||
socket.prependAnyOutgoing(() => {
|
||||
expect(count++).to.be(0);
|
||||
});
|
||||
|
||||
socket.emit("my-event", "123");
|
||||
});
|
||||
|
||||
it("should remove listener", (done) => {
|
||||
const socket = io("/abc");
|
||||
const fail = () => done(new Error("fail"));
|
||||
|
||||
socket.onAnyOutgoing(fail);
|
||||
socket.offAnyOutgoing(fail);
|
||||
expect(socket.listenersAnyOutgoing.length).to.be(0);
|
||||
|
||||
socket.onAnyOutgoing(() => {
|
||||
success(done, socket);
|
||||
});
|
||||
|
||||
socket.emit("my-event", "123");
|
||||
});
|
||||
});
|
||||
|
||||
describe("timeout", () => {
|
||||
it("should timeout after the given delay when socket is not connected", (done) => {
|
||||
const socket = io("/", {
|
||||
autoConnect: false,
|
||||
});
|
||||
|
||||
socket.timeout(50).emit("event", (err) => {
|
||||
expect(err).to.be.an(Error);
|
||||
expect(socket.sendBuffer).to.be.empty();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should timeout when the server does not acknowledge the event", (done) => {
|
||||
const socket = io("/");
|
||||
|
||||
socket.timeout(50).emit("unknown", (err) => {
|
||||
expect(err).to.be.an(Error);
|
||||
success(done, socket);
|
||||
});
|
||||
});
|
||||
|
||||
it("should timeout when the server does not acknowledge the event in time", (done) => {
|
||||
const socket = io("/");
|
||||
|
||||
let count = 0;
|
||||
|
||||
socket.timeout(0).emit("echo", 42, (err) => {
|
||||
expect(err).to.be.an(Error);
|
||||
socket.on("disconnect", () => {
|
||||
count++;
|
||||
});
|
||||
|
||||
@@ -460,14 +298,267 @@ describe("socket", function () {
|
||||
success(done, socket);
|
||||
}, 200);
|
||||
});
|
||||
});
|
||||
|
||||
it("should not timeout when the server does acknowledge the event", (done) => {
|
||||
const socket = io("/");
|
||||
it("should throw on reserved event", () => {
|
||||
const socket = io(BASE_URL + "/no", { forceNew: true });
|
||||
|
||||
socket.timeout(50).emit("echo", 42, (err, value) => {
|
||||
expect(err).to.be(null);
|
||||
expect(value).to.be(42);
|
||||
success(done, socket);
|
||||
expect(() => socket.emit("disconnecting", "goodbye")).to.throwException(
|
||||
/"disconnecting" is a reserved event name/
|
||||
);
|
||||
});
|
||||
|
||||
it("should emit events in order", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/", { autoConnect: false });
|
||||
let i = 0;
|
||||
|
||||
socket.on("connect", () => {
|
||||
socket.emit("echo", "second", () => {
|
||||
expect(++i).to.eql(2);
|
||||
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
socket.emit("echo", "first", () => {
|
||||
expect(++i).to.eql(1);
|
||||
});
|
||||
|
||||
socket.connect();
|
||||
});
|
||||
});
|
||||
|
||||
describe("volatile packets", () => {
|
||||
it("should discard a volatile packet when the socket is not connected", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL, { forceNew: true, autoConnect: false });
|
||||
|
||||
socket.volatile.emit("getId", () => {
|
||||
done(new Error("should not happen"));
|
||||
});
|
||||
|
||||
socket.emit("getId", () => {
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
|
||||
socket.connect();
|
||||
});
|
||||
});
|
||||
|
||||
it("should discard a volatile packet when the pipe is not ready", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL, { forceNew: true });
|
||||
|
||||
socket.on("connect", () => {
|
||||
socket.emit("getId", () => {
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
|
||||
socket.volatile.emit("getId", () => {
|
||||
done(new Error("should not happen"));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should send a volatile packet when the socket is connected and the pipe is ready", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL, { forceNew: true });
|
||||
|
||||
const interval = setInterval(() => {
|
||||
socket.volatile.emit("getId", () => {
|
||||
clearInterval(interval);
|
||||
socket.disconnect();
|
||||
done();
|
||||
});
|
||||
}, 200);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("onAny", () => {
|
||||
it("should call listener", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/abc", {
|
||||
forceNew: true,
|
||||
});
|
||||
|
||||
socket.onAny((event, arg1) => {
|
||||
expect(event).to.be("handshake");
|
||||
expect(arg1).to.be.an(Object);
|
||||
|
||||
success(done, socket);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should prepend listener", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/abc", { forceNew: true });
|
||||
|
||||
let count = 0;
|
||||
|
||||
socket.onAny((event, arg1) => {
|
||||
expect(count).to.be(2);
|
||||
|
||||
success(done, socket);
|
||||
});
|
||||
|
||||
socket.prependAny(() => {
|
||||
expect(count++).to.be(1);
|
||||
});
|
||||
|
||||
socket.prependAny(() => {
|
||||
expect(count++).to.be(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should remove listener", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/abc", {
|
||||
forceNew: true,
|
||||
});
|
||||
|
||||
let count = 0;
|
||||
|
||||
const fail = () => done(new Error("fail"));
|
||||
|
||||
socket.onAny(fail);
|
||||
socket.offAny(fail);
|
||||
expect(socket.listenersAny.length).to.be(0);
|
||||
|
||||
socket.onAny(() => {
|
||||
success(done, socket);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("onAnyOutgoing", () => {
|
||||
it("should call listener", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/abc", {
|
||||
forceNew: true,
|
||||
});
|
||||
|
||||
socket.on("connect", () => {
|
||||
socket.onAnyOutgoing((event, arg1) => {
|
||||
expect(event).to.be("my-event");
|
||||
expect(arg1).to.be("123");
|
||||
|
||||
success(done, socket);
|
||||
});
|
||||
|
||||
socket.emit("my-event", "123");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should prepend listener", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/abc", {
|
||||
forceNew: true,
|
||||
});
|
||||
|
||||
let count = 0;
|
||||
|
||||
socket.onAnyOutgoing(() => {
|
||||
expect(count).to.be(2);
|
||||
|
||||
success(done, socket);
|
||||
});
|
||||
|
||||
socket.prependAnyOutgoing(() => {
|
||||
expect(count++).to.be(1);
|
||||
});
|
||||
|
||||
socket.prependAnyOutgoing(() => {
|
||||
expect(count++).to.be(0);
|
||||
});
|
||||
|
||||
socket.emit("my-event", "123");
|
||||
});
|
||||
});
|
||||
|
||||
it("should remove listener", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/abc", {
|
||||
forceNew: true,
|
||||
});
|
||||
const fail = () => done(new Error("fail"));
|
||||
|
||||
socket.onAnyOutgoing(fail);
|
||||
socket.offAnyOutgoing(fail);
|
||||
expect(socket.listenersAnyOutgoing.length).to.be(0);
|
||||
|
||||
socket.onAnyOutgoing(() => {
|
||||
success(done, socket);
|
||||
});
|
||||
|
||||
socket.emit("my-event", "123");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("timeout", () => {
|
||||
it("should timeout after the given delay when socket is not connected", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/", {
|
||||
autoConnect: false,
|
||||
});
|
||||
|
||||
socket.timeout(50).emit("event", (err) => {
|
||||
expect(err).to.be.an(Error);
|
||||
expect(socket.sendBuffer).to.be.empty();
|
||||
|
||||
success(done, socket);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should timeout when the server does not acknowledge the event", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/");
|
||||
|
||||
socket.timeout(50).emit("unknown", (err) => {
|
||||
expect(err).to.be.an(Error);
|
||||
success(done, socket);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should timeout when the server does not acknowledge the event in time", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/");
|
||||
|
||||
let count = 0;
|
||||
|
||||
socket.timeout(0).emit("echo", 42, (err) => {
|
||||
expect(err).to.be.an(Error);
|
||||
count++;
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(count).to.eql(1);
|
||||
success(done, socket);
|
||||
}, 200);
|
||||
});
|
||||
});
|
||||
|
||||
it("should not timeout when the server does acknowledge the event", () => {
|
||||
return wrap((done) => {
|
||||
const socket = io(BASE_URL + "/");
|
||||
|
||||
socket.timeout(50).emit("echo", 42, (err, value) => {
|
||||
expect(err).to.be(null);
|
||||
expect(value).to.be(42);
|
||||
success(done, socket);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
// WARNING this is bad practice
|
||||
// we only do this in our tests because we need to test engine.io-client
|
||||
// support in browsers and in node.js
|
||||
// some tests do not yet work in both
|
||||
exports.browser = typeof window !== "undefined";
|
||||
exports.node = !exports.browser;
|
||||
|
||||
if (exports.node) {
|
||||
global.location = {
|
||||
protocol: "http:",
|
||||
host: "localhost:3210",
|
||||
hostname: "localhost",
|
||||
port: "3210",
|
||||
};
|
||||
}
|
||||
12
test/support/hooks.ts
Normal file
12
test/support/hooks.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { createServer } from "./server";
|
||||
|
||||
let server;
|
||||
|
||||
export const mochaHooks = {
|
||||
beforeAll() {
|
||||
server = createServer();
|
||||
},
|
||||
afterAll() {
|
||||
server.close();
|
||||
},
|
||||
};
|
||||
@@ -1,158 +0,0 @@
|
||||
// this is a test server to support tests which make requests
|
||||
|
||||
const io = require("socket.io");
|
||||
const server = io(process.env.ZUUL_PORT || 3210, { pingInterval: 2000 });
|
||||
const expect = require("expect.js");
|
||||
|
||||
server.of("/foo").on("connection", (socket) => {
|
||||
socket.on("getId", (cb) => {
|
||||
cb(socket.id);
|
||||
});
|
||||
});
|
||||
|
||||
server.of("/timeout_socket").on("connection", () => {
|
||||
// register namespace
|
||||
});
|
||||
|
||||
server.of("/valid").on("connection", () => {
|
||||
// register namespace
|
||||
});
|
||||
|
||||
server.of("/asd").on("connection", () => {
|
||||
// register namespace
|
||||
});
|
||||
|
||||
server.of("/abc").on("connection", (socket) => {
|
||||
socket.emit("handshake", socket.handshake);
|
||||
});
|
||||
|
||||
server.use((socket, next) => {
|
||||
if (socket.request._query.fail)
|
||||
return next(new Error("Auth failed (main namespace)"));
|
||||
next();
|
||||
});
|
||||
|
||||
server.of("/no").use((socket, next) => {
|
||||
next(new Error("Auth failed (custom namespace)"));
|
||||
});
|
||||
|
||||
server.on("connection", (socket) => {
|
||||
// simple test
|
||||
socket.on("hi", () => {
|
||||
socket.emit("hi");
|
||||
});
|
||||
|
||||
socket.on("echo", (arg, cb) => {
|
||||
cb(arg);
|
||||
});
|
||||
|
||||
// ack tests
|
||||
socket.on("ack", () => {
|
||||
socket.emit("ack", (a, b) => {
|
||||
if (a === 5 && b.test) {
|
||||
socket.emit("got it");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("getAckDate", (data, cb) => {
|
||||
cb(new Date());
|
||||
});
|
||||
|
||||
socket.on("getDate", () => {
|
||||
socket.emit("takeDate", new Date());
|
||||
});
|
||||
|
||||
socket.on("getDateObj", () => {
|
||||
socket.emit("takeDateObj", { date: new Date() });
|
||||
});
|
||||
|
||||
socket.on("getUtf8", () => {
|
||||
socket.emit("takeUtf8", "てすと");
|
||||
socket.emit("takeUtf8", "Я Б Г Д Ж Й");
|
||||
socket.emit("takeUtf8", "Ä ä Ü ü ß");
|
||||
socket.emit("takeUtf8", "utf8 — string");
|
||||
socket.emit("takeUtf8", "utf8 — string");
|
||||
});
|
||||
|
||||
// false test
|
||||
socket.on("false", () => {
|
||||
socket.emit("false", false);
|
||||
});
|
||||
|
||||
// binary test
|
||||
socket.on("doge", () => {
|
||||
const buf = Buffer.from("asdfasdf", "utf8");
|
||||
socket.emit("doge", buf);
|
||||
});
|
||||
|
||||
// expect receiving binary to be buffer
|
||||
socket.on("buffa", (a) => {
|
||||
if (Buffer.isBuffer(a)) socket.emit("buffack");
|
||||
});
|
||||
|
||||
// expect receiving binary with mixed JSON
|
||||
socket.on("jsonbuff", (a) => {
|
||||
expect(a.hello).to.eql("lol");
|
||||
expect(Buffer.isBuffer(a.message)).to.be(true);
|
||||
expect(a.goodbye).to.eql("gotcha");
|
||||
socket.emit("jsonbuff-ack");
|
||||
});
|
||||
|
||||
// expect receiving buffers in order
|
||||
let receivedAbuff1 = false;
|
||||
socket.on("abuff1", (a) => {
|
||||
expect(Buffer.isBuffer(a)).to.be(true);
|
||||
receivedAbuff1 = true;
|
||||
});
|
||||
socket.on("abuff2", (a) => {
|
||||
expect(receivedAbuff1).to.be(true);
|
||||
socket.emit("abuff2-ack");
|
||||
});
|
||||
|
||||
// expect sent blob to be buffer
|
||||
socket.on("blob", (a) => {
|
||||
if (Buffer.isBuffer(a)) socket.emit("back");
|
||||
});
|
||||
|
||||
// expect sent blob mixed with json to be buffer
|
||||
socket.on("jsonblob", (a) => {
|
||||
expect(a.hello).to.eql("lol");
|
||||
expect(Buffer.isBuffer(a.message)).to.be(true);
|
||||
expect(a.goodbye).to.eql("gotcha");
|
||||
socket.emit("jsonblob-ack");
|
||||
});
|
||||
|
||||
// expect blobs sent in order to arrive in correct order
|
||||
let receivedblob1 = false;
|
||||
let receivedblob2 = false;
|
||||
socket.on("blob1", (a) => {
|
||||
expect(Buffer.isBuffer(a)).to.be(true);
|
||||
receivedblob1 = true;
|
||||
});
|
||||
socket.on("blob2", (a) => {
|
||||
expect(receivedblob1).to.be(true);
|
||||
expect(a).to.eql("second");
|
||||
receivedblob2 = true;
|
||||
});
|
||||
socket.on("blob3", (a) => {
|
||||
expect(Buffer.isBuffer(a)).to.be(true);
|
||||
expect(receivedblob1).to.be(true);
|
||||
expect(receivedblob2).to.be(true);
|
||||
socket.emit("blob3-ack");
|
||||
});
|
||||
|
||||
// emit buffer to base64 receiving browsers
|
||||
socket.on("getbin", () => {
|
||||
const buf = Buffer.from("asdfasdf", "utf8");
|
||||
socket.emit("takebin", buf);
|
||||
});
|
||||
|
||||
socket.on("getHandshake", (cb) => {
|
||||
cb(socket.handshake);
|
||||
});
|
||||
|
||||
socket.on("getId", (cb) => {
|
||||
cb(socket.id);
|
||||
});
|
||||
});
|
||||
162
test/support/server.ts
Normal file
162
test/support/server.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
import { Server } from "socket.io";
|
||||
import expect from "expect.js";
|
||||
|
||||
export function createServer() {
|
||||
const server = new Server(3210, { pingInterval: 2000 });
|
||||
|
||||
server.of("/foo").on("connection", (socket) => {
|
||||
socket.on("getId", (cb) => {
|
||||
cb(socket.id);
|
||||
});
|
||||
});
|
||||
|
||||
server.of("/timeout_socket").on("connection", () => {
|
||||
// register namespace
|
||||
});
|
||||
|
||||
server.of("/valid").on("connection", () => {
|
||||
// register namespace
|
||||
});
|
||||
|
||||
server.of("/asd").on("connection", () => {
|
||||
// register namespace
|
||||
});
|
||||
|
||||
server.of("/abc").on("connection", (socket) => {
|
||||
socket.emit("handshake", socket.handshake);
|
||||
});
|
||||
|
||||
server.use((socket, next) => {
|
||||
// @ts-ignore
|
||||
if (socket.request._query.fail)
|
||||
return next(new Error("Auth failed (main namespace)"));
|
||||
next();
|
||||
});
|
||||
|
||||
server.of("/no").use((socket, next) => {
|
||||
next(new Error("Auth failed (custom namespace)"));
|
||||
});
|
||||
|
||||
server.on("connection", (socket) => {
|
||||
// simple test
|
||||
socket.on("hi", () => {
|
||||
socket.emit("hi");
|
||||
});
|
||||
|
||||
socket.on("echo", (arg, cb) => {
|
||||
cb(arg);
|
||||
});
|
||||
|
||||
// ack tests
|
||||
socket.on("ack", () => {
|
||||
socket.emit("ack", (a, b) => {
|
||||
if (a === 5 && b.test) {
|
||||
socket.emit("got it");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("getAckDate", (data, cb) => {
|
||||
cb(new Date());
|
||||
});
|
||||
|
||||
socket.on("getDate", () => {
|
||||
socket.emit("takeDate", new Date());
|
||||
});
|
||||
|
||||
socket.on("getDateObj", () => {
|
||||
socket.emit("takeDateObj", { date: new Date() });
|
||||
});
|
||||
|
||||
socket.on("getUtf8", () => {
|
||||
socket.emit("takeUtf8", "てすと");
|
||||
socket.emit("takeUtf8", "Я Б Г Д Ж Й");
|
||||
socket.emit("takeUtf8", "Ä ä Ü ü ß");
|
||||
socket.emit("takeUtf8", "utf8 — string");
|
||||
socket.emit("takeUtf8", "utf8 — string");
|
||||
});
|
||||
|
||||
// false test
|
||||
socket.on("false", () => {
|
||||
socket.emit("false", false);
|
||||
});
|
||||
|
||||
// binary test
|
||||
socket.on("doge", () => {
|
||||
const buf = Buffer.from("asdfasdf", "utf8");
|
||||
socket.emit("doge", buf);
|
||||
});
|
||||
|
||||
// expect receiving binary to be buffer
|
||||
socket.on("buffa", (a) => {
|
||||
if (Buffer.isBuffer(a)) socket.emit("buffack");
|
||||
});
|
||||
|
||||
// expect receiving binary with mixed JSON
|
||||
socket.on("jsonbuff", (a) => {
|
||||
expect(a.hello).to.eql("lol");
|
||||
expect(Buffer.isBuffer(a.message)).to.be(true);
|
||||
expect(a.goodbye).to.eql("gotcha");
|
||||
socket.emit("jsonbuff-ack");
|
||||
});
|
||||
|
||||
// expect receiving buffers in order
|
||||
let receivedAbuff1 = false;
|
||||
socket.on("abuff1", (a) => {
|
||||
expect(Buffer.isBuffer(a)).to.be(true);
|
||||
receivedAbuff1 = true;
|
||||
});
|
||||
socket.on("abuff2", (a) => {
|
||||
expect(receivedAbuff1).to.be(true);
|
||||
socket.emit("abuff2-ack");
|
||||
});
|
||||
|
||||
// expect sent blob to be buffer
|
||||
socket.on("blob", (a) => {
|
||||
if (Buffer.isBuffer(a)) socket.emit("back");
|
||||
});
|
||||
|
||||
// expect sent blob mixed with json to be buffer
|
||||
socket.on("jsonblob", (a) => {
|
||||
expect(a.hello).to.eql("lol");
|
||||
expect(Buffer.isBuffer(a.message)).to.be(true);
|
||||
expect(a.goodbye).to.eql("gotcha");
|
||||
socket.emit("jsonblob-ack");
|
||||
});
|
||||
|
||||
// expect blobs sent in order to arrive in correct order
|
||||
let receivedblob1 = false;
|
||||
let receivedblob2 = false;
|
||||
socket.on("blob1", (a) => {
|
||||
expect(Buffer.isBuffer(a)).to.be(true);
|
||||
receivedblob1 = true;
|
||||
});
|
||||
socket.on("blob2", (a) => {
|
||||
expect(receivedblob1).to.be(true);
|
||||
expect(a).to.eql("second");
|
||||
receivedblob2 = true;
|
||||
});
|
||||
socket.on("blob3", (a) => {
|
||||
expect(Buffer.isBuffer(a)).to.be(true);
|
||||
expect(receivedblob1).to.be(true);
|
||||
expect(receivedblob2).to.be(true);
|
||||
socket.emit("blob3-ack");
|
||||
});
|
||||
|
||||
// emit buffer to base64 receiving browsers
|
||||
socket.on("getbin", () => {
|
||||
const buf = Buffer.from("asdfasdf", "utf8");
|
||||
socket.emit("takebin", buf);
|
||||
});
|
||||
|
||||
socket.on("getHandshake", (cb) => {
|
||||
cb(socket.handshake);
|
||||
});
|
||||
|
||||
socket.on("getId", (cb) => {
|
||||
cb(socket.id);
|
||||
});
|
||||
});
|
||||
|
||||
return server;
|
||||
}
|
||||
25
test/support/util.ts
Normal file
25
test/support/util.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* This is needed because webdriver.io does not support mocha async mode:
|
||||
*
|
||||
* ```
|
||||
* it("works", (done) => {
|
||||
* done(); // does not work
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @see https://webdriver.io/docs/frameworks/#using-mocha
|
||||
* @param fn
|
||||
*/
|
||||
export function wrap(fn) {
|
||||
return new Promise((resolve) => fn(resolve));
|
||||
}
|
||||
|
||||
export function success(done, socket) {
|
||||
socket.disconnect();
|
||||
done();
|
||||
}
|
||||
|
||||
/**
|
||||
* URL of the Socket.IO server used in the tests (see "test/support/server.ts")
|
||||
*/
|
||||
export const BASE_URL = "http://localhost:3210";
|
||||
101
wdio.conf.js
Normal file
101
wdio.conf.js
Normal file
@@ -0,0 +1,101 @@
|
||||
const BASE_SAUCE_OPTIONS = {
|
||||
build: process.env.GITHUB_RUN_ID || "local",
|
||||
name: "socket.io-client",
|
||||
};
|
||||
|
||||
const config = {
|
||||
specs: ["./test/index.ts"],
|
||||
|
||||
capabilities: [
|
||||
{
|
||||
browserName: "chrome",
|
||||
},
|
||||
],
|
||||
|
||||
maxInstances: 5,
|
||||
logLevel: "warn",
|
||||
bail: 0,
|
||||
baseUrl: "http://localhost",
|
||||
|
||||
reporters: ["spec"],
|
||||
framework: "mocha",
|
||||
mochaOpts: {
|
||||
ui: "bdd",
|
||||
timeout: 60000,
|
||||
},
|
||||
};
|
||||
|
||||
if (process.env.CI === "true") {
|
||||
config.services = [
|
||||
[
|
||||
"sauce",
|
||||
{
|
||||
sauceConnect: true,
|
||||
},
|
||||
],
|
||||
];
|
||||
config.user = process.env.SAUCE_USERNAME;
|
||||
config.key = process.env.SAUCE_ACCESS_KEY;
|
||||
|
||||
// https://saucelabs.com/platform/platform-configurator#/
|
||||
config.capabilities = [
|
||||
{
|
||||
browserName: "chrome",
|
||||
browserVersion: "latest",
|
||||
platformName: "Windows 11",
|
||||
"sauce:options": BASE_SAUCE_OPTIONS,
|
||||
},
|
||||
{
|
||||
browserName: "MicrosoftEdge",
|
||||
browserVersion: "latest",
|
||||
platformName: "Windows 11",
|
||||
"sauce:options": BASE_SAUCE_OPTIONS,
|
||||
},
|
||||
{
|
||||
browserName: "firefox",
|
||||
browserVersion: "latest",
|
||||
platformName: "Windows 11",
|
||||
"sauce:options": BASE_SAUCE_OPTIONS,
|
||||
},
|
||||
{
|
||||
browserName: "internet explorer",
|
||||
browserVersion: "10",
|
||||
platformName: "Windows 7",
|
||||
"sauce:options": BASE_SAUCE_OPTIONS,
|
||||
},
|
||||
{
|
||||
browserName: "safari",
|
||||
browserVersion: "latest",
|
||||
platformName: "macOS 12",
|
||||
"sauce:options": BASE_SAUCE_OPTIONS,
|
||||
},
|
||||
{
|
||||
platformName: "Android",
|
||||
browserName: "Chrome",
|
||||
"appium:deviceName": "Android GoogleAPI Emulator",
|
||||
"appium:platformVersion": "latest",
|
||||
"appium:automationName": "UiAutomator2",
|
||||
"sauce:options": Object.assign(
|
||||
{
|
||||
appiumVersion: "1.22.1",
|
||||
},
|
||||
BASE_SAUCE_OPTIONS
|
||||
),
|
||||
},
|
||||
{
|
||||
platformName: "iOS",
|
||||
browserName: "Safari",
|
||||
"appium:deviceName": "iPhone Simulator",
|
||||
"appium:platformVersion": "latest",
|
||||
"appium:automationName": "XCUITest",
|
||||
"sauce:options": Object.assign(
|
||||
{
|
||||
appiumVersion: "2.0.0",
|
||||
},
|
||||
BASE_SAUCE_OPTIONS
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
exports.config = config;
|
||||
@@ -1,74 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const webpackConfig = require('./support/prod.config.js');
|
||||
|
||||
webpackConfig.module.rules.push({
|
||||
test: /\.tsx?$/,
|
||||
use: [
|
||||
{
|
||||
loader: "ts-loader",
|
||||
options: {
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
exclude: /node_modules/,
|
||||
});
|
||||
|
||||
const zuulConfig = module.exports = {
|
||||
ui: 'mocha-bdd',
|
||||
|
||||
// test on localhost by default
|
||||
local: true,
|
||||
open: true,
|
||||
|
||||
concurrency: 2, // ngrok only accepts two tunnels by default
|
||||
// if browser does not sends output in 120s since last output:
|
||||
// stop testing, something is wrong
|
||||
browser_output_timeout: 120 * 1000,
|
||||
browser_open_timeout: 60 * 4 * 1000,
|
||||
// we want to be notified something is wrong asap, so no retry
|
||||
browser_retries: 1,
|
||||
|
||||
server: './test/support/server.js',
|
||||
builder: 'zuul-builder-webpack',
|
||||
webpack: webpackConfig
|
||||
};
|
||||
|
||||
if (process.env.CI === 'true') {
|
||||
zuulConfig.local = false;
|
||||
zuulConfig.tunnel = {
|
||||
type: 'ngrok',
|
||||
bind_tls: true
|
||||
};
|
||||
}
|
||||
|
||||
zuulConfig.browsers = [
|
||||
{
|
||||
name: 'chrome',
|
||||
version: 'latest'
|
||||
}, {
|
||||
name: 'firefox',
|
||||
version: 'latest'
|
||||
}, {
|
||||
name: 'internet explorer',
|
||||
version: '9..11'
|
||||
}, {
|
||||
name: 'safari',
|
||||
version: 'latest'
|
||||
}, {
|
||||
name: 'iphone',
|
||||
version: '15.4' // temporary fix
|
||||
}, {
|
||||
name: 'android',
|
||||
version: '5.1..6.0'
|
||||
}, {
|
||||
name: 'ipad',
|
||||
version: '15.4' // temporary fix
|
||||
}, {
|
||||
name: 'MicrosoftEdge',
|
||||
version: 'latest'
|
||||
}
|
||||
];
|
||||
Reference in New Issue
Block a user