]>
Commit | Line | Data |
---|---|---|
6527f429 DM |
1 | describe("Ext.app.ViewController", function() {\r |
2 | \r | |
3 | var ct, controller, doInit, doBeforeInit;\r | |
4 | \r | |
5 | function makeContainer(cfg) {\r | |
6 | cfg = cfg || {};\r | |
7 | Ext.applyIf(cfg, {\r | |
8 | controller: 'test1'\r | |
9 | });\r | |
10 | ct = new Ext.container.Container(cfg);\r | |
11 | controller = ct.getController();\r | |
12 | }\r | |
13 | \r | |
14 | beforeEach(function() {\r | |
15 | Ext.define('spec.TestController1', {\r | |
16 | extend: 'Ext.app.ViewController',\r | |
17 | alias: 'controller.test1',\r | |
18 | \r | |
19 | beforeInit: function(view) {\r | |
20 | if (doBeforeInit) {\r | |
21 | doBeforeInit(this);\r | |
22 | }\r | |
23 | },\r | |
24 | \r | |
25 | init: function(view) {\r | |
26 | if (doInit) {\r | |
27 | doInit(this);\r | |
28 | }\r | |
29 | },\r | |
30 | \r | |
31 | method1: function() {},\r | |
32 | \r | |
33 | method2: function() {}\r | |
34 | });\r | |
35 | \r | |
36 | Ext.define('spec.TestController2', {\r | |
37 | extend: 'Ext.app.ViewController',\r | |
38 | alias: 'controller.test2',\r | |
39 | \r | |
40 | init: function() {},\r | |
41 | \r | |
42 | method1: function() {},\r | |
43 | \r | |
44 | method2: function() {}\r | |
45 | });\r | |
46 | \r | |
47 | Ext.define('spec.TestController3', {\r | |
48 | extend: 'Ext.app.ViewController',\r | |
49 | alias: 'controller.test3',\r | |
50 | \r | |
51 | method1: function() {},\r | |
52 | \r | |
53 | method2: function() {}\r | |
54 | });\r | |
55 | });\r | |
56 | \r | |
57 | afterEach(function() {\r | |
58 | Ext.destroy(ct);\r | |
59 | Ext.undefine('spec.TestController1');\r | |
60 | Ext.undefine('spec.TestController2');\r | |
61 | Ext.undefine('spec.TestController3');\r | |
62 | doBeforeInit = doInit = controller = ct = null;\r | |
63 | });\r | |
64 | \r | |
65 | describe("initializing", function() {\r | |
66 | it("should set the view on the controller", function() {\r | |
67 | makeContainer();\r | |
68 | expect(controller.getView()).toBe(ct); \r | |
69 | });\r | |
70 | \r | |
71 | it("should should call init once the container has initialized its items", function() {\r | |
72 | var count = 0;\r | |
73 | doInit = function(ctrl) {\r | |
74 | count = ctrl.getView().items.getCount();\r | |
75 | };\r | |
76 | \r | |
77 | makeContainer({\r | |
78 | items: {\r | |
79 | xtype: 'component'\r | |
80 | }\r | |
81 | }); \r | |
82 | expect(count).toBe(1);\r | |
83 | });\r | |
84 | \r | |
85 | it("should call the init method and pass the component", function() {\r | |
86 | var ctrl = new spec.TestController2();\r | |
87 | spyOn(ctrl, 'init');\r | |
88 | var c = new Ext.Component({\r | |
89 | controller: ctrl\r | |
90 | });\r | |
91 | expect(ctrl.init).toHaveBeenCalledWith(c);\r | |
92 | Ext.destroy(c);\r | |
93 | });\r | |
94 | \r | |
95 | it("should call the beforeInit method before initComponent of the component", function() {\r | |
96 | var called = false,\r | |
97 | wasCalled;\r | |
98 | \r | |
99 | var C = Ext.define(null, {\r | |
100 | extend: 'Ext.Component',\r | |
101 | \r | |
102 | initComponent: function() {\r | |
103 | called = true;\r | |
104 | this.callParent();\r | |
105 | }\r | |
106 | });\r | |
107 | \r | |
108 | doBeforeInit = function(ctrl) {\r | |
109 | wasCalled = !!called\r | |
110 | };\r | |
111 | \r | |
112 | var c = new C({\r | |
113 | controller: {\r | |
114 | type: 'test1'\r | |
115 | }\r | |
116 | });\r | |
117 | \r | |
118 | c.destroy();\r | |
119 | });\r | |
120 | \r | |
121 | it("should call the beforeInit method and pass the component", function() {\r | |
122 | var ctrl = new spec.TestController2();\r | |
123 | spyOn(ctrl, 'beforeInit');\r | |
124 | var c = new Ext.Component({\r | |
125 | controller: ctrl\r | |
126 | });\r | |
127 | expect(ctrl.beforeInit).toHaveBeenCalledWith(c);\r | |
128 | c.destroy();\r | |
129 | });\r | |
130 | });\r | |
131 | \r | |
132 | describe("template methods", function() {\r | |
133 | describe("initViewModel", function() {\r | |
134 | it("should not get called if there is no viewModel", function() {\r | |
135 | var ctrl = new spec.TestController1(),\r | |
136 | spy = spyOn(ctrl, 'initViewModel');\r | |
137 | \r | |
138 | makeContainer({\r | |
139 | controller: ctrl\r | |
140 | });\r | |
141 | // Force VM creation\r | |
142 | ct.getViewModel();\r | |
143 | expect(spy).not.toHaveBeenCalled();\r | |
144 | });\r | |
145 | \r | |
146 | it("should get called with the view model as an argument", function() {\r | |
147 | var ctrl = new spec.TestController1(),\r | |
148 | vm = new Ext.app.ViewModel(),\r | |
149 | spy = spyOn(ctrl, 'initViewModel');\r | |
150 | \r | |
151 | makeContainer({\r | |
152 | controller: ctrl,\r | |
153 | viewModel: vm\r | |
154 | });\r | |
155 | // Force VM creation\r | |
156 | ct.getViewModel();\r | |
157 | expect(spy).toHaveBeenCalledWith(vm);\r | |
158 | });\r | |
159 | \r | |
160 | it("should be able to call getViewModel", function() {\r | |
161 | var ctrl = new spec.TestController1(),\r | |
162 | vm = new Ext.app.ViewModel(),\r | |
163 | spy = spyOn(ctrl, 'initViewModel').andCallFake(function() {\r | |
164 | result = this.getViewModel();\r | |
165 | }), result;\r | |
166 | \r | |
167 | makeContainer({\r | |
168 | controller: ctrl,\r | |
169 | viewModel: vm\r | |
170 | });\r | |
171 | // Force VM creation\r | |
172 | ct.getViewModel();\r | |
173 | expect(result).toBe(vm);\r | |
174 | });\r | |
175 | });\r | |
176 | });\r | |
177 | \r | |
178 | describe("references", function() {\r | |
179 | it("should get the same reference as the view", function() {\r | |
180 | makeContainer({\r | |
181 | items: {\r | |
182 | xtype: 'component',\r | |
183 | itemId: 'compA',\r | |
184 | reference: 'a'\r | |
185 | }\r | |
186 | });\r | |
187 | var c = controller.lookupReference('a');\r | |
188 | expect(c).toBe(ct.down('#compA')); \r | |
189 | });\r | |
190 | });\r | |
191 | \r | |
192 | describe("accessing via the view", function() {\r | |
193 | it("should return null when the view has no view controller", function() {\r | |
194 | makeContainer();\r | |
195 | expect(controller.getViewModel()).toBeNull();\r | |
196 | });\r | |
197 | \r | |
198 | it("should return the view model of the view directly", function() {\r | |
199 | var vm = new Ext.app.ViewModel();\r | |
200 | makeContainer({\r | |
201 | viewModel: vm\r | |
202 | });\r | |
203 | expect(controller.getViewModel()).toBe(vm);\r | |
204 | });\r | |
205 | \r | |
206 | it("should return an inherited view model if not specified on the view", function() {\r | |
207 | var vm = new Ext.app.ViewModel();\r | |
208 | makeContainer({\r | |
209 | viewModel: vm,\r | |
210 | items: [{\r | |
211 | xtype: 'container',\r | |
212 | controller: 'test2'\r | |
213 | }]\r | |
214 | });\r | |
215 | expect(ct.items.first().getController().getViewModel()).toBe(vm);\r | |
216 | });\r | |
217 | });\r | |
218 | \r | |
219 | describe("getStore", function() {\r | |
220 | it("should return null when no named store exists on the view model", function() {\r | |
221 | makeContainer({\r | |
222 | viewModel: true,\r | |
223 | renderTo: Ext.getBody(),\r | |
224 | items: [{\r | |
225 | xtype: 'container',\r | |
226 | controller: 'test2'\r | |
227 | }]\r | |
228 | });\r | |
229 | expect(controller.getStore('users')).toBe(null);\r | |
230 | });\r | |
231 | \r | |
232 | it("should return null if there is no viewModel attached to the view", function() {\r | |
233 | makeContainer({\r | |
234 | renderTo: Ext.getBody(),\r | |
235 | items: [{\r | |
236 | xtype: 'container',\r | |
237 | controller: 'test2'\r | |
238 | }]\r | |
239 | });\r | |
240 | expect(ct.getViewModel()).toBeNull();\r | |
241 | expect(controller.getStore('users')).toBeNull();\r | |
242 | });\r | |
243 | \r | |
244 | it("should return the named store from the view model", function() {\r | |
245 | var vm = new Ext.app.ViewModel({\r | |
246 | stores: {\r | |
247 | users: {\r | |
248 | fields: ['name']\r | |
249 | }\r | |
250 | }\r | |
251 | });\r | |
252 | makeContainer({\r | |
253 | renderTo: Ext.getBody(),\r | |
254 | viewModel: vm\r | |
255 | });\r | |
256 | expect(controller.getStore('users')).toBe(vm.getStore('users'));\r | |
257 | });\r | |
258 | });\r | |
259 | \r | |
260 | describe("getSession", function() {\r | |
261 | it("should return a session attached the view", function() {\r | |
262 | var session = new Ext.data.Session();\r | |
263 | makeContainer({\r | |
264 | renderTo: Ext.getBody(),\r | |
265 | session: session\r | |
266 | });\r | |
267 | expect(controller.getSession()).toBe(session);\r | |
268 | });\r | |
269 | \r | |
270 | it("should find a session higher in the hierarchy", function() {\r | |
271 | var controller = new Ext.app.ViewController(),\r | |
272 | session = new Ext.data.Session();\r | |
273 | \r | |
274 | makeContainer({\r | |
275 | controller: null,\r | |
276 | session: session,\r | |
277 | items: {\r | |
278 | xtype: 'container',\r | |
279 | items: {\r | |
280 | xtype: 'container',\r | |
281 | items: {\r | |
282 | xtype: 'container',\r | |
283 | items: {\r | |
284 | xtype: 'container',\r | |
285 | controller: controller\r | |
286 | }\r | |
287 | }\r | |
288 | }\r | |
289 | }\r | |
290 | });\r | |
291 | expect(controller.getSession()).toBe(session);\r | |
292 | });\r | |
293 | \r | |
294 | it("should return the closest session in the hierarchy", function() {\r | |
295 | var controller = new Ext.app.ViewController(),\r | |
296 | session1 = new Ext.data.Session(),\r | |
297 | session2 = new Ext.data.Session();\r | |
298 | \r | |
299 | makeContainer({\r | |
300 | controller: null,\r | |
301 | session: session1,\r | |
302 | items: {\r | |
303 | xtype: 'container',\r | |
304 | items: {\r | |
305 | xtype: 'container',\r | |
306 | session: session2,\r | |
307 | items: {\r | |
308 | xtype: 'container',\r | |
309 | items: {\r | |
310 | xtype: 'container',\r | |
311 | controller: controller\r | |
312 | }\r | |
313 | }\r | |
314 | }\r | |
315 | }\r | |
316 | });\r | |
317 | expect(controller.getSession()).toBe(session2);\r | |
318 | });\r | |
319 | \r | |
320 | it("should return null when no session is attached to the view", function() {\r | |
321 | makeContainer({\r | |
322 | renderTo: Ext.getBody()\r | |
323 | });\r | |
324 | expect(controller.getSession()).toBeNull();\r | |
325 | });\r | |
326 | \r | |
327 | it("should return null when no session exists in the hierarchy", function() {\r | |
328 | var controller = new Ext.app.ViewController();\r | |
329 | \r | |
330 | makeContainer({\r | |
331 | controller: null,\r | |
332 | items: {\r | |
333 | xtype: 'container',\r | |
334 | items: {\r | |
335 | xtype: 'container',\r | |
336 | items: {\r | |
337 | xtype: 'container',\r | |
338 | items: {\r | |
339 | xtype: 'container',\r | |
340 | controller: controller\r | |
341 | }\r | |
342 | }\r | |
343 | }\r | |
344 | }\r | |
345 | });\r | |
346 | expect(controller.getSession()).toBeNull();\r | |
347 | });\r | |
348 | });\r | |
349 | \r | |
350 | describe("getViewModel", function() {\r | |
351 | it("should return a viewModel attached the view", function() {\r | |
352 | var vm = new Ext.app.ViewModel();\r | |
353 | makeContainer({\r | |
354 | renderTo: Ext.getBody(),\r | |
355 | viewModel: vm\r | |
356 | });\r | |
357 | expect(controller.getViewModel()).toBe(vm);\r | |
358 | });\r | |
359 | \r | |
360 | it("should find a view model higher in the hierarchy", function() {\r | |
361 | var controller = new Ext.app.ViewController(),\r | |
362 | vm = new Ext.app.ViewModel();\r | |
363 | \r | |
364 | makeContainer({\r | |
365 | controller: null,\r | |
366 | viewModel: vm,\r | |
367 | items: {\r | |
368 | xtype: 'container',\r | |
369 | items: {\r | |
370 | xtype: 'container',\r | |
371 | items: {\r | |
372 | xtype: 'container',\r | |
373 | items: {\r | |
374 | xtype: 'container',\r | |
375 | controller: controller\r | |
376 | }\r | |
377 | }\r | |
378 | }\r | |
379 | }\r | |
380 | });\r | |
381 | expect(controller.getViewModel()).toBe(vm);\r | |
382 | });\r | |
383 | \r | |
384 | it("should return the closest viewModel in the hierarchy", function() {\r | |
385 | var controller = new Ext.app.ViewController(),\r | |
386 | vm1 = new Ext.app.ViewModel(),\r | |
387 | vm2 = new Ext.app.ViewModel();\r | |
388 | \r | |
389 | makeContainer({\r | |
390 | controller: null,\r | |
391 | viewModel: vm1,\r | |
392 | items: {\r | |
393 | xtype: 'container',\r | |
394 | items: {\r | |
395 | xtype: 'container',\r | |
396 | viewModel: vm2,\r | |
397 | items: {\r | |
398 | xtype: 'container',\r | |
399 | items: {\r | |
400 | xtype: 'container',\r | |
401 | controller: controller\r | |
402 | }\r | |
403 | }\r | |
404 | }\r | |
405 | }\r | |
406 | });\r | |
407 | expect(controller.getViewModel()).toBe(vm2);\r | |
408 | });\r | |
409 | \r | |
410 | it("should return null when no viewModel is attached to the view", function() {\r | |
411 | makeContainer({\r | |
412 | renderTo: Ext.getBody()\r | |
413 | });\r | |
414 | expect(controller.getViewModel()).toBeNull();\r | |
415 | });\r | |
416 | \r | |
417 | it("should return null when no viewModel exists in the hierarchy", function() {\r | |
418 | var controller = new Ext.app.ViewController();\r | |
419 | \r | |
420 | makeContainer({\r | |
421 | controller: null,\r | |
422 | items: {\r | |
423 | xtype: 'container',\r | |
424 | items: {\r | |
425 | xtype: 'container',\r | |
426 | items: {\r | |
427 | xtype: 'container',\r | |
428 | items: {\r | |
429 | xtype: 'container',\r | |
430 | controller: controller\r | |
431 | }\r | |
432 | }\r | |
433 | }\r | |
434 | }\r | |
435 | });\r | |
436 | expect(controller.getViewModel()).toBeNull();\r | |
437 | });\r | |
438 | });\r | |
439 | \r | |
440 | describe("listen", function() {\r | |
441 | it("should ensure any control listeners get scoped to the controller", function() {\r | |
442 | makeContainer({\r | |
443 | controller: {\r | |
444 | type: 'test1',\r | |
445 | listen: {\r | |
446 | component: {\r | |
447 | container: {\r | |
448 | custom: 'method1'\r | |
449 | }\r | |
450 | }\r | |
451 | }\r | |
452 | },\r | |
453 | items: {\r | |
454 | xtype: 'container'\r | |
455 | }\r | |
456 | });\r | |
457 | \r | |
458 | spyOn(controller, 'method1');\r | |
459 | var other = new Ext.container.Container();\r | |
460 | other.fireEvent('custom');\r | |
461 | expect(controller.method1).not.toHaveBeenCalled();\r | |
462 | ct.items.first().fireEvent('custom');\r | |
463 | expect(controller.method1).toHaveBeenCalled();\r | |
464 | \r | |
465 | Ext.destroy(other);\r | |
466 | });\r | |
467 | });\r | |
468 | \r | |
469 | describe("listeners", function() {\r | |
470 | describe("direct events", function() {\r | |
471 | it("should call a method on the controller", function() {\r | |
472 | makeContainer({\r | |
473 | items: [{\r | |
474 | xtype: 'container',\r | |
475 | listeners: {\r | |
476 | custom: 'method1'\r | |
477 | }\r | |
478 | }]\r | |
479 | });\r | |
480 | spyOn(controller, 'method1');\r | |
481 | ct.items.first().fireEvent('custom');\r | |
482 | expect(controller.method1).toHaveBeenCalled();\r | |
483 | }); \r | |
484 | \r | |
485 | it("should not call a method if events are suspended", function() {\r | |
486 | makeContainer({\r | |
487 | items: [{\r | |
488 | xtype: 'container',\r | |
489 | listeners: {\r | |
490 | custom: 'method1'\r | |
491 | }\r | |
492 | }]\r | |
493 | });\r | |
494 | spyOn(controller, 'method1');\r | |
495 | var c = ct.items.first();\r | |
496 | c.suspendEvents();\r | |
497 | c.fireEvent('custom');\r | |
498 | expect(controller.method1).not.toHaveBeenCalled();\r | |
499 | });\r | |
500 | \r | |
501 | it("should encapsulate events", function() {\r | |
502 | makeContainer({\r | |
503 | renderTo: Ext.getBody(),\r | |
504 | items: [{\r | |
505 | xtype: 'container',\r | |
506 | controller: 'test2',\r | |
507 | items: [{\r | |
508 | xtype: 'component',\r | |
509 | listeners: {\r | |
510 | custom: 'method1'\r | |
511 | }\r | |
512 | }]\r | |
513 | }]\r | |
514 | });\r | |
515 | var child = ct.items.first().getController();\r | |
516 | spyOn(controller, 'method1');\r | |
517 | spyOn(child, 'method1');\r | |
518 | \r | |
519 | child.getView().items.first().fireEvent('custom');\r | |
520 | expect(child.method1).toHaveBeenCalled();\r | |
521 | expect(controller.method1).not.toHaveBeenCalled();\r | |
522 | }); \r | |
523 | });\r | |
524 | \r | |
525 | describe("on the event bus", function() {\r | |
526 | it("should react to matching selectors", function() {\r | |
527 | makeContainer({\r | |
528 | controller: {\r | |
529 | type: 'test1',\r | |
530 | control: {\r | |
531 | 'container': {\r | |
532 | custom: 'method1'\r | |
533 | }\r | |
534 | }\r | |
535 | },\r | |
536 | items: [{\r | |
537 | xtype: 'container',\r | |
538 | items: {\r | |
539 | xtype: 'container',\r | |
540 | itemId: 'a'\r | |
541 | }\r | |
542 | }]\r | |
543 | });\r | |
544 | \r | |
545 | var c = ct.down('#a');\r | |
546 | \r | |
547 | spyOn(controller, 'method1'); \r | |
548 | c.fireEvent('custom');\r | |
549 | expect(controller.method1).toHaveBeenCalled();\r | |
550 | });\r | |
551 | \r | |
552 | it("should not react to non matching selectors", function() {\r | |
553 | makeContainer({\r | |
554 | controller: {\r | |
555 | type: 'test1',\r | |
556 | control: {\r | |
557 | 'container': {\r | |
558 | custom: 'method1'\r | |
559 | }\r | |
560 | }\r | |
561 | },\r | |
562 | items: [{\r | |
563 | xtype: 'container',\r | |
564 | items: {\r | |
565 | xtype: 'button',\r | |
566 | itemId: 'a'\r | |
567 | }\r | |
568 | }]\r | |
569 | });\r | |
570 | \r | |
571 | var c = ct.down('#a');\r | |
572 | \r | |
573 | spyOn(controller, 'method1'); \r | |
574 | c.fireEvent('custom');\r | |
575 | expect(controller.method1).not.toHaveBeenCalled();\r | |
576 | });\r | |
577 | \r | |
578 | it("should react to events on itself", function() {\r | |
579 | makeContainer({\r | |
580 | controller: {\r | |
581 | type: 'test1',\r | |
582 | control: {\r | |
583 | 'container': {\r | |
584 | custom: 'method1'\r | |
585 | }\r | |
586 | }\r | |
587 | }\r | |
588 | }); \r | |
589 | spyOn(controller, 'method1'); \r | |
590 | ct.fireEvent('custom');\r | |
591 | expect(controller.method1).toHaveBeenCalled();\r | |
592 | });\r | |
593 | \r | |
594 | it("should not react to events outside the hierarchy", function() {\r | |
595 | makeContainer({\r | |
596 | controller: {\r | |
597 | type: 'test1',\r | |
598 | control: {\r | |
599 | 'container': {\r | |
600 | custom: 'method1'\r | |
601 | }\r | |
602 | }\r | |
603 | }\r | |
604 | }); \r | |
605 | spyOn(controller, 'method1'); \r | |
606 | var other = new Ext.container.Container();\r | |
607 | other.fireEvent('custom');\r | |
608 | expect(controller.method1).not.toHaveBeenCalled();\r | |
609 | other.destroy();\r | |
610 | });\r | |
611 | \r | |
612 | it("should remove listeners when the controller is destroyed", function() {\r | |
613 | makeContainer({\r | |
614 | controller: {\r | |
615 | type: 'test1',\r | |
616 | control: {\r | |
617 | 'container': {\r | |
618 | custom: 'method1'\r | |
619 | }\r | |
620 | }\r | |
621 | },\r | |
622 | items: {\r | |
623 | xtype: 'container'\r | |
624 | }\r | |
625 | }); \r | |
626 | spyOn(controller, 'method1');\r | |
627 | controller.destroy(); \r | |
628 | ct.items.first().fireEvent('custom');\r | |
629 | expect(controller.method1).not.toHaveBeenCalled();\r | |
630 | });\r | |
631 | \r | |
632 | it("should use the '#' selector to match the reference holder", function() {\r | |
633 | makeContainer({\r | |
634 | controller: {\r | |
635 | type: 'test1',\r | |
636 | control: {\r | |
637 | '#': {\r | |
638 | custom: 'method1'\r | |
639 | }\r | |
640 | }\r | |
641 | },\r | |
642 | items: {\r | |
643 | xtype: 'component',\r | |
644 | itemId: 'compA'\r | |
645 | }\r | |
646 | }); \r | |
647 | spyOn(controller, 'method1');\r | |
648 | ct.items.first().fireEvent('custom');\r | |
649 | expect(controller.method1).not.toHaveBeenCalled();\r | |
650 | ct.fireEvent('custom');\r | |
651 | expect(controller.method1).toHaveBeenCalled();\r | |
652 | });\r | |
653 | \r | |
654 | it("should not react if the controller gets destroyed during event firing", function() {\r | |
655 | makeContainer({\r | |
656 | controller: {\r | |
657 | type: 'test1',\r | |
658 | control: {\r | |
659 | '#': {\r | |
660 | custom: 'method1'\r | |
661 | }\r | |
662 | }\r | |
663 | }\r | |
664 | });\r | |
665 | ct.on('custom', function() {\r | |
666 | ct.destroy();\r | |
667 | });\r | |
668 | spyOn(controller, 'method1');\r | |
669 | ct.fireEvent('custom');\r | |
670 | expect(controller.method1).not.toHaveBeenCalled();\r | |
671 | });\r | |
672 | \r | |
673 | describe("hierarchy", function() {\r | |
674 | var makeController = function(i, control) {\r | |
675 | return {\r | |
676 | type: 'test' + i,\r | |
677 | control: control || {\r | |
678 | 'container': {\r | |
679 | custom: 'method1'\r | |
680 | }\r | |
681 | }\r | |
682 | };\r | |
683 | };\r | |
684 | it("should fire matched events up the hierarchy", function() {\r | |
685 | makeContainer({\r | |
686 | controller: makeController(1),\r | |
687 | items: {\r | |
688 | xtype: 'container',\r | |
689 | controller: makeController(2),\r | |
690 | items: {\r | |
691 | xtype: 'container',\r | |
692 | controller: makeController(3),\r | |
693 | items: {\r | |
694 | xtype: 'container',\r | |
695 | itemId: 'compA'\r | |
696 | }\r | |
697 | }\r | |
698 | }\r | |
699 | }); \r | |
700 | var inner = ct.down('#compA'),\r | |
701 | ctrl3 = inner.up().getController(),\r | |
702 | ctrl2 = inner.up().up().getController(),\r | |
703 | ctrl1 = inner.up().up().up().getController(),\r | |
704 | values = [],\r | |
705 | push = function() {\r | |
706 | values.push(this.type);\r | |
707 | };\r | |
708 | \r | |
709 | spyOn(ctrl1, 'method1').andCallFake(push);\r | |
710 | spyOn(ctrl2, 'method1').andCallFake(push); \r | |
711 | spyOn(ctrl3, 'method1').andCallFake(push);\r | |
712 | inner.fireEvent('custom');\r | |
713 | expect(values).toEqual(['test3', 'test2', 'test1']);\r | |
714 | });\r | |
715 | \r | |
716 | it("should fire parents even if the deepest child doesn't match", function() {\r | |
717 | makeContainer({\r | |
718 | controller: makeController(1),\r | |
719 | items: {\r | |
720 | xtype: 'container',\r | |
721 | controller: makeController(2),\r | |
722 | items: {\r | |
723 | xtype: 'container',\r | |
724 | controller: makeController(3, {}),\r | |
725 | items: {\r | |
726 | xtype: 'container',\r | |
727 | itemId: 'compA'\r | |
728 | }\r | |
729 | }\r | |
730 | }\r | |
731 | }); \r | |
732 | var inner = ct.down('#compA'),\r | |
733 | ctrl3 = inner.up().getController(),\r | |
734 | ctrl2 = inner.up().up().getController(),\r | |
735 | ctrl1 = inner.up().up().up().getController();\r | |
736 | \r | |
737 | spyOn(ctrl1, 'method1');\r | |
738 | spyOn(ctrl2, 'method1'); \r | |
739 | spyOn(ctrl3, 'method1');\r | |
740 | inner.fireEvent('custom');\r | |
741 | expect(ctrl1.method1).toHaveBeenCalled();\r | |
742 | expect(ctrl2.method1).toHaveBeenCalled();\r | |
743 | expect(ctrl3.method1).not.toHaveBeenCalled();\r | |
744 | });\r | |
745 | \r | |
746 | it("should be able to continue up when a controller in the hierarchy doesn't match", function() {\r | |
747 | makeContainer({\r | |
748 | controller: makeController(1),\r | |
749 | items: {\r | |
750 | xtype: 'container',\r | |
751 | controller: makeController(2, {}),\r | |
752 | items: {\r | |
753 | xtype: 'container',\r | |
754 | controller: makeController(3),\r | |
755 | items: {\r | |
756 | xtype: 'container',\r | |
757 | itemId: 'compA'\r | |
758 | }\r | |
759 | }\r | |
760 | }\r | |
761 | }); \r | |
762 | var inner = ct.down('#compA'),\r | |
763 | ctrl3 = inner.up().getController(),\r | |
764 | ctrl2 = inner.up().up().getController(),\r | |
765 | ctrl1 = inner.up().up().up().getController();\r | |
766 | \r | |
767 | spyOn(ctrl1, 'method1');\r | |
768 | spyOn(ctrl2, 'method1'); \r | |
769 | spyOn(ctrl3, 'method1');\r | |
770 | inner.fireEvent('custom');\r | |
771 | expect(ctrl1.method1).toHaveBeenCalled();\r | |
772 | expect(ctrl2.method1).not.toHaveBeenCalled();\r | |
773 | expect(ctrl3.method1).toHaveBeenCalled();\r | |
774 | });\r | |
775 | \r | |
776 | it("should not fire parent events if a lower event returns false", function() {\r | |
777 | makeContainer({\r | |
778 | controller: makeController(1),\r | |
779 | items: {\r | |
780 | xtype: 'container',\r | |
781 | controller: makeController(2),\r | |
782 | items: {\r | |
783 | xtype: 'container',\r | |
784 | controller: makeController(3),\r | |
785 | items: {\r | |
786 | xtype: 'container',\r | |
787 | itemId: 'compA'\r | |
788 | }\r | |
789 | }\r | |
790 | }\r | |
791 | }); \r | |
792 | var inner = ct.down('#compA'),\r | |
793 | ctrl3 = inner.up().getController(),\r | |
794 | ctrl2 = inner.up().up().getController(),\r | |
795 | ctrl1 = inner.up().up().up().getController();\r | |
796 | \r | |
797 | spyOn(ctrl1, 'method1');\r | |
798 | spyOn(ctrl2, 'method1'); \r | |
799 | spyOn(ctrl3, 'method1').andReturn(false);\r | |
800 | inner.fireEvent('custom');\r | |
801 | expect(ctrl1.method1).not.toHaveBeenCalled();\r | |
802 | expect(ctrl2.method1).not.toHaveBeenCalled();\r | |
803 | expect(ctrl3.method1).toHaveBeenCalled();\r | |
804 | });\r | |
805 | });\r | |
806 | });\r | |
807 | \r | |
808 | describe("mixture of both", function() {\r | |
809 | it("should fire direct events first", function() {\r | |
810 | makeContainer({\r | |
811 | controller: {\r | |
812 | type: 'test1',\r | |
813 | control: {\r | |
814 | 'container': {\r | |
815 | custom: 'method1'\r | |
816 | }\r | |
817 | }\r | |
818 | },\r | |
819 | items: {\r | |
820 | xtype: 'container',\r | |
821 | listeners: {\r | |
822 | custom: 'method2'\r | |
823 | }\r | |
824 | }\r | |
825 | });\r | |
826 | \r | |
827 | var c = ct.items.first(),\r | |
828 | ctrl = ct.getController(),\r | |
829 | values = [];\r | |
830 | \r | |
831 | spyOn(ctrl, 'method1').andCallFake(function() {\r | |
832 | values.push(1);\r | |
833 | });\r | |
834 | spyOn(ctrl, 'method2').andCallFake(function() {\r | |
835 | values.push(2);\r | |
836 | });\r | |
837 | \r | |
838 | c.fireEvent('custom');\r | |
839 | expect(values).toEqual([2, 1]);\r | |
840 | });\r | |
841 | \r | |
842 | it("should not fire bus events if direct handlers return false", function() {\r | |
843 | makeContainer({\r | |
844 | controller: {\r | |
845 | type: 'test1',\r | |
846 | control: {\r | |
847 | 'container': {\r | |
848 | custom: 'method1'\r | |
849 | }\r | |
850 | }\r | |
851 | },\r | |
852 | items: {\r | |
853 | xtype: 'container',\r | |
854 | listeners: {\r | |
855 | custom: 'method2'\r | |
856 | }\r | |
857 | }\r | |
858 | });\r | |
859 | \r | |
860 | var c = ct.items.first(),\r | |
861 | ctrl = ct.getController();\r | |
862 | \r | |
863 | spyOn(ctrl, 'method1');\r | |
864 | spyOn(ctrl, 'method2').andReturn(false);\r | |
865 | \r | |
866 | c.fireEvent('custom');\r | |
867 | expect(ctrl.method1).not.toHaveBeenCalled();\r | |
868 | });\r | |
869 | });\r | |
870 | });\r | |
871 | \r | |
872 | describe("fireViewEvent", function() {\r | |
873 | it("view should be first argument", function() {\r | |
874 | makeContainer({\r | |
875 | controller : {\r | |
876 | type: 'test1',\r | |
877 | control: {\r | |
878 | '#': {\r | |
879 | custom: 'method1'\r | |
880 | }\r | |
881 | }\r | |
882 | }\r | |
883 | });\r | |
884 | \r | |
885 | spyOn(controller, 'method1');\r | |
886 | \r | |
887 | controller.fireViewEvent('custom', 'foo');\r | |
888 | \r | |
889 | expect(controller.method1).toHaveBeenCalled();\r | |
890 | expect(controller.method1.mostRecentCall.args[0]).toEqual(ct);\r | |
891 | });\r | |
892 | \r | |
893 | it("view should not add view as first argument", function() {\r | |
894 | makeContainer({\r | |
895 | controller : {\r | |
896 | type: 'test1',\r | |
897 | control: {\r | |
898 | '#': {\r | |
899 | custom: 'method1'\r | |
900 | }\r | |
901 | }\r | |
902 | }\r | |
903 | });\r | |
904 | \r | |
905 | spyOn(controller, 'method1');\r | |
906 | \r | |
907 | controller.fireViewEvent('custom', ct, 'foo');\r | |
908 | \r | |
909 | expect(controller.method1).toHaveBeenCalled();\r | |
910 | expect(controller.method1.mostRecentCall.args[0]).toEqual(ct);\r | |
911 | });\r | |
912 | });\r | |
913 | });\r |