Browse Source

test: move some BrowserWindow specs to the main runner (#18551)

Jeremy Apthorp 5 years ago
parent
commit
901cdb22e3

+ 16 - 2
docs/api/web-contents.md

@@ -70,10 +70,24 @@ Returns:
 * `frameProcessId` Integer
 * `frameRoutingId` Integer
 
-This event is like `did-finish-load` but emitted when the load failed or was
-cancelled, e.g. `window.stop()` is invoked.
+This event is like `did-finish-load` but emitted when the load failed.
 The full list of error codes and their meaning is available [here](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h).
 
+#### Event: 'did-fail-provisional-load'
+
+Returns:
+
+* `event` Event
+* `errorCode` Integer
+* `errorDescription` String
+* `validatedURL` String
+* `isMainFrame` Boolean
+* `frameProcessId` Integer
+* `frameRoutingId` Integer
+
+This event is like `did-fail-load` but emitted when the load was cancelled
+(e.g. `window.stop()` was invoked).
+
 #### Event: 'did-frame-finish-load'
 
 Returns:

+ 3 - 3
docs/api/web-request.md

@@ -82,11 +82,11 @@ The `callback` has to be called with an `response` object.
     * `resourceType` String
     * `referrer` String
     * `timestamp` Double
-    * `requestHeaders` Object
+    * `requestHeaders` Record<string, string>
   * `callback` Function
     * `response` Object
       * `cancel` Boolean (optional)
-      * `requestHeaders` Object (optional) - When provided, request will be made
+      * `requestHeaders` Record<string, string> (optional) - When provided, request will be made
   with these headers.
 
 The `listener` will be called with `listener(details, callback)` before sending
@@ -109,7 +109,7 @@ The `callback` has to be called with an `response` object.
     * `resourceType` String
     * `referrer` String
     * `timestamp` Double
-    * `requestHeaders` Object
+    * `requestHeaders` Record<string, string>
 
 The `listener` will be called with `listener(details)` just before a request is
 going to be sent to the server, modifications of previous `onBeforeSendHeaders`

+ 539 - 0
spec-main/api-browser-window-spec.ts

@@ -0,0 +1,539 @@
+import * as chai from 'chai'
+import * as chaiAsPromised from 'chai-as-promised'
+import * as path from 'path'
+import * as fs from 'fs'
+import * as qs from 'querystring'
+import * as http from 'http'
+import { AddressInfo } from 'net'
+import { app, BrowserWindow, ipcMain, OnBeforeSendHeadersListenerDetails } from 'electron'
+import { emittedOnce } from './events-helpers';
+import { closeWindow } from './window-helpers';
+
+const { expect } = chai
+
+chai.use(chaiAsPromised)
+
+const fixtures = path.resolve(__dirname, '..', 'spec', 'fixtures')
+
+describe('BrowserWindow module', () => {
+  describe('BrowserWindow constructor', () => {
+    it('allows passing void 0 as the webContents', async () => {
+      expect(() => {
+        const w = new BrowserWindow({
+          show: false,
+          // apparently void 0 had different behaviour from undefined in the
+          // issue that this test is supposed to catch.
+          webContents: void 0
+        } as any)
+        w.destroy()
+      }).not.to.throw()
+    })
+  })
+
+  describe('BrowserWindow.close()', () => {
+    let w = null as unknown as BrowserWindow
+    beforeEach(() => {
+      w = new BrowserWindow({show: false, webPreferences: {nodeIntegration: true}})
+    })
+    afterEach(async () => {
+      await closeWindow(w)
+      w = null as unknown as BrowserWindow
+    })
+
+    it('should emit unload handler', async () => {
+      await w.loadFile(path.join(fixtures, 'api', 'unload.html'))
+      const closed = emittedOnce(w, 'closed')
+      w.close()
+      await closed
+      const test = path.join(fixtures, 'api', 'unload')
+      const content = fs.readFileSync(test)
+      fs.unlinkSync(test)
+      expect(String(content)).to.equal('unload')
+    })
+    it('should emit beforeunload handler', async () => {
+      await w.loadFile(path.join(fixtures, 'api', 'beforeunload-false.html'))
+      const beforeunload = emittedOnce(w, 'onbeforeunload')
+      w.close()
+      await beforeunload
+    })
+
+    describe('when invoked synchronously inside navigation observer', () => {
+      let server: http.Server = null as unknown as http.Server
+      let url: string = null as unknown as string
+
+      before((done) => {
+        server = http.createServer((request, response) => {
+          switch (request.url) {
+            case '/net-error':
+              response.destroy()
+              break
+            case '/301':
+              response.statusCode = 301
+              response.setHeader('Location', '/200')
+              response.end()
+              break
+            case '/200':
+              response.statusCode = 200
+              response.end('hello')
+              break
+            case '/title':
+              response.statusCode = 200
+              response.end('<title>Hello</title>')
+              break
+            default:
+              throw new Error(`unsupported endpoint: ${request.url}`)
+          }
+        }).listen(0, '127.0.0.1', () => {
+          url = 'http://127.0.0.1:' + (server.address() as AddressInfo).port
+          done()
+        })
+      })
+
+      after(() => {
+        server.close()
+      })
+
+      const events = [
+        { name: 'did-start-loading', path: '/200' },
+        { name: 'dom-ready', path: '/200' },
+        { name: 'page-title-updated', path: '/title' },
+        { name: 'did-stop-loading', path: '/200' },
+        { name: 'did-finish-load', path: '/200' },
+        { name: 'did-frame-finish-load', path: '/200' },
+        { name: 'did-fail-load', path: '/net-error' }
+      ]
+
+      for (const {name, path} of events) {
+        it(`should not crash when closed during ${name}`, async () => {
+          const w = new BrowserWindow({ show: false })
+          w.webContents.once((name as any), () => {
+            w.close()
+          })
+          const destroyed = emittedOnce(w.webContents, 'destroyed')
+          w.webContents.loadURL(url + path)
+          await destroyed
+        })
+      }
+    })
+  })
+
+  describe('window.close()', () => {
+    let w = null as unknown as BrowserWindow
+    beforeEach(() => {
+      w = new BrowserWindow({show: false, webPreferences: {nodeIntegration: true}})
+    })
+    afterEach(async () => {
+      await closeWindow(w)
+      w = null as unknown as BrowserWindow
+    })
+
+    it('should emit unload event', async () => {
+      w.loadFile(path.join(fixtures, 'api', 'close.html'))
+      await emittedOnce(w, 'closed')
+      const test = path.join(fixtures, 'api', 'close')
+      const content = fs.readFileSync(test).toString()
+      fs.unlinkSync(test)
+      expect(content).to.equal('close')
+    })
+    it('should emit beforeunload event', async () => {
+      w.loadFile(path.join(fixtures, 'api', 'close-beforeunload-false.html'))
+      await emittedOnce(w, 'onbeforeunload')
+    })
+  })
+
+  describe('BrowserWindow.destroy()', () => {
+    let w = null as unknown as BrowserWindow
+    beforeEach(() => {
+      w = new BrowserWindow({show: false, webPreferences: {nodeIntegration: true}})
+    })
+    afterEach(async () => {
+      await closeWindow(w)
+      w = null as unknown as BrowserWindow
+    })
+
+    it('prevents users to access methods of webContents', async () => {
+      const contents = w.webContents
+      w.destroy()
+      await new Promise(setImmediate)
+      expect(() => {
+        contents.getProcessId()
+      }).to.throw('Object has been destroyed')
+    })
+    it('should not crash when destroying windows with pending events', () => {
+      const focusListener = () => {}
+      app.on('browser-window-focus', focusListener)
+      const windowCount = 3
+      const windowOptions = {
+        show: false,
+        width: 400,
+        height: 400,
+        webPreferences: {
+          backgroundThrottling: false
+        }
+      }
+      const windows = Array.from(Array(windowCount)).map(x => new BrowserWindow(windowOptions))
+      windows.forEach(win => win.show())
+      windows.forEach(win => win.focus())
+      windows.forEach(win => win.destroy())
+      app.removeListener('browser-window-focus', focusListener)
+    })
+  })
+
+  describe('BrowserWindow.loadURL(url)', () => {
+    let w = null as unknown as BrowserWindow
+    beforeEach(() => {
+      w = new BrowserWindow({show: false, webPreferences: {nodeIntegration: true}})
+    })
+    afterEach(async () => {
+      await closeWindow(w)
+      w = null as unknown as BrowserWindow
+    })
+    let server = null as unknown as http.Server
+    let url = null as unknown as string
+    let postData = null as any
+    before((done) => {
+      const filePath = path.join(fixtures, 'pages', 'a.html')
+      const fileStats = fs.statSync(filePath)
+      postData = [
+        {
+          type: 'rawData',
+          bytes: Buffer.from('username=test&file=')
+        },
+        {
+          type: 'file',
+          filePath: filePath,
+          offset: 0,
+          length: fileStats.size,
+          modificationTime: fileStats.mtime.getTime() / 1000
+        }
+      ]
+      server = http.createServer((req, res) => {
+        function respond () {
+          if (req.method === 'POST') {
+            let body = ''
+            req.on('data', (data) => {
+              if (data) body += data
+            })
+            req.on('end', () => {
+              const parsedData = qs.parse(body)
+              fs.readFile(filePath, (err, data) => {
+                if (err) return
+                if (parsedData.username === 'test' &&
+                    parsedData.file === data.toString()) {
+                  res.end()
+                }
+              })
+            })
+          } else if (req.url === '/302') {
+            res.setHeader('Location', '/200')
+            res.statusCode = 302
+            res.end()
+          } else {
+            res.end()
+          }
+        }
+        setTimeout(respond, req.url && req.url.includes('slow') ? 200 : 0)
+      })
+      server.listen(0, '127.0.0.1', () => {
+        url = `http://127.0.0.1:${(server.address() as AddressInfo).port}`
+        done()
+      })
+    })
+
+    after(() => {
+      server.close()
+    })
+
+    it('should emit did-start-loading event', (done) => {
+      w.webContents.on('did-start-loading', () => { done() })
+      w.loadURL('about:blank')
+    })
+    it('should emit ready-to-show event', (done) => {
+      w.on('ready-to-show', () => { done() })
+      w.loadURL('about:blank')
+    })
+    it('should emit did-fail-load event for files that do not exist', (done) => {
+      w.webContents.on('did-fail-load', (event, code, desc, url, isMainFrame) => {
+        expect(code).to.equal(-6)
+        expect(desc).to.equal('ERR_FILE_NOT_FOUND')
+        expect(isMainFrame).to.equal(true)
+        done()
+      })
+      w.loadURL('file://a.txt')
+    })
+    it('should emit did-fail-load event for invalid URL', (done) => {
+      w.webContents.on('did-fail-load', (event, code, desc, url, isMainFrame) => {
+        expect(desc).to.equal('ERR_INVALID_URL')
+        expect(code).to.equal(-300)
+        expect(isMainFrame).to.equal(true)
+        done()
+      })
+      w.loadURL('http://example:port')
+    })
+    it('should set `mainFrame = false` on did-fail-load events in iframes', (done) => {
+      w.webContents.on('did-fail-load', (event, code, desc, url, isMainFrame) => {
+        expect(isMainFrame).to.equal(false)
+        done()
+      })
+      w.loadFile(path.join(fixtures, 'api', 'did-fail-load-iframe.html'))
+    })
+    it('does not crash in did-fail-provisional-load handler', (done) => {
+      w.webContents.once('did-fail-provisional-load', () => {
+        w.loadURL('http://127.0.0.1:11111')
+        done()
+      })
+      w.loadURL('http://127.0.0.1:11111')
+    })
+    it('should emit did-fail-load event for URL exceeding character limit', (done) => {
+      w.webContents.on('did-fail-load', (event, code, desc, url, isMainFrame) => {
+        expect(desc).to.equal('ERR_INVALID_URL')
+        expect(code).to.equal(-300)
+        expect(isMainFrame).to.equal(true)
+        done()
+      })
+      const data = Buffer.alloc(2 * 1024 * 1024).toString('base64')
+      w.loadURL(`data:image/png;base64,${data}`)
+    })
+
+    it('should return a promise', () => {
+      const p = w.loadURL('about:blank')
+      expect(p).to.have.property('then')
+    })
+
+    it('should return a promise that resolves', async () => {
+      expect(w.loadURL('about:blank')).to.eventually.be.fulfilled
+    })
+
+    it('should return a promise that rejects on a load failure', async () => {
+      const data = Buffer.alloc(2 * 1024 * 1024).toString('base64')
+      const p = w.loadURL(`data:image/png;base64,${data}`)
+      await expect(p).to.eventually.be.rejected
+    })
+
+    it('should return a promise that resolves even if pushState occurs during navigation', async () => {
+      const p = w.loadURL('data:text/html,<script>window.history.pushState({}, "/foo")</script>')
+      await expect(p).to.eventually.be.fulfilled
+    })
+
+    describe('POST navigations', () => {
+      afterEach(() => { w.webContents.session.webRequest.onBeforeSendHeaders(null) })
+
+      it('supports specifying POST data', async () => {
+        await w.loadURL(url, { postData })
+      })
+      it('sets the content type header on URL encoded forms', async () => {
+        await w.loadURL(url)
+        const requestDetails: Promise<OnBeforeSendHeadersListenerDetails> = new Promise(resolve => {
+          w.webContents.session.webRequest.onBeforeSendHeaders((details, callback) => {
+            resolve(details)
+          })
+        })
+        w.webContents.executeJavaScript(`
+          form = document.createElement('form')
+          document.body.appendChild(form)
+          form.method = 'POST'
+          form.submit()
+        `)
+        const details = await requestDetails
+        expect(details.requestHeaders['Content-Type']).to.equal('application/x-www-form-urlencoded')
+      })
+      it('sets the content type header on multi part forms', async () => {
+        await w.loadURL(url)
+        const requestDetails: Promise<OnBeforeSendHeadersListenerDetails> = new Promise(resolve => {
+          w.webContents.session.webRequest.onBeforeSendHeaders((details, callback) => {
+            resolve(details)
+          })
+        })
+        w.webContents.executeJavaScript(`
+          form = document.createElement('form')
+          document.body.appendChild(form)
+          form.method = 'POST'
+          form.enctype = 'multipart/form-data'
+          file = document.createElement('input')
+          file.type = 'file'
+          file.name = 'file'
+          form.appendChild(file)
+          form.submit()
+        `)
+        const details = await requestDetails
+        expect(details.requestHeaders['Content-Type'].startsWith('multipart/form-data; boundary=----WebKitFormBoundary')).to.equal(true)
+      })
+    })
+
+    it('should support support base url for data urls', (done) => {
+      ipcMain.once('answer', (event, test) => {
+        expect(test).to.equal('test')
+        done()
+      })
+      w.loadURL('data:text/html,<script src="loaded-from-dataurl.js"></script>', { baseURLForDataURL: `file://${path.join(fixtures, 'api')}${path.sep}` })
+    })
+  })
+
+  describe('navigation events', () => {
+    let w = null as unknown as BrowserWindow
+    beforeEach(() => {
+      w = new BrowserWindow({show: false, webPreferences: {nodeIntegration: true}})
+    })
+    afterEach(async () => {
+      await closeWindow(w)
+      w = null as unknown as BrowserWindow
+    })
+
+    describe('will-navigate event', () => {
+      it('allows the window to be closed from the event listener', (done) => {
+        w.webContents.once('will-navigate', () => {
+          w.close()
+          done()
+        })
+        w.loadFile(path.join(fixtures, 'pages', 'will-navigate.html'))
+      })
+    })
+
+    describe('will-redirect event', () => {
+      let server = null as unknown as http.Server
+      let url = null as unknown as string
+      before((done) => {
+        server = http.createServer((req, res) => {
+          if (req.url === '/302') {
+            res.setHeader('Location', '/200')
+            res.statusCode = 302
+            res.end()
+          } else if (req.url === '/navigate-302') {
+            res.end(`<html><body><script>window.location='${url}/302'</script></body></html>`)
+          } else {
+            res.end()
+          }
+        })
+        server.listen(0, '127.0.0.1', () => {
+          url = `http://127.0.0.1:${(server.address() as AddressInfo).port}`
+          done()
+        })
+      })
+
+      after(() => {
+        server.close()
+      })
+      it('is emitted on redirects', (done) => {
+        w.webContents.on('will-redirect', (event, url) => {
+          done()
+        })
+        w.loadURL(`${url}/302`)
+      })
+
+      it('is emitted after will-navigate on redirects', (done) => {
+        let navigateCalled = false
+        w.webContents.on('will-navigate', () => {
+          navigateCalled = true
+        })
+        w.webContents.on('will-redirect', (event, url) => {
+          expect(navigateCalled).to.equal(true, 'should have called will-navigate first')
+          done()
+        })
+        w.loadURL(`${url}/navigate-302`)
+      })
+
+      it('is emitted before did-stop-loading on redirects', (done) => {
+        let stopCalled = false
+        w.webContents.on('did-stop-loading', () => {
+          stopCalled = true
+        })
+        w.webContents.on('will-redirect', (event, url) => {
+          expect(stopCalled).to.equal(false, 'should not have called did-stop-loading first')
+          done()
+        })
+        w.loadURL(`${url}/302`)
+      })
+
+      it('allows the window to be closed from the event listener', (done) => {
+        w.webContents.once('will-redirect', (event, input) => {
+          w.close()
+          done()
+        })
+        w.loadURL(`${url}/302`)
+      })
+
+      it.skip('can be prevented', (done) => {
+        w.webContents.once('will-redirect', (event) => {
+          event.preventDefault()
+        })
+        w.webContents.on('will-navigate', (e, url) => {
+          expect(url).to.equal(`${url}/302`)
+        })
+        w.webContents.on('did-stop-loading', () => {
+          expect(w.webContents.getURL()).to.equal(
+            `${url}/navigate-302`,
+            'url should not have changed after navigation event'
+          )
+          done()
+        })
+        w.webContents.on('will-redirect', (e, url) => {
+          expect(url).to.equal(`${url}/200`)
+        })
+        w.loadURL(`${url}/navigate-302`)
+      })
+    })
+  })
+
+  describe('BrowserWindow.show()', () => {
+    let w = null as unknown as BrowserWindow
+    beforeEach(() => {
+      w = new BrowserWindow({show: false, webPreferences: {nodeIntegration: true}})
+    })
+    afterEach(async () => {
+      await closeWindow(w)
+      w = null as unknown as BrowserWindow
+    })
+    it('should focus on window', () => {
+      w.show()
+      if (process.platform === 'darwin' && !isCI) {
+        // on CI, the Electron window will be the only one open, so it'll get
+        // focus. on not-CI, some other window will have focus, and we don't
+        // steal focus any more, so we expect isFocused to be false.
+        expect(w.isFocused()).to.equal(false)
+      } else {
+        expect(w.isFocused()).to.equal(true)
+      }
+    })
+    it('should make the window visible', () => {
+      w.show()
+      expect(w.isVisible()).to.equal(true)
+    })
+    it('emits when window is shown', (done) => {
+      w.once('show', () => {
+        expect(w.isVisible()).to.equal(true)
+        done()
+      })
+      w.show()
+    })
+  })
+
+  describe('BrowserWindow.hide()', () => {
+    let w = null as unknown as BrowserWindow
+    beforeEach(() => {
+      w = new BrowserWindow({show: false, webPreferences: {nodeIntegration: true}})
+    })
+    afterEach(async () => {
+      await closeWindow(w)
+      w = null as unknown as BrowserWindow
+    })
+    it('should defocus on window', () => {
+      w.hide()
+      expect(w.isFocused()).to.equal(false)
+    })
+    it('should make the window not visible', () => {
+      w.show()
+      w.hide()
+      expect(w.isVisible()).to.equal(false)
+    })
+    it('emits when window is hidden', async () => {
+      const shown = emittedOnce(w, 'show')
+      w.show()
+      await shown
+      const hidden = emittedOnce(w, 'hide')
+      w.hide()
+      await hidden
+      expect(w.isVisible()).to.equal(false)
+    })
+  })
+
+})

+ 6 - 3
spec-main/window-helpers.ts

@@ -30,9 +30,12 @@ export const closeWindow = async (
 
   if (assertNotWindows) {
     const windows = BrowserWindow.getAllWindows()
-    for (const win of windows) {
-      await ensureWindowIsClosed(win)
+    try {
+      expect(windows).to.have.lengthOf(0)
+    } finally {
+      for (const win of windows) {
+        await ensureWindowIsClosed(win)
+      }
     }
-    expect(windows).to.have.lengthOf(0)
   }
 }

+ 0 - 368
spec/api-browser-window-spec.js

@@ -113,374 +113,6 @@ describe('BrowserWindow module', () => {
 
   afterEach(closeTheWindow)
 
-  describe('BrowserWindow constructor', () => {
-    it('allows passing void 0 as the webContents', async () => {
-      await openTheWindow({
-        webContents: void 0
-      })
-    })
-  })
-
-  describe('BrowserWindow.close()', () => {
-    let server
-
-    before((done) => {
-      server = http.createServer((request, response) => {
-        switch (request.url) {
-          case '/404':
-            response.statusCode = '404'
-            response.end()
-            break
-          case '/301':
-            response.statusCode = '301'
-            response.setHeader('Location', '/200')
-            response.end()
-            break
-          case '/200':
-            response.statusCode = '200'
-            response.end('hello')
-            break
-          case '/title':
-            response.statusCode = '200'
-            response.end('<title>Hello</title>')
-            break
-          default:
-            done('unsupported endpoint')
-        }
-      }).listen(0, '127.0.0.1', () => {
-        server.url = 'http://127.0.0.1:' + server.address().port
-        done()
-      })
-    })
-
-    after(() => {
-      server.close()
-      server = null
-    })
-
-    it('should emit unload handler', (done) => {
-      w.webContents.once('did-finish-load', () => { w.close() })
-      w.once('closed', () => {
-        const test = path.join(fixtures, 'api', 'unload')
-        const content = fs.readFileSync(test)
-        fs.unlinkSync(test)
-        expect(String(content)).to.equal('unload')
-        done()
-      })
-      w.loadFile(path.join(fixtures, 'api', 'unload.html'))
-    })
-    it('should emit beforeunload handler', (done) => {
-      w.once('onbeforeunload', () => { done() })
-      w.webContents.once('did-finish-load', () => { w.close() })
-      w.loadFile(path.join(fixtures, 'api', 'beforeunload-false.html'))
-    })
-    it('should not crash when invoked synchronously inside navigation observer', (done) => {
-      const events = [
-        { name: 'did-start-loading', url: `${server.url}/200` },
-        { name: 'dom-ready', url: `${server.url}/200` },
-        { name: 'page-title-updated', url: `${server.url}/title` },
-        { name: 'did-stop-loading', url: `${server.url}/200` },
-        { name: 'did-finish-load', url: `${server.url}/200` },
-        { name: 'did-frame-finish-load', url: `${server.url}/200` },
-        { name: 'did-fail-load', url: `${server.url}/404` }
-      ]
-      const responseEvent = 'window-webContents-destroyed'
-
-      function * genNavigationEvent () {
-        let eventOptions = null
-        while ((eventOptions = events.shift()) && events.length) {
-          const w = new BrowserWindow({ show: false })
-          eventOptions.id = w.id
-          eventOptions.responseEvent = responseEvent
-          ipcRenderer.send('test-webcontents-navigation-observer', eventOptions)
-          yield 1
-        }
-      }
-
-      const gen = genNavigationEvent()
-      ipcRenderer.on(responseEvent, () => {
-        if (!gen.next().value) done()
-      })
-      gen.next()
-    })
-  })
-
-  describe('window.close()', () => {
-    it('should emit unload handler', (done) => {
-      w.once('closed', () => {
-        const test = path.join(fixtures, 'api', 'close')
-        const content = fs.readFileSync(test)
-        fs.unlinkSync(test)
-        expect(String(content)).to.equal('close')
-        done()
-      })
-      w.loadFile(path.join(fixtures, 'api', 'close.html'))
-    })
-    it('should emit beforeunload handler', (done) => {
-      w.once('onbeforeunload', () => { done() })
-      w.loadFile(path.join(fixtures, 'api', 'close-beforeunload-false.html'))
-    })
-  })
-
-  describe('BrowserWindow.destroy()', () => {
-    it('prevents users to access methods of webContents', () => {
-      const contents = w.webContents
-      w.destroy()
-      expect(() => {
-        contents.getProcessId()
-      }).to.throw('Object has been destroyed')
-    })
-    it('should not crash when destroying windows with pending events', (done) => {
-      const responseEvent = 'destroy-test-completed'
-      ipcRenderer.on(responseEvent, () => done())
-      ipcRenderer.send('test-browserwindow-destroy', { responseEvent })
-    })
-  })
-
-  describe('BrowserWindow.loadURL(url)', () => {
-    it('should emit did-start-loading event', (done) => {
-      w.webContents.on('did-start-loading', () => { done() })
-      w.loadURL('about:blank')
-    })
-    it('should emit ready-to-show event', (done) => {
-      w.on('ready-to-show', () => { done() })
-      w.loadURL('about:blank')
-    })
-    it('should emit did-fail-load event for files that do not exist', (done) => {
-      w.webContents.on('did-fail-load', (event, code, desc, url, isMainFrame) => {
-        expect(code).to.equal(-6)
-        expect(desc).to.equal('ERR_FILE_NOT_FOUND')
-        expect(isMainFrame).to.be.true()
-        done()
-      })
-      w.loadURL('file://a.txt')
-    })
-    it('should emit did-fail-load event for invalid URL', (done) => {
-      w.webContents.on('did-fail-load', (event, code, desc, url, isMainFrame) => {
-        expect(desc).to.equal('ERR_INVALID_URL')
-        expect(code).to.equal(-300)
-        expect(isMainFrame).to.be.true()
-        done()
-      })
-      w.loadURL('http://example:port')
-    })
-    it('should set `mainFrame = false` on did-fail-load events in iframes', (done) => {
-      w.webContents.on('did-fail-load', (event, code, desc, url, isMainFrame) => {
-        expect(isMainFrame).to.be.false()
-        done()
-      })
-      w.loadFile(path.join(fixtures, 'api', 'did-fail-load-iframe.html'))
-    })
-    it('does not crash in did-fail-provisional-load handler', (done) => {
-      w.webContents.once('did-fail-provisional-load', () => {
-        w.loadURL('http://127.0.0.1:11111')
-        done()
-      })
-      w.loadURL('http://127.0.0.1:11111')
-    })
-    it('should emit did-fail-load event for URL exceeding character limit', (done) => {
-      w.webContents.on('did-fail-load', (event, code, desc, url, isMainFrame) => {
-        expect(desc).to.equal('ERR_INVALID_URL')
-        expect(code).to.equal(-300)
-        expect(isMainFrame).to.be.true()
-        done()
-      })
-      const data = Buffer.alloc(2 * 1024 * 1024).toString('base64')
-      w.loadURL(`data:image/png;base64,${data}`)
-    })
-
-    it('should return a promise', () => {
-      const p = w.loadURL('about:blank')
-      expect(p).to.have.property('then')
-    })
-
-    it('should return a promise that resolves', async () => {
-      expect(w.loadURL('about:blank')).to.eventually.be.fulfilled()
-    })
-
-    it('should return a promise that rejects on a load failure', async () => {
-      const data = Buffer.alloc(2 * 1024 * 1024).toString('base64')
-      const p = w.loadURL(`data:image/png;base64,${data}`)
-      await expect(p).to.eventually.be.rejected()
-    })
-
-    it('should return a promise that resolves even if pushState occurs during navigation', async () => {
-      const data = Buffer.alloc(2 * 1024 * 1024).toString('base64')
-      const p = w.loadURL('data:text/html,<script>window.history.pushState({}, "/foo")</script>')
-      await expect(p).to.eventually.be.fulfilled()
-    })
-
-    describe('POST navigations', () => {
-      afterEach(() => { w.webContents.session.webRequest.onBeforeSendHeaders(null) })
-
-      it('supports specifying POST data', async () => {
-        await w.loadURL(server.url, { postData: postData })
-      })
-      it('sets the content type header on URL encoded forms', async () => {
-        await w.loadURL(server.url)
-        const requestDetails = new Promise(resolve => {
-          w.webContents.session.webRequest.onBeforeSendHeaders((details, callback) => {
-            resolve(details)
-          })
-        })
-        w.webContents.executeJavaScript(`
-          form = document.createElement('form')
-          document.body.appendChild(form)
-          form.method = 'POST'
-          form.target = '_blank'
-          form.submit()
-        `)
-        const details = await requestDetails
-        expect(details.requestHeaders['content-type']).to.equal('application/x-www-form-urlencoded')
-      })
-      it('sets the content type header on multi part forms', async () => {
-        await w.loadURL(server.url)
-        const requestDetails = new Promise(resolve => {
-          w.webContents.session.webRequest.onBeforeSendHeaders((details, callback) => {
-            resolve(details)
-          })
-        })
-        w.webContents.executeJavaScript(`
-          form = document.createElement('form')
-          document.body.appendChild(form)
-          form.method = 'POST'
-          form.target = '_blank'
-          form.enctype = 'multipart/form-data'
-          file = document.createElement('input')
-          file.type = 'file'
-          file.name = 'file'
-          form.appendChild(file)
-          form.submit()
-        `)
-        const details = await requestDetails
-        expect(details.requestHeaders['content-type'].startsWith('multipart/form-data; boundary=----WebKitFormBoundary')).to.be.true()
-      })
-    })
-
-    it('should support support base url for data urls', (done) => {
-      ipcMain.once('answer', (event, test) => {
-        expect(test).to.equal('test')
-        done()
-      })
-      w.loadURL('data:text/html,<script src="loaded-from-dataurl.js"></script>', { baseURLForDataURL: `file://${path.join(fixtures, 'api')}${path.sep}` })
-    })
-  })
-
-  describe('will-navigate event', () => {
-    it('allows the window to be closed from the event listener', (done) => {
-      ipcRenderer.send('close-on-will-navigate', w.id)
-      ipcRenderer.once('closed-on-will-navigate', () => { done() })
-      w.loadFile(path.join(fixtures, 'pages', 'will-navigate.html'))
-    })
-  })
-
-  describe('will-redirect event', () => {
-    it('is emitted on redirects', (done) => {
-      w.webContents.on('will-redirect', (event, url) => {
-        done()
-      })
-      w.loadURL(`${server.url}/302`)
-    })
-
-    it('is emitted after will-navigate on redirects', (done) => {
-      let navigateCalled = false
-      w.webContents.on('will-navigate', () => {
-        navigateCalled = true
-      })
-      w.webContents.on('will-redirect', (event, url) => {
-        expect(navigateCalled).to.equal(true, 'should have called will-navigate first')
-        done()
-      })
-      w.loadURL(`${server.url}/navigate-302`)
-    })
-
-    it('is emitted before did-stop-loading on redirects', (done) => {
-      let stopCalled = false
-      w.webContents.on('did-stop-loading', () => {
-        stopCalled = true
-      })
-      w.webContents.on('will-redirect', (event, url) => {
-        expect(stopCalled).to.equal(false, 'should not have called did-stop-loading first')
-        done()
-      })
-      w.loadURL(`${server.url}/302`)
-    })
-
-    it('allows the window to be closed from the event listener', (done) => {
-      ipcRenderer.send('close-on-will-redirect', w.id)
-      ipcRenderer.once('closed-on-will-redirect', () => { done() })
-      w.loadURL(`${server.url}/302`)
-    })
-
-    it.skip('can be prevented', (done) => {
-      ipcRenderer.send('prevent-will-redirect', w.id)
-      w.webContents.on('will-navigate', (e, url) => {
-        expect(url).to.equal(`${server.url}/302`)
-      })
-      w.webContents.on('did-stop-loading', () => {
-        expect(w.webContents.getURL()).to.equal(
-          `${server.url}/navigate-302`,
-          'url should not have changed after navigation event'
-        )
-        done()
-      })
-      w.webContents.on('will-redirect', (e, url) => {
-        expect(url).to.equal(`${server.url}/200`)
-      })
-      w.loadURL(`${server.url}/navigate-302`)
-    })
-  })
-
-  describe('BrowserWindow.show()', () => {
-    before(function () {
-      if (isCI) {
-        this.skip()
-      }
-    })
-
-    it('should focus on window', () => {
-      w.show()
-      expect(w.isFocused()).to.be.true()
-    })
-    it('should make the window visible', () => {
-      w.show()
-      expect(w.isVisible()).to.be.true()
-    })
-    it('emits when window is shown', (done) => {
-      w.once('show', () => {
-        expect(w.isVisible()).to.be.true()
-        done()
-      })
-      w.show()
-    })
-  })
-
-  describe('BrowserWindow.hide()', () => {
-    before(function () {
-      if (isCI) {
-        this.skip()
-      }
-    })
-
-    it('should defocus on window', () => {
-      w.hide()
-      expect(w.isFocused()).to.be.false()
-    })
-    it('should make the window not visible', () => {
-      w.show()
-      w.hide()
-      expect(w.isVisible()).to.be.false()
-    })
-    it('emits when window is hidden', (done) => {
-      w.show()
-      w.once('hide', () => {
-        expect(w.isVisible()).to.be.false()
-        done()
-      })
-      w.hide()
-    })
-  })
-
   describe('BrowserWindow.showInactive()', () => {
     it('should not focus on window', () => {
       w.showInactive()

+ 0 - 66
spec/static/main.js

@@ -232,31 +232,6 @@ ipcMain.on('set-client-certificate-option', function (event, skip) {
   event.returnValue = 'done'
 })
 
-ipcMain.on('close-on-will-navigate', (event, id) => {
-  const contents = event.sender
-  const window = BrowserWindow.fromId(id)
-  window.webContents.once('will-navigate', (event, input) => {
-    window.close()
-    contents.send('closed-on-will-navigate')
-  })
-})
-
-ipcMain.on('close-on-will-redirect', (event, id) => {
-  const contents = event.sender
-  const window = BrowserWindow.fromId(id)
-  window.webContents.once('will-redirect', (event, input) => {
-    window.close()
-    contents.send('closed-on-will-redirect')
-  })
-})
-
-ipcMain.on('prevent-will-redirect', (event, id) => {
-  const window = BrowserWindow.fromId(id)
-  window.webContents.once('will-redirect', (event) => {
-    event.preventDefault()
-  })
-})
-
 ipcMain.on('create-window-with-options-cycle', (event) => {
   // This can't be done over remote since cycles are already
   // nulled out at the IPC layer
@@ -347,47 +322,6 @@ ipcMain.on('crash-service-pid', (event, pid) => {
   event.returnValue = null
 })
 
-ipcMain.on('test-webcontents-navigation-observer', (event, options) => {
-  let contents = null
-  let destroy = () => {}
-  if (options.id) {
-    const w = BrowserWindow.fromId(options.id)
-    contents = w.webContents
-    destroy = () => w.close()
-  } else {
-    contents = webContents.create()
-    destroy = () => contents.destroy()
-  }
-
-  contents.once(options.name, () => destroy())
-
-  contents.once('destroyed', () => {
-    event.sender.send(options.responseEvent)
-  })
-
-  contents.loadURL(options.url)
-})
-
-ipcMain.on('test-browserwindow-destroy', (event, testOptions) => {
-  const focusListener = (event, win) => win.id
-  app.on('browser-window-focus', focusListener)
-  const windowCount = 3
-  const windowOptions = {
-    show: false,
-    width: 400,
-    height: 400,
-    webPreferences: {
-      backgroundThrottling: false
-    }
-  }
-  const windows = Array.from(Array(windowCount)).map(x => new BrowserWindow(windowOptions))
-  windows.forEach(win => win.show())
-  windows.forEach(win => win.focus())
-  windows.forEach(win => win.destroy())
-  app.removeListener('browser-window-focus', focusListener)
-  event.sender.send(testOptions.responseEvent)
-})
-
 // Suspend listeners until the next event and then restore them
 const suspendListeners = (emitter, eventName, callback) => {
   const listeners = emitter.listeners(eventName)