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