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