wspromisify 2.4.3 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -2
  3. package/TODO +9 -0
  4. package/dist/bundle.cjs +1 -1
  5. package/dist/bundle.d.ts +7 -2
  6. package/dist/bundle.mjs +1 -1
  7. package/package.json +91 -94
  8. package/rollup.config.js +1 -1
  9. package/src/WSC.ts +271 -0
  10. package/src/config.ts +7 -6
  11. package/src/utils.ts +5 -23
  12. package/test/index.ts +21 -0
  13. package/test/mock/WS.ts +43 -0
  14. package/test/mock/server.ts +17 -0
  15. package/test/specs/close.ts +18 -0
  16. package/test/specs/drops.ts +30 -0
  17. package/test/specs/echo.ts +24 -0
  18. package/test/specs/encode-decode.ts +1 -0
  19. package/test/specs/existing_socket.ts +55 -0
  20. package/test/specs/lazy.ts +22 -0
  21. package/test/specs/lazySendBeforeOpen.ts +19 -0
  22. package/test/specs/no-native-throws.ts +18 -0
  23. package/test/specs/ready.ts +12 -0
  24. package/test/specs/reconnect.ts +23 -0
  25. package/test/specs/socket.ts +13 -0
  26. package/test/suite.ts +3 -0
  27. package/test/utils.ts +27 -0
  28. package/tsconfig.json +3 -2
  29. package/src/WS.ts +0 -166
  30. package/src/connectLib.ts +0 -120
  31. package/test/mock/WS.js +0 -51
  32. package/test/mock/index.js +0 -52
  33. package/test/specs/close.js +0 -25
  34. package/test/specs/drops.js +0 -29
  35. package/test/specs/echo.js +0 -26
  36. package/test/specs/encode-decode.js +0 -3
  37. package/test/specs/existing_socket.js +0 -55
  38. package/test/specs/lazy.js +0 -26
  39. package/test/specs/ready.js +0 -16
  40. package/test/specs/reconnect.js +0 -28
  41. package/test/specs/sendBeforeOpen.js +0 -23
  42. package/test/specs/socket.js +0 -22
  43. package/test/specs/utils_once.js +0 -16
  44. package/test/utils.js +0 -27
