Initial check-in
[dygraphs.git] / mochikit_v14 / tests / test_Signal.js
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 };