UNPKG

spectron

Version:

Easily test your Electron apps using ChromeDriver and WebdriverIO.

231 lines (197 loc) 6.87 kB
var Api = require('./api') var ChromeDriver = require('./chrome-driver') var DevNull = require('dev-null') var fs = require('fs') var path = require('path') var WebDriver = require('webdriverio') function Application (options) { options = options || {} this.host = options.host || '127.0.0.1' this.port = parseInt(options.port, 10) || 9515 this.quitTimeout = parseInt(options.quitTimeout, 10) || 1000 this.startTimeout = parseInt(options.startTimeout, 10) || 5000 this.waitTimeout = parseInt(options.waitTimeout, 10) || 5000 this.connectionRetryCount = parseInt(options.connectionRetryCount, 10) || 10 this.connectionRetryTimeout = parseInt(options.connectionRetryTimeout, 10) || 30000 this.nodePath = options.nodePath || process.execPath this.path = options.path this.args = options.args || [] this.env = options.env || {} this.workingDirectory = options.cwd || process.cwd() this.debuggerAddress = options.debuggerAddress this.chromeDriverLogPath = options.chromeDriverLogPath this.api = new Api(this, {requireName: options.requireName}) this.setupPromiseness() } Application.prototype.setupPromiseness = function () { var self = this self.transferPromiseness = function (target, promise) { self.api.transferPromiseness(target, promise) } } Application.prototype.start = function () { var self = this return self.exists() .then(function () { return self.startChromeDriver() }) .then(function () { return self.createClient() }) .then(function () { return self.api.initialize() }) .then(function () { return self.client.timeoutsAsyncScript(self.waitTimeout) }) .then(function () { self.running = true }) .then(function () { return self }) } Application.prototype.stop = function () { var self = this if (!self.isRunning()) return Promise.reject(Error('Application not running')) return new Promise(function (resolve, reject) { var endClient = function () { setTimeout(function () { self.client.end().then(function () { self.chromeDriver.stop() self.running = false resolve(self) }, reject) }, self.quitTimeout) } if (self.api.nodeIntegration) { self.client.windowByIndex(0).electron.remote.app.quit().then(endClient, reject) } else { self.client.windowByIndex(0).execute(function () { window.close() }).then(endClient, reject) } }) } Application.prototype.restart = function () { var self = this return self.stop().then(function () { return self.start() }) } Application.prototype.isRunning = function () { return this.running } Application.prototype.exists = function () { var self = this return new Promise(function (resolve, reject) { // Binary path is ignored by ChromeDriver if debuggerAddress is set if (self.debuggerAddress) return resolve() fs.stat(self.path, function (error, stat) { if (error) return reject(error) if (stat.isFile()) return resolve() reject(Error('Application path specified is not a file: ' + self.path)) }) }) } Application.prototype.startChromeDriver = function () { this.chromeDriver = new ChromeDriver(this.host, this.port, this.nodePath, this.startTimeout, this.workingDirectory, this.chromeDriverLogPath) return this.chromeDriver.start() } Application.prototype.createClient = function () { var self = this return new Promise(function (resolve, reject) { var args = [] args.push('spectron-path=' + self.path) self.args.forEach(function (arg, index) { args.push('spectron-arg' + index + '=' + arg) }) for (var name in self.env) { args.push('spectron-env-' + name + '=' + self.env[name]) } var launcherPath = null if (process.platform === 'win32') { launcherPath = path.join(__dirname, '..', 'bin', 'launcher.exe') } else { launcherPath = path.join(__dirname, 'launcher.js') } if (process.env.APPVEYOR) { args.push('no-sandbox') } var options = { host: self.host, port: self.port, waitforTimeout: self.waitTimeout, connectionRetryCount: self.connectionRetryCount, connectionRetryTimeout: self.connectionRetryTimeout, desiredCapabilities: { browserName: 'electron', chromeOptions: { binary: launcherPath, args: args, debuggerAddress: self.debuggerAddress } }, logOutput: DevNull() } self.client = WebDriver.remote(options) self.addCommands() self.initializeClient(resolve, reject) }) } Application.prototype.initializeClient = function (resolve, reject) { var maxTries = 10 var tries = 0 var self = this var init = function () { tries++ self.client.init().then(resolve, function (error) { if (tries >= maxTries) { error.message = 'Client initialization failed after ' + tries + ' attempts: ' error.message += error.type + ' ' + error.message reject(error) } else { global.setTimeout(init, 250) } }) } init() } Application.prototype.addCommands = function () { this.client.addCommand('waitUntilTextExists', function (selector, text, timeout) { return this.waitUntil(function () { return this.isExisting(selector).getText(selector).then(function (selectorText) { return selectorText.indexOf(text) !== -1 }) }, timeout).then(function () { }, function (error) { error.message = 'waitUntilTextExists ' + error.message return error }) }) this.client.addCommand('waitUntilWindowLoaded', function (timeout) { return this.waitUntil(function () { return this.isWindowLoading().then(function (loading) { return !loading }) }, timeout).then(function () { }, function (error) { error.message = 'waitUntilWindowLoaded ' + error.message return error }) }) this.client.addCommand('getWindowCount', function () { return this.windowHandles().then(getResponseValue).then(function (handles) { return handles.length }) }) this.client.addCommand('windowByIndex', function (index) { return this.windowHandles().then(getResponseValue).then(function (handles) { return this.window(handles[index]) }) }) this.client.addCommand('getSelectedText', function () { return this.execute(function () { return window.getSelection().toString() }).then(getResponseValue) }) this.client.addCommand('getRenderProcessLogs', function () { return this.log('browser').then(getResponseValue) }) var self = this this.client.addCommand('getMainProcessLogs', function () { var logs = self.chromeDriver.getLogs() self.chromeDriver.clearLogs() return logs }) } var getResponseValue = function (response) { return response.value } module.exports = Application