001    package org.apache.tapestry.scriptaculous;
002    
003    import org.apache.hivemind.ApplicationRuntimeException;
004    import org.apache.hivemind.Location;
005    import org.apache.tapestry.*;
006    import static org.apache.tapestry.Capturer.capture;
007    import static org.apache.tapestry.Capturer.newCapturer;
008    import org.apache.tapestry.coerce.ValueConverter;
009    import org.apache.tapestry.engine.DirectServiceParameter;
010    import org.apache.tapestry.engine.IEngineService;
011    import org.apache.tapestry.engine.ILink;
012    import org.apache.tapestry.form.MockForm;
013    import org.apache.tapestry.form.TranslatedFieldSupport;
014    import org.apache.tapestry.form.ValidatableFieldSupport;
015    import org.apache.tapestry.services.ResponseBuilder;
016    import org.apache.tapestry.spec.ComponentSpecification;
017    import org.apache.tapestry.valid.IValidationDelegate;
018    import org.apache.tapestry.valid.ValidationDelegate;
019    import static org.easymock.EasyMock.*;
020    import org.testng.annotations.Test;
021    
022    import java.util.ArrayList;
023    import java.util.Iterator;
024    import java.util.List;
025    import java.util.Map;
026    
027    /**
028     * Tests core functionality of {@link Suggest} component.
029     */
030    @Test
031    public class TestSuggest extends BaseComponentTestCase {
032    
033        public void test_Render_Component()
034        {
035            IRequestCycle cycle = newMock(IRequestCycle.class);
036            checkOrder(cycle, false);
037            
038            ResponseBuilder resp = newMock(ResponseBuilder.class);
039            IEngineService engine = newMock(IEngineService.class);
040            IEngine cengine = newMock(IEngine.class);
041            ILink link = newMock(ILink.class);
042            IScript script = newMock(IScript.class);
043            PageRenderSupport prs = newMock(PageRenderSupport.class);
044    
045            TranslatedFieldSupport translator = newMock(TranslatedFieldSupport.class);
046            ValidatableFieldSupport validator = newMock(ValidatableFieldSupport.class);
047    
048            IValidationDelegate delegate = new ValidationDelegate();
049            IForm form = newMock(IForm.class);
050            IMarkupWriter writer = newBufferWriter();
051    
052            Suggest comp = newInstance(Suggest.class,
053                                       "response", resp,
054                                       "templateTagName", "input",
055                                       "name", "suggest",
056                                       "clientId", "suggest",
057                                       "form", form,
058                                       "translatedFieldSupport", translator,
059                                       "validatableFieldSupport", validator,
060                                       "engineService", engine,
061                                       "script", script);
062    
063            expect(cycle.isRewinding()).andReturn(false).anyTimes();
064            expect(resp.isDynamic()).andReturn(false);
065            expect(cycle.getAttribute(TapestryUtils.FORM_ATTRIBUTE)).andReturn(form).anyTimes();
066    
067            expect(form.wasPrerendered(writer, comp)).andReturn(false).anyTimes();
068            expect(form.getDelegate()).andReturn(delegate).anyTimes();
069            expect(form.getElementId(comp)).andReturn("suggest");
070            expect(form.isRewinding()).andReturn(false).anyTimes();
071    
072            form.setFormFieldUpdating(true);
073            
074            expect(translator.format(comp, null)).andReturn("r2d2");
075            translator.renderContributions(comp, writer, cycle);
076            validator.renderContributions(comp, writer, cycle);
077    
078            expect(cycle.getEngine()).andReturn(cengine);
079            expect(cengine.getOutputEncoding()).andReturn("utf-8");
080            expect(engine.getLink(eq(false), isA(DirectServiceParameter.class))).andReturn(link);
081            expect(link.getURL()).andReturn("http://url");
082    
083            Capturer<Map> parm = newCapturer(Map.class);
084    
085            trainGetAttribute(cycle, TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE, prs);
086            script.execute(eq(comp), eq(cycle), eq(prs), capture(parm));
087    
088            replay();
089    
090            comp.renderComponent(writer, cycle);
091    
092            verify();
093    
094            assert parm.getCaptured() != null;
095            Map parms = parm.getCaptured();
096    
097            assertEquals(parms.size(), 4);
098            assertEquals(parms.get("inputId"), "suggest");
099            assertEquals(parms.get("updateId"), "suggestchoices");
100            assertEquals(parms.get("options"), "{\"onFailure\":tapestry.error,\"encoding\":\"utf-8\"}");
101            assertEquals(parms.get("updateUrl"), "http://url");
102    
103            assertBuffer("<input type=\"text\" autocomplete=\"off\" " +
104                         "id=\"suggest\" name=\"suggest\" value=\"r2d2\" />" +
105                         "<div id=\"suggestchoices\" class=\"\"></div>");
106        }
107    
108        public void test_Render_TextArea_Component()
109        {
110            IRequestCycle cycle = newMock(IRequestCycle.class);
111            checkOrder(cycle, false);
112    
113            ResponseBuilder resp = newMock(ResponseBuilder.class);
114            IEngineService engine = newMock(IEngineService.class);
115            IEngine cengine = newMock(IEngine.class);
116            ILink link = newMock(ILink.class);
117            IScript script = newMock(IScript.class);
118            PageRenderSupport prs = newMock(PageRenderSupport.class);
119    
120            TranslatedFieldSupport translator = newMock(TranslatedFieldSupport.class);
121            ValidatableFieldSupport validator = newMock(ValidatableFieldSupport.class);
122    
123            IValidationDelegate delegate = new ValidationDelegate();
124            IForm form = newMock(IForm.class);
125            IMarkupWriter writer = newBufferWriter();
126    
127            Suggest comp = newInstance(Suggest.class,
128                                       "response", resp,
129                                       "templateTagName", "textarea",
130                                       "name", "suggest",
131                                       "clientId", "suggest",
132                                       "form", form,
133                                       "translatedFieldSupport", translator,
134                                       "validatableFieldSupport", validator,
135                                       "engineService", engine,
136                                       "script", script,
137                                       "options", "{afterUpdateElement:myapp.processUpdate,other:other}");
138    
139            expect(cycle.isRewinding()).andReturn(false).anyTimes();
140            expect(resp.isDynamic()).andReturn(false);
141            expect(cycle.getAttribute(TapestryUtils.FORM_ATTRIBUTE)).andReturn(form).anyTimes();
142    
143            expect(form.wasPrerendered(writer, comp)).andReturn(false).anyTimes();
144            expect(form.getDelegate()).andReturn(delegate).anyTimes();
145            expect(form.getElementId(comp)).andReturn("suggest");
146            expect(form.isRewinding()).andReturn(false).anyTimes();
147    
148            form.setFormFieldUpdating(true);
149    
150            expect(translator.format(comp, null)).andReturn("r2d2");
151            translator.renderContributions(comp, writer, cycle);
152            validator.renderContributions(comp, writer, cycle);
153    
154            expect(cycle.getEngine()).andReturn(cengine);
155            expect(cengine.getOutputEncoding()).andReturn("utf-8");
156            expect(engine.getLink(eq(false), isA(DirectServiceParameter.class))).andReturn(link);
157            expect(link.getURL()).andReturn("http://url");
158    
159            Capturer<Map> parm = newCapturer(Map.class);
160    
161            trainGetAttribute(cycle, TapestryUtils.PAGE_RENDER_SUPPORT_ATTRIBUTE, prs);
162            script.execute(eq(comp), eq(cycle), eq(prs), capture(parm));
163    
164            replay();
165    
166            comp.renderComponent(writer, cycle);
167    
168            verify();
169    
170            assert parm.getCaptured() != null;
171            Map parms = parm.getCaptured();
172    
173            assertEquals(parms.size(), 4);
174            assertEquals(parms.get("inputId"), "suggest");
175            assertEquals(parms.get("updateId"), "suggestchoices");
176            assertEquals(parms.get("options"), 
177                    "{\"afterUpdateElement\":myapp.processUpdate,\"other\":\"other\"," +
178                    "\"onFailure\":tapestry.error,\"encoding\":\"utf-8\"}");
179            assertEquals(parms.get("updateUrl"), "http://url");
180    
181            assertBuffer("<textarea id=\"suggest\" name=\"suggest\">r2d2</textarea>" +
182                         "<div id=\"suggestchoices\" class=\"\"></div>");
183        }
184    
185        public void test_Render_Invalid_Options_JSON_Syntax()
186        {
187            IRequestCycle cycle = newMock(IRequestCycle.class);
188            checkOrder(cycle, false);
189            ResponseBuilder resp = newMock(ResponseBuilder.class);
190    
191            TranslatedFieldSupport translator = newMock(TranslatedFieldSupport.class);
192            ValidatableFieldSupport validator = newMock(ValidatableFieldSupport.class);
193    
194            IValidationDelegate delegate = new ValidationDelegate();
195            IForm form = new MockForm(delegate);
196            IMarkupWriter writer = newBufferWriter();
197    
198            IBinding binding = newMock(IBinding.class);
199            Location l = newLocation();
200            ComponentSpecification spec = new ComponentSpecification();
201            
202            Suggest comp = newInstance(Suggest.class,
203                                       "response", resp,
204                                       "templateTagName", "input",
205                                       "name", "suggest",
206                                       "clientId", "suggest",
207                                       "form", form,
208                                       "translatedFieldSupport", translator,
209                                       "validatableFieldSupport", validator,
210                                       "options", "{thisisinvalid:true",
211                                       "specification", spec);
212    
213            expect(cycle.isRewinding()).andReturn(false).anyTimes();
214            expect(resp.isDynamic()).andReturn(false);
215            expect(cycle.getAttribute(TapestryUtils.FORM_ATTRIBUTE)).andReturn(form).anyTimes();
216    
217            expect(translator.format(comp, null)).andReturn("r2d2");
218            translator.renderContributions(comp, writer, cycle);
219            validator.renderContributions(comp, writer, cycle);
220    
221            expect(binding.getObject()).andReturn("{thisisinvalid:true");
222            expect(binding.getLocation()).andReturn(l);
223    
224            replay();
225    
226            try {
227    
228                comp.setBinding("options", binding);
229    
230                comp.renderComponent(writer, cycle);
231    
232                unreachable();
233            } catch (ApplicationRuntimeException ex) {
234    
235                assertEquals(ex.getMessage(), "Invalid JSON options string given: {thisisinvalid:true. " +
236                                              "The options parameter must be properly formatted according to JSON object syntax rules. " +
237                                              "Expected a ',' or '}' at character 19 of {thisisinvalid:true>>missing value<<");
238            }
239    
240            verify();
241        }
242    
243        public void test_Render_List()
244        {
245            IRequestCycle cycle = newMock(IRequestCycle.class);
246            checkOrder(cycle, false);
247            ResponseBuilder resp = newMock(ResponseBuilder.class);
248    
249            IValidationDelegate delegate = new ValidationDelegate();
250            IForm form = newMock(IForm.class);
251            IMarkupWriter writer = newBufferWriter();
252    
253            ValueConverter converter = newMock(ValueConverter.class);
254    
255            List<String> source = new ArrayList<String>();
256            source.add("Foo");
257            source.add("Stimpy");
258            source.add("Cat");
259    
260            Suggest comp = newInstance(Suggest.class,
261                                       "response", resp,
262                                       "templateTagName", "input",
263                                       "name", "suggest",
264                                       "clientId", "suggest",
265                                       "form", form,
266                                       "searchTriggered", true,
267                                       "listSource", source,
268                                       "valueConverter", converter,
269                                       "listItemRenderer", DefaultListItemRenderer.SHARED_INSTANCE);
270    
271            expect(form.isRewinding()).andReturn(false);
272            expect(cycle.isRewinding()).andReturn(false).anyTimes();
273            expect(resp.isDynamic()).andReturn(true);
274            trainGetAttribute(cycle, TapestryUtils.FORM_ATTRIBUTE, form);
275            expect(form.wasPrerendered(writer, comp)).andReturn(false);
276    
277            expect(form.getElementId(comp)).andReturn("suggest");
278            expect(cycle.getParameter("suggest")).andReturn("b");
279            expect(converter.coerceValue(source, Iterator.class)).andReturn(source.iterator());
280    
281            replay();
282    
283            comp.renderComponent(writer, cycle);
284    
285            verify();
286    
287            assertBuffer("<ul><li>Foo</li><li>Stimpy</li><li>Cat</li></ul>");
288        }
289    }