Clover icon

Magnolia REST Content Delivery 2.0-rc1

  1. Project Clover database Mon Oct 30 2017 16:36:57 CET
  2. Package info.magnolia.rest.delivery.jcr

File QueryBuilderTest.java

 

Code metrics

0
183
30
1
569
379
30
0.16
6.1
30
1

Classes

Class Line # Actions
QueryBuilderTest 70 183 0% 30 0
1.0100%
 

Contributing tests

This file is covered by 28 tests. .

Source view

1    /**
2    * This file Copyright (c) 2017 Magnolia International
3    * Ltd. (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10    * This file is distributed in the hope that it will be
11    * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12    * implied warranty of MERCHANTABILITY or FITNESS FOR A
13    * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14    * Redistribution, except as permitted by whichever of the GPL
15    * or MNA you select, is prohibited.
16    *
17    * 1. For the GPL license (GPL), you can redistribute and/or
18    * modify this file under the terms of the GNU General
19    * Public License, Version 3, as published by the Free Software
20    * Foundation. You should have received a copy of the GNU
21    * General Public License, Version 3 along with this program;
22    * if not, write to the Free Software Foundation, Inc., 51
23    * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24    *
25    * 2. For the Magnolia Network Agreement (MNA), this file
26    * and the accompanying materials are made available under the
27    * terms of the MNA which accompanies this distribution, and
28    * is available at http://www.magnolia-cms.com/mna.html
29    *
30    * Any modifications to this file must keep this entire header
31    * intact.
32    *
33    */
34    package info.magnolia.rest.delivery.jcr;
35   
36    import static info.magnolia.rest.delivery.jcr.FilteringCondition.JCR_OFFSET_DATE_TIME;
37    import static info.magnolia.test.hamcrest.ExceptionMatcher.instanceOf;
38    import static info.magnolia.test.hamcrest.ExecutionMatcher.throwsAnException;
39    import static org.hamcrest.CoreMatchers.*;
40    import static org.junit.Assert.*;
41   
42    import info.magnolia.context.MgnlContext;
43    import info.magnolia.jcr.RuntimeRepositoryException;
44    import info.magnolia.jcr.util.NodeTypes;
45    import info.magnolia.jcr.util.PropertiesImportExport;
46    import info.magnolia.repository.RepositoryConstants;
47    import info.magnolia.test.RepositoryTestCase;
48   
49    import java.time.LocalDate;
50    import java.time.ZoneId;
51    import java.time.ZonedDateTime;
52    import java.time.format.DateTimeFormatter;
53    import java.util.Arrays;
54    import java.util.Calendar;
55    import java.util.GregorianCalendar;
56    import java.util.HashMap;
57    import java.util.List;
58    import java.util.Map;
59   
60    import javax.jcr.Node;
61    import javax.jcr.NodeIterator;
62    import javax.jcr.Session;
63    import javax.jcr.Workspace;
64    import javax.jcr.query.Query;
65    import javax.jcr.query.QueryResult;
66   
67    import org.junit.Before;
68    import org.junit.Test;
69   
 
