add chai to tests
This commit is contained in:
Generated
+213
-7
@@ -1,15 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "rpclibrary",
|
"name": "rpclibrary",
|
||||||
"version": "2.3.1",
|
"version": "2.4.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"version": "2.3.1",
|
"version": "2.4.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/chai": "^4.2.21",
|
||||||
"@types/socket.io": "^2.1.8",
|
"@types/socket.io": "^2.1.8",
|
||||||
"@types/socket.io-client": "^1.4.33",
|
"@types/socket.io-client": "^1.4.33",
|
||||||
|
"chai": "^4.3.4",
|
||||||
|
"chai-as-promised": "^7.1.1",
|
||||||
"http": "0.0.0",
|
"http": "0.0.0",
|
||||||
"socket.io": "^2.3.0",
|
"socket.io": "^2.3.0",
|
||||||
"socket.io-client": "^2.3.0",
|
"socket.io-client": "^2.3.0",
|
||||||
@@ -295,6 +298,11 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/chai": {
|
||||||
|
"version": "4.2.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.21.tgz",
|
||||||
|
"integrity": "sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg=="
|
||||||
|
},
|
||||||
"node_modules/@types/color-name": {
|
"node_modules/@types/color-name": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||||
@@ -784,6 +792,14 @@
|
|||||||
"inherits": "2.0.1"
|
"inherits": "2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/assertion-error": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/assign-symbols": {
|
"node_modules/assign-symbols": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
|
||||||
@@ -1285,6 +1301,33 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/chai": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==",
|
||||||
|
"dependencies": {
|
||||||
|
"assertion-error": "^1.1.0",
|
||||||
|
"check-error": "^1.0.2",
|
||||||
|
"deep-eql": "^3.0.1",
|
||||||
|
"get-func-name": "^2.0.0",
|
||||||
|
"pathval": "^1.1.1",
|
||||||
|
"type-detect": "^4.0.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chai-as-promised": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==",
|
||||||
|
"dependencies": {
|
||||||
|
"check-error": "^1.0.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"chai": ">= 2.1.2 < 5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chalk": {
|
"node_modules/chalk": {
|
||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
@@ -1311,6 +1354,14 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/check-error": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chokidar": {
|
"node_modules/chokidar": {
|
||||||
"version": "2.1.8",
|
"version": "2.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
|
||||||
@@ -1320,7 +1371,6 @@
|
|||||||
"anymatch": "^2.0.0",
|
"anymatch": "^2.0.0",
|
||||||
"async-each": "^1.0.1",
|
"async-each": "^1.0.1",
|
||||||
"braces": "^2.3.2",
|
"braces": "^2.3.2",
|
||||||
"fsevents": "^1.2.7",
|
|
||||||
"glob-parent": "^3.1.0",
|
"glob-parent": "^3.1.0",
|
||||||
"inherits": "^2.0.3",
|
"inherits": "^2.0.3",
|
||||||
"is-binary-path": "^1.0.0",
|
"is-binary-path": "^1.0.0",
|
||||||
@@ -1713,6 +1763,17 @@
|
|||||||
"node": ">=0.10"
|
"node": ">=0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/deep-eql": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
|
||||||
|
"dependencies": {
|
||||||
|
"type-detect": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/default-require-extensions": {
|
"node_modules/default-require-extensions": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz",
|
||||||
@@ -2726,7 +2787,71 @@
|
|||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
|
||||||
"integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
|
"integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
|
||||||
"bundleDependencies": [
|
"bundleDependencies": [
|
||||||
"node-pre-gyp"
|
"node-pre-gyp",
|
||||||
|
"abbrev",
|
||||||
|
"ansi-regex",
|
||||||
|
"aproba",
|
||||||
|
"are-we-there-yet",
|
||||||
|
"balanced-match",
|
||||||
|
"brace-expansion",
|
||||||
|
"chownr",
|
||||||
|
"code-point-at",
|
||||||
|
"concat-map",
|
||||||
|
"console-control-strings",
|
||||||
|
"core-util-is",
|
||||||
|
"debug",
|
||||||
|
"deep-extend",
|
||||||
|
"delegates",
|
||||||
|
"detect-libc",
|
||||||
|
"fs-minipass",
|
||||||
|
"fs.realpath",
|
||||||
|
"gauge",
|
||||||
|
"glob",
|
||||||
|
"has-unicode",
|
||||||
|
"iconv-lite",
|
||||||
|
"ignore-walk",
|
||||||
|
"inflight",
|
||||||
|
"inherits",
|
||||||
|
"ini",
|
||||||
|
"is-fullwidth-code-point",
|
||||||
|
"isarray",
|
||||||
|
"minimatch",
|
||||||
|
"minimist",
|
||||||
|
"minipass",
|
||||||
|
"minizlib",
|
||||||
|
"mkdirp",
|
||||||
|
"ms",
|
||||||
|
"needle",
|
||||||
|
"nopt",
|
||||||
|
"npm-bundled",
|
||||||
|
"npm-packlist",
|
||||||
|
"npmlog",
|
||||||
|
"number-is-nan",
|
||||||
|
"object-assign",
|
||||||
|
"once",
|
||||||
|
"os-homedir",
|
||||||
|
"os-tmpdir",
|
||||||
|
"osenv",
|
||||||
|
"path-is-absolute",
|
||||||
|
"process-nextick-args",
|
||||||
|
"rc",
|
||||||
|
"readable-stream",
|
||||||
|
"rimraf",
|
||||||
|
"safe-buffer",
|
||||||
|
"safer-buffer",
|
||||||
|
"sax",
|
||||||
|
"semver",
|
||||||
|
"set-blocking",
|
||||||
|
"signal-exit",
|
||||||
|
"string_decoder",
|
||||||
|
"string-width",
|
||||||
|
"strip-ansi",
|
||||||
|
"strip-json-comments",
|
||||||
|
"tar",
|
||||||
|
"util-deprecate",
|
||||||
|
"wide-align",
|
||||||
|
"wrappy",
|
||||||
|
"yallist"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
@@ -3578,6 +3703,14 @@
|
|||||||
"node": "6.* || 8.* || >= 10.*"
|
"node": "6.* || 8.* || >= 10.*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/get-func-name": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/get-stream": {
|
"node_modules/get-stream": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
||||||
@@ -3713,7 +3846,6 @@
|
|||||||
"minimist": "^1.2.5",
|
"minimist": "^1.2.5",
|
||||||
"neo-async": "^2.6.0",
|
"neo-async": "^2.6.0",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1",
|
||||||
"uglify-js": "^3.1.4",
|
|
||||||
"wordwrap": "^1.0.0"
|
"wordwrap": "^1.0.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -5962,6 +6094,14 @@
|
|||||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
|
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/pathval": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pbkdf2": {
|
"node_modules/pbkdf2": {
|
||||||
"version": "3.0.17",
|
"version": "3.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
|
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
|
||||||
@@ -7436,8 +7576,7 @@
|
|||||||
"integrity": "sha512-ZCtJK8WXxHNbFNjvUKQIXZby/+ybQQkaBcM/3QhBQUfwjpdGFE9F6iWsHhF5ifQNFV/lWiOODi2VMD5AyPcQyg==",
|
"integrity": "sha512-ZCtJK8WXxHNbFNjvUKQIXZby/+ybQQkaBcM/3QhBQUfwjpdGFE9F6iWsHhF5ifQNFV/lWiOODi2VMD5AyPcQyg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ts-node": "7.0.1",
|
"ts-node": "7.0.1"
|
||||||
"tsconfig-paths": "^3.5.0"
|
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"ts-mocha": "bin/ts-mocha"
|
"ts-mocha": "bin/ts-mocha"
|
||||||
@@ -7496,6 +7635,14 @@
|
|||||||
"integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
|
"integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/type-detect": {
|
||||||
|
"version": "4.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||||
|
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/type-fest": {
|
"node_modules/type-fest": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
||||||
@@ -8529,6 +8676,11 @@
|
|||||||
"integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==",
|
"integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/chai": {
|
||||||
|
"version": "4.2.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.21.tgz",
|
||||||
|
"integrity": "sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg=="
|
||||||
|
},
|
||||||
"@types/color-name": {
|
"@types/color-name": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||||
@@ -8980,6 +9132,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"assertion-error": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw=="
|
||||||
|
},
|
||||||
"assign-symbols": {
|
"assign-symbols": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
|
||||||
@@ -9419,6 +9576,27 @@
|
|||||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"chai": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==",
|
||||||
|
"requires": {
|
||||||
|
"assertion-error": "^1.1.0",
|
||||||
|
"check-error": "^1.0.2",
|
||||||
|
"deep-eql": "^3.0.1",
|
||||||
|
"get-func-name": "^2.0.0",
|
||||||
|
"pathval": "^1.1.1",
|
||||||
|
"type-detect": "^4.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chai-as-promised": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==",
|
||||||
|
"requires": {
|
||||||
|
"check-error": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
@@ -9441,6 +9619,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"check-error": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
|
||||||
|
},
|
||||||
"chokidar": {
|
"chokidar": {
|
||||||
"version": "2.1.8",
|
"version": "2.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
|
||||||
@@ -9793,6 +9976,14 @@
|
|||||||
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
|
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"deep-eql": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
|
||||||
|
"requires": {
|
||||||
|
"type-detect": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"default-require-extensions": {
|
"default-require-extensions": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz",
|
||||||
@@ -11336,6 +11527,11 @@
|
|||||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"get-func-name": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE="
|
||||||
|
},
|
||||||
"get-stream": {
|
"get-stream": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
||||||
@@ -13258,6 +13454,11 @@
|
|||||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
|
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"pathval": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ=="
|
||||||
|
},
|
||||||
"pbkdf2": {
|
"pbkdf2": {
|
||||||
"version": "3.0.17",
|
"version": "3.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
|
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
|
||||||
@@ -14560,6 +14761,11 @@
|
|||||||
"integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
|
"integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"type-detect": {
|
||||||
|
"version": "4.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||||
|
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="
|
||||||
|
},
|
||||||
"type-fest": {
|
"type-fest": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
||||||
|
|||||||
+4
-1
@@ -30,7 +30,7 @@
|
|||||||
"frontend": "node js/test/TestFrontend.js",
|
"frontend": "node js/test/TestFrontend.js",
|
||||||
"build": "npm run clean && tsc && npm run webpack",
|
"build": "npm run clean && tsc && npm run webpack",
|
||||||
"clean": "rm -rf js",
|
"clean": "rm -rf js",
|
||||||
"test": "npm run clean && npm run build && mocha js/test/Test.js",
|
"test": "npm run clean && npm run build && mocha --bail=true js/test/Test.js",
|
||||||
"docs": "typedoc --out docs ./src --readme ./README.md --plugin typedoc-plugin-markdown --mode file --hideBreadcrumbs --hideSources"
|
"docs": "typedoc --out docs ./src --readme ./README.md --plugin typedoc-plugin-markdown --mode file --hideBreadcrumbs --hideSources"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -52,8 +52,11 @@
|
|||||||
"why-is-node-running": "^2.1.2"
|
"why-is-node-running": "^2.1.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/chai": "^4.2.21",
|
||||||
"@types/socket.io": "^2.1.8",
|
"@types/socket.io": "^2.1.8",
|
||||||
"@types/socket.io-client": "^1.4.33",
|
"@types/socket.io-client": "^1.4.33",
|
||||||
|
"chai": "^4.3.4",
|
||||||
|
"chai-as-promised": "^7.1.1",
|
||||||
"http": "0.0.0",
|
"http": "0.0.0",
|
||||||
"socket.io": "^2.3.0",
|
"socket.io": "^2.3.0",
|
||||||
"socket.io-client": "^2.3.0",
|
"socket.io-client": "^2.3.0",
|
||||||
|
|||||||
+78
-139
@@ -8,6 +8,8 @@ import * as express from 'express';
|
|||||||
import * as fetch from 'node-fetch';
|
import * as fetch from 'node-fetch';
|
||||||
import { PromiseIO } from "../src/PromiseIO/Server";
|
import { PromiseIO } from "../src/PromiseIO/Server";
|
||||||
import { PromiseIOClient } from "../src/PromiseIO/Client";
|
import { PromiseIOClient } from "../src/PromiseIO/Client";
|
||||||
|
import { assert, expect } from 'chai';
|
||||||
|
var should = require('chai').should();
|
||||||
|
|
||||||
const noop = (...args) => { }
|
const noop = (...args) => { }
|
||||||
|
|
||||||
@@ -20,6 +22,11 @@ function makeServer(onCallback = noop, connectionHandler = noop, hookCloseHandle
|
|||||||
{
|
{
|
||||||
name: 'echo',
|
name: 'echo',
|
||||||
call: async (s: string) => s,
|
call: async (s: string) => s,
|
||||||
|
}, {
|
||||||
|
name: 'complexSignature',
|
||||||
|
call: async ([a, b]) => {
|
||||||
|
return [b, a]
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
name: 'simpleSubscribe',
|
name: 'simpleSubscribe',
|
||||||
hook: async (callback) => {
|
hook: async (callback) => {
|
||||||
@@ -140,34 +147,26 @@ describe('RPCServer', () => {
|
|||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be able to use all kinds of RPC definitions', (done) => {
|
it('should be able to use all kinds of RPC definitions', async () => {
|
||||||
client.connect().then(async () => {
|
await client.connect()
|
||||||
const r0 = await client['HelloWorldRPCGroup'].echo('Hello')
|
const r0 = await client['HelloWorldRPCGroup'].echo('Hello')
|
||||||
const r1 = await client['HelloWorldRPCGroup'].echof('World')
|
const r1 = await client['HelloWorldRPCGroup'].echof('World')
|
||||||
const r2 = await client['HelloWorldRPCGroup'].echoExplicit('R', 'P', 'C!')
|
const r2 = await client['HelloWorldRPCGroup'].echoExplicit('R', 'P', 'C!')
|
||||||
|
|
||||||
|
expect(r0).to.be.equal('Hello')
|
||||||
if (r0 === 'Hello' && r1 === 'World' && r2.join('') === 'RPC!') {
|
expect(r1).to.be.equal('World')
|
||||||
done()
|
expect(r2.join('')).to.be.equal('RPC!')
|
||||||
} else {
|
|
||||||
done(new Error("Bad response"))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('new RPCServer() should fail on bad RPC', (done) => {
|
it('new RPCServer() should fail on unnamed RPC', async () => {
|
||||||
try {
|
expect(() => {
|
||||||
const sv = new RPCServer([{
|
const sv = new RPCServer([{
|
||||||
name: 'bad',
|
name: 'bad',
|
||||||
RPCs: () => [
|
RPCs: () => [
|
||||||
(aaa, bbb, ccc) => { return aaa + bbb + ccc }
|
(aaa, bbb, ccc) => { return aaa + bbb + ccc }
|
||||||
]
|
]
|
||||||
}])
|
}])
|
||||||
sv.listen(20001)
|
}).to.throw()
|
||||||
done(new Error("Didn't fail with bad RPC"))
|
|
||||||
} catch (badRPCError) {
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -228,31 +227,21 @@ describe('RPCServer with premade http server', () => {
|
|||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should serve REST', (done) => {
|
it('should serve REST', async () => {
|
||||||
fetch('http://localhost:8080/REST_ping').then(response => {
|
const response = await fetch('http://localhost:8080/REST_ping')
|
||||||
response.text().then(text => {
|
const text = await response.text()
|
||||||
if (text === "REST_pong")
|
expect(text).to.be.equal("REST_pong")
|
||||||
done()
|
|
||||||
else
|
|
||||||
done(new Error("REST repsonse was " + text))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
it('should be able to use all kinds of RPC definitions', (done) => {
|
it('should be able to use all kinds of RPC definitions', async () => {
|
||||||
client.connect().then(async () => {
|
await client.connect()
|
||||||
const r0 = await client['HelloWorldRPCGroup'].echo('Hello')
|
const r0 = await client['HelloWorldRPCGroup'].echo('Hello')
|
||||||
const r1 = await client['HelloWorldRPCGroup'].echof('World')
|
const r1 = await client['HelloWorldRPCGroup'].echof('World')
|
||||||
const r2 = await client['HelloWorldRPCGroup'].echoExplicit('R', 'P', 'C!')
|
const r2 = await client['HelloWorldRPCGroup'].echoExplicit('R', 'P', 'C!')
|
||||||
|
expect(r0).to.be.equal('Hello')
|
||||||
|
expect(r1).to.be.equal('World')
|
||||||
if (r0 === 'Hello' && r1 === 'World' && r2.join('') === 'RPC!') {
|
expect(r2.join('')).to.be.equal('RPC!')
|
||||||
done()
|
|
||||||
} else {
|
|
||||||
done(new Error("Bad response"))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -284,19 +273,14 @@ describe('should be able to attach to non-standard path', () => {
|
|||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be able to use all kinds of RPC definitions', (done) => {
|
it('should be able to use all kinds of RPC definitions', async () => {
|
||||||
client.connect().then(async () => {
|
await client.connect()
|
||||||
const r0 = await client['HelloWorldRPCGroup'].echo('Hello')
|
const r0 = await client['HelloWorldRPCGroup'].echo('Hello')
|
||||||
const r1 = await client['HelloWorldRPCGroup'].echof('World')
|
const r1 = await client['HelloWorldRPCGroup'].echof('World')
|
||||||
const r2 = await client['HelloWorldRPCGroup'].echoExplicit('R', 'P', 'C!')
|
const r2 = await client['HelloWorldRPCGroup'].echoExplicit('R', 'P', 'C!')
|
||||||
|
expect(r0).to.be.equal('Hello')
|
||||||
|
expect(r1).to.be.equal('World')
|
||||||
if (r0 === 'Hello' && r1 === 'World' && r2.join('') === 'RPC!') {
|
expect(r2.join('')).to.be.equal('RPC!')
|
||||||
done()
|
|
||||||
} else {
|
|
||||||
done(new Error("Bad response"))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -366,22 +350,12 @@ describe('can attach multiple RPCServers to same http server', () => {
|
|||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('both servers should answer', (done) => {
|
it('both servers should answer', async () => {
|
||||||
client['HelloWorldRPCGroup'].echo("test").then(res => {
|
const res = await client['HelloWorldRPCGroup'].echo("test")
|
||||||
if(res != "test"){
|
expect(res).to.equal('test')
|
||||||
done(new Error("response was "+res))
|
const res2 = await client2['Grp2'].test()
|
||||||
}else{
|
expect(res2).to.equal('/test')
|
||||||
client2['Grp2'].test().then(res => {
|
|
||||||
if(res != "/test"){
|
|
||||||
done(new Error("response2 was "+res))
|
|
||||||
}else{
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("can attach second RPCServer if first is already running", () => {
|
describe("can attach second RPCServer if first is already running", () => {
|
||||||
@@ -409,7 +383,7 @@ describe("can attach second RPCServer if first is already running", () => {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
it("attaches correctly", done => {
|
it("attaches correctly", async () => {
|
||||||
const expressServer = express()
|
const expressServer = express()
|
||||||
const httpServer = new http.Server(expressServer)
|
const httpServer = new http.Server(expressServer)
|
||||||
|
|
||||||
@@ -427,13 +401,10 @@ describe("can attach second RPCServer if first is already running", () => {
|
|||||||
path: "test"
|
path: "test"
|
||||||
})
|
})
|
||||||
|
|
||||||
new RPCSocket(8080, 'localhost').connect().then(sock => {
|
const sock = await new RPCSocket(8080, 'localhost').connect()
|
||||||
new RPCSocket(8080, 'localhost', { path: "test" }).connect().then(sock2 => {
|
const sock2 = await new RPCSocket(8080, 'localhost', { path: "test" }).connect()
|
||||||
sock2.Grp2.test().then(resp => {
|
const resp = await sock2.Grp2.test()
|
||||||
if(resp === "/test")
|
expect(resp).to.be.equal("/test")
|
||||||
done()
|
|
||||||
else
|
|
||||||
done(new Error("response did not match"))
|
|
||||||
|
|
||||||
server.close()
|
server.close()
|
||||||
server2.close()
|
server2.close()
|
||||||
@@ -441,9 +412,6 @@ describe("can attach second RPCServer if first is already running", () => {
|
|||||||
sock2.close()
|
sock2.close()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('Serverside Triggers', () => {
|
describe('Serverside Triggers', () => {
|
||||||
let server, client
|
let server, client
|
||||||
@@ -509,33 +477,19 @@ describe('RPCSocket', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
it('should have rpc echo', (done) => {
|
it('should have rpc echo', async() => {
|
||||||
client['test'].echo("x").then(x => {
|
const x = await client['test'].echo("x")
|
||||||
if (x === 'x')
|
expect(x).to.be.equal('x')
|
||||||
done()
|
|
||||||
else
|
|
||||||
done(new Error('echo RPC response did not match'))
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add up to 6', (done) => {
|
it('should add up to 6', async() => {
|
||||||
client['test'].add(1, 2, 3).then(x => {
|
const sum = await client['test'].add(1, 2, 3)
|
||||||
if (x === 6)
|
expect(sum).to.be.equal(6)
|
||||||
done()
|
|
||||||
else
|
|
||||||
done(new Error('add RPC response did not match'))
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should subscribe with success', (done) => {
|
it('should subscribe with success', async () => {
|
||||||
client['test'].simpleSubscribe(console.log).then(res => {
|
const res = await client['test'].simpleSubscribe(noop)
|
||||||
if (res.topic === 'test') {
|
expect(res.topic).to.be.equal('test')
|
||||||
done()
|
|
||||||
} else {
|
|
||||||
console.error(res)
|
|
||||||
done(new Error('Subscribe did not return success'))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('subscribe should call back', (done) => {
|
it('subscribe should call back', (done) => {
|
||||||
@@ -616,38 +570,30 @@ describe('It should do unhook', () => {
|
|||||||
server.close()
|
server.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Subscribe with param', (done) => {
|
it('Subscribe with param', async () => {
|
||||||
client['test'].subscribeWithParam("OK", noop).then(async (res) => {
|
const res = await client['test'].subscribeWithParam("OK", noop)
|
||||||
if (res.uuid === candy) {
|
expect(res.uuid).to.be.equal(candy)
|
||||||
done()
|
|
||||||
} else
|
|
||||||
done(new Error("Results did not match " + res.uuid))
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
let run = 0
|
let run = 0
|
||||||
const expected = [yesCandy, noCandy, noCandy, noCandy]
|
const expected = [yesCandy, noCandy, noCandy, noCandy]
|
||||||
|
|
||||||
it('Unhook+unsubscribe should stop callbacks', (done) => {
|
it('Unhook+unsubscribe should stop callbacks', async() => {
|
||||||
|
await client['test'].subscribe(function myCallback(c) {
|
||||||
client['test'].subscribe(function myCallback(c) {
|
|
||||||
if (run == 1)
|
if (run == 1)
|
||||||
(myCallback as any).destroy()
|
(myCallback as any).destroy()
|
||||||
|
expect(c).to.equal(expected[run++])
|
||||||
|
})
|
||||||
|
|
||||||
if (c !== expected[run++]) {
|
|
||||||
done(new Error(`Wrong candy '${c}' in iteration '${run - 1}'`))
|
|
||||||
}
|
|
||||||
}).then(async function (res) {
|
|
||||||
const r1 = await client['test'].publish()
|
const r1 = await client['test'].publish()
|
||||||
const r3 = await client['test'].unsubscribe()
|
const r3 = await client['test'].unsubscribe()
|
||||||
const r2 = await client['test'].publish()
|
const r2 = await client['test'].publish()
|
||||||
const r4 = await client['test'].publish()
|
const r4 = await client['test'].publish()
|
||||||
|
|
||||||
if (r1 === yesCandy && r3 === noCandy && r2 === noCandy && r4 === noCandy)
|
expect(r1).to.be.equal(yesCandy)
|
||||||
done()
|
expect(r2).to.be.equal(noCandy)
|
||||||
else
|
expect(r3).to.be.equal(noCandy)
|
||||||
done(new Error("Results did not match: " + [r1, r2, r3, r4]))
|
expect(r4).to.be.equal(noCandy)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -700,42 +646,34 @@ describe('Sesame should unlock the socket', () => {
|
|||||||
server.close()
|
server.close()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should work with sesame', (done) => {
|
it('should work with sesame', async () => {
|
||||||
client.test.checkCandy().then(c => done())
|
const c = client.test.checkCandy()
|
||||||
|
expect(c).to.exist
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should work with multiple params', (done) => {
|
it('should work with multiple params', async () => {
|
||||||
client.test['manyParams']('a', 'b', 'c', 'd').then(c => {
|
const c = await client.test['manyParams']('a', 'b', 'c', 'd')
|
||||||
if (c[0] == 'a' && c[1] === 'b' && c[2] === 'c' && c[3] === 'd')
|
expect(c[0]).to.be.equal('a')
|
||||||
done()
|
expect(c[1]).to.be.equal('b')
|
||||||
})
|
expect(c[2]).to.be.equal('c')
|
||||||
|
expect(c[3]).to.be.equal('d')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not work without sesame', (done) => {
|
it('should not work without sesame', async () => {
|
||||||
const sock = new RPCSocket(21004, "localhost")
|
const sock = new RPCSocket(21004, "localhost")
|
||||||
sock.connect().then(async (cli) => {
|
const cli = await sock.connect()
|
||||||
if (!cli.test)
|
expect(cli.test).to.not.exist
|
||||||
done()
|
|
||||||
else {
|
|
||||||
done(new Error("Function supposed to be removed without sesame"))
|
|
||||||
}
|
|
||||||
cli.close()
|
cli.close()
|
||||||
sock.close()
|
sock.close()
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
it('should fail with wrong sesame', (done) => {
|
it('should fail with wrong sesame', async () => {
|
||||||
const sock = new RPCSocket(21004, "localhost")
|
const sock = new RPCSocket(21004, "localhost")
|
||||||
sock.connect('abasd').then(async (cli) => {
|
const cli = await sock.connect('iamwrong')
|
||||||
if (!cli.test)
|
expect(cli.test).to.not.exist
|
||||||
done()
|
|
||||||
else {
|
|
||||||
done(new Error("Function supposed to be removed without sesame"))
|
|
||||||
}
|
|
||||||
cli.close()
|
cli.close()
|
||||||
sock.close()
|
sock.close()
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
it('callback should work with sesame', (done) => {
|
it('callback should work with sesame', (done) => {
|
||||||
client.test.subscribe((c) => {
|
client.test.subscribe((c) => {
|
||||||
@@ -926,6 +864,7 @@ describe("Class binding", () => {
|
|||||||
let serv: RPCServer<myExporterIfc>
|
let serv: RPCServer<myExporterIfc>
|
||||||
let sock: RPCSocket & myExporterIfc
|
let sock: RPCSocket & myExporterIfc
|
||||||
let allowed = true
|
let allowed = true
|
||||||
|
const SESAME = 'xyz'
|
||||||
|
|
||||||
class MyExporter implements RPCExporter<myExporterIfc>{
|
class MyExporter implements RPCExporter<myExporterIfc>{
|
||||||
name = "MyExporter" as "MyExporter"
|
name = "MyExporter" as "MyExporter"
|
||||||
@@ -960,12 +899,12 @@ describe("Class binding", () => {
|
|||||||
if (exporter.name === 'MyExporter') {
|
if (exporter.name === 'MyExporter') {
|
||||||
if (!allowed) return false
|
if (!allowed) return false
|
||||||
allowed = false
|
allowed = false
|
||||||
return sesame === 'xxx';
|
return sesame === SESAME;
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sesame: "xxx"
|
sesame: SESAME
|
||||||
})
|
})
|
||||||
serv.listen(21004)
|
serv.listen(21004)
|
||||||
done()
|
done()
|
||||||
@@ -973,7 +912,7 @@ describe("Class binding", () => {
|
|||||||
|
|
||||||
beforeEach((done) => {
|
beforeEach((done) => {
|
||||||
const s = new RPCSocket<myExporterIfc>(21004, 'localhost')
|
const s = new RPCSocket<myExporterIfc>(21004, 'localhost')
|
||||||
s.connect("xxx").then(conn => {
|
s.connect(SESAME).then(conn => {
|
||||||
sock = conn
|
sock = conn
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user