package/src/WSC.ts ADDED
@@ -0,0 +1,271 @@
1
+ import './types'
2
+ import { Zipnum } from 'zipnum'
3
+ import { add_event, sett } from './utils'
4
+ import { processConfig } from './config'
5
+ import { AnyFunc, once, T } from 'pepka'
6
+
7
+ const MAX_32 = 2**31 - 1
8
+ const zipnum = new Zipnum()
9
+
10
+ class WebSocketClient {
11
+ private open = false
12
+ private ws: wsc.Socket|null = null
13
+ private forcibly_closed = false
14
+ private reconnect_timeout: NodeJS.Timeout|null = null
15
+ private queue = {}
16
+ private messages: any[] = []
17
+ private onReadyQueue: AnyFunc[] = []
18
+ private onCloseQueue: AnyFunc[] = []
19
+ private handlers = <{[event in wsc.WSEvent]: ((e: any) => void)[]}>{
20
+ open: [], close: [], message: [], error: []
21
+ }
22
+ private config = <wsc.Config>{}
23
+
24
+ private init_flush(): void {
25
+ this.queue = {} // data queuse
26
+ this.messages = [] // send() queue
27
+ }
28
+
29
+ private log(event: string, message: any = null, time: number|null = null): void {
30
+ const config = this.config
31
+ if(time !== null) {
32
+ config.log(event, time, message)
33
+ } else {
34
+ if(config.timer) {
35
+ config.log(event, null, message)
36
+ } else {
37
+ config.log(event, message)
38
+ }
39
+ }
40
+ }
41
+
42
+ private initSocket(ws: wsc.Socket) {
43
+ const config = this.config
44
+ this.open = true
45
+ this.onReadyQueue.forEach((fn: Function) => fn())
46
+ this.onReadyQueue.splice(0)
47
+ const {id_key, data_key} = config.server
48
+ // Works also on previously opened sockets that do not fire 'open' event.
49
+ this.handlers.open.forEach((h) => h(ws))
50
+ // Send all pending messages.
51
+ this.messages.forEach((message: any) => message.send())
52
+ // It's reconnecting.
53
+ if(this.reconnect_timeout !== null) {
54
+ clearInterval(this.reconnect_timeout)
55
+ this.reconnect_timeout = null
56
+ }
57
+ if(config.ping) {
58
+ const ping_interval = setInterval(() => {
59
+ if(this.open) this.send(config.ping.content)
60
+ if(this.forcibly_closed) clearInterval(ping_interval)
61
+ }, config.ping.interval*1e3)
62
+ }
63
+ add_event(ws, 'close', async (...e) => {
64
+ this.log('close')
65
+ this.open = false
66
+ this.onCloseQueue.forEach((fn: Function) => fn())
67
+ this.onCloseQueue.splice(0)
68
+ this.handlers.close.forEach((h: any) => h(...e))
69
+ // Auto reconnect.
70
+ const reconnect = config.reconnect
71
+ if(
72
+ typeof reconnect === 'number' &&
73
+ !isNaN(reconnect) &&
74
+ !this.forcibly_closed
75
+ ) {
76
+ const reconnectFunc = async () => {
77
+ this.log('reconnect')
78
+ if(this.ws !== null) {
79
+ this.ws.close()
80
+ this.ws = null
81
+ }
82
+ // If some error occured, try again.
83
+ const status = await this.connect()
84
+ if(status !== null) {
85
+ this.reconnect_timeout = setTimeout(reconnectFunc, reconnect * 1000)
86
+ }
87
+ }
88
+ // No need for await.
89
+ reconnectFunc()
90
+ } else {
91
+ this.ws = null
92
+ this.open = false
93
+ }
94
+ // reset the flag to reuse.
95
+ this.forcibly_closed = false
96
+ })
97
+ add_event(ws, 'message', (e) => {
98
+ try {
99
+ const data = config.decode(e.data)
100
+ this.handlers.message.forEach((h: any) => h({...e, data}))
101
+ if(data[id_key]) {
102
+ const q = this.queue[data[id_key]]
103
+ if(q) {
104
+ // Debug, Log.
105
+ const time = q.sent_time ? (Date.now() - q.sent_time) : null
106
+ this.log('message', data[data_key], time)
107
+ // Play.
108
+ q.ff(data[data_key])
109
+ clearTimeout(q.timeout)
110
+ delete this.queue[data[id_key]]
111
+ }
112
+ }
113
+ } catch (err) {
114
+ console.error(err, `WSP: Decode error. Got: ${e.data}`)
115
+ }
116
+ })
117
+ }
118
+
119
+ private async connect() { // returns status if won't open or null if ok.
120
+ return new Promise((ff) => {
121
+ if(this.open === true) {
122
+ return ff(null)
123
+ }
124
+ const config = this.config
125
+ const ws = config.socket || config.adapter(config.url, config.protocols)
126
+ this.ws = ws
127
+
128
+ if(!ws || ws.readyState > 1) {
129
+ this.ws = null
130
+ this.log('error', 'ready() on closing or closed state! status 2.')
131
+ return ff(2)
132
+ }
133
+
134
+ add_event(ws, 'error', once((e) => {
135
+ this.log('error', 'status 3.')
136
+ this.handlers.error.forEach((h) => h(e))
137
+ this.ws = null
138
+ // Some network error: Connection refused or so.
139
+ return ff(3)
140
+ }))
141
+ // Because 'open' won't be envoked on opened socket.
142
+ if(ws.readyState) {
143
+ this.initSocket(ws)
144
+ ff(null)
145
+ } else {
146
+ add_event(ws, 'open', once(() => {
147
+ this.log('open')
148
+ this.initSocket(ws)
149
+ return ff(null)
150
+ }))
151
+ }
152
+ })
153
+ }
154
+
155
+ public get socket() {
156
+ return this.ws
157
+ }
158
+
159
+ public async ready() {
160
+ return new Promise<void>((ff) => {
161
+ if(this.open) {
162
+ ff()
163
+ } else {
164
+ this.onReadyQueue.push(ff)
165
+ }
166
+ })
167
+ }
168
+
169
+ public on(
170
+ event_name: wsc.WSEvent,
171
+ handler: (data: any) => any,
172
+ predicate: (data: any) => boolean = T,
173
+ raw = false
174
+ ) {
175
+ const _handler: wsc.EventHandler = (event) =>
176
+ predicate(event) && handler(event)
177
+ return raw
178
+ ? add_event(this.ws as wsc.Socket, event_name, _handler)
179
+ : this.handlers[event_name].push(_handler)
180
+ }
181
+
182
+ public async close(): wsc.AsyncErrCode {
183
+ return new Promise((ff, rj) => {
184
+ if(this.ws === null) {
185
+ rj('WSP: closing a non-inited socket!')
186
+ } else {
187
+ this.open = false
188
+ this.onCloseQueue.push(() => {
189
+ this.init_flush()
190
+ this.ws = null
191
+ this.forcibly_closed = true
192
+ ff(null)
193
+ })
194
+ this.ws.close()
195
+ }
196
+ })
197
+ }
198
+
199
+ /** .send(your_data) wraps request to server with {id: `hash`, data: `actually your data`},
200
+ returns a Promise that will be rejected after a timeout or
201
+ resolved if server returns the same signature: {id: `same_hash`, data: `response data`}.
202
+ */
203
+ public async send<RequestDataType = any, ResponseDataType = any>(
204
+ message_data: RequestDataType,
205
+ opts = <wsc.SendOptions>{}
206
+ ): Promise<ResponseDataType> {
207
+ this.log('send', message_data)
208
+ const config = this.config
209
+ const message = {}
210
+ const data_key = config.server.data_key
211
+ const first_time_lazy = config.lazy && !this.open
212
+
213
+ const message_id = zipnum.zip((Math.random()*(MAX_32-10))|0)
214
+ if(typeof opts.top === 'object') {
215
+ if(opts.top[data_key]) {
216
+ throw new Error('Attempting to set data key/token via send() options!')
217
+ }
218
+ Object.assign(message, opts.top)
219
+ }
220
+
221
+ config.pipes.forEach(
222
+ (pipe) => message_data = pipe(message_data)
223
+ )
224
+
225
+ if(this.open === true) {
226
+ (this.ws as wsc.Socket).send(config.encode(message_id, message_data, config))
227
+ } else if(this.open === false || first_time_lazy) {
228
+ this.messages.push({
229
+ send: () => (this.ws as wsc.Socket).send(config.encode(message_id, message_data, config))
230
+ })
231
+ if(first_time_lazy) {
232
+ this.connect()
233
+ }
234
+ } else if(this.open === null) {
235
+ throw new Error('Attempting to send via closed WebSocket connection!')
236
+ }
237
+
238
+ return new Promise((ff, rj) => {
239
+ this.queue[message_id] = {
240
+ ff,
241
+ data_type: config.data_type,
242
+ sent_time: config.timer ? Date.now() : null,
243
+ timeout: sett(config.timeout, () => {
244
+ if(this.queue[message_id]) {
245
+ rj({
246
+ 'Websocket timeout expired: ': config.timeout,
247
+ 'for the message ': message_data
248
+ })
249
+ delete this.queue[message_id]
250
+ }
251
+ })
252
+ }
253
+ })
254
+ }
255
+
256
+ constructor(user_config: wsc.UserConfig = {}) {
257
+ this.config = processConfig(user_config)
258
+ // Init.
259
+ this.init_flush()
260
+ // Flags.
261
+ this.open = false
262
+ this.reconnect_timeout = null
263
+ this.forcibly_closed = false
264
+ if(!this.config.lazy) {
265
+ this.connect()
266
+ }
267
+ }
268
+ }
269
+
270
+ /* TODO: v3: @.deprecated. Use named import { WebSocketClient } instead. */
271
+ export default WebSocketClient
package/src/config.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import './types'
2
+ import { native_ws } from './utils'
2
3
 
