001    // Copyright 2005 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.valid;
016    
017    import org.apache.hivemind.Location;
018    import org.apache.hivemind.util.PropertyUtils;
019    import org.apache.tapestry.*;
020    import org.apache.tapestry.form.BaseFormComponentTestCase;
021    import org.apache.tapestry.form.IFormComponent;
022    import org.apache.tapestry.form.MockDelegate;
023    import org.apache.tapestry.html.BasePage;
024    import static org.easymock.EasyMock.checkOrder;
025    import static org.easymock.EasyMock.expect;
026    import org.testng.annotations.Test;
027    
028    /**
029     * Tests for {@link org.apache.tapestry.valid.ValidField}.
030     * 
031     * @author Howard M. Lewis Ship
032     * @since 4.0
033     */
034    @Test(sequential=true)
035    public class TestValidField extends BaseFormComponentTestCase
036    {
037    
038        public void testWasPrerendered()
039        {
040            IRequestCycle cycle = newCycle();
041            IForm form = newMock(IForm.class);
042    
043            IMarkupWriter writer = newWriter();
044            
045            ValidField component = (ValidField) newInstance(ValidField.class);
046            
047            expect(cycle.renderStackPush(component)).andReturn(component);
048            
049            trainGetForm(cycle, form);
050            
051            trainWasPrerendered(form, writer, component, true);
052            
053            expect(cycle.renderStackPop()).andReturn(component);
054            
055            replay();
056    
057            component.render(writer, cycle);
058    
059            verify();
060        }
061    
062        /**
063         * Check when the form is not rewinding, but the cycle is rewinding (a whole page rewind care of
064         * the action service).
065         */
066    
067        public void testFormNotRewinding()
068        {
069            ValidField component = (ValidField) newInstance(ValidField.class);
070    
071            IRequestCycle cycle = newCycle();
072            IForm form = newMock(IForm.class);
073    
074            IMarkupWriter writer = newWriter();
075            IValidationDelegate delegate = newDelegate();
076            
077            expect(cycle.renderStackPush(component)).andReturn(component);
078            
079            trainGetForm(cycle, form);
080            trainWasPrerendered(form, writer, component, false);
081            trainGetDelegate(form, delegate);
082    
083            delegate.setFormComponent(component);
084    
085            trainGetElementId(form, component, "fred");
086            trainIsRewinding(form, false);
087            trainIsRewinding(cycle, true);
088            
089            expect(cycle.renderStackPop()).andReturn(component);
090            
091            replay();
092    
093            component.render(writer, cycle);
094    
095            verify();
096        }
097    
098        private void trainToObject(IValidator validator, IFormComponent component,
099                String fieldValue, Object translatedValue) throws ValidatorException
100        {
101            expect(validator.toObject(component, fieldValue)).andReturn(translatedValue);
102        }
103    
104        public void testRewind() throws Exception
105        {
106            Object translatedValue = new Object();
107            
108            IValidator validator = newMock(IValidator.class);
109    
110            ValidField component = (ValidField) newInstance(ValidField.class, "validator", validator);
111    
112            IRequestCycle cycle = newCycle();
113            IForm form = newMock(IForm.class);
114    
115            IMarkupWriter writer = newWriter();
116    
117            IValidationDelegate delegate = newDelegate();
118            
119            expect(cycle.renderStackPush(component)).andReturn(component);
120            
121            trainGetForm(cycle, form);
122            trainWasPrerendered(form, writer, component, false);
123            trainGetDelegate(form, delegate);
124    
125            delegate.setFormComponent(component);
126    
127            trainGetElementId(form, component, "fred");
128            trainIsRewinding(form, true);
129    
130            trainGetParameter(cycle, "fred", "fred-value");
131    
132            delegate.recordFieldInputValue("fred-value");
133    
134            trainToObject(validator, component, "fred-value", translatedValue);
135            
136            expect(cycle.renderStackPop()).andReturn(component);
137            
138            replay();
139    
140            component.render(writer, cycle);
141    
142            verify();
143    
144            assertSame(translatedValue, PropertyUtils.read(component, "value"));
145        }
146    
147        public void testRewindNoValidator()
148        {   
149            IPage page = (IPage) newInstance(BasePage.class);
150            page.setPageName("Barney");
151            
152            ValidField component = newInstance(ValidField.class, new Object[]
153            { "page", page, "id", "inputFred", "container", page });
154            
155            IRequestCycle cycle = newCycle();
156            IForm form = newMock(IForm.class);
157            
158            IMarkupWriter writer = newWriter();
159            
160            IValidationDelegate delegate = newDelegate();
161            
162            expect(cycle.renderStackPush(component)).andReturn(component);
163            
164            trainGetForm(cycle, form);
165            
166            Location l = newLocation();
167            IBinding binding = newBinding(l);
168            
169            component.setBinding("validator", binding);
170            
171            trainWasPrerendered(form, writer, component, false);
172            trainGetDelegate(form, delegate);
173            
174            delegate.setFormComponent(component);
175            
176            trainGetElementId(form, component, "fred");
177            trainIsRewinding(form, true);
178            
179            trainGetParameter(cycle, "fred", "fred-value");
180    
181            expect(cycle.renderStackPop()).andReturn(component);
182            
183            replay();
184    
185            try
186            {
187                component.render(writer, cycle);
188                unreachable();
189            }
190            catch (BindingException ex)
191            {
192                assertEquals(
193                        "Value for parameter 'validator' in component Barney/inputFred is null, and a non-null value is required.",
194                        ex.getMessage());
195                assertSame(l, ex.getLocation());
196                assertSame(binding, ex.getBinding());
197            }
198    
199            verify();
200        }
201    
202        public void testRender()
203        {
204            Object value = new Object();
205            
206            IValidator validator = newMock(IValidator.class);
207    
208            ValidField component = newInstance(ValidField.class, new Object[]
209            { "value", value, "validator", validator });
210    
211            IRequestCycle cycle = newCycle();
212            IForm form = newMock(IForm.class);
213            checkOrder(form, false);
214            
215            IMarkupWriter writer = newBufferWriter();
216    
217            MockDelegate delegate = new MockDelegate();
218            
219            expect(cycle.renderStackPush(component)).andReturn(component);
220            
221            trainGetForm(cycle, form);
222            trainWasPrerendered(form, writer, component, false);
223            trainGetDelegate(form, delegate);
224    
225            trainGetElementId(form, component, "fred");
226            trainIsRewinding(form, false);
227            trainIsRewinding(cycle, false);
228    
229            form.setFormFieldUpdating(true);
230            
231            trainToString(validator, component, value, "fred value");
232    
233            expect(validator.isRequired()).andReturn(false);
234    
235            // Would be nice to have this do something so we could check the timing, but ...
236    
237            validator.renderValidatorContribution(component, writer, cycle);
238            
239            expect(cycle.renderStackPop()).andReturn(component);
240            
241            replay();
242    
243            component.render(writer, cycle);
244    
245            verify();
246    
247            assertSame(component, delegate.getFormComponent());
248            assertBuffer("<span class=\"prefix\"><input type=\"text\" name=\"fred\" " +
249                    "value=\"fred value\" id=\"fred\" class=\"validation-delegate\" /></span>");
250        }
251    
252        private void trainToString(IValidator validator,
253                IFormComponent component, Object value, String string)
254        {
255            expect(validator.toString(component, value)).andReturn(string);
256        }
257    
258        public void testRenderNull()
259        {
260            IPage page = (IPage) newInstance(BasePage.class);
261            IValidator validator = newMock(IValidator.class);
262    
263            ValidField component = newInstance(ValidField.class, new Object[]
264            { "validator", validator, "page", page, "container", page });
265            
266            IRequestCycle cycle = newCycle();
267            
268            page.attach(null, cycle);
269            
270            expect(cycle.renderStackPush(component)).andReturn(component);
271            
272            IForm form = newMock(IForm.class);
273            checkOrder(form, false);
274    
275            IMarkupWriter writer = newBufferWriter();
276    
277            MockDelegate delegate = new MockDelegate();
278    
279            trainGetForm(cycle, form);
280            trainWasPrerendered(form, writer, component, false);
281            trainGetDelegate(form, delegate);
282    
283            trainGetElementId(form, component, "fred");
284            trainIsRewinding(form, false);
285            trainIsRewinding(cycle, false);
286            
287            form.setFormFieldUpdating(true);
288            
289            trainToString(validator, component, null, null);
290    
291            expect(validator.isRequired()).andReturn(false);
292    
293            // Would be nice to have this do something so we could check the timing, but ...
294    
295            validator.renderValidatorContribution(component, writer, cycle);
296    
297            // Short cut this here, so that it appears some other field is
298            // taking the honors ...
299            
300            expect(cycle.renderStackPop()).andReturn(component);
301            
302            replay();
303    
304            component.render(writer, cycle);
305    
306            verify();
307    
308            assertSame(component, delegate.getFormComponent());
309            assertBuffer("<span class=\"prefix\"><input type=\"text\" name=\"fred\" id=\"fred\" class=\"validation-delegate\" /></span>");
310        }
311    
312        public void testRenderWithError()
313        {
314            Object value = new Object();
315            
316            IValidator validator = newMock(IValidator.class);
317            
318            IRequestCycle cycle = newCycle();
319            IForm form = newMock(IForm.class);
320            checkOrder(form, false);
321            
322            ValidField component = newInstance(ValidField.class, new Object[]
323            { "value", value, "validator", validator, "form", form, "name", "fred" });
324            
325            expect(cycle.renderStackPush(component)).andReturn(component);
326            
327            IMarkupWriter writer = newBufferWriter();
328    
329            MockDelegate delegate = new MockDelegate(true);
330            delegate.recordFieldInputValue("recorded field value");
331    
332            trainGetForm(cycle, form);
333            trainWasPrerendered(form, writer, component, false);
334            trainGetDelegate(form, delegate);
335            
336            trainGetElementId(form, component, "fred");
337            trainIsRewinding(form, false);
338            trainIsRewinding(cycle, false);
339    
340            form.setFormFieldUpdating(true);
341            
342            expect(validator.isRequired()).andReturn(true);
343    
344            // Would be nice to have this do something so we could check the timing, but ...
345    
346            validator.renderValidatorContribution(component, writer, cycle);
347            
348            expect(cycle.renderStackPop()).andReturn(component);
349            
350            replay();
351    
352            component.render(writer, cycle);
353    
354            verify();
355    
356            assertSame(component, delegate.getFormComponent());
357            assertBuffer("<span class=\"prefix\"><input type=\"text\" name=\"fred\" " +
358                    "value=\"recorded field value\" id=\"fred\" class=\"validation-delegate\" /></span>");
359        }
360    }