70    public class QueryBuilderTest extends RepositoryTestCase {
71   
72    private Session session;
73    private Workspace workspace;
74   
 
75  28 toggle @Before
76    public void setUp() throws Exception {
77  28 super.setUp();
78  28 session = MgnlContext.getJCRSession(RepositoryConstants.WEBSITE);
79  28 new PropertiesImportExport().createNodes(session.getRootNode(), getClass().getClassLoader().getResourceAsStream("travel-test-data.properties"));
80  28 session.save();
81   
82  28 workspace = session.getWorkspace();
83    }
84   
 
85  1 toggle @Test
86    public void listNodes() throws Exception {
87    // WHEN
88  1 Query query = QueryBuilder.inWorkspace(workspace)
89    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
90    .build();
91  1 QueryResult queryResult = query.execute();
92  1 NodeIterator nodeIterator = queryResult.getNodes();
93   
94    // THEN
95  1 assertNotNull(nodeIterator);
96  1 assertEquals(3, nodeIterator.getSize());
97  1 assertEquals("about", nodeIterator.nextNode().getName());
98  1 assertEquals("company", nodeIterator.nextNode().getName());
99  1 assertEquals("travel", nodeIterator.nextNode().getName());
100    }
101   
 
102  1 toggle @Test
103    public void orderByOneProperty() throws Exception {
104    // WHEN
105  1 Query query = QueryBuilder.inWorkspace(workspace)
106    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
107    .orderBy(Arrays.asList("@name desc"))
108    .build();
109   
110    // THEN
111  1 assertThat(query.getStatement(), endsWith("ORDER BY LOWER(NAME(t)) DESC"));
112    }
113   
 
114  1 toggle @Test
115    public void orderByTwoProperties() throws Exception {
116    // WHEN
117  1 Query query = QueryBuilder.inWorkspace(workspace)
118    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
119    .orderBy(Arrays.asList("mgnl:lastModified desc", "@name desc"))
120    .build();
121   
122    // THEN
123  1 assertThat(query.getStatement(), endsWith("ORDER BY t.[mgnl:lastModified] DESC, LOWER(NAME(t)) DESC"));
124    }
125   
 
126  1 toggle @Test
127    public void listNodesWithRootPath() throws Exception {
128    // WHEN
129  1 Query query = QueryBuilder.inWorkspace(workspace)
130    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
131    .rootPath("/travel")
132    .build();
133  1 QueryResult queryResult = query.execute();
134  1 NodeIterator nodeIterator = queryResult.getNodes();
135   
136    // THEN
137  1 assertNotNull(nodeIterator);
138  1 assertEquals(2, nodeIterator.getSize());
139  1 assertEquals("about", nodeIterator.nextNode().getName());
140  1 assertEquals("company", nodeIterator.nextNode().getName());
141    }
142   
 
143  1 toggle @Test
144    public void listNodesWithOffset() throws Exception {
145    // WHEN
146  1 Query query = QueryBuilder.inWorkspace(workspace)
147    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
148    .offset(1)
149    .build();
150  1 QueryResult queryResult = query.execute();
151  1 NodeIterator nodeIterator = queryResult.getNodes();
152   
153    // THEN
154  1 assertNotNull(nodeIterator);
155  1 assertEquals(2, nodeIterator.getSize());
156  1 assertEquals("company", nodeIterator.nextNode().getName());
157  1 assertEquals("travel", nodeIterator.nextNode().getName());
158    }
159   
 
160  1 toggle @Test
161    public void listNodesWithLimit() throws Exception {
162    // WHEN
163  1 Query query = QueryBuilder.inWorkspace(workspace)
164    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
165    .limit(2)
166    .build();
167  1 QueryResult queryResult = query.execute();
168  1 NodeIterator nodeIterator = queryResult.getNodes();
169   
170    // THEN
171  1 assertNotNull(nodeIterator);
172  1 assertEquals(2, nodeIterator.getSize());
173  1 assertEquals("about", nodeIterator.nextNode().getName());
174  1 assertEquals("company", nodeIterator.nextNode().getName());
175    }
176   
 
177  1 toggle @Test
178    public void listNodesWithOffsetAndLimit() throws Exception {
179    // WHEN
180  1 Query query = QueryBuilder.inWorkspace(workspace)
181    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
182    .offset(1)
183    .limit(1)
184    .build();
185  1 QueryResult queryResult = query.execute();
186  1 NodeIterator nodeIterator = queryResult.getNodes();
187   
188    // THEN
189  1 assertNotNull(nodeIterator);
190  1 assertEquals(1, nodeIterator.getSize());
191  1 assertEquals("company", nodeIterator.nextNode().getName());
192    }
193   
 
194  1 toggle @Test
195    public void listingNodesShouldNotReturnFolders() throws Exception {
196    // GIVEN
197  1 session.getRootNode().addNode("thisIsAFolder", NodeTypes.Folder.NAME);
198   
199    // WHEN
200  1 Query query = QueryBuilder.inWorkspace(workspace)
201    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME, NodeTypes.Folder.NAME))
202    .build();
203  1 QueryResult queryResult = query.execute();
204  1 NodeIterator nodeIterator = queryResult.getNodes();
205   
206    // THEN
207  1 assertNotNull(nodeIterator);
208  1 assertEquals(3, nodeIterator.getSize());
209  1 assertEquals("about", nodeIterator.nextNode().getName());
210  1 assertEquals("company", nodeIterator.nextNode().getName());
211  1 assertEquals("travel", nodeIterator.nextNode().getName());
212    }
213   
 
