api-power-monitor-spec.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // For these tests we use a fake DBus daemon to verify powerMonitor module
  2. // interaction with the system bus. This requires python-dbusmock installed and
  3. // running (with the DBUS_SYSTEM_BUS_ADDRESS environment variable set).
  4. // script/spec-runner.js will take care of spawning the fake DBus daemon and setting
  5. // DBUS_SYSTEM_BUS_ADDRESS when python-dbusmock is installed.
  6. //
  7. // See https://pypi.python.org/pypi/python-dbusmock for more information about
  8. // python-dbusmock.
  9. const chai = require('chai')
  10. const dirtyChai = require('dirty-chai')
  11. const dbus = require('dbus-native')
  12. const Promise = require('bluebird')
  13. const { expect } = chai
  14. chai.use(dirtyChai)
  15. const skip = process.platform !== 'linux' || !process.env.DBUS_SYSTEM_BUS_ADDRESS
  16. describe('powerMonitor', () => {
  17. let logindMock, dbusMockPowerMonitor, getCalls, emitSignal, reset
  18. if (!skip) {
  19. before(async () => {
  20. const systemBus = dbus.systemBus()
  21. const loginService = systemBus.getService('org.freedesktop.login1')
  22. const getInterface = Promise.promisify(loginService.getInterface, { context: loginService })
  23. logindMock = await getInterface('/org/freedesktop/login1', 'org.freedesktop.DBus.Mock')
  24. getCalls = Promise.promisify(logindMock.GetCalls, { context: logindMock })
  25. emitSignal = Promise.promisify(logindMock.EmitSignal, { context: logindMock })
  26. reset = Promise.promisify(logindMock.Reset, { context: logindMock })
  27. })
  28. after(async () => {
  29. await reset()
  30. })
  31. }
  32. (skip ? describe.skip : describe)('when powerMonitor module is loaded with dbus mock', () => {
  33. function onceMethodCalled (done) {
  34. function cb () {
  35. logindMock.removeListener('MethodCalled', cb)
  36. }
  37. done()
  38. return cb
  39. }
  40. before(done => {
  41. logindMock.on('MethodCalled', onceMethodCalled(done))
  42. // lazy load powerMonitor after we listen to MethodCalled mock signal
  43. dbusMockPowerMonitor = require('electron').remote.powerMonitor
  44. })
  45. it('should call Inhibit to delay suspend', async () => {
  46. const calls = await getCalls()
  47. expect(calls).to.be.an('array').that.has.lengthOf(1)
  48. expect(calls[0].slice(1)).to.deep.equal([
  49. 'Inhibit', [
  50. [[{ type: 's', child: [] }], ['sleep']],
  51. [[{ type: 's', child: [] }], ['electron']],
  52. [[{ type: 's', child: [] }], ['Application cleanup before suspend']],
  53. [[{ type: 's', child: [] }], ['delay']]
  54. ]
  55. ])
  56. })
  57. describe('when PrepareForSleep(true) signal is sent by logind', () => {
  58. it('should emit "suspend" event', (done) => {
  59. dbusMockPowerMonitor.once('suspend', () => done())
  60. emitSignal('org.freedesktop.login1.Manager', 'PrepareForSleep',
  61. 'b', [['b', true]])
  62. })
  63. describe('when PrepareForSleep(false) signal is sent by logind', () => {
  64. it('should emit "resume" event', done => {
  65. dbusMockPowerMonitor.once('resume', () => done())
  66. emitSignal('org.freedesktop.login1.Manager', 'PrepareForSleep',
  67. 'b', [['b', false]])
  68. })
  69. it('should have called Inhibit again', async () => {
  70. const calls = await getCalls()
  71. expect(calls).to.be.an('array').that.has.lengthOf(2)
  72. expect(calls[1].slice(1)).to.deep.equal([
  73. 'Inhibit', [
  74. [[{ type: 's', child: [] }], ['sleep']],
  75. [[{ type: 's', child: [] }], ['electron']],
  76. [[{ type: 's', child: [] }], ['Application cleanup before suspend']],
  77. [[{ type: 's', child: [] }], ['delay']]
  78. ]
  79. ])
  80. })
  81. })
  82. })
  83. describe('when a listener is added to shutdown event', () => {
  84. before(async () => {
  85. const calls = await getCalls()
  86. expect(calls).to.be.an('array').that.has.lengthOf(2)
  87. dbusMockPowerMonitor.once('shutdown', () => { })
  88. })
  89. it('should call Inhibit to delay shutdown', async () => {
  90. const calls = await getCalls()
  91. expect(calls).to.be.an('array').that.has.lengthOf(3)
  92. expect(calls[2].slice(1)).to.deep.equal([
  93. 'Inhibit', [
  94. [[{ type: 's', child: [] }], ['shutdown']],
  95. [[{ type: 's', child: [] }], ['electron']],
  96. [[{ type: 's', child: [] }], ['Ensure a clean shutdown']],
  97. [[{ type: 's', child: [] }], ['delay']]
  98. ]
  99. ])
  100. })
  101. describe('when PrepareForShutdown(true) signal is sent by logind', () => {
  102. it('should emit "shutdown" event', done => {
  103. dbusMockPowerMonitor.once('shutdown', () => { done() })
  104. emitSignal('org.freedesktop.login1.Manager', 'PrepareForShutdown',
  105. 'b', [['b', true]])
  106. })
  107. })
  108. })
  109. })
  110. describe('when powerMonitor module is loaded', () => {
  111. let powerMonitor
  112. before(() => {
  113. powerMonitor = require('electron').remote.powerMonitor
  114. })
  115. // TODO(nitsakh): Remove in 7.0
  116. describe('powerMonitor.querySystemIdleState', () => {
  117. it('notify current system idle state', done => {
  118. // this function is not mocked out, so we can test the result's
  119. // form and type but not its value.
  120. powerMonitor.querySystemIdleState(1, idleState => {
  121. expect(idleState).to.be.a('string')
  122. const validIdleStates = [ 'active', 'idle', 'locked', 'unknown' ]
  123. expect(validIdleStates).to.include(idleState)
  124. done()
  125. })
  126. })
  127. it('does not accept non positive integer threshold', () => {
  128. expect(() => {
  129. powerMonitor.querySystemIdleState(-1, (idleState) => {})
  130. }).to.throw()
  131. expect(() => {
  132. powerMonitor.querySystemIdleState(NaN, (idleState) => {})
  133. }).to.throw()
  134. expect(() => {
  135. powerMonitor.querySystemIdleState('a', (idleState) => {})
  136. }).to.throw()
  137. })
  138. })
  139. // TODO(nitsakh): Remove in 7.0
  140. describe('powerMonitor.querySystemIdleTime', () => {
  141. it('notify current system idle time', done => {
  142. powerMonitor.querySystemIdleTime(idleTime => {
  143. expect(idleTime).to.be.at.least(0)
  144. done()
  145. })
  146. })
  147. })
  148. describe('powerMonitor.getSystemIdleState', () => {
  149. it('gets current system idle state', () => {
  150. // this function is not mocked out, so we can test the result's
  151. // form and type but not its value.
  152. const idleState = powerMonitor.getSystemIdleState(1)
  153. expect(idleState).to.be.a('string')
  154. const validIdleStates = [ 'active', 'idle', 'locked', 'unknown' ]
  155. expect(validIdleStates).to.include(idleState)
  156. })
  157. it('does not accept non positive integer threshold', () => {
  158. expect(() => {
  159. powerMonitor.getSystemIdleState(-1)
  160. }).to.throw(/must be greater than 0/)
  161. expect(() => {
  162. powerMonitor.getSystemIdleState(NaN)
  163. }).to.throw(/conversion failure/)
  164. expect(() => {
  165. powerMonitor.getSystemIdleState('a')
  166. }).to.throw(/conversion failure/)
  167. })
  168. })
  169. describe('powerMonitor.getSystemIdleTime', () => {
  170. it('notify current system idle time', () => {
  171. const idleTime = powerMonitor.getSystemIdleTime()
  172. expect(idleTime).to.be.at.least(0)
  173. })
  174. })
  175. })
  176. })