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 }