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