214  1 toggle @Test
215    public void searchForNodeByName() throws Exception {
216    // WHEN
217  1 Query query = QueryBuilder.inWorkspace(workspace)
218    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
219    .keyword("travel")
220    .build();
221  1 QueryResult queryResult = query.execute();
222  1 NodeIterator nodeIterator = queryResult.getNodes();
223   
224    // THEN
225  1 assertThatTravelNodeExists(nodeIterator);
226    }
227   
 
228  1 toggle @Test
229    public void searchForNodeByAbsolutePath() throws Exception {
230    // WHEN
231  1 Query query = QueryBuilder.inWorkspace(workspace)
232    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME, NodeTypes.Component.NAME))
233    .keyword("/travel/about/company")
234    .build();
235  1 QueryResult queryResult = query.execute();
236  1 NodeIterator nodeIterator = queryResult.getNodes();
237   
238    // THEN
239  1 assertNotNull(nodeIterator);
240  1 assertEquals(1, nodeIterator.getSize());
241  1 assertEquals("company", nodeIterator.nextNode().getName());
242    }
243   
 
244  1 toggle @Test
245    public void searchingForSomethingReturnsNothing() throws Exception {
246    // WHEN
247  1 Query query = QueryBuilder.inWorkspace(workspace)
248    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME, NodeTypes.Component.NAME))
249    .keyword("something")
250    .build();
251  1 QueryResult queryResult = query.execute();
252  1 NodeIterator nodeIterator = queryResult.getNodes();
253   
254    // THEN
255  1 assertNotNull(nodeIterator);
256  1 assertEquals(0, nodeIterator.getSize());
257    }
258   
 
259  1 toggle @Test
260    public void searchForAPageContainingUnicode() throws Exception {
261    // GIVEN
262  1 String unicodeNodeName = "sài-gòn";
263  1 session.getRootNode().addNode(unicodeNodeName, NodeTypes.Page.NAME);
264  1 session.save();
265   
266    // WHEN
267  1 Query query = QueryBuilder.inWorkspace(workspace)
268    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
269    .keyword(unicodeNodeName)
270    .build();
271  1 QueryResult queryResult = query.execute();
272  1 NodeIterator nodeIterator = queryResult.getNodes();
273   
274    // THEN
275  1 assertNotNull(nodeIterator);
276  1 assertEquals(1, nodeIterator.getSize());
277  1 assertEquals(unicodeNodeName, nodeIterator.nextNode().getName());
278    }
279   
 
280  1 toggle @Test
281    public void searchForQuotedTextToMakeSureItIsEscapedProperly() throws Exception {
282    // GIVEN
283  1 String quotedTextValue = "'text between quotes'";
284  1 session.getNode("/travel").setProperty("quotedText", quotedTextValue);
285  1 session.save();
286   
287    // WHEN
288  1 Query query = QueryBuilder.inWorkspace(workspace)
289    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
290    .keyword(quotedTextValue)
291    .build();
292  1 QueryResult queryResult = query.execute();
293  1 NodeIterator nodeIterator = queryResult.getNodes();
294   
295    // THEN
296  1 assertThatTravelNodeExists(nodeIterator);
297    }
298   
 
