Line | Hits | Source |
---|---|---|
1 | /*! | |
2 | * | |
3 | * Copyright (c) 2013 Sebastian Golasch | |
4 | * | |
5 | * Permission is hereby granted, free of charge, to any person obtaining a | |
6 | * copy of this software and associated documentation files (the "Software"), | |
7 | * to deal in the Software without restriction, including without limitation | |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
9 | * and/or sell copies of the Software, and to permit persons to whom the | |
10 | * Software is furnished to do so, subject to the following conditions: | |
11 | * | |
12 | * The above copyright notice and this permission notice shall be included | |
13 | * in all copies or substantial portions of the Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
21 | * DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
25 | 1 | 'use strict'; |
26 | ||
27 | // ext. libs | |
28 | 1 | var fs = require('fs'); |
29 | 1 | var Q = require('q'); |
30 | ||
31 | // int. libs | |
32 | 1 | var WD = require('dalek-internal-webdriver'); |
33 | 1 | var Browser = require('./lib/browser'); |
34 | ||
35 | /** | |
36 | * Initializes the sauce labs driver & the remote browser instance | |
37 | * | |
38 | * @param {object} opts Initializer options | |
39 | * @constructor | |
40 | */ | |
41 | ||
42 | 1 | var Sauce = function (opts) { |
43 | // get the browser configuration & the browser module | |
44 | 0 | var browserConf = {name: null}; |
45 | 0 | var browser = opts.browserMo; |
46 | ||
47 | // prepare properties | |
48 | 0 | this._initializeProperties(opts); |
49 | ||
50 | // create a new webdriver client instance | |
51 | 0 | this.webdriverClient = new WD(browser, this.events); |
52 | ||
53 | // listen on browser events | |
54 | 0 | this._startBrowserEventListeners(browser); |
55 | ||
56 | // assign the current browser name | |
57 | 0 | browserConf.name = this.browserName; |
58 | ||
59 | // store desired capabilities of this session | |
60 | 0 | this.desiredCapabilities = browser.getDesiredCapabilities(this.browserName, this.config); |
61 | 0 | this.browserDefaults = browser.driverDefaults; |
62 | 0 | this.browserDefaults.status = browser.getStatusDefaults(this.desiredCapabilities); |
63 | 0 | this.browserData = browser; |
64 | ||
65 | // set auth data | |
66 | 0 | var driverConfig = this.config.get('driver.sauce'); |
67 | 0 | browser.setAuth(driverConfig.user, driverConfig.key); |
68 | ||
69 | // launch the browser & when the browser launch | |
70 | // promise is fullfilled, issue the driver:ready event | |
71 | // for the particular browser | |
72 | 0 | browser |
73 | .launch(browserConf, this.reporterEvents, this.config) | |
74 | .then(this.events.emit.bind(this.events, 'driver:ready:sauce:' + this.browserName, browser)); | |
75 | }; | |
76 | ||
77 | /** | |
78 | * This module is a driver plugin for [DalekJS](//github.com/dalekjs/dalek). | |
79 | * It connects Daleks testsuite with the remote testing environment of [Sauce Labs](https://saucelabs.com). | |
80 | * | |
81 | * The driver can be installed with the following command: | |
82 | * | |
83 | * ```bash | |
84 | * $ npm install dalek-driver-sauce --save-dev | |
85 | * ``` | |
86 | * | |
87 | * You can use the driver by adding a config option to the your [Dalekfile](/docs/config.html) | |
88 | * | |
89 | * ```javascript | |
90 | * "driver": ["sauce"] | |
91 | * ``` | |
92 | * | |
93 | * Or you can tell Dalek that it should run your tests via sauces service via the command line: | |
94 | * | |
95 | * ```bash | |
96 | * $ dalek mytest.js -d sauce | |
97 | * ``` | |
98 | * | |
99 | * In order to run your tests within the Sauce Labs infrastructure, you must add your sauce username & key | |
100 | * to your dalek configuration. Those two parameters must be set in order to get this driver up & running. | |
101 | * You can specifiy them within your [Dalekfile](/docs/config.html) like so: | |
102 | * | |
103 | * ```javascript | |
104 | * "driver.sauce": { | |
105 | * "user": "dalekjs", | |
106 | * "key": "aaaaaa-1234-567a-1abc-1br6d9f68689" | |
107 | * } | |
108 | * ``` | |
109 | * | |
110 | * It is also possible to specify a set of other extra saucy parameters like `name` & `tags`: | |
111 | * | |
112 | * ```javascript | |
113 | * "driver.sauce": { | |
114 | * "user": "dalekjs", | |
115 | * "key": "aaaaaa-1234-567a-1abc-1br6d9f68689", | |
116 | * "name": "Guineapig", | |
117 | * "tags": ["dalek", "testproject"] | |
118 | * } | |
119 | * ``` | |
120 | * | |
121 | * If you would like to have a more control over the browser/OS combinations that are available, you are able | |
122 | * to configure you custom combinations: | |
123 | * | |
124 | * ```javascript | |
125 | * "browsers": [{ | |
126 | * "chrome": { | |
127 | * "platform": "OS X 10.6", | |
128 | * "actAs": "chrome", | |
129 | * "version": 27 | |
130 | * }, | |
131 | * "chromeWin": { | |
132 | * "platform": "Windows 7", | |
133 | * "actAs": "chrome", | |
134 | * "version": 27 | |
135 | * }, | |
136 | * "chromeLinux": { | |
137 | * "platform": "Linux", | |
138 | * "actAs": "chrome", | |
139 | * "version": 26 | |
140 | * } | |
141 | * ``` | |
142 | * | |
143 | * You can then call your custom browsers like so: | |
144 | * | |
145 | * ```bash | |
146 | * $ dalek mytest.js -d sauce -b chrome,chromeWin,chromeLinux | |
147 | * ``` | |
148 | * | |
149 | * or you can define them in your Dalekfile: | |
150 | * | |
151 | * ```javascript | |
152 | * "browser": ["chrome", "chromeWin", "chromeLinux"] | |
153 | * ``` | |
154 | * | |
155 | * A list of all available browser/OS combinations, can be found [here](https://saucelabs.com/docs/platforms). | |
156 | * | |
157 | * @module Driver | |
158 | * @class Sauce | |
159 | * @namespace Dalek | |
160 | * @part Sauce | |
161 | * @api | |
162 | */ | |
163 | ||
164 | 1 | Sauce.prototype = { |
165 | ||
166 | /** | |
167 | * Initializes the driver properties | |
168 | * | |
169 | * @method _initializeProperties | |
170 | * @param {object} opts Options needed to kick off the driver | |
171 | * @chainable | |
172 | * @private | |
173 | */ | |
174 | ||
175 | _initializeProperties: function (opts) { | |
176 | // prepare properties | |
177 | 0 | this.actionQueue = []; |
178 | 0 | this.config = opts.config; |
179 | 0 | this.lastCalledUrl = null; |
180 | 0 | this.driverStatus = {}; |
181 | 0 | this.sessionStatus = {}; |
182 | // store injcted options in object properties | |
183 | 0 | this.events = opts.events; |
184 | 0 | this.reporterEvents = opts.reporter; |
185 | 0 | this.browserName = opts.browser; |
186 | 0 | return this; |
187 | }, | |
188 | ||
189 | /** | |
190 | * Binds listeners on browser events | |
191 | * | |
192 | * @method _initializeProperties | |
193 | * @param {object} browser Browser module | |
194 | * @chainable | |
195 | * @private | |
196 | */ | |
197 | ||
198 | _startBrowserEventListeners: function (browser) { | |
199 | // issue the kill command to the browser, when all tests are completed | |
200 | 0 | this.events.on('tests:complete:sauce:' + this.browserName, browser.kill.bind(browser)); |
201 | // clear the webdriver session, when all tests are completed | |
202 | 0 | this.events.on('tests:complete:sauce:' + this.browserName, this.webdriverClient.closeSession.bind(this.webdriverClient)); |
203 | 0 | return this; |
204 | }, | |
205 | ||
206 | /** | |
207 | * Checks if a webdriver session has already been established, | |
208 | * if not, create a new one | |
209 | * | |
210 | * @method start | |
211 | * @return {object} promise Driver promise | |
212 | */ | |
213 | ||
214 | start: function () { | |
215 | 0 | var deferred = Q.defer(); |
216 | ||
217 | // store desired capabilities of this session | |
218 | 0 | this.desiredCapabilities = this.browserData.getDesiredCapabilities(this.browserName, this.config); |
219 | 0 | this.browserDefaults = this.browserData.driverDefaults; |
220 | 0 | this.browserDefaults.status = this.browserData.getStatusDefaults(this.desiredCapabilities); |
221 | ||
222 | // start a browser session | |
223 | 0 | this._startBrowserSession(deferred, this.desiredCapabilities, this.browserDefaults); |
224 | ||
225 | 0 | return deferred.promise; |
226 | }, | |
227 | ||
228 | /** | |
229 | * Creates a new webdriver session | |
230 | * Gets the driver status | |
231 | * Gets the session status | |
232 | * Resolves the promise (e.g. let them tests run) | |
233 | * | |
234 | * @method _startBrowserSession | |
235 | * @param {object} deferred Browser session deferred | |
236 | * @chainable | |
237 | * @private | |
238 | */ | |
239 | ||
240 | _startBrowserSession: function (deferred, desiredCapabilities, defaults) { | |
241 | 0 | var viewport = this.config.get('viewport'); |
242 | ||
243 | // start a session, transmit the desired capabilities | |
244 | 0 | var promise = this.webdriverClient.createSession({desiredCapabilities: desiredCapabilities}); |
245 | ||
246 | // set the default viewport if supported by the browser | |
247 | 0 | if (defaults.viewport) { |
248 | 0 | promise = promise.then(this.webdriverClient.setWindowSize.bind(this.webdriverClient, viewport.width, viewport.height)); |
249 | } | |
250 | ||
251 | // get the driver status if supported by the browser | |
252 | 0 | if (defaults.status === true) { |
253 | 0 | promise = promise |
254 | .then(this.webdriverClient.status.bind(this.webdriverClient)) | |
255 | .then(this._driverStatus.bind(this)); | |
256 | } else { | |
257 | 0 | promise = promise.then(this._driverStatus.bind(this, JSON.stringify({value: defaults.status}))); |
258 | } | |
259 | ||
260 | // get the session info if supported by the browser | |
261 | 0 | if (defaults.sessionInfo === true) { |
262 | 0 | promise = promise |
263 | .then(this.webdriverClient.sessionInfo.bind(this.webdriverClient)) | |
264 | .then(this._sessionStatus.bind(this)); | |
265 | } else { | |
266 | 0 | promise = promise.then(this._driverStatus.bind(this, JSON.stringify({value: defaults.sessionInfo}))); |
267 | } | |
268 | ||
269 | // finally resolve the deferred | |
270 | 0 | promise.then(deferred.resolve); |
271 | 0 | return this; |
272 | }, | |
273 | ||
274 | /** | |
275 | * Starts to execution of a batch of tests | |
276 | * | |
277 | * @method end | |
278 | * @chainable | |
279 | */ | |
280 | ||
281 | end: function () { | |
282 | 0 | var result = Q.resolve(); |
283 | ||
284 | // loop through all promises created by the remote methods | |
285 | // this is synchronous, so it waits if a method is finished before | |
286 | // the next one will be executed | |
287 | 0 | this.actionQueue.forEach(function (f) { |
288 | 0 | result = result.then(f); |
289 | }); | |
290 | ||
291 | // flush the queue & fire an event | |
292 | // when the queue finished its executions | |
293 | 0 | result.then(this.flushQueue.bind(this)); |
294 | 0 | return this; |
295 | }, | |
296 | ||
297 | /** | |
298 | * Flushes the action queue (e.g. commands that should be send to the wbdriver server) | |
299 | * | |
300 | * @method flushQueue | |
301 | * @chainable | |
302 | */ | |
303 | ||
304 | flushQueue: function () { | |
305 | // clear the action queue | |
306 | 0 | this.actionQueue = []; |
307 | ||
308 | // kill the session | |
309 | 0 | var promise = this.webdriverClient.deleteSession(); |
310 | ||
311 | // emit the run.complete event | |
312 | 0 | promise.then(function () { |
313 | 0 | this.events.emit('driver:message', {key: 'run.complete', value: null}); |
314 | }.bind(this)); | |
315 | ||
316 | 0 | return this; |
317 | }, | |
318 | ||
319 | /** | |
320 | * Loads the browser session status | |
321 | * | |
322 | * @method _sessionStatus | |
323 | * @param {object} sessionInfo Session information | |
324 | * @return {object} promise Browser session promise | |
325 | * @private | |
326 | */ | |
327 | ||
328 | _sessionStatus: function (sessionInfo) { | |
329 | 0 | var defer = Q.defer(); |
330 | 0 | this.sessionStatus = JSON.parse(sessionInfo).value; |
331 | 0 | this.events.emit('driver:sessionStatus:sauce:' + this.browserName, this.sessionStatus); |
332 | 0 | defer.resolve(); |
333 | 0 | return defer.promise; |
334 | }, | |
335 | ||
336 | /** | |
337 | * Loads the browser driver status | |
338 | * | |
339 | * @method _driverStatus | |
340 | * @param {object} statusInfo Driver status information | |
341 | * @return {object} promise Driver status promise | |
342 | * @private | |
343 | */ | |
344 | ||
345 | _driverStatus: function (statusInfo) { | |
346 | 0 | var defer = Q.defer(); |
347 | 0 | this.driverStatus = JSON.parse(statusInfo).value; |
348 | 0 | this.events.emit('driver:status:sauce:' + this.browserName, this.driverStatus); |
349 | 0 | defer.resolve(); |
350 | 0 | return defer.promise; |
351 | }, | |
352 | ||
353 | /** | |
354 | * Creates an anonymus function that calls a webdriver | |
355 | * method that has no return value, emits an empty result event | |
356 | * if the function has been run | |
357 | * TODO: Name is weird, should be saner | |
358 | * | |
359 | * @method _createNonReturnee | |
360 | * @param {string} fnName Name of the webdriver function that should be called | |
361 | * @return {function} fn | |
362 | * @private | |
363 | */ | |
364 | ||
365 | _createNonReturnee: function (fnName) { | |
366 | 0 | return this._actionQueueNonReturneeTemplate.bind(this, fnName); |
367 | }, | |
368 | ||
369 | /** | |
370 | * Generates a chain of webdriver calls for webdriver | |
371 | * methods that don't have a return value | |
372 | * TODO: Name is weird, should be saner | |
373 | * | |
374 | * @method _actionQueueNonReturneeTemplate | |
375 | * @param {string} fnName Name of the webdriver function that should be called | |
376 | * @param {string} hash Unique action hash | |
377 | * @param {string} uuid Unique action hash | |
378 | * @chainable | |
379 | * @private | |
380 | */ | |
381 | ||
382 | _actionQueueNonReturneeTemplate:function (fnName, hash, uuid) { | |
383 | 0 | this.actionQueue.push(this.webdriverClient[fnName].bind(this.webdriverClient)); |
384 | 0 | this.actionQueue.push(this._generateDummyDriverMessageFn.bind(this, fnName, hash, uuid)); |
385 | 0 | return this; |
386 | }, | |
387 | ||
388 | /** | |
389 | * Creates a driver notification with an empty value | |
390 | * TODO: Name is weird, should be saner | |
391 | * | |
392 | * @method _generateDummyDriverMessageFn | |
393 | * @param {string} fnName Name of the webdriver function that should be called | |
394 | * @param {string} hash Unique action hash | |
395 | * @param {string} uuid Unique action hash | |
396 | * @return {object} promise Driver message promise | |
397 | * @private | |
398 | */ | |
399 | ||
400 | _generateDummyDriverMessageFn: function (fnName, hash, uuid) { | |
401 | 0 | var deferred = Q.defer(); |
402 | 0 | this.events.emit('driver:message', {key: fnName, value: null, uuid: uuid, hash: hash}); |
403 | 0 | deferred.resolve(); |
404 | 0 | return deferred.promise; |
405 | } | |
406 | }; | |
407 | ||
408 | /** | |
409 | * Determines if the driver is a "multi" browser driver, | |
410 | * e.g. can handle more than one browser | |
411 | * | |
412 | * @method isMultiBrowser | |
413 | * @return {bool} isMultiBrowser Driver can handle more than one browser | |
414 | */ | |
415 | ||
416 | 1 | module.exports.isMultiBrowser = function () { |
417 | 0 | return true; |
418 | }; | |
419 | ||
420 | /** | |
421 | * Verifies a browser request | |
422 | * TODO: Still a noop, need to add "verify the browser" logic | |
423 | * | |
424 | * @method verifyBrowser | |
425 | * @return {bool} isVerifiedBrowser Driver can handle this browser | |
426 | */ | |
427 | ||
428 | 1 | module.exports.verifyBrowser = function () { |
429 | 0 | return true; |
430 | }; | |
431 | ||
432 | /** | |
433 | * Determines if the driver comes with its own browsers bundled | |
434 | * | |
435 | * @method dummyBrowser | |
436 | * @return {bool} isDummyBrowser Driver does not rely on Dalek browser modules | |
437 | */ | |
438 | ||
439 | 1 | module.exports.dummyBrowser = function () { |
440 | 0 | return true; |
441 | }; | |
442 | ||
443 | /** | |
444 | * Returnes the browser that comes bundled with the driver | |
445 | * | |
446 | * @method getBrowser | |
447 | * @param {object} driver Driver instance | |
448 | * @return {object} Browser module | |
449 | */ | |
450 | ||
451 | 1 | module.exports.getBrowser = function (driver) { |
452 | 0 | return {configuration: null, module: new Browser(driver)}; |
453 | }; | |
454 | ||
455 | /** | |
456 | * Creates a new driver instance | |
457 | * | |
458 | * @method create | |
459 | * @param {object} opts Options needed to kick off the driver | |
460 | * @return {Sauce} driver | |
461 | */ | |
462 | ||
463 | 1 | module.exports.create = function (opts) { |
464 | // load the remote command helper methods | |
465 | 0 | var dir = __dirname + '/lib/commands/'; |
466 | 0 | fs.readdirSync(dir).forEach(function (file) { |
467 | 0 | require(dir + file)(Sauce); |
468 | }); | |
469 | ||
470 | 0 | return new Sauce(opts); |
471 | }; | |
472 |
Line | Hits | Source |
---|---|---|
1 | /*! | |
2 | * | |
3 | * Copyright (c) 2013 Sebastian Golasch | |
4 | * | |
5 | * Permission is hereby granted, free of charge, to any person obtaining a | |
6 | * copy of this software and associated documentation files (the "Software"), | |
7 | * to deal in the Software without restriction, including without limitation | |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
9 | * and/or sell copies of the Software, and to permit persons to whom the | |
10 | * Software is furnished to do so, subject to the following conditions: | |
11 | * | |
12 | * The above copyright notice and this permission notice shall be included | |
13 | * in all copies or substantial portions of the Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
21 | * DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
25 | 1 | 'use strict'; |
26 | ||
27 | // ext. libs | |
28 | 1 | var Q = require('q'); |
29 | ||
30 | /** | |
31 | * Loads the webdriver client, | |
32 | * launches the browser, | |
33 | * initializes al object properties, | |
34 | * binds to browser events | |
35 | * | |
36 | * @param {object} opts Options needed to kick off the driver | |
37 | * @constructor | |
38 | */ | |
39 | ||
40 | 1 | var DummyBrowser = function (driver) { |
41 | 0 | this.driver = driver; |
42 | }; | |
43 | ||
44 | /** | |
45 | * Verfies a given browser config & mimics a | |
46 | * real browser while using the Sauce infrstructure | |
47 | * | |
48 | * @module Driver | |
49 | * @class Browser | |
50 | * @namespace Dalek | |
51 | */ | |
52 | ||
53 | 1 | DummyBrowser.prototype = { |
54 | ||
55 | /** | |
56 | * Sauce labs authentication realm (user:key) | |
57 | * | |
58 | * @property auth | |
59 | * @type {string|null} | |
60 | */ | |
61 | ||
62 | auth: null, | |
63 | ||
64 | /** | |
65 | * Browser session config | |
66 | * | |
67 | * @property sessionConfig | |
68 | * @type {object} | |
69 | */ | |
70 | ||
71 | sessionConfig: {}, | |
72 | ||
73 | /** | |
74 | * Saucelabs remote webdriver path | |
75 | * | |
76 | * @property path | |
77 | * @type {string} | |
78 | * @default /wd/hub | |
79 | */ | |
80 | ||
81 | path: '/wd/hub', | |
82 | ||
83 | /** | |
84 | * Saucelabs remote port | |
85 | * | |
86 | * @property port | |
87 | * @type {integer} | |
88 | * @default 80 | |
89 | */ | |
90 | ||
91 | port: 80, | |
92 | ||
93 | /** | |
94 | * Saucelabs remote host | |
95 | * | |
96 | * @property host | |
97 | * @type {string} | |
98 | * @default host | |
99 | */ | |
100 | ||
101 | host: 'ondemand.saucelabs.com', | |
102 | ||
103 | /** | |
104 | * Available browsers with their default capabilities | |
105 | * | |
106 | * @property browsers | |
107 | * @type {object} | |
108 | */ | |
109 | ||
110 | browsers: { | |
111 | 'iphone': {platform: 'OS X 10.8', version: '6', longName: 'iOS Safari (iPhone)'}, | |
112 | 'ipad': {platform: 'OS X 10.8', version: '6', longName: 'iOS Safari (iPad)'}, | |
113 | 'android': {platform: 'Linux', version: '4.0', longName: 'Chrome on Android'}, | |
114 | 'firefox': {platform: 'OS X 10.6', version: '25', longName: 'Mozilla Firefox'}, | |
115 | 'internet explorer': {platform: 'Windows 8', version: '10', longName: 'Internet Explorer'}, | |
116 | 'chrome': {platform: 'OS X 10.6', version: '28', longName: 'Google Chrome'}, | |
117 | 'opera': {platform: 'Windows 7', version: '12', longName: 'Opera'}, | |
118 | 'safari': {platform: 'OS X 10.8', version: '6', longName: 'Safari'} | |
119 | }, | |
120 | ||
121 | /** | |
122 | * Default verbose browser name | |
123 | * | |
124 | * @property longName | |
125 | * @type {string} | |
126 | */ | |
127 | ||
128 | longName: 'Mozilla Firefox', | |
129 | ||
130 | /** | |
131 | * Default desired capabilities | |
132 | * | |
133 | * @property desiredCapabilities | |
134 | * @type {object} | |
135 | */ | |
136 | ||
137 | desiredCapabilities: { | |
138 | platform: 'OS X 10.8', | |
139 | browserName: 'chrome', | |
140 | 'browser-version': 'latest', | |
141 | name: 'Dalek Testsuite' | |
142 | }, | |
143 | ||
144 | /** | |
145 | * Driver defaults | |
146 | * | |
147 | * @property driverDefaults | |
148 | * @type {object} | |
149 | */ | |
150 | ||
151 | driverDefaults: { | |
152 | viewport: false, | |
153 | status: { | |
154 | os: { | |
155 | name: 'Linux', | |
156 | version: null, | |
157 | arch: null | |
158 | } | |
159 | }, | |
160 | sessionInfo: true | |
161 | }, | |
162 | ||
163 | /** | |
164 | * Available platforms | |
165 | * | |
166 | * @property platforms | |
167 | * @type {array} | |
168 | */ | |
169 | ||
170 | platforms: ['Windows 8.1', 'Windows 8', 'Windows 7', 'Windows XP', 'OS X 10.9', 'OS X 10.8', 'OS X 10.6', 'Linux'], | |
171 | ||
172 | /** | |
173 | * Stores & validates the incoming browser config | |
174 | * | |
175 | * @method launch | |
176 | * @param {object} configuration Browser configuration | |
177 | * @param {EventEmitter2} events EventEmitter (Reporter Emitter instance) | |
178 | * @param {Dalek.Internal.Config} config Dalek configuration class | |
179 | * @return {object} Browser promise | |
180 | */ | |
181 | ||
182 | launch: function (configuration, events, config) { | |
183 | 0 | var deferred = Q.defer(); |
184 | ||
185 | // override desired capabilities, status & browser longname | |
186 | 0 | this.desiredCapabilities = this._generateDesiredCaps(configuration.name, config); |
187 | 0 | this.driverDefaults.status = this._generateStatusInfo(this.desiredCapabilities); |
188 | 0 | this.longName = this._generateLongName(configuration.name,config); |
189 | ||
190 | // store injected configuration/log event handlers | |
191 | 0 | this.reporterEvents = events; |
192 | 0 | this.configuration = configuration; |
193 | 0 | this.config = config; |
194 | ||
195 | // immediatly resolve the deferred | |
196 | 0 | deferred.resolve(); |
197 | 0 | return deferred.promise; |
198 | }, | |
199 | ||
200 | /** | |
201 | * Kills the remote browser | |
202 | * TODO: Close the remote session | |
203 | * | |
204 | * @method kill | |
205 | * @return {object} Promise | |
206 | */ | |
207 | ||
208 | kill: function () { | |
209 | 0 | var deferred = Q.defer(); |
210 | 0 | deferred.resolve(); |
211 | 0 | return deferred.promise; |
212 | }, | |
213 | ||
214 | /** | |
215 | * Generates the status defaults for the OS configuration | |
216 | * | |
217 | * @method getStatusDefaults | |
218 | * @param {object} desiredCapabilities Desired capabilities | |
219 | * @param {object} desiredCapabilities Desired capabilities | |
220 | * @return {object} OS status information | |
221 | */ | |
222 | ||
223 | getDesiredCapabilities: function (browserName, config) { | |
224 | 0 | return this._generateDesiredCaps(browserName, config); |
225 | }, | |
226 | ||
227 | /** | |
228 | * Generates the status defaults for the OS configuration | |
229 | * | |
230 | * @method getStatusDefaults | |
231 | * @param {object} desiredCapabilities Desired capabilities | |
232 | * @return {object} OS status information | |
233 | */ | |
234 | ||
235 | getStatusDefaults: function (desiredCapabilities) { | |
236 | 0 | return this._generateStatusInfo(desiredCapabilities); |
237 | }, | |
238 | ||
239 | /** | |
240 | * Sets the sauce authentication token | |
241 | * | |
242 | * @method setAuth | |
243 | * @param {string} user Sauce labs username | |
244 | * @param {string} key Sauce labs key | |
245 | * @chainable | |
246 | */ | |
247 | ||
248 | setAuth: function (user, key) { | |
249 | 0 | this.auth = user + ':' + key; |
250 | 0 | return this; |
251 | }, | |
252 | ||
253 | /** | |
254 | * Verifies the browser config | |
255 | * | |
256 | * @method _verfiyBrowserConfig | |
257 | * @param {string} browserName Name of the browser to verify | |
258 | * @param {object} config Daleks internal config helper | |
259 | * @return {object} Browser config | |
260 | * @private | |
261 | */ | |
262 | ||
263 | _verfiyBrowserConfig: function (browserName, config) { | |
264 | 0 | var browsers = config.get('browsers'); |
265 | ||
266 | // check if we couldnt find a configured alias, | |
267 | // set to defaults otherwise | |
268 | 0 | if (!browsers) { |
269 | 0 | return {actAs: this.desiredCapabilities.browserName, version: this.desiredCapabilities['browser-version']}; |
270 | } | |
271 | 0 | var browser = config.get('browsers')[0][browserName] || null; |
272 | // check if we couldnt find a configured alias, | |
273 | // check and apply if there is a default config | |
274 | 0 | if (!browser && this.browsers[browserName]) { |
275 | 0 | browser = this.browsers[browserName]; |
276 | } | |
277 | ||
278 | // check if the actas property has been set, if not | |
279 | // use the given browser name | |
280 | 0 | if (!browser.actAs) { |
281 | 0 | browser.actAs = browserName; |
282 | } | |
283 | ||
284 | 0 | return browser; |
285 | }, | |
286 | ||
287 | /** | |
288 | * Verfies the OS platform config | |
289 | * | |
290 | * @method _verfiyPlatformConfig | |
291 | * @param {object} browser Browser information | |
292 | * @return {string} Platform | |
293 | * @private | |
294 | */ | |
295 | ||
296 | _verfiyPlatformConfig: function (browser) { | |
297 | 0 | var isValid = this.platforms.reduce(function (previousValue, platform) { |
298 | 0 | if (previousValue === browser.platform || platform === browser.platform) { |
299 | 0 | return browser.platform; |
300 | } | |
301 | }); | |
302 | ||
303 | 0 | return isValid || this.desiredCapabilities.platform; |
304 | }, | |
305 | ||
306 | /** | |
307 | * Generates the desired capabilities for this session | |
308 | * | |
309 | * @method _generateDesiredCaps | |
310 | * @param {string} browserName The browser name | |
311 | * @param {object} config Daleks internal config helper | |
312 | * @return {object} The sessions desired capabilities | |
313 | * @private | |
314 | */ | |
315 | ||
316 | _generateDesiredCaps: function (browserName, config) { | |
317 | 0 | var browser = this._verfiyBrowserConfig(browserName, config); |
318 | 0 | var platform = this._verfiyPlatformConfig(browser); |
319 | 0 | var driverConfig = config.get('driver.sauce'); |
320 | 0 | var desiredCaps = { |
321 | browserName: browser.actAs, | |
322 | platform: platform, | |
323 | 'screen-resolution': (browser['screen-resolution'] || null), | |
324 | version: (browser.version || this.desiredCapabilities['browser-version']), | |
325 | name: driverConfig.name || this.desiredCapabilities.name | |
326 | }; | |
327 | ||
328 | // check if the user added tags | |
329 | 0 | if (driverConfig.tags) { |
330 | 0 | desiredCaps.tags = driverConfig.tags; |
331 | } | |
332 | ||
333 | // check if the user added a build id | |
334 | 0 | if (driverConfig.build) { |
335 | 0 | desiredCaps.build = driverConfig.build; |
336 | } | |
337 | ||
338 | 0 | return desiredCaps; |
339 | }, | |
340 | ||
341 | /** | |
342 | * Generates OS status information | |
343 | * | |
344 | * @method _generateStatusInfo | |
345 | * @param {object} desiredCaps The sessions desired capabilities | |
346 | * @return {object} OS status information | |
347 | * @private | |
348 | */ | |
349 | ||
350 | _generateStatusInfo: function (desiredCaps) { | |
351 | 0 | return {os: {name: desiredCaps.platform, arch: null, version: null}}; |
352 | }, | |
353 | ||
354 | /** | |
355 | * Generates the verbose name of the current remote browser in use | |
356 | * | |
357 | * @method _generateLongName | |
358 | * @param {object} desiredCaps The sessions desired capabilities | |
359 | * @return {string} Verbose browser name | |
360 | * @private | |
361 | */ | |
362 | ||
363 | _generateLongName: function (browserName, config) { | |
364 | 0 | var longName = null; |
365 | 0 | if(this.browsers.hasOwnProperty(browserName)){ |
366 | 0 | longName = this.browsers[browserName].longName; |
367 | } | |
368 | 0 | if(config.get('browsers')[0].hasOwnProperty(browserName)){ |
369 | 0 | longName = config.get('browsers')[0][browserName].longName; |
370 | } | |
371 | 0 | return longName; |
372 | } | |
373 | }; | |
374 | ||
375 | 1 | module.exports = DummyBrowser; |
376 |
Line | Hits | Source |
---|---|---|
1 | /*! | |
2 | * | |
3 | * Copyright (c) 2013 Sebastian Golasch | |
4 | * | |
5 | * Permission is hereby granted, free of charge, to any person obtaining a | |
6 | * copy of this software and associated documentation files (the "Software"), | |
7 | * to deal in the Software without restriction, including without limitation | |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
9 | * and/or sell copies of the Software, and to permit persons to whom the | |
10 | * Software is furnished to do so, subject to the following conditions: | |
11 | * | |
12 | * The above copyright notice and this permission notice shall be included | |
13 | * in all copies or substantial portions of the Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
21 | * DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
25 | 1 | 'use strict'; |
26 | ||
27 | // ext. libs | |
28 | 1 | var Q = require('q'); |
29 | ||
30 | /** | |
31 | * Cookie related methods | |
32 | * | |
33 | * @module Driver | |
34 | * @class Cookie | |
35 | * @namespace Dalek.DriverNative.Commands | |
36 | */ | |
37 | ||
38 | 1 | var Cookie = { |
39 | ||
40 | /** | |
41 | * Sets an cookie | |
42 | * | |
43 | * @method setCookie | |
44 | * @param {string} name Name of the cookie | |
45 | * @param {string} contents Contents of the cookie | |
46 | * @param {string} hash Unique hash of that fn call | |
47 | * @chainable | |
48 | */ | |
49 | ||
50 | setCookie: function (name, contents, hash) { | |
51 | 0 | this.actionQueue.push(this.webdriverClient.setCookie.bind(this.webdriverClient, {name: name, value: contents})); |
52 | 0 | this.actionQueue.push(this._setCookieCb.bind(this, name, contents, hash)); |
53 | 0 | return this; |
54 | }, | |
55 | ||
56 | /** | |
57 | * Sends out an event with the results of the `setCookie` call | |
58 | * | |
59 | * @method _setCookieCb | |
60 | * @param {string} name Name of the cookie | |
61 | * @param {string} contents Contents of the cookie | |
62 | * @param {string} hash Unique hash of that fn call | |
63 | * @return {object} promise Exists promise | |
64 | * @private | |
65 | */ | |
66 | ||
67 | _setCookieCb: function (name, contents, hash) { | |
68 | 0 | var deferred = Q.defer(); |
69 | 0 | this.events.emit('driver:message', {key: 'setCookie', value: name, contents: contents, uuid: hash, hash: hash}); |
70 | 0 | deferred.resolve(); |
71 | 0 | return deferred.promise; |
72 | }, | |
73 | ||
74 | /** | |
75 | * Retrieves an cookie | |
76 | * | |
77 | * @method cookie | |
78 | * @param {string} name Name of the cookie | |
79 | * @param {string} cookie Expected contents of the cookie | |
80 | * @param {string} hash Unique hash of that fn call | |
81 | * @chainable | |
82 | */ | |
83 | ||
84 | cookie: function (name, cookie, hash) { | |
85 | 0 | this.actionQueue.push(this.webdriverClient.getCookie.bind(this.webdriverClient, name)); |
86 | 0 | this.actionQueue.push(this._cookieCb.bind(this, name, hash)); |
87 | 0 | return this; |
88 | }, | |
89 | ||
90 | /** | |
91 | * Sends out an event with the results of the `setCookie` call | |
92 | * | |
93 | * @method _cookieCb | |
94 | * @param {string} name Name of the cookie | |
95 | * @param {string} expected Expected contents of the cookie | |
96 | * @param {string} hash Unique hash of that fn call | |
97 | * @param {string} result Serialized JSON with the reuslts of the exists call | |
98 | * @return {object} promise Exists promise | |
99 | * @private | |
100 | */ | |
101 | ||
102 | _cookieCb: function (name, expected, hash, res) { | |
103 | 0 | var deferred = Q.defer(); |
104 | 0 | var cookies = JSON.parse(res).value; |
105 | 0 | var cookie = false; |
106 | 0 | cookies.forEach(function (cookieItem) { |
107 | 0 | if (cookieItem.name === name) { |
108 | 0 | cookie = cookieItem.value; |
109 | } | |
110 | }); | |
111 | ||
112 | 0 | this.events.emit('driver:message', {key: 'cookie', value: cookie, name: name, expected: expected, uuid: hash, hash: hash}); |
113 | 0 | deferred.resolve(); |
114 | 0 | return deferred.promise; |
115 | }, | |
116 | }; | |
117 | ||
118 | /** | |
119 | * Mixes in cookie methods | |
120 | * | |
121 | * @param {Dalek.DriverNative} DalekNative Native driver base class | |
122 | * @return {Dalek.DriverNative} DalekNative Native driver base class | |
123 | */ | |
124 | ||
125 | 1 | module.exports = function (DalekNative) { |
126 | // mixin methods | |
127 | 0 | Object.keys(Cookie).forEach(function (fn) { |
128 | 0 | DalekNative.prototype[fn] = Cookie[fn]; |
129 | }); | |
130 | ||
131 | 0 | return DalekNative; |
132 | }; | |
133 |
Line | Hits | Source |
---|---|---|
1 | /*! | |
2 | * | |
3 | * Copyright (c) 2013 Sebastian Golasch | |
4 | * | |
5 | * Permission is hereby granted, free of charge, to any person obtaining a | |
6 | * copy of this software and associated documentation files (the "Software"), | |
7 | * to deal in the Software without restriction, including without limitation | |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
9 | * and/or sell copies of the Software, and to permit persons to whom the | |
10 | * Software is furnished to do so, subject to the following conditions: | |
11 | * | |
12 | * The above copyright notice and this permission notice shall be included | |
13 | * in all copies or substantial portions of the Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
21 | * DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
25 | 1 | 'use strict'; |
26 | ||
27 | // ext. libs | |
28 | 1 | var Q = require('q'); |
29 | ||
30 | /** | |
31 | * Element related methods | |
32 | * | |
33 | * @module Driver | |
34 | * @class Element | |
35 | * @namespace Dalek.DriverNative.Commands | |
36 | */ | |
37 | ||
38 | 1 | var Element = { |
39 | ||
40 | /** | |
41 | * Checks if an element exists | |
42 | * | |
43 | * @method exists | |
44 | * @param {string} selector Selector expression to find the element | |
45 | * @param {string} hash Unique hash of that fn call | |
46 | * @chainable | |
47 | */ | |
48 | ||
49 | exists: function (selector, hash) { | |
50 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
51 | 0 | this.actionQueue.push(this._existsCb.bind(this, selector, hash)); |
52 | 0 | return this; |
53 | }, | |
54 | ||
55 | /** | |
56 | * Sends out an event with the results of the `exists` call | |
57 | * | |
58 | * @method _existsCb | |
59 | * @param {string} selector Selector expression to find the element | |
60 | * @param {string} hash Unique hash of that fn call | |
61 | * @param {string} result Serialized JSON with the reuslts of the exists call | |
62 | * @return {object} promise Exists promise | |
63 | * @private | |
64 | */ | |
65 | ||
66 | _existsCb: function (selector, hash, result) { | |
67 | 0 | var deferred = Q.defer(); |
68 | 0 | this.events.emit('driver:message', {key: 'exists', selector: selector, hash: hash, value: (JSON.parse(result).value === -1 || JSON.parse(result).status === 7 ? 'false' : 'true')}); |
69 | 0 | deferred.resolve(); |
70 | 0 | return deferred.promise; |
71 | }, | |
72 | ||
73 | /** | |
74 | * Checks if an element is visible | |
75 | * | |
76 | * @method visible | |
77 | * @param {string} selector Selector expression to find the element | |
78 | * @param {string} hash Unique hash of that fn call | |
79 | * @chainable | |
80 | */ | |
81 | ||
82 | visible: function (selector, hash) { | |
83 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
84 | 0 | this.actionQueue.push(this.webdriverClient.displayed.bind(this.webdriverClient, selector)); |
85 | 0 | this.actionQueue.push(this._visibleCb.bind(this, selector, hash)); |
86 | 0 | return this; |
87 | }, | |
88 | ||
89 | /** | |
90 | * Sends out an event with the results of the `visible` call | |
91 | * | |
92 | * @method _visibleCb | |
93 | * @param {string} selector Selector expression to find the element | |
94 | * @param {string} hash Unique hash of that fn call | |
95 | * @param {string} result Serialized JSON with the reuslts of the visible call | |
96 | * @return {object} promise Visible promise | |
97 | * @private | |
98 | */ | |
99 | ||
100 | _visibleCb: function (selector, hash, result) { | |
101 | 0 | var deferred = Q.defer(); |
102 | 0 | this.events.emit('driver:message', {key: 'visible', selector: selector, hash: hash, value: JSON.parse(result).value}); |
103 | 0 | deferred.resolve(); |
104 | 0 | return deferred.promise; |
105 | }, | |
106 | ||
107 | /** | |
108 | * Checks if an element has the expected text | |
109 | * | |
110 | * @method text | |
111 | * @param {string} selector Selector expression to find the element | |
112 | * @param {string} expected The expected text content | |
113 | * @param {string} hash Unique hash of that fn call | |
114 | * @chainable | |
115 | */ | |
116 | ||
117 | text: function (selector, expected, hash) { | |
118 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
119 | 0 | this.actionQueue.push(this.webdriverClient.text.bind(this.webdriverClient, selector)); |
120 | 0 | this.actionQueue.push(this._textCb.bind(this, selector, hash, expected)); |
121 | 0 | return this; |
122 | }, | |
123 | ||
124 | /** | |
125 | * Sends out an event with the results of the `text` call | |
126 | * | |
127 | * @method _textCb | |
128 | * @param {string} selector Selector expression to find the element | |
129 | * @param {string} hash Unique hash of that fn call | |
130 | * @param {string} expected The expected text content | |
131 | * @param {string} result Serialized JSON with the reuslts of the text call | |
132 | * @return {object} Promise | |
133 | * @private | |
134 | */ | |
135 | ||
136 | _textCb: function (selector, hash, expected, result) { | |
137 | 0 | var deferred = Q.defer(); |
138 | 0 | this.events.emit('driver:message', {key: 'text', hash: hash, expected: expected, selector: selector, value: JSON.parse(result).value}); |
139 | 0 | deferred.resolve(); |
140 | 0 | return deferred.promise; |
141 | }, | |
142 | ||
143 | /** | |
144 | * Checks if an element has the expected css property/value pairs | |
145 | * | |
146 | * @method css | |
147 | * @param {string} selector Selector expression to find the element | |
148 | * @param {string} property The css property to check | |
149 | * @param {string} expected The expected css value | |
150 | * @param {string} hash Unique hash of that fn call | |
151 | * @chainable | |
152 | */ | |
153 | ||
154 | css: function (selector, property, expected, hash) { | |
155 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
156 | 0 | this.actionQueue.push(this.webdriverClient.cssProperty.bind(this.webdriverClient, property)); |
157 | 0 | this.actionQueue.push(this._cssCb.bind(this, selector, property, hash, expected)); |
158 | 0 | return this; |
159 | }, | |
160 | ||
161 | /** | |
162 | * Sends out an event with the results of the `css` call | |
163 | * | |
164 | * @method _cssCb | |
165 | * @param {string} selector Selector expression to find the element | |
166 | * @param {string} property The css property to check | |
167 | * @param {string} expected The expected css value | |
168 | * @param {string} hash Unique hash of that fn call | |
169 | * @param {string} result Serialized JSON with the reuslts of the text call | |
170 | * @return {object} Promise | |
171 | * @private | |
172 | */ | |
173 | ||
174 | _cssCb: function (selector, property, hash, expected, result) { | |
175 | 0 | var deferred = Q.defer(); |
176 | 0 | this.events.emit('driver:message', {key: 'css', hash: hash, property: property, expected: expected, selector: selector, value: JSON.parse(result).value}); |
177 | 0 | deferred.resolve(); |
178 | 0 | return deferred.promise; |
179 | }, | |
180 | ||
181 | /** | |
182 | * Checks th width of an element | |
183 | * | |
184 | * @method width | |
185 | * @param {string} selector Selector expression to find the element | |
186 | * @param {string} expected The expected width value | |
187 | * @param {string} hash Unique hash of that fn call | |
188 | * @chainable | |
189 | */ | |
190 | ||
191 | width: function (selector, expected, hash) { | |
192 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
193 | 0 | this.actionQueue.push(this.webdriverClient.size.bind(this.webdriverClient)); |
194 | 0 | this.actionQueue.push(this._widthCb.bind(this, selector, hash, expected)); |
195 | 0 | return this; |
196 | }, | |
197 | ||
198 | /** | |
199 | * Sends out an event with the results of the `width` call | |
200 | * | |
201 | * @method _widthCb | |
202 | * @param {string} selector Selector expression to find the element | |
203 | * @param {string} expected The expected width value | |
204 | * @param {string} hash Unique hash of that fn call | |
205 | * @param {string} result Serialized JSON with the reuslts of the text call | |
206 | * @return {object} Promise | |
207 | * @private | |
208 | */ | |
209 | ||
210 | _widthCb: function (selector, hash, expected, result) { | |
211 | 0 | var deferred = Q.defer(); |
212 | 0 | this.events.emit('driver:message', {key: 'width', hash: hash, expected: expected, selector: selector, value: JSON.parse(result).value.width}); |
213 | 0 | deferred.resolve(); |
214 | 0 | return deferred.promise; |
215 | }, | |
216 | ||
217 | /** | |
218 | * Checks th height of an element | |
219 | * | |
220 | * @method height | |
221 | * @param {string} selector Selector expression to find the element | |
222 | * @param {string} expected The expected height value | |
223 | * @param {string} hash Unique hash of that fn call | |
224 | * @chainable | |
225 | */ | |
226 | ||
227 | height: function (selector, expected, hash) { | |
228 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
229 | 0 | this.actionQueue.push(this.webdriverClient.size.bind(this.webdriverClient)); |
230 | 0 | this.actionQueue.push(this._heightCb.bind(this, selector, hash, expected)); |
231 | 0 | return this; |
232 | }, | |
233 | ||
234 | /** | |
235 | * Sends out an event with the results of the `height` call | |
236 | * | |
237 | * @method _heightCb | |
238 | * @param {string} selector Selector expression to find the element | |
239 | * @param {string} expected The expected height value | |
240 | * @param {string} hash Unique hash of that fn call | |
241 | * @param {string} result Serialized JSON with the reuslts of the text call | |
242 | * @return {object} Promise | |
243 | * @private | |
244 | */ | |
245 | ||
246 | _heightCb: function (selector, hash, expected, result) { | |
247 | 0 | var deferred = Q.defer(); |
248 | 0 | this.events.emit('driver:message', {key: 'height', hash: hash, expected: expected, selector: selector, value: JSON.parse(result).value.height}); |
249 | 0 | deferred.resolve(); |
250 | 0 | return deferred.promise; |
251 | }, | |
252 | ||
253 | /** | |
254 | * Checks if an element has an attribute with the expected value | |
255 | * | |
256 | * @method attribute | |
257 | * @param {string} selector Selector expression to find the element | |
258 | * @param {string} attribute The attribute that should be checked | |
259 | * @param {string} expected The expected text content | |
260 | * @param {string} hash Unique hash of that fn call | |
261 | * @chainable | |
262 | */ | |
263 | ||
264 | attribute: function (selector, attribute, expected, hash) { | |
265 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
266 | 0 | this.actionQueue.push(this.webdriverClient.getAttribute.bind(this.webdriverClient, attribute)); |
267 | 0 | this.actionQueue.push(this._attributeCb.bind(this, selector, hash, attribute, expected)); |
268 | 0 | return this; |
269 | }, | |
270 | ||
271 | /** | |
272 | * Sends out an event with the results of the `attribute` call | |
273 | * | |
274 | * @method _attributeCb | |
275 | * @param {string} selector Selector expression to find the element | |
276 | * @param {string} hash Unique hash of that fn call | |
277 | * @param {string} attribute The attribute that should be checked | |
278 | * @param {string} expected The expected attribute content | |
279 | * @param {string} result Serialized JSON with the results of the attribute call | |
280 | * @return {object} promise Attribute promise | |
281 | * @private | |
282 | */ | |
283 | ||
284 | _attributeCb: function (selector, hash, attribute, expected, result) { | |
285 | 0 | var deferred = Q.defer(); |
286 | 0 | this.events.emit('driver:message', {key: 'attribute', selector: selector, hash: hash, expected: expected, value: JSON.parse(result).value }); |
287 | 0 | deferred.resolve(); |
288 | 0 | return deferred.promise; |
289 | }, | |
290 | ||
291 | /** | |
292 | * Checks if an element has the expected value | |
293 | * | |
294 | * @method val | |
295 | * @param {string} selector Selector expression to find the element | |
296 | * @param {string} expected The expected content | |
297 | * @param {string} hash Unique hash of that fn call | |
298 | * @chainable | |
299 | */ | |
300 | ||
301 | val: function (selector, expected, hash) { | |
302 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
303 | 0 | this.actionQueue.push(this.webdriverClient.getAttribute.bind(this.webdriverClient, 'value')); |
304 | 0 | this.actionQueue.push(this._valCb.bind(this, selector, hash, expected)); |
305 | 0 | return this; |
306 | }, | |
307 | ||
308 | /** | |
309 | * Sends out an event with the results of the `val` call | |
310 | * | |
311 | * @method _valCb | |
312 | * @param {string} selector Selector expression to find the element | |
313 | * @param {string} hash Unique hash of that fn call | |
314 | * @param {string} expected The expected content | |
315 | * @param {string} result Serialized JSON with the results of the val call | |
316 | * @return {object} Promise | |
317 | * @private | |
318 | */ | |
319 | ||
320 | _valCb: function (selector, hash, expected, result) { | |
321 | 0 | var deferred = Q.defer(); |
322 | 0 | this.events.emit('driver:message', {key: 'val', selector: selector, hash: hash, expected: expected, value: JSON.parse(result).value }); |
323 | 0 | deferred.resolve(); |
324 | 0 | return deferred.promise; |
325 | }, | |
326 | ||
327 | /** | |
328 | * Checks if an element is selected | |
329 | * | |
330 | * @method selected | |
331 | * @param {string} selector Selector expression to find the element | |
332 | * @param {string} expected The expected content | |
333 | * @param {string} hash Unique hash of that fn call | |
334 | * @chainable | |
335 | */ | |
336 | ||
337 | selected: function (selector, expected, hash) { | |
338 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
339 | 0 | this.actionQueue.push(this.webdriverClient.selected.bind(this.webdriverClient)); |
340 | 0 | this.actionQueue.push(this._selectedCb.bind(this, selector, hash, expected)); |
341 | 0 | return this; |
342 | }, | |
343 | ||
344 | /** | |
345 | * Sends out an event with the results of the `selected` call | |
346 | * | |
347 | * @method _selectedCb | |
348 | * @param {string} selector Selector expression to find the element | |
349 | * @param {string} hash Unique hash of that fn call | |
350 | * @param {string} expected The expected content | |
351 | * @param {string} result Serialized JSON with the results of the selected call | |
352 | * @return {object} Promise | |
353 | * @private | |
354 | */ | |
355 | ||
356 | _selectedCb: function (selector, hash, expected, result) { | |
357 | 0 | var deferred = Q.defer(); |
358 | 0 | this.events.emit('driver:message', {key: 'selected', selector: selector, hash: hash, expected: expected, value: JSON.parse(result).value }); |
359 | 0 | deferred.resolve(); |
360 | 0 | return deferred.promise; |
361 | }, | |
362 | ||
363 | /** | |
364 | * Checks if an element is enabled | |
365 | * | |
366 | * @method enabled | |
367 | * @param {string} selector Selector expression to find the element | |
368 | * @param {string} expected The expected content | |
369 | * @param {string} hash Unique hash of that fn call | |
370 | * @chainable | |
371 | */ | |
372 | ||
373 | enabled: function (selector, expected, hash) { | |
374 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
375 | 0 | this.actionQueue.push(this.webdriverClient.enabled.bind(this.webdriverClient)); |
376 | 0 | this.actionQueue.push(this._enabledCb.bind(this, selector, hash, expected)); |
377 | 0 | return this; |
378 | }, | |
379 | ||
380 | /** | |
381 | * Sends out an event with the results of the `enabled` call | |
382 | * | |
383 | * @method _enabledCb | |
384 | * @param {string} selector Selector expression to find the element | |
385 | * @param {string} hash Unique hash of that fn call | |
386 | * @param {string} expected The expected content | |
387 | * @param {string} result Serialized JSON with the results of the selected call | |
388 | * @return {object} Promise | |
389 | * @private | |
390 | */ | |
391 | ||
392 | _enabledCb: function (selector, hash, expected, result) { | |
393 | 0 | var deferred = Q.defer(); |
394 | 0 | this.events.emit('driver:message', {key: 'enabled', selector: selector, hash: hash, expected: expected, value: JSON.parse(result).value }); |
395 | 0 | deferred.resolve(); |
396 | 0 | return deferred.promise; |
397 | }, | |
398 | ||
399 | /** | |
400 | * Submits a form | |
401 | * | |
402 | * @method submit | |
403 | * @param {string} selector Selector expression to find the element | |
404 | * @param {string} hash Unique hash of that fn call | |
405 | * @param {string} uuid Unique hash of that fn call | |
406 | * @chainable | |
407 | */ | |
408 | ||
409 | submit: function (selector, hash, uuid) { | |
410 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
411 | 0 | this.actionQueue.push(this.webdriverClient.submit.bind(this.webdriverClient)); |
412 | 0 | this.actionQueue.push(this._submitCb.bind(this, selector, hash, uuid)); |
413 | 0 | return this; |
414 | }, | |
415 | ||
416 | /** | |
417 | * Sends out an event with the results of the `submit` call | |
418 | * | |
419 | * @method _submitCb | |
420 | * @param {string} selector Selector expression to find the element | |
421 | * @param {string} hash Unique hash of that fn call | |
422 | * @param {string} uuid Unique hash of that fn call | |
423 | * @return {object} promise Click promise | |
424 | * @private | |
425 | */ | |
426 | ||
427 | _submitCb: function (selector, hash, uuid) { | |
428 | 0 | var deferred = Q.defer(); |
429 | 0 | this.events.emit('driver:message', {key: 'submit', value: selector, uuid: uuid, hash: hash}); |
430 | 0 | deferred.resolve(); |
431 | 0 | return deferred.promise; |
432 | }, | |
433 | ||
434 | /** | |
435 | * Clicks an element | |
436 | * | |
437 | * @method click | |
438 | * @param {string} selector Selector expression to find the element | |
439 | * @param {string} hash Unique hash of that fn call | |
440 | * @param {string} uuid Unique hash of that fn call | |
441 | * @chainable | |
442 | */ | |
443 | ||
444 | click: function (selector, hash, uuid) { | |
445 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
446 | 0 | this.actionQueue.push(this.webdriverClient.click.bind(this.webdriverClient)); |
447 | 0 | this.actionQueue.push(this._clickCb.bind(this, selector, hash, uuid)); |
448 | 0 | return this; |
449 | }, | |
450 | ||
451 | /** | |
452 | * Sends out an event with the results of the `click` call | |
453 | * | |
454 | * @method _clickCb | |
455 | * @param {string} selector Selector expression to find the element | |
456 | * @param {string} hash Unique hash of that fn call | |
457 | * @param {string} uuid Unique hash of that fn call | |
458 | * @return {object} promise Click promise | |
459 | * @private | |
460 | */ | |
461 | ||
462 | _clickCb: function (selector, hash, uuid) { | |
463 | 0 | var deferred = Q.defer(); |
464 | 0 | this.events.emit('driver:message', {key: 'click', value: selector, uuid: uuid, hash: hash}); |
465 | 0 | deferred.resolve(); |
466 | 0 | return deferred.promise; |
467 | }, | |
468 | ||
469 | /** | |
470 | * Scrolls from an element to a location defined in pixels | |
471 | * | |
472 | * @method scroll | |
473 | * @param {string} selector Selector expression to find the element | |
474 | * @param {object} options X offset, Y offset, Speed | |
475 | * @param {string} hash Unique hash of that fn call | |
476 | * @param {string} uuid Unique hash of that fn call | |
477 | * @chainable | |
478 | */ | |
479 | ||
480 | scroll: function (selector, options, hash, uuid) { | |
481 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector, options)); |
482 | 0 | this.actionQueue.push(this.webdriverClient.scroll.bind(this.webdriverClient)); |
483 | 0 | this.actionQueue.push(this._clickCb.bind(this, selector, options, hash, uuid)); |
484 | 0 | return this; |
485 | }, | |
486 | ||
487 | /** | |
488 | * Sends out an event with the results of the `scroll` call | |
489 | * | |
490 | * @method _scrollCb | |
491 | * @param {string} selector Selector expression to find the element | |
492 | * @param {object} options X offset, Y offset, Speed | |
493 | * @param {string} hash Unique hash of that fn call | |
494 | * @param {string} uuid Unique hash of that fn call | |
495 | * @return {object} promise Scroll promise | |
496 | * @private | |
497 | */ | |
498 | ||
499 | _scrollCb: function (selector, options, hash, uuid) { | |
500 | 0 | var deferred = Q.defer(); |
501 | 0 | this.events.emit('driver:message', {key: 'scroll', value: selector, uuid: uuid, hash: hash}); |
502 | 0 | deferred.resolve(); |
503 | 0 | return deferred.promise; |
504 | }, | |
505 | ||
506 | /** | |
507 | * Clicks an element | |
508 | * | |
509 | * @method click | |
510 | * @param {string} selector Selector expression to find the element | |
511 | * @param {string} hash Unique hash of that fn call | |
512 | * @chainable | |
513 | */ | |
514 | ||
515 | type: function (selector, keystrokes, hash) { | |
516 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
517 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
518 | 0 | this.actionQueue.push(this.webdriverClient.val.bind(this.webdriverClient, keystrokes)); |
519 | 0 | this.actionQueue.push(this._typeCb.bind(this, selector, keystrokes, hash)); |
520 | 0 | return this; |
521 | }, | |
522 | ||
523 | /** | |
524 | * Sends out an event with the results of the `type` call | |
525 | * | |
526 | * @method _typeCb | |
527 | * @param {string} selector Selector expression to find the element | |
528 | * @param {string} hash Unique hash of that fn call | |
529 | * @return {object} promise Type promise | |
530 | * @private | |
531 | */ | |
532 | ||
533 | _typeCb: function (selector, keystrokes, hash) { | |
534 | 0 | var deferred = Q.defer(); |
535 | 0 | this.events.emit('driver:message', {key: 'type', value: selector, keystrokes: keystrokes, uuid: hash, hash: hash}); |
536 | 0 | deferred.resolve(); |
537 | 0 | return deferred.promise; |
538 | }, | |
539 | ||
540 | /** | |
541 | * Sends keys to an element (whether or not it is an input) | |
542 | * | |
543 | * @method sendKeys | |
544 | * @param {string} selector Selector expression to find the element | |
545 | * @param {string} hash Unique hash of that fn call | |
546 | * @chainable | |
547 | */ | |
548 | ||
549 | sendKeys: function (selector, keystrokes, hash) { | |
550 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
551 | 0 | this.actionQueue.push(this.webdriverClient.sendKeys.bind(this.webdriverClient, keystrokes)); |
552 | 0 | this.actionQueue.push(this._sendKeysCb.bind(this, selector, keystrokes, hash)); |
553 | 0 | return this; |
554 | }, | |
555 | ||
556 | /** | |
557 | * Sends out an event with the results of the `sendKeys` call | |
558 | * | |
559 | * @method _sendKeysCb | |
560 | * @param {string} selector Selector expression to find the element | |
561 | * @param {string} hash Unique hash of that fn call | |
562 | * @return {object} promise Type promise | |
563 | * @private | |
564 | */ | |
565 | ||
566 | _sendKeysCb: function (selector, keystrokes, hash) { | |
567 | 0 | var deferred = Q.defer(); |
568 | 0 | this.events.emit('driver:message', {key: 'sendKeys', value: selector, keystrokes: keystrokes, uuid: hash, hash: hash}); |
569 | 0 | deferred.resolve(); |
570 | 0 | return deferred.promise; |
571 | }, | |
572 | ||
573 | /** | |
574 | * Wait for an element for a specific amount of time | |
575 | * | |
576 | * @method waitForElement | |
577 | * @param {string} selector Selector expression to find the element | |
578 | * @param {integer} timeout Time to wait in ms | |
579 | * @param {string} hash Unique hash of that fn call | |
580 | * @param {string} uuid Unique hash of that fn call | |
581 | * @chainable | |
582 | */ | |
583 | ||
584 | waitForElement: function (selector, timeout, hash, uuid) { | |
585 | 0 | this.actionQueue.push(this.webdriverClient.implicitWait.bind(this.webdriverClient, timeout)); |
586 | 0 | this.actionQueue.push(this._waitForElementCb.bind(this, selector, hash, uuid)); |
587 | 0 | return this; |
588 | }, | |
589 | ||
590 | /** | |
591 | * Sends out an event with the results of the `waitForElement` call | |
592 | * | |
593 | * @method _waitForElementCb | |
594 | * @param {string} selector Selector expression to find the element | |
595 | * @param {string} hash Unique hash of that fn call | |
596 | * @param {string} uuid Unique hash of that fn call | |
597 | * @return {object} promise WaitForElement promise | |
598 | * @private | |
599 | */ | |
600 | ||
601 | _waitForElementCb: function (selector, hash, uuid) { | |
602 | 0 | var deferred = Q.defer(); |
603 | 0 | this.events.emit('driver:message', {key: 'waitForElement', selector: selector, uuid: uuid, hash: hash}); |
604 | 0 | deferred.resolve(); |
605 | 0 | return deferred.promise; |
606 | }, | |
607 | ||
608 | /** | |
609 | * Returns the number of elements matched by the selector | |
610 | * | |
611 | * @method getNumberOfElements | |
612 | * @param {string} selector Selector expression to find the elements | |
613 | * @param {integer} expected Expected number of matched elements | |
614 | * @param {string} uuid Unique hash of that fn call | |
615 | * @chainable | |
616 | */ | |
617 | ||
618 | getNumberOfElements: function (selector, expected, hash) { | |
619 | 0 | this.actionQueue.push(this.webdriverClient.elements.bind(this.webdriverClient, selector)); |
620 | 0 | this.actionQueue.push(this._getNumberOfElementsCb.bind(this, selector, hash, expected)); |
621 | 0 | return this; |
622 | }, | |
623 | ||
624 | /** | |
625 | * Sends out an event with the results of the `getNumberOfElements` call | |
626 | * | |
627 | * @method _getNumberOfElementsCb | |
628 | * @param {string} selector Selector expression to find the element | |
629 | * @param {string} hash Unique hash of that fn call | |
630 | * @param {integer} expected Expected number of matched elements | |
631 | * @param {string} res Serialized JSON with the results of the getNumberOfElements call | |
632 | * @return {object} promise GetNumberOfElements promise | |
633 | * @private | |
634 | */ | |
635 | ||
636 | _getNumberOfElementsCb: function (selector, hash, expected, res) { | |
637 | 0 | var deferred = Q.defer(); |
638 | 0 | var result = JSON.parse(res); |
639 | // check if the expression matched any element | |
640 | 0 | if (result.value === -1) { |
641 | 0 | this.events.emit('driver:message', {key: 'numberOfElements', hash: hash, selector: selector, expected: expected, value: 0}); |
642 | } else { | |
643 | 0 | this.events.emit('driver:message', {key: 'numberOfElements', selector: selector, expected: expected, hash: hash, value: result.value.length}); |
644 | } | |
645 | ||
646 | 0 | deferred.resolve(); |
647 | 0 | return deferred.promise; |
648 | }, | |
649 | ||
650 | ||
651 | /** | |
652 | * Returns the number of visible elements matched by the selector | |
653 | * | |
654 | * @method getNumberOfVisibleElements | |
655 | * @param {string} selector Selector expression to find the elements | |
656 | * @param {integer} expected Expected number of matched elements | |
657 | * @param {string} uuid Unique hash of that fn call | |
658 | * @chainable | |
659 | */ | |
660 | ||
661 | getNumberOfVisibleElements: function (selector, expected, hash) { | |
662 | 0 | this.actionQueue.push(this.webdriverClient.elements.bind(this.webdriverClient, selector)); |
663 | 0 | this.actionQueue.push(function (result) { |
664 | 0 | var deferred = Q.defer(); |
665 | 0 | var res = JSON.parse(result); |
666 | 0 | var resLength = res.value.length; |
667 | 0 | var curLength = 0; |
668 | 0 | var visibleElement = []; |
669 | ||
670 | 0 | res.value.forEach(function (element) { |
671 | 0 | var fakeResponse = JSON.stringify({sessionId: res.sessionId, status: 0, value: element.ELEMENT}); |
672 | 0 | this.webdriverClient.options.id = element.ELEMENT; |
673 | 0 | this.webdriverClient.displayed.bind(this.webdriverClient, selector)(fakeResponse).then(function (visRes) { |
674 | 0 | curLength++; |
675 | 0 | if (JSON.parse(visRes).value === true) { |
676 | 0 | visibleElement.push(element); |
677 | } | |
678 | 0 | if (curLength === resLength) { |
679 | 0 | deferred.resolve(JSON.stringify({sessionId: res.sessionId, status: 0, value: visibleElement})); |
680 | } | |
681 | }); | |
682 | }.bind(this)); | |
683 | ||
684 | 0 | return deferred.promise; |
685 | }.bind(this)); | |
686 | 0 | this.actionQueue.push(this._getNumberOfVisibleElementsCb.bind(this, selector, hash, expected)); |
687 | 0 | return this; |
688 | }, | |
689 | ||
690 | /** | |
691 | * Sends out an event with the results of the `getNumberOfVisibleElements` call | |
692 | * | |
693 | * @method _getNumberOfElementsCb | |
694 | * @param {string} selector Selector expression to find the element | |
695 | * @param {string} hash Unique hash of that fn call | |
696 | * @param {integer} expected Expected number of matched elements | |
697 | * @param {string} res Serialized JSON with the results of the getNumberOfVisibleElements call | |
698 | * @return {object} promise GetNumberOfElements promise | |
699 | * @private | |
700 | */ | |
701 | ||
702 | _getNumberOfVisibleElementsCb: function (selector, hash, expected, res) { | |
703 | 0 | var deferred = Q.defer(); |
704 | 0 | var result = JSON.parse(res); |
705 | ||
706 | // check if the expression matched any element | |
707 | 0 | if (result.value === -1) { |
708 | 0 | this.events.emit('driver:message', {key: 'numberOfVisibleElements', hash: hash, selector: selector, expected: expected, value: 0}); |
709 | } else { | |
710 | 0 | this.events.emit('driver:message', {key: 'numberOfVisibleElements', selector: selector, expected: expected, hash: hash, value: result.value.length}); |
711 | } | |
712 | ||
713 | 0 | deferred.resolve(); |
714 | 0 | return deferred.promise; |
715 | } | |
716 | ||
717 | }; | |
718 | ||
719 | /** | |
720 | * Mixes in element methods | |
721 | * | |
722 | * @param {Dalek.DriverNative} DalekNative Native driver base class | |
723 | * @return {Dalek.DriverNative} DalekNative Native driver base class | |
724 | */ | |
725 | ||
726 | 1 | module.exports = function (DalekNative) { |
727 | // mixin methods | |
728 | 0 | Object.keys(Element).forEach(function (fn) { |
729 | 0 | DalekNative.prototype[fn] = Element[fn]; |
730 | }); | |
731 | ||
732 | 0 | return DalekNative; |
733 | }; | |
734 |
Line | Hits | Source |
---|---|---|
1 | /*! | |
2 | * | |
3 | * Copyright (c) 2013 Sebastian Golasch | |
4 | * | |
5 | * Permission is hereby granted, free of charge, to any person obtaining a | |
6 | * copy of this software and associated documentation files (the "Software"), | |
7 | * to deal in the Software without restriction, including without limitation | |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
9 | * and/or sell copies of the Software, and to permit persons to whom the | |
10 | * Software is furnished to do so, subject to the following conditions: | |
11 | * | |
12 | * The above copyright notice and this permission notice shall be included | |
13 | * in all copies or substantial portions of the Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
21 | * DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
25 | 1 | 'use strict'; |
26 | ||
27 | // ext. libs | |
28 | 1 | var Q = require('q'); |
29 | ||
30 | /** | |
31 | * Frame related methods | |
32 | * | |
33 | * @module Driver | |
34 | * @class Frame | |
35 | * @namespace Dalek.DriverNative.Commands | |
36 | */ | |
37 | ||
38 | 1 | var Frame = { |
39 | ||
40 | /** | |
41 | * Switches to frame context | |
42 | * | |
43 | * @method toFrame | |
44 | * @param {string} selector Selector expression to find the element | |
45 | * @param {string} hash Unique hash of that fn call | |
46 | * @chainable | |
47 | */ | |
48 | ||
49 | toFrame: function (selector, hash) { | |
50 | 0 | if (selector !== null) { |
51 | 0 | this.actionQueue.push(this.webdriverClient.element.bind(this.webdriverClient, selector)); |
52 | } | |
53 | 0 | this.actionQueue.push(this.webdriverClient.frame.bind(this.webdriverClient)); |
54 | 0 | this.actionQueue.push(this._frameCb.bind(this, selector, hash)); |
55 | 0 | return this; |
56 | }, | |
57 | ||
58 | /** | |
59 | * Sends out an event with the results of the `toFrame` call | |
60 | * | |
61 | * @method _frameCb | |
62 | * @param {string} selector Selector expression to find the element | |
63 | * @param {string} hash Unique hash of that fn call | |
64 | * @param {string} result Serialized JSON with the reuslts of the toFrame call | |
65 | * @return {object} promise Exists promise | |
66 | * @private | |
67 | */ | |
68 | ||
69 | _frameCb: function (selector, hash) { | |
70 | 0 | var deferred = Q.defer(); |
71 | 0 | this.events.emit('driver:message', {key: 'toFrame', selector: selector, hash: hash, value: true}); |
72 | 0 | deferred.resolve(); |
73 | 0 | return deferred.promise; |
74 | } | |
75 | }; | |
76 | ||
77 | /** | |
78 | * Mixes in element methods | |
79 | * | |
80 | * @param {Dalek.DriverNative} DalekNative Native driver base class | |
81 | * @return {Dalek.DriverNative} DalekNative Native driver base class | |
82 | */ | |
83 | ||
84 | 1 | module.exports = function (DalekNative) { |
85 | // mixin methods | |
86 | 0 | Object.keys(Frame).forEach(function (fn) { |
87 | 0 | DalekNative.prototype[fn] = Frame[fn]; |
88 | }); | |
89 | ||
90 | 0 | return DalekNative; |
91 | }; | |
92 |
Line | Hits | Source |
---|---|---|
1 | /*! | |
2 | * | |
3 | * Copyright (c) 2013 Sebastian Golasch | |
4 | * | |
5 | * Permission is hereby granted, free of charge, to any person obtaining a | |
6 | * copy of this software and associated documentation files (the "Software"), | |
7 | * to deal in the Software without restriction, including without limitation | |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
9 | * and/or sell copies of the Software, and to permit persons to whom the | |
10 | * Software is furnished to do so, subject to the following conditions: | |
11 | * | |
12 | * The above copyright notice and this permission notice shall be included | |
13 | * in all copies or substantial portions of the Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
21 | * DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
25 | 1 | 'use strict'; |
26 | ||
27 | // ext. libs | |
28 | 1 | var Q = require('q'); |
29 | ||
30 | /** | |
31 | * Page related methods | |
32 | * | |
33 | * @module Driver | |
34 | * @class Page | |
35 | * @namespace Dalek.DriverNative.Commands | |
36 | */ | |
37 | ||
38 | 1 | var Page = { |
39 | ||
40 | /** | |
41 | * This function is non operational | |
42 | * | |
43 | * @method noop | |
44 | * @param {mixed} message Whatever yu like | |
45 | * @param {string} hash Unique hash of that fn call | |
46 | * @chainable | |
47 | */ | |
48 | ||
49 | noop: function (message, hash) { | |
50 | 0 | this.actionQueue.push(this._noopCb.bind(this, message, hash)); |
51 | 0 | return this; |
52 | }, | |
53 | ||
54 | /** | |
55 | * Sends out an event with the results of the `noop` call | |
56 | * | |
57 | * @method _noopCb | |
58 | * @param {mixed} message Whatever yu like | |
59 | * @param {string} hash Unique hash of that fn call | |
60 | * @return {object} Promise | |
61 | * @private | |
62 | */ | |
63 | ||
64 | _noopCb: function (message, hash) { | |
65 | 0 | var deferred = Q.defer(); |
66 | 0 | this.events.emit('driver:message', {key: 'noop', uuid: hash, hash: hash, value: message}); |
67 | 0 | deferred.resolve(); |
68 | 0 | return deferred.promise; |
69 | }, | |
70 | ||
71 | /** | |
72 | * Gets the HTML source of a page | |
73 | * | |
74 | * @method source | |
75 | * @param {string} hash Unique hash of that fn call | |
76 | * @chainable | |
77 | */ | |
78 | ||
79 | source: function (hash) { | |
80 | 0 | this.actionQueue.push(this.webdriverClient.source.bind(this.webdriverClient)); |
81 | 0 | this.actionQueue.push(this._sourceCb.bind(this, hash)); |
82 | 0 | return this; |
83 | }, | |
84 | ||
85 | /** | |
86 | * Sends out an event with the results of the `source` call | |
87 | * | |
88 | * @method _sourceCb | |
89 | * @param {string} hash Unique hash of that fn call | |
90 | * @param {string} source Serialized JSON with the results of the source call | |
91 | * @return {object} Promise | |
92 | * @private | |
93 | */ | |
94 | ||
95 | _sourceCb: function (hash, source) { | |
96 | 0 | var deferred = Q.defer(); |
97 | 0 | this.events.emit('driver:message', {key: 'source', uuid: hash, hash: hash, value: JSON.parse(source).value}); |
98 | 0 | deferred.resolve(); |
99 | 0 | return deferred.promise; |
100 | }, | |
101 | ||
102 | /** | |
103 | * Checks the document title of a page | |
104 | * | |
105 | * @method title | |
106 | * @param {string} expected Expected page title | |
107 | * @param {string} hash Unique hash of that fn call | |
108 | * @chainable | |
109 | */ | |
110 | ||
111 | title: function (expected, hash) { | |
112 | 0 | this.actionQueue.push(this.webdriverClient.title.bind(this.webdriverClient)); |
113 | 0 | this.actionQueue.push(this._titleCb.bind(this, expected, hash)); |
114 | 0 | return this; |
115 | }, | |
116 | ||
117 | /** | |
118 | * Sends out an event with the results of the `title` call | |
119 | * | |
120 | * @method _titleCb | |
121 | * @param {string} expected Expected page title | |
122 | * @param {string} hash Unique hash of that fn call | |
123 | * @param {string} title Serialized JSON with the results of the title call | |
124 | * @return {object} promise Title promise | |
125 | * @private | |
126 | */ | |
127 | ||
128 | _titleCb: function (expected, hash, title) { | |
129 | 0 | var deferred = Q.defer(); |
130 | 0 | this.events.emit('driver:message', {key: 'title', expected: expected, hash: hash, value: JSON.parse(title).value}); |
131 | 0 | deferred.resolve(); |
132 | 0 | return deferred.promise; |
133 | }, | |
134 | ||
135 | /** | |
136 | * Checks the text of an alaert, prompt or confirm dialog | |
137 | * | |
138 | * @method alertText | |
139 | * @param {string} expected Expected alert text | |
140 | * @param {string} hash Unique hash of that fn call | |
141 | * @chainable | |
142 | */ | |
143 | ||
144 | alertText: function (expected, hash) { | |
145 | 0 | this.actionQueue.push(this.webdriverClient.alertText.bind(this.webdriverClient)); |
146 | 0 | this.actionQueue.push(this._alertTextCb.bind(this, expected, hash)); |
147 | 0 | return this; |
148 | }, | |
149 | ||
150 | /** | |
151 | * Sends out an event with the results of the `alertText` call | |
152 | * | |
153 | * @method _alertTextCb | |
154 | * @param {string} expected Expected alert text | |
155 | * @param {string} hash Unique hash of that fn call | |
156 | * @param {string} alertText Serialized JSON with the results of the alertText call | |
157 | * @return {object} promise alertText promise | |
158 | * @private | |
159 | */ | |
160 | ||
161 | _alertTextCb: function (expected, hash, alertText) { | |
162 | 0 | var deferred = Q.defer(); |
163 | 0 | this.events.emit('driver:message', {key: 'alertText', expected: expected, hash: hash, value: JSON.parse(alertText).value}); |
164 | 0 | deferred.resolve(); |
165 | 0 | return deferred.promise; |
166 | }, | |
167 | ||
168 | /** | |
169 | * Sends text to a javascript prompt dialog box | |
170 | * | |
171 | * @method promptText | |
172 | * @param {object} dimensions New window width & height | |
173 | * @param {string} hash Unique hash of that fn call | |
174 | * @chainable | |
175 | */ | |
176 | ||
177 | promptText: function (text, hash) { | |
178 | 0 | this.actionQueue.push(this.webdriverClient.promptText.bind(this.webdriverClient, text)); |
179 | 0 | this.actionQueue.push(this._promptTextCb.bind(this, text, hash)); |
180 | 0 | return this; |
181 | }, | |
182 | ||
183 | /** | |
184 | * Sends out an event with the results of the `promptText` call | |
185 | * | |
186 | * @method _promptTextCb | |
187 | * @param {object} dimensions New window width & height | |
188 | * @param {string} hash Unique hash of that fn call | |
189 | * @param {string} result Serialized JSON with the reuslts of the toFrame call | |
190 | * @return {object} promise Exists promise | |
191 | * @private | |
192 | */ | |
193 | ||
194 | _promptTextCb: function (text, hash) { | |
195 | 0 | var deferred = Q.defer(); |
196 | 0 | this.events.emit('driver:message', {key: 'promptText', text: text, hash: hash, value: true}); |
197 | 0 | deferred.resolve(); |
198 | 0 | return deferred.promise; |
199 | }, | |
200 | ||
201 | /** | |
202 | * Accepts (e.g. oressing the OK button) an javascript alert, prompt or confirm dialog | |
203 | * | |
204 | * @method acceptAlert | |
205 | * @param {string} hash Unique hash of that fn call | |
206 | * @chainable | |
207 | */ | |
208 | ||
209 | acceptAlert: function (hash) { | |
210 | 0 | this.actionQueue.push(this.webdriverClient.acceptAlert.bind(this.webdriverClient)); |
211 | 0 | this.actionQueue.push(this._acceptAlertCb.bind(this, hash)); |
212 | 0 | return this; |
213 | }, | |
214 | ||
215 | /** | |
216 | * Sends out an event with the results of the `acceptAlert` call | |
217 | * | |
218 | * @method _acceptAlertCb | |
219 | * @param {string} hash Unique hash of that fn call | |
220 | * @param {string} result Serialized JSON with the reuslts of the toFrame call | |
221 | * @return {object} promise Exists promise | |
222 | * @private | |
223 | */ | |
224 | ||
225 | _acceptAlertCb: function (text, hash) { | |
226 | 0 | var deferred = Q.defer(); |
227 | 0 | this.events.emit('driver:message', {key: 'acceptAlert', hash: hash, value: true}); |
228 | 0 | deferred.resolve(); |
229 | 0 | return deferred.promise; |
230 | }, | |
231 | ||
232 | /** | |
233 | * Accepts (e.g. oressing the OK button) an javascript alert, prompt or confirm dialog | |
234 | * | |
235 | * @method dismissAlert | |
236 | * @param {string} hash Unique hash of that fn call | |
237 | * @chainable | |
238 | */ | |
239 | ||
240 | dismissAlert: function (hash) { | |
241 | 0 | this.actionQueue.push(this.webdriverClient.dismissAlert.bind(this.webdriverClient)); |
242 | 0 | this.actionQueue.push(this._dismissAlertCb.bind(this, hash)); |
243 | 0 | return this; |
244 | }, | |
245 | ||
246 | /** | |
247 | * Sends out an event with the results of the `dismissAlert` call | |
248 | * | |
249 | * @method _dismissAlertCb | |
250 | * @param {string} hash Unique hash of that fn call | |
251 | * @param {string} result Serialized JSON with the reuslts of the toFrame call | |
252 | * @return {object} promise Exists promise | |
253 | * @private | |
254 | */ | |
255 | ||
256 | _dismissAlertCb: function (text, hash) { | |
257 | 0 | var deferred = Q.defer(); |
258 | 0 | this.events.emit('driver:message', {key: 'dismissAlert', hash: hash, value: true}); |
259 | 0 | deferred.resolve(); |
260 | 0 | return deferred.promise; |
261 | }, | |
262 | ||
263 | /** | |
264 | * Wait for a specific amount of time | |
265 | * | |
266 | * @method wait | |
267 | * @param {integer} timeout Time to wait in ms | |
268 | * @param {string} hash Unique hash of that fn call | |
269 | * @param {string} uuid Unique hash of that fn call | |
270 | * @chainable | |
271 | */ | |
272 | ||
273 | wait: function (timeout, hash, uuid) { | |
274 | 0 | this.actionQueue.push(this.webdriverClient.implicitWait.bind(this.webdriverClient, timeout)); |
275 | 0 | this.actionQueue.push(this._waitCb.bind(this, timeout, hash, uuid)); |
276 | 0 | return this; |
277 | }, | |
278 | ||
279 | /** | |
280 | * Sends out an event with the results of the `wait` call | |
281 | * | |
282 | * @method _waitCb | |
283 | * @param {integer} timeout Time to wait in ms | |
284 | * @param {string} hash Unique hash of that fn call | |
285 | * @param {string} uuid Unique hash of that fn call | |
286 | * @return {object} promise WaitForElement promise | |
287 | * @private | |
288 | */ | |
289 | ||
290 | _waitCb: function (timeout, hash, uuid) { | |
291 | 0 | var deferred = Q.defer(); |
292 | 0 | this.events.emit('driver:message', {key: 'wait', timeout: timeout, uuid: uuid, hash: hash, value: timeout + ' ms'}); |
293 | 0 | setTimeout(function () { |
294 | 0 | deferred.resolve(); |
295 | }.bind(this), timeout); | |
296 | 0 | return deferred.promise; |
297 | } | |
298 | ||
299 | }; | |
300 | ||
301 | /** | |
302 | * Mixes in page methods | |
303 | * | |
304 | * @param {Dalek.DriverNative} DalekNative Native driver base class | |
305 | * @return {Dalek.DriverNative} DalekNative Native driver base class | |
306 | */ | |
307 | ||
308 | 1 | module.exports = function (DalekNative) { |
309 | // mixin methods | |
310 | 0 | Object.keys(Page).forEach(function (fn) { |
311 | 0 | DalekNative.prototype[fn] = Page[fn]; |
312 | }); | |
313 | ||
314 | 0 | return DalekNative; |
315 | }; | |
316 |
Line | Hits | Source |
---|---|---|
1 | /*! | |
2 | * | |
3 | * Copyright (c) 2013 Sebastian Golasch | |
4 | * | |
5 | * Permission is hereby granted, free of charge, to any person obtaining a | |
6 | * copy of this software and associated documentation files (the "Software"), | |
7 | * to deal in the Software without restriction, including without limitation | |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
9 | * and/or sell copies of the Software, and to permit persons to whom the | |
10 | * Software is furnished to do so, subject to the following conditions: | |
11 | * | |
12 | * The above copyright notice and this permission notice shall be included | |
13 | * in all copies or substantial portions of the Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
21 | * DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
25 | 1 | 'use strict'; |
26 | ||
27 | // ext. libs | |
28 | 1 | var Q = require('q'); |
29 | 1 | var fs = require('fs'); |
30 | ||
31 | /** | |
32 | * Screenshot related methods | |
33 | * | |
34 | * @module Driver | |
35 | * @class Screenshot | |
36 | * @namespace Dalek.DriverNative.Commands | |
37 | */ | |
38 | ||
39 | 1 | var Screenshot = { |
40 | ||
41 | /** | |
42 | * Makes an screenshot of the current page | |
43 | * | |
44 | * @method screenshot | |
45 | * @param {string} path Root directory path | |
46 | * @param {string} pathname Pathname of the screenshot path | |
47 | * @param {string} hash Unique hash of that fn call | |
48 | * @param {string} uuid Unique hash of that fn call | |
49 | * @chainable | |
50 | */ | |
51 | ||
52 | screenshot: function (path, pathname, hash, uuid) { | |
53 | 0 | this.actionQueue.push(this.webdriverClient.screenshot.bind(this.webdriverClient)); |
54 | 0 | this.actionQueue.push(this._screenshotCb.bind(this, path, pathname, hash, uuid)); |
55 | 0 | return this; |
56 | }, | |
57 | ||
58 | /** | |
59 | * Sends out an event with the results of the `screenshot` call | |
60 | * and stores the screenshot in the filesystem | |
61 | * | |
62 | * @method _screenshotCb | |
63 | * @param {string} path Root directory path | |
64 | * @param {string} pathname Pathname of the screenshot path | |
65 | * @param {string} hash Unique hash of that fn call | |
66 | * @param {string} uuid Unique hash of that fn call | |
67 | * @param {string} result Serialized JSON result of the screenshot call | |
68 | * @return {object} promise Screenshot promise | |
69 | * @private | |
70 | */ | |
71 | ||
72 | _screenshotCb: function (path, pathname, hash, uuid, result) { | |
73 | 0 | var deferred = Q.defer(); |
74 | // replace base64 metadata | |
75 | 0 | var base64Data = JSON.parse(result).value.replace(/^data:image\/png;base64,/,''); |
76 | // replace placeholders | |
77 | 0 | var realpath = this._replacePathPlaceholder(path + pathname); |
78 | // check if we need to add a new directory | |
79 | 0 | this._recursiveMakeDirSync(realpath.substring(0, realpath.lastIndexOf('/'))); |
80 | // write the screenshot | |
81 | 0 | fs.writeFileSync(realpath, base64Data, 'base64'); |
82 | 0 | this.events.emit('driver:message', {key: 'screenshot', value: realpath, uuid: hash, hash: hash}); |
83 | 0 | deferred.resolve(); |
84 | 0 | return deferred.promise; |
85 | }, | |
86 | ||
87 | /** | |
88 | * Recursige mkdir helper | |
89 | * | |
90 | * @method _recursiveMakeDirSync | |
91 | * @param {string} path Path to create | |
92 | * @private | |
93 | */ | |
94 | ||
95 | _recursiveMakeDirSync: function (path) { | |
96 | 0 | var pathSep = require('path').sep; |
97 | 0 | var dirs = path.split(pathSep); |
98 | 0 | var root = ''; |
99 | ||
100 | 0 | while (dirs.length > 0) { |
101 | 0 | var dir = dirs.shift(); |
102 | 0 | if (dir === '') { |
103 | 0 | root = pathSep; |
104 | } | |
105 | 0 | if (!fs.existsSync(root + dir)) { |
106 | 0 | fs.mkdirSync(root + dir); |
107 | } | |
108 | 0 | root += dir + pathSep; |
109 | } | |
110 | }, | |
111 | ||
112 | /** | |
113 | * Return the formatted os name | |
114 | * | |
115 | * @method _parseOS | |
116 | * @param {string} Pathname | |
117 | * @return {string} Formatted pathname | |
118 | * @private | |
119 | */ | |
120 | ||
121 | _replacePathPlaceholder: function (pathname) { | |
122 | 0 | pathname = pathname.replace(':browser', this.browserName); |
123 | 0 | pathname = pathname.replace(':version', this._parseBrowserVersion(this.sessionStatus.version)); |
124 | 0 | pathname = pathname.replace(':timestamp', Math.round(new Date().getTime() / 1000)); |
125 | 0 | pathname = pathname.replace(':osVersion', this._parseOSVersion(this.driverStatus.os.version)); |
126 | 0 | pathname = pathname.replace(':os', this._parseOS(this.driverStatus.os.name)); |
127 | 0 | pathname = pathname.replace(':datetime', this._parseDatetime()); |
128 | 0 | pathname = pathname.replace(':date', this._parseDate()); |
129 | 0 | pathname = pathname.replace(':viewport', this._parseViewport()); |
130 | 0 | return pathname; |
131 | }, | |
132 | ||
133 | /** | |
134 | * Return the formatted os name | |
135 | * | |
136 | * @method _parseOS | |
137 | * @return {string} OS name | |
138 | * @private | |
139 | */ | |
140 | ||
141 | _parseOS: function (os) { | |
142 | 0 | var mappings = { |
143 | 'mac': 'OSX', | |
144 | 'Mac OS X': 'OSX' | |
145 | }; | |
146 | 0 | return mappings[os] || 'unknown'; |
147 | }, | |
148 | ||
149 | /** | |
150 | * Return the formatted os version | |
151 | * | |
152 | * @method _parseOSVersion | |
153 | * @return {string} OS version | |
154 | * @private | |
155 | */ | |
156 | ||
157 | _parseOSVersion: function (version) { | |
158 | 0 | var vs = version.replace(/[^0-9\\.]/g, ''); |
159 | 0 | vs = vs.replace(/\./g, '_'); |
160 | 0 | return vs; |
161 | }, | |
162 | ||
163 | /** | |
164 | * Return the formatted browser version | |
165 | * | |
166 | * @method _parseBrowserVersion | |
167 | * @return {string} Browser version | |
168 | * @private | |
169 | */ | |
170 | ||
171 | _parseBrowserVersion: function (version) { | |
172 | 0 | return version.replace(/\./g, '_'); |
173 | }, | |
174 | ||
175 | /** | |
176 | * Return the formatted date | |
177 | * | |
178 | * @method _parseDate | |
179 | * @return {string} Date | |
180 | * @private | |
181 | */ | |
182 | ||
183 | _parseDate: function () { | |
184 | 0 | var date = new Date(); |
185 | 0 | var dateStr = ''; |
186 | 0 | var day = date.getDate(); |
187 | 0 | var month = date.getMonth(); |
188 | ||
189 | 0 | month = (month+'').length === 1 ? '0' + month : month; |
190 | 0 | day = (day+'').length === 1 ? '0' + day : day; |
191 | ||
192 | 0 | dateStr += month + '_'; |
193 | 0 | dateStr += day + '_'; |
194 | 0 | dateStr += date.getFullYear(); |
195 | ||
196 | 0 | return dateStr; |
197 | }, | |
198 | ||
199 | /** | |
200 | * Return the formatted datetime | |
201 | * | |
202 | * @method _parseDatetime | |
203 | * @return {string} Datetime | |
204 | * @private | |
205 | */ | |
206 | ||
207 | _parseDatetime: function () { | |
208 | 0 | var date = new Date(); |
209 | 0 | var dateStr = this._parseDate(); |
210 | 0 | var hours = date.getHours(); |
211 | 0 | var minutes = date.getMinutes(); |
212 | 0 | var seconds = date.getSeconds(); |
213 | ||
214 | 0 | hours = (hours+'').length === 1 ? '0' + hours : hours; |
215 | 0 | minutes = (minutes+'').length === 1 ? '0' + minutes : minutes; |
216 | 0 | seconds = (seconds+'').length === 1 ? '0' + seconds : seconds; |
217 | ||
218 | 0 | dateStr = dateStr + '_' + hours; |
219 | 0 | dateStr = dateStr + '_' + minutes; |
220 | 0 | dateStr = dateStr + '_' + seconds; |
221 | ||
222 | 0 | return dateStr; |
223 | }, | |
224 | ||
225 | /** | |
226 | * Return the formatted viewport | |
227 | * | |
228 | * @method _parseViewport | |
229 | * @return {string} Viewport | |
230 | * @private | |
231 | */ | |
232 | ||
233 | _parseViewport: function () { | |
234 | 0 | var viewport = this.config.get('viewport'); |
235 | 0 | return 'w' + viewport.width + '_h' + viewport.height; |
236 | } | |
237 | ||
238 | }; | |
239 | ||
240 | /** | |
241 | * Mixes in screenshot methods | |
242 | * | |
243 | * @param {Dalek.DriverNative} DalekNative Native driver base class | |
244 | * @return {Dalek.DriverNative} DalekNative Native driver base class | |
245 | */ | |
246 | ||
247 | 1 | module.exports = function (DalekNative) { |
248 | // mixin methods | |
249 | 0 | Object.keys(Screenshot).forEach(function (fn) { |
250 | 0 | DalekNative.prototype[fn] = Screenshot[fn]; |
251 | }); | |
252 | ||
253 | 0 | return DalekNative; |
254 | }; | |
255 |
Line | Hits | Source |
---|---|---|
1 | /*! | |
2 | * | |
3 | * Copyright (c) 2013 Sebastian Golasch | |
4 | * | |
5 | * Permission is hereby granted, free of charge, to any person obtaining a | |
6 | * copy of this software and associated documentation files (the "Software"), | |
7 | * to deal in the Software without restriction, including without limitation | |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
9 | * and/or sell copies of the Software, and to permit persons to whom the | |
10 | * Software is furnished to do so, subject to the following conditions: | |
11 | * | |
12 | * The above copyright notice and this permission notice shall be included | |
13 | * in all copies or substantial portions of the Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
21 | * DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
25 | 1 | 'use strict'; |
26 | ||
27 | // ext. libs | |
28 | 1 | var Q = require('q'); |
29 | ||
30 | /** | |
31 | * Url related methods | |
32 | * | |
33 | * @module Driver | |
34 | * @class Url | |
35 | * @namespace Dalek.DriverNative.Commands | |
36 | */ | |
37 | ||
38 | 1 | var Url = { |
39 | ||
40 | /** | |
41 | * Navigate to a new URL | |
42 | * | |
43 | * @method open | |
44 | * @param {string} url Url to navigate to | |
45 | * @param {string} hash Unique hash of that fn call | |
46 | * @param {string} uuid Unique hash of that fn call | |
47 | * @chainable | |
48 | */ | |
49 | ||
50 | open: function (url, hash, uuid) { | |
51 | 0 | this.lastCalledUrl = url; |
52 | 0 | this.actionQueue.push(this.webdriverClient.url.bind(this.webdriverClient, url)); |
53 | 0 | this.actionQueue.push(this._openCb.bind(this, url, hash, uuid)); |
54 | 0 | return this; |
55 | }, | |
56 | ||
57 | /** | |
58 | * Sends out an event with the results of the `open` call | |
59 | * | |
60 | * @method _openCb | |
61 | * @param {string} url Url to navigate to | |
62 | * @param {string} hash Unique hash of that fn call | |
63 | * @param {string} uuid Unique hash of that fn call | |
64 | * @return {object} promise Open promise | |
65 | * @private | |
66 | */ | |
67 | ||
68 | _openCb: function (url, hash, uuid) { | |
69 | 0 | var deferred = Q.defer(); |
70 | 0 | this.events.emit('driver:message', {key: 'open', value: url, hash: hash, uuid: uuid}); |
71 | 0 | deferred.resolve(); |
72 | 0 | return deferred.promise; |
73 | }, | |
74 | ||
75 | /** | |
76 | * Fetches the current url | |
77 | * | |
78 | * @method url | |
79 | * @param {string} expected Expected url | |
80 | * @param {string} hash Unique hash of that fn call | |
81 | * @chainable | |
82 | */ | |
83 | ||
84 | url: function (expected, hash) { | |
85 | 0 | this.actionQueue.push(this.webdriverClient.getUrl.bind(this.webdriverClient)); |
86 | 0 | this.actionQueue.push(this._urlCb.bind(this, expected, hash)); |
87 | 0 | return this; |
88 | }, | |
89 | ||
90 | /** | |
91 | * Sends out an event with the results of the `url` call | |
92 | * | |
93 | * @method _urlCb | |
94 | * @param {string} expected Expected url | |
95 | * @param {string} hash Unique hash of that fn call | |
96 | * @param {string} url Serialized JSON result of url call | |
97 | * @return {object} promise Url promise | |
98 | * @private | |
99 | */ | |
100 | ||
101 | _urlCb: function (expected, hash, url) { | |
102 | 0 | var deferred = Q.defer(); |
103 | 0 | this.events.emit('driver:message', {key: 'url', expected: expected, hash: hash, value: JSON.parse(url).value}); |
104 | 0 | deferred.resolve(); |
105 | 0 | return deferred.promise; |
106 | }, | |
107 | ||
108 | /** | |
109 | * Navigate backwards in the browser history, if possible. | |
110 | * | |
111 | * @method back | |
112 | * @param {string} hash Unique hash of that fn call | |
113 | * @param {string} uuid Unique hash of that fn call | |
114 | * @chainable | |
115 | */ | |
116 | ||
117 | back: function (hash, uuid) { | |
118 | 0 | this._createNonReturnee('back')(hash, uuid); |
119 | 0 | return this; |
120 | }, | |
121 | ||
122 | /** | |
123 | * Navigate forwards in the browser history, if possible. | |
124 | * | |
125 | * @method forward | |
126 | * @param {string} hash Unique hash of that fn call | |
127 | * @param {string} uuid Unique hash of that fn call | |
128 | * @chainable | |
129 | */ | |
130 | ||
131 | forward: function (hash, uuid) { | |
132 | 0 | this._createNonReturnee('forward')(hash, uuid); |
133 | 0 | return this; |
134 | }, | |
135 | ||
136 | /** | |
137 | * Refresh the current page | |
138 | * | |
139 | * @method refresh | |
140 | * @param {string} hash Unique hash of that fn call | |
141 | * @param {string} uuid Unique hash of that fn call | |
142 | * @chainable | |
143 | */ | |
144 | ||
145 | refresh: function (hash, uuid) { | |
146 | 0 | this._createNonReturnee('refresh')(hash, uuid); |
147 | 0 | return this; |
148 | } | |
149 | }; | |
150 | ||
151 | /** | |
152 | * Mixes in url methods | |
153 | * | |
154 | * @param {Dalek.DriverNative} DalekNative Native driver base class | |
155 | * @return {Dalek.DriverNative} DalekNative Native driver base class | |
156 | */ | |
157 | ||
158 | 1 | module.exports = function (DalekNative) { |
159 | // mixin methods | |
160 | 0 | Object.keys(Url).forEach(function (fn) { |
161 | 0 | DalekNative.prototype[fn] = Url[fn]; |
162 | }); | |
163 | ||
164 | 0 | return DalekNative; |
165 | }; | |
166 |
Line | Hits | Source |
---|---|---|
1 | /*! | |
2 | * | |
3 | * Copyright (c) 2013 Sebastian Golasch | |
4 | * | |
5 | * Permission is hereby granted, free of charge, to any person obtaining a | |
6 | * copy of this software and associated documentation files (the "Software"), | |
7 | * to deal in the Software without restriction, including without limitation | |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
9 | * and/or sell copies of the Software, and to permit persons to whom the | |
10 | * Software is furnished to do so, subject to the following conditions: | |
11 | * | |
12 | * The above copyright notice and this permission notice shall be included | |
13 | * in all copies or substantial portions of the Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
21 | * DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
25 | 1 | 'use strict'; |
26 | ||
27 | // ext. libs | |
28 | 1 | var Q = require('q'); |
29 | ||
30 | /** | |
31 | * Window related methods | |
32 | * | |
33 | * @module Driver | |
34 | * @class Window | |
35 | * @namespace Dalek.DriverNative.Commands | |
36 | */ | |
37 | ||
38 | 1 | var Window = { |
39 | ||
40 | /** | |
41 | * Switches to another window context | |
42 | * | |
43 | * @method toFrame | |
44 | * @param {string} name Name of the window to switch to | |
45 | * @param {string} hash Unique hash of that fn call | |
46 | * @chainable | |
47 | */ | |
48 | ||
49 | toWindow: function (name, hash) { | |
50 | 0 | this.actionQueue.push(this.webdriverClient.windowHandles.bind(this.webdriverClient)); |
51 | 0 | this.actionQueue.push(function (result) { |
52 | 0 | var deferred = Q.defer(); |
53 | 0 | if (name === null) { |
54 | 0 | deferred.resolve(JSON.parse(result).value[0]); |
55 | } | |
56 | 0 | deferred.resolve(name); |
57 | 0 | return deferred.promise; |
58 | }); | |
59 | 0 | this.actionQueue.push(this.webdriverClient.changeWindow.bind(this.webdriverClient)); |
60 | 0 | this.actionQueue.push(this._windowCb.bind(this, name, hash)); |
61 | 0 | return this; |
62 | }, | |
63 | ||
64 | /** | |
65 | * Sends out an event with the results of the `toWindow` call | |
66 | * | |
67 | * @method _windowCb | |
68 | * @param {string} name Name of the window to switch to | |
69 | * @param {string} hash Unique hash of that fn call | |
70 | * @param {string} result Serialized JSON with the reuslts of the toFrame call | |
71 | * @return {object} promise Exists promise | |
72 | * @private | |
73 | */ | |
74 | ||
75 | _windowCb: function (name, hash) { | |
76 | 0 | var deferred = Q.defer(); |
77 | 0 | this.events.emit('driver:message', {key: 'toWindow', name: name, hash: hash, value: true}); |
78 | 0 | deferred.resolve(); |
79 | 0 | return deferred.promise; |
80 | }, | |
81 | ||
82 | /** | |
83 | * Resizes the current window | |
84 | * | |
85 | * @method resize | |
86 | * @param {object} dimensions New window width & height | |
87 | * @param {string} hash Unique hash of that fn call | |
88 | * @chainable | |
89 | */ | |
90 | ||
91 | resize: function (dimensions, hash) { | |
92 | 0 | this.actionQueue.push(this.webdriverClient.setWindowSize.bind(this.webdriverClient, dimensions.width, dimensions.height)); |
93 | 0 | this.actionQueue.push(this._resizeCb.bind(this, dimensions, hash)); |
94 | 0 | return this; |
95 | }, | |
96 | ||
97 | /** | |
98 | * Sends out an event with the results of the `resize` call | |
99 | * | |
100 | * @method _windowCb | |
101 | * @param {object} dimensions New window width & height | |
102 | * @param {string} hash Unique hash of that fn call | |
103 | * @param {string} result Serialized JSON with the reuslts of the toFrame call | |
104 | * @return {object} promise Exists promise | |
105 | * @private | |
106 | */ | |
107 | ||
108 | _resizeCb: function (dimensions, hash) { | |
109 | 0 | var deferred = Q.defer(); |
110 | 0 | this.events.emit('driver:message', {key: 'resize', dimensions: dimensions, hash: hash, value: true}); |
111 | 0 | deferred.resolve(); |
112 | 0 | return deferred.promise; |
113 | }, | |
114 | ||
115 | /** | |
116 | * Maximizes the current window | |
117 | * | |
118 | * @method maximize | |
119 | * @param {string} hash Unique hash of that fn call | |
120 | * @chainable | |
121 | */ | |
122 | ||
123 | maximize: function (hash) { | |
124 | 0 | this.actionQueue.push(this.webdriverClient.maximize.bind(this.webdriverClient)); |
125 | 0 | this.actionQueue.push(this._maximizeCb.bind(this, hash)); |
126 | 0 | return this; |
127 | }, | |
128 | ||
129 | /** | |
130 | * Sends out an event with the results of the `maximize` call | |
131 | * | |
132 | * @method _maximizeCb | |
133 | * @param {string} hash Unique hash of that fn call | |
134 | * @param {string} result Serialized JSON with the reuslts of the toFrame call | |
135 | * @return {object} promise Exists promise | |
136 | * @private | |
137 | */ | |
138 | ||
139 | _maximizeCb: function (hash) { | |
140 | 0 | var deferred = Q.defer(); |
141 | 0 | this.events.emit('driver:message', {key: 'maximize', hash: hash, value: true}); |
142 | 0 | deferred.resolve(); |
143 | 0 | return deferred.promise; |
144 | } | |
145 | ||
146 | }; | |
147 | ||
148 | /** | |
149 | * Mixes in element methods | |
150 | * | |
151 | * @param {Dalek.DriverNative} DalekNative Native driver base class | |
152 | * @return {Dalek.DriverNative} DalekNative Native driver base class | |
153 | */ | |
154 | ||
155 | 1 | module.exports = function (DalekNative) { |
156 | // mixin methods | |
157 | 0 | Object.keys(Window).forEach(function (fn) { |
158 | 0 | DalekNative.prototype[fn] = Window[fn]; |
159 | }); | |
160 | ||
161 | 0 | return DalekNative; |
162 | }; | |
163 |