forked from webdriverio/webdriverio
-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathbidi.test.ts
More file actions
137 lines (117 loc) · 5.02 KB
/
bidi.test.ts
File metadata and controls
137 lines (117 loc) · 5.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import path from 'node:path'
// @ts-expect-error mock feature
import { instances, setThrowError, clearInstances } from 'ws'
import { describe, it, expect, vi, beforeEach } from 'vitest'
import logger from '@testplane/wdio-logger'
import { listWebsocketCandidateUrls, createBidiConnection } from '../../src/node/bidi.js'
vi.mock('@testplane/wdio-logger', () => import(path.join(process.cwd(), '__mocks__', '@testplane/wdio-logger')))
vi.mock('dns/promises', () => ({
default: {
lookup: vi.fn().mockResolvedValue([{ address: '127.0.0.1' }, { address: '::1' }])
}
}))
vi.mock('ws', () => {
const instances: WebSocket[] = []
let throwError: Error | undefined
return {
default: class WebSocketMock {
wsUrl: string
on = vi.fn()
send = vi.fn()
once = vi.fn()
error = vi.fn()
terminate = vi.fn()
removeAllListeners = vi.fn()
constructor(url: string) {
instances.push(this as unknown as WebSocket)
this.wsUrl = url
if (throwError) {
throw throwError
}
}
},
instances,
clearInstances: () => {
instances.length = 0
},
setThrowError: (error: Error) => {
throwError = error
}
}
})
const log = logger('test')
describe('Bidi Node.js implementation', () => {
beforeEach(() => {
clearInstances()
vi.useRealTimers()
vi.clearAllMocks()
})
it('listWebsocketCandidateUrls', async () => {
const candidateUrls = await listWebsocketCandidateUrls('ws://foo/bar')
expect(candidateUrls).toEqual([
'ws://foo/bar',
'ws://127.0.0.1/bar',
'ws://::1/bar'
])
})
it('createBidiConnection', async () => {
const wsPromise = createBidiConnection('ws://foo/bar')
await new Promise((resolve) => setTimeout(resolve, 100))
expect(instances.length).toBe(3)
expect(instances[0].wsUrl).toBe('ws://foo/bar')
expect(instances[1].wsUrl).toBe('ws://127.0.0.1/bar')
expect(instances[2].wsUrl).toBe('ws://::1/bar')
expect(instances[0].once).toHaveBeenCalledWith('open', expect.any(Function))
expect(instances[1].once).toHaveBeenCalledWith('open', expect.any(Function))
expect(instances[2].once).toHaveBeenCalledWith('open', expect.any(Function))
instances[0].once.mock.calls[1][1](new Error('foo')) // error callback
instances[1].once.mock.calls[0][1]() // success callback
instances[2].once.mock.calls[1][1](new Error('bar')) // error callback
const ws = await wsPromise as any
expect(instances[0].terminate).toHaveBeenCalled()
expect(instances[1].terminate).not.toHaveBeenCalled()
expect(instances[2].terminate).toHaveBeenCalled()
expect(ws.wsUrl).toBe('ws://127.0.0.1/bar')
expect(log.info).toHaveBeenCalledWith(
'Connected to Bidi protocol at ws://127.0.0.1/bar'
)
expect(log.error).not.toHaveBeenCalled()
})
it('does not log a timeout after a successful connection', async () => {
vi.useFakeTimers()
const wsPromise = createBidiConnection('ws://foo/bar')
await vi.advanceTimersByTimeAsync(0)
instances[1].once.mock.calls[0][1]() // success callback
const ws = await wsPromise as any
await vi.advanceTimersByTimeAsync(10000)
expect(ws.wsUrl).toBe('ws://127.0.0.1/bar')
expect(log.info).toHaveBeenCalledWith(
'Connected to Bidi protocol at ws://127.0.0.1/bar'
)
expect(log.error).not.toHaveBeenCalled()
})
it('createBidiConnection returns undefined if no socket connection is established', async () => {
const wsPromise = createBidiConnection('ws://foo/bar')
await new Promise((resolve) => setTimeout(resolve, 100))
setTimeout(() => instances[0].once.mock.calls[1][1](new Error('foo')), 300) // error callback
setTimeout(() => instances[1].once.mock.calls[1][1](new Error('bar')), 100) // error callback
setTimeout(() => instances[2].once.mock.calls[1][1](new Error('loo')), 200) // error callback
await expect(wsPromise).resolves.toBeUndefined()
expect(log.error).toBeCalledWith('Could not connect to Bidi protocol\n - bar\n - loo\n - foo')
})
it('createBidiConnection times out', async () => {
vi.useFakeTimers()
const wsPromise = createBidiConnection('ws://foo/bar')
vi.runAllTimersAsync()
expect(await wsPromise).toBeUndefined()
expect(log.error).toHaveBeenCalledWith(
'Could not connect to Bidi protocol of any candidate url in time: ' +
'"ws://foo/bar", "ws://127.0.0.1/bar", "ws://::1/bar"'
)
})
it('should not fail if WebSocket url is invalid', async () => {
setThrowError(new Error('ESERVFAIL'))
const wsPromise = createBidiConnection('ws://foo/bar')
expect(await wsPromise).toBeUndefined()
})
})