1 | var chai = require('chai')
|
2 | var chalk = require('chalk')
|
3 | var log = require('npmlog')
|
4 | var sauceConnectLauncher = require('sauce-connect-launcher')
|
5 | var webdriverio = require('webdriverio')
|
6 |
|
7 | var chaiAsPromised = require('chai-as-promised')
|
8 | chai.use(chaiAsPromised)
|
9 | chai.should()
|
10 | var request = require('request')
|
11 |
|
12 | var config = require('./lib/config')
|
13 | log.level = config.log.level
|
14 |
|
15 | var tmp = config.client.split(':')
|
16 | var runner = tmp[0] || 'selenium'
|
17 | var browser = {
|
18 | name: tmp[1] || 'chrome',
|
19 | browserName: tmp[1] || 'chrome',
|
20 | version: tmp[2] || null,
|
21 | platform: tmp[3] || null
|
22 | }
|
23 |
|
24 | var options = {
|
25 | baseUrl: 'http://' + config.server.host + ':' + config.server.port,
|
26 | logLevel: config.log.level,
|
27 | desiredCapabilities: browser
|
28 | }
|
29 |
|
30 | log.silly('runner', 'runner is %s', runner)
|
31 | log.silly('options', 'set options.baseUrl to %s', options.baseUrl)
|
32 |
|
33 | if (runner === 'saucelabs') {
|
34 | options.user = config.saucelabs.username
|
35 | options.key = config.saucelabs.accessKey
|
36 |
|
37 | log.silly('options', 'set options.user to %s', options.user)
|
38 | log.silly('options', 'set options.key to ***')
|
39 |
|
40 |
|
41 | options.desiredCapabilities['tunnel-identifier'] = config.tunnelId
|
42 | options.desiredCapabilities.build = config.saucelabs.desiredCapabilities.build
|
43 |
|
44 | options.desiredCapabilities['idle-timeout'] = config.saucelabs.desiredCapabilities['idle-timeout']
|
45 | options.desiredCapabilities['max-duration'] = config.saucelabs.desiredCapabilities['max-duration']
|
46 | options.desiredCapabilities['command-timeout'] = config.saucelabs.desiredCapabilities['command-timeout']
|
47 | }
|
48 |
|
49 | if (process.env.TRAVIS_JOB_NUMBER) {
|
50 | options.desiredCapabilities.name += ' - ' + process.env.TRAVIS_JOB_NUMBER
|
51 | }
|
52 |
|
53 | log.silly('options', 'set options.desiredCapabilities to %j', options.desiredCapabilities)
|
54 |
|
55 | var client = webdriverio.remote(options)
|
56 | chaiAsPromised.transferPromiseness = client.transferPromiseness
|
57 |
|
58 |
|
59 | before(function (done) {
|
60 | var self = this
|
61 |
|
62 | this.timeout(config.timeout)
|
63 | this.client = client
|
64 |
|
65 | var seleniumRetries = 0
|
66 | var saucelabsRetries = 0
|
67 | var started = function () {
|
68 | if (++seleniumRetries > 60) {
|
69 | done(new Error('Unable to connect to selenium'))
|
70 | return
|
71 | }
|
72 |
|
73 | if (runner === 'selenium') {
|
74 | startSelenium(assureServer)
|
75 | } else {
|
76 | startSauceConnect(assureServer)
|
77 | }
|
78 |
|
79 | function startSelenium (callback) {
|
80 | log.verbose('test', 'wating for selenium at ' + config.selenium.hub + '...')
|
81 | request(config.selenium.hub, function (_error, response) {
|
82 | if (response && response.statusCode === 200) {
|
83 | log.info('selenium', 'started')
|
84 | return callback()
|
85 | }
|
86 |
|
87 | log.verbose('selenium', 'not yet ready ...')
|
88 | setTimeout(started, 1000)
|
89 | })
|
90 | }
|
91 |
|
92 | function startSauceConnect (callback) {
|
93 | log.verbose('sauce-connect', 'starting ...')
|
94 | var scOptions = {
|
95 | username: options.user,
|
96 | accessKey: options.key,
|
97 | tunnelIdentifier: config.tunnelId
|
98 | }
|
99 |
|
100 | sauceConnectLauncher(scOptions, function (error) {
|
101 | if (!error) {
|
102 | return callback()
|
103 | }
|
104 |
|
105 | if (/Not authorized/i.test(error.message)) {
|
106 | log.error('sauce-connect', error)
|
107 | return process.exit(1)
|
108 | }
|
109 |
|
110 | if (++saucelabsRetries > 10) {
|
111 | log.error('sauce-connect', 'Failed to connect in 10 attempts')
|
112 | log.error('sauce-connect', error)
|
113 | return process.exit(1)
|
114 | }
|
115 |
|
116 | log.warn('sauce-connect', 'Failed to connect')
|
117 | log.warn('sauce-connect', error)
|
118 | log.warn('sauce-connect', 'Retry ' + saucelabsRetries + '/10 in 1 minute')
|
119 |
|
120 | setTimeout(startSauceConnect.bind(null, callback), 60 * 1000)
|
121 | })
|
122 | }
|
123 |
|
124 | function assureServer () {
|
125 | var url = 'http://' + config.server.host + ':' + config.server.port
|
126 | log.verbose('test', 'waiting for server at ' + url + ' ...')
|
127 | request({
|
128 | url: url,
|
129 | headers: {
|
130 | Accept: 'text/html'
|
131 | }
|
132 | }, function (error, response, body) {
|
133 | if (response && response.statusCode === 200) {
|
134 | log.info('test', 'server found')
|
135 | return startTest()
|
136 | }
|
137 |
|
138 | if (error) {
|
139 | log.verbose('test', error)
|
140 | } else {
|
141 | log.warn('test', 'server returns ' + response.statusCode + ' but tests expect 200')
|
142 | log.verbose('test', body)
|
143 | }
|
144 |
|
145 | log.verbose('test', 'not yet ready, checking again ...')
|
146 | setTimeout(assureServer, 1000)
|
147 | })
|
148 | }
|
149 |
|
150 | function startTest () {
|
151 | self.client.on('command', function (command) {
|
152 | log.info('selenium', chalk.cyan(command.method), command.uri.path)
|
153 |
|
154 | if (command.data.script) {
|
155 | command.data.script = getScriptName(command.data.script)
|
156 | }
|
157 | log.info('selenium', command.data)
|
158 | })
|
159 | self.client.on('erorr', function (error) {
|
160 | log.error('selenium', chalk.red(error.body.value.class), error.body.value.message)
|
161 | })
|
162 |
|
163 | self.client
|
164 | .init()
|
165 |
|
166 |
|
167 | .timeouts('script', config.timeout)
|
168 | .timeouts('implicit', config.timeout)
|
169 | .timeouts('page load', config.timeout)
|
170 |
|
171 | .then(function () {
|
172 | done()
|
173 | })
|
174 | }
|
175 |
|
176 | function getScriptName (script) {
|
177 | var matches = script.match(/return \(function (\w+)/)
|
178 | return matches ? matches[1] : '[function]'
|
179 | }
|
180 | }
|
181 |
|
182 | started()
|
183 | })
|
184 |
|
185 |
|
186 | after(function (done) {
|
187 | this.client.end(done)
|
188 | })
|