|
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 |
|
6 const { LoaderWithHookedConsole } = require("sdk/test/loader"); |
|
7 |
|
8 // Exposing private methods as public in order to test |
|
9 const EventEmitter = require('sdk/deprecated/events').EventEmitter.compose({ |
|
10 listeners: function(type) this._listeners(type), |
|
11 emit: function() this._emit.apply(this, arguments), |
|
12 emitOnObject: function() this._emitOnObject.apply(this, arguments), |
|
13 removeAllListeners: function(type) this._removeAllListeners(type) |
|
14 }); |
|
15 |
|
16 exports['test:add listeners'] = function(assert) { |
|
17 let e = new EventEmitter(); |
|
18 |
|
19 let events_new_listener_emited = []; |
|
20 let times_hello_emited = 0; |
|
21 |
|
22 e.on("newListener", function (event, listener) { |
|
23 events_new_listener_emited.push(event) |
|
24 }) |
|
25 |
|
26 e.on("hello", function (a, b) { |
|
27 times_hello_emited += 1 |
|
28 assert.equal("a", a) |
|
29 assert.equal("b", b) |
|
30 assert.equal(this, e, '`this` pseudo-variable is bound to instance'); |
|
31 }) |
|
32 |
|
33 e.emit("hello", "a", "b") |
|
34 }; |
|
35 |
|
36 exports['test:removeListener'] = function(assert) { |
|
37 let count = 0; |
|
38 |
|
39 function listener1 () { |
|
40 count++; |
|
41 } |
|
42 function listener2 () { |
|
43 count++; |
|
44 } |
|
45 |
|
46 // test adding and removing listener |
|
47 let e1 = new EventEmitter(); |
|
48 assert.equal(0, e1.listeners('hello').length); |
|
49 e1.on("hello", listener1); |
|
50 assert.equal(1, e1.listeners('hello').length); |
|
51 assert.equal(listener1, e1.listeners('hello')[0]); |
|
52 e1.removeListener("hello", listener1); |
|
53 assert.equal(0, e1.listeners('hello').length); |
|
54 e1.emit("hello", ""); |
|
55 assert.equal(0, count); |
|
56 |
|
57 // test adding one listener and removing another which was not added |
|
58 let e2 = new EventEmitter(); |
|
59 assert.equal(0, e2.listeners('hello').length); |
|
60 e2.on("hello", listener1); |
|
61 assert.equal(1, e2.listeners('hello').length); |
|
62 e2.removeListener("hello", listener2); |
|
63 assert.equal(1, e2.listeners('hello').length); |
|
64 assert.equal(listener1, e2.listeners('hello')[0]); |
|
65 e2.emit("hello", ""); |
|
66 assert.equal(1, count); |
|
67 |
|
68 // test adding 2 listeners, and removing one |
|
69 let e3 = new EventEmitter(); |
|
70 assert.equal(0, e3.listeners('hello').length); |
|
71 e3.on("hello", listener1); |
|
72 assert.equal(1, e3.listeners('hello').length); |
|
73 e3.on("hello", listener2); |
|
74 assert.equal(2, e3.listeners('hello').length); |
|
75 e3.removeListener("hello", listener1); |
|
76 assert.equal(1, e3.listeners('hello').length); |
|
77 assert.equal(listener2, e3.listeners('hello')[0]); |
|
78 e3.emit("hello", ""); |
|
79 assert.equal(2, count); |
|
80 }; |
|
81 |
|
82 exports['test:removeAllListeners'] = function(assert) { |
|
83 let count = 0; |
|
84 |
|
85 function listener1 () { |
|
86 count++; |
|
87 } |
|
88 function listener2 () { |
|
89 count++; |
|
90 } |
|
91 |
|
92 // test adding a listener and removing all of that type |
|
93 let e1 = new EventEmitter(); |
|
94 e1.on("hello", listener1); |
|
95 assert.equal(1, e1.listeners('hello').length); |
|
96 e1.removeAllListeners("hello"); |
|
97 assert.equal(0, e1.listeners('hello').length); |
|
98 e1.emit("hello", ""); |
|
99 assert.equal(0, count); |
|
100 |
|
101 // test adding a listener and removing all of another type |
|
102 let e2 = new EventEmitter(); |
|
103 e2.on("hello", listener1); |
|
104 assert.equal(1, e2.listeners('hello').length); |
|
105 e2.removeAllListeners('goodbye'); |
|
106 assert.equal(1, e2.listeners('hello').length); |
|
107 e2.emit("hello", ""); |
|
108 assert.equal(1, count); |
|
109 |
|
110 // test adding 1+ listeners and removing all of that type |
|
111 let e3 = new EventEmitter(); |
|
112 e3.on("hello", listener1); |
|
113 assert.equal(1, e3.listeners('hello').length); |
|
114 e3.on("hello", listener2); |
|
115 assert.equal(2, e3.listeners('hello').length); |
|
116 e3.removeAllListeners("hello"); |
|
117 assert.equal(0, e3.listeners('hello').length); |
|
118 e3.emit("hello", ""); |
|
119 assert.equal(1, count); |
|
120 |
|
121 // test adding 2 listeners for 2 types and removing all listeners |
|
122 let e4 = new EventEmitter(); |
|
123 e4.on("hello", listener1); |
|
124 assert.equal(1, e4.listeners('hello').length); |
|
125 e4.on('goodbye', listener2); |
|
126 assert.equal(1, e4.listeners('goodbye').length); |
|
127 e4.emit("goodbye", ""); |
|
128 e4.removeAllListeners(); |
|
129 assert.equal(0, e4.listeners('hello').length); |
|
130 assert.equal(0, e4.listeners('goodbye').length); |
|
131 e4.emit("hello", ""); |
|
132 e4.emit("goodbye", ""); |
|
133 assert.equal(2, count); |
|
134 }; |
|
135 |
|
136 exports['test: modify in emit'] = function(assert) { |
|
137 let callbacks_called = [ ]; |
|
138 let e = new EventEmitter(); |
|
139 |
|
140 function callback1() { |
|
141 callbacks_called.push("callback1"); |
|
142 e.on("foo", callback2); |
|
143 e.on("foo", callback3); |
|
144 e.removeListener("foo", callback1); |
|
145 } |
|
146 function callback2() { |
|
147 callbacks_called.push("callback2"); |
|
148 e.removeListener("foo", callback2); |
|
149 } |
|
150 function callback3() { |
|
151 callbacks_called.push("callback3"); |
|
152 e.removeListener("foo", callback3); |
|
153 } |
|
154 |
|
155 e.on("foo", callback1); |
|
156 assert.equal(1, e.listeners("foo").length); |
|
157 |
|
158 e.emit("foo"); |
|
159 assert.equal(2, e.listeners("foo").length); |
|
160 assert.equal(1, callbacks_called.length); |
|
161 assert.equal('callback1', callbacks_called[0]); |
|
162 |
|
163 e.emit("foo"); |
|
164 assert.equal(0, e.listeners("foo").length); |
|
165 assert.equal(3, callbacks_called.length); |
|
166 assert.equal('callback1', callbacks_called[0]); |
|
167 assert.equal('callback2', callbacks_called[1]); |
|
168 assert.equal('callback3', callbacks_called[2]); |
|
169 |
|
170 e.emit("foo"); |
|
171 assert.equal(0, e.listeners("foo").length); |
|
172 assert.equal(3, callbacks_called.length); |
|
173 assert.equal('callback1', callbacks_called[0]); |
|
174 assert.equal('callback2', callbacks_called[1]); |
|
175 assert.equal('callback3', callbacks_called[2]); |
|
176 |
|
177 e.on("foo", callback1); |
|
178 e.on("foo", callback2); |
|
179 assert.equal(2, e.listeners("foo").length); |
|
180 e.removeAllListeners("foo"); |
|
181 assert.equal(0, e.listeners("foo").length); |
|
182 |
|
183 // Verify that removing callbacks while in emit allows emits to propagate to |
|
184 // all listeners |
|
185 callbacks_called = [ ]; |
|
186 |
|
187 e.on("foo", callback2); |
|
188 e.on("foo", callback3); |
|
189 assert.equal(2, e.listeners("foo").length); |
|
190 e.emit("foo"); |
|
191 assert.equal(2, callbacks_called.length); |
|
192 assert.equal('callback2', callbacks_called[0]); |
|
193 assert.equal('callback3', callbacks_called[1]); |
|
194 assert.equal(0, e.listeners("foo").length); |
|
195 }; |
|
196 |
|
197 exports['test:adding same listener'] = function(assert) { |
|
198 function foo() {} |
|
199 let e = new EventEmitter(); |
|
200 e.on("foo", foo); |
|
201 e.on("foo", foo); |
|
202 assert.equal( |
|
203 1, |
|
204 e.listeners("foo").length, |
|
205 "listener reregistration is ignored" |
|
206 ); |
|
207 } |
|
208 |
|
209 exports['test:errors are reported if listener throws'] = function(assert) { |
|
210 let e = new EventEmitter(), |
|
211 reported = false; |
|
212 e.on('error', function(e) reported = true) |
|
213 e.on('boom', function() { throw new Error('Boom!') }); |
|
214 e.emit('boom', 3); |
|
215 assert.ok(reported, 'error should be reported through event'); |
|
216 }; |
|
217 |
|
218 exports['test:emitOnObject'] = function(assert) { |
|
219 let e = new EventEmitter(); |
|
220 |
|
221 e.on("foo", function() { |
|
222 assert.equal(this, e, "`this` should be emitter"); |
|
223 }); |
|
224 e.emitOnObject(e, "foo"); |
|
225 |
|
226 e.on("bar", function() { |
|
227 assert.equal(this, obj, "`this` should be other object"); |
|
228 }); |
|
229 let obj = {}; |
|
230 e.emitOnObject(obj, "bar"); |
|
231 }; |
|
232 |
|
233 exports['test:once'] = function(assert) { |
|
234 let e = new EventEmitter(); |
|
235 let called = false; |
|
236 |
|
237 e.once('foo', function(value) { |
|
238 assert.ok(!called, "listener called only once"); |
|
239 assert.equal(value, "bar", "correct argument was passed"); |
|
240 }); |
|
241 |
|
242 e.emit('foo', 'bar'); |
|
243 e.emit('foo', 'baz'); |
|
244 }; |
|
245 |
|
246 exports["test:removing once"] = function(assert) { |
|
247 let e = require("sdk/deprecated/events").EventEmitterTrait.create(); |
|
248 e.once("foo", function() { assert.pass("listener was called"); }); |
|
249 e.once("error", function() { assert.fail("error event was emitted"); }); |
|
250 e._emit("foo", "bug-656684"); |
|
251 }; |
|
252 |
|
253 // Bug 726967: Ensure that `emit` doesn't do an infinite loop when `error` |
|
254 // listener throws an exception |
|
255 exports['test:emitLoop'] = function(assert) { |
|
256 // Override the console for this test so it doesn't log the exception to the |
|
257 // test output |
|
258 let { loader } = LoaderWithHookedConsole(module); |
|
259 |
|
260 let EventEmitter = loader.require('sdk/deprecated/events').EventEmitter.compose({ |
|
261 listeners: function(type) this._listeners(type), |
|
262 emit: function() this._emit.apply(this, arguments), |
|
263 emitOnObject: function() this._emitOnObject.apply(this, arguments), |
|
264 removeAllListeners: function(type) this._removeAllListeners(type) |
|
265 }); |
|
266 |
|
267 let e = new EventEmitter(); |
|
268 |
|
269 e.on("foo", function() { |
|
270 throw new Error("foo"); |
|
271 }); |
|
272 |
|
273 e.on("error", function() { |
|
274 throw new Error("error"); |
|
275 }); |
|
276 e.emit("foo"); |
|
277 |
|
278 assert.pass("emit didn't looped"); |
|
279 }; |
|
280 |
|
281 require('sdk/test').run(exports); |