299  1 toggle @Test
300    public void filterWithEqualBoolean() throws Exception {
301    // GIVEN
302  1 Node travel = session.getNode("/travel");
303  1 travel.setProperty("available", true);
304  1 Node about = session.getNode("/travel/about");
305  1 about.setProperty("available", false);
306  1 session.save();
307   
308  1 Map<String, List<String>> filteringConditions = new HashMap<>();
309  1 filteringConditions.put("available", Arrays.asList("true"));
310   
311    // WHEN
312  1 Query query = QueryBuilder.inWorkspace(workspace)
313    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
314    .conditions(filteringConditions)
315    .build();
316  1 QueryResult queryResult = query.execute();
317  1 NodeIterator nodeIterator = queryResult.getNodes();
318   
319  1 assertNotNull(nodeIterator);
320  1 assertEquals(1, nodeIterator.getSize());
321  1 assertEquals("travel", nodeIterator.nextNode().getName());
322    }
323   
 
324  1 toggle @Test
325    public void filterWithEqualNumber() throws Exception {
326    // GIVEN
327  1 Node travel = session.getNode("/travel");
328  1 travel.setProperty("tourists", 20);
329  1 Node about = session.getNode("/travel/about");
330  1 about.setProperty("tourists", 10);
331  1 session.save();
332   
333  1 Map<String, List<String>> filteringConditions = new HashMap<>();
334  1 filteringConditions.put("tourists", Arrays.asList("20"));
335   
336    // WHEN
337  1 Query query = QueryBuilder.inWorkspace(workspace)
338    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
339    .conditions(filteringConditions)
340    .build();
341  1 QueryResult queryResult = query.execute();
342  1 NodeIterator nodeIterator = queryResult.getNodes();
343   
344    // THEN
345  1 assertThatTravelNodeExists(nodeIterator);
346    }
347   
 
348  1 toggle @Test
349    public void filterWithEqualString() throws Exception {
350    // GIVEN
351  1 Node travel = session.getNode("/travel");
352  1 travel.setProperty("motto", "If you believe, you can achieve.");
353  1 Node about = session.getNode("/travel/about");
354  1 about.setProperty("motto", "Feel the fear and do it anyway.");
355  1 session.save();
356   
357  1 Map<String, List<String>> filteringConditions = new HashMap<>();
358  1 filteringConditions.put("motto", Arrays.asList("If you believe, you can achieve."));
359   
360    // WHEN
361  1 Query query = QueryBuilder.inWorkspace(workspace)
362    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
363    .conditions(filteringConditions)
364    .build();
365  1 QueryResult queryResult = query.execute();
366  1 NodeIterator nodeIterator = queryResult.getNodes();
367   
368  1 assertNotNull(nodeIterator);
369  1 assertEquals(1, nodeIterator.getSize());
370  1 assertEquals("travel", nodeIterator.nextNode().getName());
371    }
372   
 
373  1 toggle @Test
374    public void filterWithParamWhoseNameContainsColon() throws Exception {
375    // GIVEN
376  1 session.getNode("/travel").setProperty(NodeTypes.Created.CREATED_BY, "superuser");
377  1 session.save();
378  1 Map<String, List<String>> filteringConditions = new HashMap<>();
379  1 filteringConditions.put(NodeTypes.Created.CREATED_BY, Arrays.asList("superuser"));
380   
381    // WHEN
382  1 Query query = QueryBuilder.inWorkspace(workspace)
383    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
384    .conditions(filteringConditions)
385    .build();
386  1 QueryResult queryResult = query.execute();
387  1 NodeIterator nodeIterator = queryResult.getNodes();
388   
389    // THEN
390  1 assertThatTravelNodeExists(nodeIterator);
391    }
392   
 
