1 package com.atlassian.plugins.codegen.modules.confluence.blueprint;
2
3 import com.atlassian.plugins.codegen.AbstractModuleCreatorTestCase;
4 import com.atlassian.plugins.codegen.ClassId;
5 import com.atlassian.plugins.codegen.ComponentDeclaration;
6 import com.atlassian.plugins.codegen.PluginProjectChangeset;
7 import com.atlassian.plugins.codegen.ResourceFile;
8 import com.atlassian.plugins.codegen.SourceFile;
9 import com.atlassian.plugins.codegen.modules.AbstractNameBasedModuleProperties;
10 import com.atlassian.plugins.codegen.modules.common.web.WebResourceProperties;
11 import com.google.common.collect.Lists;
12 import org.dom4j.Document;
13 import org.dom4j.Element;
14 import org.dom4j.Node;
15 import org.junit.After;
16 import org.junit.Before;
17 import org.junit.Test;
18
19 import java.util.List;
20
21 import static com.atlassian.plugins.codegen.modules.confluence.blueprint.BlueprintI18nProperty.*;
22 import static com.atlassian.plugins.codegen.modules.confluence.blueprint.BlueprintPromptEntry.*;
23 import static java.lang.String.format;
24 import static org.hamcrest.Matchers.*;
25 import static org.junit.Assert.*;
26
27
28
29
30
31
32
33
34
35
36
37 public class BlueprintModuleCreatorTest extends AbstractModuleCreatorTestCase<BlueprintProperties>
38 {
39 public static final String PLUGIN_KEY = "com.atlassian.confluence.plugins.foo-print";
40
41
42
43
44
45 private BlueprintPromptEntries promptProps;
46
47 private BlueprintProperties blueprintProps;
48
49
50 private String blueprintModuleKey = "foo-print-blueprint";
51 private String blueprintIndexKey = "foo-print";
52 private String webItemName = "FooPrint";
53 private String webItemDesc = "There's no Blueprint like my FooPrint.";
54 private String templateModuleKey = "foo-plate";
55
56 public BlueprintModuleCreatorTest()
57 {
58 super("blueprint", new BlueprintModuleCreator());
59 }
60
61 @Before
62 public void setupBaseProps() throws Exception
63 {
64 createBasePromptProperties();
65 buildBlueprintProperties();
66
67 }
68
69 private void buildBlueprintProperties()
70 {
71
72
73
74 changeset = null;
75 blueprintProps = new BlueprintBuilder(promptProps).build();
76 setProps(blueprintProps);
77 }
78
79
80
81
82
83 private void createBasePromptProperties()
84 {
85 promptProps = new BlueprintPromptEntries(PLUGIN_KEY);
86
87 promptProps.put(INDEX_KEY_PROMPT, blueprintIndexKey);
88 promptProps.put(WEB_ITEM_NAME_PROMPT, webItemName);
89 promptProps.put(WEB_ITEM_DESC_PROMPT, webItemDesc);
90
91 List<String> contentTemplateKeys = Lists.newArrayList();
92 contentTemplateKeys.add(templateModuleKey);
93 promptProps.put(CONTENT_TEMPLATE_KEYS_PROMPT, contentTemplateKeys);
94 }
95
96 @After
97 public void tearDown()
98 {
99 changeset = null;
100 }
101
102 @Test
103 public void blueprintModuleBasicSettings() throws Exception
104 {
105 Element blueprintModule = getGeneratedModule();
106 assertNodeText(blueprintModule, "@key", blueprintModuleKey);
107 String blueprintModuleName = "FooPrint Blueprint";
108 assertNodeText(blueprintModule, "@name", blueprintModuleName);
109 assertNodeText(blueprintModule, "@index-key", blueprintIndexKey);
110 assertNodeText(blueprintModule, "content-template/@ref", templateModuleKey);
111
112 String indexPageI18nTitle = PLUGIN_KEY + ".index.page.title";
113 assertNodeText(blueprintModule, "@i18n-index-title-key", indexPageI18nTitle);
114
115 assertI18nString(indexPageI18nTitle, "FooPrints");
116 }
117
118 @Test
119 public void contentTemplateModuleBasicSettings() throws Exception
120 {
121 Element templateModule = getGeneratedModule("content-template");
122 assertNodeText(templateModule, "@key", templateModuleKey);
123 assertNodeText(templateModule, "@i18n-name-key", PLUGIN_KEY + "." + "foo-plate.name");
124 assertNodeText(templateModule, "description/@key", PLUGIN_KEY + "." + "foo-plate.desc");
125
126 assertNodeText(templateModule, "resource/@name", "template");
127 assertNodeText(templateModule, "resource/@type", "download");
128 assertNodeText(templateModule, "resource/@location", "xml/" + templateModuleKey + ".xml");
129
130 assertI18nString(PLUGIN_KEY + "." + templateModuleKey + ".name", "FooPrint Content Template 0");
131 String templateDesc = "Contains Storage-format XML used by the FooPrint Blueprint";
132 assertI18nString(PLUGIN_KEY + "." + templateModuleKey + ".desc", templateDesc);
133 }
134
135 @Test
136 public void contentTemplateFileIsCreated() throws Exception
137 {
138 ResourceFile file = getResourceFile("xml", templateModuleKey + ".xml");
139 String xml = new String(file.getContent());
140 String templateContentI18nKey = PLUGIN_KEY + "." + templateModuleKey + ".content.text";
141 assertThat(xml, containsString(templateContentI18nKey));
142 assertThat(xml, containsString("ac:placeholder"));
143 assertThat(xml, containsString("ac:type=\"mention\""));
144 assertI18nString(templateContentI18nKey, ContentTemplateProperties.CONTENT_I18N_DEFAULT_VALUE);
145 }
146
147 @Test
148 public void indexPageTemplateFileIsCreated() throws Exception
149 {
150 promptProps.put(INDEX_PAGE_TEMPLATE_PROMPT, true);
151 buildBlueprintProperties();
152
153 Element blueprintModule = getGeneratedModule();
154 String templateModuleKey = BlueprintProperties.INDEX_TEMPLATE_DEFAULT_KEY;
155 assertNodeText(blueprintModule, "@index-template-key", templateModuleKey);
156
157 Document templateModules = getAllGeneratedModulesOfType("content-template");
158 Element templateModule = (Element)templateModules.selectSingleNode("//content-template[@key='custom-index-page-template']");
159 assertNodeText(templateModule, "@key", templateModuleKey);
160 assertNodeText(templateModule, "@i18n-name-key", "com.atlassian.confluence.plugins.foo-print.custom-index-page-template.name");
161 assertNodeText(templateModule, "description/@key", "com.atlassian.confluence.plugins.foo-print.custom-index-page-template.desc");
162
163 assertNodeText(templateModule, "resource/@name", "template");
164 assertNodeText(templateModule, "resource/@type", "download");
165 assertNodeText(templateModule, "resource/@location", "xml/" + templateModuleKey + ".xml");
166
167 assertI18nString("com.atlassian.confluence.plugins.foo-print.custom-index-page-template.name", "Custom Index Page Content Template");
168 String templateDesc = "Contains Storage-format XML used by the FooPrint Blueprint's Index page";
169 assertI18nString("com.atlassian.confluence.plugins.foo-print.custom-index-page-template.desc", templateDesc);
170
171 ResourceFile file = getResourceFile("xml", templateModuleKey + ".xml");
172 String xml = new String(file.getContent());
173 String templateContentI18nKey = PLUGIN_KEY + "." + templateModuleKey + ".content.text";
174 assertThat(xml, containsString(templateContentI18nKey));
175 assertI18nString(templateContentI18nKey, ContentTemplateProperties.INDEX_TEMPLATE_CONTENT_VALUE);
176 }
177
178 @Test
179 public void contextProviderIsAddedToContentTemplate() throws Exception
180 {
181 promptProps.put(CONTEXT_PROVIDER_PROMPT, true);
182 buildBlueprintProperties();
183
184
185 Element templateModule = getGeneratedModule("content-template");
186 String className = "ContentTemplateContextProvider";
187 String packageName = "com.atlassian.confluence.plugins.foo_print";
188 String fqClassName = packageName + "." + className;
189 assertNodeText(templateModule, "context-provider/@class", fqClassName);
190
191
192 SourceFile sourceFile = getSourceFile(packageName, className);
193 assertThat(sourceFile.getContent(), containsString("package " + packageName + ";"));
194 assertThat(sourceFile.getContent(), containsString("\"variableA\""));
195 assertThat(sourceFile.getContent(), containsString("\"variableB\""));
196
197
198 ResourceFile file = getResourceFile("xml", templateModuleKey + ".xml");
199 String xml = new String(file.getContent());
200 assertThat(xml, containsString("<at:var at:name=\"variableA\" />"));
201 assertThat(xml, containsString("<at:var at:name=\"variableB\" at:rawXhtml=\"true\" />"));
202 }
203
204 @Test
205 public void webItemModuleBasicSettings() throws Exception
206 {
207 String webItemNameI18nKey = PLUGIN_KEY + ".blueprint.display.name";
208 String webItemDescI18nKey = PLUGIN_KEY + ".blueprint.display.desc";
209
210 Element module = getGeneratedModule("web-item");
211 assertNameBasedModuleProperties(module, blueprintProps.getWebItem());
212
213 assertNodeText(module, "@key", "foo-print-blueprint-web-item");
214 assertNodeText(module, "@i18n-name-key", webItemNameI18nKey);
215 assertNodeText(module, "@section", "system.create.dialog/content");
216 assertNodeText(module, "description/@key", webItemDescI18nKey);
217 assertNodeText(module, "param/@name", BlueprintProperties.WEB_ITEM_BLUEPRINT_KEY);
218 assertNodeText(module, "param/@value", blueprintModuleKey);
219
220 assertI18nString(webItemNameI18nKey, webItemName);
221 assertI18nString(webItemDescI18nKey, webItemDesc);
222 }
223
224 @Test
225 public void webItemIconIsCreated() throws Exception
226 {
227 Element webItem = getGeneratedModule("web-item");
228 assertNodeText(webItem, "styleClass", "icon-foo-print-blueprint large");
229
230 Element webResource = getGeneratedModule("web-resource");
231 assertNodeText(webResource, "resource[@name='blueprints.css']/@type", "download");
232 assertNodeText(webResource, "resource[@name='blueprints.css']/@location", "css/blueprints.css");
233
234 String css = new String(getResourceFile("css", "blueprints.css").getContent());
235 assertThat(css, containsString(".icon-foo-print-blueprint.large {"));
236 assertThat(css, containsString(".acs-nav-item.blueprint.foo-print .icon {"));
237 }
238
239 @Test
240 public void howToUseTemplateIsAdded() throws Exception
241 {
242 promptProps.put(HOW_TO_USE_PROMPT, true);
243 buildBlueprintProperties();
244
245
246 Element blueprintModule = getGeneratedModule();
247 assertNodeText(blueprintModule, "@how-to-use-template", blueprintProps.getHowToUseTemplate());
248
249
250 String soyHeadingI18nKey = PLUGIN_KEY + ".wizard.how-to-use.heading";
251 String soyContentI18nKey = PLUGIN_KEY + ".wizard.how-to-use.content";
252 String soy = new String(getResourceFile("soy", "my-templates.soy").getContent());
253 assertThat(soy, containsString(format("{namespace %s}", "Confluence.Blueprints.Plugin.FooPrint")));
254 assertThat(soy, containsString("{template .howToUse}"));
255 assertThat(soy, containsString(format("{getText('%s')}", soyHeadingI18nKey)));
256 assertThat(soy, containsString(format("{getText('%s')}", soyContentI18nKey)));
257
258
259 Element webResourceModule = getGeneratedModule("web-resource");
260 assertWebResource(webResourceModule, blueprintProps.getWebResource());
261
262
263 assertI18nString(soyHeadingI18nKey, HOW_TO_USE_HEADING.getI18nValue());
264 assertI18nString(soyContentI18nKey, HOW_TO_USE_CONTENT.getI18nValue());
265 }
266
267 @Test
268 public void editorIsSkipped() throws Exception
269 {
270 promptProps.put(SKIP_PAGE_EDITOR_PROMPT, true);
271 buildBlueprintProperties();
272
273 Element blueprintModule = getGeneratedModule();
274 assertNodeText(blueprintModule, "@create-result", BlueprintProperties.CREATE_RESULT_VIEW);
275
276
277 String xml = new String(getResourceFile("xml", templateModuleKey + ".xml").getContent());
278 assertThat(xml, not(containsString("ac:placeholder")));
279 }
280
281 @Test
282 public void dialogWizardIsAdded() throws Exception
283 {
284 promptProps.put(DIALOG_WIZARD_PROMPT, true);
285 buildBlueprintProperties();
286
287
288 Element blueprintModule = getGeneratedModule();
289 Element wizardElement = blueprintModule.element("dialog-wizard");
290 assertNotNull("dialog-wizard element should be created", wizardElement);
291 assertNodeText(wizardElement, "@key", "foo-print-wizard");
292
293 Element pageElement = wizardElement.element("dialog-page");
294 assertNotNull("dialog-page element should be created", pageElement);
295 assertNodeText(pageElement, "@id", "page0");
296 assertNodeText(pageElement, "@template-key", "Confluence.Blueprints.Plugin.FooPrint.wizardPage0");
297
298 String wizardPageTitle = PLUGIN_KEY + ".wizard.page0.title";
299 String wizardPageDescHeader = PLUGIN_KEY + ".wizard.page0.desc.header";
300 String wizardPageDescContent = PLUGIN_KEY + ".wizard.page0.desc.content";
301 assertNodeText(pageElement, "@title-key", wizardPageTitle);
302 assertNodeText(pageElement, "@description-header-key", wizardPageDescHeader);
303 assertNodeText(pageElement, "@description-content-key", wizardPageDescContent);
304 assertI18nString(wizardPageTitle, "Wizard Page 0 Title");
305 assertI18nString(wizardPageDescHeader, "Page 0 Description");
306 assertI18nString(wizardPageDescContent, "This wizard page does A, B and C");
307
308
309 String soy = new String(getResourceFile("soy", "my-templates.soy").getContent());
310 String fieldId = "foo-print-blueprint-page-title";
311 assertThat(soy, containsString(format("{namespace %s}", "Confluence.Blueprints.Plugin.FooPrint")));
312 assertThat(soy, containsString("{template .wizardPage0}"));
313 assertThat(soy, containsString(fieldId));
314
315
316 String js = new String(getResourceFile("js", "dialog-wizard.js").getContent());
317 assertThat(js, containsString("setWizard('" + PLUGIN_KEY + ":foo-print-blueprint-web-item"));
318 assertThat(js, containsString(fieldId));
319
320
321 Element webResourceModule = getGeneratedModule("web-resource");
322 assertWebResource(webResourceModule, blueprintProps.getWebResource());
323
324
325 String titleLabel = PLUGIN_KEY + ".wizard.page0.title.label";
326 String titlePlace = PLUGIN_KEY + ".wizard.page0.title.placeholder";
327 String titleError = PLUGIN_KEY + ".wizard.page0.title.error";
328 String preRender = PLUGIN_KEY + ".wizard.page0.pre-render";
329 String postRender = PLUGIN_KEY + ".wizard.page0.post-render";
330
331 assertThat(soy, containsString(format("{getText('%s')}", titleLabel)));
332 assertThat(soy, containsString(format("{getText('%s')}", titlePlace)));
333 assertThat(js, containsString(format("AJS.I18n.getText('%s')", preRender)));
334 assertThat(js, containsString(format("AJS.I18n.getText('%s')", postRender)));
335 assertThat(js, containsString(format("AJS.I18n.getText('%s')", titleError)));
336
337
338 String xml = new String(getResourceFile("xml", templateModuleKey + ".xml").getContent());
339 assertThat(xml, containsString("wizardVariable"));
340
341
342
343 assertThat(js, containsString("state.$container;"));
344 assertThat(js, not(containsString("(.trim")));
345 assertThat(js, not(containsString("\\$")));
346 assertThat(js, not(containsString("${")));
347
348 assertI18nString(titleLabel, WIZARD_FORM_TITLE_FIELD_LABEL.getI18nValue());
349 assertI18nString(titlePlace, WIZARD_FORM_TITLE_FIELD_PLACEHOLDER.getI18nValue());
350 assertI18nString(preRender, WIZARD_FORM_PRE_RENDER_TEXT.getI18nValue());
351 assertI18nString(postRender, WIZARD_FORM_POST_RENDER_TEXT.getI18nValue());
352 assertI18nString(titleError, WIZARD_FORM_TITLE_FIELD_ERROR.getI18nValue());
353 }
354
355 @Test
356 public void eventListenerIsAdded() throws Exception
357 {
358 promptProps.put(EVENT_LISTENER_PROMPT, true);
359 buildBlueprintProperties();
360
361
362 String packageName = "com.atlassian.confluence.plugins.foo_print";
363 String className = "BlueprintCreatedListener";
364 ClassId classId = ClassId.packageAndClass(packageName, className);
365 ComponentDeclaration component = getComponentOfClass(classId);
366 assertThat(component.getKey(), is("blueprint-created-listener"));
367 assertThat(component.getName().get(), is("Blueprint Created Event Listener"));
368
369
370 SourceFile sourceFile = getSourceFile(packageName, className);
371 assertThat(sourceFile.getContent(), containsString("package " + packageName + ";"));
372 assertThat(sourceFile.getContent(), containsString(PLUGIN_KEY));
373 }
374
375 private void assertWebResource(Element element, WebResourceProperties expectedResource)
376 {
377 assertNameBasedModuleProperties(element, expectedResource);
378
379 assertNodeText(element, "context[1]", expectedResource.getContexts().get(0));
380 assertNodeText(element, "context[2]", expectedResource.getContexts().get(1));
381
382 assertNodeText(element, "dependency", expectedResource.getDependencies().get(0));
383
384 assertNotNull(element.selectSingleNode("transformation"));
385 assertNodeText(element, "transformation[@extension='soy']/transformer/@key", "soyTransformer");
386 assertNodeText(element, "transformation[@extension='soy']/transformer/functions",
387 "com.atlassian.confluence.plugins.soy:soy-core-functions");
388
389
390 if (expectedResource.getTransformations().size() == 2)
391 {
392 assertNodeText(element, "transformation[@extension='js']/transformer/@key", "jsI18n");
393 }
394 }
395
396 private void assertNameBasedModuleProperties(Element element, AbstractNameBasedModuleProperties props)
397 {
398 assertNodeText(element, "@key", props.getModuleKey());
399 assertNodeText(element, "@name", props.getModuleName());
400 assertNodeText(element, "@i18n-name-key", props.getNameI18nKey());
401 assertNodeText(element, "description/@key", props.getDescriptionI18nKey());
402 assertNodeText(element, "description", props.getDescription());
403 }
404
405
406 @Override
407 protected PluginProjectChangeset getChangesetForModule() throws Exception
408 {
409 if (changeset == null)
410 {
411 changeset = super.getChangesetForModule();
412 }
413 return changeset;
414 }
415
416 private void assertNodeText(Element element, String nodePath, String expectedText)
417 {
418 assertEquals(expectedText, getText(element, nodePath));
419 }
420
421 private String getText(Element element, String nodePath)
422 {
423 Node node = element.selectSingleNode(nodePath);
424 assertNotNull("Couldn't find node with path: " + nodePath, node);
425 return node.getText();
426 }
427
428
429 private void assertI18nString(String i18nKey, String value) throws Exception
430 {
431 getI18nString(i18nKey, value);
432 }
433 }