-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
100 lines (83 loc) · 2.57 KB
/
index.js
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
'use strict'
const debug = require('debug')('chutney')
const fs = require('node:fs')
const path = require('node:path')
const stream = require('node:stream')
const websocket = require('websocket-stream')
const createServer = require('./lib/server')
const createTunnel = require('./lib/tunnel')
const createSauce = require('./lib/sauce')
const runner = fs.readFileSync(path.join(__dirname, 'lib/runner.bundle.js'), {encoding: 'utf8'})
const run = async (opt = {}) => {
if (!opt.user) throw new Error('You must specify a Sauce Labs user.')
if (!opt.key) throw new Error('You must specify a Sauce Labs access key.')
if (!opt.platform) throw new Error('You must specify a platform.')
if (!opt.browser) throw new Error('You must specify a browser.')
if (!opt.tests) throw new Error('You must specify test code.')
if (opt.timeout !== undefined) {
if ('number' !== opt.timeout) throw new Error('timeout must be a number.')
} else opt.timeout = 20 * 1000
const out = new stream.PassThrough()
const emitError = (err) => {
out.emit('error', err)
if (opt.bailout !== false && !out._writableState.ended) {
const msg = err && err.message || (err + '')
out.write('Bail out! ' + msg)
}
}
const httpConnections = []
const wsConnections = []
debug('creating tunnel')
// todo: find port
const tunnel = await createTunnel(3000)
tunnel.on('error', err => emitError(err))
out.once('end', () => tunnel.close())
debug('creating HTTP server')
const server = await createServer(3000, runner, opt.tests)
let stopped = false
const stop = () => {
if (stopped) return null
stopped = true
debug('stopping')
for (let tap of wsConnections) {
tap.unpipe(out)
tap.destroy()
}
for (let connection of httpConnections) {
connection.destroy()
}
server.close()
}
out.once('end', stop)
const onTimeout = () => {
debug('timeout')
if (!out._writableState.ended) {
out.end('\nnot ok test timed out after ' + opt.timeout + ' ms\n')
}
stop()
}
let timeout = setTimeout(onTimeout, opt.timeout)
out.on('data', () => {
clearTimeout(timeout)
timeout = setTimeout(onTimeout, opt.timeout)
})
server.on('connection', (connection) => {
httpConnections.push(connection)
})
// receive TAP from client
debug('creating WS server')
websocket.createServer({server}, (tap) => {
debug('WS connection!')
wsConnections.push(tap)
tap.pipe(out)
})
debug('creating SauceLabs tunnel')
const driver = await createSauce({
user: opt.user, key: opt.key,
platform: opt.platform, browser: opt.browser,
url: tunnel.url
})
out.emit('driver', driver)
return out
}
module.exports = run