test-event-core.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. 'use strict';
  5. const { on, once, off, emit, count } = require('sdk/event/core');
  6. const { LoaderWithHookedConsole } = require("sdk/test/loader");
  7. exports['test add a listener'] = function(assert) {
  8. let events = [ { name: 'event#1' }, 'event#2' ];
  9. let target = { name: 'target' };
  10. on(target, 'message', function(message) {
  11. assert.equal(this, target, 'this is a target object');
  12. assert.equal(message, events.shift(), 'message is emitted event');
  13. });
  14. emit(target, 'message', events[0]);
  15. emit(target, 'message', events[0]);
  16. };
  17. exports['test that listener is unique per type'] = function(assert) {
  18. let actual = []
  19. let target = {}
  20. function listener() { actual.push(1) }
  21. on(target, 'message', listener);
  22. on(target, 'message', listener);
  23. on(target, 'message', listener);
  24. on(target, 'foo', listener);
  25. on(target, 'foo', listener);
  26. emit(target, 'message');
  27. assert.deepEqual([ 1 ], actual, 'only one message listener added');
  28. emit(target, 'foo');
  29. assert.deepEqual([ 1, 1 ], actual, 'same listener added for other event');
  30. };
  31. exports['test event type matters'] = function(assert) {
  32. let target = { name: 'target' }
  33. on(target, 'message', function() {
  34. assert.fail('no event is expected');
  35. });
  36. on(target, 'done', function() {
  37. assert.pass('event is emitted');
  38. });
  39. emit(target, 'foo')
  40. emit(target, 'done');
  41. };
  42. exports['test all arguments are pasesd'] = function(assert) {
  43. let foo = { name: 'foo' }, bar = 'bar';
  44. let target = { name: 'target' };
  45. on(target, 'message', function(a, b) {
  46. assert.equal(a, foo, 'first argument passed');
  47. assert.equal(b, bar, 'second argument passed');
  48. });
  49. emit(target, 'message', foo, bar);
  50. };
  51. exports['test no side-effects in emit'] = function(assert) {
  52. let target = { name: 'target' };
  53. on(target, 'message', function() {
  54. assert.pass('first listener is called');
  55. on(target, 'message', function() {
  56. assert.fail('second listener is called');
  57. });
  58. });
  59. emit(target, 'message');
  60. };
  61. exports['test can remove next listener'] = function(assert) {
  62. let target = { name: 'target' };
  63. function fail() assert.fail('Listener should be removed');
  64. on(target, 'data', function() {
  65. assert.pass('first litener called');
  66. off(target, 'data', fail);
  67. });
  68. on(target, 'data', fail);
  69. emit(target, 'data', 'hello');
  70. };
  71. exports['test order of propagation'] = function(assert) {
  72. let actual = [];
  73. let target = { name: 'target' };
  74. on(target, 'message', function() { actual.push(1); });
  75. on(target, 'message', function() { actual.push(2); });
  76. on(target, 'message', function() { actual.push(3); });
  77. emit(target, 'message');
  78. assert.deepEqual([ 1, 2, 3 ], actual, 'called in order they were added');
  79. };
  80. exports['test remove a listener'] = function(assert) {
  81. let target = { name: 'target' };
  82. let actual = [];
  83. on(target, 'message', function listener() {
  84. actual.push(1);
  85. on(target, 'message', function() {
  86. off(target, 'message', listener);
  87. actual.push(2);
  88. })
  89. });
  90. emit(target, 'message');
  91. assert.deepEqual([ 1 ], actual, 'first listener called');
  92. emit(target, 'message');
  93. assert.deepEqual([ 1, 1, 2 ], actual, 'second listener called');
  94. emit(target, 'message');
  95. assert.deepEqual([ 1, 1, 2, 2, 2 ], actual, 'first listener removed');
  96. };
  97. exports['test remove all listeners for type'] = function(assert) {
  98. let actual = [];
  99. let target = { name: 'target' }
  100. on(target, 'message', function() { actual.push(1); });
  101. on(target, 'message', function() { actual.push(2); });
  102. on(target, 'message', function() { actual.push(3); });
  103. on(target, 'bar', function() { actual.push('b') });
  104. off(target, 'message');
  105. emit(target, 'message');
  106. emit(target, 'bar');
  107. assert.deepEqual([ 'b' ], actual, 'all message listeners were removed');
  108. };
  109. exports['test remove all listeners'] = function(assert) {
  110. let actual = [];
  111. let target = { name: 'target' }
  112. on(target, 'message', function() { actual.push(1); });
  113. on(target, 'message', function() { actual.push(2); });
  114. on(target, 'message', function() { actual.push(3); });
  115. on(target, 'bar', function() { actual.push('b') });
  116. off(target);
  117. emit(target, 'message');
  118. emit(target, 'bar');
  119. assert.deepEqual([], actual, 'all listeners events were removed');
  120. };
  121. exports['test falsy arguments are fine'] = function(assert) {
  122. let type, listener, actual = [];
  123. let target = { name: 'target' }
  124. on(target, 'bar', function() { actual.push(0) });
  125. off(target, 'bar', listener);
  126. emit(target, 'bar');
  127. assert.deepEqual([ 0 ], actual, '3rd bad ard will keep listeners');
  128. off(target, type);
  129. emit(target, 'bar');
  130. assert.deepEqual([ 0, 0 ], actual, '2nd bad arg will keep listener');
  131. off(target, type, listener);
  132. emit(target, 'bar');
  133. assert.deepEqual([ 0, 0, 0 ], actual, '2nd&3rd bad args will keep listener');
  134. };
  135. exports['test error handling'] = function(assert) {
  136. let target = Object.create(null);
  137. let error = Error('boom!');
  138. on(target, 'message', function() { throw error; })
  139. on(target, 'error', function(boom) {
  140. assert.equal(boom, error, 'thrown exception causes error event');
  141. });
  142. emit(target, 'message');
  143. };
  144. exports['test unhandled exceptions'] = function(assert) {
  145. let exceptions = [];
  146. let { loader, messages } = LoaderWithHookedConsole(module);
  147. let { emit, on } = loader.require('sdk/event/core');
  148. let target = {};
  149. let boom = Error('Boom!');
  150. let drax = Error('Draax!!');
  151. on(target, 'message', function() { throw boom; });
  152. emit(target, 'message');
  153. assert.equal(messages.length, 1, 'Got the first exception');
  154. assert.equal(messages[0].type, 'exception', 'The console message is exception');
  155. assert.ok(~String(messages[0].msg).indexOf('Boom!'),
  156. 'unhandled exception is logged');
  157. on(target, 'error', function() { throw drax; });
  158. emit(target, 'message');
  159. assert.equal(messages.length, 2, 'Got the second exception');
  160. assert.equal(messages[1].type, 'exception', 'The console message is exception');
  161. assert.ok(~String(messages[1].msg).indexOf('Draax!'),
  162. 'error in error handler is logged');
  163. };
  164. exports['test unhandled errors'] = function(assert) {
  165. let exceptions = [];
  166. let { loader, messages } = LoaderWithHookedConsole(module);
  167. let { emit, on } = loader.require('sdk/event/core');
  168. let target = {};
  169. let boom = Error('Boom!');
  170. emit(target, 'error', boom);
  171. assert.equal(messages.length, 1, 'Error was logged');
  172. assert.equal(messages[0].type, 'exception', 'The console message is exception');
  173. assert.ok(~String(messages[0].msg).indexOf('Boom!'),
  174. 'unhandled exception is logged');
  175. };
  176. exports['test count'] = function(assert) {
  177. let target = {};
  178. assert.equal(count(target, 'foo'), 0, 'no listeners for "foo" events');
  179. on(target, 'foo', function() {});
  180. assert.equal(count(target, 'foo'), 1, 'listener registered');
  181. on(target, 'foo', function() {}, 2, 'another listener registered');
  182. off(target)
  183. assert.equal(count(target, 'foo'), 0, 'listeners unregistered');
  184. };
  185. exports['test listen to all events'] = function(assert) {
  186. let actual = [];
  187. let target = {};
  188. on(target, 'foo', message => actual.push(message));
  189. on(target, '*', (type, ...message) => {
  190. actual.push([type].concat(message));
  191. });
  192. emit(target, 'foo', 'hello');
  193. assert.equal(actual[0], 'hello',
  194. 'non-wildcard listeners still work');
  195. assert.deepEqual(actual[1], ['foo', 'hello'],
  196. 'wildcard listener called');
  197. emit(target, 'bar', 'goodbye');
  198. assert.deepEqual(actual[2], ['bar', 'goodbye'],
  199. 'wildcard listener called for unbound event name');
  200. };
  201. require('test').run(exports);