From d1e50af4ab202bb94d72a0a158ccaaa81d026ac5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 08:33:01 -0700 Subject: [PATCH 01/80] Add initial auto-generated API --- lib/api.js | 66 ++++++++++++++++++++++++++++++++++++++++++++++ lib/application.js | 1 + 2 files changed, 67 insertions(+) create mode 100644 lib/api.js diff --git a/lib/api.js b/lib/api.js new file mode 100644 index 000000000..e8e210dad --- /dev/null +++ b/lib/api.js @@ -0,0 +1,66 @@ +exports.initialize = function (app) { + return getApis(app).then(getResponseValue).then(function (api) { + console.log(api); + app.electron = {} + addApi(app, app.electron, [], api) + }) +} + +function getApis (app) { + return app.client.execute(function () { + var electron = require('electron') + var api = {} + + Object.getOwnPropertyNames(electron).forEach(function (key) { + var module = electron[key] + api[key] = {} + Object.getOwnPropertyNames(module).forEach(function (moduleKey) { + var value = module[moduleKey] + if (typeof value === 'function') { + api[key][moduleKey] = 'function' + } + }) + }) + + return api + }) +} + +function addApi (app, parent, parentSegments, api) { + Object.keys(api).forEach(function (key) { + var segments = parentSegments.concat(key) + var commandName = 'electron.' + segments.join('.') + var value = api[key] + + if (value === 'function') { + app.client.addCommand(commandName, function () { + var args = Array.prototype.slice.call(arguments) + return this.execute.call(this, callApi, segments, args) + .then(getResponseValue) + }) + parent[key] = function () { + return app.client[commandName].apply(app.client, arguments) + } + } else { + parent[key] = {} + addApi(app, parent[key], segments, value) + } + }) +} + +function callApi (segments, args) { + var api = require('electron') + + segments.forEach(function (segment, index) { + api = api[segment] + if (api === 'function' && index < segments.length - 1) { + api = api() + } + }) + + return api.apply(api, args) +} + +function getResponseValue (response) { + return response.value +} diff --git a/lib/application.js b/lib/application.js index 1aa3e5725..6079d3955 100644 --- a/lib/application.js +++ b/lib/application.js @@ -26,6 +26,7 @@ Application.prototype.start = function () { return self.exists() .then(function () { return self.startChromeDriver() }) .then(function () { return self.createClient() }) + .then(function () { require('./api').initialize(self) }) .then(function () { self.running = true }) } From c9e14e3690bf36efb6b1641c18363f89aad1f57f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 08:33:57 -0700 Subject: [PATCH 02/80] Return initialize promise --- lib/application.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/application.js b/lib/application.js index 6079d3955..5f5c346e4 100644 --- a/lib/application.js +++ b/lib/application.js @@ -1,3 +1,4 @@ +var api = require('./api') var ChromeDriver = require('./chrome-driver') var DevNull = require('dev-null') var fs = require('fs') @@ -26,7 +27,7 @@ Application.prototype.start = function () { return self.exists() .then(function () { return self.startChromeDriver() }) .then(function () { return self.createClient() }) - .then(function () { require('./api').initialize(self) }) + .then(function () { return api.initialize(self) }) .then(function () { self.running = true }) } From 48237ac8c61c4206323d039902e5ea7e011e77fb Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 08:39:33 -0700 Subject: [PATCH 03/80] Ignore deprected modules --- lib/api.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/api.js b/lib/api.js index e8e210dad..feb09d7ff 100644 --- a/lib/api.js +++ b/lib/api.js @@ -8,12 +8,25 @@ exports.initialize = function (app) { function getApis (app) { return app.client.execute(function () { + function ignoreModule (moduleName) { + switch (moduleName) { + case 'deprecate': + case 'deprecations': + case 'hideInternalModules': + return true + } + return false + } + var electron = require('electron') var api = {} Object.getOwnPropertyNames(electron).forEach(function (key) { + if (ignoreModule(key)) return + var module = electron[key] api[key] = {} + Object.getOwnPropertyNames(module).forEach(function (moduleKey) { var value = module[moduleKey] if (typeof value === 'function') { From 65da9215e8bb26b2517db4a47faecf549393043f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 08:44:50 -0700 Subject: [PATCH 04/80] Add remote properties to api --- lib/api.js | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/lib/api.js b/lib/api.js index feb09d7ff..691cac7da 100644 --- a/lib/api.js +++ b/lib/api.js @@ -18,22 +18,27 @@ function getApis (app) { return false } - var electron = require('electron') - var api = {} + function addProperties (parent, api) { + Object.getOwnPropertyNames(parent).forEach(function (key) { + if (ignoreModule(key)) return - Object.getOwnPropertyNames(electron).forEach(function (key) { - if (ignoreModule(key)) return + var module = parent[key] + api[key] = {} - var module = electron[key] - api[key] = {} - - Object.getOwnPropertyNames(module).forEach(function (moduleKey) { - var value = module[moduleKey] - if (typeof value === 'function') { - api[key][moduleKey] = 'function' - } + Object.getOwnPropertyNames(module).forEach(function (moduleKey) { + var value = module[moduleKey] + if (typeof value === 'function') { + api[key][moduleKey] = 'function' + } + }) }) - }) + } + + var electron = require('electron') + var api = {} + + addProperties(electron, api) + addProperties(electron.remote, api.remote) return api }) From eb323537fd1e72a8241bbb6d27eca35a0ff6fdcb Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 08:50:40 -0700 Subject: [PATCH 05/80] Add transferPromiseness helper to application --- lib/application.js | 5 +++++ test/global-setup.js | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/application.js b/lib/application.js index 5f5c346e4..503ed1e09 100644 --- a/lib/application.js +++ b/lib/application.js @@ -20,6 +20,11 @@ function Application (options) { this.args = options.args || [] this.env = options.env || {} this.workingDirectory = options.cwd || process.cwd() + + var self = this + this.transferPromiseness = function (target, promise) { + self.client.transferPromiseness(target, promise) + } } Application.prototype.start = function () { diff --git a/test/global-setup.js b/test/global-setup.js index 7d9585752..ece844ddb 100644 --- a/test/global-setup.js +++ b/test/global-setup.js @@ -29,7 +29,7 @@ exports.startApplication = function (options) { var app = new Application(options) return app.start().then(function () { assert.equal(app.isRunning(), true) - chaiAsPromised.transferPromiseness = app.client.transferPromiseness + chaiAsPromised.transferPromiseness = app.transferPromiseness return app }) } From 540830d7ca0eea27e87e824771e86e4f6af0d59c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 09:58:23 -0700 Subject: [PATCH 06/80] Allow promise chaining and transfer for electron property --- lib/api.js | 4 +++- lib/application.js | 14 +++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/api.js b/lib/api.js index 691cac7da..3526419b8 100644 --- a/lib/api.js +++ b/lib/api.js @@ -1,8 +1,10 @@ exports.initialize = function (app) { return getApis(app).then(getResponseValue).then(function (api) { - console.log(api); app.electron = {} addApi(app, app.electron, [], api) + + // Add electron property to client prototype so promises can be chained + Object.getPrototypeOf(app.client).electron = app.electron }) } diff --git a/lib/application.js b/lib/application.js index 503ed1e09..34ba26a79 100644 --- a/lib/application.js +++ b/lib/application.js @@ -20,10 +20,14 @@ function Application (options) { this.args = options.args || [] this.env = options.env || {} this.workingDirectory = options.cwd || process.cwd() + this.setupPromiseness() +} +Application.prototype.setupPromiseness = function () { var self = this - this.transferPromiseness = function (target, promise) { + self.transferPromiseness = function (target, promise) { self.client.transferPromiseness(target, promise) + self.addPropertiesToPromise(target, promise) } } @@ -309,6 +313,14 @@ Application.prototype.addCurrentWindowGetter = function (methodName, commandName }) } +Application.prototype.addPropertiesToPromise = function (target, promise) { + target.electron = {} + var self = this + Object.keys(self.electron).forEach(function (module) { + target.electron[module] = self.electron[module] + }) +} + var getResponseValue = function (response) { return response.value } From 25f1fde6a9571648c82353b29888f7f924d9b39e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 10:02:48 -0700 Subject: [PATCH 07/80] Remove unneeed call() --- lib/api.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/api.js b/lib/api.js index 3526419b8..4222b851a 100644 --- a/lib/api.js +++ b/lib/api.js @@ -55,8 +55,7 @@ function addApi (app, parent, parentSegments, api) { if (value === 'function') { app.client.addCommand(commandName, function () { var args = Array.prototype.slice.call(arguments) - return this.execute.call(this, callApi, segments, args) - .then(getResponseValue) + return this.execute(callApi, segments, args).then(getResponseValue) }) parent[key] = function () { return app.client[commandName].apply(app.client, arguments) From a236759bc942ba0abf5052e76bbfbfcbbb21b9fb Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 10:54:45 -0700 Subject: [PATCH 08/80] Add api class --- lib/api.js | 31 +++++++++++++++++++++++-------- lib/application.js | 15 ++++----------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/lib/api.js b/lib/api.js index 4222b851a..2549d3d66 100644 --- a/lib/api.js +++ b/lib/api.js @@ -1,14 +1,24 @@ -exports.initialize = function (app) { - return getApis(app).then(getResponseValue).then(function (api) { - app.electron = {} - addApi(app, app.electron, [], api) +function Api (app) { + this.app = app +} + +Api.prototype.transferPromiseness = function (target, promise) { + +} + +Api.prototype.initialize = function () { + var self = this + return this.load(self.app).then(getResponseValue).then(function (api) { + self.api = api + self.app.electron = {} + self.add(self.app.electron, [], api) // Add electron property to client prototype so promises can be chained - Object.getPrototypeOf(app.client).electron = app.electron + Object.getPrototypeOf(self.app.client).electron = self.app.electron }) } -function getApis (app) { +Api.prototype.load = function (app) { return app.client.execute(function () { function ignoreModule (moduleName) { switch (moduleName) { @@ -46,7 +56,10 @@ function getApis (app) { }) } -function addApi (app, parent, parentSegments, api) { +Api.prototype.add = function (parent, parentSegments, api) { + var self = this + var app = self.app + Object.keys(api).forEach(function (key) { var segments = parentSegments.concat(key) var commandName = 'electron.' + segments.join('.') @@ -62,7 +75,7 @@ function addApi (app, parent, parentSegments, api) { } } else { parent[key] = {} - addApi(app, parent[key], segments, value) + self.add(parent[key], segments, value) } }) } @@ -83,3 +96,5 @@ function callApi (segments, args) { function getResponseValue (response) { return response.value } + +module.exports = Api diff --git a/lib/application.js b/lib/application.js index 34ba26a79..f844da854 100644 --- a/lib/application.js +++ b/lib/application.js @@ -1,4 +1,4 @@ -var api = require('./api') +var Api = require('./api') var ChromeDriver = require('./chrome-driver') var DevNull = require('dev-null') var fs = require('fs') @@ -20,6 +20,7 @@ function Application (options) { this.args = options.args || [] this.env = options.env || {} this.workingDirectory = options.cwd || process.cwd() + this.api = new Api(this) this.setupPromiseness() } @@ -27,7 +28,7 @@ Application.prototype.setupPromiseness = function () { var self = this self.transferPromiseness = function (target, promise) { self.client.transferPromiseness(target, promise) - self.addPropertiesToPromise(target, promise) + self.api.transferPromiseness(target, promise) } } @@ -36,7 +37,7 @@ Application.prototype.start = function () { return self.exists() .then(function () { return self.startChromeDriver() }) .then(function () { return self.createClient() }) - .then(function () { return api.initialize(self) }) + .then(function () { return self.api.initialize() }) .then(function () { self.running = true }) } @@ -313,14 +314,6 @@ Application.prototype.addCurrentWindowGetter = function (methodName, commandName }) } -Application.prototype.addPropertiesToPromise = function (target, promise) { - target.electron = {} - var self = this - Object.keys(self.electron).forEach(function (module) { - target.electron[module] = self.electron[module] - }) -} - var getResponseValue = function (response) { return response.value } From 978a2f09270c565278326178a9efe0efb9c77da9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 11:10:39 -0700 Subject: [PATCH 09/80] Properly transfer client properties on promises --- lib/api.js | 17 +++++++++++++++++ lib/application.js | 1 - 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/api.js b/lib/api.js index 2549d3d66..ce309387a 100644 --- a/lib/api.js +++ b/lib/api.js @@ -1,9 +1,25 @@ function Api (app) { this.app = app + this.commands = {} } Api.prototype.transferPromiseness = function (target, promise) { + var self = this + + self.app.client.transferPromiseness(target, promise) + target.electron = {} + + Object.keys(this.commands).forEach(function (command) { + var apiPath = self.commands[command] + var api = target.electron + apiPath.slice(0, -1).forEach(function (segment) { + if (!api[segment]) api[segment] = {} + api = api[segment] + }) + + api[apiPath[apiPath.length - 1]] = target[command].bind(target) + }) } Api.prototype.initialize = function () { @@ -66,6 +82,7 @@ Api.prototype.add = function (parent, parentSegments, api) { var value = api[key] if (value === 'function') { + self.commands[commandName] = segments app.client.addCommand(commandName, function () { var args = Array.prototype.slice.call(arguments) return this.execute(callApi, segments, args).then(getResponseValue) diff --git a/lib/application.js b/lib/application.js index f844da854..07ea9b3e8 100644 --- a/lib/application.js +++ b/lib/application.js @@ -27,7 +27,6 @@ function Application (options) { Application.prototype.setupPromiseness = function () { var self = this self.transferPromiseness = function (target, promise) { - self.client.transferPromiseness(target, promise) self.api.transferPromiseness(target, promise) } } From 00632048af35933568b197046337f542a61dc041 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 15:05:19 -0700 Subject: [PATCH 10/80] Upgrade electron --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1f1097c18..bc0d5deb6 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "devDependencies": { "chai": "^3.3.0", "chai-as-promised": "^5.1.0", - "electron-prebuilt": "^0.37.2", + "electron-prebuilt": "^0.37.6", "mocha": "^2.3.3", "standard": "^5.3.1", "temp": "^0.8.3" From be9c82a90a53d6b7df1dca6c47ce9727948507d1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 15:05:36 -0700 Subject: [PATCH 11/80] Add app.browserWindow proxy --- lib/api.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/lib/api.js b/lib/api.js index ce309387a..d6e3dbb9d 100644 --- a/lib/api.js +++ b/lib/api.js @@ -25,17 +25,22 @@ Api.prototype.transferPromiseness = function (target, promise) { Api.prototype.initialize = function () { var self = this return this.load(self.app).then(getResponseValue).then(function (api) { - self.api = api self.app.electron = {} - self.add(self.app.electron, [], api) + self.app.browserWindow = {} + self.add(self.app.electron, [], api.electron) + self.addBrowserWindowApis(api.browserWindow) + // Add electron property to client prototype so promises can be chained Object.getPrototypeOf(self.app.client).electron = self.app.electron + Object.getPrototypeOf(self.app.client).browserWindow = self.app.browserWindow }) } Api.prototype.load = function (app) { return app.client.execute(function () { + var electron = require('electron') + function ignoreModule (moduleName) { switch (moduleName) { case 'deprecate': @@ -62,11 +67,25 @@ Api.prototype.load = function (app) { }) } - var electron = require('electron') - var api = {} + function addBrowserWindow (api) { + var currentWindow = electron.remote.getCurrentWindow() + for (var name in currentWindow) { + var value = currentWindow[name] + if (typeof value === 'function') { + api[name] = 'function' + } + } + } + + var api = { + electron: {}, + browserWindow: {}, + webContents: {} + } - addProperties(electron, api) - addProperties(electron.remote, api.remote) + addProperties(electron, api.electron) + addProperties(electron.remote, api.electron.remote) + addBrowserWindow(api.browserWindow) return api }) @@ -97,6 +116,29 @@ Api.prototype.add = function (parent, parentSegments, api) { }) } +Api.prototype.addBrowserWindowApis = function (api) { + var app = this.app + app.browserWindow = {} + + Object.keys(api).forEach(function (name) { + var commandName = 'browserWindow.' + name + + app.client.addCommand(commandName, function () { + var args = Array.prototype.slice.call(arguments) + return this.execute(callBrowserWindowApi, name, args).then(getResponseValue) + }) + + app.browserWindow[name] = function () { + return app.client[commandName].apply(app.client, arguments) + } + }) +} + +function callBrowserWindowApi (name, args) { + var window = require('electron').remote.getCurrentWindow() + return window[name].apply(window, args) +} + function callApi (segments, args) { var api = require('electron') From a4ecf9b13f570218921d973088b47db18fcd90e8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 18:10:21 -0700 Subject: [PATCH 12/80] Bind browserWindow apis correctly --- lib/api.js | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/api.js b/lib/api.js index d6e3dbb9d..6ac996ce1 100644 --- a/lib/api.js +++ b/lib/api.js @@ -7,7 +7,9 @@ Api.prototype.transferPromiseness = function (target, promise) { var self = this self.app.client.transferPromiseness(target, promise) + target.electron = {} + target.browserWindow = {} Object.keys(this.commands).forEach(function (command) { var apiPath = self.commands[command] @@ -20,6 +22,11 @@ Api.prototype.transferPromiseness = function (target, promise) { api[apiPath[apiPath.length - 1]] = target[command].bind(target) }) + + var browserWindow = promise.browserWindow + Object.keys(promise.browserWindow).forEach(function (name) { + target.browserWindow[name] = browserWindow[name].bind(promise) + }) } Api.prototype.initialize = function () { @@ -30,10 +37,20 @@ Api.prototype.initialize = function () { self.add(self.app.electron, [], api.electron) self.addBrowserWindowApis(api.browserWindow) - // Add electron property to client prototype so promises can be chained - Object.getPrototypeOf(self.app.client).electron = self.app.electron - Object.getPrototypeOf(self.app.client).browserWindow = self.app.browserWindow + var clientPrototype = Object.getPrototypeOf(self.app.client) + clientPrototype.electron = self.app.electron + + Object.defineProperty(clientPrototype, 'browserWindow', { + get: function () { + var api = {} + var client = this + Object.keys(self.app.browserWindow).forEach(function (key) { + api[key] = client['browserWindow.' + key].bind(client) + }) + return api + } + }); }) } From 2d743eab9cff9530c6414c0e2921027a0c5cfa0e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 18:10:31 -0700 Subject: [PATCH 13/80] Start migrating specs --- test/commands-test.js | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/test/commands-test.js b/test/commands-test.js index ca3e1d760..692bb3004 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -30,7 +30,7 @@ describe('window commands', function () { describe('getWindowBounds', function () { it('gets the window bounds', function () { - return app.client.getWindowBounds().should.eventually.deep.equal({ + return app.browserWindow.getBounds().should.eventually.deep.equal({ x: 25, y: 35, width: 200, @@ -39,29 +39,17 @@ describe('window commands', function () { }) }) - describe('getWindowWidth', function () { - it('gets the window width', function () { - return app.client.getWindowWidth().should.eventually.equal(200) - }) - }) - - describe('getWindowHeight', function () { - it('gets the window height', function () { - return app.client.getWindowHeight().should.eventually.equal(100) - }) - }) - describe('setWindowBounds', function () { it('sets the window bounds', function () { - return app.client - .setWindowBounds({ + return app.browserWindow + .setBounds({ x: 100, y: 200, width: 50, height: 75 }) .pause(1000) - .getWindowBounds().should.eventually.deep.equal({ + .browserWindow.getBounds().should.eventually.deep.equal({ x: 100, y: 200, width: 50, @@ -77,12 +65,11 @@ describe('window commands', function () { }) describe('isWindowVisible()', function () { - it('returns true when the window is visible, false otherwise', function () { - return app.client - .hideWindow() - .isWindowVisible().should.eventually.be.false - .showWindow() - .isWindowVisible().should.eventually.be.true + it.only('returns true when the window is visible, false otherwise', function () { + return app.browserWindow.hide() + .browserWindow.isVisible().should.eventually.be.false + .browserWindow.show() + .browserWindow.isVisible().should.eventually.be.true }) }) From 1f4bae1711623e0e869db10ea4b935eb31d96617 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 18:18:40 -0700 Subject: [PATCH 14/80] Reuse ivar --- lib/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api.js b/lib/api.js index 6ac996ce1..57ab6ea00 100644 --- a/lib/api.js +++ b/lib/api.js @@ -24,7 +24,7 @@ Api.prototype.transferPromiseness = function (target, promise) { }) var browserWindow = promise.browserWindow - Object.keys(promise.browserWindow).forEach(function (name) { + Object.keys(browserWindow).forEach(function (name) { target.browserWindow[name] = browserWindow[name].bind(promise) }) } From a3904e06d770369f295f2069cbaadc78744eec4b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 18:19:05 -0700 Subject: [PATCH 15/80] Remove duplicate object setting --- lib/api.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/api.js b/lib/api.js index 57ab6ea00..75ee30156 100644 --- a/lib/api.js +++ b/lib/api.js @@ -33,7 +33,6 @@ Api.prototype.initialize = function () { var self = this return this.load(self.app).then(getResponseValue).then(function (api) { self.app.electron = {} - self.app.browserWindow = {} self.add(self.app.electron, [], api.electron) self.addBrowserWindowApis(api.browserWindow) From 549556edee5684649b066de4ec3801209a462ba0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 18:24:38 -0700 Subject: [PATCH 16/80] Convert more specs --- test/commands-test.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/commands-test.js b/test/commands-test.js index 692bb3004..5e7cde8a5 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -7,7 +7,7 @@ var it = global.it var before = global.before var after = global.after -describe('window commands', function () { +describe.only('window commands', function () { helpers.setupTimeout(this) var app = null @@ -65,7 +65,7 @@ describe('window commands', function () { }) describe('isWindowVisible()', function () { - it.only('returns true when the window is visible, false otherwise', function () { + it('returns true when the window is visible, false otherwise', function () { return app.browserWindow.hide() .browserWindow.isVisible().should.eventually.be.false .browserWindow.show() @@ -81,7 +81,7 @@ describe('window commands', function () { describe('isWindowFullScreen()', function () { it('returns false when the window is not in full screen mode', function () { - return app.client.isWindowFullScreen().should.eventually.be.false + return app.client.browserWindow.isFullScreen().should.eventually.be.false }) }) @@ -94,24 +94,24 @@ describe('window commands', function () { describe('isWindowMaximized()', function () { it('returns true when the window is maximized, false otherwise', function () { - return app.client.isWindowMaximized().should.eventually.be.false - .maximizeWindow().waitUntil(function () { + return app.browserWindow.isMaximized().should.eventually.be.false + .browserWindow.maximize().waitUntil(function () { // FIXME window maximized state is never true on CI if (process.env.CI) return Promise.resolve(true) - return this.isWindowMaximized() + return this.browserWindow.isMaximized() }, 5000).then(function () { }) }) }) describe('isWindowMinimized()', function () { it('returns true when the window is minimized, false otherwise', function () { - return app.client.isWindowMinimized().should.eventually.be.false - .minimizeWindow().waitUntil(function () { + return app.browserWindow.isMinimized().should.eventually.be.false + .browserWindow.minimize().waitUntil(function () { // FIXME window minimized state is never true on CI if (process.env.CI) return Promise.resolve(true) - return this.isWindowMinimized() + return this.browserWindow.isMinimized() }, 5000).then(function () { }) }) }) From e006516821ccc8174cffd7657d0f9b7c2c72721b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 18:25:57 -0700 Subject: [PATCH 17/80] Convert more tests --- test/commands-test.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/test/commands-test.js b/test/commands-test.js index 5e7cde8a5..9164f7b6d 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -140,10 +140,9 @@ describe.only('window commands', function () { it('returns true when the document is edited', function () { if (process.platform !== 'darwin') return - return app.client - .isDocumentEdited().should.eventually.be.false - .setDocumentEdited(true) - .isDocumentEdited().should.eventually.be.true + return app.browserWindow.isDocumentEdited().should.eventually.be.false + .browserWindow.setDocumentEdited(true) + .browserWindow.isDocumentEdited().should.eventually.be.true }) }) @@ -151,10 +150,9 @@ describe.only('window commands', function () { it('returns the represented filename', function () { if (process.platform !== 'darwin') return - return app.client - .getRepresentedFilename().should.eventually.equal('') - .setRepresentedFilename('/foo.js') - .getRepresentedFilename().should.eventually.equal('/foo.js') + return app.browserWindow.getRepresentedFilename().should.eventually.equal('') + .browserWindow.setRepresentedFilename('/foo.js') + .browserWindow.getRepresentedFilename().should.eventually.equal('/foo.js') }) }) From 024a3828c52958322943d662775ff7e34d3be0b9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 21 Apr 2016 18:32:46 -0700 Subject: [PATCH 18/80] Add initial webContents API --- lib/api.js | 49 ++++++++++++++++++++++++++++++++++++++++++- test/commands-test.js | 10 ++++----- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/lib/api.js b/lib/api.js index 75ee30156..085e6fc63 100644 --- a/lib/api.js +++ b/lib/api.js @@ -10,6 +10,7 @@ Api.prototype.transferPromiseness = function (target, promise) { target.electron = {} target.browserWindow = {} + target.webContents = {} Object.keys(this.commands).forEach(function (command) { var apiPath = self.commands[command] @@ -35,6 +36,7 @@ Api.prototype.initialize = function () { self.app.electron = {} self.add(self.app.electron, [], api.electron) self.addBrowserWindowApis(api.browserWindow) + self.addWebContentsApis(api.webContents) // Add electron property to client prototype so promises can be chained var clientPrototype = Object.getPrototypeOf(self.app.client) @@ -49,7 +51,18 @@ Api.prototype.initialize = function () { }) return api } - }); + }) + + Object.defineProperty(clientPrototype, 'webContents', { + get: function () { + var api = {} + var client = this + Object.keys(self.app.webContents).forEach(function (key) { + api[key] = client['webContents.' + key].bind(client) + }) + return api + } + }) }) } @@ -93,6 +106,16 @@ Api.prototype.load = function (app) { } } + function addWebContents (api) { + var webContents = electron.remote.getCurrentWindow().webContents + for (var name in webContents) { + var value = webContents[name] + if (typeof value === 'function') { + api[name] = 'function' + } + } + } + var api = { electron: {}, browserWindow: {}, @@ -102,6 +125,7 @@ Api.prototype.load = function (app) { addProperties(electron, api.electron) addProperties(electron.remote, api.electron.remote) addBrowserWindow(api.browserWindow) + addWebContents(api.webContents) return api }) @@ -150,6 +174,29 @@ Api.prototype.addBrowserWindowApis = function (api) { }) } +Api.prototype.addWebContentsApis = function (api) { + var app = this.app + app.webContents = {} + + Object.keys(api).forEach(function (name) { + var commandName = 'webContents.' + name + + app.client.addCommand(commandName, function () { + var args = Array.prototype.slice.call(arguments) + return this.execute(callWebContentsApi, name, args).then(getResponseValue) + }) + + app.webContents[name] = function () { + return app.client[commandName].apply(app.client, arguments) + } + }) +} + +function callWebContentsApi (name, args) { + var webContents = require('electron').remote.getCurrentWindow().webContents + return webContents[name].apply(webContents, args) +} + function callBrowserWindowApi (name, args) { var window = require('electron').remote.getCurrentWindow() return window[name].apply(window, args) diff --git a/test/commands-test.js b/test/commands-test.js index 9164f7b6d..1ddce2392 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -7,7 +7,7 @@ var it = global.it var before = global.before var after = global.after -describe.only('window commands', function () { +describe('window commands', function () { helpers.setupTimeout(this) var app = null @@ -124,13 +124,13 @@ describe.only('window commands', function () { }) describe('paste()', function () { - it('pastes the text into the focused element', function () { + it.only('pastes the text into the focused element', function () { return app.client .getText('textarea').should.eventually.equal('') - .setClipboardText('pasta') - .getClipboardText().should.eventually.equal('pasta') + .electron.clipboard.writeText('pasta') + .electron.clipboard.readText().should.eventually.equal('pasta') .click('textarea') - .paste() + .webContents.paste() .waitForValue('textarea', 5000) .getValue('textarea').should.eventually.equal('pasta') }) From 081c416c46def63698411545b738b93e311c05c7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 09:21:59 -0700 Subject: [PATCH 19/80] Use getCurrentWebContents() api --- lib/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api.js b/lib/api.js index 085e6fc63..c8bf4b56a 100644 --- a/lib/api.js +++ b/lib/api.js @@ -107,7 +107,7 @@ Api.prototype.load = function (app) { } function addWebContents (api) { - var webContents = electron.remote.getCurrentWindow().webContents + var webContents = electron.remote.getCurrentWebContents() for (var name in webContents) { var value = webContents[name] if (typeof value === 'function') { From 096f995ed15c2e041ed9b2c8c54d0b2f9cb88688 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 10:37:44 -0700 Subject: [PATCH 20/80] Transfer more of api over promises --- lib/api.js | 222 +++++++++++++++++++++++++----------------- test/commands-test.js | 5 +- 2 files changed, 135 insertions(+), 92 deletions(-) diff --git a/lib/api.js b/lib/api.js index c8bf4b56a..fb021a8b9 100644 --- a/lib/api.js +++ b/lib/api.js @@ -3,38 +3,11 @@ function Api (app) { this.commands = {} } -Api.prototype.transferPromiseness = function (target, promise) { - var self = this - - self.app.client.transferPromiseness(target, promise) - - target.electron = {} - target.browserWindow = {} - target.webContents = {} - - Object.keys(this.commands).forEach(function (command) { - var apiPath = self.commands[command] - var api = target.electron - - apiPath.slice(0, -1).forEach(function (segment) { - if (!api[segment]) api[segment] = {} - api = api[segment] - }) - - api[apiPath[apiPath.length - 1]] = target[command].bind(target) - }) - - var browserWindow = promise.browserWindow - Object.keys(browserWindow).forEach(function (name) { - target.browserWindow[name] = browserWindow[name].bind(promise) - }) -} - Api.prototype.initialize = function () { var self = this - return this.load(self.app).then(getResponseValue).then(function (api) { - self.app.electron = {} - self.add(self.app.electron, [], api.electron) + return this.load(self.app).then(function (api) { + self.addRenderProcessApis(api.render) + self.addMainProcessApis(api.main) self.addBrowserWindowApis(api.browserWindow) self.addWebContentsApis(api.webContents) @@ -44,23 +17,23 @@ Api.prototype.initialize = function () { Object.defineProperty(clientPrototype, 'browserWindow', { get: function () { - var api = {} + var browserWindow = {} var client = this Object.keys(self.app.browserWindow).forEach(function (key) { - api[key] = client['browserWindow.' + key].bind(client) + browserWindow[key] = client[api.browserWindow[key]].bind(client) }) - return api + return browserWindow } }) Object.defineProperty(clientPrototype, 'webContents', { get: function () { - var api = {} + var webContents = {} var client = this Object.keys(self.app.webContents).forEach(function (key) { - api[key] = client['webContents.' + key].bind(client) + webContents[key] = client[api.webContents[key]].bind(client) }) - return api + return webContents } }) }) @@ -70,8 +43,16 @@ Api.prototype.load = function (app) { return app.client.execute(function () { var electron = require('electron') + var api = { + render: {}, + main: {}, + browserWindow: {}, + webContents: {} + } + function ignoreModule (moduleName) { switch (moduleName) { + case 'CallbacksRegistry': case 'deprecate': case 'deprecations': case 'hideInternalModules': @@ -80,79 +61,117 @@ Api.prototype.load = function (app) { return false } - function addProperties (parent, api) { - Object.getOwnPropertyNames(parent).forEach(function (key) { - if (ignoreModule(key)) return + function ignoreApi (apiName) { + switch (apiName) { + case 'prototype': + return true + default: + return apiName[0] === '_' + } + } - var module = parent[key] - api[key] = {} + function addModule (parent, parentName, name, api) { + api[name] = {} + Object.getOwnPropertyNames(parent[name]).forEach(function (key) { + if (ignoreApi(key)) return + var value = parent[name][key] + if (typeof value === 'function') { + api[name][key] = parentName + '.' + name + '.' + key + } + }) + } - Object.getOwnPropertyNames(module).forEach(function (moduleKey) { - var value = module[moduleKey] - if (typeof value === 'function') { - api[key][moduleKey] = 'function' - } - }) + function addRenderProcessModules () { + Object.getOwnPropertyNames(electron).forEach(function (key) { + if (ignoreModule(key)) return + if (key === 'remote') return + addModule(electron, 'electron', key, api.render) }) } - function addBrowserWindow (api) { + function addMainProcessModules () { + Object.getOwnPropertyNames(electron.remote).forEach(function (key) { + if (ignoreModule(key)) return + addModule(electron.remote, 'electron.remote', key, api.main) + }) + } + + function addBrowserWindow () { var currentWindow = electron.remote.getCurrentWindow() for (var name in currentWindow) { var value = currentWindow[name] if (typeof value === 'function') { - api[name] = 'function' + api.browserWindow[name] = 'browserWindow.' + name } } } - function addWebContents (api) { + function addWebContents () { var webContents = electron.remote.getCurrentWebContents() for (var name in webContents) { var value = webContents[name] if (typeof value === 'function') { - api[name] = 'function' + api.webContents[name] = 'webContents.' + name } } } - var api = { - electron: {}, - browserWindow: {}, - webContents: {} - } - - addProperties(electron, api.electron) - addProperties(electron.remote, api.electron.remote) - addBrowserWindow(api.browserWindow) - addWebContents(api.webContents) + addRenderProcessModules() + addMainProcessModules() + addBrowserWindow() + addWebContents() return api + }).then(getResponseValue) +} + +Api.prototype.addRenderProcessApis = function (api) { + var self = this + var app = self.app + var electron = {} + app.electron = electron + + Object.keys(api).forEach(function (moduleName) { + electron[moduleName] = {} + var moduleApi = api[moduleName] + + Object.keys(moduleApi).forEach(function (key) { + var commandName = moduleApi[key] + + app.client.addCommand(commandName, function () { + var args = Array.prototype.slice.call(arguments) + return this.execute(callRenderApi, moduleName, key, args).then(getResponseValue) + }) + + electron[moduleName][key] = function () { + return app.client[commandName].apply(app.client, arguments) + } + }) }) } -Api.prototype.add = function (parent, parentSegments, api) { +Api.prototype.addMainProcessApis = function (api) { var self = this var app = self.app + var remote = {} + app.electron.remote = remote - Object.keys(api).forEach(function (key) { - var segments = parentSegments.concat(key) - var commandName = 'electron.' + segments.join('.') - var value = api[key] + Object.keys(api).forEach(function (moduleName) { + remote[moduleName] = {} + var moduleApi = api[moduleName] + + Object.keys(moduleApi).forEach(function (key) { + var commandName = moduleApi[key] - if (value === 'function') { - self.commands[commandName] = segments app.client.addCommand(commandName, function () { var args = Array.prototype.slice.call(arguments) - return this.execute(callApi, segments, args).then(getResponseValue) + return this.execute(callMainApi, moduleName, key, args).then(getResponseValue) }) - parent[key] = function () { + + remote[moduleName][key] = function () { return app.client[commandName].apply(app.client, arguments) } - } else { - parent[key] = {} - self.add(parent[key], segments, value) - } + }) }) } @@ -161,7 +180,7 @@ Api.prototype.addBrowserWindowApis = function (api) { app.browserWindow = {} Object.keys(api).forEach(function (name) { - var commandName = 'browserWindow.' + name + var commandName = api[name] app.client.addCommand(commandName, function () { var args = Array.prototype.slice.call(arguments) @@ -179,7 +198,7 @@ Api.prototype.addWebContentsApis = function (api) { app.webContents = {} Object.keys(api).forEach(function (name) { - var commandName = 'webContents.' + name + var commandName = api[name] app.client.addCommand(commandName, function () { var args = Array.prototype.slice.call(arguments) @@ -192,8 +211,44 @@ Api.prototype.addWebContentsApis = function (api) { }) } +Api.prototype.transferPromiseness = function (target, promise) { + this.app.client.transferPromiseness(target, promise) + + var addProperties = function (source, target, moduleName) { + var api = source[moduleName] + target[moduleName] = {} + Object.keys(api).forEach(function (name) { + target[moduleName][name] = api[name].bind(source) + }) + } + + addProperties(promise, target, 'webContents') + addProperties(promise, target, 'browserWindow') + + target.electron = {} + Object.keys(promise.electron).forEach(function (moduleName) { + if (moduleName === 'remote') return + addProperties(promise.electron, target.electron, moduleName) + }) + + target.electron.remote = {} + Object.keys(promise.electron.remote).forEach(function (moduleName) { + addProperties(promise.electron.remote, target.electron.remote, moduleName) + }) +} + +function callRenderApi (moduleName, api, args) { + var module = require('electron')[moduleName] + return module[api].apply(module, args) +} + +function callMainApi (moduleName, api, args) { + var module = require('electron').remote[moduleName] + return module[api].apply(module, args) +} + function callWebContentsApi (name, args) { - var webContents = require('electron').remote.getCurrentWindow().webContents + var webContents = require('electron').remote.getCurrentWebContents() return webContents[name].apply(webContents, args) } @@ -202,19 +257,6 @@ function callBrowserWindowApi (name, args) { return window[name].apply(window, args) } -function callApi (segments, args) { - var api = require('electron') - - segments.forEach(function (segment, index) { - api = api[segment] - if (api === 'function' && index < segments.length - 1) { - api = api() - } - }) - - return api.apply(api, args) -} - function getResponseValue (response) { return response.value } diff --git a/test/commands-test.js b/test/commands-test.js index 1ddce2392..2d31b20dd 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -118,13 +118,14 @@ describe('window commands', function () { describe('selectAll()', function () { it('selects all the text on the page', function () { - return app.client.selectAll() + return app.client.getSelectedText().should.eventually.equal('') + .webContents.selectAll() .getSelectedText().should.eventually.contain('Hello') }) }) describe('paste()', function () { - it.only('pastes the text into the focused element', function () { + it('pastes the text into the focused element', function () { return app.client .getText('textarea').should.eventually.equal('') .electron.clipboard.writeText('pasta') From 88a860e31badd8963643deb5febb3fdd9da69b44 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 10:38:50 -0700 Subject: [PATCH 21/80] Access loading state from webContents --- test/commands-test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/commands-test.js b/test/commands-test.js index 2d31b20dd..df4ffcf09 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -60,7 +60,7 @@ describe('window commands', function () { describe('isWindowFocused()', function () { it('returns true when the current window is focused', function () { - return app.client.isWindowFocused().should.eventually.be.true + return app.browserWindow.isFocused().should.eventually.be.true }) }) @@ -75,7 +75,7 @@ describe('window commands', function () { describe('isWindowDevToolsOpened()', function () { it('returns false when the dev tools are closed', function () { - return app.client.isWindowDevToolsOpened().should.eventually.be.false + return app.browserWindow.isDevToolsOpened().should.eventually.be.false }) }) @@ -88,7 +88,7 @@ describe('window commands', function () { describe('waitUntilWindowLoaded()', function () { it('waits until the current window is loaded', function () { return app.client.waitUntilWindowLoaded() - .isWindowLoading().should.eventually.be.false + .webContents.isLoading().should.eventually.be.false }) }) From 0c5a5272bfe8463953ccde4eff91d0d584fc6c9e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 10:48:08 -0700 Subject: [PATCH 22/80] Use remote.app to get path --- test/commands-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/commands-test.js b/test/commands-test.js index df4ffcf09..a67b1ecf9 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -159,7 +159,7 @@ describe('window commands', function () { describe('getAppPath', function () { it('returns the path for the given name', function () { - return app.client.getAppPath('temp').then(function (tempPath) { + return app.electron.remote.app.getPath('temp').then(function (tempPath) { return path.resolve(tempPath) }).should.eventually.equal(temp.dir) }) From 1d134c8ee4899d62c7e0c8236aa00fc7a6d3d6e7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 10:50:15 -0700 Subject: [PATCH 23/80] Remove unused object --- lib/api.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/api.js b/lib/api.js index fb021a8b9..fe44f3d62 100644 --- a/lib/api.js +++ b/lib/api.js @@ -1,6 +1,5 @@ function Api (app) { this.app = app - this.commands = {} } Api.prototype.initialize = function () { From 21fab125cab327b58cafcd3ccf556a3d07b60a69 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 10:52:50 -0700 Subject: [PATCH 24/80] :art: --- lib/api.js | 57 +++++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/lib/api.js b/lib/api.js index fe44f3d62..3cca601dc 100644 --- a/lib/api.js +++ b/lib/api.js @@ -9,32 +9,7 @@ Api.prototype.initialize = function () { self.addMainProcessApis(api.main) self.addBrowserWindowApis(api.browserWindow) self.addWebContentsApis(api.webContents) - - // Add electron property to client prototype so promises can be chained - var clientPrototype = Object.getPrototypeOf(self.app.client) - clientPrototype.electron = self.app.electron - - Object.defineProperty(clientPrototype, 'browserWindow', { - get: function () { - var browserWindow = {} - var client = this - Object.keys(self.app.browserWindow).forEach(function (key) { - browserWindow[key] = client[api.browserWindow[key]].bind(client) - }) - return browserWindow - } - }) - - Object.defineProperty(clientPrototype, 'webContents', { - get: function () { - var webContents = {} - var client = this - Object.keys(self.app.webContents).forEach(function (key) { - webContents[key] = client[api.webContents[key]].bind(client) - }) - return webContents - } - }) + self.addClientProperties() }) } @@ -124,6 +99,36 @@ Api.prototype.load = function (app) { }).then(getResponseValue) } +Api.prototype.addClientProperties = function () { + var self = this + + // Add electron property to client prototype so promises can be chained + var clientPrototype = Object.getPrototypeOf(self.app.client) + clientPrototype.electron = self.app.electron + + Object.defineProperty(clientPrototype, 'browserWindow', { + get: function () { + var browserWindow = {} + var client = this + Object.keys(self.app.browserWindow).forEach(function (key) { + browserWindow[key] = client[api.browserWindow[key]].bind(client) + }) + return browserWindow + } + }) + + Object.defineProperty(clientPrototype, 'webContents', { + get: function () { + var webContents = {} + var client = this + Object.keys(self.app.webContents).forEach(function (key) { + webContents[key] = client[api.webContents[key]].bind(client) + }) + return webContents + } + }) +} + Api.prototype.addRenderProcessApis = function (api) { var self = this var app = self.app From 026dda582ed6ea626100aa7068e49ed52d00a8cc Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 11:02:37 -0700 Subject: [PATCH 25/80] Expose electron.remote.process --- lib/api.js | 13 +++++++++---- test/application-test.js | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/api.js b/lib/api.js index 3cca601dc..41b890e19 100644 --- a/lib/api.js +++ b/lib/api.js @@ -9,7 +9,7 @@ Api.prototype.initialize = function () { self.addMainProcessApis(api.main) self.addBrowserWindowApis(api.browserWindow) self.addWebContentsApis(api.webContents) - self.addClientProperties() + self.addClientProperties(api) }) } @@ -49,7 +49,7 @@ Api.prototype.load = function (app) { Object.getOwnPropertyNames(parent[name]).forEach(function (key) { if (ignoreApi(key)) return var value = parent[name][key] - if (typeof value === 'function') { + if (typeof value === 'function' || Array.isArray(value)) { api[name][key] = parentName + '.' + name + '.' + key } }) @@ -68,6 +68,7 @@ Api.prototype.load = function (app) { if (ignoreModule(key)) return addModule(electron.remote, 'electron.remote', key, api.main) }) + addModule(electron.remote, 'electron.remote', 'process', api.main) } function addBrowserWindow () { @@ -99,7 +100,7 @@ Api.prototype.load = function (app) { }).then(getResponseValue) } -Api.prototype.addClientProperties = function () { +Api.prototype.addClientProperties = function (api) { var self = this // Add electron property to client prototype so promises can be chained @@ -248,7 +249,11 @@ function callRenderApi (moduleName, api, args) { function callMainApi (moduleName, api, args) { var module = require('electron').remote[moduleName] - return module[api].apply(module, args) + if (typeof module[api] === 'function') { + return module[api].apply(module, args) + } else { + return module[api] + } } function callWebContentsApi (name, args) { diff --git a/test/application-test.js b/test/application-test.js index 9093e11c3..d2216569b 100644 --- a/test/application-test.js +++ b/test/application-test.js @@ -52,7 +52,7 @@ describe('application loading', function () { }) it('passes through args to the launched app', function () { - return app.client.getArgv() + return app.electron.remote.process.argv() .should.eventually.contain('--foo') .should.eventually.contain('--bar=baz') }) From 14d363bf75f22d10b13a70712997ab864217cef6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 11:03:47 -0700 Subject: [PATCH 26/80] Access cwd from remote.process --- test/application-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/application-test.js b/test/application-test.js index d2216569b..d2a0c8f90 100644 --- a/test/application-test.js +++ b/test/application-test.js @@ -71,7 +71,7 @@ describe('application loading', function () { }) it('passes through cwd to the launched app', function () { - return app.client.getCwd().should.eventually.equal(path.join(__dirname, 'fixtures')) + return app.electron.remote.process.cwd().should.eventually.equal(path.join(__dirname, 'fixtures')) }) describe('start()', function () { From 05c1088afa4a3028f3e4904cff03c8ed686c85c5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 11:05:56 -0700 Subject: [PATCH 27/80] Add all apis --- lib/api.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/api.js b/lib/api.js index 41b890e19..d4cfcf072 100644 --- a/lib/api.js +++ b/lib/api.js @@ -49,9 +49,7 @@ Api.prototype.load = function (app) { Object.getOwnPropertyNames(parent[name]).forEach(function (key) { if (ignoreApi(key)) return var value = parent[name][key] - if (typeof value === 'function' || Array.isArray(value)) { - api[name][key] = parentName + '.' + name + '.' + key - } + api[name][key] = parentName + '.' + name + '.' + key }) } @@ -244,7 +242,11 @@ Api.prototype.transferPromiseness = function (target, promise) { function callRenderApi (moduleName, api, args) { var module = require('electron')[moduleName] - return module[api].apply(module, args) + if (typeof module[api] === 'function') { + return module[api].apply(module, args) + } else { + return module[api] + } } function callMainApi (moduleName, api, args) { From bfae7e5fe03a95810ff08feb0bee20c69b3ab71b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 11:14:56 -0700 Subject: [PATCH 28/80] Use browserWindow properties for APIs --- test/example-test.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/example-test.js b/test/example-test.js index dba135cd8..3143dc568 100644 --- a/test/example-test.js +++ b/test/example-test.js @@ -22,15 +22,15 @@ describe('example application launch', function () { return helpers.stopApplication(app) }) - it('opens a window', function () { + it.only('opens a window', function () { return app.client.waitUntilWindowLoaded() .getWindowCount().should.eventually.equal(1) - .isWindowMinimized().should.eventually.be.false - .isWindowDevToolsOpened().should.eventually.be.false - .isWindowVisible().should.eventually.be.true - .isWindowFocused().should.eventually.be.true - .getWindowWidth().should.eventually.be.above(0) - .getWindowHeight().should.eventually.be.above(0) + .browserWindow.isMinimized().should.eventually.be.false + .browserWindow.isDevToolsOpened().should.eventually.be.false + .browserWindow.isVisible().should.eventually.be.true + .browserWindow.isFocused().should.eventually.be.true + .browserWindow.getBounds().should.eventually.have.property('width', 800) + .browserWindow.getBounds().should.eventually.have.property('height', 400) }) describe('when the make larger button is clicked', function () { From b1e0401323a5106d256fee6adb8688fa146c15f9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 11:16:14 -0700 Subject: [PATCH 29/80] Remove only --- test/example-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/example-test.js b/test/example-test.js index 3143dc568..c9ae51503 100644 --- a/test/example-test.js +++ b/test/example-test.js @@ -22,7 +22,7 @@ describe('example application launch', function () { return helpers.stopApplication(app) }) - it.only('opens a window', function () { + it('opens a window', function () { return app.client.waitUntilWindowLoaded() .getWindowCount().should.eventually.equal(1) .browserWindow.isMinimized().should.eventually.be.false From 3ccf0a10c7b5fceead290f10d3b9711f336b65fe Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 11:17:36 -0700 Subject: [PATCH 30/80] Use browserWindow for more assertions --- test/example-test.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/example-test.js b/test/example-test.js index c9ae51503..adea1ddcf 100644 --- a/test/example-test.js +++ b/test/example-test.js @@ -36,24 +36,24 @@ describe('example application launch', function () { describe('when the make larger button is clicked', function () { it('increases the window height and width by 10 pixels', function () { return app.client.waitUntilWindowLoaded() - .getWindowHeight().should.eventually.equal(400) - .getWindowWidth().should.eventually.equal(800) + .browserWindow.getBounds().should.eventually.have.property('width', 800) + .browserWindow.getBounds().should.eventually.have.property('height', 400) .click('.btn-make-bigger') .pause(1000) - .getWindowHeight().should.eventually.equal(410) - .getWindowWidth().should.eventually.equal(810) + .browserWindow.getBounds().should.eventually.have.property('width', 810) + .browserWindow.getBounds().should.eventually.have.property('height', 410) }) }) describe('when the make smaller button is clicked', function () { it('decreases the window height and width by 10 pixels', function () { return app.client.waitUntilWindowLoaded() - .getWindowHeight().should.eventually.equal(400) - .getWindowWidth().should.eventually.equal(800) + .browserWindow.getBounds().should.eventually.have.property('width', 800) + .browserWindow.getBounds().should.eventually.have.property('height', 400) .click('.btn-make-smaller') .pause(1000) - .getWindowHeight().should.eventually.equal(390) - .getWindowWidth().should.eventually.equal(790) + .browserWindow.getBounds().should.eventually.have.property('width', 790) + .browserWindow.getBounds().should.eventually.have.property('height', 390) }) }) }) From 8dcf8f5e26f23f863463bffcf65d351750babb4b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 11:57:27 -0700 Subject: [PATCH 31/80] :art: --- lib/api.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/api.js b/lib/api.js index d4cfcf072..7b8ade7dc 100644 --- a/lib/api.js +++ b/lib/api.js @@ -129,8 +129,7 @@ Api.prototype.addClientProperties = function (api) { } Api.prototype.addRenderProcessApis = function (api) { - var self = this - var app = self.app + var app = this.app var electron = {} app.electron = electron @@ -154,8 +153,7 @@ Api.prototype.addRenderProcessApis = function (api) { } Api.prototype.addMainProcessApis = function (api) { - var self = this - var app = self.app + var app = this.app var remote = {} app.electron.remote = remote From 7ddbb835fb8217c8a83ce17e0e9273700c13cd35 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 14:16:29 -0700 Subject: [PATCH 32/80] Add render process helper to application --- lib/api.js | 76 ++++++++++++++++++++++++++++------------ test/application-test.js | 11 +++--- 2 files changed, 59 insertions(+), 28 deletions(-) diff --git a/lib/api.js b/lib/api.js index 7b8ade7dc..fd807bf0b 100644 --- a/lib/api.js +++ b/lib/api.js @@ -5,11 +5,13 @@ function Api (app) { Api.prototype.initialize = function () { var self = this return this.load(self.app).then(function (api) { + self.api = api self.addRenderProcessApis(api.render) self.addMainProcessApis(api.main) self.addBrowserWindowApis(api.browserWindow) self.addWebContentsApis(api.webContents) - self.addClientProperties(api) + self.addProcessApis(api.process) + self.addClientProperties() }) } @@ -18,9 +20,10 @@ Api.prototype.load = function (app) { var electron = require('electron') var api = { - render: {}, - main: {}, browserWindow: {}, + main: {}, + process: {}, + render: {}, webContents: {} } @@ -89,43 +92,45 @@ Api.prototype.load = function (app) { } } + function addProcess () { + for (var name in process) { + if (ignoreApi(name)) continue + api.process[name] = 'process.' + name + } + } + addRenderProcessModules() addMainProcessModules() addBrowserWindow() addWebContents() + addProcess() return api }).then(getResponseValue) } -Api.prototype.addClientProperties = function (api) { +Api.prototype.addClientProperty = function (name) { var self = this - - // Add electron property to client prototype so promises can be chained var clientPrototype = Object.getPrototypeOf(self.app.client) - clientPrototype.electron = self.app.electron - Object.defineProperty(clientPrototype, 'browserWindow', { + Object.defineProperty(clientPrototype, name, { get: function () { - var browserWindow = {} + var api = {} var client = this - Object.keys(self.app.browserWindow).forEach(function (key) { - browserWindow[key] = client[api.browserWindow[key]].bind(client) + Object.keys(self.app[name]).forEach(function (key) { + api[key] = client[self.api[name][key]].bind(client) }) - return browserWindow + return api } }) +} + +Api.prototype.addClientProperties = function () { + Object.getPrototypeOf(this.app.client).electron = this.app.electron + this.addClientProperty('browserWindow') + this.addClientProperty('webContents') + this.addClientProperty('process') - Object.defineProperty(clientPrototype, 'webContents', { - get: function () { - var webContents = {} - var client = this - Object.keys(self.app.webContents).forEach(function (key) { - webContents[key] = client[api.webContents[key]].bind(client) - }) - return webContents - } - }) } Api.prototype.addRenderProcessApis = function (api) { @@ -212,6 +217,24 @@ Api.prototype.addWebContentsApis = function (api) { }) } +Api.prototype.addProcessApis = function (api) { + var app = this.app + app.process = {} + + Object.keys(api).forEach(function (name) { + var commandName = api[name] + + app.client.addCommand(commandName, function () { + var args = Array.prototype.slice.call(arguments) + return this.execute(callProcessApi, name, args).then(getResponseValue) + }) + + app.process[name] = function () { + return app.client[commandName].apply(app.client, arguments) + } + }) +} + Api.prototype.transferPromiseness = function (target, promise) { this.app.client.transferPromiseness(target, promise) @@ -266,6 +289,15 @@ function callBrowserWindowApi (name, args) { return window[name].apply(window, args) } +function callProcessApi (name, args) { + if (typeof process[name] === 'function') { + return process[name].apply(process, args) + } else { + return process[name] + } +} + + function getResponseValue (response) { return response.value } diff --git a/test/application-test.js b/test/application-test.js index d2a0c8f90..d1f6fa8a0 100644 --- a/test/application-test.js +++ b/test/application-test.js @@ -58,14 +58,13 @@ describe('application loading', function () { }) it('passes through env to the launched app', function () { - var getEnv = function () { return process.env } - return app.client.execute(getEnv).then(function (response) { + return app.process.env().then(function (env) { if (process.platform === 'win32') { - assert.equal(response.value.foo, 'BAR') - assert.equal(response.value.hello, 'WORLD') + assert.equal(env.foo, 'BAR') + assert.equal(env.hello, 'WORLD') } else { - assert.equal(response.value.FOO, 'BAR') - assert.equal(response.value.HELLO, 'WORLD') + assert.equal(env.FOO, 'BAR') + assert.equal(env.HELLO, 'WORLD') } }) }) From bead62e7207753c2b6e6fcad9718b7ce4851333a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 14:18:33 -0700 Subject: [PATCH 33/80] :art: --- lib/api.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/api.js b/lib/api.js index fd807bf0b..4c977334b 100644 --- a/lib/api.js +++ b/lib/api.js @@ -130,7 +130,6 @@ Api.prototype.addClientProperties = function () { this.addClientProperty('browserWindow') this.addClientProperty('webContents') this.addClientProperty('process') - } Api.prototype.addRenderProcessApis = function (api) { From 613cb4910991786424215a768da5e0ea9e24e074 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 15:19:54 -0700 Subject: [PATCH 34/80] Consistently transfer client and promise properties --- lib/api.js | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/lib/api.js b/lib/api.js index 4c977334b..73657631d 100644 --- a/lib/api.js +++ b/lib/api.js @@ -5,12 +5,20 @@ function Api (app) { Api.prototype.initialize = function () { var self = this return this.load(self.app).then(function (api) { - self.api = api self.addRenderProcessApis(api.render) self.addMainProcessApis(api.main) self.addBrowserWindowApis(api.browserWindow) self.addWebContentsApis(api.webContents) self.addProcessApis(api.process) + + self.api = { + electron: api.render, + process: api.process, + browserWindow: api.browserWindow, + webContents: api.webContents + } + self.api.electron.remote = api.main + self.addClientProperties() }) } @@ -111,22 +119,20 @@ Api.prototype.load = function (app) { Api.prototype.addClientProperty = function (name) { var self = this - var clientPrototype = Object.getPrototypeOf(self.app.client) + var clientPrototype = Object.getPrototypeOf(self.app.client) Object.defineProperty(clientPrototype, name, { get: function () { - var api = {} var client = this - Object.keys(self.app[name]).forEach(function (key) { - api[key] = client[self.api[name][key]].bind(client) + return transformObject(self.api[name], {}, function (value) { + return client[value].bind(client) }) - return api } }) } Api.prototype.addClientProperties = function () { - Object.getPrototypeOf(this.app.client).electron = this.app.electron + this.addClientProperty('electron') this.addClientProperty('browserWindow') this.addClientProperty('webContents') this.addClientProperty('process') @@ -238,26 +244,28 @@ Api.prototype.transferPromiseness = function (target, promise) { this.app.client.transferPromiseness(target, promise) var addProperties = function (source, target, moduleName) { - var api = source[moduleName] - target[moduleName] = {} - Object.keys(api).forEach(function (name) { - target[moduleName][name] = api[name].bind(source) + target[moduleName] = transformObject(source[moduleName], {}, function (value, parent) { + return value.bind(parent) }) } addProperties(promise, target, 'webContents') addProperties(promise, target, 'browserWindow') + addProperties(promise, target, 'electron') + addProperties(promise, target, 'process') +} - target.electron = {} - Object.keys(promise.electron).forEach(function (moduleName) { - if (moduleName === 'remote') return - addProperties(promise.electron, target.electron, moduleName) - }) - - target.electron.remote = {} - Object.keys(promise.electron.remote).forEach(function (moduleName) { - addProperties(promise.electron.remote, target.electron.remote, moduleName) +function transformObject (input, output, callback) { + Object.keys(input).forEach(function (name) { + var value = input[name] + if (typeof value === 'object') { + output[name] = {} + transformObject(value, output[name], callback) + } else { + output[name] = callback(value, input) + } }) + return output } function callRenderApi (moduleName, api, args) { @@ -296,7 +304,6 @@ function callProcessApi (name, args) { } } - function getResponseValue (response) { return response.value } From 39c2b8ea3f83f86ef50250d7da7c6ab380bb0b9a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 15:30:09 -0700 Subject: [PATCH 35/80] Exercise get/set path on app --- test/commands-test.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/commands-test.js b/test/commands-test.js index a67b1ecf9..f88b0620f 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -1,3 +1,4 @@ +var fs = require('fs') var helpers = require('./global-setup') var path = require('path') var temp = require('temp').track() @@ -159,9 +160,9 @@ describe('window commands', function () { describe('getAppPath', function () { it('returns the path for the given name', function () { - return app.electron.remote.app.getPath('temp').then(function (tempPath) { - return path.resolve(tempPath) - }).should.eventually.equal(temp.dir) + var tempDir = fs.realpathSync(temp.dir) + return app.electron.remote.app.setPath('music', tempDir) + .electron.remote.app.getPath('music').should.eventually.equal(tempDir) }) }) From 1fd094835c918c1da9d085497cda9d0c52a4e5d9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 15:32:20 -0700 Subject: [PATCH 36/80] Add top-level aliases for both processes --- lib/api.js | 12 ++++++++---- test/application-test.js | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/api.js b/lib/api.js index 73657631d..96100e492 100644 --- a/lib/api.js +++ b/lib/api.js @@ -135,7 +135,8 @@ Api.prototype.addClientProperties = function () { this.addClientProperty('electron') this.addClientProperty('browserWindow') this.addClientProperty('webContents') - this.addClientProperty('process') + this.addClientProperty('mainProcess') + this.addClientProperty('rendererProcess') } Api.prototype.addRenderProcessApis = function (api) { @@ -224,7 +225,7 @@ Api.prototype.addWebContentsApis = function (api) { Api.prototype.addProcessApis = function (api) { var app = this.app - app.process = {} + app.rendererProcess = {} Object.keys(api).forEach(function (name) { var commandName = api[name] @@ -234,10 +235,12 @@ Api.prototype.addProcessApis = function (api) { return this.execute(callProcessApi, name, args).then(getResponseValue) }) - app.process[name] = function () { + app.rendererProcess[name] = function () { return app.client[commandName].apply(app.client, arguments) } }) + + app.mainProcess = app.electron.remote.process } Api.prototype.transferPromiseness = function (target, promise) { @@ -252,7 +255,8 @@ Api.prototype.transferPromiseness = function (target, promise) { addProperties(promise, target, 'webContents') addProperties(promise, target, 'browserWindow') addProperties(promise, target, 'electron') - addProperties(promise, target, 'process') + addProperties(promise, target, 'mainProcess') + addProperties(promise, target, 'rendererProcess') } function transformObject (input, output, callback) { diff --git a/test/application-test.js b/test/application-test.js index d1f6fa8a0..e1dac456e 100644 --- a/test/application-test.js +++ b/test/application-test.js @@ -52,13 +52,13 @@ describe('application loading', function () { }) it('passes through args to the launched app', function () { - return app.electron.remote.process.argv() + return app.mainProcess.argv() .should.eventually.contain('--foo') .should.eventually.contain('--bar=baz') }) it('passes through env to the launched app', function () { - return app.process.env().then(function (env) { + return app.rendererProcess.env().then(function (env) { if (process.platform === 'win32') { assert.equal(env.foo, 'BAR') assert.equal(env.hello, 'WORLD') From b9c01139a249a17261d1e5c6e7159aede8046f33 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 15:42:55 -0700 Subject: [PATCH 37/80] Use mainProcess alias in specs --- lib/api.js | 11 ++++++++--- test/application-test.js | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/api.js b/lib/api.js index 96100e492..1b8db672c 100644 --- a/lib/api.js +++ b/lib/api.js @@ -12,9 +12,9 @@ Api.prototype.initialize = function () { self.addProcessApis(api.process) self.api = { - electron: api.render, - process: api.process, browserWindow: api.browserWindow, + electron: api.render, + rendererProcess: api.process, webContents: api.webContents } self.api.electron.remote = api.main @@ -135,8 +135,13 @@ Api.prototype.addClientProperties = function () { this.addClientProperty('electron') this.addClientProperty('browserWindow') this.addClientProperty('webContents') - this.addClientProperty('mainProcess') this.addClientProperty('rendererProcess') + + Object.defineProperty(Object.getPrototypeOf(this.app.client), 'mainProcess', { + get: function () { + return this.electron.remote.process + } + }) } Api.prototype.addRenderProcessApis = function (api) { diff --git a/test/application-test.js b/test/application-test.js index e1dac456e..dffb9214f 100644 --- a/test/application-test.js +++ b/test/application-test.js @@ -70,7 +70,7 @@ describe('application loading', function () { }) it('passes through cwd to the launched app', function () { - return app.electron.remote.process.cwd().should.eventually.equal(path.join(__dirname, 'fixtures')) + return app.mainProcess.cwd().should.eventually.equal(path.join(__dirname, 'fixtures')) }) describe('start()', function () { From a32e1ff554da8029817bbfbfe701e060f9ccb96f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 15:47:14 -0700 Subject: [PATCH 38/80] Remove unused value --- lib/api.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/api.js b/lib/api.js index 1b8db672c..ceb8bd165 100644 --- a/lib/api.js +++ b/lib/api.js @@ -59,7 +59,6 @@ Api.prototype.load = function (app) { api[name] = {} Object.getOwnPropertyNames(parent[name]).forEach(function (key) { if (ignoreApi(key)) return - var value = parent[name][key] api[name][key] = parentName + '.' + name + '.' + key }) } From cd00c6877520bbdb345cc6674c26207172283992 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 15:49:51 -0700 Subject: [PATCH 39/80] Only transfer properties that exist --- lib/api.js | 4 +++- test/application-test.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/api.js b/lib/api.js index ceb8bd165..8c832afcb 100644 --- a/lib/api.js +++ b/lib/api.js @@ -251,7 +251,9 @@ Api.prototype.transferPromiseness = function (target, promise) { this.app.client.transferPromiseness(target, promise) var addProperties = function (source, target, moduleName) { - target[moduleName] = transformObject(source[moduleName], {}, function (value, parent) { + var sourceModule = source[moduleName] + if (!sourceModule) return + target[moduleName] = transformObject(sourceModule, {}, function (value, parent) { return value.bind(parent) }) } diff --git a/test/application-test.js b/test/application-test.js index dffb9214f..463940543 100644 --- a/test/application-test.js +++ b/test/application-test.js @@ -42,7 +42,7 @@ describe('application loading', function () { it('launches the application', function () { return app.client.windowHandles().then(function (response) { assert.equal(response.value.length, 1) - }).getWindowBounds().should.eventually.deep.equal({ + }).browserWindow.getBounds().should.eventually.deep.equal({ x: 25, y: 35, width: 200, From 9dd93df142aa14a60ae8b71184353e37b8da2311 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:06:44 -0700 Subject: [PATCH 40/80] Add API methods directly on remote --- lib/api.js | 31 ++++++++++++++++++++++++++++--- test/application-test.js | 3 +-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/lib/api.js b/lib/api.js index 8c832afcb..90587ea77 100644 --- a/lib/api.js +++ b/lib/api.js @@ -74,7 +74,11 @@ Api.prototype.load = function (app) { function addMainProcessModules () { Object.getOwnPropertyNames(electron.remote).forEach(function (key) { if (ignoreModule(key)) return - addModule(electron.remote, 'electron.remote', key, api.main) + if (typeof electron.remote[key] === 'function') { + api.main[key] = 'electron.remote.' + key + } else { + addModule(electron.remote, 'electron.remote', key, api.main) + } }) addModule(electron.remote, 'electron.remote', 'process', api.main) } @@ -172,7 +176,25 @@ Api.prototype.addMainProcessApis = function (api) { var remote = {} app.electron.remote = remote - Object.keys(api).forEach(function (moduleName) { + 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).then(getResponseValue) + }) + + remote[name] = function () { + return app.client[commandName].apply(app.client, arguments) + } + }) + + + Object.keys(api).filter(function (moduleName) { + return typeof api[moduleName] === 'object' + }).forEach(function (moduleName) { remote[moduleName] = {} var moduleApi = api[moduleName] @@ -288,7 +310,10 @@ function callRenderApi (moduleName, api, args) { } function callMainApi (moduleName, api, args) { - var module = require('electron').remote[moduleName] + var module = require('electron').remote + if (moduleName) { + module = module[moduleName] + } if (typeof module[api] === 'function') { return module[api].apply(module, args) } else { diff --git a/test/application-test.js b/test/application-test.js index 463940543..df0e77d80 100644 --- a/test/application-test.js +++ b/test/application-test.js @@ -156,8 +156,7 @@ describe('application loading', function () { describe('getMainProcessGlobal', function () { it('returns the requested global from the main process', function () { - return app.client - .getMainProcessGlobal('mainProcessGlobal').should.eventually.equal('foo') + return app.electron.remote.getGlobal('mainProcessGlobal').should.eventually.equal('foo') }) }) }) From 8129ad5494c139dd40ffae01b3b61d43bd70ee52 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:17:21 -0700 Subject: [PATCH 41/80] Remove deprecated APIs --- lib/application.js | 8 -------- test/commands-test.js | 16 ---------------- 2 files changed, 24 deletions(-) diff --git a/lib/application.js b/lib/application.js index 07ea9b3e8..77ef61c92 100644 --- a/lib/application.js +++ b/lib/application.js @@ -144,14 +144,6 @@ Application.prototype.initializeClient = function (resolve, reject) { } Application.prototype.addCommands = function () { - // TODO Remove in favor of get/setBounds API - this.client.addCommand('getWindowDimensions', function () { - return this.getWindowBounds() - }) - this.client.addCommand('setWindowDimensions', function (x, y, width, height) { - return this.setWindowBounds({x: x, y: y, width: width, height: height}) - }) - this.client.addCommand('getWindowWidth', function () { return this.getWindowBounds().then(function (bounds) { return bounds.width diff --git a/test/commands-test.js b/test/commands-test.js index f88b0620f..239c96545 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -165,20 +165,4 @@ describe('window commands', function () { .electron.remote.app.getPath('music').should.eventually.equal(tempDir) }) }) - - describe('deprecated APIs', function () { - describe('setWindowDimensions', function () { - it('sets the bounds of the window', function () { - return app.client - .setWindowDimensions(100, 200, 50, 75) - .pause(1000) - .getWindowDimensions().should.eventually.deep.equal({ - x: 100, - y: 200, - width: 50, - height: 75 - }) - }) - }) - }) }) From 15888b611614f203ef8e4405c5d25b1a398c4766 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:20:39 -0700 Subject: [PATCH 42/80] Use new API for app.quit --- lib/application.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/application.js b/lib/application.js index 77ef61c92..eedfc257c 100644 --- a/lib/application.js +++ b/lib/application.js @@ -46,7 +46,7 @@ Application.prototype.stop = function () { if (!self.isRunning()) return Promise.reject(Error('Application not running')) return new Promise(function (resolve, reject) { - self.client.windowByIndex(0).quitApplication().then(function () { + self.client.windowByIndex(0).electron.remote.app.quit().then(function () { setTimeout(function () { self.client.end().then(function () { self.chromeDriver.stop() @@ -173,12 +173,6 @@ Application.prototype.addCommands = function () { }) }) - this.client.addCommand('quitApplication', function () { - return this.execute(function () { - require('electron').remote.app.quit() - }) - }) - this.client.addCommand('getAppPath', function (pathName) { return this.execute(function (pathName) { return require('electron').remote.app.getPath(pathName) From ca383da760bcc29e7e23824d6c5f4e3a6e2e12dd Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:22:30 -0700 Subject: [PATCH 43/80] Remove unused global api wrappers --- lib/application.js | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/lib/application.js b/lib/application.js index eedfc257c..1752713d2 100644 --- a/lib/application.js +++ b/lib/application.js @@ -208,24 +208,6 @@ Application.prototype.addCommands = function () { }).then(getResponseValue) }) - this.client.addCommand('getMainProcessGlobal', function (globalName) { - return this.execute(function (globalName) { - return require('electron').remote.getGlobal(globalName) - }, globalName).then(getResponseValue) - }) - - this.client.addCommand('getArgv', function () { - return this.execute(function () { - return require('electron').remote.getGlobal('process').argv - }).then(getResponseValue) - }) - - this.client.addCommand('getCwd', function () { - return this.execute(function () { - return require('electron').remote.getGlobal('process').cwd() - }).then(getResponseValue) - }) - this.client.addCommand('getClipboardText', function () { return this.execute(function () { return require('electron').clipboard.readText() From d26423de8240d3ebbc303594669ca065f1e3ecb4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:24:55 -0700 Subject: [PATCH 44/80] Remove unused api wrappers --- lib/application.js | 85 ---------------------------------------------- 1 file changed, 85 deletions(-) diff --git a/lib/application.js b/lib/application.js index 1752713d2..e624825a2 100644 --- a/lib/application.js +++ b/lib/application.js @@ -144,24 +144,6 @@ Application.prototype.initializeClient = function (resolve, reject) { } Application.prototype.addCommands = function () { - this.client.addCommand('getWindowWidth', function () { - return this.getWindowBounds().then(function (bounds) { - return bounds.width - }) - }) - - this.client.addCommand('getWindowHeight', function () { - return this.getWindowBounds().then(function (bounds) { - return bounds.height - }) - }) - - this.client.addCommand('setWindowBounds', function (bounds) { - return this.execute(function (bounds) { - require('electron').remote.getCurrentWindow().setBounds(bounds) - }, bounds) - }) - this.client.addCommand('waitUntilTextExists', function (selector, text, timeout) { return this.waitUntil(function () { return this.isExisting(selector).getText(selector).then(function (selectorText) { @@ -173,12 +155,6 @@ Application.prototype.addCommands = function () { }) }) - this.client.addCommand('getAppPath', function (pathName) { - return this.execute(function (pathName) { - return require('electron').remote.app.getPath(pathName) - }, pathName).then(getResponseValue) - }) - this.client.addCommand('waitUntilWindowLoaded', function (timeout) { return this.waitUntil(function () { return this.isWindowLoading().then(function (loading) { @@ -208,30 +184,6 @@ Application.prototype.addCommands = function () { }).then(getResponseValue) }) - this.client.addCommand('getClipboardText', function () { - return this.execute(function () { - return require('electron').clipboard.readText() - }).then(getResponseValue) - }) - - this.client.addCommand('setClipboardText', function (text) { - return this.execute(function (text) { - return require('electron').clipboard.writeText(text) - }, text).then(getResponseValue) - }) - - this.client.addCommand('setDocumentEdited', function (edited) { - return this.execute(function (edited) { - return require('electron').remote.getCurrentWindow().setDocumentEdited(edited) - }, edited).then(getResponseValue) - }) - - this.client.addCommand('setRepresentedFilename', function (filename) { - return this.execute(function (filename) { - return require('electron').remote.getCurrentWindow().setRepresentedFilename(filename) - }, filename).then(getResponseValue) - }) - this.client.addCommand('getRenderProcessLogs', function () { return this.log('browser').then(getResponseValue) }) @@ -242,43 +194,6 @@ Application.prototype.addCommands = function () { self.chromeDriver.clearLogs() return logs }) - - this.client.addCommand('isWindowLoading', function () { - return this.execute(function () { - return require('electron').remote.getCurrentWindow().webContents.isLoading() - }).then(getResponseValue) - }) - - this.addCurrentWindowGetter('getBounds', 'getWindowBounds') - this.addCurrentWindowGetter('isDevToolsOpened', 'isWindowDevToolsOpened') - this.addCurrentWindowGetter('isFocused', 'isWindowFocused') - this.addCurrentWindowGetter('isFullScreen', 'isWindowFullScreen') - this.addCurrentWindowGetter('isMaximized', 'isWindowMaximized') - this.addCurrentWindowGetter('isMinimized', 'isWindowMinimized') - this.addCurrentWindowGetter('isVisible', 'isWindowVisible') - - this.addCurrentWindowGetter('hide', 'hideWindow') - this.addCurrentWindowGetter('maximize', 'maximizeWindow') - this.addCurrentWindowGetter('minimize', 'minimizeWindow') - this.addCurrentWindowGetter('show', 'showWindow') - - this.addCurrentWindowGetter('selectAll', 'selectAll') - this.addCurrentWindowGetter('paste', 'paste') - - this.addCurrentWindowGetter('isDocumentEdited', 'isDocumentEdited') - this.addCurrentWindowGetter('getRepresentedFilename', 'getRepresentedFilename') -} - -Application.prototype.addCurrentWindowGetter = function (methodName, commandName) { - if (!commandName) commandName = methodName - - var currentWindowGetter = function (methodName) { - return require('electron').remote.getCurrentWindow()[methodName]() - } - - this.client.addCommand(commandName, function () { - return this.execute(currentWindowGetter, methodName).then(getResponseValue) - }) } var getResponseValue = function (response) { From f4e76a09b7e3bbc0b08d9cb1e7983a1abc2f455c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:24:58 -0700 Subject: [PATCH 45/80] :art: --- test/commands-test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/commands-test.js b/test/commands-test.js index 239c96545..222c22bd9 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -42,8 +42,7 @@ describe('window commands', function () { describe('setWindowBounds', function () { it('sets the window bounds', function () { - return app.browserWindow - .setBounds({ + return app.browserWindow.setBounds({ x: 100, y: 200, width: 50, From 9edcf9b91a2a69e284865df046c7b6535537944b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:27:16 -0700 Subject: [PATCH 46/80] Remove standard errors --- lib/api.js | 3 +-- test/commands-test.js | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/api.js b/lib/api.js index 90587ea77..18d0a699c 100644 --- a/lib/api.js +++ b/lib/api.js @@ -74,7 +74,7 @@ Api.prototype.load = function (app) { function addMainProcessModules () { Object.getOwnPropertyNames(electron.remote).forEach(function (key) { if (ignoreModule(key)) return - if (typeof electron.remote[key] === 'function') { + if (typeof electron.remote[key] === 'function') { api.main[key] = 'electron.remote.' + key } else { addModule(electron.remote, 'electron.remote', key, api.main) @@ -191,7 +191,6 @@ Api.prototype.addMainProcessApis = function (api) { } }) - Object.keys(api).filter(function (moduleName) { return typeof api[moduleName] === 'object' }).forEach(function (moduleName) { diff --git a/test/commands-test.js b/test/commands-test.js index 222c22bd9..4a628eda3 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -43,18 +43,18 @@ describe('window commands', function () { describe('setWindowBounds', function () { it('sets the window bounds', function () { return app.browserWindow.setBounds({ - x: 100, - y: 200, - width: 50, - height: 75 - }) - .pause(1000) - .browserWindow.getBounds().should.eventually.deep.equal({ - x: 100, - y: 200, - width: 50, - height: 75 - }) + x: 100, + y: 200, + width: 50, + height: 75 + }) + .pause(1000) + .browserWindow.getBounds().should.eventually.deep.equal({ + x: 100, + y: 200, + width: 50, + height: 75 + }) }) }) From 2ffd8def0db9558ee7415cdde6c4c165d7d59745 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:28:08 -0700 Subject: [PATCH 47/80] Use browserWindow.getBounds() --- test/multi-window-test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/multi-window-test.js b/test/multi-window-test.js index 48469854e..b786439cc 100644 --- a/test/multi-window-test.js +++ b/test/multi-window-test.js @@ -6,7 +6,7 @@ var it = global.it var beforeEach = global.beforeEach var afterEach = global.afterEach -describe('multiple windows', function () { +describe.only('multiple windows', function () { helpers.setupTimeout(this) var app = null @@ -25,7 +25,7 @@ describe('multiple windows', function () { return app.client .getWindowCount().should.eventually.equal(2) .windowByIndex(1) - .getWindowBounds().should.eventually.deep.equal({ + .browserWindow.getBounds().should.eventually.deep.equal({ x: 25, y: 35, width: 200, @@ -33,7 +33,7 @@ describe('multiple windows', function () { }) .getTitle().should.eventually.equal('Top') .windowByIndex(0) - .getWindowBounds().should.eventually.deep.equal({ + .browserWindow.getBounds().should.eventually.deep.equal({ x: 25, y: 135, width: 300, From adfb946355897377a070c427c32fadc43617c968 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:34:16 -0700 Subject: [PATCH 48/80] Update spec descriptions --- test/commands-test.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/commands-test.js b/test/commands-test.js index 4a628eda3..2457858f1 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -29,7 +29,7 @@ describe('window commands', function () { }) }) - describe('getWindowBounds', function () { + describe('browserWindow.getBounds()', function () { it('gets the window bounds', function () { return app.browserWindow.getBounds().should.eventually.deep.equal({ x: 25, @@ -40,7 +40,7 @@ describe('window commands', function () { }) }) - describe('setWindowBounds', function () { + describe('browserWindow.setBounds()', function () { it('sets the window bounds', function () { return app.browserWindow.setBounds({ x: 100, @@ -58,13 +58,13 @@ describe('window commands', function () { }) }) - describe('isWindowFocused()', function () { + describe('browserWindow.isFocused()', function () { it('returns true when the current window is focused', function () { return app.browserWindow.isFocused().should.eventually.be.true }) }) - describe('isWindowVisible()', function () { + describe('browserWindow.isVisible()', function () { it('returns true when the window is visible, false otherwise', function () { return app.browserWindow.hide() .browserWindow.isVisible().should.eventually.be.false @@ -73,13 +73,13 @@ describe('window commands', function () { }) }) - describe('isWindowDevToolsOpened()', function () { + describe('browserWindow.isDevToolsOpened()', function () { it('returns false when the dev tools are closed', function () { return app.browserWindow.isDevToolsOpened().should.eventually.be.false }) }) - describe('isWindowFullScreen()', function () { + describe('browserWindow.isFullScreen()', function () { it('returns false when the window is not in full screen mode', function () { return app.client.browserWindow.isFullScreen().should.eventually.be.false }) @@ -92,7 +92,7 @@ describe('window commands', function () { }) }) - describe('isWindowMaximized()', function () { + describe('browserWindow.isMaximized()', function () { it('returns true when the window is maximized, false otherwise', function () { return app.browserWindow.isMaximized().should.eventually.be.false .browserWindow.maximize().waitUntil(function () { @@ -104,7 +104,7 @@ describe('window commands', function () { }) }) - describe('isWindowMinimized()', function () { + describe('browserWindow.isMinimized()', function () { it('returns true when the window is minimized, false otherwise', function () { return app.browserWindow.isMinimized().should.eventually.be.false .browserWindow.minimize().waitUntil(function () { @@ -116,7 +116,7 @@ describe('window commands', function () { }) }) - describe('selectAll()', function () { + describe('webContents.selectAll()', function () { it('selects all the text on the page', function () { return app.client.getSelectedText().should.eventually.equal('') .webContents.selectAll() @@ -124,7 +124,7 @@ describe('window commands', function () { }) }) - describe('paste()', function () { + describe('webContents.paste()', function () { it('pastes the text into the focused element', function () { return app.client .getText('textarea').should.eventually.equal('') @@ -137,7 +137,7 @@ describe('window commands', function () { }) }) - describe('isDocumentEdited', function () { + describe('browserWindow.isDocumentEdited()', function () { it('returns true when the document is edited', function () { if (process.platform !== 'darwin') return @@ -147,7 +147,7 @@ describe('window commands', function () { }) }) - describe('getRepresentedFilename', function () { + describe('browserWindow.getRepresentedFilename()', function () { it('returns the represented filename', function () { if (process.platform !== 'darwin') return @@ -157,7 +157,7 @@ describe('window commands', function () { }) }) - describe('getAppPath', function () { + describe('electron.remote.app.getPath()', function () { it('returns the path for the given name', function () { var tempDir = fs.realpathSync(temp.dir) return app.electron.remote.app.setPath('music', tempDir) From 58b04da090c3e47130c4e0bd45f3a5e0792f2f94 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:37:35 -0700 Subject: [PATCH 49/80] Remove .only call --- test/multi-window-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/multi-window-test.js b/test/multi-window-test.js index b786439cc..41756d939 100644 --- a/test/multi-window-test.js +++ b/test/multi-window-test.js @@ -6,7 +6,7 @@ var it = global.it var beforeEach = global.beforeEach var afterEach = global.afterEach -describe.only('multiple windows', function () { +describe('multiple windows', function () { helpers.setupTimeout(this) var app = null From a575ebe8748f7673b956be09a0d35fd6dc98ba20 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:41:07 -0700 Subject: [PATCH 50/80] Add helper to write detected API as JSON --- .gitignore | 1 + lib/api.js | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index 93f136199..9f42f5f7b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules npm-debug.log +lib/api.json diff --git a/lib/api.js b/lib/api.js index 18d0a699c..3f6efda04 100644 --- a/lib/api.js +++ b/lib/api.js @@ -286,6 +286,13 @@ Api.prototype.transferPromiseness = function (target, promise) { 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) +} + function transformObject (input, output, callback) { Object.keys(input).forEach(function (name) { var value = input[name] From e906d144cfb9f7d856ce9f3ceb52f38d5b246bf4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:42:35 -0700 Subject: [PATCH 51/80] Check ignored browserWindow/webContents APIs --- lib/api.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/api.js b/lib/api.js index 3f6efda04..2b8bf1bbe 100644 --- a/lib/api.js +++ b/lib/api.js @@ -86,6 +86,7 @@ Api.prototype.load = function (app) { function addBrowserWindow () { var currentWindow = electron.remote.getCurrentWindow() for (var name in currentWindow) { + if (ignoreApi(name)) continue var value = currentWindow[name] if (typeof value === 'function') { api.browserWindow[name] = 'browserWindow.' + name @@ -96,6 +97,7 @@ Api.prototype.load = function (app) { function addWebContents () { var webContents = electron.remote.getCurrentWebContents() for (var name in webContents) { + if (ignoreApi(name)) continue var value = webContents[name] if (typeof value === 'function') { api.webContents[name] = 'webContents.' + name From fc8c197929c499a15a251b1da3f9bf0e549d4101 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 16:46:29 -0700 Subject: [PATCH 52/80] Use forin for module apis --- lib/api.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/api.js b/lib/api.js index 2b8bf1bbe..c5c1fa959 100644 --- a/lib/api.js +++ b/lib/api.js @@ -57,10 +57,10 @@ Api.prototype.load = function (app) { function addModule (parent, parentName, name, api) { api[name] = {} - Object.getOwnPropertyNames(parent[name]).forEach(function (key) { - if (ignoreApi(key)) return + for (var key in parent[name]) { + if (ignoreApi(key)) continue api[name][key] = parentName + '.' + name + '.' + key - }) + } } function addRenderProcessModules () { From 285e3132cc210f08af89ec9c4444210bc400621b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 17:00:20 -0700 Subject: [PATCH 53/80] Whitelist BrowserWindow, Menu, and MenuItem as objects --- lib/api.js | 12 +++++++++++- test/commands-test.js | 4 ++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/api.js b/lib/api.js index c5c1fa959..036ffafb0 100644 --- a/lib/api.js +++ b/lib/api.js @@ -46,6 +46,16 @@ Api.prototype.load = function (app) { return false } + function isRemoteFunction (name) { + switch (name) { + case 'BrowserWindow': + case 'Menu': + case 'MenuItem': + return false + } + return typeof electron.remote[name] === 'function' + } + function ignoreApi (apiName) { switch (apiName) { case 'prototype': @@ -74,7 +84,7 @@ Api.prototype.load = function (app) { function addMainProcessModules () { Object.getOwnPropertyNames(electron.remote).forEach(function (key) { if (ignoreModule(key)) return - if (typeof electron.remote[key] === 'function') { + if (isRemoteFunction(key)) { api.main[key] = 'electron.remote.' + key } else { addModule(electron.remote, 'electron.remote', key, api.main) diff --git a/test/commands-test.js b/test/commands-test.js index 2457858f1..aea57bae4 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -164,4 +164,8 @@ describe('window commands', function () { .electron.remote.app.getPath('music').should.eventually.equal(tempDir) }) }) + + it('exposes properties on constructor APIs', function () { + return app.electron.remote.MenuItem.types().should.eventually.include('normal') + }) }) From 50f989c6519913aaa0cd685b73b074d2a831804c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 17:06:15 -0700 Subject: [PATCH 54/80] Ignore Tray module --- lib/api.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/api.js b/lib/api.js index 036ffafb0..21b395d13 100644 --- a/lib/api.js +++ b/lib/api.js @@ -41,6 +41,7 @@ Api.prototype.load = function (app) { case 'deprecate': case 'deprecations': case 'hideInternalModules': + case 'Tray': return true } return false From 4c1ca001fc36c5ca72d8f12297d80a355f5465aa Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 17:09:39 -0700 Subject: [PATCH 55/80] Add global shortcut spec --- test/commands-test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/commands-test.js b/test/commands-test.js index aea57bae4..4f44e64a4 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -168,4 +168,10 @@ describe('window commands', function () { it('exposes properties on constructor APIs', function () { return app.electron.remote.MenuItem.types().should.eventually.include('normal') }) + + describe('globalShortcut.isRegistered()', function () { + it('returns false if the shortcut is not registered', function () { + return app.electron.remote.globalShortcut.isRegistered('CommandOrControl+X').should.eventually.be.false + }) + }) }) From eff630eea3c63b23e87ff9dbef1536ab8336d0a3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 25 Apr 2016 17:14:08 -0700 Subject: [PATCH 56/80] Add spec for process.versions.electron --- test/commands-test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/commands-test.js b/test/commands-test.js index 4f44e64a4..75fbb8daa 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -174,4 +174,10 @@ describe('window commands', function () { return app.electron.remote.globalShortcut.isRegistered('CommandOrControl+X').should.eventually.be.false }) }) + + describe('rendererProcess.versions', function () { + it('includes the Electron version', function () { + return app.rendererProcess.versions().should.eventually.have.property('electron').and.not.be.empty + }) + }) }) From 658fa693104fb7e6d7dbdd8355b22a64fa6eaab6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 10:24:26 -0700 Subject: [PATCH 57/80] Add screen api test --- test/commands-test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/commands-test.js b/test/commands-test.js index 75fbb8daa..f7b3706e9 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -180,4 +180,10 @@ describe('window commands', function () { return app.rendererProcess.versions().should.eventually.have.property('electron').and.not.be.empty }) }) + + describe('electron.screen.getPrimaryDisplay()', function () { + it('returns information about the primary display', function () { + return app.electron.screen.getPrimaryDisplay().should.eventually.have.property('workArea').and.not.be.empty + }) + }) }) From 3bc6c30fb159a279a0a722ad0104f08d3a3a01b9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 10:25:46 -0700 Subject: [PATCH 58/80] Add webFrame.getZoomFactor spec --- test/commands-test.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/commands-test.js b/test/commands-test.js index f7b3706e9..ce8cae50e 100644 --- a/test/commands-test.js +++ b/test/commands-test.js @@ -186,4 +186,11 @@ describe('window commands', function () { return app.electron.screen.getPrimaryDisplay().should.eventually.have.property('workArea').and.not.be.empty }) }) + + describe('electron.webFrame.getZoomFactor()', function () { + it('returns information about the primary display', function () { + return app.electron.webFrame.setZoomFactor(4) + .electron.webFrame.getZoomFactor().should.eventually.equal(4) + }) + }) }) From f5198379bbc59d28fa17d934d8b90ea1f8258628 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 10:36:50 -0700 Subject: [PATCH 59/80] Remove deleted commands --- README.md | 221 ------------------------------------------------------ 1 file changed, 221 deletions(-) diff --git a/README.md b/README.md index c37d08f63..04130db39 100644 --- a/README.md +++ b/README.md @@ -251,46 +251,6 @@ Several additional commands are provided specific to Electron. All the commands return a `Promise`. -#### getAppPath(name) - -Get the path using the `require('electron').app.getPath(name)` API. - -```js -app.client.getAppPath('userData').then(function (userDataPath) { - console.log(userDataPath) -}) -``` - -#### getArgv() - -Get the `argv` array from the main process. - -```js -app.client.getArgv().then(function (argv) { - console.log(argv) -}) -``` - -#### getClipboardText() - -Gets the clipboard text. - -```js -app.client.getClipboardText().then(function (clipboardText) { - console.log(clipboardText) -}) -``` - -#### getCwd() - -Get the current working directory of the main process. - -```js -app.client.getCwd().then(function (cwd) { - console.log(cwd) -}) -``` - #### getMainProcessLogs() Gets the `console` log output from the main process. The logs are cleared @@ -306,16 +266,6 @@ app.client.getMainProcessLogs().then(function (logs) { }) ``` -#### getMainProcessGlobal(globalName) - -Gets a global from the main process by name. - -```js -app.client.getMainProcessGlobal('aGlobal').then(function (globalValue) { - console.log(globalValue) -}) -``` - #### getRenderProcessLogs() Gets the `console` log output from the render process. The logs are cleared @@ -333,16 +283,6 @@ app.client.getRenderProcessLogs().then(function (logs) { }) ``` -#### getRepresentedFilename() - -Gets the represented file name. Only supported on Mac OS X. - -```js -app.client.getRepresentedFilename().then(function (filename) { - console.log(filename) -}) -``` - #### getSelectedText() Get the selected text in the current window. @@ -363,167 +303,6 @@ app.client.getWindowCount().then(function (count) { }) ``` -#### getWindowBounds() - -Gets the bounds of the current window. Object returned has -`x`, `y`, `width`, and `height` properties. - -```js -app.client.getWindowBounds().then(function (bounds) { - console.log(bounds.x, bounds.y, bounds.width, bounds.height) -}) -``` - -#### getWindowHeight() - -Get the height of the current window. - -```js -app.client.getWindowHeight().then(function (height) { - console.log(height) -}) -``` - -#### getWindowWidth() - -Get the width of the current window. - -```js -app.client.getWindowWidth().then(function (width) { - console.log(width) -}) -``` - -#### isDocumentEdited() - -Returns true if the document is edited, false otherwise. Only supported on -Mac OS X. - -```js -app.client.isDocumentEdited().then(function (edited) { - console.log(edited) -}) -``` - -#### isWindowDevToolsOpened() - -Returns whether the current window's dev tools are opened. - -```js -app.client.isWindowDevToolsOpened().then(function (devToolsOpened) { - console.log(devToolsOpened) -}) -``` - -#### isWindowFocused() - -Returns whether the current window has focus. - -```js -app.client.isWindowFocused().then(function (focused) { - console.log(focused) -}) -``` - -#### isWindowFullScreen() - -Returns whether the current window is in full screen mode. - -```js -app.client.isWindowFullScreen().then(function (fullScreen) { - console.log(fullScreen) -}) -``` - -#### isWindowLoading() - -Returns whether the current window is loading. - -```js -app.client.isWindowLoading().then(function (loading) { - console.log(loading) -}) -``` - -#### isWindowMaximized() - -Returns whether the current window is maximized. - -```js -app.client.isWindowMaximized().then(function (maximized) { - console.log(maximized) -}) -``` - -#### isWindowMinimized() - -Returns whether the current window is minimized. - -```js -app.client.isWindowMinimized().then(function (minimized) { - console.log(minimized) -}) -``` - -#### isWindowVisible() - -Returns whether the current window is visible. - -```js -app.client.isWindowVisible().then(function (visible) { - console.log(visible) -}) -``` - -#### paste() - -Paste the text from the clipboard in the current window. - -```js -app.client.paste() -``` - -#### selectAll() - -Select all the text in the current window. - -```js -app.client.selectAll() -``` - -#### setClipboardText(clipboardText) - -Sets the clipboard text. - -```js -app.client.setClipboardText('pasta') -``` - -#### setDocumentEdited(edited) - -Sets the document edited state. Only supported on Mac OS X. - -```js -app.client.setDocumentEdited(true) -``` - -#### setRepresentedFilename(filename) - -Sets the represented file name. Only supported on Mac OS X. - -```js -app.client.setRepresentedFilename('/foo.js') -``` - -#### setWindowBounds(bounds) - -Sets the window position and size. The bounds object should have `x`, `y`, -`height`, and `width` keys. - -```js -app.client.setWindowBounds({x: 100, y: 200, width: 50, height: 75}) -``` - #### waitUntilTextExists(selector, text, [timeout]) Waits until the element matching the given selector contains the given From ece023d8cc50aceb375967b68fc236c12f9d039b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 10:47:28 -0700 Subject: [PATCH 60/80] Update examples for new API --- README.md | 39 +++++++++++++++++++-------------------- test/example-test.js | 6 +++--- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 04130db39..d407c9dac 100644 --- a/README.md +++ b/README.md @@ -101,12 +101,12 @@ describe('application launch', function () { it('opens a window', function () { return this.app.client.waitUntilWindowLoaded() .getWindowCount().should.eventually.equal(1) - .isWindowMinimized().should.eventually.be.false - .isWindowDevToolsOpened().should.eventually.be.false - .isWindowVisible().should.eventually.be.true - .isWindowFocused().should.eventually.be.true - .getWindowWidth().should.eventually.be.above(0) - .getWindowHeight().should.eventually.be.above(0) + .browserWindow.isMinimized().should.eventually.be.false + .browserWindow.isDevToolsOpened().should.eventually.be.false + .browserWindow.isVisible().should.eventually.be.true + .browserWindow.isFocused().should.eventually.be.true + .browserWindow.getBounds().should.eventually.have.property('width').and.be.above(0) + .browserWindow.getBounds().should.eventually.have.property('height').and.be.above(0) }) }) ``` @@ -138,18 +138,17 @@ test(t => { return t.context.app.client.waitUntilWindowLoaded() .getWindowCount().then(count => { t.is(count, 1); - }).isWindowMinimized().then(min => { + }).browserWindow.isMinimized().then(min => { t.false(min); - }).isWindowDevToolsOpened().then(opened => { + }).browserWindow.isDevToolsOpened().then(opened => { t.false(opened); - }).isWindowVisible().then(visible => { + }).browserWindow.isVisible().then(visible => { t.true(visible); - }).isWindowFocused().then(focused => { + }).browserWindow.isFocused().then(focused => { t.true(focused); - }).getWindowWidth().then(width => { - t.ok(width > 0); - }).getWindowHeight().then(height => { - t.ok(height > 0); + }).browserWindow.getBounds().then(bounds => { + t.ok(bounds.width > 0); + t.ok(bounds.height > 0); }); }); ``` @@ -160,12 +159,12 @@ AVA supports ECMAScript advanced features not only promise but also async/await. test(async t => { await t.context.app.client.waitUntilWindowLoaded(); t.is(1, await app.client.getWindowCount()); - t.false(await app.client.isWindowMinimized()); - t.false(await app.client.isWindowDevToolsOpened()); - t.true(await app.client.isWindowVisible()); - t.true(await app.client.isWindowFocused()); - t.ok(await app.client.getWindowWidth() > 0); - t.ok(await app.client.getWindowHeight() > 0); + t.false(await app.browserWindow.isMinimized()); + t.false(await app.browserWindow.isDevToolsOpened()); + t.true(await app.browserWindow.isVisible()); + t.true(await app.browserWindow.isFocused()); + t.ok((await app.browserWindow.getBounds()).width > 0); + t.ok((await app.browserWindow.getBounds()).height > 0); }); ``` diff --git a/test/example-test.js b/test/example-test.js index adea1ddcf..125df3ef9 100644 --- a/test/example-test.js +++ b/test/example-test.js @@ -22,15 +22,15 @@ describe('example application launch', function () { return helpers.stopApplication(app) }) - it('opens a window', function () { + it.only('opens a window', function () { return app.client.waitUntilWindowLoaded() .getWindowCount().should.eventually.equal(1) .browserWindow.isMinimized().should.eventually.be.false .browserWindow.isDevToolsOpened().should.eventually.be.false .browserWindow.isVisible().should.eventually.be.true .browserWindow.isFocused().should.eventually.be.true - .browserWindow.getBounds().should.eventually.have.property('width', 800) - .browserWindow.getBounds().should.eventually.have.property('height', 400) + .browserWindow.getBounds().should.eventually.have.property('width').and.be.above(0) + .browserWindow.getBounds().should.eventually.have.property('height').and.be.above(0) }) describe('when the make larger button is clicked', function () { From 766e107107a192e454a9d71175fcfb043061cc84 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 10:53:09 -0700 Subject: [PATCH 61/80] Move library examples to the bottom --- README.md | 222 +++++++++++++++++++++++++++--------------------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/README.md b/README.md index d407c9dac..f594ed81a 100644 --- a/README.md +++ b/README.md @@ -57,117 +57,6 @@ describe('application launch', function () { }) ``` -### With Chai As Promised - -WebdriverIO is promise-based and so it pairs really well with the -[Chai as Promised](https://github.com/domenic/chai-as-promised) library that -builds on top of [Chai](http://chaijs.com). - -Using these together allows you to chain assertions together and have fewer -callback blocks. See below for a simple example: - -```sh -npm install --save-dev chai -npm install --save-dev chai-as-promised -``` - -```js -var Application = require('spectron').Application -var chai = require('chai') -var chaiAsPromised = require('chai-as-promised') -var path = require('path') - -chai.should() -chai.use(chaiAsPromised) - -describe('application launch', function () { - beforeEach(function () { - this.app = new Application({ - path: '/Applications/MyApp.app/Contents/MacOS/MyApp' - }) - return this.app.start() - }) - - beforeEach(function () { - chaiAsPromised.transferPromiseness = this.app.client.transferPromiseness - }) - - afterEach(function () { - if (this.app && this.app.isRunning()) { - return this.app.stop() - } - }) - - it('opens a window', function () { - return this.app.client.waitUntilWindowLoaded() - .getWindowCount().should.eventually.equal(1) - .browserWindow.isMinimized().should.eventually.be.false - .browserWindow.isDevToolsOpened().should.eventually.be.false - .browserWindow.isVisible().should.eventually.be.true - .browserWindow.isFocused().should.eventually.be.true - .browserWindow.getBounds().should.eventually.have.property('width').and.be.above(0) - .browserWindow.getBounds().should.eventually.have.property('height').and.be.above(0) - }) -}) -``` - -### With AVA - -Spectron works with [AVA](https://github.com/sindresorhus/ava) which allows you -to write your tests in ES2015 without extra support. - -```js -'use strict'; - -import test from 'ava'; -import {Application} from 'spectron'; - -test.beforeEach(t => { - t.context.app = new Application({ - path: '/Applications/MyApp.app/Contents/MacOS/MyApp' - }); - - return t.context.app.start(); -}); - -test.afterEach(t => { - return t.context.app.stop(); -}); - -test(t => { - return t.context.app.client.waitUntilWindowLoaded() - .getWindowCount().then(count => { - t.is(count, 1); - }).browserWindow.isMinimized().then(min => { - t.false(min); - }).browserWindow.isDevToolsOpened().then(opened => { - t.false(opened); - }).browserWindow.isVisible().then(visible => { - t.true(visible); - }).browserWindow.isFocused().then(focused => { - t.true(focused); - }).browserWindow.getBounds().then(bounds => { - t.ok(bounds.width > 0); - t.ok(bounds.height > 0); - }); -}); -``` - -AVA supports ECMAScript advanced features not only promise but also async/await. - -```js -test(async t => { - await t.context.app.client.waitUntilWindowLoaded(); - t.is(1, await app.client.getWindowCount()); - t.false(await app.browserWindow.isMinimized()); - t.false(await app.browserWindow.isDevToolsOpened()); - t.true(await app.browserWindow.isVisible()); - t.true(await app.browserWindow.isFocused()); - t.ok((await app.browserWindow.getBounds()).width > 0); - t.ok((await app.browserWindow.getBounds()).height > 0); -}); -``` - ### On Travis CI You will want to add the following to your `.travis.yml` file when building on @@ -327,3 +216,114 @@ Focus a window using its index from the `windowHandles()` array. ```js app.client.windowByIndex(1) ``` + +### With Chai As Promised + +WebdriverIO is promise-based and so it pairs really well with the +[Chai as Promised](https://github.com/domenic/chai-as-promised) library that +builds on top of [Chai](http://chaijs.com). + +Using these together allows you to chain assertions together and have fewer +callback blocks. See below for a simple example: + +```sh +npm install --save-dev chai +npm install --save-dev chai-as-promised +``` + +```js +var Application = require('spectron').Application +var chai = require('chai') +var chaiAsPromised = require('chai-as-promised') +var path = require('path') + +chai.should() +chai.use(chaiAsPromised) + +describe('application launch', function () { + beforeEach(function () { + this.app = new Application({ + path: '/Applications/MyApp.app/Contents/MacOS/MyApp' + }) + return this.app.start() + }) + + beforeEach(function () { + chaiAsPromised.transferPromiseness = this.app.client.transferPromiseness + }) + + afterEach(function () { + if (this.app && this.app.isRunning()) { + return this.app.stop() + } + }) + + it('opens a window', function () { + return this.app.client.waitUntilWindowLoaded() + .getWindowCount().should.eventually.equal(1) + .browserWindow.isMinimized().should.eventually.be.false + .browserWindow.isDevToolsOpened().should.eventually.be.false + .browserWindow.isVisible().should.eventually.be.true + .browserWindow.isFocused().should.eventually.be.true + .browserWindow.getBounds().should.eventually.have.property('width').and.be.above(0) + .browserWindow.getBounds().should.eventually.have.property('height').and.be.above(0) + }) +}) +``` + +### With AVA + +Spectron works with [AVA](https://github.com/sindresorhus/ava) which allows you +to write your tests in ES2015 without extra support. + +```js +'use strict'; + +import test from 'ava'; +import {Application} from 'spectron'; + +test.beforeEach(t => { + t.context.app = new Application({ + path: '/Applications/MyApp.app/Contents/MacOS/MyApp' + }); + + return t.context.app.start(); +}); + +test.afterEach(t => { + return t.context.app.stop(); +}); + +test(t => { + return t.context.app.client.waitUntilWindowLoaded() + .getWindowCount().then(count => { + t.is(count, 1); + }).browserWindow.isMinimized().then(min => { + t.false(min); + }).browserWindow.isDevToolsOpened().then(opened => { + t.false(opened); + }).browserWindow.isVisible().then(visible => { + t.true(visible); + }).browserWindow.isFocused().then(focused => { + t.true(focused); + }).browserWindow.getBounds().then(bounds => { + t.ok(bounds.width > 0); + t.ok(bounds.height > 0); + }); +}); +``` + +AVA supports ECMAScript advanced features not only promise but also async/await. + +```js +test(async t => { + await t.context.app.client.waitUntilWindowLoaded(); + t.is(1, await app.client.getWindowCount()); + t.false(await app.browserWindow.isMinimized()); + t.false(await app.browserWindow.isDevToolsOpened()); + t.true(await app.browserWindow.isVisible()); + t.true(await app.browserWindow.isFocused()); + t.ok((await app.browserWindow.getBounds()).width > 0); + t.ok((await app.browserWindow.getBounds()).height > 0); +}); +``` From 13a2b8f62e3d798ac2ccf7dee2051509e3591dfb Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 10:53:40 -0700 Subject: [PATCH 62/80] Add more headings --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index f594ed81a..d75389e3f 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,8 @@ os: unstable Check out Spectron's [appveyor.yml](https://github.com/kevinsawicki/spectron/blob/master/appveyor.yml) file for a production example. +## API + ### Application #### new Application(options) @@ -217,6 +219,8 @@ Focus a window using its index from the `windowHandles()` array. app.client.windowByIndex(1) ``` +## Test Library Examples + ### With Chai As Promised WebdriverIO is promise-based and so it pairs really well with the From 65fc7e35bc16aa340e8288f124760c6dff37ab30 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 11:10:20 -0700 Subject: [PATCH 63/80] Document properties --- README.md | 129 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 107 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index d75389e3f..09fee2b84 100644 --- a/README.md +++ b/README.md @@ -83,11 +83,12 @@ os: unstable Check out Spectron's [appveyor.yml](https://github.com/kevinsawicki/spectron/blob/master/appveyor.yml) file for a production example. -## API +## Application API -### Application +Spectron exports an `Application` class that when configured, can start and +stop your Electron application. -#### new Application(options) +### new Application(options) Create a new application with the following options: @@ -117,19 +118,9 @@ Create a new application with the following options: `waitUntilTextExists` and `waitUntilWindowLoaded` to complete. Defaults to `5000` milliseconds. +### Properties -#### start() - -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. - -#### stop() - -Stops the application. Returns a `Promise` that will be resolved once the -application has stopped. - -### Client Commands +#### client Spectron uses [WebdriverIO](http://webdriver.io) and exposes the managed `client` property on the created `Application` instances. @@ -141,7 +132,101 @@ Several additional commands are provided specific to Electron. All the commands return a `Promise`. -#### getMainProcessLogs() +#### electron + +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. + +So if you wanted to access the [clipboard](http://electron.atom.io/docs/latest/api/clipboard) +API in your tests you would do: + +```js +app.electron.clipboard.writeText('pasta') + .electron.clipboard.readText().then(function (clipboardText) { + console.log('The clipboard text is ' + clipboardText) + }) +``` + +#### browserWindow + +The `browserWindow` property is an alias for `require('electron').remote.getCurrentWindow()`. +It provides you easy access to the current [BrowserWindow](http://electron.atom.io/docs/latest/api/browser-window/) +and contains all the APIs. + +So if you wanted to check if the current window is visible you would do: + +```js +app.browserWindow.isVisible().then(function (visible) { + console.log('window is visible? ' + visible) +}) +``` + +It is named `browserWindow` instead of `window` so that it doesn't collide +with the WebDriver command of that name. + +#### webContents + +The `browserWindow` property is an alias for `require('electron').remote.getCurrentWebContents()`. +It provides you easy access to the [WebContents](http://electron.atom.io/docs/latest/api/web-contents/) +for the current window and contains all the APIs. + +So if you wanted to check if the current window is loading you would do: + +```js +app.webContents.isLoading().then(function (visible) { + console.log('window is loading? ' + visible) +}) +``` + +#### mainProcess + +The `mainProcess` property is an alias for `require('electron').remote.process`. +It provides you access to the main process's [process](https://nodejs.org/api/process.html) +global. + +So if you wanted to get the `argv` for the main process you would do: + +```js +app.mainProcess.argv().then(function (argv) { + console.log('main process args: ' + argv) +}) +``` + +Properties on the `process` are exposed as functions that return promises so +make sure to call `mainProcess.env().then(...)` instead of +`mainProcess.env.then(...)`. + +#### rendererProcess + +The `rendererProcess` property is an alias for `global.process`. It provides +you access to the renderer process's [process](https://nodejs.org/api/process.html) +global. + +So if you wanted to get the environment variables for the renderer process you +would do: + +```js +app.rendererProcess.env().then(function (env) { + console.log('main process args: ' + env) +}) +``` + +### Methods + +#### start() + +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. + +#### stop() + +Stops the application. Returns a `Promise` that will be resolved once the +application has stopped. + +#### client.getMainProcessLogs() Gets the `console` log output from the main process. The logs are cleared after they are returned. @@ -156,7 +241,7 @@ app.client.getMainProcessLogs().then(function (logs) { }) ``` -#### getRenderProcessLogs() +#### client.getRenderProcessLogs() Gets the `console` log output from the render process. The logs are cleared after they are returned. @@ -173,7 +258,7 @@ app.client.getRenderProcessLogs().then(function (logs) { }) ``` -#### getSelectedText() +#### client.getSelectedText() Get the selected text in the current window. @@ -183,7 +268,7 @@ app.client.getSelectedText().then(function (selectedText) { }) ``` -#### getWindowCount() +#### client.getWindowCount() Gets the number of open windows. @@ -193,7 +278,7 @@ app.client.getWindowCount().then(function (count) { }) ``` -#### waitUntilTextExists(selector, text, [timeout]) +#### client.waitUntilTextExists(selector, text, [timeout]) Waits until the element matching the given selector contains the given text. Takes an optional timeout in milliseconds that defaults to `5000`. @@ -202,7 +287,7 @@ text. Takes an optional timeout in milliseconds that defaults to `5000`. app.client.waitUntilTextExists('#message', 'Success', 10000) ``` -#### waitUntilWindowLoaded([timeout]) +#### client.waitUntilWindowLoaded([timeout]) Wait until the window is no longer loading. Takes an optional timeout in milliseconds that defaults to `5000`. @@ -211,7 +296,7 @@ in milliseconds that defaults to `5000`. app.client.waitUntilWindowLoaded(10000) ``` -#### windowByIndex(index) +#### client.windowByIndex(index) Focus a window using its index from the `windowHandles()` array. From bb5568b655d752e4aed1295259c4b0d3b7b5b96f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 11:10:59 -0700 Subject: [PATCH 64/80] Move CI after api docs --- README.md | 55 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 09fee2b84..cd3a8748e 100644 --- a/README.md +++ b/README.md @@ -57,32 +57,6 @@ describe('application launch', function () { }) ``` -### On Travis CI - -You will want to add the following to your `.travis.yml` file when building on -Linux: - -```yml -before_script: - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" - - sleep 3 # give xvfb some time to start -``` - -Check out Spectron's [.travis.yml](https://github.com/kevinsawicki/spectron/blob/master/.travis.yml) -file for a production example. - -### On AppVeyor - -You will want to add the following to your `appveyor.yml` file: - -```yml -os: unstable -``` - -Check out Spectron's [appveyor.yml](https://github.com/kevinsawicki/spectron/blob/master/appveyor.yml) -file for a production example. - ## Application API Spectron exports an `Application` class that when configured, can start and @@ -304,6 +278,35 @@ Focus a window using its index from the `windowHandles()` array. app.client.windowByIndex(1) ``` +## Continuous Integration + +### On Travis CI + +You will want to add the following to your `.travis.yml` file when building on +Linux: + +```yml +before_script: + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" + - sleep 3 # give xvfb some time to start +``` + +Check out Spectron's [.travis.yml](https://github.com/kevinsawicki/spectron/blob/master/.travis.yml) +file for a production example. + +### On AppVeyor + +You will want to add the following to your `appveyor.yml` file: + +```yml +os: unstable +``` + +Check out Spectron's [appveyor.yml](https://github.com/kevinsawicki/spectron/blob/master/appveyor.yml) +file for a production example. + + ## Test Library Examples ### With Chai As Promised From 65519e5548566dbe113bde2159d1a3d2f568d599 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 11:14:10 -0700 Subject: [PATCH 65/80] Tweak property descriptions --- README.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index cd3a8748e..c9af62209 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,7 @@ All the commands return a `Promise`. #### electron 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. @@ -126,10 +127,12 @@ app.electron.clipboard.writeText('pasta') #### browserWindow The `browserWindow` property is an alias for `require('electron').remote.getCurrentWindow()`. -It provides you easy access to the current [BrowserWindow](http://electron.atom.io/docs/latest/api/browser-window/) + +It provides you access to the current [BrowserWindow](http://electron.atom.io/docs/latest/api/browser-window/) and contains all the APIs. -So if you wanted to check if the current window is visible you would do: +So if you wanted to check if the current window is visible in your tests you +would do: ```js app.browserWindow.isVisible().then(function (visible) { @@ -143,10 +146,12 @@ with the WebDriver command of that name. #### webContents The `browserWindow` property is an alias for `require('electron').remote.getCurrentWebContents()`. -It provides you easy access to the [WebContents](http://electron.atom.io/docs/latest/api/web-contents/) + +It provides you access to the [WebContents](http://electron.atom.io/docs/latest/api/web-contents/) for the current window and contains all the APIs. -So if you wanted to check if the current window is loading you would do: +So if you wanted to check if the current window is loading in your tests you +would do: ```js app.webContents.isLoading().then(function (visible) { @@ -157,10 +162,12 @@ app.webContents.isLoading().then(function (visible) { #### mainProcess The `mainProcess` property is an alias for `require('electron').remote.process`. + It provides you access to the main process's [process](https://nodejs.org/api/process.html) global. -So if you wanted to get the `argv` for the main process you would do: +So if you wanted to get the `argv` for the main process in your tests you would +do: ```js app.mainProcess.argv().then(function (argv) { @@ -174,12 +181,13 @@ make sure to call `mainProcess.env().then(...)` instead of #### rendererProcess -The `rendererProcess` property is an alias for `global.process`. It provides -you access to the renderer process's [process](https://nodejs.org/api/process.html) +The `rendererProcess` property is an alias for `global.process`. + +It provides you access to the renderer process's [process](https://nodejs.org/api/process.html) global. -So if you wanted to get the environment variables for the renderer process you -would do: +So if you wanted to get the environment variables for the renderer process in +your tests you would do: ```js app.rendererProcess.env().then(function (env) { From 301f50194f82eecb2318fab264cfd49c2b838681 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 11:15:33 -0700 Subject: [PATCH 66/80] Remove only call --- test/example-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/example-test.js b/test/example-test.js index 125df3ef9..88dc70176 100644 --- a/test/example-test.js +++ b/test/example-test.js @@ -22,7 +22,7 @@ describe('example application launch', function () { return helpers.stopApplication(app) }) - it.only('opens a window', function () { + it('opens a window', function () { return app.client.waitUntilWindowLoaded() .getWindowCount().should.eventually.equal(1) .browserWindow.isMinimized().should.eventually.be.false From 6c40e3b2009634c6f1048fa3747a380a08270570 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 11:16:24 -0700 Subject: [PATCH 67/80] Access transferPromiseness from app instead of client --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c9af62209..58104c514 100644 --- a/README.md +++ b/README.md @@ -349,7 +349,7 @@ describe('application launch', function () { }) beforeEach(function () { - chaiAsPromised.transferPromiseness = this.app.client.transferPromiseness + chaiAsPromised.transferPromiseness = this.app.transferPromiseness }) afterEach(function () { From 484333498ff0fa1f45ea69fa6ca799ef9217091c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 11:23:32 -0700 Subject: [PATCH 68/80] Start 2.x changelog --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e159a125..f5b5ef5a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# 2.37.0 + + * Add support for the full Electron API + * Many custom helpers have been removed in favor of accessing the Electron + APIs directly through the new properties on the `Application` object. + * `app.client.getWindowBounds()` should now be `app.browserWindow.getBounds()` + * `app.client.getClipboardText()` should now be `app.electron.clipboard.readText()` + * See the README or https://github.com/kevinsawicki/spectron/pull/18 for + full details. + * You should now use `app.transferPromiseness` instead of `app.client.transferPromiseness` + to ensure these new properties are correctly transferred to chained promises. + # 1.37.1 * Add the `getAppPath(name)` that maps to the From b6bb43d4387367c6dd5f7dba4a4039f617b580fd Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 11:23:45 -0700 Subject: [PATCH 69/80] full -> more --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5b5ef5a8..b304033be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ * `app.client.getWindowBounds()` should now be `app.browserWindow.getBounds()` * `app.client.getClipboardText()` should now be `app.electron.clipboard.readText()` * See the README or https://github.com/kevinsawicki/spectron/pull/18 for - full details. + more details. * You should now use `app.transferPromiseness` instead of `app.client.transferPromiseness` to ensure these new properties are correctly transferred to chained promises. From c6087fe2224d3f79488f3d14a8fa8b91356148d0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 11:36:23 -0700 Subject: [PATCH 70/80] Add Application.restart() --- CHANGELOG.md | 3 ++- README.md | 5 +++++ lib/application.js | 7 +++++++ test/application-test.js | 17 +++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b304033be..47d95520f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # 2.37.0 - * Add support for the full Electron API + * Added a `restart()` method to `Application` + * Added support for the full Electron API * Many custom helpers have been removed in favor of accessing the Electron APIs directly through the new properties on the `Application` object. * `app.client.getWindowBounds()` should now be `app.browserWindow.getBounds()` diff --git a/README.md b/README.md index 58104c514..089867db6 100644 --- a/README.md +++ b/README.md @@ -208,6 +208,11 @@ before running any commands. Stops the application. Returns a `Promise` that will be resolved once the application has stopped. +#### restart() + +Stops the application and then starts it. Returns a `Promise` that will be +resolved once the application has started again. + #### client.getMainProcessLogs() Gets the `console` log output from the main process. The logs are cleared diff --git a/lib/application.js b/lib/application.js index e624825a2..a794e38c1 100644 --- a/lib/application.js +++ b/lib/application.js @@ -58,6 +58,13 @@ Application.prototype.stop = function () { }) } +Application.prototype.restart = function () { + var self = this + return self.stop().then(function () { + return self.start() + }) +} + Application.prototype.isRunning = function () { return this.running } diff --git a/test/application-test.js b/test/application-test.js index df0e77d80..16e032c16 100644 --- a/test/application-test.js +++ b/test/application-test.js @@ -101,6 +101,23 @@ describe('application loading', function () { }) }) + describe('restart()', function () { + it('restarts the application', function () { + var quitPath = path.join(tempPath, 'quit.txt') + assert.equal(fs.existsSync(quitPath), false) + return app.restart().then(function () { + assert.equal(fs.existsSync(quitPath), true) + assert.equal(app.isRunning(), true) + }) + }) + + it('rejects with an error if the application is not running', function () { + return app.stop().should.be.fulfilled.then(function () { + return app.restart().should.be.rejectedWith(Error) + }) + }) + }) + describe('getRenderProcessLogs', function () { it('gets the render process console logs and clears them', function () { return app.client.waitUntilWindowLoaded() From fd0de2b3179487f4be8c5dfb148c1e0fb656773a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 11:37:07 -0700 Subject: [PATCH 71/80] Assert not running after stop --- test/application-test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/application-test.js b/test/application-test.js index 16e032c16..4ff3b47e2 100644 --- a/test/application-test.js +++ b/test/application-test.js @@ -91,6 +91,7 @@ describe('application loading', function () { assert.equal(fs.existsSync(quitPath), false) return app.stop().then(function () { assert.equal(fs.existsSync(quitPath), true) + assert.equal(app.isRunning(), false) }) }) From de735555a0e8dc62752a1abc1e598a178f1ab868 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 11:40:52 -0700 Subject: [PATCH 72/80] Resolve start/stop/restart with application --- lib/application.js | 3 ++- test/application-test.js | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/application.js b/lib/application.js index a794e38c1..7ee1dc69b 100644 --- a/lib/application.js +++ b/lib/application.js @@ -38,6 +38,7 @@ Application.prototype.start = function () { .then(function () { return self.createClient() }) .then(function () { return self.api.initialize() }) .then(function () { self.running = true }) + .then(function () { return self }) } Application.prototype.stop = function () { @@ -51,7 +52,7 @@ Application.prototype.stop = function () { self.client.end().then(function () { self.chromeDriver.stop() self.running = false - resolve() + resolve(self) }, reject) }, self.quitTimeout) }, reject) diff --git a/test/application-test.js b/test/application-test.js index 4ff3b47e2..51abeda7f 100644 --- a/test/application-test.js +++ b/test/application-test.js @@ -89,7 +89,8 @@ describe('application loading', function () { it('quits the application', function () { var quitPath = path.join(tempPath, 'quit.txt') assert.equal(fs.existsSync(quitPath), false) - return app.stop().then(function () { + return app.stop().then(function (stoppedApp) { + assert.equal(stoppedApp, app) assert.equal(fs.existsSync(quitPath), true) assert.equal(app.isRunning(), false) }) @@ -106,7 +107,8 @@ describe('application loading', function () { it('restarts the application', function () { var quitPath = path.join(tempPath, 'quit.txt') assert.equal(fs.existsSync(quitPath), false) - return app.restart().then(function () { + return app.restart().then(function (restartedApp) { + assert.equal(restartedApp, app) assert.equal(fs.existsSync(quitPath), true) assert.equal(app.isRunning(), true) }) From 3eea77da76621a2b1b6b881bf5c994d34aaec270 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 13:52:08 -0700 Subject: [PATCH 73/80] :art: --- lib/api.js | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/lib/api.js b/lib/api.js index 21b395d13..601b9f102 100644 --- a/lib/api.js +++ b/lib/api.js @@ -3,28 +3,36 @@ function Api (app) { } Api.prototype.initialize = function () { - var self = this - return this.load(self.app).then(function (api) { - self.addRenderProcessApis(api.render) - self.addMainProcessApis(api.main) - self.addBrowserWindowApis(api.browserWindow) - self.addWebContentsApis(api.webContents) - self.addProcessApis(api.process) - - self.api = { - browserWindow: api.browserWindow, - electron: api.render, - rendererProcess: api.process, - webContents: api.webContents - } - self.api.electron.remote = api.main + return this.load() + .then(this.addApiCommands.bind(this)) +} - self.addClientProperties() - }) +Api.prototype.addApiCommands = function (api) { + this.addRenderProcessApis(api.render) + this.addMainProcessApis(api.main) + this.addBrowserWindowApis(api.browserWindow) + this.addWebContentsApis(api.webContents) + this.addProcessApis(api.process) + + this.api = { + browserWindow: api.browserWindow, + electron: api.render, + rendererProcess: api.process, + webContents: api.webContents + } + this.api.electron.remote = api.main + + this.addClientProperties() +} + +Api.prototype.getVersion = function () { + return this.app.client.execute(function () { + return process.versions.electron + }).then(getResponseValue) } -Api.prototype.load = function (app) { - return app.client.execute(function () { +Api.prototype.load = function () { + return this.app.client.execute(function () { var electron = require('electron') var api = { From 1cf3113eca96ddedb74d1cadaf761207cd5b24a1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 14:05:57 -0700 Subject: [PATCH 74/80] Cache api by electron version --- lib/api.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/api.js b/lib/api.js index 601b9f102..15da2b63f 100644 --- a/lib/api.js +++ b/lib/api.js @@ -1,3 +1,5 @@ +var apiCache = {} + function Api (app) { this.app = app } @@ -16,7 +18,7 @@ Api.prototype.addApiCommands = function (api) { this.api = { browserWindow: api.browserWindow, - electron: api.render, + electron: Object.create(api.render), rendererProcess: api.process, webContents: api.webContents } @@ -25,13 +27,26 @@ Api.prototype.addApiCommands = function (api) { this.addClientProperties() } +Api.prototype.load = function () { + var self = this + return this.getVersion().then(function (version) { + var api = apiCache[version] + if (api) return api + + return self.loadApi().then(function (api) { + apiCache[version] = api + return api + }) + }) +} + Api.prototype.getVersion = function () { return this.app.client.execute(function () { return process.versions.electron }).then(getResponseValue) } -Api.prototype.load = function () { +Api.prototype.loadApi = function () { return this.app.client.execute(function () { var electron = require('electron') @@ -173,6 +188,7 @@ Api.prototype.addRenderProcessApis = function (api) { var electron = {} app.electron = electron + Object.keys(api).forEach(function (moduleName) { electron[moduleName] = {} var moduleApi = api[moduleName] From cf8731d37ad54dbdbddc3042eda60ae7af03836b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 14:06:15 -0700 Subject: [PATCH 75/80] Update spec description --- test/application-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/application-test.js b/test/application-test.js index 51abeda7f..1b805a562 100644 --- a/test/application-test.js +++ b/test/application-test.js @@ -174,7 +174,7 @@ describe('application loading', function () { }) }) - describe('getMainProcessGlobal', function () { + describe('electron.remote.getGlobal', function () { it('returns the requested global from the main process', function () { return app.electron.remote.getGlobal('mainProcessGlobal').should.eventually.equal('foo') }) From 9267761d8539c1e6ffbccb63578fc56ce1725057 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 14:06:50 -0700 Subject: [PATCH 76/80] :art: --- lib/api.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/api.js b/lib/api.js index 15da2b63f..cc8757591 100644 --- a/lib/api.js +++ b/lib/api.js @@ -5,8 +5,7 @@ function Api (app) { } Api.prototype.initialize = function () { - return this.load() - .then(this.addApiCommands.bind(this)) + return this.load().then(this.addApiCommands.bind(this)) } Api.prototype.addApiCommands = function (api) { From 0256ca1ee4c3166f85c35f9b3f66fd54bb7d1b6b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 14:11:10 -0700 Subject: [PATCH 77/80] Remove newline --- lib/api.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/api.js b/lib/api.js index cc8757591..4593a0718 100644 --- a/lib/api.js +++ b/lib/api.js @@ -187,7 +187,6 @@ Api.prototype.addRenderProcessApis = function (api) { var electron = {} app.electron = electron - Object.keys(api).forEach(function (moduleName) { electron[moduleName] = {} var moduleApi = api[moduleName] From 0f5ae529f33d578fd06508819e855f4e28dfd01a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 14:12:53 -0700 Subject: [PATCH 78/80] Bump major in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 089867db6..7b238e979 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Easily test your [Electron](http://electron.atom.io) apps using This minor version of this library tracks the minor version of the Electron versions released. So if you are using Electron `0.37.x` you would want to use -a `spectron` dependency of `~1.37` in your `package.json` file. +a `spectron` dependency of `~2.37` in your `package.json` file. Learn more from [this presentation](https://speakerdeck.com/kevinsawicki/testing-your-electron-apps-with-chromedriver). From f47991ccb3d3c3f4734fb5a6ac3d11fd17befd70 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 14:30:38 -0700 Subject: [PATCH 79/80] Collect main/render APIs in single electron object --- lib/api.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/api.js b/lib/api.js index 4593a0718..1e66a506b 100644 --- a/lib/api.js +++ b/lib/api.js @@ -9,19 +9,18 @@ Api.prototype.initialize = function () { } Api.prototype.addApiCommands = function (api) { - this.addRenderProcessApis(api.render) - this.addMainProcessApis(api.main) + this.addRenderProcessApis(api.electron) + this.addMainProcessApis(api.electron.remote) this.addBrowserWindowApis(api.browserWindow) this.addWebContentsApis(api.webContents) this.addProcessApis(api.process) this.api = { browserWindow: api.browserWindow, - electron: Object.create(api.render), + electron: api.electron, rendererProcess: api.process, webContents: api.webContents } - this.api.electron.remote = api.main this.addClientProperties() } @@ -51,9 +50,8 @@ Api.prototype.loadApi = function () { var api = { browserWindow: {}, - main: {}, + electron: {}, process: {}, - render: {}, webContents: {} } @@ -100,20 +98,21 @@ Api.prototype.loadApi = function () { Object.getOwnPropertyNames(electron).forEach(function (key) { if (ignoreModule(key)) return if (key === 'remote') return - addModule(electron, 'electron', key, api.render) + addModule(electron, 'electron', key, api.electron) }) } function addMainProcessModules () { + api.electron.remote = {} Object.getOwnPropertyNames(electron.remote).forEach(function (key) { if (ignoreModule(key)) return if (isRemoteFunction(key)) { - api.main[key] = 'electron.remote.' + key + api.electron.remote[key] = 'electron.remote.' + key } else { - addModule(electron.remote, 'electron.remote', key, api.main) + addModule(electron.remote, 'electron.remote', key, api.electron.remote) } }) - addModule(electron.remote, 'electron.remote', 'process', api.main) + addModule(electron.remote, 'electron.remote', 'process', api.electron.remote) } function addBrowserWindow () { @@ -188,6 +187,7 @@ Api.prototype.addRenderProcessApis = function (api) { app.electron = electron Object.keys(api).forEach(function (moduleName) { + if (moduleName === 'remote') return electron[moduleName] = {} var moduleApi = api[moduleName] From ab15dfd96412fdd49656eaef8cc7b13277685d35 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Apr 2016 14:32:12 -0700 Subject: [PATCH 80/80] process -> rendererProcess for clarity --- lib/api.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/api.js b/lib/api.js index 1e66a506b..0bdb39e46 100644 --- a/lib/api.js +++ b/lib/api.js @@ -13,12 +13,12 @@ Api.prototype.addApiCommands = function (api) { this.addMainProcessApis(api.electron.remote) this.addBrowserWindowApis(api.browserWindow) this.addWebContentsApis(api.webContents) - this.addProcessApis(api.process) + this.addProcessApis(api.rendererProcess) this.api = { browserWindow: api.browserWindow, electron: api.electron, - rendererProcess: api.process, + rendererProcess: api.rendererProcess, webContents: api.webContents } @@ -51,7 +51,7 @@ Api.prototype.loadApi = function () { var api = { browserWindow: {}, electron: {}, - process: {}, + rendererProcess: {}, webContents: {} } @@ -140,7 +140,7 @@ Api.prototype.loadApi = function () { function addProcess () { for (var name in process) { if (ignoreApi(name)) continue - api.process[name] = 'process.' + name + api.rendererProcess[name] = 'process.' + name } }