api-ipc-main-spec.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. 'use strict'
  2. const chai = require('chai')
  3. const dirtyChai = require('dirty-chai')
  4. const path = require('path')
  5. const cp = require('child_process')
  6. const { closeWindow } = require('./window-helpers')
  7. const { emittedOnce } = require('./events-helpers')
  8. const { expect } = chai
  9. chai.use(dirtyChai)
  10. const { remote } = require('electron')
  11. const { ipcMain, BrowserWindow } = remote
  12. describe('ipc main module', () => {
  13. const fixtures = path.join(__dirname, 'fixtures')
  14. let w = null
  15. afterEach(() => closeWindow(w).then(() => { w = null }))
  16. describe('ipc.sendSync', () => {
  17. afterEach(() => { ipcMain.removeAllListeners('send-sync-message') })
  18. it('does not crash when reply is not sent and browser is destroyed', (done) => {
  19. w = new BrowserWindow({ show: false })
  20. ipcMain.once('send-sync-message', (event) => {
  21. event.returnValue = null
  22. done()
  23. })
  24. w.loadFile(path.join(fixtures, 'api', 'send-sync-message.html'))
  25. })
  26. it('does not crash when reply is sent by multiple listeners', (done) => {
  27. w = new BrowserWindow({ show: false })
  28. ipcMain.on('send-sync-message', (event) => {
  29. event.returnValue = null
  30. })
  31. ipcMain.on('send-sync-message', (event) => {
  32. event.returnValue = null
  33. done()
  34. })
  35. w.loadFile(path.join(fixtures, 'api', 'send-sync-message.html'))
  36. })
  37. })
  38. describe('remote listeners', () => {
  39. it('can be added and removed correctly', () => {
  40. w = new BrowserWindow({ show: false })
  41. const listener = () => {}
  42. w.on('test', listener)
  43. expect(w.listenerCount('test')).to.equal(1)
  44. w.removeListener('test', listener)
  45. expect(w.listenerCount('test')).to.equal(0)
  46. })
  47. })
  48. describe('remote objects registry', () => {
  49. it('does not dereference until the render view is deleted (regression)', (done) => {
  50. w = new BrowserWindow({ show: false })
  51. ipcMain.once('error-message', (event, message) => {
  52. const correctMsgStart = message.startsWith('Cannot call function \'getURL\' on missing remote object')
  53. expect(correctMsgStart).to.be.true()
  54. done()
  55. })
  56. w.loadFile(path.join(fixtures, 'api', 'render-view-deleted.html'))
  57. })
  58. })
  59. describe('ipcMain.on', () => {
  60. it('is not used for internals', async () => {
  61. const appPath = path.join(__dirname, 'fixtures', 'api', 'ipc-main-listeners')
  62. const electronPath = remote.getGlobal('process').execPath
  63. const appProcess = cp.spawn(electronPath, [appPath])
  64. let output = ''
  65. appProcess.stdout.on('data', (data) => { output += data })
  66. await emittedOnce(appProcess.stdout, 'end')
  67. output = JSON.parse(output)
  68. expect(output).to.deep.equal(['error'])
  69. })
  70. })
  71. })