View Javadoc

1   package com.atlassian.plugin.web.descriptors;
2   
3   import com.atlassian.plugin.Plugin;
4   import com.atlassian.plugin.PluginAccessor;
5   import com.atlassian.plugin.PluginParseException;
6   import com.atlassian.plugin.hostcontainer.HostContainer;
7   import com.atlassian.plugin.impl.AbstractPlugin;
8   import com.atlassian.plugin.module.ModuleFactory;
9   import com.atlassian.plugin.web.NoOpContextProvider;
10  import com.atlassian.plugin.web.WebFragmentHelper;
11  import com.atlassian.plugin.web.WebInterfaceManager;
12  import com.atlassian.plugin.web.model.EmbeddedTemplateWebPanel;
13  import com.atlassian.plugin.web.model.ResourceTemplateWebPanel;
14  import com.atlassian.plugin.web.model.WebPanel;
15  import com.atlassian.plugin.web.model.WebPanelTestUtils;
16  import com.atlassian.plugin.web.renderer.RendererException;
17  import com.atlassian.plugin.web.renderer.WebPanelRenderer;
18  import com.google.common.collect.ImmutableList;
19  import junit.framework.TestCase;
20  import org.dom4j.Document;
21  import org.dom4j.DocumentException;
22  import org.dom4j.DocumentHelper;
23  import org.dom4j.Element;
24  
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.StringWriter;
28  import java.io.Writer;
29  import java.net.URL;
30  import java.util.HashMap;
31  import java.util.Map;
32  
33  import static org.mockito.Matchers.any;
34  import static org.mockito.Mockito.*;
35  
36  public class TestDefaultWebPanelModuleDescriptor extends TestCase
37  {
38      private WebPanelModuleDescriptor descriptor;
39      private final Plugin plugin = new MockPlugin(this.getClass().getName());
40      private HostContainer hostContainer = mock(HostContainer.class);
41      private WebInterfaceManager webInterfaceManager = spy(new MockWebInterfaceManager());
42      private ModuleFactory moduleClassFactory = mock(ModuleFactory.class);
43      private PluginAccessor pluginAccessor = mock(PluginAccessor.class);
44      private Map<String, Object> context = new HashMap<String, Object>();
45  
46      @Override
47      protected void setUp() throws Exception
48      {
49          when(hostContainer.create(EmbeddedTemplateWebPanel.class)).thenReturn(new EmbeddedTemplateWebPanel(pluginAccessor));
50          when(hostContainer.create(ResourceTemplateWebPanel.class)).thenReturn(new ResourceTemplateWebPanel(pluginAccessor));
51  
52          descriptor = new DefaultWebPanelModuleDescriptor(hostContainer, moduleClassFactory, webInterfaceManager);
53      }
54  
55      public void testMissingResource() throws DocumentException, PluginParseException
56      {
57          final String webPanelXml = "<web-panel key=\"myPanel\" location=\"atl.header\"/>";
58          try
59          {
60              descriptor.init(plugin, createElement(webPanelXml));
61              fail("Descriptor should check for a resource with name 'view'");
62          }
63          catch (PluginParseException e)
64          {
65              // pass
66          }
67      }
68  
69      public void testMissingLocation() throws DocumentException, PluginParseException
70      {
71          final String webPanelXml = "<web-panel key=\"myPanel\">\n" +
72                                      "  <resource name=\"view\" type=\"static\"><![CDATA[<b>Hello World!</b>]]></resource>\n" +
73                                      "</web-panel>";
74          try
75          {
76              descriptor.init(plugin, createElement(webPanelXml));
77              fail("Descriptor should check for a location attribute");
78          }
79          catch (PluginParseException e)
80          {
81              // pass
82          }
83      }
84  
85      public void testGetEmbeddedTemplate() throws DocumentException, PluginParseException
86      {
87          final String webPanelXml = "<web-panel key=\"myPanel\" location=\"atl.header\">\n" +
88                                      "  <resource name=\"view\" type=\"static\"><![CDATA[<b>Hello World!</b>]]></resource>\n" +
89                                      "</web-panel>";
90          descriptor.init(plugin, createElement(webPanelXml));
91          descriptor.enabled();
92  
93          assertEquals("atl.header", descriptor.getLocation());
94          assertContextProvider(NoOpContextProvider.class);
95          assertEquals("<b>Hello World!</b>", descriptor.getModule().getHtml(context));
96      }
97  
98      public void testGetEmbeddedTemplateWithContextProvider() throws DocumentException, PluginParseException
99      {
100         final String webPanelXml = "<web-panel key=\"myPanel\" location=\"atl.header\">\n" +
101                                     "  <resource name=\"view\" type=\"velocity\"><![CDATA[$addedToContext]]></resource>\n" +
102                                     "  <context-provider class=\"com.atlassian.plugin.web.descriptors.MockContextProvider\" />\n" +
103                                     "</web-panel>";
104         descriptor.init(plugin, createElement(webPanelXml));
105         descriptor.enabled();
106 
107         final WebPanelRenderer renderer = new MockVelocityRenderer();
108         WebPanelTestUtils.mockPluginAccessorReturning(pluginAccessor, renderer);
109 
110         HashMap<String, Object> originalContext = new HashMap<String, Object>();
111         assertRendered(MockContextProvider.DATA_ADDED_TO_CONTEXT, originalContext);
112         assertEquals(0, originalContext.size());
113     }
114 
115     public void testGetResourceTemplate() throws DocumentException, PluginParseException
116     {
117         final String webPanelXml = "<web-panel key=\"myPanel\" location=\"atl.header\">\n" +
118                                     "  <resource name=\"view\" type=\"static\" location=\"ResourceTemplateWebPanelTest.txt\"/>\n" +
119                                     "</web-panel>";
120 
121         descriptor.init(plugin, createElement(webPanelXml));
122         descriptor.enabled();
123 
124         assertContextProvider(NoOpContextProvider.class);
125 
126         String html = descriptor.getModule().getHtml(context);
127         assertTrue(html.startsWith("This <file> is used as web panel contents in unit tests"));
128     }
129 
130     public void testGetResourceTemplateWithContextProvider() throws DocumentException, PluginParseException
131     {
132         final String webPanelXml = "<web-panel key=\"myPanel\" location=\"atl.header\">\n" +
133                                     "  <resource name=\"view\" type=\"velocity\" location=\"ResourceTemplateWebPanelTest.txt\"/>\n" +
134                                     "  <context-provider class=\"com.atlassian.plugin.web.descriptors.MockContextProvider\" />\n" +
135                                     "</web-panel>";
136         descriptor.init(plugin, createElement(webPanelXml));
137         descriptor.enabled();
138 
139         final WebPanelRenderer renderer = new MockVelocityRenderer();
140         WebPanelTestUtils.mockPluginAccessorReturning(pluginAccessor, renderer);
141 
142         HashMap<String, Object> originalContext = new HashMap<String, Object>();
143         assertRendered(MockContextProvider.DATA_ADDED_TO_CONTEXT, originalContext);
144         assertEquals(0, originalContext.size());
145     }
146 
147     public void testWebPanelClass() throws DocumentException, PluginParseException
148     {
149         when(moduleClassFactory.createModule(eq("com.atlassian.plugin.web.descriptors.MockWebPanel"), any(DefaultWebPanelModuleDescriptor.class))).thenReturn(new MockWebPanel());
150 
151         final String webPanelXml = "<web-panel key=\"myPanel\" location=\"atl.header\" class=\"com.atlassian.plugin.web.descriptors.MockWebPanel\"/>";
152         descriptor.init(plugin, createElement(webPanelXml));
153         descriptor.enabled();
154 
155         assertRendered(MockWebPanel.NOTHING_IN_CONTEXT, new HashMap<String, Object>());
156     }
157 
158     public void testWebPanelClassWithContextProvider() throws DocumentException, PluginParseException
159     {
160         when(moduleClassFactory.createModule(eq("com.atlassian.plugin.web.descriptors.MockWebPanel"), any(DefaultWebPanelModuleDescriptor.class))).thenReturn(new MockWebPanel());
161 
162         final String webPanelXml = "<web-panel key=\"myPanel\" location=\"atl.header\" class=\"com.atlassian.plugin.web.descriptors.MockWebPanel\">\n" +
163                                     "  <context-provider class=\"com.atlassian.plugin.web.descriptors.MockContextProvider\" />\n" +
164                                     "</web-panel>";
165         descriptor.init(plugin, createElement(webPanelXml));
166         descriptor.enabled();
167 
168         HashMap<String, Object> originalContext = new HashMap<String, Object>();
169         assertRendered(MockContextProvider.DATA_ADDED_TO_CONTEXT, originalContext);
170 
171         // Confirm that the original context was protected from the ContextProvider's changes
172         assertEquals(0, originalContext.size());
173     }
174 
175     public void testSimpleLabelTemplate() throws DocumentException, PluginParseException
176     {
177         WebFragmentHelper fragmentHelper = spy(webInterfaceManager.getWebFragmentHelper());
178         when(webInterfaceManager.getWebFragmentHelper()).thenReturn(fragmentHelper);
179 
180         when(fragmentHelper.renderVelocityFragment(eq("Hello ${x}"), any(Map.class))).thenReturn("It Worked!");
181 
182         final String webPanelXml = "<web-panel key=\"myPanel\" location=\"atl.header\">\n" +
183                                     "  <resource name=\"view\" type=\"static\"><![CDATA[<b>Hello World!</b>]]></resource>\n" +
184                                     "  <label>Hello ${x}</label>" +
185                                     "</web-panel>";
186         descriptor.init(plugin, createElement(webPanelXml));
187         descriptor.enabled();
188 
189         assertContextProvider(NoOpContextProvider.class);
190         Map<String,Object> ctx = new HashMap<String, Object>();
191         ctx.put("x", "foo");
192         assertEquals("It Worked!", descriptor.getWebLabel().getDisplayableLabel(null, ctx));
193     }
194 
195     private void assertRendered(String expectedHtml, Map<String, Object> originalContext)
196     {
197         WebPanel webPanel = descriptor.getModule();
198         String renderedHtml = webPanel.getHtml(originalContext);
199         assertEquals(expectedHtml, renderedHtml);
200     }
201 
202     private void assertContextProvider(Class expectedContextProviderClass)
203     {
204         assertEquals(expectedContextProviderClass, descriptor.getContextProvider().getClass());
205     }
206 
207     private Element createElement(final String childElement) throws DocumentException
208     {
209         final Document document = DocumentHelper.parseText(childElement);
210         final Element element = document.getRootElement();
211         return element;
212     }
213 
214     private class MockPlugin extends AbstractPlugin
215     {
216         MockPlugin(final String key)
217         {
218             setKey(key);
219             setName(key);
220         }
221 
222         public boolean isUninstallable()
223         {
224             return false;
225         }
226 
227         public boolean isDeleteable()
228         {
229             return false;
230         }
231 
232         public boolean isDynamicallyLoaded()
233         {
234             return false;
235         }
236 
237         public <T> Class<T> loadClass(final String clazz, final Class<?> callingClass) throws ClassNotFoundException
238         {
239             return null;
240         }
241 
242         public ClassLoader getClassLoader()
243         {
244             return this.getClass().getClassLoader();
245         }
246 
247         public URL getResource(final String path)
248         {
249             return null;
250         }
251 
252         public InputStream getResourceAsStream(final String name)
253         {
254             return null;
255         }
256     }
257 
258     private class MockVelocityRenderer implements WebPanelRenderer
259     {
260         static final String NOTHING_IN_CONTEXT = "nothing in context";
261 
262         public String getResourceType()
263         {
264             return "velocity";
265         }
266 
267         public void render(String templateName, Plugin plugin,
268             Map<String, Object> context, Writer writer)
269             throws RendererException, IOException
270         {
271             if (!context.isEmpty())
272             {
273                 for (Object value : context.values())
274                 {
275                     writer.append(value.toString());
276                 }
277             }
278             else
279             {
280                 writer.append(NOTHING_IN_CONTEXT);
281             }
282         }
283 
284         public String renderFragment(String fragment, Plugin plugin,
285             Map<String, Object> context) throws RendererException
286         {
287             try
288             {
289                 StringWriter out = new StringWriter();
290                 renderFragment(out, fragment, plugin, context);
291                 return out.toString();
292             }
293             catch (IOException e)
294             {
295                 throw new RuntimeException(e);
296             }
297         }
298 
299         @Override
300         public void renderFragment(Writer writer, String fragment, Plugin plugin, Map<String, Object> context)
301                 throws RendererException, IOException
302         {
303             if (!context.isEmpty())
304             {
305                 for (Object value : context.values())
306                 {
307                     writer.write(value.toString());
308                 }
309             }
310             else
311             {
312                 writer.write(NOTHING_IN_CONTEXT);
313             }
314         }
315     }
316 }