393  1 toggle @Test
394    public void filterByIsoDateTime() throws Exception {
395    // GIVEN
396   
397    // Update lastModified of "travel".
398  1 ZonedDateTime expectedDate = ZonedDateTime.of(2015, 1, 26, 23, 17, 2, 0, ZoneId.systemDefault());
399  1 String expectedDateString = JCR_OFFSET_DATE_TIME.format(expectedDate);
400   
401  1 Calendar calendar = GregorianCalendar.from(expectedDate);
402  1 NodeTypes.LastModified.update(session.getNode("/travel"), calendar);
403  1 session.save();
404   
405    // Prepare filteringConditions.
406  1 Map<String, List<String>> filteringConditions = new HashMap<>();
407  1 filteringConditions.put(NodeTypes.LastModified.NAME, Arrays.asList(expectedDateString));
408   
409    // WHEN
410  1 Query query = QueryBuilder.inWorkspace(workspace)
411    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
412    .conditions(filteringConditions)
413    .build();
414  1 QueryResult queryResult = query.execute();
415  1 NodeIterator nodeIterator = queryResult.getNodes();
416   
417    // THEN
418  1 assertThatTravelNodeExists(nodeIterator);
419    }
420   
 
421  1 toggle @Test
422    public void filterByIsoLocalDate() throws Exception {
423    // GIVEN
424   
425    // Update lastModified of "travel".
426  1 String dateStr = "2015-01-26";
427  1 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
428  1 LocalDate localDate = LocalDate.parse(dateStr, dateTimeFormatter);
429  1 ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
430  1 Calendar calendar = GregorianCalendar.from(zonedDateTime);
431  1 NodeTypes.LastModified.update(session.getNode("/travel"), calendar);
432  1 session.save();
433   
434    // Prepare filteringConditions.
435  1 Map<String, List<String>> filteringConditions = new HashMap<>();
436  1 filteringConditions.put(NodeTypes.LastModified.NAME, Arrays.asList(dateStr));
437   
438    // WHEN
439  1 Query query = QueryBuilder.inWorkspace(workspace)
440    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
441    .conditions(filteringConditions)
442    .build();
443  1 QueryResult queryResult = query.execute();
444  1 NodeIterator nodeIterator = queryResult.getNodes();
445   
446    // THEN
447  1 assertThatTravelNodeExists(nodeIterator);
448    }
449   
 
450  1 toggle @Test
451    public void fullTextExpressionContainingJcrIllegalCharsShouldBeEscapedForLikeOperator() throws Exception {
452    // GIVEN
453  1 String keyword = "test%/:[]*|\t\n";
454   
455    // WHEN
456  1 Query query = QueryBuilder.inWorkspace(workspace)
457    .keyword(keyword)
458    .build();
459   
460    // THEN
461  1 assertThat(query.getStatement(), endsWith("LOWER(LOCALNAME(t)) LIKE 'test%25%2F%3A%5B%5D%2A%7C%09%0A%' OR CONTAINS(t.*, 'test%/:\\[\\]*|') ORDER BY LOWER(NAME(t))"));
462    }
463   
 
464  1 toggle @Test
465    public void fullTextExpressionContainingSingleQuoteShouldBeEscaped() throws Exception {
466    // GIVEN
467  1 String keyword = "'text'";
468   
469    // WHEN
470  1 Query query = QueryBuilder.inWorkspace(workspace)
471    .keyword(keyword)
472    .build();
473   
474    // THEN
475  1 assertThat(query.getStatement(), endsWith("LOWER(LOCALNAME(t)) LIKE '''text''%' OR CONTAINS(t.*, '''text''') ORDER BY LOWER(NAME(t))"));
476    }
477   
 
478  1 toggle @Test
479    public void filterValueContainingSingleQuoteShouldBeEscaped() throws Exception {
480    // GIVEN
481  1 Map<String, List<String>> filteringConditions = new HashMap<>();
482  1 filteringConditions.put("property", Arrays.asList("value'"));
483   
484    // WHEN
485  1 Query query = QueryBuilder.inWorkspace(workspace)
486    .conditions(filteringConditions)
487    .build();
488   
489    // THEN
490  1 assertThat(query.getStatement(), containsString("t.property = 'value'''"));
491    }
492   
 
