001: // Copyright 2006, 2007 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:
015: package org.apache.tapestry.internal.structure;
016:
017: import org.apache.tapestry.Binding;
018: import org.apache.tapestry.Block;
019: import org.apache.tapestry.BlockNotFoundException;
020: import org.apache.tapestry.ComponentResources;
021: import org.apache.tapestry.internal.InternalComponentResources;
022: import org.apache.tapestry.internal.services.Instantiator;
023: import org.apache.tapestry.internal.test.InternalBaseTestCase;
024: import org.apache.tapestry.ioc.Location;
025: import org.apache.tapestry.ioc.internal.util.TapestryException;
026: import org.apache.tapestry.ioc.services.TypeCoercer;
027: import org.apache.tapestry.model.ComponentModel;
028: import org.apache.tapestry.model.ParameterModel;
029: import org.apache.tapestry.runtime.Component;
030: import org.easymock.EasyMock;
031: import org.testng.annotations.Test;
032:
033: public class ComponentPageElementImplTest extends InternalBaseTestCase {
034: public static final String PAGE_NAME = "Foo";
035:
036: private Page newPage(String pageName) {
037: Page page = mockPage();
038:
039: train_getLogicalName(page, pageName);
040:
041: return page;
042: }
043:
044: @Test
045: public void block_not_found() {
046: Page page = newPage(PAGE_NAME);
047: Component component = mockComponent();
048: ComponentModel model = mockComponentModel();
049: TypeCoercer coercer = mockTypeCoercer();
050:
051: Instantiator ins = newInstantiator(component, model);
052:
053: replay();
054:
055: ComponentPageElement cpe = new ComponentPageElementImpl(page,
056: ins, coercer, null);
057:
058: ComponentResources resources = cpe.getComponentResources();
059:
060: try {
061: resources.getBlock("notFound");
062: unreachable();
063: } catch (BlockNotFoundException ex) {
064: assertTrue(ex
065: .getMessage()
066: .contains(
067: "does not contain a block with identifier 'notFound'."));
068: }
069:
070: verify();
071: }
072:
073: @Test
074: public void block_found() {
075: Page page = newPage(PAGE_NAME);
076: Component component = mockComponent();
077: ComponentModel model = mockComponentModel();
078: TypeCoercer coercer = mockTypeCoercer();
079: Block block = mockBlock();
080:
081: Instantiator ins = newInstantiator(component, model);
082:
083: replay();
084:
085: ComponentPageElement cpe = new ComponentPageElementImpl(page,
086: ins, coercer, null);
087:
088: ComponentResources resources = cpe.getComponentResources();
089:
090: cpe.addBlock("known", block);
091:
092: assertSame(resources.getBlock("known"), block);
093: // Caseless check
094: assertSame(resources.getBlock("KNOWN"), block);
095:
096: verify();
097: }
098:
099: @Test
100: public void parameter_is_bound() {
101: Page page = newPage(PAGE_NAME);
102: Component component = mockComponent();
103: ComponentModel model = mockComponentModel();
104: Binding binding = mockBinding();
105: TypeCoercer coercer = mockTypeCoercer();
106:
107: Instantiator ins = newInstantiator(component, model);
108:
109: train_getParameterModel(model, "barney", null);
110:
111: train_getSupportsInformalParameters(model, true);
112:
113: replay();
114:
115: ComponentPageElement cpe = new ComponentPageElementImpl(page,
116: ins, coercer, null);
117:
118: ComponentResources resources = cpe.getComponentResources();
119: assertFalse(resources.isBound("fred"));
120:
121: cpe.bindParameter("barney", binding);
122:
123: assertFalse(resources.isBound("fred"));
124: assertTrue(resources.isBound("barney"));
125:
126: verify();
127: }
128:
129: @Test
130: public void duplicate_block_id() {
131: Page page = newPage(PAGE_NAME);
132: Component component = mockComponent();
133: ComponentModel model = mockComponentModel();
134: TypeCoercer coercer = mockTypeCoercer();
135: Block block1 = mockBlock();
136: Block block2 = mockBlock();
137:
138: Instantiator ins = newInstantiator(component, model);
139:
140: replay();
141:
142: ComponentPageElement cpe = new ComponentPageElementImpl(page,
143: ins, coercer, null);
144:
145: cpe.addBlock("myblock", block1);
146:
147: try {
148: cpe.addBlock("MyBlock", block2);
149: unreachable();
150: } catch (TapestryException ex) {
151: assertEquals(
152: ex.getMessage(),
153: "Component Foo already contains a block with id \'MyBlock\'. Block ids must be unique (excluding case, which is ignored).");
154: }
155:
156: verify();
157: }
158:
159: @Test
160: public void verify_required_parameters_all_are_bound() {
161: Page page = newPage(PAGE_NAME);
162: Component component = mockComponent();
163: ComponentModel model = mockComponentModel();
164: Binding binding = mockBinding();
165: TypeCoercer coercer = mockTypeCoercer();
166: ParameterModel pmodel = mockParameterModel();
167:
168: Instantiator ins = newInstantiator(component, model);
169:
170: train_getParameterNames(model, "barney");
171: train_getParameterModel(model, "barney", pmodel);
172:
173: component.containingPageDidLoad();
174:
175: replay();
176:
177: ComponentPageElementImpl cpe = new ComponentPageElementImpl(
178: page, ins, coercer, null);
179:
180: cpe.bindParameter("barney", binding);
181:
182: cpe.containingPageDidLoad();
183:
184: verify();
185: }
186:
187: @Test
188: public void verify_required_parameters_unbound_but_not_required() {
189: Page page = newPage(PAGE_NAME);
190: Component component = mockComponent();
191: ComponentModel model = mockComponentModel();
192: ParameterModel pmodel = mockParameterModel();
193: TypeCoercer coercer = mockTypeCoercer();
194:
195: Instantiator ins = newInstantiator(component, model);
196:
197: train_getParameterNames(model, "barney");
198: train_getParameterModel(model, "barney", pmodel);
199: train_isRequired(pmodel, false);
200:
201: component.containingPageDidLoad();
202:
203: replay();
204:
205: ComponentPageElementImpl cpe = new ComponentPageElementImpl(
206: page, ins, coercer, null);
207:
208: cpe.containingPageDidLoad();
209:
210: verify();
211: }
212:
213: @Test
214: public void verify_required_parameters_unbound_and_required() {
215: Page page = mockPage();
216: ComponentPageElement container = mockComponentPageElement();
217: InternalComponentResources containerResources = mockInternalComponentResources();
218: Component component = mockComponent();
219: ComponentModel model = mockComponentModel();
220: ParameterModel pmodel = mockParameterModel();
221: Location l = mockLocation();
222: TypeCoercer coercer = mockTypeCoercer();
223:
224: Instantiator ins = newInstantiator(component, model);
225:
226: train_getComponentResources(container, containerResources);
227:
228: train_getNestedId(container, null);
229: train_getLogicalName(page, "MyPage");
230:
231: train_getParameterNames(model, "wilma", "barney", "fred");
232: train_getParameterModel(model, "wilma", pmodel);
233: train_isRequired(pmodel, true);
234:
235: train_getParameterModel(model, "barney", pmodel);
236: train_isRequired(pmodel, false);
237:
238: train_getParameterModel(model, "fred", pmodel);
239: train_isRequired(pmodel, true);
240:
241: // Now called *before* the check for unbound parametesr
242:
243: component.containingPageDidLoad();
244:
245: train_getComponentClassName(model, "foo.components.MyComponent");
246:
247: replay();
248:
249: ComponentPageElementImpl cpe = new ComponentPageElementImpl(
250: page, container, "myid", null, ins, coercer, null, l);
251:
252: try {
253: cpe.containingPageDidLoad();
254: } catch (TapestryException ex) {
255: assertEquals(
256: ex.getMessage(),
257: "Parameter(s) fred, wilma are required for foo.components.MyComponent, but have not been bound.");
258: assertSame(ex.getLocation(), l);
259: }
260:
261: verify();
262: }
263:
264: @Test
265: public void is_invariant() {
266: Page page = newPage(PAGE_NAME);
267: Component component = mockComponent();
268: ComponentModel model = mockComponentModel();
269: Binding binding = mockBinding();
270: TypeCoercer coercer = mockTypeCoercer();
271: ParameterModel pmodel = mockParameterModel();
272:
273: Instantiator ins = newInstantiator(component, model);
274:
275: train_getParameterModel(model, "barney", pmodel);
276:
277: train_isInvariant(binding, true);
278:
279: replay();
280:
281: ComponentPageElement cpe = new ComponentPageElementImpl(page,
282: ins, coercer, null);
283:
284: assertFalse(cpe.getComponentResources().isInvariant("fred"));
285:
286: cpe.bindParameter("barney", binding);
287:
288: assertFalse(cpe.getComponentResources().isInvariant("fred"));
289: assertTrue(cpe.getComponentResources().isInvariant("barney"));
290:
291: verify();
292: }
293:
294: @Test
295: public void read_binding() {
296: Page page = newPage(PAGE_NAME);
297: Component component = mockComponent();
298: ComponentModel model = mockComponentModel();
299: TypeCoercer coercer = mockTypeCoercer();
300: Binding binding = mockBinding();
301:
302: train_getSupportsInformalParameters(model, true);
303:
304: Long boundValue = new Long(23);
305:
306: Instantiator ins = newInstantiator(component, model);
307:
308: train_getParameterModel(model, "barney", null);
309:
310: train_get(binding, boundValue);
311:
312: train_coerce(coercer, boundValue, Long.class, boundValue);
313:
314: replay();
315:
316: ComponentPageElement cpe = new ComponentPageElementImpl(page,
317: ins, coercer, null);
318:
319: cpe.bindParameter("barney", binding);
320:
321: assertSame(cpe.getComponentResources().readParameter("barney",
322: Long.class), boundValue);
323:
324: verify();
325: }
326:
327: @Test
328: public void write_binding() {
329: Page page = newPage(PAGE_NAME);
330: Component component = mockComponent();
331: ComponentModel model = mockComponentModel();
332: TypeCoercer coercer = mockTypeCoercer();
333: Binding binding = mockBinding();
334:
335: Instantiator ins = newInstantiator(component, model);
336:
337: train_getParameterModel(model, "barney", null);
338:
339: train_getSupportsInformalParameters(model, true);
340:
341: expect(binding.getBindingType()).andReturn(Integer.class);
342:
343: train_coerce(coercer, 23, Integer.class, 23);
344:
345: binding.set(23);
346:
347: replay();
348:
349: ComponentPageElement cpe = new ComponentPageElementImpl(page,
350: ins, coercer, null);
351:
352: cpe.bindParameter("barney", binding);
353:
354: cpe.getComponentResources().writeParameter("barney", 23);
355:
356: verify();
357: }
358:
359: @Test
360: public void get_embedded_does_not_exist() {
361: Page page = newPage(PAGE_NAME);
362: Component component = mockComponent();
363: ComponentModel model = mockComponentModel();
364: TypeCoercer coercer = mockTypeCoercer();
365:
366: Instantiator ins = newInstantiator(component, model);
367:
368: replay();
369:
370: ComponentPageElement cpe = new ComponentPageElementImpl(page,
371: ins, coercer, null);
372:
373: try {
374: cpe.getEmbeddedElement("unknown");
375: unreachable();
376: } catch (TapestryException ex) {
377: assertEquals(
378: ex.getMessage(),
379: "Component "
380: + PAGE_NAME
381: + " does not contain an embedded component with id 'unknown'.");
382: }
383:
384: verify();
385: }
386:
387: @Test
388: public void get_existing_embedded_component() {
389: Page page = newPage(PAGE_NAME);
390: Component component = mockComponent();
391: ComponentModel model = mockComponentModel();
392: ComponentPageElement childElement = mockComponentPageElement();
393: Component childComponent = mockComponent();
394: TypeCoercer coercer = mockTypeCoercer();
395:
396: Instantiator ins = newInstantiator(component, model);
397:
398: train_getId(childElement, "child");
399: train_getComponent(childElement, childComponent);
400:
401: replay();
402:
403: ComponentPageElement cpe = new ComponentPageElementImpl(page,
404: ins, coercer, null);
405:
406: cpe.addEmbeddedElement(childElement);
407:
408: assertSame(cpe.getComponentResources().getEmbeddedComponent(
409: "child"), childComponent);
410:
411: // Now check that the search is caseless.
412:
413: assertSame(cpe.getComponentResources().getEmbeddedComponent(
414: "CHILD"), childComponent);
415:
416: verify();
417: }
418:
419: @Test
420: public void component_ids_must_be_unique_within_container() {
421: Page page = newPage(PAGE_NAME);
422: Component pageComponent = mockComponent();
423: ComponentModel model = mockComponentModel();
424: ComponentPageElement child1 = mockComponentPageElement();
425: ComponentPageElement child2 = mockComponentPageElement();
426: TypeCoercer coercer = mockTypeCoercer();
427: Location l = mockLocation();
428:
429: Instantiator ins = newInstantiator(pageComponent, model);
430:
431: train_getId(child1, "Child");
432: train_getId(child2, "CHILD");
433:
434: train_getLocation(child2, l);
435:
436: replay();
437:
438: ComponentPageElement cpe = new ComponentPageElementImpl(page,
439: ins, coercer, null);
440:
441: cpe.addEmbeddedElement(child1);
442:
443: try {
444: cpe.addEmbeddedElement(child2);
445: unreachable();
446: } catch (TapestryException ex) {
447: assertTrue(ex
448: .getMessage()
449: .contains(
450: "already contains a child component with id 'CHILD'."));
451: assertSame(ex.getLocation(), l);
452: }
453:
454: verify();
455: }
456:
457: @Test
458: public void get_mixin_by_class_name() {
459: Page page = newPage(PAGE_NAME);
460: Component component = mockComponent();
461: ComponentModel model = mockComponentModel();
462: TypeCoercer coercer = mockTypeCoercer();
463: final String mixinClassName = "foo.Bar";
464: Component mixin = mockComponent();
465: ComponentModel mixinModel = mockComponentModel();
466:
467: Instantiator ins = newInstantiator(component, model);
468: Instantiator mixinIns = newInstantiator(mixin, mixinModel);
469:
470: train_getComponentClassName(mixinModel, mixinClassName);
471:
472: replay();
473:
474: ComponentPageElement cpe = new ComponentPageElementImpl(page,
475: ins, coercer, null);
476:
477: cpe.addMixin(mixinIns);
478:
479: assertSame(cpe.getMixinByClassName(mixinClassName), mixin);
480:
481: verify();
482: }
483:
484: @Test
485: public void get_mixin_by_unknown_class_name() {
486: Page page = newPage(PAGE_NAME);
487: Component component = mockComponent();
488: ComponentModel model = mockComponentModel();
489: TypeCoercer coercer = mockTypeCoercer();
490: Component mixin = mockComponent();
491: ComponentModel mixinModel = mockComponentModel();
492:
493: Instantiator ins = newInstantiator(component, model);
494: Instantiator mixinIns = newInstantiator(mixin, mixinModel);
495:
496: train_getComponentClassName(mixinModel, "foo.Bar");
497:
498: replay();
499:
500: ComponentPageElement cpe = new ComponentPageElementImpl(page,
501: ins, coercer, null);
502:
503: cpe.addMixin(mixinIns);
504:
505: try {
506: cpe.getMixinByClassName("foo.Baz");
507: unreachable();
508: } catch (TapestryException ex) {
509: assertTrue(ex.getMessage().endsWith(
510: " does not contain a mixin of type foo.Baz."));
511: }
512:
513: verify();
514:
515: }
516:
517: @Test
518: public void set_explicit_parameter_of_unknown_mixin() {
519: Page page = newPage(PAGE_NAME);
520: Component component = mockComponent();
521: ComponentModel model = mockComponentModel();
522: ComponentModel mixinModel = mockComponentModel();
523: Component mixin = mockComponent();
524: TypeCoercer coercer = mockTypeCoercer();
525: Binding binding = mockBinding();
526:
527: Instantiator ins = newInstantiator(component, model);
528: Instantiator mixinInstantiator = newInstantiator(mixin,
529: mixinModel);
530:
531: train_getComponentClassName(mixinModel, "foo.Fred");
532:
533: replay();
534:
535: ComponentPageElement cpe = new ComponentPageElementImpl(page,
536: ins, coercer, null);
537:
538: cpe.addMixin(mixinInstantiator);
539:
540: try {
541: cpe.bindParameter("Wilma.barney", binding);
542: unreachable();
543: } catch (TapestryException ex) {
544: assertTrue(ex
545: .getMessage()
546: .contains(
547: "does not contain a mixin named 'Wilma' (setting parameter 'Wilma.barney')"));
548: }
549:
550: verify();
551: }
552:
553: private Instantiator newInstantiator(Component component,
554: ComponentModel model) {
555: Instantiator ins = newMock(Instantiator.class);
556:
557: expect(ins.getModel()).andReturn(model).anyTimes();
558:
559: expect(
560: ins.newInstance(EasyMock
561: .isA(InternalComponentResources.class)))
562: .andReturn(component);
563:
564: return ins;
565: }
566: }
|