001    // Copyright May 21, 2006 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    package org.apache.tapestry.services.impl;
015    
016    import org.apache.hivemind.ClassResolver;
017    import org.apache.hivemind.Resource;
018    import org.apache.hivemind.impl.DefaultClassResolver;
019    import org.apache.hivemind.util.ClasspathResource;
020    import org.apache.tapestry.*;
021    import org.apache.tapestry.dojo.IWidget;
022    import org.apache.tapestry.engine.IEngineService;
023    import org.apache.tapestry.engine.ILink;
024    import org.apache.tapestry.engine.IScriptSource;
025    import org.apache.tapestry.html.Body;
026    import org.apache.tapestry.internal.event.ComponentEventProperty;
027    import org.apache.tapestry.internal.event.IComponentEventInvoker;
028    import org.apache.tapestry.internal.event.impl.ComponentEventInvoker;
029    import org.apache.tapestry.spec.ComponentSpecification;
030    import org.apache.tapestry.spec.IComponentSpecification;
031    import static org.easymock.EasyMock.*;
032    import org.easymock.MockControl;
033    import org.easymock.classextension.MockClassControl;
034    import org.testng.annotations.Test;
035    
036    import java.util.ArrayList;
037    import java.util.Iterator;
038    import java.util.List;
039    import java.util.Map;
040    
041    
042    /**
043     * Test functionality of {@link ComponentEventConnectionWorker}.
044     * 
045     * @author jkuhnert
046     */
047    @Test
048    public class ComponentEventConnectionWorkerTest extends BaseComponentTestCase
049    {
050        public void test_Event_Render_Chain()
051        {   
052            ClassResolver resolver = new DefaultClassResolver();
053            
054            IComponentEventInvoker invoker = new ComponentEventInvoker();
055            IEngineService engine = newMock(IEngineService.class);
056            IRequestCycle cycle = newCycle();
057            checkOrder(cycle, false);
058            
059            IComponentSpecification spec = new ComponentSpecification();
060            IComponentSpecification widgetSpec = new ComponentSpecification();
061            
062            IScriptSource scriptSource = newMock(IScriptSource.class);
063            IScript script = newMock(IScript.class);
064            
065            PageRenderSupport prs = newPageRenderSupport();
066            
067            ILink link = newMock(ILink.class);
068            
069            String elemScript = "/org/apache/tapestry/html/ElementEvent.script";
070            String compScript = "/org/apache/tapestry/ComponentEvent.script";
071            String widScript = "/org/apache/tapestry/dojo/html/WidgetEvent.script";
072            
073            Resource compScriptResource = new ClasspathResource(resolver, compScript);
074            Resource widScriptResource = new ClasspathResource(resolver, widScript);
075            Resource elemScriptResource = new ClasspathResource(resolver, elemScript);
076            
077            ComponentEventConnectionWorker worker = new ComponentEventConnectionWorker();
078            worker.setClassResolver(resolver);
079            worker.setEventInvoker(invoker);
080            worker.setComponentScript(compScript);
081            worker.setWidgetScript(widScript);
082            worker.setElementScript(elemScript);
083            worker.setEventEngine(engine);
084            worker.setScriptSource(scriptSource);
085            
086            IDirectEvent component = newMock(IDirectEvent.class);
087            IWidget widget = newMock(IWidget.class);
088            
089            assertNotNull(worker.getScript(component));
090            assertEquals(compScript, worker.getScript(component).getPath());
091            
092            assertNotNull(worker.getScript(widget));
093            assertEquals(widScript, worker.getScript(widget).getPath());
094            
095            assertNotNull(worker.getElementScript());
096            assertEquals(elemScript, worker.getElementScript().getPath());
097            
098            // now test render
099            invoker.addEventListener("comp1", spec);
100            spec.addEventListener("comp1", new String[] {"onclick"}, "testMethod", null, false, true, false, false);
101            spec.addElementEventListener("elementId", new String[] {"onclick"}, "testMethod", null, false, true, false);
102            
103            /////////////////////////////////
104            
105            Map elmEvents = spec.getElementEvents();
106            Iterator keyIt = elmEvents.keySet().iterator();
107            
108            while (keyIt.hasNext())
109            {
110                String elem = (String)keyIt.next();
111                assertEquals(elem, "elementId");
112                
113                ComponentEventProperty prop = (ComponentEventProperty)elmEvents.get(elem);
114                assertNotNull(prop);
115                
116                Object[][] events = worker.getEvents(prop, elem);
117                
118                assertNotNull(events);
119                assertEquals(events.length, 1);
120                assertEquals(events[0].length, 2);
121            }
122            
123            ////////////////////////////////////////////
124            
125            expect(cycle.isRewinding()).andReturn(false);
126            expect(cycle.getAttribute(TapestryUtils.FIELD_PRERENDER)).andReturn(null);
127            
128            expect(component.getExtendedId()).andReturn("comp1").anyTimes();
129            expect(component.getClientId()).andReturn("comp1").anyTimes();
130            
131            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(prs).anyTimes();
132            expect(component.getSpecification()).andReturn(spec);
133            
134            trainGetLinkCheckIgnoreParameter(engine, cycle, false, new Object(), link);
135            trainGetURL(link, "/some/url");
136            
137            expect(scriptSource.getScript(compScriptResource)).andReturn(script);
138            script.execute(eq(component), eq(cycle), eq(prs), isA(Map.class));
139            
140            expect(component.getSpecification()).andReturn(spec);
141            
142            trainGetLinkCheckIgnoreParameter(engine, cycle, false, new Object(), link);
143            trainGetURL(link, "/some/url");
144            
145            expect(scriptSource.getScript(elemScriptResource)).andReturn(script);
146            script.execute(eq(component), eq(cycle), eq(prs), isA(Map.class));
147            
148            replay();
149            
150            worker.renderComponent(cycle, component);
151            
152            verify();
153            
154            assertEquals(0, worker.getDefferedFormConnections().size());
155            
156            // test widget render
157            
158            invoker.addEventListener("wid1", widgetSpec);
159            widgetSpec.addEventListener("wid1", new String[] {"onclick"}, "testMethod", null, false, true, false, false);
160            
161            checkOrder(cycle, false);
162            expect(cycle.isRewinding()).andReturn(false);
163            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(prs).anyTimes();
164            
165            expect(widget.getSpecification()).andReturn(widgetSpec);
166            expect(cycle.getAttribute(TapestryUtils.FIELD_PRERENDER)).andReturn(null);
167            
168            expect(widget.getExtendedId()).andReturn("wid1").anyTimes();
169            expect(widget.getClientId()).andReturn("wid1").anyTimes();
170            
171            assert widgetSpec.getComponentEvents("wid1") != null;
172            
173            trainGetLinkCheckIgnoreParameter(engine, cycle, false, new Object(), link);
174            trainGetURL(link, "/some/url2");
175            
176            expect(scriptSource.getScript(widScriptResource)).andReturn(script);
177            
178            script.execute(eq(widget), eq(cycle), eq(prs), isA(Map.class));
179            
180            replay();
181            
182            worker.renderComponent(cycle, widget);
183            
184            verify();
185        }
186        
187        public void test_Rewind_Render()
188        {
189            IRequestCycle cycle = newCycle();
190            
191            ComponentEventConnectionWorker worker = new ComponentEventConnectionWorker();
192            
193            expect(cycle.isRewinding()).andReturn(true);
194            
195            replay();
196            
197            worker.renderComponent(cycle, null);
198            
199            verify();
200        }
201        
202        public void test_Null_PageSupport()
203        {
204            IRequestCycle cycle = newCycle();
205            
206            ComponentEventConnectionWorker worker = new ComponentEventConnectionWorker();
207            
208            expect(cycle.isRewinding()).andReturn(false);
209            
210            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(null);
211            
212            replay();
213            
214            worker.renderComponent(cycle, null);
215            
216            verify();
217        }
218        
219        
220        public void test_Deferred_Connection()
221        {
222            IComponentEventInvoker invoker = new org.apache.tapestry.internal.event.impl.ComponentEventInvoker();
223            IEngineService engine = newMock(IEngineService.class);
224            IRequestCycle cycle = newCycle();
225            PageRenderSupport prs = newPageRenderSupport();
226            
227            ComponentEventConnectionWorker worker = new ComponentEventConnectionWorker();
228            worker.setEventInvoker(invoker);
229            worker.setEventEngine(engine);
230            
231            IDirectEvent component = newMock(IDirectEvent.class);
232            IComponentSpecification spec = new ComponentSpecification();
233            
234            IDirectEvent comp1 = newMock(IDirectEvent.class);
235            IComponentSpecification comp1Spec = new ComponentSpecification();
236            
237            IDirectEvent comp2 = newMock(IDirectEvent.class);
238            IComponentSpecification comp2Spec = new ComponentSpecification();
239            
240            // now test render
241            spec.addEventListener("comp1", new String[] {"onclick", "onchange"}, "testMethod", "form1", true, true, false, false);
242            invoker.addEventListener("comp1", spec);
243            invoker.addFormEventListener("form1", spec);
244            
245            spec.addEventListener("comp2", new String[] {"onclick"}, "testAnotherMethod", "form1", true, true, false, false);
246            invoker.addEventListener("comp2", spec);
247            invoker.addFormEventListener("form1", spec);
248            
249            // render of comp1
250            
251            expect(cycle.isRewinding()).andReturn(false);
252            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(prs);
253            expect(cycle.getAttribute(TapestryUtils.FIELD_PRERENDER)).andReturn(null);
254            
255            expect(comp1.getExtendedId()).andReturn("comp1").anyTimes();
256            expect(comp1.getClientId()).andReturn("comp1").anyTimes();
257            
258            expect(cycle.getAttribute(ComponentEventConnectionWorker.FORM_NAME_LIST + "form1")).andReturn(null).times(2);
259            expect(comp1.getSpecification()).andReturn(comp1Spec);
260            
261            // render of comp2
262            
263            expect(cycle.isRewinding()).andReturn(false);
264            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(prs);
265            expect(cycle.getAttribute(TapestryUtils.FIELD_PRERENDER)).andReturn(null);
266            
267            expect(comp2.getExtendedId()).andReturn("comp2");
268            expect(comp2.getClientId()).andReturn("comp2");
269    
270            expect(cycle.getAttribute(ComponentEventConnectionWorker.FORM_NAME_LIST + "form1")).andReturn(null);
271            expect(comp2.getSpecification()).andReturn(comp2Spec);
272    
273            // second render of comp2
274    
275            expect(cycle.isRewinding()).andReturn(false);
276            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(prs);
277            expect(cycle.getAttribute(TapestryUtils.FIELD_PRERENDER)).andReturn(null);
278    
279            expect(comp2.getExtendedId()).andReturn("comp2");
280            expect(comp2.getClientId()).andReturn("comp2_0");
281    
282            expect(cycle.getAttribute(ComponentEventConnectionWorker.FORM_NAME_LIST + "form1")).andReturn(null);
283            expect(comp2.getSpecification()).andReturn(comp2Spec);
284    
285            // render of component
286            
287            expect(cycle.isRewinding()).andReturn(false);
288            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(prs);
289            expect(cycle.getAttribute(TapestryUtils.FIELD_PRERENDER)).andReturn(null);
290            
291            expect(component.getExtendedId()).andReturn("comp").anyTimes();
292            expect(component.getSpecification()).andReturn(spec);
293            
294            replay();
295            
296            worker.renderComponent(cycle, comp1);
297            worker.renderComponent(cycle, comp2);
298            worker.renderComponent(cycle, comp2); // to test unique client id connections
299            worker.renderComponent(cycle, component);
300            
301            verify();
302            
303            assertEquals(worker.getDefferedFormConnections().size(), 1);
304            
305            List deferred = (List)worker.getDefferedFormConnections().get("form1");
306            
307            assert deferred != null;
308            assertEquals(deferred.size(), 3);
309    
310            ComponentEventConnectionWorker.DeferredFormConnection fConn = (ComponentEventConnectionWorker.DeferredFormConnection)deferred.get(0);
311            
312            // assert async is false
313            assert fConn._async;
314            assert fConn._validate;
315            
316            Map parm = fConn._scriptParms;
317            
318            assert parm.get("clientId") != null;
319            assert parm.get("component") != null;
320            assert parm.get("url") == null;
321            assert parm.get("formEvents") == null;
322            assert parm.get("target") == null;
323            
324            assertEquals("comp1", parm.get("clientId"));
325            assertEquals(comp1, parm.get("component"));
326    
327            // test comp2 connections
328    
329            fConn = (ComponentEventConnectionWorker.DeferredFormConnection)deferred.get(1);
330            parm = fConn._scriptParms;
331    
332            assert fConn._async;
333            assert fConn._validate;
334    
335            assert parm.get("clientId") != null;
336            assert parm.get("component") != null;
337            assert parm.get("url") == null;
338            assert parm.get("formEvents") == null;
339            assert parm.get("target") == null;
340            
341            assertEquals(parm.get("clientId"), "comp2");
342            assertEquals(parm.get("component"), comp2);
343    
344            // test comp2 second render connections
345    
346            fConn = (ComponentEventConnectionWorker.DeferredFormConnection)deferred.get(2);
347            parm = fConn._scriptParms;
348    
349            assert fConn._async;
350            assert fConn._validate;
351    
352            assert parm.get("clientId") != null;
353            assert parm.get("component") != null;
354            assert parm.get("url") == null;
355            assert parm.get("formEvents") == null;
356            assert parm.get("target") == null;
357    
358            assertEquals(parm.get("clientId"), "comp2_0");
359            assertEquals(parm.get("component"), comp2);
360        }
361        
362        public void test_Form_Render_Deffered()
363        {
364            ClassResolver resolver = new DefaultClassResolver();
365            
366            IComponentEventInvoker invoker = new ComponentEventInvoker();
367            IEngineService engine = newMock(IEngineService.class);
368            IRequestCycle cycle = newCycle();
369            IScriptSource scriptSource = newMock(IScriptSource.class);
370            IScript script = newMock(IScript.class);
371            
372            PageRenderSupport prs = newPageRenderSupport();
373            
374            String compScript = "/org/apache/tapestry/ComponentEvent.script";
375            Resource compScriptResource = new ClasspathResource(resolver, compScript);
376            
377            ComponentEventConnectionWorker worker = new ComponentEventConnectionWorker();
378            worker.setClassResolver(resolver);
379            worker.setEventInvoker(invoker);
380            worker.setComponentScript(compScript);
381            worker.setEventEngine(engine);
382            worker.setScriptSource(scriptSource);
383            
384            IDirectEvent component = newMock(IDirectEvent.class);
385            IComponentSpecification spec = new ComponentSpecification();
386            
387            IComponent comp1 = newMock(IComponent.class);
388            IComponentSpecification comp1Spec = new ComponentSpecification();
389            
390            IComponent comp2 = newMock(IComponent.class);
391            IComponentSpecification comp2Spec = new ComponentSpecification();
392            
393            IForm form = newMock(IForm.class);
394            IComponentSpecification formSpec = new ComponentSpecification();
395            
396            // now test render
397            spec.addEventListener("comp1", new String[] {"onclick"}, "testMethod", "form1", false, true, false, false);
398            invoker.addEventListener("comp1", spec);
399            invoker.addFormEventListener("form1", spec);
400            
401            spec.addEventListener("comp2", new String[] {"ondoubleclick"}, "clickMethod", "form1", false, true, false, false);
402            invoker.addEventListener("comp2", spec);
403            invoker.addFormEventListener("form1", spec);
404            
405            expect(cycle.isRewinding()).andReturn(false);
406            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(prs);
407            expect(cycle.getAttribute(TapestryUtils.FIELD_PRERENDER)).andReturn(null);
408            
409            expect(component.getExtendedId()).andReturn("compListener").anyTimes();
410            expect(component.getClientId()).andReturn("compListener").anyTimes();
411            expect(component.getSpecification()).andReturn(spec);
412            
413            // comp1 render
414            
415            expect(cycle.isRewinding()).andReturn(false);
416            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(prs);
417            expect(cycle.getAttribute(TapestryUtils.FIELD_PRERENDER)).andReturn(null);
418            
419            expect(comp1.getExtendedId()).andReturn("comp1").anyTimes();
420            expect(comp1.getClientId()).andReturn("comp1").anyTimes();
421            
422            expect(cycle.getAttribute(ComponentEventConnectionWorker.FORM_NAME_LIST + "form1")).andReturn(null);
423            expect(comp1.getSpecification()).andReturn(comp1Spec).anyTimes();
424            
425            // comp2 render
426            
427            expect(cycle.isRewinding()).andReturn(false);
428            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(prs);
429            expect(cycle.getAttribute(TapestryUtils.FIELD_PRERENDER)).andReturn(null);
430            
431            expect(comp2.getExtendedId()).andReturn("comp2").anyTimes();
432            expect(comp2.getClientId()).andReturn("comp2").anyTimes();
433            
434            expect(cycle.getAttribute(ComponentEventConnectionWorker.FORM_NAME_LIST + "form1")).andReturn(null);
435            
436            expect(comp2.getSpecification()).andReturn(comp2Spec).anyTimes();
437            
438            replay();
439            
440            worker.renderComponent(cycle, component);
441            worker.renderComponent(cycle, comp1);
442            worker.renderComponent(cycle, comp2);
443            
444            verify();
445            
446            assertEquals(worker.getDefferedFormConnections().size(), 1);
447            assertEquals(((List)worker.getDefferedFormConnections().get("form1")).size(), 2);
448            
449            checkOrder(form, false);
450            checkOrder(component, false);
451            checkOrder(comp1, false);
452            checkOrder(comp2, false);
453            
454            expect(cycle.isRewinding()).andReturn(false);
455            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(prs);
456            
457            expect(form.getSpecification()).andReturn(formSpec);
458            
459            expect(cycle.getAttribute(TapestryUtils.FIELD_PRERENDER)).andReturn(null);
460            
461            expect(form.getExtendedId()).andReturn("form1").anyTimes();
462            
463            expect(cycle.getAttribute(ComponentEventConnectionWorker.FORM_NAME_LIST + "form1")).andReturn(null);
464            cycle.setAttribute(eq(ComponentEventConnectionWorker.FORM_NAME_LIST + "form1"), isA(List.class));
465            
466            expect(form.getName()).andReturn("form1_0").anyTimes();
467    
468            expect(comp1.getSpecification()).andReturn(comp1Spec);
469            expect(comp1.getExtendedId()).andReturn("comp1").anyTimes();
470            
471            expect(comp2.getSpecification()).andReturn(comp2Spec);
472            expect(comp2.getExtendedId()).andReturn("comp2").anyTimes();
473            
474            List formNames = new ArrayList();
475            formNames.add("form1_0");
476            
477            expect(cycle.getAttribute(ComponentEventConnectionWorker.FORM_NAME_LIST + "form1")).andReturn(formNames).anyTimes();
478            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(prs).anyTimes();
479            
480            expect(scriptSource.getScript(compScriptResource)).andReturn(script);
481            script.execute(eq(form), eq(cycle), eq(prs), isA(Map.class));
482            
483            expect(scriptSource.getScript(compScriptResource)).andReturn(script);
484            script.execute(eq(form), eq(cycle), eq(prs), isA(Map.class));
485            
486            replay();
487            
488            worker.renderComponent(cycle, form);
489            
490            verify();
491        }
492        
493        
494        public void test_Script_Resource()
495        {   
496            ClassResolver resolver = new DefaultClassResolver();
497            IComponentEventInvoker invoker = new org.apache.tapestry.internal.event.impl.ComponentEventInvoker();
498            
499            String compScript = "/org/apache/tapestry/ComponentEvent.script";
500            String widScript = "/org/apache/tapestry/dojo/html/WidgetEvent.script";
501            String elementScript = "/org/apache/tapestry/html/ElementEvent.script";
502            
503            ComponentEventConnectionWorker worker = new ComponentEventConnectionWorker();
504            worker.setClassResolver(resolver);
505            worker.setEventInvoker(invoker);
506            worker.setComponentScript(compScript);
507            worker.setWidgetScript(widScript);
508            worker.setElementScript(elementScript);
509            
510            IDirectEvent component = newMock(IDirectEvent.class);
511            IWidget widget = newMock(IWidget.class);
512            
513            MockControl bodyControl = MockClassControl.createControl(Body.class);
514            Body body = (Body) bodyControl.getMock();
515            
516            assertNotNull(worker.getScript(component));
517            assertEquals(compScript, worker.getScript(component).getPath());
518            
519            assertNotNull(worker.getScript(widget));
520            assertEquals(widScript, worker.getScript(widget).getPath());
521            
522            assertNotNull(worker.getScript(body));
523            assertEquals(compScript, worker.getScript(body).getPath());
524            
525            replay();
526            
527            verify();
528        }
529        
530        public void test_Prerendered_Field()
531        {   
532            ClassResolver resolver = new DefaultClassResolver();
533            
534            IComponentEventInvoker invoker = new org.apache.tapestry.internal.event.impl.ComponentEventInvoker();
535            IEngineService engine = newMock(IEngineService.class);
536            IRequestCycle cycle = newCycle();
537            checkOrder(cycle, false);
538            
539            PageRenderSupport prs = newPageRenderSupport();
540            
541            IScriptSource scriptSource = newMock(IScriptSource.class);
542            
543            ComponentEventConnectionWorker worker = new ComponentEventConnectionWorker();
544            worker.setClassResolver(resolver);
545            worker.setEventInvoker(invoker);
546            worker.setEventEngine(engine);
547            worker.setScriptSource(scriptSource);
548            
549            IDirectEvent component = newMock(IDirectEvent.class);
550            IComponentSpecification spec = new ComponentSpecification();
551            
552            // now test render
553            invoker.addEventListener("comp1", spec);
554            spec.addEventListener("comp1", new String[] {"onclick"}, "testMethod", "form1", false, false, false, false);
555            
556            expect(cycle.isRewinding()).andReturn(false);
557            
558            expect(cycle.getAttribute(TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE)).andReturn(prs);
559            
560            expect(cycle.getAttribute(TapestryUtils.FIELD_PRERENDER)).andReturn(component);
561            
562            replay();
563            
564            worker.renderComponent(cycle, component);
565            
566            verify();
567        }
568    }