001 package org.apache.tapestry;
002
003 import org.apache.commons.logging.Log;
004 import org.apache.hivemind.*;
005 import org.apache.hivemind.impl.DefaultClassResolver;
006 import org.apache.hivemind.impl.RegistryBuilder;
007 import org.apache.hivemind.impl.XmlModuleDescriptorProvider;
008 import org.apache.hivemind.util.URLResource;
009 import org.apache.tapestry.components.ILinkComponent;
010 import org.apache.tapestry.engine.IEngineService;
011 import org.apache.tapestry.engine.ILink;
012 import org.apache.tapestry.engine.NullWriter;
013 import org.apache.tapestry.event.BrowserEvent;
014 import org.apache.tapestry.json.IJSONWriter;
015 import org.apache.tapestry.markup.AsciiMarkupFilter;
016 import org.apache.tapestry.markup.JSONWriterImpl;
017 import org.apache.tapestry.markup.MarkupWriterImpl;
018 import org.apache.tapestry.services.ResponseBuilder;
019 import org.apache.tapestry.services.impl.DefaultResponseBuilder;
020 import org.apache.tapestry.spec.IComponentSpecification;
021 import org.apache.tapestry.spec.IParameterSpecification;
022 import org.apache.tapestry.test.Creator;
023 import org.apache.tapestry.web.WebRequest;
024 import static org.easymock.EasyMock.*;
025
026 import java.io.CharArrayWriter;
027 import java.io.PrintWriter;
028 import java.net.URL;
029 import java.util.ArrayList;
030 import java.util.Arrays;
031 import java.util.List;
032 import java.util.Locale;
033
034 /**
035 * Base class for testing components, or testing classes that operate on components. Simplifies
036 * creating much of the infrastructure around the components.
037 *
038 */
039 public class BaseComponentTestCase extends TestBase
040 {
041 private Creator _creator;
042
043 protected Creator getCreator()
044 {
045 if (_creator == null)
046 _creator = new Creator();
047
048 return _creator;
049 }
050
051 protected ClassResolver getClassResolver()
052 {
053 return new DefaultClassResolver();
054 }
055
056 protected CharArrayWriter _charArrayWriter;
057
058 protected IMarkupWriter newBufferWriter()
059 {
060 _charArrayWriter = new CharArrayWriter();
061 PrintWriter pw = new PrintWriter(_charArrayWriter);
062
063 return new MarkupWriterImpl("text/html", pw, new AsciiMarkupFilter());
064 }
065
066 protected IJSONWriter newBufferJSONWriter()
067 {
068 _charArrayWriter = new CharArrayWriter();
069 PrintWriter pw = new PrintWriter(_charArrayWriter);
070
071 return new JSONWriterImpl(pw);
072 }
073
074 protected void assertBuffer(String expected)
075 {
076 String actual = _charArrayWriter.toString();
077
078 assertEquals(actual, expected);
079
080 _charArrayWriter.reset();
081 }
082
083 protected void assertExceptionSubstring(Throwable t, String msg)
084 {
085 assertTrue(t.getMessage().contains(msg));
086 }
087
088 protected Object newInstance(Class componentClass)
089 {
090 return newInstance(componentClass, null);
091 }
092
093 protected Object newInstance(Class componentClass, String propertyName, Object propertyValue)
094 {
095 return getCreator().newInstance(componentClass, new Object[]
096 { propertyName, propertyValue });
097 }
098
099 protected IRequestCycle newCycle()
100 {
101 return newMock(IRequestCycle.class);
102 }
103
104 protected IRequestCycle newCycle(IMarkupWriter writer)
105 {
106 IRequestCycle cycle = newMock(IRequestCycle.class);
107
108 trainResponseBuilder(cycle, writer);
109
110 return cycle;
111 }
112
113 protected IRequestCycle newCycle(boolean rewinding)
114 {
115 return newCycle(rewinding, null);
116 }
117
118 protected IRequestCycle newCycle(boolean rewinding, boolean trainWriter)
119 {
120 IRequestCycle cycle = newRequestCycle();
121
122 trainIsRewinding(cycle, rewinding);
123
124 if (trainWriter)
125 trainResponseBuilder(cycle, null);
126
127 return cycle;
128 }
129
130 protected IRequestCycle newCycle(boolean rewinding, IMarkupWriter writer)
131 {
132 IRequestCycle cycle = newRequestCycle();
133 checkOrder(cycle, false);
134
135 trainIsRewinding(cycle, rewinding);
136
137 if (writer != null)
138 trainResponseBuilder(cycle, writer);
139
140 return cycle;
141 }
142
143 protected void trainResponseBuilder(IRequestCycle cycle, IMarkupWriter writer)
144 {
145 ResponseBuilder builder =
146 new DefaultResponseBuilder(writer == null ? NullWriter.getSharedInstance() : writer);
147
148 expect(cycle.getResponseBuilder()).andReturn(builder);
149 }
150
151 protected void trainIsRewinding(IRequestCycle cycle, boolean rewinding)
152 {
153 expect(cycle.isRewinding()).andReturn(rewinding);
154 }
155
156 protected IRequestCycle newCycleGetPage(String pageName, IPage page)
157 {
158 IRequestCycle cycle = newRequestCycle();
159
160 expect(cycle.getPage(pageName)).andReturn(page);
161
162 return cycle;
163 }
164
165 protected IRequestCycle newCycleGetUniqueId(String id, String uniqueId)
166 {
167 IRequestCycle cycle = newRequestCycle();
168
169 expect(cycle.getUniqueId(id)).andReturn(uniqueId);
170 return cycle;
171 }
172
173 protected IRequestCycle newCycleGetParameter(String name, String value)
174 {
175 IRequestCycle cycle = newRequestCycle();
176
177 expect(cycle.getParameter(name)).andReturn(value);
178 return cycle;
179 }
180
181 protected IMarkupWriter newWriter()
182 {
183 return newMock(IMarkupWriter.class);
184 }
185
186 protected IBinding newBinding(Object value)
187 {
188 IBinding binding = newMock(IBinding.class);
189 checkOrder(binding, false);
190
191 expect(binding.getObject()).andReturn(value);
192 return binding;
193 }
194
195 protected IBinding newBinding(Location location)
196 {
197 IBinding binding = newBinding();
198 checkOrder(binding, false);
199
200 trainGetLocation(binding, location);
201
202 return binding;
203 }
204
205 protected IComponent newComponent(String extendedId, Location location)
206 {
207 IComponent component = newMock(IComponent.class);
208 checkOrder(component, false);
209
210 expect(component.getExtendedId()).andReturn(extendedId);
211 expect(component.getLocation()).andReturn(location);
212 return component;
213 }
214
215 protected IComponentSpecification newSpec(String parameterName, IParameterSpecification pspec)
216 {
217 IComponentSpecification spec = newMock(IComponentSpecification.class);
218
219 expect(spec.getParameter(parameterName)).andReturn(pspec);
220 return spec;
221 }
222
223 protected IRender newRender()
224 {
225 return newMock(IRender.class);
226 }
227
228 protected IPage newPage()
229 {
230 return newMock(IPage.class);
231 }
232
233 protected IPage newPage(String name)
234 {
235 return newPage(name, 1);
236 }
237
238 protected IPage newPage(String name, int count)
239 {
240 IPage page = newMock(IPage.class);
241 checkOrder(page, false);
242
243 expect(page.getPageName()).andReturn(name).times(count);
244
245 return page;
246 }
247
248 protected IForm newForm()
249 {
250 return newMock(IForm.class);
251 }
252
253 protected IRender newBody()
254 {
255 return new IRender()
256 {
257 public void render(IMarkupWriter writer, IRequestCycle cycle)
258 {
259 writer.print("BODY");
260 }
261 };
262 }
263
264 protected PageRenderSupport newPageRenderSupport()
265 {
266 return newMock(PageRenderSupport.class);
267 }
268
269 protected void trainGetSupport(IRequestCycle cycle, PageRenderSupport support)
270 {
271 trainGetAttribute(cycle, TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE, support);
272 }
273
274 protected void trainGetAttribute(IRequestCycle cycle, String attributeName, Object attribute)
275 {
276 expect(cycle.getAttribute(attributeName)).andReturn(attribute);
277 }
278
279 protected void trainGetUniqueId(IRequestCycle cycle, String id, String uniqueId)
280 {
281 expect(cycle.getUniqueId(id)).andReturn(uniqueId);
282 }
283
284 protected void trainGetIdPath(IComponent component, String idPath)
285 {
286 expect(component.getIdPath()).andReturn(idPath);
287 }
288
289 protected void trainGetParameter(IRequestCycle cycle, String name, String value)
290 {
291 expect(cycle.getParameter(name)).andReturn(value);
292 }
293
294 protected void trainGetPageName(IPage page, String pageName)
295 {
296 expect(page.getPageName()).andReturn(pageName);
297 }
298
299 protected void trainBuildURL(IAsset asset, IRequestCycle cycle, String URL)
300 {
301 expect(asset.buildURL()).andReturn(URL);
302 }
303
304 protected IAsset newAsset()
305 {
306 return newMock(IAsset.class);
307 }
308
309 protected IEngine newEngine(ClassResolver resolver)
310 {
311 return newMock(IEngine.class);
312 }
313
314 protected void trainGetEngine(IPage page, IEngine engine)
315 {
316 expect(page.getEngine()).andReturn(engine);
317 }
318
319 protected IComponent newComponent()
320 {
321 return newMock(IComponent.class);
322 }
323
324 protected void trainGetPage(IComponent component, IPage page)
325 {
326 expect(component.getPage()).andReturn(page);
327 }
328
329 protected void trainGetExtendedId(IComponent component, String extendedId)
330 {
331 expect(component.getExtendedId()).andReturn(extendedId);
332 }
333
334 protected void trainGetLocation(Locatable locatable, Location location)
335 {
336 expect(locatable.getLocation()).andReturn(location);
337 }
338
339 protected IBinding newBinding()
340 {
341 return newMock(IBinding.class);
342 }
343
344 protected void trainGetComponent(IComponent container, String componentId, IComponent containee)
345 {
346 expect(container.getComponent(componentId)).andReturn(containee);
347 }
348
349 protected IEngineService newEngineService()
350 {
351 return newMock(IEngineService.class);
352 }
353
354 protected void trainGetLink(IEngineService service, IRequestCycle cycle, boolean post,
355 Object parameter, ILink link)
356 {
357 expect(service.getLink(post, parameter)).andReturn(link);
358 }
359
360 protected void trainGetLinkCheckIgnoreParameter(IEngineService service, IRequestCycle cycle,
361 boolean post, Object parameter, ILink link)
362 {
363 expect(service.getLink(eq(post), anyObject())).andReturn(link);
364 }
365
366 protected void trainGetURL(ILink link, String URL)
367 {
368 expect(link.getURL()).andReturn(URL);
369 }
370
371 protected void trainGetPageRenderSupport(IRequestCycle cycle, PageRenderSupport support)
372 {
373 trainGetAttribute(cycle, TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE, support);
374 }
375
376 protected IComponentSpecification newSpec()
377 {
378 return newMock(IComponentSpecification.class);
379 }
380
381 protected Resource newResource()
382 {
383 return newMock(Resource.class);
384 }
385
386 protected WebRequest newRequest()
387 {
388 return newMock(WebRequest.class);
389 }
390
391 protected Location newLocation()
392 {
393 return newMock(Location.class);
394 }
395
396 protected Location fabricateLocation(int line)
397 {
398 Location location = newLocation();
399 checkOrder(location, false);
400
401 expect(location.getLineNumber()).andReturn(line).anyTimes();
402
403 return location;
404 }
405
406 protected void trainEncodeURL(IRequestCycle rc, String URL, String encodedURL)
407 {
408 expect(rc.encodeURL(URL)).andReturn(encodedURL);
409 }
410
411 protected void trainGetServerPort(WebRequest request, int port)
412 {
413 expect(request.getServerPort()).andReturn(port);
414 }
415
416 protected void trainGetServerName(WebRequest request, String serverName)
417 {
418 expect(request.getServerName()).andReturn(serverName);
419 }
420
421 protected void trainGetScheme(WebRequest request, String scheme)
422 {
423 expect(request.getScheme()).andReturn(scheme);
424 }
425
426 protected NestedMarkupWriter newNestedWriter()
427 {
428 return newMock(NestedMarkupWriter.class);
429 }
430
431 protected void trainGetNestedWriter(IMarkupWriter writer, NestedMarkupWriter nested)
432 {
433 expect(writer.getNestedWriter()).andReturn(nested);
434 }
435
436 protected void trainGetURL(ILink link, String scheme, String anchor, String URL)
437 {
438 trainGetURL(link, scheme, anchor, URL, 0);
439 }
440
441 protected void trainGetURL(ILink link, String scheme, String anchor, String URL, int port)
442 {
443 expect(link.getURL(scheme, null, port, anchor, true)).andReturn(URL);
444 }
445
446 protected ILink newLink()
447 {
448 return newMock(ILink.class);
449 }
450
451 protected void trainGetLink(ILinkComponent component, IRequestCycle cycle, ILink link)
452 {
453 expect(component.getLink(cycle)).andReturn(link);
454 }
455
456 protected void trainGetEngine(IRequestCycle cycle, IEngine engine)
457 {
458 expect(cycle.getEngine()).andReturn(engine);
459 }
460
461 protected void trainGetParameterValues(ILink link, String parameterName, String[] values)
462 {
463 expect(link.getParameterValues(parameterName)).andReturn(values);
464 }
465
466 protected void trainGetParameterNames(ILink link, String[] names)
467 {
468 expect(link.getParameterNames()).andReturn(names);
469 }
470
471 protected void trainGetSpecification(IComponent component, IComponentSpecification spec)
472 {
473 expect(component.getSpecification()).andReturn(spec);
474 }
475
476 protected void trainGetBinding(IComponent component, String name, IBinding binding)
477 {
478 expect(component.getBinding(name)).andReturn(binding);
479 }
480
481 protected Log newLog()
482 {
483 return newMock(Log.class);
484 }
485
486 protected void trainGetId(IComponent component, String id)
487 {
488 expect(component.getId()).andReturn(id);
489 }
490
491 protected void trainExtractBrowserEvent(IRequestCycle cycle)
492 {
493 expect(cycle.getParameter(BrowserEvent.NAME)).andReturn("onClick").anyTimes();
494
495 expect(cycle.getParameter(BrowserEvent.TYPE)).andReturn("click");
496 expect(cycle.getParameters(BrowserEvent.KEYS)).andReturn(null);
497 expect(cycle.getParameter(BrowserEvent.CHAR_CODE)).andReturn(null);
498 expect(cycle.getParameter(BrowserEvent.PAGE_X)).andReturn("123");
499 expect(cycle.getParameter(BrowserEvent.PAGE_Y)).andReturn("1243");
500 expect(cycle.getParameter(BrowserEvent.LAYER_X)).andReturn(null);
501 expect(cycle.getParameter(BrowserEvent.LAYER_Y)).andReturn(null);
502
503 expect(cycle.getParameter(BrowserEvent.TARGET + "." + BrowserEvent.TARGET_ATTR_ID))
504 .andReturn("element1");
505 }
506
507 /**
508 * Convienience method for invoking {@link #buildFrameworkRegistry(String[])} with only a single
509 * file.
510 *
511 * @param file
512 * The path to the hivemind xml configuration file.
513 * @return The constructed registry.
514 *
515 * @throws Exception When file can't be found or parsed.
516 */
517 protected Registry buildFrameworkRegistry(String file)
518 throws Exception
519 {
520 return buildFrameworkRegistry(new String[] { file });
521 }
522
523 /**
524 * Builds a minimal registry, containing only the specified files, plus the master module
525 * descriptor (i.e., those visible on the classpath).
526 *
527 * @param files
528 * The path to the hivemind xml configuration files to parse.
529 * @return The constructed registry.
530 *
531 * @throws Exception When file can't be found or parsed.
532 */
533 protected Registry buildFrameworkRegistry(String[] files)
534 throws Exception
535 {
536 ClassResolver resolver = getClassResolver();
537
538 List<Resource> descriptorResources = new ArrayList<Resource>();
539 for (String file : files)
540 {
541 Resource resource = getResource(file);
542
543 descriptorResources.add(resource);
544 }
545
546 ModuleDescriptorProvider provider = new XmlModuleDescriptorProvider(resolver, descriptorResources);
547
548 return buildFrameworkRegistry(provider);
549 }
550
551 /**
552 * Builds a registry, containing only the modules delivered by the specified
553 * {@link org.apache.hivemind.ModuleDescriptorProvider}, plus the master module descriptor
554 * (i.e., those visible on the classpath).
555 *
556 * @param customProvider
557 * The custom module provider that should be added to the configuration.
558 *
559 * @return A constructed {@link Registry}.
560 */
561 protected Registry buildFrameworkRegistry(ModuleDescriptorProvider customProvider)
562 {
563 ClassResolver resolver = getClassResolver();
564
565 RegistryBuilder builder = new RegistryBuilder();
566
567 builder.addModuleDescriptorProvider(new XmlModuleDescriptorProvider(resolver));
568 builder.addModuleDescriptorProvider(customProvider);
569
570 return builder.constructRegistry(Locale.getDefault());
571 }
572
573 /**
574 * Builds a registry from exactly the provided resource; this registry will not include the
575 * <code>hivemind</code> module.
576 *
577 * @param l
578 * The resource to build the registry from.
579 * @return A constructed {@link Registry} instance.
580 *
581 * @throws Exception If error building registry.
582 */
583 protected Registry buildMinimalRegistry(Resource l)
584 throws Exception
585 {
586 RegistryBuilder builder = new RegistryBuilder();
587
588 return builder.constructRegistry(Locale.getDefault());
589 }
590
591 /**
592 * Returns the given file as a {@link Resource} from the classpath. Typically, this is to find
593 * files in the same folder as the invoking class.
594 *
595 * @param file
596 * Gets a resource object for the file representing the path specified.
597 * @return A {@link Resource} object.
598 */
599 protected Resource getResource(String file)
600 {
601 URL url = getClass().getResource(file);
602
603 if (url == null)
604 throw new NullPointerException("No resource named '" + file + "'.");
605
606 return new URLResource(url);
607 }
608
609 public static boolean assertListEquals(Object[] expected, Object[] actual)
610 {
611 if (expected == null || actual == null)
612 notEquals(expected, actual);
613
614 if (!Arrays.equals(expected, actual))
615 notEquals(expected, actual);
616
617 return true;
618 }
619
620 public static boolean assertListEquals(Object[] expected, List actual)
621 {
622 if (expected == null || actual == null)
623 notEquals(expected, actual);
624
625 Object[] acarr = actual.toArray(new Object[actual.size()]);
626 return assertListEquals(expected, acarr);
627 }
628
629 public static void notEquals(Object expected, Object actual)
630 {
631 throw new AssertionError("Parameters don't match, expected: <"
632 + expected + "> actual: <" + actual + ">");
633 }
634 }