123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- 'use strict'
- const chai = require('chai')
- const dirtyChai = require('dirty-chai')
- const http = require('http')
- const path = require('path')
- const {closeWindow} = require('./window-helpers')
- const {expect} = chai
- chai.use(dirtyChai)
- const {ipcRenderer, remote} = require('electron')
- const {ipcMain, webContents, BrowserWindow} = remote
- describe('ipc renderer module', () => {
- const fixtures = path.join(__dirname, 'fixtures')
- let w = null
- afterEach(() => closeWindow(w).then(() => { w = null }))
- describe('ipc.sender.send', () => {
- it('should work when sending an object containing id property', done => {
- const obj = {
- id: 1,
- name: 'ly'
- }
- ipcRenderer.once('message', (event, message) => {
- expect(message).to.deep.equal(obj)
- done()
- })
- ipcRenderer.send('message', obj)
- })
- it('can send instances of Date', done => {
- const currentDate = new Date()
- ipcRenderer.once('message', (event, value) => {
- expect(value).to.equal(currentDate.toISOString())
- done()
- })
- ipcRenderer.send('message', currentDate)
- })
- it('can send instances of Buffer', done => {
- const buffer = Buffer.from('hello')
- ipcRenderer.once('message', (event, message) => {
- expect(buffer.equals(message)).to.be.true()
- done()
- })
- ipcRenderer.send('message', buffer)
- })
- it('can send objects with DOM class prototypes', done => {
- ipcRenderer.once('message', (event, value) => {
- expect(value.protocol).to.equal('file:')
- expect(value.hostname).to.equal('')
- done()
- })
- ipcRenderer.send('message', document.location)
- })
- it('can send Electron API objects', done => {
- const webContents = remote.getCurrentWebContents()
- ipcRenderer.once('message', (event, value) => {
- expect(value.browserWindowOptions).to.deep.equal(webContents.browserWindowOptions)
- done()
- })
- ipcRenderer.send('message', webContents)
- })
- it('does not crash on external objects (regression)', done => {
- const request = http.request({port: 5000, hostname: '127.0.0.1', method: 'GET', path: '/'})
- const stream = request.agent.sockets['127.0.0.1:5000:'][0]._handle._externalStream
- request.on('error', () => {})
- ipcRenderer.once('message', (event, requestValue, externalStreamValue) => {
- expect(requestValue.method).to.equal('GET')
- expect(requestValue.path).to.equal('/')
- expect(externalStreamValue).to.be.null()
- done()
- })
- ipcRenderer.send('message', request, stream)
- })
- it('can send objects that both reference the same object', done => {
- const child = {hello: 'world'}
- const foo = {name: 'foo', child: child}
- const bar = {name: 'bar', child: child}
- const array = [foo, bar]
- ipcRenderer.once('message', (event, arrayValue, fooValue, barValue, childValue) => {
- expect(arrayValue).to.deep.equal(array)
- expect(fooValue).to.deep.equal(foo)
- expect(barValue).to.deep.equal(bar)
- expect(childValue).to.deep.equal(child)
- done()
- })
- ipcRenderer.send('message', array, foo, bar, child)
- })
- it('inserts null for cyclic references', done => {
- const array = [5]
- array.push(array)
- const child = {hello: 'world'}
- child.child = child
- ipcRenderer.once('message', (event, arrayValue, childValue) => {
- expect(arrayValue[0]).to.equal(5)
- expect(arrayValue[1]).to.be.null()
- expect(childValue.hello).to.equal('world')
- expect(childValue.child).to.be.null()
- done()
- })
- ipcRenderer.send('message', array, child)
- })
- })
- describe('ipc.sendSync', () => {
- afterEach(() => {
- ipcMain.removeAllListeners('send-sync-message')
- })
- it('can be replied by setting event.returnValue', () => {
- const msg = ipcRenderer.sendSync('echo', 'test')
- expect(msg).to.equal('test')
- })
- })
- describe('ipcRenderer.sendTo', () => {
- let contents = null
- beforeEach(() => { contents = webContents.create({}) })
- afterEach(() => {
- ipcRenderer.removeAllListeners('pong')
- contents.destroy()
- contents = null
- })
- const generateSpecs = (description, webPreferences) => {
- describe(description, () => {
- it('sends message to WebContents', done => {
- contents = webContents.create({
- preload: path.join(fixtures, 'module', 'preload-ipc-ping-pong.js'),
- ...webPreferences
- })
- const payload = 'Hello World!'
- const webContentsId = remote.getCurrentWebContents().id
- ipcRenderer.once('pong', (event, data) => {
- expect(payload).to.equal(data)
- done()
- })
- contents.once('did-finish-load', () => {
- ipcRenderer.sendTo(contents.id, 'ping', webContentsId, payload)
- })
- contents.loadFile(path.join(fixtures, 'pages', 'base-page.html'))
- })
- })
- }
- generateSpecs('without sandbox', {})
- generateSpecs('with sandbox', { sandbox: true })
- generateSpecs('with contextIsolation', { contextIsolation: true })
- generateSpecs('with contextIsolation + sandbox', { contextIsolation: true, sandbox: true })
- })
- describe('remote listeners', () => {
- it('detaches listeners subscribed to destroyed renderers, and shows a warning', (done) => {
- w = new BrowserWindow({ show: false })
- w.webContents.once('did-finish-load', () => {
- w.webContents.once('did-finish-load', () => {
- const expectedMessage = [
- 'Attempting to call a function in a renderer window that has been closed or released.',
- 'Function provided here: remote-event-handler.html:11:33',
- 'Remote event names: remote-handler, other-remote-handler'
- ].join('\n')
- const results = ipcRenderer.sendSync('try-emit-web-contents-event', w.webContents.id, 'remote-handler')
- expect(results).to.deep.equal({
- warningMessage: expectedMessage,
- listenerCountBefore: 2,
- listenerCountAfter: 1
- })
- done()
- })
- w.webContents.reload()
- })
- w.loadURL(`file://${path.join(fixtures, 'api', 'remote-event-handler.html')}`)
- })
- })
- it('throws an error when removing all the listeners', () => {
- ipcRenderer.on('test-event', () => {})
- expect(ipcRenderer.listenerCount('test-event')).to.equal(1)
- expect(() => {
- ipcRenderer.removeAllListeners()
- }).to.throw(/Removing all listeners from ipcRenderer will make Electron internals stop working/)
- ipcRenderer.removeAllListeners('test-event')
- expect(ipcRenderer.listenerCount('test-event')).to.equal(0)
- })
- })
|