From c842ca1f127cb6e9b1850929c7b6a319c323536b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 09:52:04 -0800 Subject: [PATCH 01/22] Don't use ES6 class for AutoUpdater windows class --- .../api/lib/auto-updater/auto-updater-win.js | 88 +++++++++---------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.js b/atom/browser/api/lib/auto-updater/auto-updater-win.js index f8a07902f21..1c81763f35e 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.js +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.js @@ -4,59 +4,59 @@ const app = require('electron').app; const EventEmitter = require('events').EventEmitter; const squirrelUpdate = require('./squirrel-update-win'); -class AutoUpdater extends EventEmitter { - constructor() { - super(); - } +function AutoUpdater() { + EventEmitter.call(this) +} - quitAndInstall() { - squirrelUpdate.processStart(); - return app.quit(); - } +require('util').inherits(AutoUpdater, EventEmitter); - setFeedURL(updateURL) { - return this.updateURL = updateURL; - } +AutoUpdater.prototype.quitAndInstall = function() { + squirrelUpdate.processStart(); + return app.quit(); +} - checkForUpdates() { - if (!this.updateURL) { - return this.emitError('Update URL is not set'); - } - if (!squirrelUpdate.supported()) { - return this.emitError('Can not find Squirrel'); - } - this.emit('checking-for-update'); - return squirrelUpdate.download(this.updateURL, (function(_this) { - return function(error, update) { +AutoUpdater.prototype.setFeedURL = function(updateURL) { + return this.updateURL = updateURL; +} + +AutoUpdater.prototype.checkForUpdates = function() { + if (!this.updateURL) { + return this.emitError('Update URL is not set'); + } + if (!squirrelUpdate.supported()) { + return this.emitError('Can not find Squirrel'); + } + this.emit('checking-for-update'); + return squirrelUpdate.download(this.updateURL, (function(_this) { + return function(error, update) { + if (error != null) { + return _this.emitError(error); + } + if (update == null) { + return _this.emit('update-not-available'); + } + _this.emit('update-available'); + return squirrelUpdate.update(_this.updateURL, function(error) { + var date, releaseNotes, version; if (error != null) { return _this.emitError(error); } - if (update == null) { - return _this.emit('update-not-available'); - } - _this.emit('update-available'); - return squirrelUpdate.update(_this.updateURL, function(error) { - var date, releaseNotes, version; - if (error != null) { - return _this.emitError(error); - } - releaseNotes = update.releaseNotes, version = update.version; + releaseNotes = update.releaseNotes, version = update.version; - // Following information is not available on Windows, so fake them. - date = new Date; - return _this.emit('update-downloaded', {}, releaseNotes, version, date, _this.updateURL, function() { - return _this.quitAndInstall(); - }); + // Following information is not available on Windows, so fake them. + date = new Date; + return _this.emit('update-downloaded', {}, releaseNotes, version, date, _this.updateURL, function() { + return _this.quitAndInstall(); }); - }; - })(this)); - } + }); + }; + })(this)); +} - // Private: Emit both error object and message, this is to keep compatibility - // with Old APIs. - emitError(message) { - return this.emit('error', new Error(message), message); - } +// Private: Emit both error object and message, this is to keep compatibility +// with Old APIs. +AutoUpdater.prototype.emitError = (message) { + return this.emit('error', new Error(message), message); } module.exports = new AutoUpdater; From 6617592224a9e57e0513e9e05ed59e8a235d67d6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 10:01:01 -0800 Subject: [PATCH 02/22] Remove lint errors --- .../browser/api/lib/auto-updater/auto-updater-win.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.js b/atom/browser/api/lib/auto-updater/auto-updater-win.js index 1c81763f35e..f5f2202f58d 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.js +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.js @@ -5,7 +5,7 @@ const EventEmitter = require('events').EventEmitter; const squirrelUpdate = require('./squirrel-update-win'); function AutoUpdater() { - EventEmitter.call(this) + EventEmitter.call(this); } require('util').inherits(AutoUpdater, EventEmitter); @@ -13,11 +13,11 @@ require('util').inherits(AutoUpdater, EventEmitter); AutoUpdater.prototype.quitAndInstall = function() { squirrelUpdate.processStart(); return app.quit(); -} +}; AutoUpdater.prototype.setFeedURL = function(updateURL) { return this.updateURL = updateURL; -} +}; AutoUpdater.prototype.checkForUpdates = function() { if (!this.updateURL) { @@ -51,12 +51,12 @@ AutoUpdater.prototype.checkForUpdates = function() { }); }; })(this)); -} +}; // Private: Emit both error object and message, this is to keep compatibility // with Old APIs. -AutoUpdater.prototype.emitError = (message) { +AutoUpdater.prototype.emitError = function(message) { return this.emit('error', new Error(message), message); -} +}; module.exports = new AutoUpdater; From 7da4c3acf7b2ac901ef5c5ff2828cec55e434c09 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 11:00:34 -0800 Subject: [PATCH 03/22] Use const for util require --- atom/browser/api/lib/auto-updater/auto-updater-win.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/lib/auto-updater/auto-updater-win.js b/atom/browser/api/lib/auto-updater/auto-updater-win.js index f5f2202f58d..1270f8f2bdb 100644 --- a/atom/browser/api/lib/auto-updater/auto-updater-win.js +++ b/atom/browser/api/lib/auto-updater/auto-updater-win.js @@ -3,12 +3,13 @@ const app = require('electron').app; const EventEmitter = require('events').EventEmitter; const squirrelUpdate = require('./squirrel-update-win'); +const util = require('util'); function AutoUpdater() { EventEmitter.call(this); } -require('util').inherits(AutoUpdater, EventEmitter); +util.inherits(AutoUpdater, EventEmitter); AutoUpdater.prototype.quitAndInstall = function() { squirrelUpdate.processStart(); From 3ab14e14e9fae0a78ff7f9e88ac7087b87ef1182 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Feb 2016 12:53:56 -0800 Subject: [PATCH 04/22] Add initial auto updater specs --- spec/api-auto-updater-spec.js | 34 ++++++++++++++++++++++++++++++++++ spec/static/main.js | 5 +++++ 2 files changed, 39 insertions(+) create mode 100644 spec/api-auto-updater-spec.js diff --git a/spec/api-auto-updater-spec.js b/spec/api-auto-updater-spec.js new file mode 100644 index 00000000000..72a1d90a7fe --- /dev/null +++ b/spec/api-auto-updater-spec.js @@ -0,0 +1,34 @@ +const assert = require('assert'); +const autoUpdater = require('electron').remote.autoUpdater; +const ipcRenderer = require('electron').ipcRenderer; + +describe('autoUpdater module', function() { + describe('checkForUpdates', function() { + it('emits an error on Windows when called the feed URL is not set', function (done) { + if (process.platform !== 'win32') { + return done(); + } + + ipcRenderer.once('auto-updater-error', function(event, message) { + assert.equal(message, 'Update URL is not set'); + done(); + }); + autoUpdater.setFeedURL(''); + autoUpdater.checkForUpdates(); + }); + }); + + describe('setFeedURL', function() { + it('emits an error on Mac OS X when the application is unsigned', function (done) { + if (process.platform !== 'darwin') { + return done(); + } + + ipcRenderer.once('auto-updater-error', function(event, message) { + assert.equal(message, 'Could not get code signature for running application'); + done(); + }); + autoUpdater.setFeedURL(''); + }); + }); +}); diff --git a/spec/static/main.js b/spec/static/main.js index 13d2dd6a6e1..125ef72f609 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -72,6 +72,11 @@ app.on('ready', function() { // Test if using protocol module would crash. electron.protocol.registerStringProtocol('test-if-crashes', function() {}); + // Send auto updater errors to window to be verified in specs + electron.autoUpdater.on('error', function (error) { + window.send('auto-updater-error', error.message) + }); + window = new BrowserWindow({ title: 'Electron Tests', show: false, From 16594d6ed08240cf4c26b00c3e779095957bd541 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Feb 2016 09:37:44 -0800 Subject: [PATCH 05/22] Add bootstrap script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3f0983bc441..218454372fb 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "lint": "python ./script/eslint.py && python ./script/cpplint.py", "preinstall": "node -e 'process.exit(0)'", "start": "python ./script/start.py", - "test": "python ./script/test.py" + "test": "python ./script/test.py", + "bootstrap": "python ./script/bootstrap.py" } } From 03482a442728c7222a6fb38a0346b0395e690461 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Feb 2016 09:39:22 -0800 Subject: [PATCH 06/22] Add build script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 218454372fb..2060e54a1e3 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "preinstall": "node -e 'process.exit(0)'", "start": "python ./script/start.py", "test": "python ./script/test.py", - "bootstrap": "python ./script/bootstrap.py" + "bootstrap": "python ./script/bootstrap.py", + "build": "python ./script/build.py -c D" } } From a8e6e24e58f7bdcd2fecd6e70379aa23baeedeca Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Feb 2016 09:43:29 -0800 Subject: [PATCH 07/22] Sort scripts keys --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 2060e54a1e3..6d812087199 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,11 @@ }, "private": true, "scripts": { + "bootstrap": "python ./script/bootstrap.py", + "build": "python ./script/build.py -c D", "lint": "python ./script/eslint.py && python ./script/cpplint.py", "preinstall": "node -e 'process.exit(0)'", "start": "python ./script/start.py", - "test": "python ./script/test.py", - "bootstrap": "python ./script/bootstrap.py", - "build": "python ./script/build.py -c D" + "test": "python ./script/test.py" } } From 55d4db1387c4f97dc72b00d8524d64dbfa8feeb8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 10:03:49 -0800 Subject: [PATCH 08/22] :art: --- atom/browser/api/lib/web-contents.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/lib/web-contents.js b/atom/browser/api/lib/web-contents.js index 709694bcf72..08252923fc2 100644 --- a/atom/browser/api/lib/web-contents.js +++ b/atom/browser/api/lib/web-contents.js @@ -76,8 +76,8 @@ let wrapWebContents = function(webContents) { // WebContents::send(channel, args..) webContents.send = function() { - var args, channel; - channel = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; + var args = 2 <= arguments.length ? slice.call(arguments, 1) : []; + var channel = arguments[0]; return this._send(channel, slice.call(args)); }; From 4828835998f05e2b59d2ff48a17768472de6636a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 10:12:45 -0800 Subject: [PATCH 09/22] Clean up returns after CoffeeScript migration --- spec/api-browser-window-spec.js | 240 +++++++++++++++++++------------- 1 file changed, 140 insertions(+), 100 deletions(-) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index fc8d3523c8f..69b895c366d 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -14,29 +14,31 @@ const BrowserWindow = remote.require('electron').BrowserWindow; const isCI = remote.getGlobal('isCi'); describe('browser-window module', function() { - var fixtures, w; - fixtures = path.resolve(__dirname, 'fixtures'); - w = null; + var fixtures = path.resolve(__dirname, 'fixtures'); + var w = null; + beforeEach(function() { if (w != null) { w.destroy(); } - return w = new BrowserWindow({ + w = new BrowserWindow({ show: false, width: 400, height: 400 }); }); + afterEach(function() { if (w != null) { w.destroy(); } - return w = null; + w = null; }); + describe('BrowserWindow.close()', function() { it('should emit unload handler', function(done) { w.webContents.on('did-finish-load', function() { - return w.close(); + w.close(); }); w.on('closed', function() { var content, test; @@ -44,20 +46,22 @@ describe('browser-window module', function() { content = fs.readFileSync(test); fs.unlinkSync(test); assert.equal(String(content), 'unload'); - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'unload.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'unload.html')); }); - return it('should emit beforeunload handler', function(done) { + + it('should emit beforeunload handler', function(done) { w.on('onbeforeunload', function() { - return done(); + done(); }); w.webContents.on('did-finish-load', function() { - return w.close(); + w.close(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'beforeunload-false.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'beforeunload-false.html')); }); }); + describe('window.close()', function() { it('should emit unload handler', function(done) { w.on('closed', function() { @@ -66,104 +70,113 @@ describe('browser-window module', function() { content = fs.readFileSync(test); fs.unlinkSync(test); assert.equal(String(content), 'close'); - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'close.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'close.html')); }); - return it('should emit beforeunload handler', function(done) { + + it('should emit beforeunload handler', function(done) { w.on('onbeforeunload', function() { - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html')); }); }); + describe('BrowserWindow.destroy()', function() { - return it('prevents users to access methods of webContents', function() { + it('prevents users to access methods of webContents', function() { var webContents; webContents = w.webContents; w.destroy(); - return assert.throws((function() { - return webContents.getId(); + assert.throws((function() { + webContents.getId(); }), /Object has been destroyed/); }); }); + describe('BrowserWindow.loadURL(url)', function() { it('should emit did-start-loading event', function(done) { w.webContents.on('did-start-loading', function() { - return done(); + done(); }); - return w.loadURL('about:blank'); + w.loadURL('about:blank'); }); - return it('should emit did-fail-load event', function(done) { + + it('should emit did-fail-load event', function(done) { w.webContents.on('did-fail-load', function() { - return done(); + done(); }); - return w.loadURL('file://a.txt'); + w.loadURL('file://a.txt'); }); }); + describe('BrowserWindow.show()', function() { - return it('should focus on window', function() { + it('should focus on window', function() { if (isCI) { return; } + w.show(); - return assert(w.isFocused()); + assert(w.isFocused()); }); }); + describe('BrowserWindow.showInactive()', function() { - return it('should not focus on window', function() { + it('should not focus on window', function() { w.showInactive(); - return assert(!w.isFocused()); + assert(!w.isFocused()); }); }); + describe('BrowserWindow.focus()', function() { - return it('does not make the window become visible', function() { + it('does not make the window become visible', function() { assert.equal(w.isVisible(), false); w.focus(); - return assert.equal(w.isVisible(), false); + assert.equal(w.isVisible(), false); }); }); + describe('BrowserWindow.capturePage(rect, callback)', function() { - return it('calls the callback with a Buffer', function(done) { - return w.capturePage({ + it('calls the callback with a Buffer', function(done) { + w.capturePage({ x: 0, y: 0, width: 100, height: 100 }, function(image) { assert.equal(image.isEmpty(), true); - return done(); + done(); }); }); }); + describe('BrowserWindow.setSize(width, height)', function() { - return it('sets the window size', function(done) { - var size; - size = [300, 400]; + it('sets the window size', function(done) { + var size = [300, 400]; w.once('resize', function() { - var newSize; - newSize = w.getSize(); + var newSize = w.getSize(); assert.equal(newSize[0], size[0]); assert.equal(newSize[1], size[1]); - return done(); + done(); }); - return w.setSize(size[0], size[1]); + w.setSize(size[0], size[1]); }); }); + describe('BrowserWindow.setPosition(x, y)', function() { - return it('sets the window position', function(done) { - var pos; - pos = [10, 10]; + it('sets the window position', function(done) { + var pos = [10, 10]; w.once('move', function() { var newPos; newPos = w.getPosition(); assert.equal(newPos[0], pos[0]); assert.equal(newPos[1], pos[1]); - return done(); + done(); }); - return w.setPosition(pos[0], pos[1]); + w.setPosition(pos[0], pos[1]); }); }); + describe('BrowserWindow.setContentSize(width, height)', function() { it('sets the content size', function() { var after, size; @@ -171,9 +184,10 @@ describe('browser-window module', function() { w.setContentSize(size[0], size[1]); after = w.getContentSize(); assert.equal(after[0], size[0]); - return assert.equal(after[1], size[1]); + assert.equal(after[1], size[1]); }); - return it('works for framless window', function() { + + it('works for framless window', function() { var after, size; w.destroy(); w = new BrowserWindow({ @@ -186,14 +200,16 @@ describe('browser-window module', function() { w.setContentSize(size[0], size[1]); after = w.getContentSize(); assert.equal(after[0], size[0]); - return assert.equal(after[1], size[1]); + assert.equal(after[1], size[1]); }); }); + describe('BrowserWindow.fromId(id)', function() { - return it('returns the window with id', function() { - return assert.equal(w.id, BrowserWindow.fromId(w.id).id); + it('returns the window with id', function() { + assert.equal(w.id, BrowserWindow.fromId(w.id).id); }); }); + describe('"useContentSize" option', function() { it('make window created with content size when used', function() { var contentSize; @@ -206,15 +222,16 @@ describe('browser-window module', function() { }); contentSize = w.getContentSize(); assert.equal(contentSize[0], 400); - return assert.equal(contentSize[1], 400); + assert.equal(contentSize[1], 400); }); + it('make window created with window size when not used', function() { - var size; - size = w.getSize(); + var size = w.getSize(); assert.equal(size[0], 400); - return assert.equal(size[1], 400); + assert.equal(size[1], 400); }); - return it('works for framless window', function() { + + it('works for framless window', function() { var contentSize, size; w.destroy(); w = new BrowserWindow({ @@ -229,9 +246,10 @@ describe('browser-window module', function() { assert.equal(contentSize[1], 400); size = w.getSize(); assert.equal(size[0], 400); - return assert.equal(size[1], 400); + assert.equal(size[1], 400); }); }); + describe('"title-bar-style" option', function() { if (process.platform !== 'darwin') { return; @@ -239,6 +257,7 @@ describe('browser-window module', function() { if (parseInt(os.release().split('.')[0]) < 14) { return; } + it('creates browser window with hidden title bar', function() { var contentSize; w.destroy(); @@ -249,9 +268,10 @@ describe('browser-window module', function() { titleBarStyle: 'hidden' }); contentSize = w.getContentSize(); - return assert.equal(contentSize[1], 400); + assert.equal(contentSize[1], 400); }); - return it('creates browser window with hidden inset title bar', function() { + + it('creates browser window with hidden inset title bar', function() { var contentSize; w.destroy(); w = new BrowserWindow({ @@ -261,30 +281,34 @@ describe('browser-window module', function() { titleBarStyle: 'hidden-inset' }); contentSize = w.getContentSize(); - return assert.equal(contentSize[1], 400); + assert.equal(contentSize[1], 400); }); }); + describe('"enableLargerThanScreen" option', function() { if (process.platform === 'linux') { return; } + beforeEach(function() { w.destroy(); - return w = new BrowserWindow({ + w = new BrowserWindow({ show: true, width: 400, height: 400, enableLargerThanScreen: true }); }); + it('can move the window out of screen', function() { var after; w.setPosition(-10, -10); after = w.getPosition(); assert.equal(after[0], -10); - return assert.equal(after[1], -10); + assert.equal(after[1], -10); }); - return it('can set the window larger than screen', function() { + + it('can set the window larger than screen', function() { var after, size; size = screen.getPrimaryDisplay().size; size.width += 100; @@ -292,21 +316,22 @@ describe('browser-window module', function() { w.setSize(size.width, size.height); after = w.getSize(); assert.equal(after[0], size.width); - return assert.equal(after[1], size.height); + assert.equal(after[1], size.height); }); }); describe('"web-preferences" option', function() { afterEach(function() { - return ipcMain.removeAllListeners('answer'); + ipcMain.removeAllListeners('answer'); }); + describe('"preload" option', function() { - return it('loads the script before other scripts in window', function(done) { + it('loads the script before other scripts in window', function(done) { var preload; preload = path.join(fixtures, 'module', 'set-global.js'); ipcMain.once('answer', function(event, test) { assert.equal(test, 'preload'); - return done(); + done(); }); w.destroy(); w = new BrowserWindow({ @@ -315,16 +340,17 @@ describe('browser-window module', function() { preload: preload } }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'preload.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'preload.html')); }); }); - return describe('"node-integration" option', function() { - return it('disables node integration when specified to false', function(done) { + + describe('"node-integration" option', function() { + it('disables node integration when specified to false', function(done) { var preload; preload = path.join(fixtures, 'module', 'send-later.js'); ipcMain.once('answer', function(event, test) { assert.equal(test, 'undefined'); - return done(); + done(); }); w.destroy(); w = new BrowserWindow({ @@ -334,107 +360,121 @@ describe('browser-window module', function() { nodeIntegration: false } }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'blank.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'blank.html')); }); }); }); + describe('beforeunload handler', function() { it('returning true would not prevent close', function(done) { w.on('closed', function() { - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-true.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-true.html')); }); + it('returning non-empty string would not prevent close', function(done) { w.on('closed', function() { - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-string.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-string.html')); }); + it('returning false would prevent close', function(done) { w.on('onbeforeunload', function() { - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html')); }); - return it('returning empty string would prevent close', function(done) { + + it('returning empty string would prevent close', function(done) { w.on('onbeforeunload', function() { - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-empty-string.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'close-beforeunload-empty-string.html')); }); }); + describe('new-window event', function() { if (isCI && process.platform === 'darwin') { return; } + it('emits when window.open is called', function(done) { w.webContents.once('new-window', function(e, url, frameName) { e.preventDefault(); assert.equal(url, 'http://host/'); assert.equal(frameName, 'host'); - return done(); + done(); }); - return w.loadURL("file://" + fixtures + "/pages/window-open.html"); + w.loadURL("file://" + fixtures + "/pages/window-open.html"); }); - return it('emits when link with target is called', function(done) { + + it('emits when link with target is called', function(done) { this.timeout(10000); w.webContents.once('new-window', function(e, url, frameName) { e.preventDefault(); assert.equal(url, 'http://host/'); assert.equal(frameName, 'target'); - return done(); + done(); }); - return w.loadURL("file://" + fixtures + "/pages/target-name.html"); + w.loadURL("file://" + fixtures + "/pages/target-name.html"); }); }); + describe('maximize event', function() { if (isCI) { return; } - return it('emits when window is maximized', function(done) { + + it('emits when window is maximized', function(done) { this.timeout(10000); w.once('maximize', function() { - return done(); + done(); }); w.show(); - return w.maximize(); + w.maximize(); }); }); + describe('unmaximize event', function() { if (isCI) { return; } - return it('emits when window is unmaximized', function(done) { + + it('emits when window is unmaximized', function(done) { this.timeout(10000); w.once('unmaximize', function() { - return done(); + done(); }); w.show(); w.maximize(); - return w.unmaximize(); + w.unmaximize(); }); }); + describe('minimize event', function() { if (isCI) { return; } - return it('emits when window is minimized', function(done) { + + it('emits when window is minimized', function(done) { this.timeout(10000); w.once('minimize', function() { - return done(); + done(); }); w.show(); - return w.minimize(); + w.minimize(); }); }); + xdescribe('beginFrameSubscription method', function() { - return it('subscribes frame updates', function(done) { + it('subscribes frame updates', function(done) { w.loadURL("file://" + fixtures + "/api/blank.html"); - return w.webContents.beginFrameSubscription(function(data) { + w.webContents.beginFrameSubscription(function(data) { assert.notEqual(data.length, 0); w.webContents.endFrameSubscription(); - return done(); + done(); }); }); }); @@ -472,13 +512,13 @@ describe('browser-window module', function() { }); describe('BrowserWindow options argument is optional', function() { - return it('should create a window with default size (800x600)', function() { + it('should create a window with default size (800x600)', function() { var size; w.destroy(); w = new BrowserWindow(); size = w.getSize(); assert.equal(size[0], 800); - return assert.equal(size[1], 600); + assert.equal(size[1], 600); }); }); From cead84d5d118bfc6b6a8d5418474959fd3021c54 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 10:18:01 -0800 Subject: [PATCH 10/22] Add failing spec --- spec/api-browser-window-spec.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 69b895c366d..d91e9d410e0 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -658,4 +658,12 @@ describe('browser-window module', function() { }); }); }); + + describe('window.webContents.send(channel, args...)', function() { + it('throws an error when the channel is missing', function() { + assert.throws(function () { + w.webContents.send(); + }, 'channel must be specified'); + }); + }); }); From c94f1fc857e0c07303e60d8df0e89e48808f207c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 10:20:55 -0800 Subject: [PATCH 11/22] Throw error when IPC channel is missing --- atom/browser/api/lib/web-contents.js | 3 +++ spec/api-browser-window-spec.js | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/atom/browser/api/lib/web-contents.js b/atom/browser/api/lib/web-contents.js index 08252923fc2..8dde10df4d1 100644 --- a/atom/browser/api/lib/web-contents.js +++ b/atom/browser/api/lib/web-contents.js @@ -78,6 +78,9 @@ let wrapWebContents = function(webContents) { webContents.send = function() { var args = 2 <= arguments.length ? slice.call(arguments, 1) : []; var channel = arguments[0]; + if (channel == null) { + throw new Error('channel must be specified'); + } return this._send(channel, slice.call(args)); }; diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index d91e9d410e0..ee34ba2c576 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -664,6 +664,10 @@ describe('browser-window module', function() { assert.throws(function () { w.webContents.send(); }, 'channel must be specified'); + + assert.throws(function () { + w.webContents.send(null); + }, 'channel must be specified'); }); }); }); From 3e399d09d7bdcd21154f65a233e487ca2c65c15f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 10:24:48 -0800 Subject: [PATCH 12/22] Match existing function style --- spec/api-browser-window-spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index ee34ba2c576..cb041a9320d 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -661,11 +661,11 @@ describe('browser-window module', function() { describe('window.webContents.send(channel, args...)', function() { it('throws an error when the channel is missing', function() { - assert.throws(function () { + assert.throws(function() { w.webContents.send(); }, 'channel must be specified'); - assert.throws(function () { + assert.throws(function() { w.webContents.send(null); }, 'channel must be specified'); }); From 704bd4d191a399107a0a3ea187628a851940adb5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 10:34:50 -0800 Subject: [PATCH 13/22] Improve error message --- atom/browser/api/lib/web-contents.js | 2 +- spec/api-browser-window-spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/lib/web-contents.js b/atom/browser/api/lib/web-contents.js index 8dde10df4d1..e0c16999c72 100644 --- a/atom/browser/api/lib/web-contents.js +++ b/atom/browser/api/lib/web-contents.js @@ -79,7 +79,7 @@ let wrapWebContents = function(webContents) { var args = 2 <= arguments.length ? slice.call(arguments, 1) : []; var channel = arguments[0]; if (channel == null) { - throw new Error('channel must be specified'); + throw new Error('Missing required channel argument'); } return this._send(channel, slice.call(args)); }; diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index cb041a9320d..d59eb9a8baa 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -663,11 +663,11 @@ describe('browser-window module', function() { it('throws an error when the channel is missing', function() { assert.throws(function() { w.webContents.send(); - }, 'channel must be specified'); + }, 'Missing required channel argument'); assert.throws(function() { w.webContents.send(null); - }, 'channel must be specified'); + }, 'Missing required channel argument'); }); }); }); From a4d21cadfa3d6a7e706d1bae61b424e599301c08 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Feb 2016 10:27:05 -0800 Subject: [PATCH 14/22] Format webview spec post CoffeeScript conversion --- spec/webview-spec.js | 335 ++++++++++++++++++++++++------------------- 1 file changed, 188 insertions(+), 147 deletions(-) diff --git a/spec/webview-spec.js b/spec/webview-spec.js index cac5fb56b44..904dfcab6e0 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -1,166 +1,175 @@ -var assert, http, path, url; - -assert = require('assert'); - -path = require('path'); - -http = require('http'); - -url = require('url'); +const assert = require('assert'); +const path = require('path'); +const http = require('http'); +const url = require('url'); describe(' tag', function() { - var fixtures, webview; this.timeout(10000); - fixtures = path.join(__dirname, 'fixtures'); - webview = null; + + var fixtures = path.join(__dirname, 'fixtures'); + var webview = null; + beforeEach(function() { - return webview = new WebView; + webview = new WebView; }); + afterEach(function() { if (document.body.contains(webview)) { - return document.body.removeChild(webview); + document.body.removeChild(webview); } }); + describe('src attribute', function() { it('specifies the page to load', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'a'); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/a.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('navigates to new page when changed', function(done) { + + it('navigates to new page when changed', function(done) { var listener = function() { webview.src = "file://" + fixtures + "/pages/b.html"; webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'b'); - return done(); + done(); }); - return webview.removeEventListener('did-finish-load', listener); + webview.removeEventListener('did-finish-load', listener); }; webview.addEventListener('did-finish-load', listener); webview.src = "file://" + fixtures + "/pages/a.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('nodeintegration attribute', function() { it('inserts no node symbols when not set', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'undefined undefined undefined undefined'); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/c.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + it('inserts node symbols when set', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'function object object'); - return done(); + done(); }); webview.setAttribute('nodeintegration', 'on'); webview.src = "file://" + fixtures + "/pages/d.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + it('loads node symbols after POST navigation when set', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'function object object'); - return done(); + done(); }); webview.setAttribute('nodeintegration', 'on'); webview.src = "file://" + fixtures + "/pages/post.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + if (process.platform !== 'win32' || process.execPath.toLowerCase().indexOf('\\out\\d\\') === -1) { - return it('loads native modules when navigation happens', function(done) { + it('loads native modules when navigation happens', function(done) { var listener = function() { webview.removeEventListener('did-finish-load', listener); var listener2 = function(e) { assert.equal(e.message, 'function'); - return done(); + done(); }; webview.addEventListener('console-message', listener2); - return webview.reload(); + webview.reload(); }; webview.addEventListener('did-finish-load', listener); webview.setAttribute('nodeintegration', 'on'); webview.src = "file://" + fixtures + "/pages/native-module.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); } }); + describe('preload attribute', function() { it('loads the script before other scripts in window', function(done) { var listener; listener = function(e) { assert.equal(e.message, 'function object object'); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.setAttribute('preload', fixtures + "/module/preload.js"); webview.src = "file://" + fixtures + "/pages/e.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + it('preload script can still use "process" in required modules when nodeintegration is off', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'object undefined object'); - return done(); + done(); }); webview.setAttribute('preload', fixtures + "/module/preload-node-off.js"); webview.src = "file://" + fixtures + "/api/blank.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('receives ipc message in preload script', function(done) { + + it('receives ipc message in preload script', function(done) { var listener, listener2, message; message = 'boom!'; listener = function(e) { assert.equal(e.channel, 'pong'); assert.deepEqual(e.args, [message]); webview.removeEventListener('ipc-message', listener); - return done(); + done(); }; listener2 = function() { webview.send('ping', message); - return webview.removeEventListener('did-finish-load', listener2); + webview.removeEventListener('did-finish-load', listener2); }; webview.addEventListener('ipc-message', listener); webview.addEventListener('did-finish-load', listener2); webview.setAttribute('preload', fixtures + "/module/preload-ipc.js"); webview.src = "file://" + fixtures + "/pages/e.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('httpreferrer attribute', function() { - return it('sets the referrer url', function(done) { + it('sets the referrer url', function(done) { var listener, referrer; referrer = 'http://github.com/'; listener = function(e) { assert.equal(e.message, referrer); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.setAttribute('httpreferrer', referrer); webview.src = "file://" + fixtures + "/pages/referrer.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('useragent attribute', function() { - return it('sets the user agent', function(done) { + it('sets the user agent', function(done) { var listener, referrer; referrer = 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko'; listener = function(e) { assert.equal(e.message, referrer); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.setAttribute('useragent', referrer); webview.src = "file://" + fixtures + "/pages/useragent.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('disablewebsecurity attribute', function() { it('does not disable web security when not set', function(done) { var encoded, listener, src; @@ -169,164 +178,177 @@ describe(' tag', function() { listener = function(e) { assert(/Not allowed to load local resource/.test(e.message)); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.src = "data:text/html;base64," + encoded; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('disables web security when set', function(done) { + + it('disables web security when set', function(done) { var encoded, listener, src; src = " "; encoded = btoa(unescape(encodeURIComponent(src))); listener = function(e) { assert.equal(e.message, 'ok'); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.setAttribute('disablewebsecurity', ''); webview.src = "data:text/html;base64," + encoded; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); describe('partition attribute', function() { it('inserts no node symbols when not set', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'undefined undefined undefined undefined'); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/c.html"; webview.partition = 'test1'; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + it('inserts node symbols when set', function(done) { webview.addEventListener('console-message', function(e) { assert.equal(e.message, 'function object object'); - return done(); + done(); }); webview.setAttribute('nodeintegration', 'on'); webview.src = "file://" + fixtures + "/pages/d.html"; webview.partition = 'test2'; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + it('isolates storage for different id', function(done) { var listener; listener = function(e) { assert.equal(e.message, " 0"); webview.removeEventListener('console-message', listener); - return done(); + done(); }; window.localStorage.setItem('test', 'one'); webview.addEventListener('console-message', listener); webview.src = "file://" + fixtures + "/pages/partition/one.html"; webview.partition = 'test3'; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('uses current session storage when no id is provided', function(done) { + + it('uses current session storage when no id is provided', function(done) { var listener; listener = function(e) { assert.equal(e.message, "one 1"); webview.removeEventListener('console-message', listener); - return done(); + done(); }; window.localStorage.setItem('test', 'one'); webview.addEventListener('console-message', listener); webview.src = "file://" + fixtures + "/pages/partition/one.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('allowpopups attribute', function() { it('can not open new window when not set', function(done) { var listener; listener = function(e) { assert.equal(e.message, 'null'); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.src = "file://" + fixtures + "/pages/window-open-hide.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('can open new window when set', function(done) { + + it('can open new window when set', function(done) { var listener; listener = function(e) { assert.equal(e.message, 'window'); webview.removeEventListener('console-message', listener); - return done(); + done(); }; webview.addEventListener('console-message', listener); webview.setAttribute('allowpopups', 'on'); webview.src = "file://" + fixtures + "/pages/window-open-hide.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('new-window event', function() { it('emits when window.open is called', function(done) { webview.addEventListener('new-window', function(e) { assert.equal(e.url, 'http://host/'); assert.equal(e.frameName, 'host'); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/window-open.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('emits when link with target is called', function(done) { + + it('emits when link with target is called', function(done) { webview.addEventListener('new-window', function(e) { assert.equal(e.url, 'http://host/'); assert.equal(e.frameName, 'target'); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/target-name.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('ipc-message event', function() { - return it('emits when guest sends a ipc message to browser', function(done) { + it('emits when guest sends a ipc message to browser', function(done) { webview.addEventListener('ipc-message', function(e) { assert.equal(e.channel, 'channel'); assert.deepEqual(e.args, ['arg1', 'arg2']); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/ipc-message.html"; webview.setAttribute('nodeintegration', 'on'); - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('page-title-set event', function() { - return it('emits when title is set', function(done) { + it('emits when title is set', function(done) { webview.addEventListener('page-title-set', function(e) { assert.equal(e.title, 'test'); assert(e.explicitSet); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/a.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('page-favicon-updated event', function() { - return it('emits when favicon urls are received', function(done) { + it('emits when favicon urls are received', function(done) { webview.addEventListener('page-favicon-updated', function(e) { var pageUrl; assert.equal(e.favicons.length, 2); pageUrl = process.platform === 'win32' ? 'file:///C:/favicon.png' : 'file:///favicon.png'; assert.equal(e.favicons[0], pageUrl); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/a.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('will-navigate event', function() { - return it('emits when a url that leads to oustide of the page is clicked', function(done) { + it('emits when a url that leads to oustide of the page is clicked', function(done) { webview.addEventListener('will-navigate', function(e) { assert.equal(e.url, "http://host/"); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/webview-will-navigate.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('did-navigate event', function() { var p, pageUrl; p = path.join(fixtures, 'pages', 'webview-will-navigate.html'); @@ -336,13 +358,14 @@ describe(' tag', function() { slashes: true, pathname: p }); - return it('emits when a url that leads to outside of the page is clicked', function(done) { + + it('emits when a url that leads to outside of the page is clicked', function(done) { webview.addEventListener('did-navigate', function(e) { assert.equal(e.url, pageUrl); - return done(); + done(); }); webview.src = pageUrl; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); describe('did-navigate-in-page event', function() { @@ -357,20 +380,22 @@ describe(' tag', function() { }); webview.addEventListener('did-navigate-in-page', function(e) { assert.equal(e.url, pageUrl + "#test_content"); - return done(); + done(); }); webview.src = pageUrl; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); + it('emits when window.history.replaceState is called', function(done) { webview.addEventListener('did-navigate-in-page', function(e) { assert.equal(e.url, "http://host/"); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/webview-did-navigate-in-page-with-history.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('emits when window.location.hash is changed', function(done) { + + it('emits when window.location.hash is changed', function(done) { var p, pageUrl; p = path.join(fixtures, 'pages', 'webview-did-navigate-in-page-with-hash.html'); p = p.replace(/\\/g, '/'); @@ -381,94 +406,100 @@ describe(' tag', function() { }); webview.addEventListener('did-navigate-in-page', function(e) { assert.equal(e.url, pageUrl + "#test"); - return done(); + done(); }); webview.src = pageUrl; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('close event', function() { - return it('should fire when interior page calls window.close', function(done) { + it('should fire when interior page calls window.close', function(done) { webview.addEventListener('close', function() { - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/close.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('devtools-opened event', function() { - return it('should fire when webview.openDevTools() is called', function(done) { + it('should fire when webview.openDevTools() is called', function(done) { var listener; listener = function() { webview.removeEventListener('devtools-opened', listener); webview.closeDevTools(); - return done(); + done(); }; webview.addEventListener('devtools-opened', listener); webview.addEventListener('dom-ready', function() { - return webview.openDevTools(); + webview.openDevTools(); }); webview.src = "file://" + fixtures + "/pages/base-page.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('devtools-closed event', function() { - return it('should fire when webview.closeDevTools() is called', function(done) { + it('should fire when webview.closeDevTools() is called', function(done) { var listener, listener2; listener2 = function() { webview.removeEventListener('devtools-closed', listener2); - return done(); + done(); }; listener = function() { webview.removeEventListener('devtools-opened', listener); - return webview.closeDevTools(); + webview.closeDevTools(); }; webview.addEventListener('devtools-opened', listener); webview.addEventListener('devtools-closed', listener2); webview.addEventListener('dom-ready', function() { - return webview.openDevTools(); + webview.openDevTools(); }); webview.src = "file://" + fixtures + "/pages/base-page.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('devtools-focused event', function() { - return it('should fire when webview.openDevTools() is called', function(done) { + it('should fire when webview.openDevTools() is called', function(done) { var listener; listener = function() { webview.removeEventListener('devtools-focused', listener); webview.closeDevTools(); - return done(); + done(); }; webview.addEventListener('devtools-focused', listener); webview.addEventListener('dom-ready', function() { - return webview.openDevTools(); + webview.openDevTools(); }); webview.src = "file://" + fixtures + "/pages/base-page.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('.reload()', function() { - return it('should emit beforeunload handler', function(done) { + it('should emit beforeunload handler', function(done) { var listener, listener2; listener = function(e) { assert.equal(e.channel, 'onbeforeunload'); webview.removeEventListener('ipc-message', listener); - return done(); + done(); }; listener2 = function() { webview.reload(); - return webview.removeEventListener('did-finish-load', listener2); + webview.removeEventListener('did-finish-load', listener2); }; webview.addEventListener('ipc-message', listener); webview.addEventListener('did-finish-load', listener2); webview.setAttribute('nodeintegration', 'on'); webview.src = "file://" + fixtures + "/pages/beforeunload-false.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('.clearHistory()', function() { - return it('should clear the navigation history', function(done) { + it('should clear the navigation history', function(done) { var listener; listener = function(e) { assert.equal(e.channel, 'history'); @@ -477,18 +508,19 @@ describe(' tag', function() { webview.clearHistory(); assert(!webview.canGoBack()); webview.removeEventListener('ipc-message', listener); - return done(); + done(); }; webview.addEventListener('ipc-message', listener); webview.setAttribute('nodeintegration', 'on'); webview.src = "file://" + fixtures + "/pages/history.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('basic auth', function() { var auth; auth = require('basic-auth'); - return it('should authenticate with correct credentials', function(done) { + it('should authenticate with correct credentials', function(done) { var message, server; message = 'Authenticated'; server = http.createServer(function(req, res) { @@ -499,67 +531,71 @@ describe(' tag', function() { } else { res.end('failed'); } - return server.close(); + server.close(); }); - return server.listen(0, '127.0.0.1', function() { + server.listen(0, '127.0.0.1', function() { var port; port = server.address().port; webview.addEventListener('ipc-message', function(e) { assert.equal(e.channel, message); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/basic-auth.html?port=" + port; webview.setAttribute('nodeintegration', 'on'); - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); }); + describe('dom-ready event', function() { - return it('emits when document is loaded', function(done) { + it('emits when document is loaded', function(done) { var server; server = http.createServer(function() {}); - return server.listen(0, '127.0.0.1', function() { + server.listen(0, '127.0.0.1', function() { var port; port = server.address().port; webview.addEventListener('dom-ready', function() { - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/dom-ready.html?port=" + port; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); }); + describe('executeJavaScript', function() { if (process.env.TRAVIS !== 'true') { return; } - return it('should support user gesture', function(done) { + + it('should support user gesture', function(done) { var listener, listener2; listener = function() { webview.removeEventListener('enter-html-full-screen', listener); - return done(); + done(); }; listener2 = function() { var jsScript; jsScript = 'document.getElementsByTagName("video")[0].webkitRequestFullScreen()'; webview.executeJavaScript(jsScript, true); - return webview.removeEventListener('did-finish-load', listener2); + webview.removeEventListener('did-finish-load', listener2); }; webview.addEventListener('enter-html-full-screen', listener); webview.addEventListener('did-finish-load', listener2); webview.src = "file://" + fixtures + "/pages/fullscreen.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('sendInputEvent', function() { it('can send keyboard event', function(done) { webview.addEventListener('ipc-message', function(e) { assert.equal(e.channel, 'keyup'); assert.deepEqual(e.args, [67, true, false]); - return done(); + done(); }); webview.addEventListener('dom-ready', function() { - return webview.sendInputEvent({ + webview.sendInputEvent({ type: 'keyup', keyCode: 'c', modifiers: ['shift'] @@ -567,16 +603,17 @@ describe(' tag', function() { }); webview.src = "file://" + fixtures + "/pages/onkeyup.html"; webview.setAttribute('nodeintegration', 'on'); - return document.body.appendChild(webview); + document.body.appendChild(webview); }); - return it('can send mouse event', function(done) { + + it('can send mouse event', function(done) { webview.addEventListener('ipc-message', function(e) { assert.equal(e.channel, 'mouseup'); assert.deepEqual(e.args, [10, 20, false, true]); - return done(); + done(); }); webview.addEventListener('dom-ready', function() { - return webview.sendInputEvent({ + webview.sendInputEvent({ type: 'mouseup', modifiers: ['ctrl'], x: 10, @@ -585,26 +622,28 @@ describe(' tag', function() { }); webview.src = "file://" + fixtures + "/pages/onmouseup.html"; webview.setAttribute('nodeintegration', 'on'); - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('media-started-playing media-paused events', function() { - return it('emits when audio starts and stops playing', function(done) { + it('emits when audio starts and stops playing', function(done) { var audioPlayed; audioPlayed = false; webview.addEventListener('media-started-playing', function() { - return audioPlayed = true; + audioPlayed = true; }); webview.addEventListener('media-paused', function() { assert(audioPlayed); - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/audio.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('found-in-page event', function() { - return it('emits when a request is made', function(done) { + it('emits when a request is made', function(done) { var listener, listener2, requestId; requestId = null; listener = function(e) { @@ -612,27 +651,29 @@ describe(' tag', function() { if (e.result.finalUpdate) { assert.equal(e.result.matches, 3); webview.stopFindInPage("clearSelection"); - return done(); + done(); } }; listener2 = function() { - return requestId = webview.findInPage("virtual"); + requestId = webview.findInPage("virtual"); }; webview.addEventListener('found-in-page', listener); webview.addEventListener('did-finish-load', listener2); webview.src = "file://" + fixtures + "/pages/content.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + xdescribe('did-change-theme-color event', function() { - return it('emits when theme color changes', function(done) { + it('emits when theme color changes', function(done) { webview.addEventListener('did-change-theme-color', function() { - return done(); + done(); }); webview.src = "file://" + fixtures + "/pages/theme-color.html"; - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + describe('permission-request event', function() { function setUpRequestHandler(webview, requested_permission) { const session = require('electron').remote.session; @@ -645,7 +686,7 @@ describe(' tag', function() { session.fromPartition(webview.partition).setPermissionRequestHandler(listener); } - it ('emits when using navigator.getUserMedia api', function(done) { + it('emits when using navigator.getUserMedia api', function(done) { webview.addEventListener('ipc-message', function(e) { assert(e.channel, 'message'); assert(e.args, ['PermissionDeniedError']); @@ -658,7 +699,7 @@ describe(' tag', function() { document.body.appendChild(webview); }); - it ('emits when using navigator.geolocation api', function(done) { + it('emits when using navigator.geolocation api', function(done) { webview.addEventListener('ipc-message', function(e) { assert(e.channel, 'message'); assert(e.args, ['ERROR(1): User denied Geolocation']); @@ -671,7 +712,7 @@ describe(' tag', function() { document.body.appendChild(webview); }); - it ('emits when using navigator.requestMIDIAccess api', function(done) { + it('emits when using navigator.requestMIDIAccess api', function(done) { webview.addEventListener('ipc-message', function(e) { assert(e.channel, 'message'); assert(e.args, ['SecurityError']); From 6bc48ba123f31148f9d41790447ff0c58fd16b70 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Feb 2016 10:48:07 -0800 Subject: [PATCH 15/22] Add failing spec for custom error message --- spec/webview-spec.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 904dfcab6e0..faafec73db3 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -561,6 +561,17 @@ describe(' tag', function() { document.body.appendChild(webview); }); }); + + it('throws a custom error when an API method is called before the event is emitted', function() { + var readyError = null; + try { + webview.stop(); + } catch (error) { + readyError = error; + } + + assert.equal(readyError.message, 'stop can only be called after the dom-ready event is emitted'); + }); }); describe('executeJavaScript', function() { From 8cacd0b931fe842afe3c54e618344924dc3fc0f6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Feb 2016 10:55:32 -0800 Subject: [PATCH 16/22] Throw custom error when WebView API is unavailable --- atom/renderer/lib/web-view/web-view.js | 11 +++++++---- spec/webview-spec.js | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 5257f0c12f9..4e34d2e5592 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -404,10 +404,13 @@ var registerWebViewElement = function() { // Forward proto.foo* method calls to WebViewImpl.foo*. createBlockHandler = function(m) { return function() { - var args, internal, ref1; - args = 1 <= arguments.length ? slice.call(arguments, 0) : []; - internal = v8Util.getHiddenValue(this, 'internal'); - return (ref1 = internal.webContents)[m].apply(ref1, args); + var args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + var internal = v8Util.getHiddenValue(this, 'internal'); + if (internal.webContents) { + return internal.webContents[m].apply(internal.webContents, args); + } else { + throw new Error('Cannot call ' + m + ' before the dom-ready event is emitted') + } }; }; for (i = 0, len = methods.length; i < len; i++) { diff --git a/spec/webview-spec.js b/spec/webview-spec.js index faafec73db3..072a51f36a5 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -570,7 +570,7 @@ describe(' tag', function() { readyError = error; } - assert.equal(readyError.message, 'stop can only be called after the dom-ready event is emitted'); + assert.equal(readyError.message, 'Cannot call stop before the dom-ready event is emitted'); }); }); From 42a8674cea58ab3fe73c391e21a403ee66b40d86 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Feb 2016 11:05:17 -0800 Subject: [PATCH 17/22] Add missing semicolon --- atom/renderer/lib/web-view/web-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 4e34d2e5592..29af92e9bd3 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -409,7 +409,7 @@ var registerWebViewElement = function() { if (internal.webContents) { return internal.webContents[m].apply(internal.webContents, args); } else { - throw new Error('Cannot call ' + m + ' before the dom-ready event is emitted') + throw new Error('Cannot call ' + m + ' before the dom-ready event is emitted'); } }; }; From 674af4211c403e767882781c44ba282c591b84af Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 13:24:58 -0800 Subject: [PATCH 18/22] Use interpolated string --- atom/renderer/lib/web-view/web-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 29af92e9bd3..49440527c40 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -409,7 +409,7 @@ var registerWebViewElement = function() { if (internal.webContents) { return internal.webContents[m].apply(internal.webContents, args); } else { - throw new Error('Cannot call ' + m + ' before the dom-ready event is emitted'); + throw new Error(`Cannot call ${m} before the dom-ready event is emitted`); } }; }; From bad48169764278154cb47e218024ed224de9ae7d Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 13:51:35 -0800 Subject: [PATCH 19/22] Expand error message --- atom/renderer/lib/web-view/web-view.js | 2 +- spec/webview-spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 49440527c40..9cc6ac4e880 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -409,7 +409,7 @@ var registerWebViewElement = function() { if (internal.webContents) { return internal.webContents[m].apply(internal.webContents, args); } else { - throw new Error(`Cannot call ${m} before the dom-ready event is emitted`); + throw new Error(`Cannot call ${m} because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.`); } }; }; diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 072a51f36a5..0b6572a5084 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -570,7 +570,7 @@ describe(' tag', function() { readyError = error; } - assert.equal(readyError.message, 'Cannot call stop before the dom-ready event is emitted'); + assert.equal(readyError.message, 'Cannot call stop because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.'); }); }); From da6ebac7424e931a5789b95a5b6c70effacfffd1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 13:53:10 -0800 Subject: [PATCH 20/22] Use assert.throws --- spec/webview-spec.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 0b6572a5084..eb1427e0855 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -563,14 +563,9 @@ describe(' tag', function() { }); it('throws a custom error when an API method is called before the event is emitted', function() { - var readyError = null; - try { - webview.stop(); - } catch (error) { - readyError = error; - } - - assert.equal(readyError.message, 'Cannot call stop because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.'); + assert.throws(function () { + webview.stop() + }, 'Cannot call stop because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.'); }); }); From 9609b36b3cab670b5274d4c77b767ba1123db4b7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Feb 2016 13:55:49 -0800 Subject: [PATCH 21/22] Add missing semicolon --- spec/webview-spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/webview-spec.js b/spec/webview-spec.js index eb1427e0855..973c1c24031 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -564,7 +564,7 @@ describe(' tag', function() { it('throws a custom error when an API method is called before the event is emitted', function() { assert.throws(function () { - webview.stop() + webview.stop(); }, 'Cannot call stop because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.'); }); }); From 042825e8fb40244c665b720266ff7112333d5eb2 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Feb 2016 13:32:34 -0800 Subject: [PATCH 22/22] emmitted -> emitted --- atom/renderer/lib/web-view/web-view.js | 2 +- spec/webview-spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view.js b/atom/renderer/lib/web-view/web-view.js index 9cc6ac4e880..7e38bb33715 100644 --- a/atom/renderer/lib/web-view/web-view.js +++ b/atom/renderer/lib/web-view/web-view.js @@ -409,7 +409,7 @@ var registerWebViewElement = function() { if (internal.webContents) { return internal.webContents[m].apply(internal.webContents, args); } else { - throw new Error(`Cannot call ${m} because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.`); + throw new Error(`Cannot call ${m} because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emitted before this method can be called.`); } }; }; diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 973c1c24031..a18e152ea6a 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -565,7 +565,7 @@ describe(' tag', function() { it('throws a custom error when an API method is called before the event is emitted', function() { assert.throws(function () { webview.stop(); - }, 'Cannot call stop because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emmitted before this method can be called.'); + }, 'Cannot call stop because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emitted before this method can be called.'); }); });