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.html;
016    
017    import org.apache.hivemind.ApplicationRuntimeException;
018    import org.apache.hivemind.Location;
019    import org.apache.hivemind.Resource;
020    import org.apache.tapestry.*;
021    import org.apache.tapestry.asset.AssetSource;
022    import org.apache.tapestry.engine.IScriptSource;
023    import org.apache.tapestry.spec.ComponentSpecification;
024    import org.apache.tapestry.spec.IComponentSpecification;
025    import static org.easymock.EasyMock.*;
026    import org.testng.annotations.Test;
027    
028    import java.util.HashMap;
029    import java.util.Locale;
030    import java.util.Map;
031    
032    /**
033     * Tests for the {@link Script} component.
034     * 
035     * @author Howard M. Lewis Ship
036     * @since 4.0
037     */
038    @Test
039    public class ScriptTest extends BaseComponentTestCase
040    {
041        private static class MockScript implements IScript
042        {
043            Map _symbols;
044    
045            public void execute(IRequestCycle cycle, IScriptProcessor processor, Map symbols)
046            {
047                _symbols = symbols;
048            }
049    
050            public void execute(IComponent target, IRequestCycle cycle, IScriptProcessor processor, Map symbols)
051            {
052                _symbols = symbols;
053            }
054            
055            public Resource getScriptResource()
056            {
057                // TODO Auto-generated method stub
058                return null;
059            }
060    
061        }
062    
063        /**
064         * No input symbols, no informal parameters.
065         */
066        public void test_Minimal_Render()
067        {
068            IScriptSource source = newScriptSource();
069            IScript script = newScript();
070    
071            IMarkupWriter writer = newWriter();
072            
073            PageRenderSupport support = newPageRenderSupport();
074            
075            IRequestCycle cycle = newCycle(false, null);
076            AssetSource assetSource = newMock(AssetSource.class);
077            IPage page = newMock(IPage.class);
078            expect(page.getLocale()).andReturn(Locale.getDefault());
079            
080            trainGetPageRenderSupport(cycle, support);
081            
082            Resource scriptLocation = newResource();
083            IRender body = newRender();
084            
085            IComponent container = newComponent();
086    
087            String scriptPath = "MyScript.script";
088    
089            Script component = newInstance(Script.class,
090                    "specification", new ComponentSpecification(),
091                    "container", container,
092                    "scriptSource", source,
093                    "scriptPath", scriptPath,
094                    "assetSource", assetSource,
095                    "page", page
096            );
097            
098            trainGetScriptLocation(container, scriptPath, scriptLocation, assetSource);
099            
100            trainGetScript(source, scriptLocation, script);
101    
102            script.execute(component, cycle, support, new HashMap());
103    
104            trainResponseBuilder(cycle, writer);
105            
106            body.render(writer, cycle);
107            
108            replay();
109    
110            component.addBody(body);
111    
112            component.renderComponent(writer, cycle);
113    
114            verify();
115        }
116    
117        public void test_With_Symbols_Map()
118        {
119            IScriptSource source = newScriptSource();
120            MockScript script = new MockScript();
121    
122            PageRenderSupport support = newPageRenderSupport();
123            IMarkupWriter writer = newWriter();
124            IRequestCycle cycle = newCycle(false, null);
125            AssetSource assetSource = newMock(AssetSource.class);
126    
127            IPage page = newMock(IPage.class);
128            expect(page.getLocale()).andReturn(Locale.getDefault());
129    
130            trainGetPageRenderSupport(cycle, support);
131            
132            Resource scriptLocation = newResource();
133            IRender body = newRender();
134    
135            IComponent container = newComponent();
136    
137            Map baseSymbols = new HashMap();
138            baseSymbols.put("fred", "barney");
139    
140            String scriptPath = "MyScript.script";
141    
142            Script component = newInstance(Script.class,
143                    "specification", new ComponentSpecification(),
144                    "container", container,
145                    "scriptSource", source,
146                    "scriptPath", scriptPath,
147                    "baseSymbols", baseSymbols,
148                    "assetSource", assetSource,
149                    "page", page
150            );
151    
152            trainGetScriptLocation(container, scriptPath, scriptLocation, assetSource);
153    
154            trainGetScript(source, scriptLocation, script);
155    
156            trainResponseBuilder(cycle, writer);
157            
158            body.render(writer, cycle);
159            
160            replay();
161    
162            component.addBody(body);
163    
164            component.renderComponent(writer, cycle);
165    
166            verify();
167    
168            assertEquals(baseSymbols, script._symbols);
169            assertSame(script._symbols, component.getSymbols());
170            assertNotSame(baseSymbols, script._symbols);
171        }
172    
173        public void test_With_Symbols_Map_And_Informal_Parameters()
174        {
175            IScriptSource source = newScriptSource();
176            MockScript script = new MockScript();
177    
178            PageRenderSupport support = newPageRenderSupport();
179            IRequestCycle cycle = newCycle(false, null);
180            AssetSource assetSource = newMock(AssetSource.class);
181            
182            IPage page = newMock(IPage.class);
183            expect(page.getLocale()).andReturn(Locale.getDefault());
184    
185            trainGetPageRenderSupport(cycle, support);
186            
187            IMarkupWriter writer = newWriter();
188            Resource scriptLocation = newResource();
189            IRender body = newRender();
190    
191            IComponent container = newComponent();
192    
193            Map baseSymbols = new HashMap();
194            baseSymbols.put("fred", "flintstone");
195            baseSymbols.put("flash", "gordon");
196    
197            IBinding informal = newBinding("mercury");
198    
199            String scriptPath = "MyScript.script";
200    
201            Script component = newInstance(Script.class,
202                    "specification", new ComponentSpecification(),
203                    "container", container,
204                    "scriptSource", source,
205                    "scriptPath", scriptPath,
206                    "baseSymbols", baseSymbols,
207                    "assetSource", assetSource,
208                    "page", page
209            );
210            component.setBinding("fred", informal);
211    
212            trainGetScriptLocation(container, scriptPath, scriptLocation, assetSource);
213    
214            trainGetScript(source, scriptLocation, script);
215    
216            trainResponseBuilder(cycle, writer);
217            
218            body.render(writer, cycle);
219            
220            replay();
221    
222            component.addBody(body);
223    
224            component.renderComponent(writer, cycle);
225    
226            verify();
227    
228            Map expectedSymbols = new HashMap(baseSymbols);
229            expectedSymbols.put("fred", "mercury");
230    
231            assertEquals(expectedSymbols, script._symbols);
232            assertSame(script._symbols, component.getSymbols());
233        }
234    
235        public void test_Rewinding()
236        {
237            IMarkupWriter writer = newWriter();
238            IRequestCycle cycle = newCycle(true, writer);
239            IRender body = newRender();
240    
241            body.render(writer, cycle);
242            
243            replay();
244    
245            Script component = (Script) newInstance(Script.class);
246    
247            component.addBody(body);
248    
249            component.renderComponent(writer, cycle);
250    
251            verify();
252        }
253    
254        public void test_MultiParam_Exception() 
255        {
256            IScriptSource source = newScriptSource();
257            
258            PageRenderSupport support = newPageRenderSupport();
259            IRequestCycle cycle = newCycle(false, false);
260            IMarkupWriter writer = newWriter();
261            IRender body = newRender();
262            
263            IComponent container = newComponent();
264    
265            String scriptPath = "MyScript.script";
266            
267            IAsset scriptAsset = newAsset();
268    
269            Script component = newInstance(Script.class,
270                    "specification", new ComponentSpecification(),
271                    "container", container,
272                    "scriptSource", source,
273                    "scriptPath", scriptPath,
274                    "scriptAsset", scriptAsset
275            );
276    
277            trainGetPageRenderSupport(cycle, support);
278            
279            replay();
280            
281            component.addBody(body);
282            
283            try {
284                    component.renderComponent(writer, cycle);
285            } catch (ApplicationRuntimeException ex) {
286                    assertExceptionSubstring(ex, "Script component has both script IAsset");
287            }
288            
289            verify();
290        }
291        
292        public void test_NoParam_Exception() 
293        {
294            IScriptSource source = newScriptSource();
295            
296            PageRenderSupport support = newPageRenderSupport();
297            IRequestCycle cycle = newCycle(false, false);
298            IMarkupWriter writer = newWriter();
299            IRender body = newRender();
300            
301            IComponent container = newComponent();
302    
303            String scriptPath = "MyScript.script";
304            
305            IAsset scriptAsset = newAsset();
306    
307            Script component = newInstance(Script.class,
308                    "specification", new ComponentSpecification(),
309                    "container", container,
310                    "scriptSource", source
311            );
312    
313            trainGetPageRenderSupport(cycle, support);
314            
315            replay();
316            
317            component.addBody(body);
318            
319            try {
320                    component.renderComponent(writer, cycle);
321            } catch (ApplicationRuntimeException ex) {
322                    assertExceptionSubstring(ex, "neither parameter was set");
323            }
324            
325            verify();
326        }    
327        
328        public void test_IAsset_NotFound_Exception() 
329        {
330            IScriptSource source = newScriptSource();
331            IScript script = newScript();
332            
333            PageRenderSupport support = newPageRenderSupport();
334            
335            IRequestCycle cycle = newCycle(false, null);
336            
337            trainGetPageRenderSupport(cycle, support);
338            
339            IMarkupWriter writer = newWriter();
340            Resource scriptLocation = newResource();
341            IRender body = newRender();
342            
343            IComponent container = newComponent();
344            
345            IAsset scriptAsset = newAsset();
346            
347            expect(scriptAsset.getResourceLocation()).andReturn(scriptLocation);
348    
349            Script component = newInstance(Script.class,
350                    "specification", new ComponentSpecification(),
351                    "container", container,
352                    "scriptSource", source,
353                    "scriptAsset", scriptAsset
354            );
355            
356            expect(source.getScript(scriptLocation)).andThrow(new RuntimeException());
357            
358            replay();
359            
360            component.addBody(body);
361            
362            try {
363                    component.renderComponent(writer, cycle);
364                    unreachable();
365            } catch (ApplicationRuntimeException ex) {
366            }        
367            
368            verify();
369        }      
370        
371        public void test_IAsset_Param_Render()
372        {
373            IScriptSource source = newScriptSource();
374            IScript script = newScript();
375            
376            PageRenderSupport support = newPageRenderSupport();
377            
378            IRequestCycle cycle = newCycle(false, null);
379            
380            trainGetPageRenderSupport(cycle, support);
381            
382            IMarkupWriter writer = newWriter();
383            Resource scriptLocation = newResource();
384            IRender body = newRender();
385            
386            IComponent container = newComponent();
387            
388            IAsset scriptAsset = newAsset();
389            
390            expect(scriptAsset.getResourceLocation()).andReturn(scriptLocation);
391    
392            Script component = newInstance(Script.class,
393                    "specification", new ComponentSpecification(),
394                    "container", container,
395                    "scriptSource", source,
396                    "scriptAsset", scriptAsset
397            );
398    
399            trainGetScript(source, scriptLocation, script);
400            
401            script.execute(component, cycle, support, new HashMap());
402            
403            trainResponseBuilder(cycle, writer);
404            
405            body.render(writer, cycle);
406            
407            replay();
408            
409            component.addBody(body);
410            
411            component.renderComponent(writer, cycle);
412            
413            verify();
414        }
415        
416        protected IScript newScript()
417        {
418            return newMock(IScript.class);
419        }
420    
421        protected void trainGetScript(IScriptSource source, Resource scriptLocation, IScript script)
422        {
423            expect(source.getScript(scriptLocation)).andReturn(script);
424        }
425    
426        protected IScriptSource newScriptSource()
427        {
428            return newMock(IScriptSource.class);
429        }
430    
431        protected void trainGetScriptLocation(IComponent component, String scriptPath,
432                Resource scriptLocation, AssetSource assetSource)
433        {
434            IComponentSpecification spec = newSpec();
435            Resource resource = newResource();
436            IAsset asset = newMock(IAsset.class);
437    
438            expect(component.getSpecification()).andReturn(spec).anyTimes();
439            
440            expect(spec.getSpecificationLocation()).andReturn(resource);
441    
442            expect(assetSource.findAsset(eq(resource), eq(spec), eq(scriptPath), isA(Locale.class), (Location)isNull())).andReturn(asset);
443            expect(asset.getResourceLocation()).andReturn(scriptLocation);        
444        }
445    }