Comparing version 11.0.0 to 11.1.0
@@ -1,1 +0,1 @@ | ||
exports.Application = require('./lib/application') | ||
exports.Application = require('./lib/application'); |
@@ -1,61 +0,72 @@ | ||
var axsPath = require.resolve('../vendor/axs_testing') | ||
const axsPath = require.resolve('../vendor/axs_testing'); | ||
exports.addCommand = function (client, requireName) { | ||
client.addCommand('auditAccessibility', function (options) { | ||
return this.execute(function (axsPath, requireName, options) { | ||
options = options || {} | ||
var ignoreWarnings = options.ignoreWarnings || false | ||
var ignoreRules = Array.isArray(options.ignoreRules) ? options.ignoreRules : [] | ||
return this.execute( | ||
function (axsPath, requireName, options) { | ||
options = options || {}; | ||
const ignoreWarnings = options.ignoreWarnings || false; | ||
const ignoreRules = Array.isArray(options.ignoreRules) | ||
? options.ignoreRules | ||
: []; | ||
var axs = window[requireName](axsPath) | ||
var audit = axs.Audit.run(new axs.AuditConfiguration({ | ||
showUnsupportedRulesWarning: false | ||
})) | ||
const axs = window[requireName](axsPath); | ||
const audit = axs.Audit.run( | ||
new axs.AuditConfiguration({ | ||
showUnsupportedRulesWarning: false | ||
}) | ||
); | ||
var failures = audit.filter(function (result) { | ||
return result.result === 'FAIL' | ||
}) | ||
let failures = audit.filter(function (result) { | ||
return result.result === 'FAIL'; | ||
}); | ||
if (ignoreWarnings) { | ||
if (ignoreWarnings) { | ||
failures = failures.filter(function (result) { | ||
return result.rule.severity !== 'Warning'; | ||
}); | ||
} | ||
failures = failures.filter(function (result) { | ||
return result.rule.severity !== 'Warning' | ||
}) | ||
} | ||
return ignoreRules.indexOf(result.rule.code) === -1; | ||
}); | ||
failures = failures.filter(function (result) { | ||
return ignoreRules.indexOf(result.rule.code) === -1 | ||
}) | ||
if (failures.length > 0) { | ||
let message = 'Accessibilty audit failed\n\n'; | ||
message += failures | ||
.map(function (result) { | ||
return axs.Audit.accessibilityErrorMessage(result); | ||
}) | ||
.join('\n\n'); | ||
if (failures.length > 0) { | ||
var message = 'Accessibilty audit failed\n\n' | ||
message += failures.map(function (result) { | ||
return axs.Audit.accessibilityErrorMessage(result) | ||
}).join('\n\n') | ||
return { | ||
message: message, | ||
failed: true, | ||
results: failures.map(function (result) { | ||
return { | ||
code: result.rule.code, | ||
elements: result.elements.map(function (element) { | ||
return axs.utils.getQuerySelectorText(element) | ||
}), | ||
message: result.rule.heading, | ||
severity: result.rule.severity, | ||
url: result.rule.url | ||
} | ||
}) | ||
return { | ||
message: message, | ||
failed: true, | ||
results: failures.map(function (result) { | ||
return { | ||
code: result.rule.code, | ||
elements: result.elements.map(function (element) { | ||
return axs.utils.getQuerySelectorText(element); | ||
}), | ||
message: result.rule.heading, | ||
severity: result.rule.severity, | ||
url: result.rule.url | ||
}; | ||
}) | ||
}; | ||
} else { | ||
return { | ||
message: 'Accessibilty audit passed', | ||
results: [], | ||
failed: false | ||
}; | ||
} | ||
} else { | ||
return { | ||
message: 'Accessibilty audit passed', | ||
results: [], | ||
failed: false | ||
} | ||
} | ||
}, axsPath, requireName, options).then(function (response) { | ||
return response.value | ||
}) | ||
}) | ||
} | ||
}, | ||
axsPath, | ||
requireName, | ||
options | ||
).then(function (response) { | ||
return response; | ||
}); | ||
}); | ||
}; |
663
lib/api.js
@@ -1,20 +0,21 @@ | ||
var apiCache = {} | ||
const apiCache = {}; | ||
function Api (app, requireName) { | ||
this.app = app | ||
this.requireName = requireName | ||
function Api(app, requireName) { | ||
this.app = app; | ||
this.requireName = requireName; | ||
} | ||
Api.prototype.initialize = function () { | ||
return this.load().then(this.addApiCommands.bind(this)) | ||
} | ||
const self = this; | ||
return self.load().then(self.addApiCommands.bind(self)); | ||
}; | ||
Api.prototype.addApiCommands = function (api) { | ||
if (!this.nodeIntegration) return | ||
if (!this.nodeIntegration) return; | ||
this.addRenderProcessApis(api.electron) | ||
this.addMainProcessApis(api.electron.remote) | ||
this.addBrowserWindowApis(api.browserWindow) | ||
this.addWebContentsApis(api.webContents) | ||
this.addProcessApis(api.rendererProcess) | ||
this.addRenderProcessApis(api.electron); | ||
this.addMainProcessApis(api.electron.remote); | ||
this.addBrowserWindowApis(api.browserWindow); | ||
this.addWebContentsApis(api.webContents); | ||
this.addProcessApis(api.rendererProcess); | ||
@@ -26,11 +27,12 @@ this.api = { | ||
webContents: api.webContents | ||
} | ||
}; | ||
this.addClientProperties() | ||
} | ||
this.addClientProperties(); | ||
}; | ||
Api.prototype.load = function () { | ||
var self = this | ||
const self = this; | ||
return this.isNodeIntegrationEnabled().then(function (nodeIntegration) { | ||
self.nodeIntegration = nodeIntegration | ||
self.nodeIntegration = nodeIntegration; | ||
if (!nodeIntegration) { | ||
@@ -42,31 +44,32 @@ return { | ||
rendererProcess: {} | ||
} | ||
}; | ||
} | ||
return self.getVersion().then(function (version) { | ||
var api = apiCache[version] | ||
if (api) return api | ||
const api = apiCache[version]; | ||
if (api) return api; | ||
return self.loadApi().then(function (api) { | ||
if (version) apiCache[version] = api | ||
return api | ||
}) | ||
}) | ||
}) | ||
} | ||
if (version) apiCache[version] = api; | ||
return api; | ||
}); | ||
}); | ||
}); | ||
}; | ||
Api.prototype.isNodeIntegrationEnabled = function () { | ||
return this.app.client.execute(function (requireName) { | ||
return typeof window[requireName] === 'function' | ||
}, this.requireName).then(getResponseValue) | ||
} | ||
const self = this; | ||
return self.app.client.execute(function (requireName) { | ||
return typeof window[requireName] === 'function'; | ||
}, self.requireName); | ||
}; | ||
Api.prototype.getVersion = function () { | ||
return this.app.client.execute(function (requireName) { | ||
var process = window[requireName]('process') | ||
const process = window[requireName]('process'); | ||
if (process != null && process.versions != null) { | ||
return process.versions.electron | ||
return process.versions.electron; | ||
} | ||
}, this.requireName).then(getResponseValue) | ||
} | ||
}, this.requireName); | ||
}; | ||
@@ -76,8 +79,10 @@ Api.prototype.loadApi = function () { | ||
if (typeof window[requireName] !== 'function') { | ||
throw new Error('Could not find global require method with name: ' + requireName) | ||
throw new Error( | ||
'Could not find global require method with name: ' + requireName | ||
); | ||
} | ||
var electron = window[requireName]('electron') | ||
var process = window[requireName]('process') | ||
const electron = window[requireName]('electron'); | ||
const process = window[requireName]('process'); | ||
var api = { | ||
const api = { | ||
browserWindow: {}, | ||
@@ -87,5 +92,5 @@ electron: {}, | ||
webContents: {} | ||
} | ||
}; | ||
function ignoreModule (moduleName) { | ||
function ignoreModule(moduleName) { | ||
switch (moduleName) { | ||
@@ -97,10 +102,10 @@ case 'CallbacksRegistry': | ||
case 'Tray': | ||
return true | ||
return true; | ||
case 'inAppPurchase': | ||
return process.platform !== 'darwin' | ||
return process.platform !== 'darwin'; | ||
} | ||
return false | ||
return false; | ||
} | ||
function isRemoteFunction (name) { | ||
function isRemoteFunction(name) { | ||
switch (name) { | ||
@@ -110,52 +115,62 @@ case 'BrowserWindow': | ||
case 'MenuItem': | ||
return false | ||
return false; | ||
} | ||
return typeof electron.remote[name] === 'function' | ||
return typeof electron.remote[name] === 'function'; | ||
} | ||
function ignoreApi (apiName) { | ||
function ignoreApi(apiName) { | ||
switch (apiName) { | ||
case 'prototype': | ||
return true | ||
return true; | ||
default: | ||
return apiName[0] === '_' | ||
return apiName[0] === '_'; | ||
} | ||
} | ||
function addModule (parent, parentName, name, api) { | ||
api[name] = {} | ||
for (var key in parent[name]) { | ||
if (ignoreApi(key)) continue | ||
api[name][key] = parentName + '.' + name + '.' + key | ||
function addModule(parent, parentName, name, api) { | ||
api[name] = {}; | ||
for (const key in parent[name]) { | ||
if (ignoreApi(key)) continue; | ||
api[name][key] = parentName + '.' + name + '.' + key; | ||
} | ||
} | ||
function addRenderProcessModules () { | ||
function addRenderProcessModules() { | ||
Object.getOwnPropertyNames(electron).forEach(function (key) { | ||
if (ignoreModule(key)) return | ||
if (key === 'remote') return | ||
addModule(electron, 'electron', key, api.electron) | ||
}) | ||
if (ignoreModule(key)) return; | ||
if (key === 'remote') return; | ||
addModule(electron, 'electron', key, api.electron); | ||
}); | ||
} | ||
function addMainProcessModules () { | ||
api.electron.remote = {} | ||
function addMainProcessModules() { | ||
api.electron.remote = {}; | ||
Object.getOwnPropertyNames(electron.remote).forEach(function (key) { | ||
if (ignoreModule(key)) return | ||
if (ignoreModule(key)) return; | ||
if (isRemoteFunction(key)) { | ||
api.electron.remote[key] = 'electron.remote.' + key | ||
api.electron.remote[key] = 'electron.remote.' + key; | ||
} else { | ||
addModule(electron.remote, 'electron.remote', key, api.electron.remote) | ||
addModule( | ||
electron.remote, | ||
'electron.remote', | ||
key, | ||
api.electron.remote | ||
); | ||
} | ||
}) | ||
addModule(electron.remote, 'electron.remote', 'process', api.electron.remote) | ||
}); | ||
addModule( | ||
electron.remote, | ||
'electron.remote', | ||
'process', | ||
api.electron.remote | ||
); | ||
} | ||
function addBrowserWindow () { | ||
var currentWindow = electron.remote.getCurrentWindow() | ||
for (var name in currentWindow) { | ||
if (ignoreApi(name)) continue | ||
var value = currentWindow[name] | ||
function addBrowserWindow() { | ||
const currentWindow = electron.remote.getCurrentWindow(); | ||
for (const name in currentWindow) { | ||
if (ignoreApi(name)) continue; | ||
const value = currentWindow[name]; | ||
if (typeof value === 'function') { | ||
api.browserWindow[name] = 'browserWindow.' + name | ||
api.browserWindow[name] = 'browserWindow.' + name; | ||
} | ||
@@ -165,9 +180,9 @@ } | ||
function addWebContents () { | ||
var webContents = electron.remote.getCurrentWebContents() | ||
for (var name in webContents) { | ||
if (ignoreApi(name)) continue | ||
var value = webContents[name] | ||
function addWebContents() { | ||
const webContents = electron.remote.getCurrentWebContents(); | ||
for (const name in webContents) { | ||
if (ignoreApi(name)) continue; | ||
const value = webContents[name]; | ||
if (typeof value === 'function') { | ||
api.webContents[name] = 'webContents.' + name | ||
api.webContents[name] = 'webContents.' + name; | ||
} | ||
@@ -177,172 +192,199 @@ } | ||
function addProcess () { | ||
if (typeof process !== 'object') return | ||
function addProcess() { | ||
if (typeof process !== 'object') return; | ||
for (var name in process) { | ||
if (ignoreApi(name)) continue | ||
api.rendererProcess[name] = 'process.' + name | ||
for (const name in process) { | ||
if (ignoreApi(name)) continue; | ||
api.rendererProcess[name] = 'process.' + name; | ||
} | ||
} | ||
addRenderProcessModules() | ||
addMainProcessModules() | ||
addBrowserWindow() | ||
addWebContents() | ||
addProcess() | ||
addRenderProcessModules(); | ||
addMainProcessModules(); | ||
addBrowserWindow(); | ||
addWebContents(); | ||
addProcess(); | ||
return api | ||
}, this.requireName).then(getResponseValue) | ||
} | ||
return api; | ||
}, this.requireName); | ||
}; | ||
Api.prototype.addClientProperty = function (name) { | ||
var self = this | ||
const self = this; | ||
var clientPrototype = Object.getPrototypeOf(self.app.client) | ||
const clientPrototype = Object.getPrototypeOf(self.app.client); | ||
Object.defineProperty(clientPrototype, name, { | ||
get: function () { | ||
var client = this | ||
const client = this; | ||
return transformObject(self.api[name], {}, function (value) { | ||
return client[value].bind(client) | ||
}) | ||
return client[value].bind(client); | ||
}); | ||
} | ||
}) | ||
} | ||
}); | ||
}; | ||
Api.prototype.addClientProperties = function () { | ||
this.addClientProperty('electron') | ||
this.addClientProperty('browserWindow') | ||
this.addClientProperty('webContents') | ||
this.addClientProperty('rendererProcess') | ||
this.addClientProperty('electron'); | ||
this.addClientProperty('browserWindow'); | ||
this.addClientProperty('webContents'); | ||
this.addClientProperty('rendererProcess'); | ||
Object.defineProperty(Object.getPrototypeOf(this.app.client), 'mainProcess', { | ||
get: function () { | ||
return this.electron.remote.process | ||
return this.electron.remote.process; | ||
} | ||
}) | ||
} | ||
}); | ||
}; | ||
Api.prototype.addRenderProcessApis = function (api) { | ||
var app = this.app | ||
var self = this | ||
var electron = {} | ||
app.electron = electron | ||
const app = this.app; | ||
const self = this; | ||
const electron = {}; | ||
app.electron = electron; | ||
Object.keys(api).forEach(function (moduleName) { | ||
if (moduleName === 'remote') return | ||
electron[moduleName] = {} | ||
var moduleApi = api[moduleName] | ||
if (moduleName === 'remote') return; | ||
electron[moduleName] = {}; | ||
const moduleApi = api[moduleName]; | ||
Object.keys(moduleApi).forEach(function (key) { | ||
var commandName = moduleApi[key] | ||
const commandName = moduleApi[key]; | ||
app.client.addCommand(commandName, function () { | ||
var args = Array.prototype.slice.call(arguments) | ||
return this.execute(callRenderApi, moduleName, key, args, self.requireName).then(getResponseValue) | ||
}) | ||
const args = Array.prototype.slice.call(arguments); | ||
return this.execute( | ||
callRenderApi, | ||
moduleName, | ||
key, | ||
args, | ||
self.requireName | ||
); | ||
}); | ||
electron[moduleName][key] = function () { | ||
return app.client[commandName].apply(app.client, arguments) | ||
} | ||
}) | ||
}) | ||
} | ||
return app.client[commandName].apply(app.client, arguments); | ||
}; | ||
}); | ||
}); | ||
}; | ||
Api.prototype.addMainProcessApis = function (api) { | ||
var app = this.app | ||
var self = this | ||
var remote = {} | ||
app.electron.remote = remote | ||
const app = this.app; | ||
const self = this; | ||
const remote = {}; | ||
app.electron.remote = remote; | ||
Object.keys(api).filter(function (propertyName) { | ||
return typeof api[propertyName] === 'string' | ||
}).forEach(function (name) { | ||
var commandName = api[name] | ||
app.client.addCommand(commandName, function () { | ||
var args = Array.prototype.slice.call(arguments) | ||
return this.execute(callMainApi, null, name, args, self.requireName).then(getResponseValue) | ||
Object.keys(api) | ||
.filter(function (propertyName) { | ||
return typeof api[propertyName] === 'string'; | ||
}) | ||
.forEach(function (name) { | ||
const commandName = api[name]; | ||
remote[name] = function () { | ||
return app.client[commandName].apply(app.client, arguments) | ||
} | ||
}) | ||
app.client.addCommand(commandName, function () { | ||
const args = Array.prototype.slice.call(arguments); | ||
return this.execute(callMainApi, '', name, args, self.requireName); | ||
}); | ||
Object.keys(api).filter(function (moduleName) { | ||
return typeof api[moduleName] === 'object' | ||
}).forEach(function (moduleName) { | ||
remote[moduleName] = {} | ||
var moduleApi = api[moduleName] | ||
remote[name] = function () { | ||
return app.client[commandName].apply(app.client, arguments); | ||
}; | ||
}); | ||
Object.keys(moduleApi).forEach(function (key) { | ||
var commandName = moduleApi[key] | ||
Object.keys(api) | ||
.filter(function (moduleName) { | ||
return typeof api[moduleName] === 'object'; | ||
}) | ||
.forEach(function (moduleName) { | ||
remote[moduleName] = {}; | ||
const moduleApi = api[moduleName]; | ||
app.client.addCommand(commandName, function () { | ||
var args = Array.prototype.slice.call(arguments) | ||
return this.execute(callMainApi, moduleName, key, args, self.requireName).then(getResponseValue) | ||
}) | ||
Object.keys(moduleApi).forEach(function (key) { | ||
const commandName = moduleApi[key]; | ||
remote[moduleName][key] = function () { | ||
return app.client[commandName].apply(app.client, arguments) | ||
} | ||
}) | ||
}) | ||
} | ||
app.client.addCommand(commandName, function () { | ||
const args = Array.prototype.slice.call(arguments); | ||
return this.execute( | ||
callMainApi, | ||
moduleName, | ||
key, | ||
args, | ||
self.requireName | ||
); | ||
}); | ||
remote[moduleName][key] = function () { | ||
return app.client[commandName].apply(app.client, arguments); | ||
}; | ||
}); | ||
}); | ||
}; | ||
Api.prototype.addBrowserWindowApis = function (api) { | ||
var app = this.app | ||
var self = this | ||
app.browserWindow = {} | ||
const app = this.app; | ||
const self = this; | ||
app.browserWindow = {}; | ||
const asyncApis = { | ||
'browserWindow.capturePage': true | ||
} | ||
}; | ||
Object.keys(api).filter(function (name) { | ||
return !asyncApis.hasOwnProperty(api[name]) | ||
}).forEach(function (name) { | ||
var commandName = api[name] | ||
app.client.addCommand(commandName, function () { | ||
var args = Array.prototype.slice.call(arguments) | ||
return this.execute(callBrowserWindowApi, name, args, self.requireName).then(getResponseValue) | ||
Object.keys(api) | ||
.filter(function (name) { | ||
return !Object.prototype.hasOwnProperty.call(asyncApis, api[name]); | ||
}) | ||
.forEach(function (name) { | ||
const commandName = api[name]; | ||
app.browserWindow[name] = function () { | ||
return app.client[commandName].apply(app.client, arguments) | ||
} | ||
}) | ||
app.client.addCommand(commandName, function () { | ||
const args = Array.prototype.slice.call(arguments); | ||
return this.execute(callBrowserWindowApi, name, args, self.requireName); | ||
}); | ||
this.addCapturePageSupport() | ||
} | ||
app.browserWindow[name] = function () { | ||
return app.client[commandName].apply(app.client, arguments); | ||
}; | ||
}); | ||
this.addCapturePageSupport(); | ||
}; | ||
Api.prototype.addCapturePageSupport = function () { | ||
var app = this.app | ||
var self = this | ||
const app = this.app; | ||
const self = this; | ||
app.client.addCommand('browserWindow.capturePage', function (rect) { | ||
return this.executeAsync(async function (rect, requireName, done) { | ||
var args = [] | ||
if (rect != null) args.push(rect) | ||
var browserWindow = window[requireName]('electron').remote.getCurrentWindow() | ||
const image = await browserWindow.capturePage.apply(browserWindow, args) | ||
if (image != null) { | ||
done(image.toPNG().toString('base64')) | ||
} else { | ||
done(image) | ||
} | ||
}, rect, self.requireName).then(getResponseValue).then(function (image) { | ||
return Buffer.from(image, 'base64') | ||
}) | ||
}) | ||
return this.executeAsync( | ||
async function (rect, requireName, done) { | ||
const args = []; | ||
if (rect != null) args.push(rect); | ||
const browserWindow = window[requireName]( | ||
'electron' | ||
).remote.getCurrentWindow(); | ||
const image = await browserWindow.capturePage.apply( | ||
browserWindow, | ||
args | ||
); | ||
if (image != null) { | ||
done(image.toPNG().toString('base64')); | ||
} else { | ||
done(image); | ||
} | ||
}, | ||
rect, | ||
self.requireName | ||
).then(function (image) { | ||
return Buffer.from(image, 'base64'); | ||
}); | ||
}); | ||
app.browserWindow.capturePage = function () { | ||
return app.client['browserWindow.capturePage'].apply(app.client, arguments) | ||
} | ||
} | ||
return app.client['browserWindow.capturePage'].apply(app.client, arguments); | ||
}; | ||
}; | ||
Api.prototype.addWebContentsApis = function (api) { | ||
var app = this.app | ||
var self = this | ||
app.webContents = {} | ||
const app = this.app; | ||
const self = this; | ||
app.webContents = {}; | ||
@@ -352,166 +394,189 @@ const asyncApis = { | ||
'webContents.executeJavaScript': true | ||
} | ||
}; | ||
Object.keys(api).filter(function (name) { | ||
return !asyncApis.hasOwnProperty(api[name]) | ||
}).forEach(function (name) { | ||
var commandName = api[name] | ||
app.client.addCommand(commandName, function () { | ||
var args = Array.prototype.slice.call(arguments) | ||
return this.execute(callWebContentsApi, name, args, self.requireName).then(getResponseValue) | ||
Object.keys(api) | ||
.filter(function (name) { | ||
return !Object.prototype.hasOwnProperty.call(asyncApis, api[name]); | ||
}) | ||
.forEach(function (name) { | ||
const commandName = api[name]; | ||
app.webContents[name] = function () { | ||
return app.client[commandName].apply(app.client, arguments) | ||
} | ||
}) | ||
app.client.addCommand(commandName, function () { | ||
const args = Array.prototype.slice.call(arguments); | ||
return this.execute(callWebContentsApi, name, args, self.requireName); | ||
}); | ||
this.addSavePageSupport() | ||
this.addExecuteJavaScriptSupport() | ||
} | ||
app.webContents[name] = function () { | ||
return app.client[commandName].apply(app.client, arguments); | ||
}; | ||
}); | ||
this.addSavePageSupport(); | ||
this.addExecuteJavaScriptSupport(); | ||
}; | ||
Api.prototype.addSavePageSupport = function () { | ||
var app = this.app | ||
var self = this | ||
const app = this.app; | ||
const self = this; | ||
app.client.addCommand('webContents.savePage', function (fullPath, saveType) { | ||
return this.executeAsync(async function (fullPath, saveType, requireName, done) { | ||
var webContents = window[requireName]('electron').remote.getCurrentWebContents() | ||
await webContents.savePage(fullPath, saveType) | ||
done() | ||
}, fullPath, saveType, self.requireName).then(getResponseValue).then(function (rawError) { | ||
return this.executeAsync( | ||
async function (fullPath, saveType, requireName, done) { | ||
const webContents = window[requireName]( | ||
'electron' | ||
).remote.getCurrentWebContents(); | ||
await webContents.savePage(fullPath, saveType); | ||
done(); | ||
}, | ||
fullPath, | ||
saveType, | ||
self.requireName | ||
).then(function (rawError) { | ||
if (rawError) { | ||
var error = new Error(rawError.message) | ||
if (rawError.name) error.name = rawError.name | ||
throw error | ||
const error = new Error(rawError.message); | ||
if (rawError.name) error.name = rawError.name; | ||
throw error; | ||
} | ||
}) | ||
}) | ||
}); | ||
}); | ||
app.webContents.savePage = function () { | ||
return app.client['webContents.savePage'].apply(app.client, arguments) | ||
} | ||
} | ||
return app.client['webContents.savePage'].apply(app.client, arguments); | ||
}; | ||
}; | ||
Api.prototype.addExecuteJavaScriptSupport = function () { | ||
const app = this.app | ||
const self = this | ||
const app = this.app; | ||
const self = this; | ||
app.client.addCommand('webContents.executeJavaScript', function (code, useGesture) { | ||
return this.executeAsync(async function (code, useGesture, requireName, done) { | ||
const webContents = window[requireName]('electron').remote.getCurrentWebContents() | ||
const result = await webContents.executeJavaScript(code, useGesture) | ||
done(result) | ||
}, code, useGesture, self.requireName).then(getResponseValue) | ||
}) | ||
app.client.addCommand('webContents.executeJavaScript', function ( | ||
code, | ||
useGesture | ||
) { | ||
return this.executeAsync( | ||
async function (code, useGesture, requireName, done) { | ||
const webContents = window[requireName]( | ||
'electron' | ||
).remote.getCurrentWebContents(); | ||
const result = await webContents.executeJavaScript(code, useGesture); | ||
done(result); | ||
}, | ||
code, | ||
useGesture, | ||
self.requireName | ||
); | ||
}); | ||
app.webContents.executeJavaScript = function () { | ||
return app.client['webContents.executeJavaScript'].apply(app.client, arguments) | ||
} | ||
} | ||
return app.client['webContents.executeJavaScript'].apply( | ||
app.client, | ||
arguments | ||
); | ||
}; | ||
}; | ||
Api.prototype.addProcessApis = function (api) { | ||
var app = this.app | ||
app.rendererProcess = {} | ||
const app = this.app; | ||
app.rendererProcess = {}; | ||
Object.keys(api).forEach(function (name) { | ||
var commandName = api[name] | ||
const commandName = api[name]; | ||
app.client.addCommand(commandName, function () { | ||
var args = Array.prototype.slice.call(arguments) | ||
return this.execute(callProcessApi, name, args).then(getResponseValue) | ||
}) | ||
const args = Array.prototype.slice.call(arguments); | ||
return this.execute(callProcessApi, name, args); | ||
}); | ||
app.rendererProcess[name] = function () { | ||
return app.client[commandName].apply(app.client, arguments) | ||
} | ||
}) | ||
return app.client[commandName].apply(app.client, arguments); | ||
}; | ||
}); | ||
app.mainProcess = app.electron.remote.process | ||
} | ||
app.mainProcess = app.electron.remote.process; | ||
}; | ||
Api.prototype.transferPromiseness = function (target, promise) { | ||
this.app.client.transferPromiseness(target, promise) | ||
if (!this.nodeIntegration) return; | ||
if (!this.nodeIntegration) return | ||
const addProperties = function (source, target, moduleName) { | ||
const sourceModule = source[moduleName]; | ||
if (!sourceModule) return; | ||
target[moduleName] = transformObject(sourceModule, {}, function ( | ||
value, | ||
parent | ||
) { | ||
return value.bind(parent); | ||
}); | ||
}; | ||
var addProperties = function (source, target, moduleName) { | ||
var sourceModule = source[moduleName] | ||
if (!sourceModule) return | ||
target[moduleName] = transformObject(sourceModule, {}, function (value, parent) { | ||
return value.bind(parent) | ||
}) | ||
} | ||
addProperties(promise, target, 'webContents'); | ||
addProperties(promise, target, 'browserWindow'); | ||
addProperties(promise, target, 'electron'); | ||
addProperties(promise, target, 'mainProcess'); | ||
addProperties(promise, target, 'rendererProcess'); | ||
}; | ||
addProperties(promise, target, 'webContents') | ||
addProperties(promise, target, 'browserWindow') | ||
addProperties(promise, target, 'electron') | ||
addProperties(promise, target, 'mainProcess') | ||
addProperties(promise, target, 'rendererProcess') | ||
} | ||
Api.prototype.logApi = function () { | ||
var fs = require('fs') | ||
var path = require('path') | ||
var json = JSON.stringify(this.api, null, 2) | ||
fs.writeFileSync(path.join(__dirname, 'api.json'), json) | ||
} | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const json = JSON.stringify(this.api, null, 2); | ||
fs.writeFileSync(path.join(__dirname, 'api.json'), json); | ||
}; | ||
function transformObject (input, output, callback) { | ||
function transformObject(input, output, callback) { | ||
Object.keys(input).forEach(function (name) { | ||
var value = input[name] | ||
const value = input[name]; | ||
if (typeof value === 'object') { | ||
output[name] = {} | ||
transformObject(value, output[name], callback) | ||
output[name] = {}; | ||
transformObject(value, output[name], callback); | ||
} else { | ||
output[name] = callback(value, input) | ||
output[name] = callback(value, input); | ||
} | ||
}) | ||
return output | ||
}); | ||
return output; | ||
} | ||
function callRenderApi (moduleName, api, args, requireName) { | ||
var module = window[requireName]('electron')[moduleName] | ||
function callRenderApi(moduleName, api, args, requireName) { | ||
const module = window[requireName]('electron')[moduleName]; | ||
if (typeof module[api] === 'function') { | ||
return module[api].apply(module, args) | ||
return module[api].apply(module, args); | ||
} else { | ||
return module[api] | ||
return module[api]; | ||
} | ||
} | ||
function callMainApi (moduleName, api, args, requireName) { | ||
var module = window[requireName]('electron').remote | ||
function callMainApi(moduleName, api, args, requireName) { | ||
let module = window[requireName]('electron').remote; | ||
if (moduleName) { | ||
module = module[moduleName] | ||
module = module[moduleName]; | ||
} | ||
if (typeof module[api] === 'function') { | ||
return module[api].apply(module, args) | ||
return module[api].apply(module, args); | ||
} else { | ||
return module[api] | ||
return module[api]; | ||
} | ||
} | ||
function callWebContentsApi (name, args, requireName) { | ||
var webContents = window[requireName]('electron').remote.getCurrentWebContents() | ||
return webContents[name].apply(webContents, args) | ||
function callWebContentsApi(name, args, requireName) { | ||
const webContents = window[requireName]( | ||
'electron' | ||
).remote.getCurrentWebContents(); | ||
return webContents[name].apply(webContents, args); | ||
} | ||
function callBrowserWindowApi (name, args, requireName) { | ||
var browserWindow = window[requireName]('electron').remote.getCurrentWindow() | ||
return browserWindow[name].apply(browserWindow, args) | ||
function callBrowserWindowApi(name, args, requireName) { | ||
const browserWindow = window[requireName]( | ||
'electron' | ||
).remote.getCurrentWindow(); | ||
return browserWindow[name].apply(browserWindow, args); | ||
} | ||
function callProcessApi (name, args) { | ||
function callProcessApi(name, args) { | ||
if (typeof process[name] === 'function') { | ||
return process[name].apply(process, args) | ||
return process[name].apply(process, args); | ||
} else { | ||
return process[name] | ||
return process[name]; | ||
} | ||
} | ||
function getResponseValue (response) { | ||
return response.value | ||
} | ||
module.exports = Api | ||
module.exports = Api; |
@@ -1,92 +0,113 @@ | ||
var Accessibility = require('./accessibility') | ||
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') | ||
const Accessibility = require('./accessibility'); | ||
const Api = require('./api'); | ||
const ChromeDriver = require('./chrome-driver'); | ||
const DevNull = require('dev-null'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const WebDriver = require('webdriverio'); | ||
function Application (options) { | ||
options = options || {} | ||
this.host = options.host || '127.0.0.1' | ||
this.port = parseInt(options.port, 10) || 9515 | ||
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.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.connectionRetryCount = parseInt(options.connectionRetryCount, 10) || 10; | ||
this.connectionRetryTimeout = | ||
parseInt(options.connectionRetryTimeout, 10) || 30000; | ||
this.nodePath = options.nodePath || process.execPath | ||
this.path = options.path | ||
this.nodePath = options.nodePath || process.execPath; | ||
this.path = options.path; | ||
this.args = options.args || [] | ||
this.chromeDriverArgs = options.chromeDriverArgs || [] | ||
this.env = options.env || {} | ||
this.workingDirectory = options.cwd || process.cwd() | ||
this.debuggerAddress = options.debuggerAddress | ||
this.chromeDriverLogPath = options.chromeDriverLogPath | ||
this.webdriverLogPath = options.webdriverLogPath | ||
this.webdriverOptions = options.webdriverOptions || {} | ||
this.requireName = options.requireName || 'require' | ||
this.args = options.args || []; | ||
this.chromeDriverArgs = options.chromeDriverArgs || []; | ||
this.env = options.env || {}; | ||
this.workingDirectory = options.cwd || process.cwd(); | ||
this.debuggerAddress = options.debuggerAddress; | ||
this.chromeDriverLogPath = options.chromeDriverLogPath; | ||
this.webdriverLogPath = options.webdriverLogPath; | ||
this.webdriverOptions = options.webdriverOptions || {}; | ||
this.requireName = options.requireName || 'require'; | ||
this.api = new Api(this, this.requireName) | ||
this.setupPromiseness() | ||
this.api = new Api(this, this.requireName); | ||
this.setupPromiseness(); | ||
} | ||
Application.prototype.setupPromiseness = function () { | ||
var self = this | ||
const self = this; | ||
self.transferPromiseness = function (target, promise) { | ||
self.api.transferPromiseness(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.timeouts('script', self.waitTimeout) }) | ||
.then(function () { self.running = true }) | ||
.then(function () { return self }) | ||
} | ||
const 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.setTimeouts( | ||
self.waitTimeout, | ||
self.waitTimeout, | ||
self.waitTimeout | ||
); | ||
}) | ||
.then(function () { | ||
self.running = true; | ||
}) | ||
.then(function () { | ||
return self; | ||
}); | ||
}; | ||
Application.prototype.stop = function () { | ||
var self = this | ||
const self = this; | ||
if (!self.isRunning()) return Promise.reject(Error('Application not running')) | ||
if (!self.isRunning()) { | ||
return Promise.reject(Error('Application not running')); | ||
} | ||
return new Promise(function (resolve, reject) { | ||
var endClient = function () { | ||
const endClient = function () { | ||
setTimeout(function () { | ||
self.client.end().then(function () { | ||
self.chromeDriver.stop() | ||
self.running = false | ||
resolve(self) | ||
}, reject) | ||
}, self.quitTimeout) | ||
} | ||
self.chromeDriver.stop(); | ||
self.running = false; | ||
resolve(self); | ||
}, self.quitTimeout); | ||
}; | ||
if (self.api.nodeIntegration) { | ||
self.client.windowByIndex(0).electron.remote.app.quit().then(endClient, reject) | ||
self.client.electron.remote.app.quit().then(endClient, reject); | ||
} else { | ||
self.client.windowByIndex(0).execute(function () { | ||
window.close() | ||
}).then(endClient, reject) | ||
self.client | ||
.windowByIndex(0) | ||
.then(function () { | ||
self.client.closeWindow(); | ||
}) | ||
.then(endClient, reject); | ||
} | ||
}) | ||
} | ||
}); | ||
}; | ||
Application.prototype.restart = function () { | ||
var self = this | ||
const self = this; | ||
return self.stop().then(function () { | ||
return self.start() | ||
}) | ||
} | ||
return self.start(); | ||
}); | ||
}; | ||
Application.prototype.isRunning = function () { | ||
return this.running | ||
} | ||
return this.running; | ||
}; | ||
@@ -113,54 +134,66 @@ Application.prototype.getSettings = function () { | ||
requireName: this.requireName | ||
} | ||
} | ||
}; | ||
}; | ||
Application.prototype.exists = function () { | ||
var self = this | ||
const self = this; | ||
return new Promise(function (resolve, reject) { | ||
// Binary path is ignored by ChromeDriver if debuggerAddress is set | ||
if (self.debuggerAddress) return resolve() | ||
if (self.debuggerAddress) return resolve(); | ||
if (typeof self.path !== 'string') { | ||
return reject(Error('Application path must be a string')) | ||
return reject(Error('Application path must be a string')); | ||
} | ||
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)) | ||
}) | ||
}) | ||
} | ||
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() | ||
} | ||
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 | ||
const self = this; | ||
return new Promise(function (resolve, reject) { | ||
var args = [] | ||
args.push('spectron-path=' + self.path) | ||
const args = []; | ||
args.push('spectron-path=' + self.path); | ||
self.args.forEach(function (arg, index) { | ||
args.push('spectron-arg' + index + '=' + arg) | ||
}) | ||
args.push('spectron-arg' + index + '=' + arg); | ||
}); | ||
for (var name in self.env) { | ||
args.push('spectron-env-' + name + '=' + self.env[name]) | ||
for (const name in self.env) { | ||
if (Object.prototype.hasOwnProperty.call(self.env, name)) { | ||
args.push('spectron-env-' + name + '=' + self.env[name]); | ||
} | ||
} | ||
self.chromeDriverArgs.forEach(function (arg) { | ||
args.push(arg) | ||
}) | ||
args.push(arg); | ||
}); | ||
var isWin = process.platform === 'win32' | ||
var launcherPath = path.join(__dirname, isWin ? 'launcher.bat' : 'launcher.js') | ||
const isWin = process.platform === 'win32'; | ||
const launcherPath = path.join( | ||
__dirname, | ||
isWin ? 'launcher.bat' : 'launcher.js' | ||
); | ||
if (process.env.APPVEYOR) { | ||
args.push('no-sandbox') | ||
args.push('no-sandbox'); | ||
} | ||
var options = { | ||
host: self.host, | ||
const options = { | ||
hostname: self.host, | ||
port: self.port, | ||
@@ -170,5 +203,5 @@ waitforTimeout: self.waitTimeout, | ||
connectionRetryTimeout: self.connectionRetryTimeout, | ||
desiredCapabilities: { | ||
browserName: 'electron', | ||
chromeOptions: { | ||
logLevel: 'silent', | ||
capabilities: { | ||
'goog:chromeOptions': { | ||
binary: launcherPath, | ||
@@ -181,132 +214,98 @@ args: args, | ||
logOutput: DevNull() | ||
} | ||
}; | ||
if (self.webdriverLogPath) { | ||
options.logOutput = self.webdriverLogPath | ||
options.logLevel = 'verbose' | ||
options.outputDir = self.webdriverLogPath; | ||
options.logLevel = 'trace'; | ||
} | ||
Object.assign(options, self.webdriverOptions) | ||
Object.assign(options, self.webdriverOptions); | ||
self.client = WebDriver.remote(options) | ||
self.addCommands() | ||
self.initializeClient(resolve, reject) | ||
}) | ||
} | ||
self.client = WebDriver.remote(options).then(function (remote) { | ||
self.client = remote; | ||
self.addCommands(); | ||
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).then(function (exists) { | ||
if (!exists) return false | ||
return this.getText(selector).then(function (selectorText) { | ||
return Array.isArray(selectorText) ? selectorText.some(s => s.includes(text)) : selectorText.includes(text) | ||
}) | ||
}) | ||
}, timeout).then(function () { }, function (error) { | ||
error.message = 'waitUntilTextExists ' + error.message | ||
throw error | ||
}) | ||
}) | ||
this.client.addCommand('waitUntilTextExists', function ( | ||
selector, | ||
text, | ||
timeout | ||
) { | ||
const self = this; | ||
return self | ||
.waitUntil(async function () { | ||
const elem = await self.$(selector); | ||
const exists = await elem.isExisting(); | ||
if (!exists) { | ||
return false; | ||
} | ||
/** | ||
* Utility from webdriverio v5 | ||
* https://github.com/webdriverio/webdriverio/blob/v5.9.4/packages/webdriverio/src/commands/browser/switchWindow.js | ||
*/ | ||
this.client.addCommand('switchWindow', async function (urlOrTitleToMatch) { | ||
if (typeof urlOrTitleToMatch !== 'string' && !(urlOrTitleToMatch instanceof RegExp)) { | ||
throw new TypeError('Invalid parameter urlOrTitleToMatch: expected a string or a RegExp') | ||
} | ||
const selectorText = await elem.getText(); | ||
return Array.isArray(selectorText) | ||
? selectorText.some((s) => s.includes(text)) | ||
: selectorText.includes(text); | ||
}, timeout) | ||
.then( | ||
function () {}, | ||
function (error) { | ||
error.message = 'waitUntilTextExists ' + error.message; | ||
throw error; | ||
} | ||
); | ||
}); | ||
const tabs = await this.windowHandles().then(getResponseValue) | ||
for (const tab of tabs) { | ||
await this.window(tab) | ||
/** | ||
* check if url matches | ||
*/ | ||
const url = await this.getUrl() | ||
if (url.match(urlOrTitleToMatch)) { | ||
return tab | ||
} | ||
/** | ||
* check title | ||
*/ | ||
const title = await this.getTitle() | ||
if (title.match(urlOrTitleToMatch)) { | ||
return tab | ||
} | ||
} | ||
throw new Error(`No window found with title or url matching "${urlOrTitleToMatch}"`) | ||
}) | ||
this.client.addCommand('waitUntilWindowLoaded', function (timeout) { | ||
return this.waitUntil(function () { | ||
return this.webContents.isLoading().then(function (loading) { | ||
return !loading | ||
}) | ||
}, timeout).then(function () { }, function (error) { | ||
error.message = 'waitUntilWindowLoaded ' + error.message | ||
throw error | ||
}) | ||
}) | ||
const self = this; | ||
return self | ||
.waitUntil(function () { | ||
return self.webContents.isLoading().then(function (loading) { | ||
return !loading; | ||
}); | ||
}, timeout) | ||
.then( | ||
function () {}, | ||
function (error) { | ||
error.message = 'waitUntilWindowLoaded ' + error.message; | ||
throw error; | ||
} | ||
); | ||
}); | ||
this.client.addCommand('getWindowCount', function () { | ||
return this.windowHandles().then(getResponseValue).then(function (handles) { | ||
return handles.length | ||
}) | ||
}) | ||
return this.getWindowHandles().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]) | ||
}) | ||
}) | ||
const self = this; | ||
return self.getWindowHandles().then(function (handles) { | ||
return self.switchToWindow(handles[index]); | ||
}); | ||
}); | ||
this.client.addCommand('getSelectedText', function () { | ||
return this.execute(function () { | ||
return window.getSelection().toString() | ||
}).then(getResponseValue) | ||
}) | ||
return window.getSelection().toString(); | ||
}); | ||
}); | ||
this.client.addCommand('getRenderProcessLogs', function () { | ||
return this.log('browser').then(getResponseValue) | ||
}) | ||
return this.getLogs('browser'); | ||
}); | ||
var self = this | ||
const self = this; | ||
this.client.addCommand('getMainProcessLogs', function () { | ||
var logs = self.chromeDriver.getLogs() | ||
self.chromeDriver.clearLogs() | ||
return logs | ||
}) | ||
const logs = self.chromeDriver.getLogs(); | ||
self.chromeDriver.clearLogs(); | ||
return logs; | ||
}); | ||
Accessibility.addCommand(this.client, this.requireName) | ||
} | ||
Accessibility.addCommand(this.client, this.requireName); | ||
}; | ||
var getResponseValue = function (response) { | ||
return response.value | ||
} | ||
module.exports = Application | ||
module.exports = Application; |
@@ -1,135 +0,145 @@ | ||
var ChildProcess = require('child_process') | ||
var path = require('path') | ||
var request = require('request') | ||
var split = require('split') | ||
const ChildProcess = require('child_process'); | ||
const path = require('path'); | ||
const request = require('request'); | ||
const split = require('split'); | ||
function ChromeDriver (host, port, nodePath, startTimeout, workingDirectory, chromeDriverLogPath) { | ||
this.host = host | ||
this.port = port | ||
this.nodePath = nodePath | ||
this.startTimeout = startTimeout | ||
this.workingDirectory = workingDirectory | ||
this.chromeDriverLogPath = chromeDriverLogPath | ||
function ChromeDriver( | ||
host, | ||
port, | ||
nodePath, | ||
startTimeout, | ||
workingDirectory, | ||
chromeDriverLogPath | ||
) { | ||
this.host = host; | ||
this.port = port; | ||
this.nodePath = nodePath; | ||
this.startTimeout = startTimeout; | ||
this.workingDirectory = workingDirectory; | ||
this.chromeDriverLogPath = chromeDriverLogPath; | ||
this.path = require.resolve('electron-chromedriver/chromedriver') | ||
this.urlBase = '/wd/hub' | ||
this.statusUrl = 'http://' + this.host + ':' + this.port + this.urlBase + '/status' | ||
this.logLines = [] | ||
this.path = require.resolve('electron-chromedriver/chromedriver'); | ||
this.urlBase = '/'; | ||
this.statusUrl = | ||
'http://' + this.host + ':' + this.port + this.urlBase + 'status'; | ||
this.logLines = []; | ||
} | ||
ChromeDriver.prototype.start = function () { | ||
if (this.process) throw new Error('ChromeDriver already started') | ||
if (this.process) throw new Error('ChromeDriver already started'); | ||
var args = [ | ||
this.path, | ||
'--port=' + this.port, | ||
'--url-base=' + this.urlBase | ||
] | ||
const args = [this.path, '--port=' + this.port, '--url-base=' + this.urlBase]; | ||
if (this.chromeDriverLogPath) { | ||
args.push('--verbose') | ||
args.push('--log-path=' + this.chromeDriverLogPath) | ||
args.push('--verbose'); | ||
args.push('--log-path=' + this.chromeDriverLogPath); | ||
} | ||
var options = { | ||
const options = { | ||
cwd: this.workingDirectory, | ||
env: this.getEnvironment() | ||
} | ||
this.process = ChildProcess.spawn(this.nodePath, args, options) | ||
}; | ||
this.process = ChildProcess.spawn(this.nodePath, args, options); | ||
var self = this | ||
this.exitHandler = function () { self.stop() } | ||
global.process.on('exit', this.exitHandler) | ||
const self = this; | ||
this.exitHandler = function () { | ||
self.stop(); | ||
}; | ||
global.process.on('exit', this.exitHandler); | ||
this.setupLogs() | ||
return this.waitUntilRunning() | ||
} | ||
this.setupLogs(); | ||
return this.waitUntilRunning(); | ||
}; | ||
ChromeDriver.prototype.waitUntilRunning = function () { | ||
var self = this | ||
const self = this; | ||
return new Promise(function (resolve, reject) { | ||
var startTime = Date.now() | ||
var checkIfRunning = function () { | ||
const startTime = Date.now(); | ||
const checkIfRunning = function () { | ||
self.isRunning(function (running) { | ||
if (!self.process) { | ||
return reject(Error('ChromeDriver has been stopped')) | ||
return reject(Error('ChromeDriver has been stopped')); | ||
} | ||
if (running) { | ||
return resolve() | ||
return resolve(); | ||
} | ||
var elapsedTime = Date.now() - startTime | ||
const elapsedTime = Date.now() - startTime; | ||
if (elapsedTime > self.startTimeout) { | ||
return reject(Error('ChromeDriver did not start within ' + self.startTimeout + 'ms')) | ||
return reject( | ||
Error( | ||
'ChromeDriver did not start within ' + self.startTimeout + 'ms' | ||
) | ||
); | ||
} | ||
global.setTimeout(checkIfRunning, 100) | ||
}) | ||
} | ||
checkIfRunning() | ||
}) | ||
} | ||
global.setTimeout(checkIfRunning, 100); | ||
}); | ||
}; | ||
checkIfRunning(); | ||
}); | ||
}; | ||
ChromeDriver.prototype.setupLogs = function () { | ||
var linesToIgnore = 2 // First two lines are ChromeDriver specific | ||
var lineCount = 0 | ||
const linesToIgnore = 2; // First two lines are ChromeDriver specific | ||
let lineCount = 0; | ||
this.logLines = [] | ||
this.logLines = []; | ||
var self = this | ||
const self = this; | ||
this.process.stdout.pipe(split()).on('data', function (line) { | ||
if (lineCount < linesToIgnore) { | ||
lineCount++ | ||
return | ||
lineCount++; | ||
return; | ||
} | ||
self.logLines.push(line) | ||
}) | ||
} | ||
self.logLines.push(line); | ||
}); | ||
}; | ||
ChromeDriver.prototype.getEnvironment = function () { | ||
var env = {} | ||
const env = {}; | ||
Object.keys(process.env).forEach(function (key) { | ||
env[key] = process.env[key] | ||
}) | ||
env[key] = process.env[key]; | ||
}); | ||
if (process.platform === 'win32') { | ||
env.SPECTRON_NODE_PATH = process.execPath | ||
env.SPECTRON_LAUNCHER_PATH = path.join(__dirname, 'launcher.js') | ||
env.SPECTRON_NODE_PATH = process.execPath; | ||
env.SPECTRON_LAUNCHER_PATH = path.join(__dirname, 'launcher.js'); | ||
} | ||
return env | ||
} | ||
return env; | ||
}; | ||
ChromeDriver.prototype.stop = function () { | ||
if (this.exitHandler) global.process.removeListener('exit', this.exitHandler) | ||
this.exitHandler = null | ||
if (this.exitHandler) global.process.removeListener('exit', this.exitHandler); | ||
this.exitHandler = null; | ||
if (this.process) this.process.kill() | ||
this.process = null | ||
if (this.process) this.process.kill(); | ||
this.process = null; | ||
this.clearLogs() | ||
} | ||
this.clearLogs(); | ||
}; | ||
ChromeDriver.prototype.isRunning = function (callback) { | ||
const cb = false | ||
var requestOptions = { | ||
const cb = false; | ||
const requestOptions = { | ||
uri: this.statusUrl, | ||
json: true, | ||
followAllRedirects: true | ||
} | ||
}; | ||
request(requestOptions, function (error, response, body) { | ||
if (error) return callback(cb) | ||
if (response.statusCode !== 200) return callback(cb) | ||
callback(body && body.value.ready) | ||
}) | ||
} | ||
if (error) return callback(cb); | ||
if (response.statusCode !== 200) return callback(cb); | ||
callback(body && body.value.ready); | ||
}); | ||
}; | ||
ChromeDriver.prototype.getLogs = function () { | ||
return this.logLines.slice() | ||
} | ||
return this.logLines.slice(); | ||
}; | ||
ChromeDriver.prototype.clearLogs = function () { | ||
this.logLines = [] | ||
} | ||
this.logLines = []; | ||
}; | ||
module.exports = ChromeDriver | ||
module.exports = ChromeDriver; |
#!/usr/bin/env node | ||
var ChildProcess = require('child_process') | ||
const ChildProcess = require('child_process'); | ||
var executablePath = null | ||
var appArgs = [] | ||
var chromeArgs = [] | ||
let executablePath = null; | ||
const appArgs = []; | ||
const chromeArgs = []; | ||
process.argv.slice(2).forEach(function (arg) { | ||
var indexOfEqualSign = arg.indexOf('=') | ||
const indexOfEqualSign = arg.indexOf('='); | ||
if (indexOfEqualSign === -1) { | ||
chromeArgs.push(arg) | ||
return | ||
chromeArgs.push(arg); | ||
return; | ||
} | ||
var name = arg.substring(0, indexOfEqualSign) | ||
var value = arg.substring(indexOfEqualSign + 1) | ||
const name = arg.substring(0, indexOfEqualSign); | ||
const value = arg.substring(indexOfEqualSign + 1); | ||
if (name === '--spectron-path') { | ||
executablePath = value | ||
executablePath = value; | ||
} else if (name.indexOf('--spectron-arg') === 0) { | ||
appArgs[Number(name.substring(14))] = value | ||
appArgs[Number(name.substring(14))] = value; | ||
} else if (name.indexOf('--spectron-env') === 0) { | ||
process.env[name.substring(15)] = value | ||
process.env[name.substring(15)] = value; | ||
} else if (name.indexOf('--spectron-') !== 0) { | ||
chromeArgs.push(arg) | ||
chromeArgs.push(arg); | ||
} | ||
}) | ||
}); | ||
var args = appArgs.concat(chromeArgs) | ||
var appProcess = ChildProcess.spawn(executablePath, args) | ||
appProcess.on('exit', function (code) { process.exit(code) }) | ||
appProcess.stderr.pipe(process.stdout) | ||
appProcess.stdout.pipe(process.stdout) | ||
appProcess.stdin.pipe(process.stdin) | ||
const args = appArgs.concat(chromeArgs); | ||
const appProcess = ChildProcess.spawn(executablePath, args); | ||
appProcess.on('exit', function (code) { | ||
process.exit(code); | ||
}); | ||
appProcess.stderr.pipe(process.stdout); | ||
appProcess.stdout.pipe(process.stdout); | ||
appProcess.stdin.pipe(process.stdin); |
@@ -1,13 +0,24 @@ | ||
if (process.platform !== 'darwin') process.exit(0) | ||
if (process.platform !== 'darwin') process.exit(0); | ||
const cp = require('child_process') | ||
const path = require('path') | ||
const cp = require('child_process'); | ||
const path = require('path'); | ||
const pathToChromedriver = require.resolve('electron-chromedriver/chromedriver') | ||
const pathToChromedriverBin = path.resolve(pathToChromedriver, '..', 'bin', 'chromedriver') | ||
const pathToChromedriver = require.resolve( | ||
'electron-chromedriver/chromedriver' | ||
); | ||
const pathToChromedriverBin = path.resolve( | ||
pathToChromedriver, | ||
'..', | ||
'bin', | ||
'chromedriver' | ||
); | ||
const result = cp.spawnSync('install_name_tool', ['-add_rpath', '@executable_path/.', pathToChromedriverBin], {}) | ||
const result = cp.spawnSync( | ||
'install_name_tool', | ||
['-add_rpath', '@executable_path/.', pathToChromedriverBin], | ||
{} | ||
); | ||
if (result.status !== 0) { | ||
if (result.stderr.includes('file already has LC_RPATH')) process.exit(0) | ||
process.exit(result.status) | ||
if (result.stderr.includes('file already has LC_RPATH')) process.exit(0); | ||
process.exit(result.status); | ||
} |
@@ -7,303 +7,315 @@ // Type definitions for spectron v3.6.0 | ||
declare module "spectron" { | ||
import * as Electron from "electron"; | ||
import * as WebdriverIO from "webdriverio"; | ||
declare module 'spectron' { | ||
import * as Electron from 'electron'; | ||
import * as WebdriverIO from 'webdriverio'; | ||
interface AccessibilityAuditOptions { | ||
/** | ||
* true to ignore failures with a severity of 'Warning' and only | ||
* include failures with a severity of 'Severe'. Defaults to false. | ||
*/ | ||
ignoreWarnings?:boolean; | ||
/** | ||
* Rule code values such as AX_COLOR_01 to ignore failures for. | ||
*/ | ||
ignoreRules?:string[]; | ||
} | ||
interface AccessibilityAuditOptions { | ||
/** | ||
* true to ignore failures with a severity of 'Warning' and only | ||
* include failures with a severity of 'Severe'. Defaults to false. | ||
*/ | ||
ignoreWarnings?: boolean; | ||
interface AccessibilityAuditResult { | ||
/** | ||
* False when the audit has failures | ||
*/ | ||
failed:boolean; | ||
/** | ||
* A detailed message about the results | ||
*/ | ||
message:string; | ||
/** | ||
* An array of detail objects for each failed rule | ||
*/ | ||
results:{ | ||
/** | ||
* A unique accessibility rule identifier | ||
*/ | ||
code:string; | ||
/** | ||
* Selector path of each HTML element that failed the rule | ||
*/ | ||
elements:string[]; | ||
/** | ||
* A String message about the failed rule | ||
*/ | ||
message:string; | ||
/** | ||
* 'Warning' or 'Severe' | ||
*/ | ||
severity:'Warning' | 'Severe'; | ||
/** | ||
* URL providing more details about the failed rule | ||
*/ | ||
url:string; | ||
}[]; | ||
} | ||
export interface SpectronClient extends WebdriverIO.Client<void> { | ||
/** | ||
* Focus a window using its title or URL. | ||
* <webview> tags can also be focused as a separate window. | ||
*/ | ||
switchWindow(urlOrTitleToMatch:string):Promise<void>; | ||
/** | ||
* Rule code values such as AX_COLOR_01 to ignore failures for. | ||
*/ | ||
ignoreRules?: string[]; | ||
} | ||
/** | ||
* Wait until the window is no longer loading. | ||
* Takes an optional timeout in milliseconds that defaults to 5000. | ||
*/ | ||
waitUntilWindowLoaded(timeout?:number):Promise<void>; | ||
interface AccessibilityAuditResult { | ||
/** | ||
* False when the audit has failures | ||
*/ | ||
failed: boolean; | ||
/** | ||
* Wait until the element matching the given selector contains the given text. | ||
* Takes an optional timeout in milliseconds that defaults to 5000. | ||
*/ | ||
waitUntilTextExists(selector:string, text:string, timeout?:number):Promise<void>; | ||
/** | ||
* A detailed message about the results | ||
*/ | ||
message: string; | ||
/** | ||
* Gets the number of open windows. <webview> tags are also counted as separate windows. | ||
*/ | ||
getWindowCount():Promise<number>; | ||
/** | ||
* Focus a window using its index from the windowHandles() array. | ||
* <webview> tags can also be focused as a separate window. | ||
*/ | ||
windowByIndex(index:number):Promise<void>; | ||
/** | ||
* Get the selected text in the current window. | ||
*/ | ||
getSelectedText():Promise<string>; | ||
/** | ||
* Gets the console log output from the render process. | ||
* The logs are cleared after they are returned. | ||
*/ | ||
getRenderProcessLogs():Promise<WebdriverIO.LogEntry[]>; | ||
/** | ||
* Gets the console log output from the main process. | ||
* The logs are cleared after they are returned. | ||
*/ | ||
getMainProcessLogs():Promise<string[]>; | ||
/** | ||
* Run an accessibility audit in the focused window with the specified options. | ||
*/ | ||
auditAccessibility(options?:AccessibilityAuditOptions):Promise<AccessibilityAuditResult>; | ||
} | ||
/** | ||
* An array of detail objects for each failed rule | ||
*/ | ||
results: { | ||
/** | ||
* A unique accessibility rule identifier | ||
*/ | ||
code: string; | ||
export interface SpectronWindow extends Electron.BrowserWindow { | ||
capturePage():Promise<Electron.NativeImage>; | ||
} | ||
/** | ||
* Selector path of each HTML element that failed the rule | ||
*/ | ||
elements: string[]; | ||
export interface SpectronWebContents extends Electron.WebContents { | ||
savePage( | ||
fullPath:string, | ||
saveType:"HTMLOnly" | "HTMLComplete" | "MHTML", | ||
callback?:(eror:Error) => void | ||
):boolean; | ||
savePage(fullPath:string, saveType:"HTMLOnly" | "HTMLComplete" | "MHTML"):Promise<void>; | ||
savePage(fullPath:string, saveType:"HTMLOnly" | "HTMLComplete" | "MHTML"):any; | ||
executeJavaScript(code:string, userGesture?:boolean):Promise<any>; | ||
} | ||
/** | ||
* A String message about the failed rule | ||
*/ | ||
message: string; | ||
type BasicAppSettings = { | ||
/** | ||
* String host name of the launched chromedriver process. Defaults to 'localhost'. | ||
*/ | ||
host?:string, | ||
/** | ||
* Number port of the launched chromedriver process. Defaults to 9515. | ||
*/ | ||
port?:number, | ||
/** | ||
* Number in milliseconds to wait for application quitting. | ||
* Defaults to 1000 milliseconds. | ||
*/ | ||
quitTimeout?:number, | ||
/** | ||
* Number in milliseconds to wait for ChromeDriver to start. | ||
* Defaults to 5000 milliseconds. | ||
*/ | ||
startTimeout?:number, | ||
/** | ||
* Number in milliseconds to wait for calls like waitUntilTextExists and | ||
* waitUntilWindowLoaded to complete. | ||
* Defaults to 5000 milliseconds. | ||
*/ | ||
waitTimeout?:number, | ||
/** | ||
* Number of retry attempts to make when connecting to ChromeDriver. | ||
* Defaults to 10 attempts. | ||
*/ | ||
connectionRetryCount?:number, | ||
/** | ||
* Number in milliseconds to wait for connections to ChromeDriver to be made. | ||
* Defaults to 30000 milliseconds. | ||
*/ | ||
connectionRetryTimeout?:number, | ||
/** | ||
* String path to a node executable to launch ChromeDriver with. | ||
* Defaults to process.execPath. | ||
*/ | ||
nodePath?:string, | ||
/** String path to the Electron application executable to launch. | ||
* Note: If you want to invoke electron directly with your app's main script then you should | ||
* specify path as electron via electron-prebuilt and specify your app's main script path as | ||
* the first argument in the args array. | ||
*/ | ||
path:string, | ||
/** | ||
* Array of arguments to pass to the Electron application. | ||
*/ | ||
args?:string[], | ||
/** | ||
* Array of arguments to pass to ChromeDriver. | ||
* See here (https://sites.google.com/a/chromium.org/chromedriver/capabilities) for details | ||
* on the Chrome arguments. | ||
*/ | ||
chromeDriverArgs?:string[], | ||
/** | ||
* Object of additional environment variables to set in the launched application. | ||
*/ | ||
env?:object, | ||
/** | ||
* String address of a Chrome debugger server to connect to. | ||
*/ | ||
debuggerAddress?:string, | ||
/** | ||
* String path to file to store ChromeDriver logs in. | ||
* Setting this option enables --verbose logging when starting ChromeDriver. | ||
*/ | ||
chromeDriverLogPath?:string, | ||
/** | ||
* String path to a directory where Webdriver will write logs to. | ||
* Setting this option enables verbose logging from Webdriver. | ||
*/ | ||
webdriverLogPath?:string, | ||
/** | ||
* Extra Webdriver options | ||
*/ | ||
webdriverOptions?:object, | ||
/** | ||
* Custom property name to use when requiring modules. | ||
* Defaults to require. | ||
* This should only be used if your application deletes the main window.require function | ||
* and assigns it to another property name on window. | ||
*/ | ||
requireName?:string | ||
}; | ||
type AppConstructorOptions = BasicAppSettings & { | ||
/** | ||
* String path to the working directory to use for the launched application. | ||
* Defaults to process.cwd(). | ||
*/ | ||
cwd?:string, | ||
}; | ||
export type ApplicationSettings = BasicAppSettings & { | ||
/** | ||
* String path to the working directory to use for the launched application. | ||
* Defaults to process.cwd(). | ||
*/ | ||
workingDirectory?:string, | ||
}; | ||
/** | ||
* 'Warning' or 'Severe' | ||
*/ | ||
severity: 'Warning' | 'Severe'; | ||
/** | ||
* URL providing more details about the failed rule | ||
*/ | ||
url: string; | ||
}[]; | ||
} | ||
export interface SpectronClient extends WebdriverIO.BrowserObject { | ||
/** | ||
* Start and stop your Electron application. | ||
* Focus a window using its title or URL. | ||
* <webview> tags can also be focused as a separate window. | ||
*/ | ||
export class Application { | ||
/** | ||
* Spectron uses WebdriverIO and exposes the managed client property on the created | ||
* Application instances. | ||
* The full client API provided by WebdriverIO can be found here | ||
* http://webdriver.io/api.html | ||
* Several additional commands are provided specific to Electron. | ||
*/ | ||
client:SpectronClient; | ||
/** | ||
* The electron property is your gateway to accessing the full Electron API. | ||
* Each Electron module is exposed as a property on the electron property so you can | ||
* think of it as an alias for require('electron') from within your app. | ||
*/ | ||
electron:Electron.AllElectron; | ||
/** | ||
* The browserWindow property is an alias for require('electron').remote.getCurrentWindow(). | ||
* It provides you access to the current BrowserWindow and contains all the APIs. | ||
* https://electron.atom.io/docs/api/browser-window/ | ||
*/ | ||
browserWindow:SpectronWindow; | ||
/** | ||
* The webContents property is an alias for | ||
* require('electron').remote.getCurrentWebContents(). | ||
* It provides you access to the WebContents for the current window | ||
* and contains all the APIs. | ||
* https://electron.atom.io/docs/api/web-contents/ | ||
*/ | ||
webContents:SpectronWebContents; | ||
/** | ||
* The mainProcess property is an alias for require('electron').remote.process. | ||
* It provides you access to the main process's process global. | ||
* https://nodejs.org/api/process.html | ||
*/ | ||
mainProcess:NodeJS.Process; | ||
/** | ||
*The rendererProcess property is an alias for global.process. | ||
* It provides you access to the main process's process global. | ||
* https://nodejs.org/api/process.html | ||
*/ | ||
rendererProcess:NodeJS.Process; | ||
switchWindow(urlOrTitleToMatch: string): Promise<void>; | ||
constructor(options:AppConstructorOptions); | ||
/** | ||
* Wait until the window is no longer loading. | ||
* Takes an optional timeout in milliseconds that defaults to 5000. | ||
*/ | ||
waitUntilWindowLoaded(timeout?: number): Promise<void>; | ||
/** | ||
* Starts the application. | ||
* Returns a Promise that will be resolved when the application is ready to use. | ||
* You should always wait for start to complete before running any commands. | ||
*/ | ||
start():Promise<Application>; | ||
/** | ||
* Wait until the element matching the given selector contains the given text. | ||
* Takes an optional timeout in milliseconds that defaults to 5000. | ||
*/ | ||
waitUntilTextExists( | ||
selector: string, | ||
text: string, | ||
timeout?: number | ||
): Promise<void>; | ||
/** | ||
* Stops the application. | ||
* Returns a Promise that will be resolved once the application has stopped. | ||
*/ | ||
stop():Promise<Application>; | ||
/** | ||
* Gets the number of open windows. <webview> tags are also counted as separate windows. | ||
*/ | ||
getWindowCount(): Promise<number>; | ||
/** | ||
* Focus a window using its index from the windowHandles() array. | ||
* <webview> tags can also be focused as a separate window. | ||
*/ | ||
windowByIndex(index: number): Promise<void>; | ||
/** | ||
* Get the selected text in the current window. | ||
*/ | ||
getSelectedText(): Promise<string>; | ||
/** | ||
* Gets the console log output from the render process. | ||
* The logs are cleared after they are returned. | ||
*/ | ||
getRenderProcessLogs(): Promise<object[]>; | ||
/** | ||
* Gets the console log output from the main process. | ||
* The logs are cleared after they are returned. | ||
*/ | ||
getMainProcessLogs(): Promise<string[]>; | ||
/** | ||
* Stops the application and then starts it. | ||
* Returns a Promise that will be resolved once the application has started again. | ||
*/ | ||
restart():Promise<Application>; | ||
/** | ||
* Run an accessibility audit in the focused window with the specified options. | ||
*/ | ||
auditAccessibility( | ||
options?: AccessibilityAuditOptions | ||
): Promise<AccessibilityAuditResult>; | ||
} | ||
/** | ||
* Checks to determine if the application is running or not. | ||
*/ | ||
isRunning():boolean; | ||
export interface SpectronWindow extends Electron.BrowserWindow { | ||
capturePage(): Promise<Electron.NativeImage>; | ||
} | ||
/** | ||
* Get all the configured options passed to the new Application() constructor. | ||
* This will include the default options values currently being used. | ||
*/ | ||
getSettings():ApplicationSettings; | ||
} | ||
export interface SpectronWebContents extends Electron.WebContents { | ||
savePage( | ||
fullPath: string, | ||
saveType: 'HTMLOnly' | 'HTMLComplete' | 'MHTML', | ||
callback?: (eror: Error) => void | ||
): boolean; | ||
savePage( | ||
fullPath: string, | ||
saveType: 'HTMLOnly' | 'HTMLComplete' | 'MHTML' | ||
): Promise<void>; | ||
savePage( | ||
fullPath: string, | ||
saveType: 'HTMLOnly' | 'HTMLComplete' | 'MHTML' | ||
): any; | ||
executeJavaScript(code: string, userGesture?: boolean): Promise<any>; | ||
} | ||
type BasicAppSettings = { | ||
/** | ||
* String host name of the launched chromedriver process. Defaults to 'localhost'. | ||
*/ | ||
host?: string; | ||
/** | ||
* Number port of the launched chromedriver process. Defaults to 9515. | ||
*/ | ||
port?: number; | ||
/** | ||
* Number in milliseconds to wait for application quitting. | ||
* Defaults to 1000 milliseconds. | ||
*/ | ||
quitTimeout?: number; | ||
/** | ||
* Number in milliseconds to wait for ChromeDriver to start. | ||
* Defaults to 5000 milliseconds. | ||
*/ | ||
startTimeout?: number; | ||
/** | ||
* Number in milliseconds to wait for calls like waitUntilTextExists and | ||
* waitUntilWindowLoaded to complete. | ||
* Defaults to 5000 milliseconds. | ||
*/ | ||
waitTimeout?: number; | ||
/** | ||
* Number of retry attempts to make when connecting to ChromeDriver. | ||
* Defaults to 10 attempts. | ||
*/ | ||
connectionRetryCount?: number; | ||
/** | ||
* Number in milliseconds to wait for connections to ChromeDriver to be made. | ||
* Defaults to 30000 milliseconds. | ||
*/ | ||
connectionRetryTimeout?: number; | ||
/** | ||
* String path to a node executable to launch ChromeDriver with. | ||
* Defaults to process.execPath. | ||
*/ | ||
nodePath?: string; | ||
/** String path to the Electron application executable to launch. | ||
* Note: If you want to invoke electron directly with your app's main script then you should | ||
* specify path as electron via electron-prebuilt and specify your app's main script path as | ||
* the first argument in the args array. | ||
*/ | ||
path: string; | ||
/** | ||
* Array of arguments to pass to the Electron application. | ||
*/ | ||
args?: string[]; | ||
/** | ||
* Array of arguments to pass to ChromeDriver. | ||
* See here (https://sites.google.com/a/chromium.org/chromedriver/capabilities) for details | ||
* on the Chrome arguments. | ||
*/ | ||
chromeDriverArgs?: string[]; | ||
/** | ||
* Object of additional environment variables to set in the launched application. | ||
*/ | ||
env?: object; | ||
/** | ||
* String address of a Chrome debugger server to connect to. | ||
*/ | ||
debuggerAddress?: string; | ||
/** | ||
* String path to file to store ChromeDriver logs in. | ||
* Setting this option enables --verbose logging when starting ChromeDriver. | ||
*/ | ||
chromeDriverLogPath?: string; | ||
/** | ||
* String path to a directory where Webdriver will write logs to. | ||
* Setting this option enables verbose logging from Webdriver. | ||
*/ | ||
webdriverLogPath?: string; | ||
/** | ||
* Extra Webdriver options | ||
*/ | ||
webdriverOptions?: object; | ||
/** | ||
* Custom property name to use when requiring modules. | ||
* Defaults to require. | ||
* This should only be used if your application deletes the main window.require function | ||
* and assigns it to another property name on window. | ||
*/ | ||
requireName?: string; | ||
}; | ||
type AppConstructorOptions = BasicAppSettings & { | ||
/** | ||
* String path to the working directory to use for the launched application. | ||
* Defaults to process.cwd(). | ||
*/ | ||
cwd?: string; | ||
}; | ||
export type ApplicationSettings = BasicAppSettings & { | ||
/** | ||
* String path to the working directory to use for the launched application. | ||
* Defaults to process.cwd(). | ||
*/ | ||
workingDirectory?: string; | ||
}; | ||
/** | ||
* Start and stop your Electron application. | ||
*/ | ||
export class Application { | ||
/** | ||
* Spectron uses WebdriverIO and exposes the managed client property on the created | ||
* Application instances. | ||
* The full client API provided by WebdriverIO can be found here | ||
* http://webdriver.io/api.html | ||
* Several additional commands are provided specific to Electron. | ||
*/ | ||
client: SpectronClient; | ||
/** | ||
* The electron property is your gateway to accessing the full Electron API. | ||
* Each Electron module is exposed as a property on the electron property so you can | ||
* think of it as an alias for require('electron') from within your app. | ||
*/ | ||
electron: Electron.AllElectron; | ||
/** | ||
* The browserWindow property is an alias for require('electron').remote.getCurrentWindow(). | ||
* It provides you access to the current BrowserWindow and contains all the APIs. | ||
* https://electron.atom.io/docs/api/browser-window/ | ||
*/ | ||
browserWindow: SpectronWindow; | ||
/** | ||
* The webContents property is an alias for | ||
* require('electron').remote.getCurrentWebContents(). | ||
* It provides you access to the WebContents for the current window | ||
* and contains all the APIs. | ||
* https://electron.atom.io/docs/api/web-contents/ | ||
*/ | ||
webContents: SpectronWebContents; | ||
/** | ||
* The mainProcess property is an alias for require('electron').remote.process. | ||
* It provides you access to the main process's process global. | ||
* https://nodejs.org/api/process.html | ||
*/ | ||
mainProcess: NodeJS.Process; | ||
/** | ||
*The rendererProcess property is an alias for global.process. | ||
* It provides you access to the main process's process global. | ||
* https://nodejs.org/api/process.html | ||
*/ | ||
rendererProcess: NodeJS.Process; | ||
constructor(options: AppConstructorOptions); | ||
/** | ||
* Starts the application. | ||
* Returns a Promise that will be resolved when the application is ready to use. | ||
* You should always wait for start to complete before running any commands. | ||
*/ | ||
start(): Promise<Application>; | ||
/** | ||
* Stops the application. | ||
* Returns a Promise that will be resolved once the application has stopped. | ||
*/ | ||
stop(): Promise<Application>; | ||
/** | ||
* Stops the application and then starts it. | ||
* Returns a Promise that will be resolved once the application has started again. | ||
*/ | ||
restart(): Promise<Application>; | ||
/** | ||
* Checks to determine if the application is running or not. | ||
*/ | ||
isRunning(): boolean; | ||
/** | ||
* Get all the configured options passed to the new Application() constructor. | ||
* This will include the default options values currently being used. | ||
*/ | ||
getSettings(): ApplicationSettings; | ||
} | ||
} |
{ | ||
"name": "spectron", | ||
"version": "11.0.0", | ||
"version": "11.1.0", | ||
"description": "Easily test your Electron apps using ChromeDriver and WebdriverIO.", | ||
@@ -8,7 +8,8 @@ "main": "index.js", | ||
"scripts": { | ||
"lint": "standard", | ||
"lint": "eslint \"**/*.js\" \"**/*.ts\" && prettier --check \"**/*.js\" \"**/*.ts\"", | ||
"prettier:write": "prettier --write \"**/*.js\" \"**/*.ts\"", | ||
"prepack": "check-for-leaks", | ||
"prepush": "check-for-leaks", | ||
"pretest": "tslint lib/spectron.d.ts && tsc lib/spectron.d.ts", | ||
"test": "xvfb-maybe mocha && standard", | ||
"pretest": "tsc lib/spectron.d.ts", | ||
"test": "npm run lint && xvfb-maybe mocha", | ||
"postinstall": "node lib/rpath-fix.js" | ||
@@ -29,3 +30,2 @@ }, | ||
"dependencies": { | ||
"@types/webdriverio": "^4.8.0", | ||
"dev-null": "^0.1.1", | ||
@@ -35,5 +35,7 @@ "electron-chromedriver": "^9.0.0", | ||
"split": "^1.0.0", | ||
"webdriverio": "^4.13.0" | ||
"webdriverio": "^6.1.20" | ||
}, | ||
"devDependencies": { | ||
"@typescript-eslint/eslint-plugin": "^3.4.0", | ||
"@typescript-eslint/parser": "^3.4.0", | ||
"chai": "^4.2.0", | ||
@@ -44,4 +46,11 @@ "chai-as-promised": "^7.1.1", | ||
"electron": "^9.0.0", | ||
"eslint": "^7.3.1", | ||
"eslint-config-standard": "^14.1.1", | ||
"eslint-plugin-import": "^2.22.0", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-promise": "^4.2.1", | ||
"eslint-plugin-standard": "^4.0.1", | ||
"husky": "^4.2.1", | ||
"mocha": "^7.1.2", | ||
"prettier": "^2.0.5", | ||
"standard": "^12.0.1", | ||
@@ -48,0 +57,0 @@ "temp": "^0.9.0", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
184970
5
20
3714
21
+ Added@babel/code-frame@7.24.7(transitive)
+ Added@babel/helper-validator-identifier@7.24.7(transitive)
+ Added@babel/highlight@7.24.7(transitive)
+ Added@puppeteer/browsers@2.4.0(transitive)
+ Added@sindresorhus/is@4.6.0(transitive)
+ Added@szmarczak/http-timer@4.0.6(transitive)
+ Added@tootallnate/quickjs-emscripten@0.23.0(transitive)
+ Added@types/cacheable-request@6.0.3(transitive)
+ Added@types/http-cache-semantics@4.0.4(transitive)
+ Added@types/keyv@3.1.4(transitive)
+ Added@types/puppeteer@7.0.4(transitive)
+ Added@types/puppeteer-core@5.4.0(transitive)
+ Added@types/responselike@1.0.3(transitive)
+ Added@types/which@1.3.2(transitive)
+ Added@wdio/config@6.12.1(transitive)
+ Added@wdio/logger@6.10.10(transitive)
+ Added@wdio/protocols@6.12.0(transitive)
+ Added@wdio/repl@6.11.0(transitive)
+ Added@wdio/utils@6.11.0(transitive)
+ Addedagent-base@5.1.17.1.1(transitive)
+ Addedansi-regex@5.0.1(transitive)
+ Addedansi-styles@4.3.0(transitive)
+ Addedarchiver@5.3.2(transitive)
+ Addedarchiver-utils@2.1.03.0.4(transitive)
+ Addedargparse@2.0.1(transitive)
+ Addedast-types@0.13.4(transitive)
+ Addedasync@3.2.6(transitive)
+ Addedat-least-node@1.0.0(transitive)
+ Addedb4a@1.6.6(transitive)
+ Addedbare-events@2.4.2(transitive)
+ Addedbare-fs@2.3.5(transitive)
+ Addedbare-os@2.4.4(transitive)
+ Addedbare-path@2.1.3(transitive)
+ Addedbare-stream@2.3.0(transitive)
+ Addedbasic-ftp@5.0.5(transitive)
+ Addedbl@4.1.0(transitive)
+ Addedbrace-expansion@2.0.1(transitive)
+ Addedcacheable-lookup@5.0.4(transitive)
+ Addedcacheable-request@7.0.4(transitive)
+ Addedcallsites@3.1.0(transitive)
+ Addedchalk@4.1.2(transitive)
+ Addedchownr@1.1.4(transitive)
+ Addedchrome-launcher@0.13.4(transitive)
+ Addedchromium-bidi@0.6.5(transitive)
+ Addedcliui@8.0.1(transitive)
+ Addedcolor-convert@2.0.1(transitive)
+ Addedcolor-name@1.1.4(transitive)
+ Addedcompress-commons@4.1.2(transitive)
+ Addedcosmiconfig@9.0.0(transitive)
+ Addedcrc-32@1.2.2(transitive)
+ Addedcrc32-stream@4.0.3(transitive)
+ Addedcss-shorthand-properties@1.1.1(transitive)
+ Addeddata-uri-to-buffer@6.0.2(transitive)
+ Addeddebug@2.6.9(transitive)
+ Addeddecompress-response@6.0.0(transitive)
+ Addeddeepmerge@4.3.1(transitive)
+ Addeddefer-to-connect@2.0.1(transitive)
+ Addeddegenerator@5.0.1(transitive)
+ Addeddevtools@6.12.1(transitive)
+ Addeddevtools-protocol@0.0.13306620.0.818844(transitive)
+ Addededge-paths@2.2.1(transitive)
+ Addedemoji-regex@8.0.0(transitive)
+ Addederror-ex@1.3.2(transitive)
+ Addedescalade@3.2.0(transitive)
+ Addedescodegen@2.1.0(transitive)
+ Addedesprima@4.0.1(transitive)
+ Addedestraverse@5.3.0(transitive)
+ Addedesutils@2.0.3(transitive)
+ Addedfast-deep-equal@2.0.1(transitive)
+ Addedfast-fifo@1.3.2(transitive)
+ Addedfind-up@4.1.0(transitive)
+ Addedfs-extra@11.2.09.1.0(transitive)
+ Addedget-caller-file@2.0.5(transitive)
+ Addedget-port@5.1.1(transitive)
+ Addedget-uri@6.0.3(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedgot@11.8.6(transitive)
+ Addedhas-flag@4.0.0(transitive)
+ Addedhttp-proxy-agent@7.0.2(transitive)
+ Addedhttp2-wrapper@1.0.3(transitive)
+ Addedhttps-proxy-agent@4.0.07.0.5(transitive)
+ Addedimport-fresh@3.3.0(transitive)
+ Addedip-address@9.0.5(transitive)
+ Addedis-arrayish@0.2.1(transitive)
+ Addedis-docker@2.2.1(transitive)
+ Addedis-fullwidth-code-point@3.0.0(transitive)
+ Addedis-wsl@2.2.0(transitive)
+ Addedisexe@2.0.0(transitive)
+ Addedjs-tokens@4.0.0(transitive)
+ Addedjs-yaml@4.1.0(transitive)
+ Addedjsbn@1.1.0(transitive)
+ Addedjson-buffer@3.0.1(transitive)
+ Addedjson-parse-even-better-errors@2.3.1(transitive)
+ Addedjsonfile@6.1.0(transitive)
+ Addedkeyv@4.5.4(transitive)
+ Addedlighthouse-logger@1.4.2(transitive)
+ Addedlines-and-columns@1.2.4(transitive)
+ Addedlocate-path@5.0.0(transitive)
+ Addedlodash.clonedeep@4.5.0(transitive)
+ Addedlodash.defaults@4.2.0(transitive)
+ Addedlodash.difference@4.5.0(transitive)
+ Addedlodash.flatten@4.4.0(transitive)
+ Addedlodash.isobject@3.0.2(transitive)
+ Addedlodash.isplainobject@4.0.6(transitive)
+ Addedlodash.merge@4.6.2(transitive)
+ Addedlodash.union@4.6.0(transitive)
+ Addedlodash.zip@4.2.0(transitive)
+ Addedloglevel@1.9.2(transitive)
+ Addedloglevel-plugin-prefix@0.8.4(transitive)
+ Addedlru-cache@7.18.3(transitive)
+ Addedmarky@1.2.5(transitive)
+ Addedmimic-response@3.1.0(transitive)
+ Addedminimatch@5.1.6(transitive)
+ Addedmitt@3.0.1(transitive)
+ Addedmkdirp-classic@0.5.3(transitive)
+ Addedms@2.0.0(transitive)
+ Addednetmask@2.0.2(transitive)
+ Addednode-fetch@2.7.0(transitive)
+ Addednormalize-path@3.0.0(transitive)
+ Addednormalize-url@6.1.0(transitive)
+ Addedp-cancelable@2.1.1(transitive)
+ Addedp-limit@2.3.0(transitive)
+ Addedp-locate@4.1.0(transitive)
+ Addedp-try@2.2.0(transitive)
+ Addedpac-proxy-agent@7.0.2(transitive)
+ Addedpac-resolver@7.0.1(transitive)
+ Addedparent-module@1.0.1(transitive)
+ Addedparse-json@5.2.0(transitive)
+ Addedpath-exists@4.0.0(transitive)
+ Addedpicocolors@1.1.0(transitive)
+ Addedpkg-dir@4.2.0(transitive)
+ Addedproxy-agent@6.4.0(transitive)
+ Addedproxy-from-env@1.1.0(transitive)
+ Addedpuppeteer@23.3.0(transitive)
+ Addedpuppeteer-core@23.3.05.5.0(transitive)
+ Addedqueue-tick@1.0.1(transitive)
+ Addedquick-lru@5.1.1(transitive)
+ Addedreadable-stream@3.6.2(transitive)
+ Addedreaddir-glob@1.1.3(transitive)
+ Addedrequire-directory@2.1.1(transitive)
+ Addedresolve-alpn@1.2.1(transitive)
+ Addedresolve-from@4.0.0(transitive)
+ Addedresponselike@2.0.1(transitive)
+ Addedresq@1.11.0(transitive)
+ Addedrgb2hex@0.2.3(transitive)
+ Addedrimraf@3.0.2(transitive)
+ Addedserialize-error@8.1.0(transitive)
+ Addedsmart-buffer@4.2.0(transitive)
+ Addedsocks@2.8.3(transitive)
+ Addedsocks-proxy-agent@8.0.4(transitive)
+ Addedstreamx@2.20.1(transitive)
+ Addedstring-width@4.2.3(transitive)
+ Addedstrip-ansi@6.0.1(transitive)
+ Addedsupports-color@7.2.0(transitive)
+ Addedtar-fs@2.1.13.0.6(transitive)
+ Addedtar-stream@2.2.03.1.7(transitive)
+ Addedtext-decoder@1.2.0(transitive)
+ Addedtr46@0.0.3(transitive)
+ Addedtslib@2.7.0(transitive)
+ Addedtype-fest@0.20.2(transitive)
+ Addedtyped-query-selector@2.12.0(transitive)
+ Addedua-parser-js@0.7.39(transitive)
+ Addedunbzip2-stream@1.4.3(transitive)
+ Addeduniversalify@2.0.1(transitive)
+ Addedurlpattern-polyfill@10.0.0(transitive)
+ Addeduuid@8.3.2(transitive)
+ Addedwebdriver@6.12.1(transitive)
+ Addedwebdriverio@6.12.1(transitive)
+ Addedwebidl-conversions@3.0.1(transitive)
+ Addedwhatwg-url@5.0.0(transitive)
+ Addedwhich@2.0.2(transitive)
+ Addedwrap-ansi@7.0.0(transitive)
+ Addedws@7.5.108.18.0(transitive)
+ Addedy18n@5.0.8(transitive)
+ Addedyargs@17.7.2(transitive)
+ Addedyargs-parser@21.1.1(transitive)
+ Addedzip-stream@4.1.1(transitive)
+ Addedzod@3.23.8(transitive)
- Removed@types/webdriverio@^4.8.0
- Removed@types/webdriverio@4.13.3(transitive)
- Removedansi-escapes@3.2.0(transitive)
- Removedansi-regex@3.0.1(transitive)
- Removedarchiver@2.1.1(transitive)
- Removedarchiver-utils@1.3.0(transitive)
- Removedasync@2.6.4(transitive)
- Removedbabel-runtime@6.26.0(transitive)
- Removedbl@1.2.3(transitive)
- Removedbuffer-alloc@1.2.0(transitive)
- Removedbuffer-alloc-unsafe@1.1.0(transitive)
- Removedbuffer-fill@1.0.0(transitive)
- Removedcall-bind@1.0.7(transitive)
- Removedchardet@0.4.2(transitive)
- Removedcli-cursor@2.1.0(transitive)
- Removedcli-width@2.2.1(transitive)
- Removedcompress-commons@1.2.2(transitive)
- Removedcore-js@2.6.12(transitive)
- Removedcrc@3.8.0(transitive)
- Removedcrc32-stream@2.0.0(transitive)
- Removedcss@2.2.4(transitive)
- Removedcss-parse@2.0.0(transitive)
- Removeddecode-uri-component@0.2.2(transitive)
- Removeddeepmerge@2.0.1(transitive)
- Removedejs@2.5.9(transitive)
- Removedexternal-editor@2.2.0(transitive)
- Removedfigures@2.0.0(transitive)
- Removedgaze@1.1.3(transitive)
- Removedglob@7.1.7(transitive)
- Removedglobule@1.3.4(transitive)
- Removedhas-flag@2.0.0(transitive)
- Removediconv-lite@0.4.24(transitive)
- Removedinquirer@3.3.0(transitive)
- Removedis-fullwidth-code-point@2.0.0(transitive)
- Removedmimic-fn@1.2.0(transitive)
- Removedminimatch@3.0.8(transitive)
- Removedminimist@0.0.10(transitive)
- Removedmute-stream@0.0.7(transitive)
- Removednormalize-path@2.1.1(transitive)
- Removednpm-install-package@2.1.0(transitive)
- Removedobject-inspect@1.13.2(transitive)
- Removedonetime@2.0.1(transitive)
- Removedoptimist@0.6.1(transitive)
- Removedos-tmpdir@1.0.2(transitive)
- Removedpunycode@1.4.1(transitive)
- Removedq@1.5.1(transitive)
- Removedqs@6.13.0(transitive)
- Removedregenerator-runtime@0.11.1(transitive)
- Removedremove-trailing-separator@1.1.0(transitive)
- Removedresolve-url@0.2.1(transitive)
- Removedrestore-cursor@2.0.0(transitive)
- Removedrgb2hex@0.1.10(transitive)
- Removedrun-async@2.4.1(transitive)
- Removedrx-lite@4.0.8(transitive)
- Removedrx-lite-aggregates@4.0.8(transitive)
- Removedset-function-length@1.2.2(transitive)
- Removedside-channel@1.0.6(transitive)
- Removedsignal-exit@3.0.7(transitive)
- Removedsource-map-resolve@0.5.3(transitive)
- Removedsource-map-url@0.4.1(transitive)
- Removedstring-width@2.1.1(transitive)
- Removedstrip-ansi@4.0.0(transitive)
- Removedsupports-color@5.0.1(transitive)
- Removedtar-stream@1.6.2(transitive)
- Removedtmp@0.0.33(transitive)
- Removedto-buffer@1.1.1(transitive)
- Removedurix@0.1.0(transitive)
- Removedurl@0.11.4(transitive)
- Removedwdio-dot-reporter@0.0.10(transitive)
- Removedwebdriverio@4.14.4(transitive)
- Removedwgxpath@1.0.0(transitive)
- Removedwordwrap@0.0.3(transitive)
- Removedxtend@4.0.2(transitive)
- Removedzip-stream@1.2.0(transitive)
Updatedwebdriverio@^6.1.20