Commit | Line | Data |
---|---|---|
6a1aa64f DV |
1 | if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Signal'); } |
2 | if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Signal'); } | |
3 | if (typeof(tests) == 'undefined') { tests = {}; } | |
4 | ||
5 | tests.test_Signal = function (t) { | |
6 | ||
7 | var submit = MochiKit.DOM.getElement('submit'); | |
8 | var ident = null; | |
9 | var i = 0; | |
10 | var aFunction = function() { | |
11 | t.ok(this === submit, "aFunction should have 'this' as submit"); | |
12 | i++; | |
13 | if (typeof(this.someVar) != 'undefined') { | |
14 | i += this.someVar; | |
15 | } | |
16 | }; | |
17 | ||
18 | var aObject = {}; | |
19 | aObject.aMethod = function() { | |
20 | t.ok(this === aObject, "aMethod should have 'this' as aObject"); | |
21 | i++; | |
22 | }; | |
23 | ||
24 | ident = connect('submit', 'onclick', aFunction); | |
25 | MochiKit.DOM.getElement('submit').click(); | |
26 | t.is(i, 1, 'HTML onclick event can be connected to a function'); | |
27 | ||
28 | disconnect(ident); | |
29 | MochiKit.DOM.getElement('submit').click(); | |
30 | t.is(i, 1, 'HTML onclick can be disconnected from a function'); | |
31 | ||
32 | var submit = MochiKit.DOM.getElement('submit'); | |
33 | ||
34 | ident = connect(submit, 'onclick', aFunction); | |
35 | submit.click(); | |
36 | t.is(i, 2, 'Checking that a DOM element can be connected to a function'); | |
37 | ||
38 | disconnect(ident); | |
39 | submit.click(); | |
40 | t.is(i, 2, '...and then disconnected'); | |
41 | ||
42 | if (MochiKit.DOM.getElement('submit').fireEvent || | |
43 | (document.createEvent && | |
44 | typeof(document.createEvent('MouseEvents').initMouseEvent) == 'function')) { | |
45 | ||
46 | /* | |
47 | ||
48 | Adapted from: | |
49 | http://www.devdaily.com/java/jwarehouse/jforum/tests/selenium/javascript/htmlutils.js.shtml | |
50 | License: Apache | |
51 | Copyright: Copyright 2004 ThoughtWorks, Inc | |
52 | ||
53 | */ | |
54 | var triggerMouseEvent = function(element, eventType, canBubble) { | |
55 | element = MochiKit.DOM.getElement(element); | |
56 | canBubble = (typeof(canBubble) == 'undefined') ? true : canBubble; | |
57 | if (element.fireEvent) { | |
58 | var newEvt = document.createEventObject(); | |
59 | newEvt.clientX = 1; | |
60 | newEvt.clientY = 1; | |
61 | newEvt.button = 1; | |
62 | element.fireEvent('on' + eventType, newEvt); | |
63 | } else if (document.createEvent && (typeof(document.createEvent('MouseEvents').initMouseEvent) == 'function')) { | |
64 | var evt = document.createEvent('MouseEvents'); | |
65 | evt.initMouseEvent(eventType, canBubble, true, // event, bubbles, cancelable | |
66 | document.defaultView, 1, // view, # of clicks | |
67 | 1, 0, 0, 0, // screenX, screenY, clientX, clientY | |
68 | false, false, false, false, // ctrlKey, altKey, shiftKey, metaKey | |
69 | 0, null); // buttonCode, relatedTarget | |
70 | element.dispatchEvent(evt); | |
71 | } | |
72 | }; | |
73 | ||
74 | var eventTest = function(e) { | |
75 | i++; | |
76 | t.ok((typeof(e.event()) === 'object'), 'checking that event() is an object'); | |
77 | t.ok((typeof(e.type()) === 'string'), 'checking that type() is a string'); | |
78 | t.ok((e.target() === MochiKit.DOM.getElement('submit')), 'checking that target is "submit"'); | |
79 | t.ok((typeof(e.modifier()) === 'object'), 'checking that modifier() is an object'); | |
80 | t.ok(e.modifier().alt === false, 'checking that modifier().alt is defined, but false'); | |
81 | t.ok(e.modifier().ctrl === false, 'checking that modifier().ctrl is defined, but false'); | |
82 | t.ok(e.modifier().meta === false, 'checking that modifier().meta is defined, but false'); | |
83 | t.ok(e.modifier().shift === false, 'checking that modifier().shift is defined, but false'); | |
84 | t.ok((typeof(e.mouse()) === 'object'), 'checking that mouse() is an object'); | |
85 | t.ok((typeof(e.mouse().button) === 'object'), 'checking that mouse().button is an object'); | |
86 | t.ok(e.mouse().button.left === true, 'checking that mouse().button.left is true'); | |
87 | t.ok(e.mouse().button.middle === false, 'checking that mouse().button.middle is false'); | |
88 | t.ok(e.mouse().button.right === false, 'checking that mouse().button.right is false'); | |
89 | t.ok((typeof(e.mouse().page) === 'object'), 'checking that mouse().page is an object'); | |
90 | t.ok((typeof(e.mouse().page.x) === 'number'), 'checking that mouse().page.x is a number'); | |
91 | t.ok((typeof(e.mouse().page.y) === 'number'), 'checking that mouse().page.y is a number'); | |
92 | t.ok((typeof(e.mouse().client) === 'object'), 'checking that mouse().client is an object'); | |
93 | t.ok((typeof(e.mouse().client.x) === 'number'), 'checking that mouse().client.x is a number'); | |
94 | t.ok((typeof(e.mouse().client.y) === 'number'), 'checking that mouse().client.y is a number'); | |
95 | ||
96 | /* these should not be defined */ | |
97 | t.ok((typeof(e.relatedTarget()) === 'undefined'), 'checking that relatedTarget() is undefined'); | |
98 | t.ok((typeof(e.key()) === 'undefined'), 'checking that key() is undefined'); | |
99 | }; | |
100 | ||
101 | ||
102 | ident = connect('submit', 'onmousedown', eventTest); | |
103 | triggerMouseEvent('submit', 'mousedown', false); | |
104 | t.is(i, 3, 'Connecting an event to an HTML object and firing a synthetic event'); | |
105 | ||
106 | disconnect(ident); | |
107 | triggerMouseEvent('submit', 'mousedown', false); | |
108 | t.is(i, 3, 'Disconnecting an event to an HTML object and firing a synthetic event'); | |
109 | ||
110 | ||
111 | ||
112 | } | |
113 | ||
114 | // non-DOM tests | |
115 | ||
116 | var hasNoSignals = {}; | |
117 | ||
118 | var hasSignals = {someVar: 1}; | |
119 | ||
120 | var i = 0; | |
121 | ||
122 | var aFunction = function() { | |
123 | i++; | |
124 | if (typeof(this.someVar) != 'undefined') { | |
125 | i += this.someVar; | |
126 | } | |
127 | }; | |
128 | ||
129 | var bFunction = function(someArg, someOtherArg) { | |
130 | i += someArg + someOtherArg; | |
131 | }; | |
132 | ||
133 | ||
134 | var aObject = {}; | |
135 | aObject.aMethod = function() { | |
136 | i++; | |
137 | }; | |
138 | ||
139 | aObject.bMethod = function() { | |
140 | i++; | |
141 | }; | |
142 | ||
143 | var bObject = {}; | |
144 | bObject.bMethod = function() { | |
145 | i++; | |
146 | }; | |
147 | ||
148 | ||
149 | ident = connect(hasSignals, 'signalOne', aFunction); | |
150 | signal(hasSignals, 'signalOne'); | |
151 | t.is(i, 2, 'Connecting function'); | |
152 | i = 0; | |
153 | ||
154 | disconnect(ident); | |
155 | signal(hasSignals, 'signalOne'); | |
156 | t.is(i, 0, 'New style disconnecting function'); | |
157 | i = 0; | |
158 | ||
159 | ||
160 | ident = connect(hasSignals, 'signalOne', bFunction); | |
161 | signal(hasSignals, 'signalOne', 1, 2); | |
162 | t.is(i, 3, 'Connecting function'); | |
163 | i = 0; | |
164 | ||
165 | disconnect(ident); | |
166 | signal(hasSignals, 'signalOne', 1, 2); | |
167 | t.is(i, 0, 'New style disconnecting function'); | |
168 | i = 0; | |
169 | ||
170 | ||
171 | connect(hasSignals, 'signalOne', aFunction); | |
172 | signal(hasSignals, 'signalOne'); | |
173 | t.is(i, 2, 'Connecting function'); | |
174 | i = 0; | |
175 | ||
176 | disconnect(hasSignals, 'signalOne', aFunction); | |
177 | signal(hasSignals, 'signalOne'); | |
178 | t.is(i, 0, 'Old style disconnecting function'); | |
179 | i = 0; | |
180 | ||
181 | ||
182 | ident = connect(hasSignals, 'signalOne', aObject, aObject.aMethod); | |
183 | signal(hasSignals, 'signalOne'); | |
184 | t.is(i, 1, 'Connecting obj-function'); | |
185 | i = 0; | |
186 | ||
187 | disconnect(ident); | |
188 | signal(hasSignals, 'signalOne'); | |
189 | t.is(i, 0, 'New style disconnecting obj-function'); | |
190 | i = 0; | |
191 | ||
192 | connect(hasSignals, 'signalOne', aObject, aObject.aMethod); | |
193 | signal(hasSignals, 'signalOne'); | |
194 | t.is(i, 1, 'Connecting obj-function'); | |
195 | i = 0; | |
196 | ||
197 | disconnect(hasSignals, 'signalOne', aObject, aObject.aMethod); | |
198 | signal(hasSignals, 'signalOne'); | |
199 | t.is(i, 0, 'Disconnecting obj-function'); | |
200 | i = 0; | |
201 | ||
202 | ||
203 | ident = connect(hasSignals, 'signalTwo', aObject, 'aMethod'); | |
204 | signal(hasSignals, 'signalTwo'); | |
205 | t.is(i, 1, 'Connecting obj-string'); | |
206 | i = 0; | |
207 | ||
208 | disconnect(ident); | |
209 | signal(hasSignals, 'signalTwo'); | |
210 | t.is(i, 0, 'New style disconnecting obj-string'); | |
211 | i = 0; | |
212 | ||
213 | ||
214 | connect(hasSignals, 'signalTwo', aObject, 'aMethod'); | |
215 | signal(hasSignals, 'signalTwo'); | |
216 | t.is(i, 1, 'Connecting obj-string'); | |
217 | i = 0; | |
218 | ||
219 | disconnect(hasSignals, 'signalTwo', aObject, 'aMethod'); | |
220 | signal(hasSignals, 'signalTwo'); | |
221 | t.is(i, 0, 'Old style disconnecting obj-string'); | |
222 | i = 0; | |
223 | ||
224 | ||
225 | var shouldRaise = function() { return undefined.attr; }; | |
226 | ||
227 | try { | |
228 | connect(hasSignals, 'signalOne', shouldRaise); | |
229 | signal(hasSignals, 'signalOne'); | |
230 | t.ok(false, 'An exception was not raised'); | |
231 | } catch (e) { | |
232 | t.ok(true, 'An exception was raised'); | |
233 | } | |
234 | disconnect(hasSignals, 'signalOne', shouldRaise); | |
235 | t.is(i, 0, 'Exception raised, signal should not have fired'); | |
236 | i = 0; | |
237 | ||
238 | ||
239 | connect(hasSignals, 'signalOne', aObject, 'aMethod'); | |
240 | connect(hasSignals, 'signalOne', aObject, 'bMethod'); | |
241 | signal(hasSignals, 'signalOne'); | |
242 | t.is(i, 2, 'Connecting one signal to two slots in one object'); | |
243 | i = 0; | |
244 | ||
245 | disconnect(hasSignals, 'signalOne', aObject, 'aMethod'); | |
246 | disconnect(hasSignals, 'signalOne', aObject, 'bMethod'); | |
247 | signal(hasSignals, 'signalOne'); | |
248 | t.is(i, 0, 'Disconnecting one signal from two slots in one object'); | |
249 | i = 0; | |
250 | ||
251 | ||
252 | connect(hasSignals, 'signalOne', aObject, 'aMethod'); | |
253 | connect(hasSignals, 'signalOne', bObject, 'bMethod'); | |
254 | signal(hasSignals, 'signalOne'); | |
255 | t.is(i, 2, 'Connecting one signal to two slots in two objects'); | |
256 | i = 0; | |
257 | ||
258 | disconnect(hasSignals, 'signalOne', aObject, 'aMethod'); | |
259 | disconnect(hasSignals, 'signalOne', bObject, 'bMethod'); | |
260 | signal(hasSignals, 'signalOne'); | |
261 | t.is(i, 0, 'Disconnecting one signal from two slots in two objects'); | |
262 | i = 0; | |
263 | ||
264 | ||
265 | try { | |
266 | connect(nothing, 'signalOne', aObject, 'aMethod'); | |
267 | signal(nothing, 'signalOne'); | |
268 | t.ok(false, 'An exception was not raised when connecting undefined'); | |
269 | } catch (e) { | |
270 | t.ok(true, 'An exception was raised when connecting undefined'); | |
271 | } | |
272 | ||
273 | try { | |
274 | disconnect(nothing, 'signalOne', aObject, 'aMethod'); | |
275 | t.ok(false, 'An exception was not raised when disconnecting undefined'); | |
276 | } catch (e) { | |
277 | t.ok(true, 'An exception was raised when disconnecting undefined'); | |
278 | } | |
279 | ||
280 | ||
281 | try { | |
282 | connect(hasSignals, 'signalOne', nothing); | |
283 | signal(hasSignals, 'signalOne'); | |
284 | t.ok(false, 'An exception was not raised when connecting an undefined function'); | |
285 | } catch (e) { | |
286 | t.ok(true, 'An exception was raised when connecting an undefined function'); | |
287 | } | |
288 | ||
289 | try { | |
290 | disconnect(hasSignals, 'signalOne', nothing); | |
291 | t.ok(false, 'An exception was not raised when disconnecting an undefined function'); | |
292 | } catch (e) { | |
293 | t.ok(true, 'An exception was raised when disconnecting an undefined function'); | |
294 | } | |
295 | ||
296 | ||
297 | try { | |
298 | connect(hasSignals, 'signalOne', aObject, aObject.nothing); | |
299 | signal(hasSignals, 'signalOne'); | |
300 | t.ok(false, 'An exception was not raised when connecting an undefined method'); | |
301 | } catch (e) { | |
302 | t.ok(true, 'An exception was raised when connecting an undefined method'); | |
303 | } | |
304 | ||
305 | try { | |
306 | connect(hasSignals, 'signalOne', aObject, 'nothing'); | |
307 | signal(hasSignals, 'signalOne'); | |
308 | t.ok(false, 'An exception was not raised when connecting an undefined method (as string)'); | |
309 | } catch (e) { | |
310 | t.ok(true, 'An exception was raised when connecting an undefined method (as string)'); | |
311 | } | |
312 | ||
313 | t.is(i, 0, 'Signals should not have fired'); | |
314 | ||
315 | connect(hasSignals, 'signalOne', aFunction); | |
316 | connect(hasSignals, 'signalOne', aObject, 'aMethod'); | |
317 | disconnectAll(hasSignals, 'signalOne'); | |
318 | signal(hasSignals, 'signalOne'); | |
319 | t.is(i, 0, 'disconnectAll works with single explicit signal'); | |
320 | i = 0; | |
321 | ||
322 | connect(hasSignals, 'signalOne', aFunction); | |
323 | connect(hasSignals, 'signalOne', aObject, 'aMethod'); | |
324 | connect(hasSignals, 'signalTwo', aFunction); | |
325 | connect(hasSignals, 'signalTwo', aObject, 'aMethod'); | |
326 | disconnectAll(hasSignals, 'signalOne'); | |
327 | signal(hasSignals, 'signalOne'); | |
328 | t.is(i, 0, 'disconnectAll works with single explicit signal'); | |
329 | signal(hasSignals, 'signalTwo'); | |
330 | t.is(i, 3, 'disconnectAll does not disconnect unrelated signals'); | |
331 | i = 0; | |
332 | ||
333 | connect(hasSignals, 'signalOne', aFunction); | |
334 | connect(hasSignals, 'signalOne', aObject, 'aMethod'); | |
335 | connect(hasSignals, 'signalTwo', aFunction); | |
336 | connect(hasSignals, 'signalTwo', aObject, 'aMethod'); | |
337 | disconnectAll(hasSignals, 'signalOne', 'signalTwo'); | |
338 | signal(hasSignals, 'signalOne'); | |
339 | signal(hasSignals, 'signalTwo'); | |
340 | t.is(i, 0, 'disconnectAll works with two explicit signals'); | |
341 | i = 0; | |
342 | ||
343 | connect(hasSignals, 'signalOne', aFunction); | |
344 | connect(hasSignals, 'signalOne', aObject, 'aMethod'); | |
345 | connect(hasSignals, 'signalTwo', aFunction); | |
346 | connect(hasSignals, 'signalTwo', aObject, 'aMethod'); | |
347 | disconnectAll(hasSignals, ['signalOne', 'signalTwo']); | |
348 | signal(hasSignals, 'signalOne'); | |
349 | signal(hasSignals, 'signalTwo'); | |
350 | t.is(i, 0, 'disconnectAll works with two explicit signals as a list'); | |
351 | i = 0; | |
352 | ||
353 | connect(hasSignals, 'signalOne', aFunction); | |
354 | connect(hasSignals, 'signalOne', aObject, 'aMethod'); | |
355 | connect(hasSignals, 'signalTwo', aFunction); | |
356 | connect(hasSignals, 'signalTwo', aObject, 'aMethod'); | |
357 | disconnectAll(hasSignals); | |
358 | signal(hasSignals, 'signalOne'); | |
359 | signal(hasSignals, 'signalTwo'); | |
360 | t.is(i, 0, 'disconnectAll works with implicit signals'); | |
361 | i = 0; | |
362 | ||
363 | var toggle = function() { | |
364 | disconnectAll(hasSignals, 'signalOne'); | |
365 | connect(hasSignals, 'signalOne', aFunction); | |
366 | i++; | |
367 | }; | |
368 | ||
369 | connect(hasSignals, 'signalOne', aFunction); | |
370 | connect(hasSignals, 'signalTwo', function() { i++; }); | |
371 | connect(hasSignals, 'signalTwo', toggle); | |
372 | connect(hasSignals, 'signalTwo', function() { i++; }); // #147 | |
373 | connect(hasSignals, 'signalTwo', function() { i++; }); | |
374 | signal(hasSignals, 'signalTwo'); | |
375 | t.is(i, 4, 'disconnectAll fired in a signal loop works'); | |
376 | i = 0; | |
377 | disconnectAll('signalOne'); | |
378 | disconnectAll('signalTwo'); | |
379 | ||
380 | var testfunc = function () { arguments.callee.count++; }; | |
381 | testfunc.count = 0; | |
382 | var testObj = { | |
383 | methOne: function () { this.countOne++; }, countOne: 0, | |
384 | methTwo: function () { this.countTwo++; }, countTwo: 0 | |
385 | }; | |
386 | connect(hasSignals, 'signalOne', testfunc); | |
387 | connect(hasSignals, 'signalTwo', testfunc); | |
388 | signal(hasSignals, 'signalOne'); | |
389 | signal(hasSignals, 'signalTwo'); | |
390 | t.is(testfunc.count, 2, 'disconnectAllTo func precondition'); | |
391 | disconnectAllTo(testfunc); | |
392 | signal(hasSignals, 'signalOne'); | |
393 | signal(hasSignals, 'signalTwo'); | |
394 | t.is(testfunc.count, 2, 'disconnectAllTo func'); | |
395 | ||
396 | connect(hasSignals, 'signalOne', testObj, 'methOne'); | |
397 | connect(hasSignals, 'signalTwo', testObj, 'methTwo'); | |
398 | signal(hasSignals, 'signalOne'); | |
399 | signal(hasSignals, 'signalTwo'); | |
400 | t.is(testObj.countOne, 1, 'disconnectAllTo obj precondition'); | |
401 | t.is(testObj.countTwo, 1, 'disconnectAllTo obj precondition'); | |
402 | disconnectAllTo(testObj); | |
403 | signal(hasSignals, 'signalOne'); | |
404 | signal(hasSignals, 'signalTwo'); | |
405 | t.is(testObj.countOne, 1, 'disconnectAllTo obj'); | |
406 | t.is(testObj.countTwo, 1, 'disconnectAllTo obj'); | |
407 | ||
408 | testObj.countOne = testObj.countTwo = 0; | |
409 | connect(hasSignals, 'signalOne', testObj, 'methOne'); | |
410 | connect(hasSignals, 'signalTwo', testObj, 'methTwo'); | |
411 | disconnectAllTo(testObj, 'methOne'); | |
412 | signal(hasSignals, 'signalOne'); | |
413 | signal(hasSignals, 'signalTwo'); | |
414 | t.is(testObj.countOne, 0, 'disconnectAllTo obj+str'); | |
415 | t.is(testObj.countTwo, 1, 'disconnectAllTo obj+str'); | |
416 | ||
417 | has__Connect = { | |
418 | count: 0, | |
419 | __connect__: function (ident) { | |
420 | this.count += arguments.length; | |
421 | disconnect(ident); | |
422 | } | |
423 | }; | |
424 | ||
425 | connect(has__Connect, 'signalOne', aFunction); | |
426 | t.is(has__Connect.count, 3, '__connect__ is called when it exists'); | |
427 | signal(has__Connect, 'signalOne'); | |
428 | t.is(has__Connect.count, 3, '__connect__ can disconnect the signal'); | |
429 | ||
430 | }; |