api-notification-dbus-spec.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // For these tests we use a fake DBus daemon to verify libnotify interaction
  2. // with the session bus. This requires python-dbusmock to be installed and
  3. // running at $DBUS_SESSION_BUS_ADDRESS.
  4. //
  5. // script/spec-runner.js spawns dbusmock, which sets DBUS_SESSION_BUS_ADDRESS.
  6. //
  7. // See https://pypi.python.org/pypi/python-dbusmock to read about dbusmock.
  8. const { expect } = require('chai')
  9. const dbus = require('dbus-native')
  10. const Promise = require('bluebird')
  11. const { remote } = require('electron')
  12. const { app } = remote
  13. const skip = process.platform !== 'linux' ||
  14. process.arch === 'ia32' ||
  15. process.arch.indexOf('arm') === 0 ||
  16. !process.env.DBUS_SESSION_BUS_ADDRESS;
  17. (skip ? describe.skip : describe)('Notification module (dbus)', () => {
  18. let mock, Notification, getCalls, reset
  19. const realAppName = app.name
  20. const realAppVersion = app.getVersion()
  21. const appName = 'api-notification-dbus-spec'
  22. const serviceName = 'org.freedesktop.Notifications'
  23. before(async () => {
  24. // init app
  25. app.name = appName
  26. app.setDesktopName(`${appName}.desktop`)
  27. // init dbus
  28. const path = '/org/freedesktop/Notifications'
  29. const iface = 'org.freedesktop.DBus.Mock'
  30. const bus = dbus.sessionBus()
  31. console.log(`session bus: ${process.env.DBUS_SESSION_BUS_ADDRESS}`)
  32. const service = bus.getService(serviceName)
  33. const getInterface = Promise.promisify(service.getInterface, { context: service })
  34. mock = await getInterface(path, iface)
  35. getCalls = Promise.promisify(mock.GetCalls, { context: mock })
  36. reset = Promise.promisify(mock.Reset, { context: mock })
  37. })
  38. after(async () => {
  39. // cleanup dbus
  40. await reset()
  41. // cleanup app
  42. app.setName(realAppName)
  43. app.setVersion(realAppVersion)
  44. })
  45. describe(`Notification module using ${serviceName}`, () => {
  46. function onMethodCalled (done) {
  47. function cb (name) {
  48. console.log(`onMethodCalled: ${name}`)
  49. if (name === 'Notify') {
  50. mock.removeListener('MethodCalled', cb)
  51. console.log('done')
  52. done()
  53. }
  54. }
  55. return cb
  56. }
  57. function unmarshalDBusNotifyHints (dbusHints) {
  58. const o = {}
  59. for (const hint of dbusHints) {
  60. const key = hint[0]
  61. const value = hint[1][1][0]
  62. o[key] = value
  63. }
  64. return o
  65. }
  66. function unmarshalDBusNotifyArgs (dbusArgs) {
  67. return {
  68. app_name: dbusArgs[0][1][0],
  69. replaces_id: dbusArgs[1][1][0],
  70. app_icon: dbusArgs[2][1][0],
  71. title: dbusArgs[3][1][0],
  72. body: dbusArgs[4][1][0],
  73. actions: dbusArgs[5][1][0],
  74. hints: unmarshalDBusNotifyHints(dbusArgs[6][1][0])
  75. }
  76. }
  77. before(done => {
  78. mock.on('MethodCalled', onMethodCalled(done))
  79. // lazy load Notification after we listen to MethodCalled mock signal
  80. Notification = require('electron').remote.Notification
  81. const n = new Notification({
  82. title: 'title',
  83. subtitle: 'subtitle',
  84. body: 'body',
  85. replyPlaceholder: 'replyPlaceholder',
  86. sound: 'sound',
  87. closeButtonText: 'closeButtonText'
  88. })
  89. n.show()
  90. })
  91. it(`should call ${serviceName} to show notifications`, async () => {
  92. const calls = await getCalls()
  93. expect(calls).to.be.an('array').of.lengthOf.at.least(1)
  94. const lastCall = calls[calls.length - 1]
  95. const methodName = lastCall[1]
  96. expect(methodName).to.equal('Notify')
  97. const args = unmarshalDBusNotifyArgs(lastCall[2])
  98. expect(args).to.deep.equal({
  99. app_name: appName,
  100. replaces_id: 0,
  101. app_icon: '',
  102. title: 'title',
  103. body: 'body',
  104. actions: [],
  105. hints: {
  106. 'append': 'true',
  107. 'desktop-entry': appName
  108. }
  109. })
  110. })
  111. })
  112. })