3
4
  const default_config = <wsc.Config>{
4
5
  data_type: 'json', // ToDo some other stuff maybe.
@@ -29,13 +30,17 @@ const default_config = <wsc.Config>{
29
30
  }
30
31
  }
31
32
 
32
- const enrichConfig = (config: wsc.UserConfig) => {
33
+ export const processConfig = (config: wsc.UserConfig) => {
34
+ if(native_ws===null && !('adapter' in config)) throw new Error(`
35
+ This platform has no native WebSocket implementation.
36
+ Please use 'ws' package as an adapter.
37
+ See https://github.com/houd1ni/WebsocketPromisify/issues/23
38
+ `)
33
39
  const full_config: wsc.Config = Object.assign(
34
40
  {},
35
41
  default_config,
36
42
  config
37
43
  )
38
-
39
44
  const url = full_config.url
40
45
  if(url[0] == '/') {
41
46
  try {
@@ -47,8 +52,4 @@ const enrichConfig = (config: wsc.UserConfig) => {
47
52
  }
48
53
 
49
54
  return full_config
50
- }
51
-
52
- export {
53
- enrichConfig
54
55
  }
package/src/utils.ts CHANGED
@@ -1,30 +1,12 @@
1
1
  import './types'
2
2
 
3
- const add_event = (o: wsc.Socket, e: string, handler: wsc.EventHandler) => {
4
- return o.addEventListener(e, handler)
5
- }
3
+ export const native_ws = (() => {try {return WebSocket||null}catch { return null }})()
6
4
 
7
- const once = (fn: Function) => {
8
- let has_been_cached = false
9
- let cached = null
10
- return (...args: any) => {
11
- if(has_been_cached) {
12
- return cached
13
- } else {
14
- has_been_cached = true
15
- return cached = fn(...args)
16
- }
17
- }
5
+ export const add_event = (o: wsc.Socket, e: string, handler: wsc.EventHandler) => {
6
+ return o.addEventListener(e, handler)
18
7
  }
19
8
 
20
- const sett = (
9
+ export const sett = (
21
10
  a: number,
22
11
  b: { (): void; (...args: any[]): void; }
23
- ) => setTimeout(b, a)
24
-
25
-
26
- export {
27
- add_event,
28
- once,
29
- sett
30
- }
12
+ ) => setTimeout(b, a)
package/test/index.ts ADDED
@@ -0,0 +1,21 @@
1
+ import './specs/close'
2
+ import './specs/drops'
3
+ import './specs/echo'
4
+ import './specs/existing_socket'
5
+ import './specs/lazy'
6
+ import './specs/ready'
7
+ import './specs/reconnect'
8
+ import './specs/lazySendBeforeOpen'
9
+ import './specs/socket'
10
+ import './specs/no-native-throws'
11
+ import mockServer from './mock/server'
12
+ import {test} from './suite'
13
+
14
+ const {shutDown} = await mockServer()
15
+ test.after(() => {
16
+ setTimeout(async () => {
17
+ await shutDown()
18
+ process.exit()
19
+ }, 100)
20
+ })
21
+ test.run()
@@ -0,0 +1,43 @@
1
+
2
+ import WebSocket, { WebSocketServer } from 'ws'
3
+ import {noop} from 'pepka'
4
+
5
+ let server: WebSocketServer|null = null
6
+
7
+ const createServer = (port = 40510) => new Promise<WebSocketServer>((ff, rj) => {
8
+ if(server) return rj('The server is already running!')
9
+ server = new WebSocketServer({ port }, () => {
10
+ server!.on('connection', (socket: WebSocket&{isAlive: boolean}) => {
11
+ socket.on('message', (rawMessage: string) => {
12
+ const {id, data} = JSON.parse(rawMessage)
13
+ let response = ''
14
+ if(data.shut) {
15
+ socket.terminate()
16
+ socket.isAlive = false
17
+ socket.ping('', false, noop)
18
+ return null
19
+ } else if(data.echo) {
20
+ response = data
21
+ }
22
+ socket.send(JSON.stringify({ id, data: response }))
23
+ return null
24
+ })
25
+ return true
26
+ })
27
+ return ff(server!)
28
+ })
29
+ server.on('', console.log)
30
+ })
31
+
32
+ const killServer = async () => new Promise<void>((ff, rj) => {
33
+ if(server) {
34
+ for(const socket of server.clients) socket.terminate()
35
+ server.close(() => {
36
+ server = null
37
+ ff()
38
+ })
39
+ } else
40
+ rj('The server is already down!')
41
+ })
42
+
43
+ export { createServer, killServer }
@@ -0,0 +1,17 @@
1
+
2
+ import { WebSocketServer } from 'ws'
3
+ import { createServer, killServer } from './WS.js'
4
+
5
+ let port: number,
6
+ server: WebSocketServer|null
7
+
8
+ export default async (new_port?: number) => {
9
+ if(!server) {
10
+ port = new_port || 8000 + Math.ceil(Math.random()*500)
11
+ server = await createServer(port)
12
+ }
13
+ return {
14
+ server, port,
15
+ shutDown: async () => { await killServer(); server=null }
16
+ }
17
+ }
@@ -0,0 +1,18 @@
1
+ import { test } from '../suite'
2
+ import { createNew } from '../utils.js'
3
+ import mockServer from '../mock/server'
4
+
5
+ /** Closes the connenction. */
6
+ test('close', () => new Promise<void>(async (ff, rj) => {
7
+ const {port} = await mockServer()
8
+ const ws = createNew({}, port)
9
+
10
+ setTimeout(async () => {
11
+ try {
12
+ await ws.close()
13
+ if(ws.socket === null) ff(); else rj()
14
+ } catch(e) {
15
+ rj()
16
+ }
17
+ }, 500)
18
+ }))
@@ -0,0 +1,30 @@
1
+ import { createNew } from '../utils'
2
+ import mockServer from '../mock/server'
3
+ import { test } from '../suite'
4
+
5
+ /** Rejects messages by timout */
6
+ test('drops', () => new Promise(async (ff, rj) => {
7
+ const {port, shutDown} = await mockServer()
8
+ const ws = createNew({timeout: 500}, port)
9
+
10
+ await shutDown()
11
+ const lauchServ = async () => await mockServer(port)
12
+
13
+ setTimeout(async () => {
14
+ const msg = {echo: true, msg: 'hello!'}
15
+ let to: NodeJS.Timeout
16
+ try {
17
+ to = setTimeout(() => {
18
+ return rj()
19
+ }, 600)
20
+ await ws.send(msg)
21
+ if(to) clearTimeout(to)
22
+ await lauchServ()
23
+ return rj()
24
+ } catch(e) {
25
+ if(to!) clearTimeout(to)
26
+ await lauchServ()
27
+ return ff()
28
+ }
29
+ }, 200)
30
+ }))
@@ -0,0 +1,24 @@
1
+ import { equals } from 'pepka'
2
+ import { createNew, timeout } from '../utils'
3
+ import mockServer from '../mock/server'
4
+ import { test } from '../suite'
5
+
6
+ /** Proof of work. */
7
+ test('echo', timeout(5e3, () => new Promise<void>(async (ff, rj) => {
8
+ const {port} = await mockServer()
9
+ let to = setTimeout(() => rj('cannot create'), 2e2)
10
+ const ws = createNew({}, port)
11
+ clearTimeout(to)
12
+
13
+ to = setTimeout(() => rj('cannot ready'), 2e2)
14
+ await ws.ready()
15
+ clearTimeout(to)
16
+
17
+ const msg = {echo: true, msg: 'hello!'}
18
+ to = setTimeout(() => rj('cannot send'), 2e2)
19
+ const response = await ws.send(msg)
20
+ clearTimeout(to)
21
+
22
+ if(equals(response, msg)) ff(); else rj('echo msg is not equal.')
23
+ })
24
+ ))
@@ -0,0 +1 @@
1
+ // TODO with mock server with specific port.
@@ -0,0 +1,55 @@
1
+ import { createNew } from '../utils'
2
+ import mockServer from '../mock/server'
3
+
4
+ import WS from 'ws'
5
+ import { test } from '../suite'
6
+ import { equals } from 'pepka'
7
+
8
+
9
+ const addr = (port: number) => 'ws://localhost:' + port
10
+
11
+ /** If an existing socket connection is provided via config. */
12
+ test('existing_socket', () => {
13
+ return new Promise(async (ff, rj) => {
14
+ const {port} = await mockServer()
15
+ const to = setTimeout(() => rj(), 4e4)
16
+ const existing_addr = addr(port)
17
+
18
+ // This one CANNOT connect as fast as we send to it,
19
+ // So readyState is 0.
20
+ const ws1 = createNew({socket: new WS(existing_addr)}, port)
21
+
22
+ if(ws1.socket?.readyState !== 0) return rj('not ready.')
23
+
24
+ const msg1 = {echo: true, msg: 'existing_socket!'}
25
+ const response1 = await ws1.send(msg1)
26
+
27
+ if(
28
+ ws1.socket?.readyState as number !== 1
29
+ || !equals(response1, msg1)
30
+ ) return rj('not ready.')
31
+ await ws1.close()
32
+
33
+ // This one DO CAN connect as fast as we send to it,
34
+ // So readyState should be 1.
35
+ const ws2_0 = new WS(existing_addr)
36
+
37
+ ws2_0.addEventListener('open', async () => {
38
+ const ws2 = await createNew({socket: ws2_0}, port)
39
+
40
+ if(ws2.socket?.readyState !== 1) return rj('not ready.')
41
+
42
+ const msg2 = {echo: true, msg: 'existing_socket!'}
43
+ const response2 = await ws2.send(msg2)
44
+
45
+ if(
46
+ ws2.socket?.readyState as number !== 1
47
+ || !equals(response2, msg2)
48
+ ) return rj('not ready.')
49
+ await ws2.close()
50
+
51
+ clearTimeout(to)
52
+ ff()
53
+ })
54
+ })
55
+ })
@@ -0,0 +1,22 @@
1
+ import { createNew, timeout } from '../utils'
2
+ import mockServer from '../mock/server'
3
+ import { equals } from 'pepka'
4
+ import { test } from '../suite'
5
+
6
+ /** Lazy connect */
7
+ test('lazy', timeout(2e3, () => {
8
+ return new Promise<void>(async (ff, rj) => {
9
+ const {port} = await mockServer()
10
+ const ws = createNew({ lazy: true }, port)
11
+
12
+ setTimeout(async () => {
13
+ if(ws.socket !== null) {
14
+ rj()
15
+ } else {
16
+ const msg = {echo: true, msg: 'hello!'}
17
+ const response = await ws.send(msg)
18
+ if(equals(response, msg)) ff(); else rj()
19
+ }
20
+ }, 500)
21
+ })
22
+ }))
@@ -0,0 +1,19 @@
1
+ import { createNew } from '../utils.js'
2
+ import mockServer from '../mock/server'
3
+ import { equals } from 'pepka'
4
+ import { test } from '../suite'
5
+
6
+ /** Sends massages if they were .send() before connection is estabilished. */
7
+ test('lazy send before open queued.', () => new Promise(async (ff, rj) => {
8
+ const {port} = await mockServer()
9
+ let to = setTimeout(() => rj('cannot create'), 2e2)
10
+ const ws = createNew({lazy: true}, port)
11
+ clearTimeout(to)
12
+
13
+ const msg = {echo: true, msg: 'hello!'}
14
+ to = setTimeout(() => rj('cannot send'), 2e2)
15
+ const response = await ws.send(msg)
16
+ clearTimeout(to)
17
+
18
+ if(equals(response, msg)) ff(); else rj()
19
+ }))
@@ -0,0 +1,18 @@
1
+ import mockServer from '../mock/server'
2
+ import { test } from '../suite'
3
+ import {WebSocketClient} from '../../src/WSC'
4
+
5
+ /** Ready method. */
6
+ test('No native throws without an adapter', async () => {
7
+ const {port} = await mockServer()
8
+ let pass = false
9
+ try {
10
+ new WebSocketClient({ url: 'ws://127.0.0.1:' + port })
11
+ try {
12
+ if(WebSocket) pass = true
13
+ } catch {}
14
+ } catch {
15
+ pass=true
16
+ }
17
+ if(!pass) throw new Error('Does not throw.')
18
+ })
@@ -0,0 +1,12 @@
1
+ import { createNew, timeout } from '../utils'
2
+ import mockServer from '../mock/server'
3
+ import { test } from '../suite'
4
+
5
+ /** Ready method. */
6
+ test('ready', timeout(4e3, async () => {
7
+ const {port} = await mockServer()
8
+ const ws = createNew({}, port)
9
+
10
+ await ws.ready()
11
+ if(!ws.socket) throw new Error()
12
+ }))
@@ -0,0 +1,23 @@
1
+ import { createNew, timeout } from '../utils'
2
+ import mockServer from '../mock/server'
3
+ import { equals } from 'pepka'
4
+ import { test } from '../suite'
5
+
6
+ /** Reconnects if connection is broken. */
7
+ test('reconnect', timeout(1e4, () => new Promise<void>(async (ff, rj) => {
8
+ const {port, shutDown} = await mockServer()
9
+ const ws = createNew({ reconnect: 1 }, port)
10
+
11
+ setTimeout(async () => {
12
+ await shutDown()
13
+ setTimeout(async () => {
14
+ await mockServer(port)
15
+ setTimeout(async () => {
16
+ const msg = {echo: true, msg: 'hello!'}
17
+ const response = await ws.send(msg)
18
+ if(equals(response, msg)) ff(); else rj('not equals.')
19
+ }, 1500)
20
+ }, 1100)
21
+ }, 500)
22
+ })
23
+ ))
@@ -0,0 +1,13 @@
1
+ import { createNew, timeout } from '../utils'
2
+ import mockServer from '../mock/server'
3
+ import { test } from '../suite'
4
+
5
+ /** Socket property check. */
6
+ test('sockets', timeout(1e4, () => new Promise<void>(async (ff, rj) => {
7
+ const {port} = await mockServer()
8
+ const ws = createNew({}, port)
9
+
10
+ await ws.ready()
11
+
12
+ if(ws.socket && !isNaN(ws.socket.readyState)) ff(); else rj()
13
+ })))
package/test/suite.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { suite as uvu_suite } from 'uvu'
2
+
3
+ export const test = uvu_suite('.')