View Javadoc
1   package com.atlassian.plugin.web.descriptors;
2   
3   import com.atlassian.plugin.Plugin;
4   import com.atlassian.plugin.PluginParseException;
5   import com.atlassian.plugin.web.Condition;
6   import com.atlassian.plugin.web.conditions.ConditionLoadingException;
7   import org.dom4j.Document;
8   import org.dom4j.DocumentException;
9   import org.dom4j.DocumentHelper;
10  import org.junit.Rule;
11  import org.junit.Test;
12  import org.junit.rules.ExpectedException;
13  import org.mockito.Mockito;
14  
15  import static org.junit.Assert.assertEquals;
16  
17  public class TestConditionElementParser {
18      private static final String TYPE_OR = "<conditions type=\"OR\">";
19      private static final String TYPE_AND = "<conditions type=\"AND\">";
20      private static final String TYPE_CLOSE = "</conditions>";
21      private static final String FALSE = "<condition class=\"com.atlassian.plugin.web.conditions.NeverDisplayCondition\" />";
22      private static final String TRUE = "<condition class=\"com.atlassian.plugin.web.conditions.AlwaysDisplayCondition\" />";
23      private static final String NOT_FALSE = "<condition class=\"com.atlassian.plugin.web.conditions.NeverDisplayCondition\" invert=\"true\" />";
24      private static final String NOT_TRUE = "<condition class=\"com.atlassian.plugin.web.conditions.AlwaysDisplayCondition\" invert=\"true\" />";
25  
26      private final ConditionElementParser conditionElementParser = new ConditionElementParser(new ConditionElementParser.ConditionFactory() {
27          public Condition create(String className, Plugin plugin) throws ConditionLoadingException {
28              return new MockWebFragmentHelper().loadCondition(className, plugin);
29          }
30      });
31  
32      @Rule
33      public ExpectedException expectedException = ExpectedException.none();
34  
35      @Test
36      public void testSimple() throws DocumentException, PluginParseException {
37          assertConditions(TRUE, true); //true
38          assertConditions(FALSE, false); //false
39          assertConditions(NOT_TRUE, false); //NOT true = false
40          assertConditions(NOT_FALSE, true); //NOT false = true
41      }
42  
43      @Test
44      public void testAnd() throws DocumentException, PluginParseException {
45          //using the condition elements only (by default they are grouped with AND operator)
46          assertConditions(TRUE + TRUE, true);//true AND true = true
47          assertConditions(TRUE + FALSE, false);//true AND false = false
48          assertConditions(FALSE + TRUE, false);//false AND true = false
49          assertConditions(FALSE + FALSE, false);//false AND false = false
50  
51          //using the conditions element and explicitly specifying the AND operator
52          assertConditions(TYPE_AND + TRUE + TRUE + TYPE_CLOSE, true);//true AND true = true
53          assertConditions(TYPE_AND + TRUE + FALSE + TYPE_CLOSE, false);//true AND false = false
54          assertConditions(TYPE_AND + FALSE + TRUE + TYPE_CLOSE, false);//false AND true = false
55          assertConditions(TYPE_AND + FALSE + FALSE + TYPE_CLOSE, false);//false AND false = false
56      }
57  
58      @Test
59      public void testOr() throws DocumentException, PluginParseException {
60          assertConditions(TYPE_OR + TRUE + TRUE + TYPE_CLOSE, true);//true OR true = true
61          assertConditions(TYPE_OR + TRUE + FALSE + TYPE_CLOSE, true);//true OR false = true
62          assertConditions(TYPE_OR + FALSE + TRUE + TYPE_CLOSE, true);//false OR true = true
63          assertConditions(TYPE_OR + FALSE + FALSE + TYPE_CLOSE, false);//false OR false = false
64      }
65  
66      //test nested AND's - normally all nested AND's should be a single AND
67      @Test
68      public void testNestedAnd() throws DocumentException, PluginParseException {
69          //nested AND'ed conditions
70          assertConditions(TYPE_AND +
71                  TYPE_AND + TRUE + TRUE + TYPE_CLOSE +
72                  TYPE_AND + TRUE + TRUE + TYPE_CLOSE +
73                  TYPE_CLOSE, true);//(true AND true) AND (true AND true) = true
74  
75          //same as above but without explicit AND
76          assertConditions(TYPE_AND + TRUE + TRUE + TYPE_CLOSE +
77                  TYPE_AND + TRUE + TRUE + TYPE_CLOSE, true);//(true AND true) AND (true AND true) = true
78  
79          assertConditions(TYPE_AND +
80                  TYPE_AND + TRUE + TRUE + TYPE_CLOSE +
81                  TYPE_AND + FALSE + TRUE + TYPE_CLOSE +
82                  TYPE_CLOSE, false);//(true AND true) AND (false AND true) = false
83      }
84  
85      //test nested OR's - normally all nested OR's should be a single OR
86      @Test
87      public void testNestedOr() throws DocumentException, PluginParseException {
88          //nested OR'ed conditions
89          assertConditions(TYPE_OR +
90                  TYPE_OR + FALSE + FALSE + TYPE_CLOSE +
91                  TYPE_OR + FALSE + TRUE + TYPE_CLOSE +
92                  TYPE_CLOSE, true);//(false OR false) OR (false OR true) = true
93  
94          assertConditions(TYPE_OR +
95                  TYPE_OR + FALSE + FALSE + TYPE_CLOSE +
96                  TYPE_OR + FALSE + FALSE + TYPE_CLOSE +
97                  TYPE_CLOSE, false);//(false OR false) OR (false OR false) = false
98      }
99  
100     @Test
101     public void testNestedMix() throws DocumentException, PluginParseException {
102         //AND with nested OR conditions
103         assertConditions(TYPE_AND +
104                 TYPE_OR + FALSE + FALSE + TYPE_CLOSE +
105                 TYPE_OR + FALSE + TRUE + TYPE_CLOSE +
106                 TYPE_CLOSE, false);//(false OR false) AND (false OR true) = false
107 
108         assertConditions(TYPE_AND +
109                 TYPE_OR + TRUE + FALSE + TYPE_CLOSE +
110                 TYPE_OR + FALSE + TRUE + TYPE_CLOSE +
111                 TYPE_CLOSE, true);//(true OR false) AND (false OR true) = true
112 
113         //OR with nested AND conditions
114         assertConditions(TYPE_OR +
115                 TYPE_AND + FALSE + FALSE + TYPE_CLOSE +
116                 TYPE_AND + FALSE + TRUE + TYPE_CLOSE +
117                 TYPE_CLOSE, false);//(false AND false) OR (false AND true) = false
118 
119         assertConditions(TYPE_OR +
120                 TYPE_AND + FALSE + FALSE + TYPE_CLOSE +
121                 TYPE_AND + TRUE + TRUE + TYPE_CLOSE +
122                 TYPE_CLOSE, true);//(false AND false) OR (true AND true) = true
123     }
124 
125     @Test
126     public void testComplex() throws DocumentException, PluginParseException {
127         assertConditions(TRUE +
128                 TYPE_OR +
129                 TYPE_AND +
130                 FALSE + FALSE +
131                 TYPE_CLOSE +
132                 FALSE +
133                 TYPE_AND +
134                 TRUE +
135                 TYPE_OR +
136                 FALSE + TRUE +
137                 TYPE_CLOSE +
138                 TYPE_CLOSE +
139                 TYPE_CLOSE, true);//true AND ((false AND false) OR false OR (true AND (false OR true))) = true
140     }
141 
142     @Test
143     public void testThatClassAttributeIsCheckedFor() throws DocumentException {
144         expectedException.expect(PluginParseException.class);
145         expectedException.expectMessage("Condition element must specify a class attribute");
146         buildConditionFromXml("<condition/>");
147     }
148 
149     private void assertConditions(String conditionElement, boolean expectedResult) throws DocumentException, PluginParseException {
150         Condition condition = buildConditionFromXml(conditionElement);
151         assertEquals(expectedResult, condition.shouldDisplay(null));
152     }
153 
154     private Condition buildConditionFromXml(String conditionElement) throws DocumentException {
155         String rootElement = "<root>" + conditionElement + "</root>";
156         Document document = DocumentHelper.parseText(rootElement);
157 
158         return conditionElementParser.makeConditions(Mockito.mock(Plugin.class), document
159                 .getRootElement(), ConditionElementParser.CompositeType.AND);
160     }
161 }