unit tests, and some cleaning up
This commit is contained in:
21
node_modules/mock-socket/LICENSE.txt
generated
vendored
Normal file
21
node_modules/mock-socket/LICENSE.txt
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Travis Hoover
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
232
node_modules/mock-socket/README.md
generated
vendored
Normal file
232
node_modules/mock-socket/README.md
generated
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
<p align="center">
|
||||
<img width=600 src="http://imgur.com/Xt9X83M.png">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
Javascript mocking library for <a href="https://developer.mozilla.org/en-US/docs/WebSockets">websockets</a> and <a href="http://socket.io/">socket.io</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/thoov/mock-socket">
|
||||
<img src="https://img.shields.io/travis/thoov/mock-socket.svg?style=for-the-badge" alt="Build Status">
|
||||
</a>
|
||||
<a href="https://github.com/thoov/mock-socket/blob/master/LICENSE.txt">
|
||||
<img src="https://img.shields.io/github/license/thoov/mock-socket.svg?style=for-the-badge" alt="Code Coverage">
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/mock-socket">
|
||||
<img src="https://img.shields.io/npm/v/mock-socket.svg?style=for-the-badge" alt="NPM Version">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Contents
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Basic Usage](#usage)
|
||||
- [Advanced Usage](#advanced-usage)
|
||||
- [Typescript Support](#typescript-support)
|
||||
- [Socket.IO](#socket-io)
|
||||
- [Contributing](#contributing)
|
||||
- [Feedback](#feedback)
|
||||
|
||||
## Installation
|
||||
|
||||
```shell
|
||||
npm install mock-socket
|
||||
```
|
||||
|
||||
```js
|
||||
import { WebSocket, Server } from 'mock-socket';
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import test from 'ava';
|
||||
import { Server } from 'mock-socket';
|
||||
|
||||
class ChatApp {
|
||||
constructor(url) {
|
||||
this.messages = [];
|
||||
this.connection = new WebSocket(url);
|
||||
|
||||
this.connection.onmessage = (event) => {
|
||||
this.messages.push(event.data);
|
||||
};
|
||||
}
|
||||
|
||||
sendMessage(message) {
|
||||
this.connection.send(message);
|
||||
}
|
||||
}
|
||||
|
||||
test.cb('that chat app can be mocked', t => {
|
||||
const fakeURL = 'ws://localhost:8080';
|
||||
const mockServer = new Server(fakeURL);
|
||||
|
||||
mockServer.on('connection', socket => {
|
||||
socket.on('message', data => {
|
||||
t.is(data, 'test message from app', 'we have intercepted the message and can assert on it');
|
||||
socket.send('test message from mock server');
|
||||
});
|
||||
});
|
||||
|
||||
const app = new ChatApp(fakeURL);
|
||||
app.sendMessage('test message from app'); // NOTE: this line creates a micro task
|
||||
|
||||
// NOTE: this timeout is for creating another micro task that will happen after the above one
|
||||
setTimeout(() => {
|
||||
t.is(app.messages.length, 1);
|
||||
t.is(app.messages[0], 'test message from mock server', 'we have subbed our websocket backend');
|
||||
mockServer.stop(t.done);
|
||||
}, 100);
|
||||
});
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Stubbing the "global"
|
||||
|
||||
```js
|
||||
import { WebSocket, Server } from 'mock-socket';
|
||||
|
||||
/*
|
||||
* By default the global WebSocket object is stubbed out. However,
|
||||
* if you need to stub something else out you can like so:
|
||||
*/
|
||||
|
||||
window.WebSocket = WebSocket; // Here we stub out the window object
|
||||
```
|
||||
|
||||
### Server Methods
|
||||
|
||||
```js
|
||||
const mockServer = new Server('ws://localhost:8080');
|
||||
|
||||
mockServer.on('connection', socket => {
|
||||
socket.on('message', () => {});
|
||||
socket.on('close', () => {});
|
||||
|
||||
socket.send('message');
|
||||
socket.close();
|
||||
});
|
||||
|
||||
mockServer.clients() // array of all connected clients
|
||||
mockServer.emit('room', 'message');
|
||||
mockServer.stop(optionalCallback);
|
||||
```
|
||||
## Typescript Support
|
||||
|
||||
A [declaration file](https://github.com/thoov/mock-socket/blob/master/index.d.ts) is included by default. If you notice any issues with the types please create an issue or a PR!
|
||||
|
||||
## Socket IO
|
||||
|
||||
[Socket.IO](https://socket.io/) has **limited support**. Below is a similar example to the one above but modified to show off socket.io support.
|
||||
|
||||
```js
|
||||
import test from 'ava';
|
||||
import { SocketIO, Server } from 'mock-socket';
|
||||
|
||||
class ChatApp {
|
||||
constructor(url) {
|
||||
this.messages = [];
|
||||
this.connection = new io(url);
|
||||
|
||||
this.connection.on('chat-message', data => {
|
||||
this.messages.push(event.data);
|
||||
};
|
||||
}
|
||||
|
||||
sendMessage(message) {
|
||||
this.connection.emit('chat-message', message);
|
||||
}
|
||||
}
|
||||
|
||||
test.cb('that socket.io works', t => {
|
||||
const fakeURL = 'ws://localhost:8080';
|
||||
const mockServer = new Server(fakeURL);
|
||||
|
||||
window.io = SocketIO;
|
||||
|
||||
mockServer.on('connection', socket => {
|
||||
socket.on('chat-message', data => {
|
||||
t.is(data, 'test message from app', 'we have intercepted the message and can assert on it');
|
||||
socket.emit('chat-message', 'test message from mock server');
|
||||
});
|
||||
});
|
||||
|
||||
const app = new ChatApp(fakeURL);
|
||||
app.sendMessage('test message from app');
|
||||
|
||||
setTimeout(() => {
|
||||
t.is(app.messages.length, 1);
|
||||
t.is(app.messages[0], 'test message from mock server', 'we have subbed our websocket backend');
|
||||
|
||||
mockServer.stop(t.done);
|
||||
}, 100);
|
||||
});
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
The easiest way to work on the project is to clone the repo down via:
|
||||
|
||||
```shell
|
||||
git clone git@github.com:thoov/mock-socket.git
|
||||
cd mock-socket
|
||||
yarn install
|
||||
```
|
||||
|
||||
Then to create a local build via:
|
||||
|
||||
```shell
|
||||
yarn build
|
||||
```
|
||||
|
||||
Then create a local npm link via:
|
||||
|
||||
```shell
|
||||
yarn link
|
||||
```
|
||||
|
||||
At this point you can create other projects / apps locally and reference this local build via:
|
||||
|
||||
```shell
|
||||
yarn link mock-socket
|
||||
```
|
||||
|
||||
from within your other projects folder. Make sure that after any changes you run `yarn build`!
|
||||
|
||||
### Tests
|
||||
This project uses [ava.js](https://github.com/avajs/ava) as its test framework. Tests are located in /tests. To run tests:
|
||||
|
||||
```shell
|
||||
yarn test
|
||||
```
|
||||
|
||||
### Linting
|
||||
|
||||
This project uses eslint and a rules set from [airbnb's javascript style guides](https://github.com/airbnb/javascript). To run linting:
|
||||
|
||||
```shell
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Formatting
|
||||
|
||||
This project uses [prettier](https://github.com/prettier/prettier). To run the formatting:
|
||||
|
||||
```shell
|
||||
yarn format
|
||||
```
|
||||
|
||||
### Code Coverage
|
||||
|
||||
Code coverage reports are created in /coverage after all of the tests have successfully passed. To run the coverage:
|
||||
|
||||
```shell
|
||||
yarn test:coverage
|
||||
```
|
||||
|
||||
## Feedback
|
||||
|
||||
If you have any feedback, encounter any bugs, or just have a question, please feel free to create a [github issue](https://github.com/thoov/mock-socket/issues/new) or send me a tweet at [@thoov](https://twitter.com/thoov).
|
1928
node_modules/mock-socket/dist/mock-socket.amd.js
generated
vendored
Normal file
1928
node_modules/mock-socket/dist/mock-socket.amd.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1926
node_modules/mock-socket/dist/mock-socket.cjs.js
generated
vendored
Normal file
1926
node_modules/mock-socket/dist/mock-socket.cjs.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1920
node_modules/mock-socket/dist/mock-socket.es.js
generated
vendored
Normal file
1920
node_modules/mock-socket/dist/mock-socket.es.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1932
node_modules/mock-socket/dist/mock-socket.js
generated
vendored
Normal file
1932
node_modules/mock-socket/dist/mock-socket.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
84
node_modules/mock-socket/index.d.ts
generated
vendored
Normal file
84
node_modules/mock-socket/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
// Type definitions for Mock Socket 8.X+
|
||||
// Project: Mock Socket
|
||||
// Definitions by: Travis Hoover <https://github.com/thoov/mock-socket>
|
||||
|
||||
declare module 'mock-socket' {
|
||||
class EventTarget {
|
||||
listeners: any;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void;
|
||||
dispatchEvent(evt: Event): boolean;
|
||||
removeEventListener(type: string, listener?: EventListenerOrEventListenerObject | null, options?: EventListenerOptions | boolean): void;
|
||||
}
|
||||
|
||||
//
|
||||
// https://html.spec.whatwg.org/multipage/web-sockets.html#websocket
|
||||
//
|
||||
class WebSocket extends EventTarget {
|
||||
constructor(url?: string, protocols?: string|string[]);
|
||||
|
||||
static readonly CONNECTING: 0;
|
||||
static readonly OPEN: 1;
|
||||
static readonly CLOSING: 2;
|
||||
static readonly CLOSED: 3;
|
||||
|
||||
readonly url: string;
|
||||
|
||||
readonly CONNECTING: 0;
|
||||
readonly OPEN: 1;
|
||||
readonly CLOSING: 2;
|
||||
readonly CLOSED: 3;
|
||||
readonly readyState: number;
|
||||
readonly bufferedAmount: number;
|
||||
|
||||
onopen: EventHandlerNonNull;
|
||||
onerror: EventHandlerNonNull;
|
||||
onclose: EventHandlerNonNull;
|
||||
readonly extensions: string;
|
||||
readonly protocol: string;
|
||||
close(code?: number, reason?: string): void;
|
||||
|
||||
onmessage: EventHandlerNonNull;
|
||||
binaryType: BinaryType;
|
||||
send(data: string | Blob | ArrayBuffer | ArrayBufferView): void;
|
||||
}
|
||||
|
||||
class Server extends EventTarget {
|
||||
constructor(url: string, options?: ServerOptions);
|
||||
|
||||
readonly options?: ServerOptions;
|
||||
|
||||
start(): void;
|
||||
stop(callback?: () => void): void;
|
||||
|
||||
on(type: string, callback: (socket: WebSocket) => void): void;
|
||||
close(options?: CloseOptions): void;
|
||||
emit(event: string, data: any, options?: EmitOptions): void;
|
||||
|
||||
clients(): WebSocket[];
|
||||
to(room: any, broadcaster: any, broadcastList?: object): ToReturnObject;
|
||||
in(any: any): ToReturnObject;
|
||||
simulate(event: Event): void;
|
||||
|
||||
public of(url: string): Server;
|
||||
}
|
||||
|
||||
interface CloseOptions {
|
||||
code: number;
|
||||
reason: string;
|
||||
wasClean: boolean;
|
||||
}
|
||||
|
||||
interface EmitOptions {
|
||||
websockets: WebSocket[];
|
||||
}
|
||||
|
||||
interface ToReturnObject {
|
||||
to: (chainedRoom: any, chainedBroadcaster: any) => ToReturnObject;
|
||||
emit(event: Event, data: any): void;
|
||||
}
|
||||
|
||||
interface ServerOptions {
|
||||
verifyClient: () => any;
|
||||
selectProtocol: () => any;
|
||||
}
|
||||
}
|
108
node_modules/mock-socket/package.json
generated
vendored
Normal file
108
node_modules/mock-socket/package.json
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
{
|
||||
"_from": "mock-socket",
|
||||
"_id": "mock-socket@8.0.5",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-dE2EbcxJKQCeYLZSsI7BAiMZCe/bHbJ2LHb5aGwUuDmfoOINEJ8QI6qYJ85NHsSNkNa90F3s6onZcmt/+MppFA==",
|
||||
"_location": "/mock-socket",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"registry": true,
|
||||
"raw": "mock-socket",
|
||||
"name": "mock-socket",
|
||||
"escapedName": "mock-socket",
|
||||
"rawSpec": "",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#DEV:/",
|
||||
"#USER"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-8.0.5.tgz",
|
||||
"_shasum": "4ce8909601b2bcdf5f7680f35c2f7b34beb2afc4",
|
||||
"_spec": "mock-socket",
|
||||
"_where": "/Users/josh.burman/Projects/braid",
|
||||
"author": {
|
||||
"name": "Travis Hoover"
|
||||
},
|
||||
"ava": {
|
||||
"files": [
|
||||
"tests/**/*.test.js"
|
||||
],
|
||||
"require": [
|
||||
"babel-register",
|
||||
"babel-polyfill"
|
||||
],
|
||||
"babel": "inherit"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/thoov/mock-socket/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"url-parse": "^1.2.0"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Javascript mocking library for websockets and socket.io",
|
||||
"devDependencies": {
|
||||
"ava": "^0.19.1",
|
||||
"babel-core": "^6.24.1",
|
||||
"babel-loader": "^7.0.0",
|
||||
"babel-polyfill": "^6.23.0",
|
||||
"babel-preset-latest": "^6.24.1",
|
||||
"cross-env": "^5.0.0",
|
||||
"eslint": "^3.19.0",
|
||||
"eslint-config-airbnb-base": "^11.2.0",
|
||||
"eslint-plugin-import": "^2.0.1",
|
||||
"husky": "^0.13.3",
|
||||
"jsdom": "^11.5.1",
|
||||
"lint-staged": "^3.4.1",
|
||||
"nyc": "^10.3.2",
|
||||
"prettier": "^1.3.1",
|
||||
"rollup": "^0.41.6",
|
||||
"rollup-plugin-buble": "^0.15.0",
|
||||
"rollup-plugin-commonjs": "^8.2.6",
|
||||
"rollup-plugin-node-resolve": "^3.0.0",
|
||||
"systemjs": "^0.20.12",
|
||||
"typescript": "^2.9.2",
|
||||
"typescript-eslint-parser": "^16.0.1"
|
||||
},
|
||||
"directories": {
|
||||
"test": "tests"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
},
|
||||
"homepage": "https://github.com/thoov/mock-socket",
|
||||
"keywords": [
|
||||
"websockets",
|
||||
"mock",
|
||||
"mocksocket",
|
||||
"sockets"
|
||||
],
|
||||
"license": "MIT",
|
||||
"lint-staged": {
|
||||
"*.js": [
|
||||
"format",
|
||||
"lint",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"main": "./dist/mock-socket",
|
||||
"name": "mock-socket",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/thoov/mock-socket.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rm -rf dist && rollup -c rollup.config.js",
|
||||
"format": "prettier --print-width 120 --single-quote --write '{src,tests}/**/*.js'",
|
||||
"lint": "eslint src tests",
|
||||
"precommit": "lint-staged",
|
||||
"prepublishOnly": "yarn build",
|
||||
"test": "cross-env NODE_ENV=test ava --serial --verbose",
|
||||
"test:coverage": "cross-env NODE_ENV=test nyc ava --serial"
|
||||
},
|
||||
"version": "8.0.5"
|
||||
}
|
57
node_modules/mock-socket/src/algorithms/close.js
generated
vendored
Normal file
57
node_modules/mock-socket/src/algorithms/close.js
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
import WebSocket from '../websocket';
|
||||
import delay from '../helpers/delay';
|
||||
import networkBridge from '../network-bridge';
|
||||
import { createCloseEvent, createEvent } from '../event/factory';
|
||||
|
||||
export function closeWebSocketConnection(context, code, reason) {
|
||||
context.readyState = WebSocket.CLOSING;
|
||||
|
||||
const server = networkBridge.serverLookup(context.url);
|
||||
const closeEvent = createCloseEvent({
|
||||
type: 'close',
|
||||
target: context,
|
||||
code,
|
||||
reason
|
||||
});
|
||||
|
||||
delay(() => {
|
||||
networkBridge.removeWebSocket(context, context.url);
|
||||
|
||||
context.readyState = WebSocket.CLOSED;
|
||||
context.dispatchEvent(closeEvent);
|
||||
|
||||
if (server) {
|
||||
server.dispatchEvent(closeEvent, server);
|
||||
}
|
||||
}, context);
|
||||
}
|
||||
|
||||
export function failWebSocketConnection(context, code, reason) {
|
||||
context.readyState = WebSocket.CLOSING;
|
||||
|
||||
const server = networkBridge.serverLookup(context.url);
|
||||
const closeEvent = createCloseEvent({
|
||||
type: 'close',
|
||||
target: context,
|
||||
code,
|
||||
reason,
|
||||
wasClean: false
|
||||
});
|
||||
|
||||
const errorEvent = createEvent({
|
||||
type: 'error',
|
||||
target: context
|
||||
});
|
||||
|
||||
delay(() => {
|
||||
networkBridge.removeWebSocket(context, context.url);
|
||||
|
||||
context.readyState = WebSocket.CLOSED;
|
||||
context.dispatchEvent(errorEvent);
|
||||
context.dispatchEvent(closeEvent);
|
||||
|
||||
if (server) {
|
||||
server.dispatchEvent(closeEvent, server);
|
||||
}
|
||||
}, context);
|
||||
}
|
29
node_modules/mock-socket/src/constants.js
generated
vendored
Normal file
29
node_modules/mock-socket/src/constants.js
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
||||
*/
|
||||
export const CLOSE_CODES = {
|
||||
CLOSE_NORMAL: 1000,
|
||||
CLOSE_GOING_AWAY: 1001,
|
||||
CLOSE_PROTOCOL_ERROR: 1002,
|
||||
CLOSE_UNSUPPORTED: 1003,
|
||||
CLOSE_NO_STATUS: 1005,
|
||||
CLOSE_ABNORMAL: 1006,
|
||||
UNSUPPORTED_DATA: 1007,
|
||||
POLICY_VIOLATION: 1008,
|
||||
CLOSE_TOO_LARGE: 1009,
|
||||
MISSING_EXTENSION: 1010,
|
||||
INTERNAL_ERROR: 1011,
|
||||
SERVICE_RESTART: 1012,
|
||||
TRY_AGAIN_LATER: 1013,
|
||||
TLS_HANDSHAKE: 1015
|
||||
};
|
||||
|
||||
export const ERROR_PREFIX = {
|
||||
CONSTRUCTOR_ERROR: "Failed to construct 'WebSocket':",
|
||||
CLOSE_ERROR: "Failed to execute 'close' on 'WebSocket':",
|
||||
EVENT: {
|
||||
CONSTRUCT: "Failed to construct 'Event':",
|
||||
MESSAGE: "Failed to construct 'MessageEvent':",
|
||||
CLOSE: "Failed to construct 'CloseEvent':"
|
||||
}
|
||||
};
|
34
node_modules/mock-socket/src/event/close.js
generated
vendored
Normal file
34
node_modules/mock-socket/src/event/close.js
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
import EventPrototype from './prototype';
|
||||
import { ERROR_PREFIX } from '../constants';
|
||||
|
||||
export default class CloseEvent extends EventPrototype {
|
||||
constructor(type, eventInitConfig = {}) {
|
||||
super();
|
||||
|
||||
if (!type) {
|
||||
throw new TypeError(`${ERROR_PREFIX.EVENT.CLOSE} 1 argument required, but only 0 present.`);
|
||||
}
|
||||
|
||||
if (typeof eventInitConfig !== 'object') {
|
||||
throw new TypeError(`${ERROR_PREFIX.EVENT.CLOSE} parameter 2 ('eventInitDict') is not an object`);
|
||||
}
|
||||
|
||||
const { bubbles, cancelable, code, reason, wasClean } = eventInitConfig;
|
||||
|
||||
this.type = `${type}`;
|
||||
this.timeStamp = Date.now();
|
||||
this.target = null;
|
||||
this.srcElement = null;
|
||||
this.returnValue = true;
|
||||
this.isTrusted = false;
|
||||
this.eventPhase = 0;
|
||||
this.defaultPrevented = false;
|
||||
this.currentTarget = null;
|
||||
this.cancelable = cancelable ? Boolean(cancelable) : false;
|
||||
this.cancelBubble = false;
|
||||
this.bubbles = bubbles ? Boolean(bubbles) : false;
|
||||
this.code = typeof code === 'number' ? parseInt(code, 10) : 0;
|
||||
this.reason = `${reason || ''}`;
|
||||
this.wasClean = wasClean ? Boolean(wasClean) : false;
|
||||
}
|
||||
}
|
31
node_modules/mock-socket/src/event/event.js
generated
vendored
Normal file
31
node_modules/mock-socket/src/event/event.js
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
import EventPrototype from './prototype';
|
||||
import { ERROR_PREFIX } from '../constants';
|
||||
|
||||
export default class Event extends EventPrototype {
|
||||
constructor(type, eventInitConfig = {}) {
|
||||
super();
|
||||
|
||||
if (!type) {
|
||||
throw new TypeError(`${ERROR_PREFIX.EVENT_ERROR} 1 argument required, but only 0 present.`);
|
||||
}
|
||||
|
||||
if (typeof eventInitConfig !== 'object') {
|
||||
throw new TypeError(`${ERROR_PREFIX.EVENT_ERROR} parameter 2 ('eventInitDict') is not an object.`);
|
||||
}
|
||||
|
||||
const { bubbles, cancelable } = eventInitConfig;
|
||||
|
||||
this.type = `${type}`;
|
||||
this.timeStamp = Date.now();
|
||||
this.target = null;
|
||||
this.srcElement = null;
|
||||
this.returnValue = true;
|
||||
this.isTrusted = false;
|
||||
this.eventPhase = 0;
|
||||
this.defaultPrevented = false;
|
||||
this.currentTarget = null;
|
||||
this.cancelable = cancelable ? Boolean(cancelable) : false;
|
||||
this.canncelBubble = false;
|
||||
this.bubbles = bubbles ? Boolean(bubbles) : false;
|
||||
}
|
||||
}
|
75
node_modules/mock-socket/src/event/factory.js
generated
vendored
Normal file
75
node_modules/mock-socket/src/event/factory.js
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
import Event from './event';
|
||||
import MessageEvent from './message';
|
||||
import CloseEvent from './close';
|
||||
|
||||
/*
|
||||
* Creates an Event object and extends it to allow full modification of
|
||||
* its properties.
|
||||
*
|
||||
* @param {object} config - within config you will need to pass type and optionally target
|
||||
*/
|
||||
function createEvent(config) {
|
||||
const { type, target } = config;
|
||||
const eventObject = new Event(type);
|
||||
|
||||
if (target) {
|
||||
eventObject.target = target;
|
||||
eventObject.srcElement = target;
|
||||
eventObject.currentTarget = target;
|
||||
}
|
||||
|
||||
return eventObject;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a MessageEvent object and extends it to allow full modification of
|
||||
* its properties.
|
||||
*
|
||||
* @param {object} config - within config: type, origin, data and optionally target
|
||||
*/
|
||||
function createMessageEvent(config) {
|
||||
const { type, origin, data, target } = config;
|
||||
const messageEvent = new MessageEvent(type, {
|
||||
data,
|
||||
origin
|
||||
});
|
||||
|
||||
if (target) {
|
||||
messageEvent.target = target;
|
||||
messageEvent.srcElement = target;
|
||||
messageEvent.currentTarget = target;
|
||||
}
|
||||
|
||||
return messageEvent;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a CloseEvent object and extends it to allow full modification of
|
||||
* its properties.
|
||||
*
|
||||
* @param {object} config - within config: type and optionally target, code, and reason
|
||||
*/
|
||||
function createCloseEvent(config) {
|
||||
const { code, reason, type, target } = config;
|
||||
let { wasClean } = config;
|
||||
|
||||
if (!wasClean) {
|
||||
wasClean = code === 1000;
|
||||
}
|
||||
|
||||
const closeEvent = new CloseEvent(type, {
|
||||
code,
|
||||
reason,
|
||||
wasClean
|
||||
});
|
||||
|
||||
if (target) {
|
||||
closeEvent.target = target;
|
||||
closeEvent.srcElement = target;
|
||||
closeEvent.currentTarget = target;
|
||||
}
|
||||
|
||||
return closeEvent;
|
||||
}
|
||||
|
||||
export { createEvent, createMessageEvent, createCloseEvent };
|
35
node_modules/mock-socket/src/event/message.js
generated
vendored
Normal file
35
node_modules/mock-socket/src/event/message.js
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
import EventPrototype from './prototype';
|
||||
import { ERROR_PREFIX } from '../constants';
|
||||
|
||||
export default class MessageEvent extends EventPrototype {
|
||||
constructor(type, eventInitConfig = {}) {
|
||||
super();
|
||||
|
||||
if (!type) {
|
||||
throw new TypeError(`${ERROR_PREFIX.EVENT.MESSAGE} 1 argument required, but only 0 present.`);
|
||||
}
|
||||
|
||||
if (typeof eventInitConfig !== 'object') {
|
||||
throw new TypeError(`${ERROR_PREFIX.EVENT.MESSAGE} parameter 2 ('eventInitDict') is not an object`);
|
||||
}
|
||||
|
||||
const { bubbles, cancelable, data, origin, lastEventId, ports } = eventInitConfig;
|
||||
|
||||
this.type = `${type}`;
|
||||
this.timeStamp = Date.now();
|
||||
this.target = null;
|
||||
this.srcElement = null;
|
||||
this.returnValue = true;
|
||||
this.isTrusted = false;
|
||||
this.eventPhase = 0;
|
||||
this.defaultPrevented = false;
|
||||
this.currentTarget = null;
|
||||
this.cancelable = cancelable ? Boolean(cancelable) : false;
|
||||
this.canncelBubble = false;
|
||||
this.bubbles = bubbles ? Boolean(bubbles) : false;
|
||||
this.origin = `${origin}`;
|
||||
this.ports = typeof ports === 'undefined' ? null : ports;
|
||||
this.data = typeof data === 'undefined' ? null : data;
|
||||
this.lastEventId = `${lastEventId || ''}`;
|
||||
}
|
||||
}
|
13
node_modules/mock-socket/src/event/prototype.js
generated
vendored
Normal file
13
node_modules/mock-socket/src/event/prototype.js
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
export default class EventPrototype {
|
||||
// Noops
|
||||
stopPropagation() {}
|
||||
stopImmediatePropagation() {}
|
||||
|
||||
// if no arguments are passed then the type is set to "undefined" on
|
||||
// chrome and safari.
|
||||
initEvent(type = 'undefined', bubbles = false, cancelable = false) {
|
||||
this.type = `${type}`;
|
||||
this.bubbles = Boolean(bubbles);
|
||||
this.cancelable = Boolean(cancelable);
|
||||
}
|
||||
}
|
73
node_modules/mock-socket/src/event/target.js
generated
vendored
Normal file
73
node_modules/mock-socket/src/event/target.js
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
import { reject, filter } from '../helpers/array-helpers';
|
||||
|
||||
/*
|
||||
* EventTarget is an interface implemented by objects that can
|
||||
* receive events and may have listeners for them.
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
|
||||
*/
|
||||
class EventTarget {
|
||||
constructor() {
|
||||
this.listeners = {};
|
||||
}
|
||||
|
||||
/*
|
||||
* Ties a listener function to an event type which can later be invoked via the
|
||||
* dispatchEvent method.
|
||||
*
|
||||
* @param {string} type - the type of event (ie: 'open', 'message', etc.)
|
||||
* @param {function} listener - the callback function to invoke whenever an event is dispatched matching the given type
|
||||
* @param {boolean} useCapture - N/A TODO: implement useCapture functionality
|
||||
*/
|
||||
addEventListener(type, listener /* , useCapture */) {
|
||||
if (typeof listener === 'function') {
|
||||
if (!Array.isArray(this.listeners[type])) {
|
||||
this.listeners[type] = [];
|
||||
}
|
||||
|
||||
// Only add the same function once
|
||||
if (filter(this.listeners[type], item => item === listener).length === 0) {
|
||||
this.listeners[type].push(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the listener so it will no longer be invoked via the dispatchEvent method.
|
||||
*
|
||||
* @param {string} type - the type of event (ie: 'open', 'message', etc.)
|
||||
* @param {function} listener - the callback function to invoke whenever an event is dispatched matching the given type
|
||||
* @param {boolean} useCapture - N/A TODO: implement useCapture functionality
|
||||
*/
|
||||
removeEventListener(type, removingListener /* , useCapture */) {
|
||||
const arrayOfListeners = this.listeners[type];
|
||||
this.listeners[type] = reject(arrayOfListeners, listener => listener === removingListener);
|
||||
}
|
||||
|
||||
/*
|
||||
* Invokes all listener functions that are listening to the given event.type property. Each
|
||||
* listener will be passed the event as the first argument.
|
||||
*
|
||||
* @param {object} event - event object which will be passed to all listeners of the event.type property
|
||||
*/
|
||||
dispatchEvent(event, ...customArguments) {
|
||||
const eventName = event.type;
|
||||
const listeners = this.listeners[eventName];
|
||||
|
||||
if (!Array.isArray(listeners)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
listeners.forEach(listener => {
|
||||
if (customArguments.length > 0) {
|
||||
listener.apply(this, customArguments);
|
||||
} else {
|
||||
listener.call(this, event);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default EventTarget;
|
21
node_modules/mock-socket/src/helpers/array-helpers.js
generated
vendored
Normal file
21
node_modules/mock-socket/src/helpers/array-helpers.js
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
export function reject(array, callback) {
|
||||
const results = [];
|
||||
array.forEach(itemInArray => {
|
||||
if (!callback(itemInArray)) {
|
||||
results.push(itemInArray);
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
export function filter(array, callback) {
|
||||
const results = [];
|
||||
array.forEach(itemInArray => {
|
||||
if (callback(itemInArray)) {
|
||||
results.push(itemInArray);
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
5
node_modules/mock-socket/src/helpers/byte-length.js
generated
vendored
Normal file
5
node_modules/mock-socket/src/helpers/byte-length.js
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
export default function lengthInUtf8Bytes(str) {
|
||||
// Matches only the 10.. bytes that are non-initial characters in a multi-byte sequence.
|
||||
const m = encodeURIComponent(str).match(/%[89ABab]/g);
|
||||
return str.length + (m ? m.length : 0);
|
||||
}
|
5
node_modules/mock-socket/src/helpers/dedupe.js
generated
vendored
Normal file
5
node_modules/mock-socket/src/helpers/dedupe.js
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
export default arr =>
|
||||
arr.reduce((deduped, b) => {
|
||||
if (deduped.indexOf(b) > -1) return deduped;
|
||||
return deduped.concat(b);
|
||||
}, []);
|
11
node_modules/mock-socket/src/helpers/delay.js
generated
vendored
Normal file
11
node_modules/mock-socket/src/helpers/delay.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/*
|
||||
* This delay allows the thread to finish assigning its on* methods
|
||||
* before invoking the delay callback. This is purely a timing hack.
|
||||
* http://geekabyte.blogspot.com/2014/01/javascript-effect-of-setting-settimeout.html
|
||||
*
|
||||
* @param {callback: function} the callback which will be invoked after the timeout
|
||||
* @parma {context: object} the context in which to invoke the function
|
||||
*/
|
||||
export default function delay(callback, context) {
|
||||
setTimeout(timeoutContext => callback.call(timeoutContext), 4, context);
|
||||
}
|
7
node_modules/mock-socket/src/helpers/global-object.js
generated
vendored
Normal file
7
node_modules/mock-socket/src/helpers/global-object.js
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
export default function retrieveGlobalObject() {
|
||||
if (typeof window !== 'undefined') {
|
||||
return window;
|
||||
}
|
||||
|
||||
return typeof process === 'object' && typeof require === 'function' && typeof global === 'object' ? global : this;
|
||||
}
|
7
node_modules/mock-socket/src/helpers/logger.js
generated
vendored
Normal file
7
node_modules/mock-socket/src/helpers/logger.js
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
export default function log(method, message) {
|
||||
/* eslint-disable no-console */
|
||||
if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'test') {
|
||||
console[method].call(null, message);
|
||||
}
|
||||
/* eslint-enable no-console */
|
||||
}
|
7
node_modules/mock-socket/src/helpers/normalize-send.js
generated
vendored
Normal file
7
node_modules/mock-socket/src/helpers/normalize-send.js
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
export default function normalizeSendData(data) {
|
||||
if (Object.prototype.toString.call(data) !== '[object Blob]' && !(data instanceof ArrayBuffer)) {
|
||||
data = String(data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
24
node_modules/mock-socket/src/helpers/protocol-verification.js
generated
vendored
Normal file
24
node_modules/mock-socket/src/helpers/protocol-verification.js
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
import { ERROR_PREFIX } from '../constants';
|
||||
|
||||
export default function protocolVerification(protocols = []) {
|
||||
if (!Array.isArray(protocols) && typeof protocols !== 'string') {
|
||||
throw new SyntaxError(`${ERROR_PREFIX.CONSTRUCTOR_ERROR} The subprotocol '${protocols.toString()}' is invalid.`);
|
||||
}
|
||||
|
||||
if (typeof protocols === 'string') {
|
||||
protocols = [protocols];
|
||||
}
|
||||
|
||||
const uniq = protocols.map(p => ({ count: 1, protocol: p })).reduce((a, b) => {
|
||||
a[b.protocol] = (a[b.protocol] || 0) + b.count;
|
||||
return a;
|
||||
}, {});
|
||||
|
||||
const duplicates = Object.keys(uniq).filter(a => uniq[a] > 1);
|
||||
|
||||
if (duplicates.length > 0) {
|
||||
throw new SyntaxError(`${ERROR_PREFIX.CONSTRUCTOR_ERROR} The subprotocol '${duplicates[0]}' is duplicated.`);
|
||||
}
|
||||
|
||||
return protocols;
|
||||
}
|
45
node_modules/mock-socket/src/helpers/proxy-factory.js
generated
vendored
Normal file
45
node_modules/mock-socket/src/helpers/proxy-factory.js
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
import { CLOSE_CODES } from '../constants';
|
||||
import { closeWebSocketConnection } from '../algorithms/close';
|
||||
import normalizeSendData from './normalize-send';
|
||||
import { createMessageEvent } from '../event/factory';
|
||||
|
||||
export default function proxyFactory(target) {
|
||||
const handler = {
|
||||
get(obj, prop) {
|
||||
if (prop === 'close') {
|
||||
return function close(options = {}) {
|
||||
const code = options.code || CLOSE_CODES.CLOSE_NORMAL;
|
||||
const reason = options.reason || '';
|
||||
|
||||
closeWebSocketConnection(target, code, reason);
|
||||
};
|
||||
}
|
||||
|
||||
if (prop === 'send') {
|
||||
return function send(data) {
|
||||
data = normalizeSendData(data);
|
||||
|
||||
target.dispatchEvent(
|
||||
createMessageEvent({
|
||||
type: 'message',
|
||||
data,
|
||||
origin: this.url,
|
||||
target
|
||||
})
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
if (prop === 'on') {
|
||||
return function onWrapper(type, cb) {
|
||||
target.addEventListener(`server::${type}`, cb);
|
||||
};
|
||||
}
|
||||
|
||||
return obj[prop];
|
||||
}
|
||||
};
|
||||
|
||||
const proxy = new Proxy(target, handler);
|
||||
return proxy;
|
||||
}
|
37
node_modules/mock-socket/src/helpers/url-verification.js
generated
vendored
Normal file
37
node_modules/mock-socket/src/helpers/url-verification.js
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
import URL from 'url-parse';
|
||||
import { ERROR_PREFIX } from '../constants';
|
||||
|
||||
export default function urlVerification(url) {
|
||||
const urlRecord = new URL(url);
|
||||
const { pathname, protocol, hash } = urlRecord;
|
||||
|
||||
if (!url) {
|
||||
throw new TypeError(`${ERROR_PREFIX.CONSTRUCTOR_ERROR} 1 argument required, but only 0 present.`);
|
||||
}
|
||||
|
||||
if (!pathname) {
|
||||
urlRecord.pathname = '/';
|
||||
}
|
||||
|
||||
if (protocol === '') {
|
||||
throw new SyntaxError(`${ERROR_PREFIX.CONSTRUCTOR_ERROR} The URL '${urlRecord.toString()}' is invalid.`);
|
||||
}
|
||||
|
||||
if (protocol !== 'ws:' && protocol !== 'wss:') {
|
||||
throw new SyntaxError(
|
||||
`${ERROR_PREFIX.CONSTRUCTOR_ERROR} The URL's scheme must be either 'ws' or 'wss'. '${protocol}' is not allowed.`
|
||||
);
|
||||
}
|
||||
|
||||
if (hash !== '') {
|
||||
/* eslint-disable max-len */
|
||||
throw new SyntaxError(
|
||||
`${
|
||||
ERROR_PREFIX.CONSTRUCTOR_ERROR
|
||||
} The URL contains a fragment identifier ('${hash}'). Fragment identifiers are not allowed in WebSocket URLs.`
|
||||
);
|
||||
/* eslint-enable max-len */
|
||||
}
|
||||
|
||||
return urlRecord.toString();
|
||||
}
|
7
node_modules/mock-socket/src/index.js
generated
vendored
Normal file
7
node_modules/mock-socket/src/index.js
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import MockServer from './server';
|
||||
import MockSocketIO from './socket-io';
|
||||
import MockWebSocket from './websocket';
|
||||
|
||||
export const Server = MockServer;
|
||||
export const WebSocket = MockWebSocket;
|
||||
export const SocketIO = MockSocketIO;
|
135
node_modules/mock-socket/src/network-bridge.js
generated
vendored
Normal file
135
node_modules/mock-socket/src/network-bridge.js
generated
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
import { reject } from './helpers/array-helpers';
|
||||
|
||||
/*
|
||||
* The network bridge is a way for the mock websocket object to 'communicate' with
|
||||
* all available servers. This is a singleton object so it is important that you
|
||||
* clean up urlMap whenever you are finished.
|
||||
*/
|
||||
class NetworkBridge {
|
||||
constructor() {
|
||||
this.urlMap = {};
|
||||
}
|
||||
|
||||
/*
|
||||
* Attaches a websocket object to the urlMap hash so that it can find the server
|
||||
* it is connected to and the server in turn can find it.
|
||||
*
|
||||
* @param {object} websocket - websocket object to add to the urlMap hash
|
||||
* @param {string} url
|
||||
*/
|
||||
attachWebSocket(websocket, url) {
|
||||
const connectionLookup = this.urlMap[url];
|
||||
|
||||
if (connectionLookup && connectionLookup.server && connectionLookup.websockets.indexOf(websocket) === -1) {
|
||||
connectionLookup.websockets.push(websocket);
|
||||
return connectionLookup.server;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attaches a websocket to a room
|
||||
*/
|
||||
addMembershipToRoom(websocket, room) {
|
||||
const connectionLookup = this.urlMap[websocket.url];
|
||||
|
||||
if (connectionLookup && connectionLookup.server && connectionLookup.websockets.indexOf(websocket) !== -1) {
|
||||
if (!connectionLookup.roomMemberships[room]) {
|
||||
connectionLookup.roomMemberships[room] = [];
|
||||
}
|
||||
|
||||
connectionLookup.roomMemberships[room].push(websocket);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attaches a server object to the urlMap hash so that it can find a websockets
|
||||
* which are connected to it and so that websockets can in turn can find it.
|
||||
*
|
||||
* @param {object} server - server object to add to the urlMap hash
|
||||
* @param {string} url
|
||||
*/
|
||||
attachServer(server, url) {
|
||||
const connectionLookup = this.urlMap[url];
|
||||
|
||||
if (!connectionLookup) {
|
||||
this.urlMap[url] = {
|
||||
server,
|
||||
websockets: [],
|
||||
roomMemberships: {}
|
||||
};
|
||||
|
||||
return server;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the server which is 'running' on the given url.
|
||||
*
|
||||
* @param {string} url - the url to use to find which server is running on it
|
||||
*/
|
||||
serverLookup(url) {
|
||||
const connectionLookup = this.urlMap[url];
|
||||
|
||||
if (connectionLookup) {
|
||||
return connectionLookup.server;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds all websockets which is 'listening' on the given url.
|
||||
*
|
||||
* @param {string} url - the url to use to find all websockets which are associated with it
|
||||
* @param {string} room - if a room is provided, will only return sockets in this room
|
||||
* @param {class} broadcaster - socket that is broadcasting and is to be excluded from the lookup
|
||||
*/
|
||||
websocketsLookup(url, room, broadcaster) {
|
||||
let websockets;
|
||||
const connectionLookup = this.urlMap[url];
|
||||
|
||||
websockets = connectionLookup ? connectionLookup.websockets : [];
|
||||
|
||||
if (room) {
|
||||
const members = connectionLookup.roomMemberships[room];
|
||||
websockets = members || [];
|
||||
}
|
||||
|
||||
return broadcaster ? websockets.filter(websocket => websocket !== broadcaster) : websockets;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the entry associated with the url.
|
||||
*
|
||||
* @param {string} url
|
||||
*/
|
||||
removeServer(url) {
|
||||
delete this.urlMap[url];
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the individual websocket from the map of associated websockets.
|
||||
*
|
||||
* @param {object} websocket - websocket object to remove from the url map
|
||||
* @param {string} url
|
||||
*/
|
||||
removeWebSocket(websocket, url) {
|
||||
const connectionLookup = this.urlMap[url];
|
||||
|
||||
if (connectionLookup) {
|
||||
connectionLookup.websockets = reject(connectionLookup.websockets, socket => socket === websocket);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes a websocket from a room
|
||||
*/
|
||||
removeMembershipFromRoom(websocket, room) {
|
||||
const connectionLookup = this.urlMap[websocket.url];
|
||||
const memberships = connectionLookup.roomMemberships[room];
|
||||
|
||||
if (connectionLookup && memberships !== null) {
|
||||
connectionLookup.roomMemberships[room] = reject(memberships, socket => socket === websocket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new NetworkBridge(); // Note: this is a singleton
|
217
node_modules/mock-socket/src/server.js
generated
vendored
Normal file
217
node_modules/mock-socket/src/server.js
generated
vendored
Normal file
@ -0,0 +1,217 @@
|
||||
import URL from 'url-parse';
|
||||
import WebSocket from './websocket';
|
||||
import dedupe from './helpers/dedupe';
|
||||
import EventTarget from './event/target';
|
||||
import { CLOSE_CODES } from './constants';
|
||||
import networkBridge from './network-bridge';
|
||||
import globalObject from './helpers/global-object';
|
||||
import normalizeSendData from './helpers/normalize-send';
|
||||
import { createEvent, createMessageEvent, createCloseEvent } from './event/factory';
|
||||
|
||||
class Server extends EventTarget {
|
||||
constructor(url, options = {}) {
|
||||
super();
|
||||
const urlRecord = new URL(url);
|
||||
|
||||
if (!urlRecord.pathname) {
|
||||
urlRecord.pathname = '/';
|
||||
}
|
||||
|
||||
this.url = urlRecord.toString();
|
||||
|
||||
this.originalWebSocket = null;
|
||||
const server = networkBridge.attachServer(this, this.url);
|
||||
|
||||
if (!server) {
|
||||
this.dispatchEvent(createEvent({ type: 'error' }));
|
||||
throw new Error('A mock server is already listening on this url');
|
||||
}
|
||||
|
||||
if (typeof options.verifyClient === 'undefined') {
|
||||
options.verifyClient = null;
|
||||
}
|
||||
|
||||
if (typeof options.selectProtocol === 'undefined') {
|
||||
options.selectProtocol = null;
|
||||
}
|
||||
|
||||
this.options = options;
|
||||
this.start();
|
||||
}
|
||||
|
||||
/*
|
||||
* Attaches the mock websocket object to the global object
|
||||
*/
|
||||
start() {
|
||||
const globalObj = globalObject();
|
||||
|
||||
if (globalObj.WebSocket) {
|
||||
this.originalWebSocket = globalObj.WebSocket;
|
||||
}
|
||||
|
||||
globalObj.WebSocket = WebSocket;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the mock websocket object from the global object
|
||||
*/
|
||||
stop(callback = () => {}) {
|
||||
const globalObj = globalObject();
|
||||
|
||||
if (this.originalWebSocket) {
|
||||
globalObj.WebSocket = this.originalWebSocket;
|
||||
} else {
|
||||
delete globalObj.WebSocket;
|
||||
}
|
||||
|
||||
this.originalWebSocket = null;
|
||||
|
||||
networkBridge.removeServer(this.url);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the main function for the mock server to subscribe to the on events.
|
||||
*
|
||||
* ie: mockServer.on('connection', function() { console.log('a mock client connected'); });
|
||||
*
|
||||
* @param {string} type - The event key to subscribe to. Valid keys are: connection, message, and close.
|
||||
* @param {function} callback - The callback which should be called when a certain event is fired.
|
||||
*/
|
||||
on(type, callback) {
|
||||
this.addEventListener(type, callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Closes the connection and triggers the onclose method of all listening
|
||||
* websockets. After that it removes itself from the urlMap so another server
|
||||
* could add itself to the url.
|
||||
*
|
||||
* @param {object} options
|
||||
*/
|
||||
close(options = {}) {
|
||||
const { code, reason, wasClean } = options;
|
||||
const listeners = networkBridge.websocketsLookup(this.url);
|
||||
|
||||
// Remove server before notifications to prevent immediate reconnects from
|
||||
// socket onclose handlers
|
||||
networkBridge.removeServer(this.url);
|
||||
|
||||
listeners.forEach(socket => {
|
||||
socket.readyState = WebSocket.CLOSE;
|
||||
socket.dispatchEvent(
|
||||
createCloseEvent({
|
||||
type: 'close',
|
||||
target: socket,
|
||||
code: code || CLOSE_CODES.CLOSE_NORMAL,
|
||||
reason: reason || '',
|
||||
wasClean
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
this.dispatchEvent(createCloseEvent({ type: 'close' }), this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends a generic message event to all mock clients.
|
||||
*/
|
||||
emit(event, data, options = {}) {
|
||||
let { websockets } = options;
|
||||
|
||||
if (!websockets) {
|
||||
websockets = networkBridge.websocketsLookup(this.url);
|
||||
}
|
||||
|
||||
if (typeof options !== 'object' || arguments.length > 3) {
|
||||
data = Array.prototype.slice.call(arguments, 1, arguments.length);
|
||||
data = data.map(item => normalizeSendData(item));
|
||||
} else {
|
||||
data = normalizeSendData(data);
|
||||
}
|
||||
|
||||
websockets.forEach(socket => {
|
||||
if (Array.isArray(data)) {
|
||||
socket.dispatchEvent(
|
||||
createMessageEvent({
|
||||
type: event,
|
||||
data,
|
||||
origin: this.url,
|
||||
target: socket
|
||||
}),
|
||||
...data
|
||||
);
|
||||
} else {
|
||||
socket.dispatchEvent(
|
||||
createMessageEvent({
|
||||
type: event,
|
||||
data,
|
||||
origin: this.url,
|
||||
target: socket
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an array of websockets which are listening to this server
|
||||
* TOOD: this should return a set and not be a method
|
||||
*/
|
||||
clients() {
|
||||
return networkBridge.websocketsLookup(this.url);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepares a method to submit an event to members of the room
|
||||
*
|
||||
* e.g. server.to('my-room').emit('hi!');
|
||||
*/
|
||||
to(room, broadcaster, broadcastList = []) {
|
||||
const self = this;
|
||||
const websockets = dedupe(broadcastList.concat(networkBridge.websocketsLookup(this.url, room, broadcaster)));
|
||||
|
||||
return {
|
||||
to: (chainedRoom, chainedBroadcaster) => this.to.call(this, chainedRoom, chainedBroadcaster, websockets),
|
||||
emit(event, data) {
|
||||
self.emit(event, data, { websockets });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Alias for Server.to
|
||||
*/
|
||||
in(...args) {
|
||||
return this.to.apply(null, args);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simulate an event from the server to the clients. Useful for
|
||||
* simulating errors.
|
||||
*/
|
||||
simulate(event) {
|
||||
const listeners = networkBridge.websocketsLookup(this.url);
|
||||
|
||||
if (event === 'error') {
|
||||
listeners.forEach(socket => {
|
||||
socket.readyState = WebSocket.CLOSE;
|
||||
socket.dispatchEvent(createEvent({ type: 'error' }));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Alternative constructor to support namespaces in socket.io
|
||||
*
|
||||
* http://socket.io/docs/rooms-and-namespaces/#custom-namespaces
|
||||
*/
|
||||
Server.of = function of(url) {
|
||||
return new Server(url);
|
||||
};
|
||||
|
||||
export default Server;
|
279
node_modules/mock-socket/src/socket-io.js
generated
vendored
Normal file
279
node_modules/mock-socket/src/socket-io.js
generated
vendored
Normal file
@ -0,0 +1,279 @@
|
||||
import URL from 'url-parse';
|
||||
import delay from './helpers/delay';
|
||||
import EventTarget from './event/target';
|
||||
import networkBridge from './network-bridge';
|
||||
import { CLOSE_CODES } from './constants';
|
||||
import logger from './helpers/logger';
|
||||
import { createEvent, createMessageEvent, createCloseEvent } from './event/factory';
|
||||
|
||||
/*
|
||||
* The socket-io class is designed to mimick the real API as closely as possible.
|
||||
*
|
||||
* http://socket.io/docs/
|
||||
*/
|
||||
class SocketIO extends EventTarget {
|
||||
/*
|
||||
* @param {string} url
|
||||
*/
|
||||
constructor(url = 'socket.io', protocol = '') {
|
||||
super();
|
||||
|
||||
this.binaryType = 'blob';
|
||||
const urlRecord = new URL(url);
|
||||
|
||||
if (!urlRecord.pathname) {
|
||||
urlRecord.pathname = '/';
|
||||
}
|
||||
|
||||
this.url = urlRecord.toString();
|
||||
this.readyState = SocketIO.CONNECTING;
|
||||
this.protocol = '';
|
||||
|
||||
if (typeof protocol === 'string' || (typeof protocol === 'object' && protocol !== null)) {
|
||||
this.protocol = protocol;
|
||||
} else if (Array.isArray(protocol) && protocol.length > 0) {
|
||||
this.protocol = protocol[0];
|
||||
}
|
||||
|
||||
const server = networkBridge.attachWebSocket(this, this.url);
|
||||
|
||||
/*
|
||||
* Delay triggering the connection events so they can be defined in time.
|
||||
*/
|
||||
delay(function delayCallback() {
|
||||
if (server) {
|
||||
this.readyState = SocketIO.OPEN;
|
||||
server.dispatchEvent(createEvent({ type: 'connection' }), server, this);
|
||||
server.dispatchEvent(createEvent({ type: 'connect' }), server, this); // alias
|
||||
this.dispatchEvent(createEvent({ type: 'connect', target: this }));
|
||||
} else {
|
||||
this.readyState = SocketIO.CLOSED;
|
||||
this.dispatchEvent(createEvent({ type: 'error', target: this }));
|
||||
this.dispatchEvent(
|
||||
createCloseEvent({
|
||||
type: 'close',
|
||||
target: this,
|
||||
code: CLOSE_CODES.CLOSE_NORMAL
|
||||
})
|
||||
);
|
||||
|
||||
logger('error', `Socket.io connection to '${this.url}' failed`);
|
||||
}
|
||||
}, this);
|
||||
|
||||
/**
|
||||
Add an aliased event listener for close / disconnect
|
||||
*/
|
||||
this.addEventListener('close', event => {
|
||||
this.dispatchEvent(
|
||||
createCloseEvent({
|
||||
type: 'disconnect',
|
||||
target: event.target,
|
||||
code: event.code
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Closes the SocketIO connection or connection attempt, if any.
|
||||
* If the connection is already CLOSED, this method does nothing.
|
||||
*/
|
||||
close() {
|
||||
if (this.readyState !== SocketIO.OPEN) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const server = networkBridge.serverLookup(this.url);
|
||||
networkBridge.removeWebSocket(this, this.url);
|
||||
|
||||
this.readyState = SocketIO.CLOSED;
|
||||
this.dispatchEvent(
|
||||
createCloseEvent({
|
||||
type: 'close',
|
||||
target: this,
|
||||
code: CLOSE_CODES.CLOSE_NORMAL
|
||||
})
|
||||
);
|
||||
|
||||
if (server) {
|
||||
server.dispatchEvent(
|
||||
createCloseEvent({
|
||||
type: 'disconnect',
|
||||
target: this,
|
||||
code: CLOSE_CODES.CLOSE_NORMAL
|
||||
}),
|
||||
server
|
||||
);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Alias for Socket#close
|
||||
*
|
||||
* https://github.com/socketio/socket.io-client/blob/master/lib/socket.js#L383
|
||||
*/
|
||||
disconnect() {
|
||||
return this.close();
|
||||
}
|
||||
|
||||
/*
|
||||
* Submits an event to the server with a payload
|
||||
*/
|
||||
emit(event, ...data) {
|
||||
if (this.readyState !== SocketIO.OPEN) {
|
||||
throw new Error('SocketIO is already in CLOSING or CLOSED state');
|
||||
}
|
||||
|
||||
const messageEvent = createMessageEvent({
|
||||
type: event,
|
||||
origin: this.url,
|
||||
data
|
||||
});
|
||||
|
||||
const server = networkBridge.serverLookup(this.url);
|
||||
|
||||
if (server) {
|
||||
server.dispatchEvent(messageEvent, ...data);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Submits a 'message' event to the server.
|
||||
*
|
||||
* Should behave exactly like WebSocket#send
|
||||
*
|
||||
* https://github.com/socketio/socket.io-client/blob/master/lib/socket.js#L113
|
||||
*/
|
||||
send(data) {
|
||||
this.emit('message', data);
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* For broadcasting events to other connected sockets.
|
||||
*
|
||||
* e.g. socket.broadcast.emit('hi!');
|
||||
* e.g. socket.broadcast.to('my-room').emit('hi!');
|
||||
*/
|
||||
get broadcast() {
|
||||
if (this.readyState !== SocketIO.OPEN) {
|
||||
throw new Error('SocketIO is already in CLOSING or CLOSED state');
|
||||
}
|
||||
|
||||
const self = this;
|
||||
const server = networkBridge.serverLookup(this.url);
|
||||
if (!server) {
|
||||
throw new Error(`SocketIO can not find a server at the specified URL (${this.url})`);
|
||||
}
|
||||
|
||||
return {
|
||||
emit(event, data) {
|
||||
server.emit(event, data, { websockets: networkBridge.websocketsLookup(self.url, null, self) });
|
||||
return self;
|
||||
},
|
||||
to(room) {
|
||||
return server.to(room, self);
|
||||
},
|
||||
in(room) {
|
||||
return server.in(room, self);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* For registering events to be received from the server
|
||||
*/
|
||||
on(type, callback) {
|
||||
this.addEventListener(type, callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove event listener
|
||||
*
|
||||
* https://socket.io/docs/client-api/#socket-on-eventname-callback
|
||||
*/
|
||||
off(type) {
|
||||
this.removeEventListener(type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Join a room on a server
|
||||
*
|
||||
* http://socket.io/docs/rooms-and-namespaces/#joining-and-leaving
|
||||
*/
|
||||
join(room) {
|
||||
networkBridge.addMembershipToRoom(this, room);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the websocket to leave the room
|
||||
*
|
||||
* http://socket.io/docs/rooms-and-namespaces/#joining-and-leaving
|
||||
*/
|
||||
leave(room) {
|
||||
networkBridge.removeMembershipFromRoom(this, room);
|
||||
}
|
||||
|
||||
to(room) {
|
||||
return this.broadcast.to(room);
|
||||
}
|
||||
|
||||
in() {
|
||||
return this.to.apply(null, arguments);
|
||||
}
|
||||
|
||||
/*
|
||||
* Invokes all listener functions that are listening to the given event.type property. Each
|
||||
* listener will be passed the event as the first argument.
|
||||
*
|
||||
* @param {object} event - event object which will be passed to all listeners of the event.type property
|
||||
*/
|
||||
dispatchEvent(event, ...customArguments) {
|
||||
const eventName = event.type;
|
||||
const listeners = this.listeners[eventName];
|
||||
|
||||
if (!Array.isArray(listeners)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
listeners.forEach(listener => {
|
||||
if (customArguments.length > 0) {
|
||||
listener.apply(this, customArguments);
|
||||
} else {
|
||||
// Regular WebSockets expect a MessageEvent but Socketio.io just wants raw data
|
||||
// payload instanceof MessageEvent works, but you can't isntance of NodeEvent
|
||||
// for now we detect if the output has data defined on it
|
||||
listener.call(this, event.data ? event.data : event);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
SocketIO.CONNECTING = 0;
|
||||
SocketIO.OPEN = 1;
|
||||
SocketIO.CLOSING = 2;
|
||||
SocketIO.CLOSED = 3;
|
||||
|
||||
/*
|
||||
* Static constructor methods for the IO Socket
|
||||
*/
|
||||
const IO = function ioConstructor(url, protocol) {
|
||||
return new SocketIO(url, protocol);
|
||||
};
|
||||
|
||||
/*
|
||||
* Alias the raw IO() constructor
|
||||
*/
|
||||
IO.connect = function ioConnect(url, protocol) {
|
||||
/* eslint-disable new-cap */
|
||||
return IO(url, protocol);
|
||||
/* eslint-enable new-cap */
|
||||
};
|
||||
|
||||
export default IO;
|
191
node_modules/mock-socket/src/websocket.js
generated
vendored
Normal file
191
node_modules/mock-socket/src/websocket.js
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
import delay from './helpers/delay';
|
||||
import logger from './helpers/logger';
|
||||
import EventTarget from './event/target';
|
||||
import networkBridge from './network-bridge';
|
||||
import proxyFactory from './helpers/proxy-factory';
|
||||
import lengthInUtf8Bytes from './helpers/byte-length';
|
||||
import { CLOSE_CODES, ERROR_PREFIX } from './constants';
|
||||
import urlVerification from './helpers/url-verification';
|
||||
import normalizeSendData from './helpers/normalize-send';
|
||||
import protocolVerification from './helpers/protocol-verification';
|
||||
import { createEvent, createMessageEvent, createCloseEvent } from './event/factory';
|
||||
import { closeWebSocketConnection, failWebSocketConnection } from './algorithms/close';
|
||||
|
||||
/*
|
||||
* The main websocket class which is designed to mimick the native WebSocket class as close
|
||||
* as possible.
|
||||
*
|
||||
* https://html.spec.whatwg.org/multipage/web-sockets.html
|
||||
*/
|
||||
class WebSocket extends EventTarget {
|
||||
constructor(url, protocols) {
|
||||
super();
|
||||
|
||||
this.url = urlVerification(url);
|
||||
protocols = protocolVerification(protocols);
|
||||
this.protocol = protocols[0] || '';
|
||||
|
||||
this.binaryType = 'blob';
|
||||
this.readyState = WebSocket.CONNECTING;
|
||||
|
||||
const server = networkBridge.attachWebSocket(this, this.url);
|
||||
|
||||
/*
|
||||
* This delay is needed so that we dont trigger an event before the callbacks have been
|
||||
* setup. For example:
|
||||
*
|
||||
* var socket = new WebSocket('ws://localhost');
|
||||
*
|
||||
* If we dont have the delay then the event would be triggered right here and this is
|
||||
* before the onopen had a chance to register itself.
|
||||
*
|
||||
* socket.onopen = () => { // this would never be called };
|
||||
*
|
||||
* and with the delay the event gets triggered here after all of the callbacks have been
|
||||
* registered :-)
|
||||
*/
|
||||
delay(function delayCallback() {
|
||||
if (server) {
|
||||
if (
|
||||
server.options.verifyClient &&
|
||||
typeof server.options.verifyClient === 'function' &&
|
||||
!server.options.verifyClient()
|
||||
) {
|
||||
this.readyState = WebSocket.CLOSED;
|
||||
|
||||
logger(
|
||||
'error',
|
||||
`WebSocket connection to '${this.url}' failed: HTTP Authentication failed; no valid credentials available`
|
||||
);
|
||||
|
||||
networkBridge.removeWebSocket(this, this.url);
|
||||
this.dispatchEvent(createEvent({ type: 'error', target: this }));
|
||||
this.dispatchEvent(createCloseEvent({ type: 'close', target: this, code: CLOSE_CODES.CLOSE_NORMAL }));
|
||||
} else {
|
||||
if (server.options.selectProtocol && typeof server.options.selectProtocol === 'function') {
|
||||
const selectedProtocol = server.options.selectProtocol(protocols);
|
||||
const isFilled = selectedProtocol !== '';
|
||||
const isRequested = protocols.indexOf(selectedProtocol) !== -1;
|
||||
if (isFilled && !isRequested) {
|
||||
this.readyState = WebSocket.CLOSED;
|
||||
|
||||
logger('error', `WebSocket connection to '${this.url}' failed: Invalid Sub-Protocol`);
|
||||
|
||||
networkBridge.removeWebSocket(this, this.url);
|
||||
this.dispatchEvent(createEvent({ type: 'error', target: this }));
|
||||
this.dispatchEvent(createCloseEvent({ type: 'close', target: this, code: CLOSE_CODES.CLOSE_NORMAL }));
|
||||
return;
|
||||
}
|
||||
this.protocol = selectedProtocol;
|
||||
}
|
||||
this.readyState = WebSocket.OPEN;
|
||||
this.dispatchEvent(createEvent({ type: 'open', target: this }));
|
||||
server.dispatchEvent(createEvent({ type: 'connection' }), proxyFactory(this));
|
||||
}
|
||||
} else {
|
||||
this.readyState = WebSocket.CLOSED;
|
||||
this.dispatchEvent(createEvent({ type: 'error', target: this }));
|
||||
this.dispatchEvent(createCloseEvent({ type: 'close', target: this, code: CLOSE_CODES.CLOSE_NORMAL }));
|
||||
|
||||
logger('error', `WebSocket connection to '${this.url}' failed`);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
||||
get onopen() {
|
||||
return this.listeners.open;
|
||||
}
|
||||
|
||||
get onmessage() {
|
||||
return this.listeners.message;
|
||||
}
|
||||
|
||||
get onclose() {
|
||||
return this.listeners.close;
|
||||
}
|
||||
|
||||
get onerror() {
|
||||
return this.listeners.error;
|
||||
}
|
||||
|
||||
set onopen(listener) {
|
||||
delete this.listeners.open;
|
||||
this.addEventListener('open', listener);
|
||||
}
|
||||
|
||||
set onmessage(listener) {
|
||||
delete this.listeners.message;
|
||||
this.addEventListener('message', listener);
|
||||
}
|
||||
|
||||
set onclose(listener) {
|
||||
delete this.listeners.close;
|
||||
this.addEventListener('close', listener);
|
||||
}
|
||||
|
||||
set onerror(listener) {
|
||||
delete this.listeners.error;
|
||||
this.addEventListener('error', listener);
|
||||
}
|
||||
|
||||
send(data) {
|
||||
if (this.readyState === WebSocket.CLOSING || this.readyState === WebSocket.CLOSED) {
|
||||
throw new Error('WebSocket is already in CLOSING or CLOSED state');
|
||||
}
|
||||
|
||||
// TODO: handle bufferedAmount
|
||||
|
||||
const messageEvent = createMessageEvent({
|
||||
type: 'server::message',
|
||||
origin: this.url,
|
||||
data: normalizeSendData(data)
|
||||
});
|
||||
|
||||
const server = networkBridge.serverLookup(this.url);
|
||||
|
||||
if (server) {
|
||||
delay(() => {
|
||||
this.dispatchEvent(messageEvent, data);
|
||||
}, server);
|
||||
}
|
||||
}
|
||||
|
||||
close(code, reason) {
|
||||
if (code !== undefined) {
|
||||
if (typeof code !== 'number' || (code !== 1000 && (code < 3000 || code > 4999))) {
|
||||
throw new TypeError(
|
||||
`${ERROR_PREFIX.CLOSE_ERROR} The code must be either 1000, or between 3000 and 4999. ${code} is neither.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (reason !== undefined) {
|
||||
const length = lengthInUtf8Bytes(reason);
|
||||
|
||||
if (length > 123) {
|
||||
throw new SyntaxError(`${ERROR_PREFIX.CLOSE_ERROR} The message must not be greater than 123 bytes.`);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.readyState === WebSocket.CLOSING || this.readyState === WebSocket.CLOSED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.readyState === WebSocket.CONNECTING) {
|
||||
failWebSocketConnection(this, code, reason);
|
||||
} else {
|
||||
closeWebSocketConnection(this, code, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WebSocket.CONNECTING = 0;
|
||||
WebSocket.prototype.CONNECTING = WebSocket.CONNECTING;
|
||||
WebSocket.OPEN = 1;
|
||||
WebSocket.prototype.OPEN = WebSocket.OPEN;
|
||||
WebSocket.CLOSING = 2;
|
||||
WebSocket.prototype.CLOSING = WebSocket.CLOSING;
|
||||
WebSocket.CLOSED = 3;
|
||||
WebSocket.prototype.CLOSED = WebSocket.CLOSED;
|
||||
|
||||
export default WebSocket;
|
4687
node_modules/mock-socket/yarn.lock
generated
vendored
Normal file
4687
node_modules/mock-socket/yarn.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user