493  1 toggle @Test
494    public void filterPropertyContainingSingleQuoteShouldBeEscaped() throws Exception {
495    // GIVEN
496  1 Map<String, List<String>> filteringConditions = new HashMap<>();
497  1 filteringConditions.put("property'", Arrays.asList("value"));
498   
499    // WHEN
500  1 Query query = QueryBuilder.inWorkspace(workspace)
501    .conditions(filteringConditions)
502    .build();
503   
504    // THEN
505  1 assertThat(query.getStatement(), containsString("t.property = 'value'"));
506    }
507   
 
508  1 toggle @Test
509    public void filterPropertyContainingBracketThrowsException() throws Exception {
510    // GIVEN
511  1 Map<String, List<String>> filteringConditions = new HashMap<>();
512  1 filteringConditions.put("property]", Arrays.asList("value"));
513   
514    // WHEN & THEN
515  1 assertThat(() -> QueryBuilder.inWorkspace(workspace).conditions(filteringConditions).build(),
516    throwsAnException(instanceOf(RuntimeRepositoryException.class)
517    .withMessage(containsString("javax.jcr.query.InvalidQueryException"))));
518    }
519   
 
520  1 toggle @Test
521    public void orderByClauseContainingBracketThrowsException() throws Exception {
522  1 assertThat(() -> QueryBuilder.inWorkspace(workspace).orderBy(Arrays.asList("test] desc")).build(),
523    throwsAnException(instanceOf(RuntimeRepositoryException.class)
524    .withMessage(containsString("javax.jcr.query.InvalidQueryException"))));
525    }
526   
 
527  1 toggle @Test
528    public void orderByClauseContainsSingleQuoteThrowsException() throws Exception {
529  1 assertThat(() -> QueryBuilder.inWorkspace(workspace).orderBy(Arrays.asList("test''desc")).build(),
530    throwsAnException(instanceOf(RuntimeRepositoryException.class)
531    .withMessage(containsString("javax.jcr.query.InvalidQueryException"))));
532    }
533   
 
534  1 toggle @Test
535    public void filterByMultiValueProperty() throws Exception {
536    // GIVEN
537  1 Map<String, List<String>> filteringConditions = new HashMap<>();
538  1 filteringConditions.put("title", Arrays.asList("first", "second"));
539   
540    // WHEN
541  1 Query query = QueryBuilder.inWorkspace(workspace)
542    .conditions(filteringConditions)
543    .build();
544   
545    // THEN
546  1 assertThat(query.getStatement(), containsString("SELECT t.* FROM [nt:base] AS t WHERE t.title = 'first' AND t.title = 'second' ORDER BY LOWER(NAME(t))"));
547    }
548   
 
549  1 toggle @Test
550    public void filterByPropertyHavingOrOperator() throws Exception {
551    // GIVEN
552  1 Map<String, List<String>> filteringConditions = new HashMap<>();
553  1 filteringConditions.put("title", Arrays.asList("this|that"));
554   
555    // WHEN
556  1 Query query = QueryBuilder.inWorkspace(workspace)
557    .conditions(filteringConditions)
558    .build();
559   
560    // THEN
561  1 assertThat(query.getStatement(), containsString("SELECT t.* FROM [nt:base] AS t WHERE t.title = 'this' OR t.title = 'that' ORDER BY LOWER(NAME(t))"));
562    }
563   
 
564  6 toggle private static void assertThatTravelNodeExists(NodeIterator nodeIterator) throws Exception {
565  6 assertNotNull(nodeIterator);
566  6 assertEquals(1, nodeIterator.getSize());
567  6 assertEquals("travel", nodeIterator.nextNode().getName());
568    }
569    }