diff --git a/spec-main/api-web-frame-spec.ts b/spec-main/api-web-frame-spec.ts index f7d9d9ffb138..5b6b71b93f4b 100644 --- a/spec-main/api-web-frame-spec.ts +++ b/spec-main/api-web-frame-spec.ts @@ -1,23 +1,22 @@ import { expect } from 'chai'; import * as path from 'path'; -import { BrowserWindow, ipcMain } from 'electron/main'; -import { closeAllWindows } from './window-helpers'; +import { BrowserWindow, ipcMain, WebContents } from 'electron/main'; import { emittedOnce } from './events-helpers'; +import { defer } from './spec-helpers'; describe('webFrame module', () => { const fixtures = path.resolve(__dirname, '..', 'spec', 'fixtures'); - afterEach(closeAllWindows); - it('can use executeJavaScript', async () => { const w = new BrowserWindow({ - show: true, + show: false, webPreferences: { nodeIntegration: true, contextIsolation: true, preload: path.join(fixtures, 'pages', 'world-safe-preload.js') } }); + defer(() => w.close()); const isSafe = emittedOnce(ipcMain, 'executejs-safe'); w.loadURL('about:blank'); const [, wasSafe] = await isSafe; @@ -26,13 +25,14 @@ describe('webFrame module', () => { it('can use executeJavaScript and catch conversion errors', async () => { const w = new BrowserWindow({ - show: true, + show: false, webPreferences: { nodeIntegration: true, contextIsolation: true, preload: path.join(fixtures, 'pages', 'world-safe-preload-error.js') } }); + defer(() => w.close()); const execError = emittedOnce(ipcMain, 'executejs-safe'); w.loadURL('about:blank'); const [, error] = await execError; @@ -48,6 +48,7 @@ describe('webFrame module', () => { contextIsolation: false } }); + defer(() => w.close()); await w.loadFile(path.join(fixtures, 'pages', 'webframe-spell-check.html')); w.focus(); await w.webContents.executeJavaScript('document.querySelector("input").focus()', true); @@ -70,4 +71,126 @@ describe('webFrame module', () => { expect(words.sort()).to.deep.equal(['spleling', 'test', 'you\'re', 'you', 're'].sort()); expect(callbackDefined).to.be.true(); }); + + describe('api', () => { + let w: WebContents; + before(async () => { + const win = new BrowserWindow({ show: false, webPreferences: { contextIsolation: false, nodeIntegration: true } }); + await win.loadURL('about:blank'); + w = win.webContents; + await w.executeJavaScript('webFrame = require(\'electron\').webFrame; null'); + }); + it('top is self for top frame', async () => { + const equal = await w.executeJavaScript('webFrame.top.context === webFrame.context'); + expect(equal).to.be.true(); + }); + + it('opener is null for top frame', async () => { + const equal = await w.executeJavaScript('webFrame.opener === null'); + expect(equal).to.be.true(); + }); + + it('firstChild is null for top frame', async () => { + const equal = await w.executeJavaScript('webFrame.firstChild === null'); + expect(equal).to.be.true(); + }); + + it('getFrameForSelector() does not crash when not found', async () => { + const equal = await w.executeJavaScript('webFrame.getFrameForSelector(\'unexist-selector\') === null'); + expect(equal).to.be.true(); + }); + + it('findFrameByName() does not crash when not found', async () => { + const equal = await w.executeJavaScript('webFrame.findFrameByName(\'unexist-name\') === null'); + expect(equal).to.be.true(); + }); + + it('findFrameByRoutingId() does not crash when not found', async () => { + const equal = await w.executeJavaScript('webFrame.findFrameByRoutingId(-1) === null'); + expect(equal).to.be.true(); + }); + + describe('executeJavaScript', () => { + before(() => { + w.executeJavaScript(` + childFrameElement = document.createElement('iframe'); + document.body.appendChild(childFrameElement); + childFrame = webFrame.firstChild; + null + `); + }); + + after(() => { + w.executeJavaScript(` + childFrameElement.remove(); + null + `); + }); + + it('executeJavaScript() yields results via a promise and a sync callback', async () => { + const { callbackResult, callbackError, result } = await w.executeJavaScript(`new Promise(resolve => { + let callbackResult, callbackError; + childFrame + .executeJavaScript('1 + 1', (result, error) => { + callbackResult = result; + callbackError = error; + }).then(result => resolve({callbackResult, callbackError, result})) + })`); + + expect(callbackResult).to.equal(2); + expect(callbackError).to.be.undefined(); + expect(result).to.equal(2); + }); + + it('executeJavaScriptInIsolatedWorld() yields results via a promise and a sync callback', async () => { + const { callbackResult, callbackError, result } = await w.executeJavaScript(`new Promise(resolve => { + let callbackResult, callbackError; + childFrame + .executeJavaScriptInIsolatedWorld(999, [{code: '1 + 1'}], (result, error) => { + callbackResult = result; + callbackError = error; + }).then(result => resolve({callbackResult, callbackError, result})) + })`); + + expect(callbackResult).to.equal(2); + expect(callbackError).to.be.undefined(); + expect(result).to.equal(2); + }); + + it('executeJavaScript() yields errors via a promise and a sync callback', async () => { + const { callbackResult, callbackError, error } = await w.executeJavaScript(`new Promise(resolve => { + let callbackResult, callbackError; + childFrame + .executeJavaScript('thisShouldProduceAnError()', (result, error) => { + callbackResult = result; + callbackError = error; + }).then(result => {throw new Error}, error => resolve({callbackResult, callbackError, error})) + })`); + + expect(callbackResult).to.be.undefined(); + expect(callbackError).to.be.an('error'); + expect(error).to.be.an('error'); + }); + + it('executeJavaScriptInIsolatedWorld() yields errors via a promise and a sync callback', async () => { + const { callbackResult, callbackError, error } = await w.executeJavaScript(`new Promise(resolve => { + let callbackResult, callbackError; + childFrame + .executeJavaScriptInIsolatedWorld(999, [{code: 'thisShouldProduceAnError()'}], (result, error) => { + callbackResult = result; + callbackError = error; + }).then(result => {throw new Error}, error => resolve({callbackResult, callbackError, error})) + })`); + + expect(callbackResult).to.be.undefined(); + expect(callbackError).to.be.an('error'); + expect(error).to.be.an('error'); + }); + + it('executeJavaScript(InIsolatedWorld) can be used without a callback', async () => { + expect(await w.executeJavaScript('webFrame.executeJavaScript(\'1 + 1\')')).to.equal(2); + expect(await w.executeJavaScript('webFrame.executeJavaScriptInIsolatedWorld(999, [{code: \'1 + 1\'}])')).to.equal(2); + }); + }); + }); }); diff --git a/spec/api-web-frame-spec.js b/spec/api-web-frame-spec.js deleted file mode 100644 index a9a76839530b..000000000000 --- a/spec/api-web-frame-spec.js +++ /dev/null @@ -1,114 +0,0 @@ -const { expect } = require('chai'); -const { webFrame } = require('electron'); - -describe('webFrame module', function () { - it('top is self for top frame', () => { - expect(webFrame.top.context).to.equal(webFrame.context); - }); - - it('opener is null for top frame', () => { - expect(webFrame.opener).to.be.null(); - }); - - it('firstChild is null for top frame', () => { - expect(webFrame.firstChild).to.be.null(); - }); - - it('getFrameForSelector() does not crash when not found', () => { - expect(webFrame.getFrameForSelector('unexist-selector')).to.be.null(); - }); - - it('findFrameByName() does not crash when not found', () => { - expect(webFrame.findFrameByName('unexist-name')).to.be.null(); - }); - - it('findFrameByRoutingId() does not crash when not found', () => { - expect(webFrame.findFrameByRoutingId(-1)).to.be.null(); - }); - - describe('executeJavaScript', () => { - let childFrameElement, childFrame; - - before(() => { - childFrameElement = document.createElement('iframe'); - document.body.appendChild(childFrameElement); - childFrame = webFrame.firstChild; - }); - - after(() => { - childFrameElement.remove(); - }); - - it('executeJavaScript() yields results via a promise and a sync callback', async () => { - let callbackResult, callbackError; - - const executeJavaScript = childFrame - .executeJavaScript('1 + 1', (result, error) => { - callbackResult = result; - callbackError = error; - }); - - expect(callbackResult).to.equal(2); - expect(callbackError).to.be.undefined(); - - const promiseResult = await executeJavaScript; - expect(promiseResult).to.equal(2); - }); - - it('executeJavaScriptInIsolatedWorld() yields results via a promise and a sync callback', async () => { - let callbackResult, callbackError; - - const executeJavaScriptInIsolatedWorld = childFrame - .executeJavaScriptInIsolatedWorld(999, [{ code: '1 + 1' }], (result, error) => { - callbackResult = result; - callbackError = error; - }); - - expect(callbackResult).to.equal(2); - expect(callbackError).to.be.undefined(); - - const promiseResult = await executeJavaScriptInIsolatedWorld; - expect(promiseResult).to.equal(2); - }); - - it('executeJavaScript() yields errors via a promise and a sync callback', async () => { - let callbackResult, callbackError; - - const executeJavaScript = childFrame - .executeJavaScript('thisShouldProduceAnError()', (result, error) => { - callbackResult = result; - callbackError = error; - }); - - expect(callbackResult).to.be.undefined(); - expect(callbackError).to.be.an('error'); - - await expect(executeJavaScript).to.eventually.be.rejected('error is expected'); - }); - - // executeJavaScriptInIsolatedWorld is failing to detect exec errors and is neither - // rejecting nor passing the error to the callback. This predates the reintroduction - // of the callback so will not be fixed as part of the callback PR - // if/when this is fixed the test can be uncommented. - // - // it('executeJavaScriptInIsolatedWorld() yields errors via a promise and a sync callback', done => { - // let callbackResult, callbackError - // - // const executeJavaScriptInIsolatedWorld = childFrame - // .executeJavaScriptInIsolatedWorld(999, [{ code: 'thisShouldProduceAnError()' }], (result, error) => { - // callbackResult = result - // callbackError = error - // }); - // - // expect(callbackResult).to.be.undefined() - // expect(callbackError).to.be.an('error') - // - // expect(executeJavaScriptInIsolatedWorld).to.eventually.be.rejected('error is expected'); - // }) - - it('executeJavaScript(InIsolatedWorld) can be used without a callback', async () => { - expect(await webFrame.executeJavaScript('1 + 1')).to.equal(2); - expect(await webFrame.executeJavaScriptInIsolatedWorld(999, [{ code: '1 + 1' }])).to.equal(2); - }); - }); -});