View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.uif.widget;
17  
18  import com.google.common.collect.Lists;
19  import org.junit.AfterClass;
20  import org.junit.Before;
21  import org.junit.BeforeClass;
22  import org.junit.Test;
23  import org.kuali.rice.core.api.config.property.ConfigurationService;
24  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
25  import org.kuali.rice.krad.datadictionary.validation.Employee;
26  import org.kuali.rice.krad.lookup.LookupView;
27  import org.kuali.rice.krad.uif.UifConstants;
28  import org.kuali.rice.krad.uif.component.Component;
29  import org.kuali.rice.krad.uif.container.CollectionGroup;
30  import org.kuali.rice.krad.uif.container.CollectionGroupBase;
31  import org.kuali.rice.krad.uif.container.Group;
32  import org.kuali.rice.krad.uif.container.GroupBase;
33  import org.kuali.rice.krad.uif.field.DataField;
34  import org.kuali.rice.krad.uif.field.DataFieldBase;
35  import org.kuali.rice.krad.uif.field.InputFieldBase;
36  import org.kuali.rice.krad.uif.layout.TableLayoutManager;
37  import org.kuali.rice.krad.uif.layout.TableLayoutManagerBase;
38  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
39  import org.kuali.rice.krad.uif.service.ViewHelperService;
40  import org.kuali.rice.krad.uif.util.CopyUtils;
41  import org.kuali.rice.krad.uif.util.UifUnitTestUtils;
42  import org.kuali.rice.krad.web.form.UifFormBase;
43  
44  import java.util.ArrayList;
45  import java.util.HashMap;
46  import java.util.HashSet;
47  import java.util.List;
48  import java.util.Map;
49  import java.util.Set;
50  
51  import static org.junit.Assert.assertEquals;
52  import static org.mockito.Mockito.*;
53  
54  /**
55   * test the RichTable widget
56   */
57  
58  public class RichTableTest {
59  
60      public static final String S_TYPE = "{\"bSortable\": false,\"sType\": \"numeric\",\"sSortDataType\": \"dom-text\",\"aTargets\": [0]}";
61      public static final String S_SORT_DATA_TARGETS_1 = "{\"sType\": \"string\",\"sSortDataType\": \"dom-text\",\"aTargets\": [1]}";
62      public static final String S_SORT_DATA_TARGETS_2 = S_SORT_DATA_TARGETS_1.replace("1", "2");
63      public static final String S_SORT_DATA_TARGETS_3 = S_SORT_DATA_TARGETS_1.replace("1", "3");
64  
65      public static final String EXPECTED = S_TYPE + "," + S_SORT_DATA_TARGETS_1 + "," + S_SORT_DATA_TARGETS_2 + "," + S_SORT_DATA_TARGETS_3;
66  
67      public static final String B_VISIBLE_FALSE_TARGETS_1 = "{\"bVisible\": false,\"aTargets\": [1]}";
68      public static final String B_SORTABLE_FALSE_TARGETS_3 = "{\"bSortable\": false,\"aTargets\": [3]}";
69  
70      private RichTable richTable;
71      private CollectionGroup group;
72      private LookupView mockView;
73  
74      @BeforeClass
75      public static void setUpClass() throws Throwable {
76          UifUnitTestUtils.establishMockConfig("KRAD-RichTableTest");
77      }
78  
79      @AfterClass
80      public static void tearDownClass() throws Throwable {
81          GlobalResourceLoader.stop();
82      }
83  
84      //private
85      @Before
86      public void setup() throws Throwable {
87          richTable = new RichTable();
88  
89          richTable = spy(richTable);
90  
91          ConfigurationService configurationService = mock(ConfigurationService.class);
92          doReturn(configurationService).when(richTable).getConfigurationService();
93  
94          group = new CollectionGroupBase();
95          group.setCollectionObjectClass(Employee.class);
96  
97          TableLayoutManager layoutManager = new TableLayoutManagerBase();
98          layoutManager.setRenderSequenceField(true);
99  
100         List<Component> items = new ArrayList<Component>(1);
101         DataField name = new DataFieldBase();
102         name.setPropertyName("employeeId");
103         items.add(name);
104         DataField number = new DataFieldBase();
105         number.setPropertyName("positionTitle");
106         items.add(number);
107         DataField contactEmail = new DataFieldBase();
108         contactEmail.setPropertyName("contactEmail");
109         items.add(contactEmail);
110 
111         layoutManager = spy(layoutManager);
112         doReturn(items).when(layoutManager).getFirstRowFields();
113         doReturn(layoutManager).when(layoutManager).clone();
114 
115         group.setLayoutManager(layoutManager);
116         group.setIncludeLineSelectionField(false);
117         group.setRenderLineActions(false);
118 
119         group.setItems(items);
120 
121         mockView = mock(LookupView.class);
122         ViewHelperService mockViewHelperService = mock(ViewHelperService.class);
123         when(mockView.getViewHelperService()).thenReturn(mockViewHelperService);
124         when(mockView.clone()).thenReturn(mockView);
125     }
126 
127     @Test
128     /**
129      * test that without aoColumns being set explicitly, the default behaviour continues
130      */
131     public void testComponentOptionsDefault() throws Exception {
132         assertRichTableComponentOptions(null, "[" + EXPECTED + "]", UifConstants.TableToolsKeys.AO_COLUMN_DEFS);
133     }
134 
135     @Test
136     /**
137      * test that when aoColumns is explicitly set, it is integrated into the rich table rendering logic
138      */
139     public void testComponentOptionsAoColumnsJSOptions() throws Exception {
140         String innerColValues = "{bVisible: false}, null, null";
141         assertRichTableComponentOptions("[" + innerColValues + "]", "[" + EXPECTED + "," + innerColValues + "]",
142                 UifConstants.TableToolsKeys.AO_COLUMN_DEFS);
143     }
144 
145     @Test
146     /**
147      * test whether a hidden column, when marked as sortable is still hidden
148      */
149     public void testComponentOptionsHideColumnOnRichTable() {
150         Set<String> hiddenColumns = new HashSet<String>();
151         hiddenColumns.add("employeeId");
152         Set<String> sortableColumns = new HashSet<String>();
153         sortableColumns.add("positionTitle");
154         richTable.setSortableColumns(sortableColumns);
155         richTable.setHiddenColumns(hiddenColumns);
156         String expected = "[" + S_TYPE + "," +
157                 B_VISIBLE_FALSE_TARGETS_1 + "," +
158                 S_SORT_DATA_TARGETS_2 + "," +
159                 B_SORTABLE_FALSE_TARGETS_3 + "]";
160         assertRichTableComponentOptions(null, expected, UifConstants.TableToolsKeys.AO_COLUMN_DEFS);
161     }
162 
163     @Test
164     /**
165      * test that sortableColumns and hiddenColumns, when set on layoutManager, will not override those properties on the richTable
166      */
167     public void testComponentOptionsHideColumnOnLayoutManager() {
168         // set rich table properties
169         Set<String> richTableHiddenColumns = new HashSet<String>();
170         richTableHiddenColumns.add("employeeId");
171         Set<String> sortableColumns = new HashSet<String>();
172         sortableColumns.add("positionTitle");
173         richTable.setSortableColumns(sortableColumns);
174         richTable.setHiddenColumns(richTableHiddenColumns);
175         // set layout manager properties
176         Set<String> lmHiddenColumns = new HashSet<String>();
177         lmHiddenColumns.add("contactEmail");
178         Set<String> lmSortableColumns = new HashSet<String>();
179         lmSortableColumns.add("employeeId");
180         ((TableLayoutManager) group.getLayoutManager()).setSortableColumns(lmSortableColumns);
181         ((TableLayoutManager) group.getLayoutManager()).setHiddenColumns(lmHiddenColumns);
182         // Watch out for spaces
183         String expected = "[" + EXPECTED.replace(S_SORT_DATA_TARGETS_1 + ",", B_VISIBLE_FALSE_TARGETS_1 + ",") + "]";
184         expected = expected.replace(S_SORT_DATA_TARGETS_3, B_SORTABLE_FALSE_TARGETS_3);
185         assertRichTableComponentOptions(null, expected, UifConstants.TableToolsKeys.AO_COLUMN_DEFS);
186     }
187 
188     @Test
189     /**
190      * test that the default sort options, when set on the view, sort in the correct order
191      */
192     public void testComponentOptionsDefaultSort() {
193         when(mockView.isDefaultSortAscending()).thenReturn(false);
194         when(mockView.getDefaultSortAttributeNames()).thenReturn(Lists.newArrayList("employeeId", "contactEmail"));
195 
196         String expected = "[[1,'desc'],[3,'desc']]";
197         assertRichTableComponentOptions(null, expected, UifConstants.TableToolsKeys.AASORTING);
198     }
199 
200     @Test
201     /**
202      * test that the default sort options, when set on the view, sort in the correct order
203      */
204     public void testComponentOptionsDefaultSortReverse() {
205         when(mockView.isDefaultSortAscending()).thenReturn(false);
206         when(mockView.getDefaultSortAttributeNames()).thenReturn(Lists.newArrayList("contactEmail", "employeeId"));
207 
208         String expected = "[[3,'desc'],[1,'desc']]";
209         assertRichTableComponentOptions(null, expected, UifConstants.TableToolsKeys.AASORTING);
210     }
211 
212     @Test
213     /**
214      * test that the default sort options, when set on the view, sort in the correct order and in the correct position
215      * when no sequence column is added
216      */
217     public void testComponentOptionsDefaultSortWithoutSequence() {
218         when(mockView.isDefaultSortAscending()).thenReturn(false);
219         when(mockView.getDefaultSortAttributeNames()).thenReturn(Lists.newArrayList("employeeId", "contactEmail"));
220 
221         ((TableLayoutManager) group.getLayoutManager()).setRenderSequenceField(false);
222 
223         String expected = "[[0,'desc'],[2,'desc']]";
224         assertRichTableComponentOptions(null, expected, UifConstants.TableToolsKeys.AASORTING);
225     }
226 
227     @Test
228     /**
229      * test that the default sort options, when set on the view, sort in the correct order and in the correct position
230      * relative to the details column
231      */
232     public void testComponentOptionsDefaultSortWithDetails() {
233         when(mockView.isDefaultSortAscending()).thenReturn(false);
234         when(mockView.getDefaultSortAttributeNames()).thenReturn(Lists.newArrayList("employeeId", "contactEmail"));
235 
236         Group rowDetailsGroup = new GroupBase();
237         rowDetailsGroup.setItems(Lists.newArrayList(new InputFieldBase()));
238         ((TableLayoutManager) group.getLayoutManager()).setRowDetailsGroup(rowDetailsGroup);
239 
240         String expected = "[[2,'desc'],[4,'desc']]";
241         assertRichTableComponentOptions(null, expected, UifConstants.TableToolsKeys.AASORTING);
242     }
243 
244     @Test
245     /**
246      * test that the default sort options, when set on the view, sort in the correct order and in the correct position
247      * relative to the action column on the left
248      */
249     public void testComponentOptionsDefaultSortWithActionLeft() {
250         when(mockView.isDefaultSortAscending()).thenReturn(false);
251         when(mockView.getDefaultSortAttributeNames()).thenReturn(Lists.newArrayList("employeeId", "contactEmail"));
252 
253         group.setRenderLineActions(true);
254         ((TableLayoutManager) group.getLayoutManager()).setActionColumnPlacement("LEFT");
255 
256         String expected = "[[2,'desc'],[4,'desc']]";
257         assertRichTableComponentOptions(null, expected, UifConstants.TableToolsKeys.AASORTING);
258     }
259 
260     @Test
261     /**
262      * test that the default sort options, when set on the view, sort in the correct order and in the correct position
263      * relative to the action column on the right
264      */
265     public void testComponentOptionsDefaultSortWithActionRight() {
266         when(mockView.isDefaultSortAscending()).thenReturn(false);
267         when(mockView.getDefaultSortAttributeNames()).thenReturn(Lists.newArrayList("employeeId", "contactEmail"));
268 
269         group.setRenderLineActions(true);
270         ((TableLayoutManager) group.getLayoutManager()).setActionColumnPlacement("RIGHT");
271 
272         String expected = "[[1,'desc'],[3,'desc']]";
273         assertRichTableComponentOptions(null, expected, UifConstants.TableToolsKeys.AASORTING);
274     }
275 
276     @Test
277     /**
278      * test that the default sort options, when set on the view, sort in the correct order and in the correct position
279      * relative to the multiple columns on the left
280      */
281     public void testComponentOptionsDefaultSortWithMultipleColumns() {
282         when(mockView.isDefaultSortAscending()).thenReturn(false);
283         when(mockView.getDefaultSortAttributeNames()).thenReturn(Lists.newArrayList("employeeId", "contactEmail"));
284 
285         Group rowDetailsGroup = new GroupBase();
286         rowDetailsGroup.setItems(Lists.newArrayList(new InputFieldBase()));
287         ((TableLayoutManager) group.getLayoutManager()).setRowDetailsGroup(rowDetailsGroup);
288 
289         group.setRenderLineActions(true);
290         ((TableLayoutManager) group.getLayoutManager()).setActionColumnPlacement("LEFT");
291 
292         String expected = "[[3,'desc'],[5,'desc']]";
293         assertRichTableComponentOptions(null, expected, UifConstants.TableToolsKeys.AASORTING);
294     }
295 
296     @Test
297     /**
298      * test that the default sort options, when set on the view, sort in the correct order and in the correct position
299      * relative to the action column in the middle
300      */
301     public void testComponentOptionsDefaultSortWithActionMiddle() {
302         when(mockView.isDefaultSortAscending()).thenReturn(false);
303         when(mockView.getDefaultSortAttributeNames()).thenReturn(Lists.newArrayList("employeeId", "contactEmail"));
304 
305         group.setRenderLineActions(true);
306         ((TableLayoutManager) group.getLayoutManager()).setActionColumnPlacement("4");
307 
308         String expected = "[[1,'desc'],[4,'desc']]";
309         assertRichTableComponentOptions(null, expected, UifConstants.TableToolsKeys.AASORTING);
310     }
311 
312     /**
313      * a common method to test rich table options
314      *
315      * @param optionsOnGroup - a string in JSON format of the options set on the collection group
316      * @param optionsOnRichTable - a string in JSON format of the options set on the rich table
317      * @param optionKey - a string with the rich table option key being tested
318      */
319     private void assertRichTableComponentOptions(String optionsOnGroup, final String optionsOnRichTable,
320             final String optionKey) {
321 
322         Map<String, String> templateOptions = richTable.getTemplateOptions();
323         if (templateOptions == null) {
324             templateOptions = new HashMap<String, String>();
325         } else {
326             templateOptions = new HashMap<String, String>(templateOptions);
327         }
328 
329         templateOptions.put(optionKey, optionsOnGroup);
330         richTable.setTemplateOptions(templateOptions);
331 
332         ViewLifecycle.encapsulateLifecycle(mockView, null, null, new Runnable() {
333             @Override
334             public void run() {
335                 RichTable mutableRichTable = richTable.<RichTable>copy();
336                 mutableRichTable.performFinalize(new UifFormBase(), (Group) CopyUtils.copy(group));
337                 assertEquals(optionsOnRichTable, mutableRichTable.getTemplateOptions().get(optionKey));
338             }
339         });
340     }
341 }