Clover icon

Magnolia REST Content Delivery 2.1

  1. Project Clover database Fri Mar 16 2018 18:21:08 CET
  2. Package info.magnolia.rest.delivery.jcr

File QueryBuilderTest.java

 

Code metrics

0
87
28
1
441
268
28
0.32
3.11
28
1

Classes

Class Line # Actions
QueryBuilderTest 65 87 0% 28 0
1.0100%
 

Contributing tests

This file is covered by 27 tests. .

Source view

1    /**
2    * This file Copyright (c) 2017-2018 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.*;
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.assertThat;
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.LocalTime;
51    import java.time.ZoneId;
52    import java.time.ZonedDateTime;
53    import java.util.Arrays;
54    import java.util.HashMap;
55    import java.util.List;
56    import java.util.Map;
57   
58    import javax.jcr.Session;
59    import javax.jcr.Workspace;
60    import javax.jcr.query.Query;
61   
62    import org.junit.Before;
63    import org.junit.Test;
64   
 
65    public class QueryBuilderTest extends RepositoryTestCase {
66   
67    private Session session;
68    private Workspace workspace;
69   
 
70  27 toggle @Before
71    public void setUp() throws Exception {
72  27 super.setUp();
73  27 session = MgnlContext.getJCRSession(RepositoryConstants.WEBSITE);
74  27 new PropertiesImportExport().createNodes(session.getRootNode(), getClass().getClassLoader().getResourceAsStream("travel-test-data.properties"));
75  27 session.save();
76   
77  27 workspace = session.getWorkspace();
78    }
79   
 
80  1 toggle @Test
81    public void listNodes() throws Exception {
82    // WHEN
83  1 Query query = QueryBuilder.inWorkspace(workspace)
84    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
85    .build();
86   
87    // THEN
88  1 assertThat(query.getStatement(), equalTo("SELECT t.* FROM [nt:base] AS t WHERE t.[jcr:primaryType] = 'mgnl:page'"));
89    }
90   
 
91  1 toggle @Test
92    public void orderByOneProperty() throws Exception {
93    // WHEN
94  1 Query query = QueryBuilder.inWorkspace(workspace)
95    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
96    .orderBy(Arrays.asList("@name desc"))
97    .build();
98   
99    // THEN
100  1 assertThat(query.getStatement(), endsWith("ORDER BY LOWER(NAME(t)) DESC"));
101    }
102   
 
103  1 toggle @Test
104    public void orderByOnePropertyWithDefaultDirection() throws Exception {
105    // WHEN
106  1 Query query = QueryBuilder.inWorkspace(workspace)
107    .orderBy(Arrays.asList("title"))
108    .build();
109   
110    // THEN
111  1 assertThat(query.getStatement(), endsWith("ORDER BY t.title"));
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 orderByTwoPropertiesWithDefaultDirections() throws Exception {
128    // WHEN
129  1 Query query = QueryBuilder.inWorkspace(workspace)
130    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
131    .orderBy(Arrays.asList("mgnl:lastModified", "@name asc"))
132    .build();
133   
134    // THEN
135  1 assertThat(query.getStatement(), endsWith("ORDER BY t.[mgnl:lastModified], LOWER(NAME(t))"));
136    }
137   
 
138  1 toggle @Test
139    public void listNodesWithRootPath() throws Exception {
140    // WHEN
141  1 Query query = QueryBuilder.inWorkspace(workspace)
142    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
143    .rootPath("/travel")
144    .build();
145   
146    // THEN
147  1 assertThat(query.getStatement(), containsString("AND ISDESCENDANTNODE(t, [/travel])"));
148    }
149   
 
150  1 toggle @Test
151    public void foldersShouldNotIncludedInQuery() throws Exception {
152    // WHEN
153  1 Query query = QueryBuilder.inWorkspace(workspace)
154    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME, NodeTypes.Folder.NAME))
155    .build();
156   
157    // THEN
158  1 assertThat(query.getStatement(), equalTo("SELECT t.* FROM [nt:base] AS t WHERE t.[jcr:primaryType] = 'mgnl:page'"));
159    }
160   
 
161  1 toggle @Test
162    public void searchForNode() throws Exception {
163    // WHEN
164  1 Query query = QueryBuilder.inWorkspace(workspace)
165    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
166    .keyword("travel")
167    .build();
168   
169    // THEN
170  1 assertThat(query.getStatement(), containsString("AND (LOWER(LOCALNAME(t)) LIKE 'travel%' OR CONTAINS(t.*, 'travel'))"));
171    }
172   
 
173  1 toggle @Test
174    public void searchForNodeByAbsolutePath() throws Exception {
175    // WHEN
176  1 Query query = QueryBuilder.inWorkspace(workspace)
177    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME, NodeTypes.Component.NAME))
178    .keyword("/travel/about/company")
179    .build();
180   
181    // THEN
182  1 assertThat(query.getStatement(), containsString("AND ISSAMENODE(t, [/travel/about/company])"));
183    }
184   
 
185  1 toggle @Test
186    public void searchForAPageContainingUnicode() throws Exception {
187    // WHEN
188  1 Query query = QueryBuilder.inWorkspace(workspace)
189    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
190    .keyword("sài-gòn")
191    .build();
192   
193    // THEN
194  1 assertThat(query.getStatement(), containsString("(LOWER(LOCALNAME(t)) LIKE 'sài-gòn%' OR CONTAINS(t.*, 'sài-gòn'))"));
195    }
196   
 
197  1 toggle @Test
198    public void searchForQuotedTextToMakeSureItIsEscapedProperly() throws Exception {
199    // WHEN
200  1 Query query = QueryBuilder.inWorkspace(workspace)
201    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
202    .keyword("'text between quotes'")
203    .build();
204   
205    // THEN
206  1 assertThat(query.getStatement(), containsString("(LOWER(LOCALNAME(t)) LIKE '''text between quotes''%' OR CONTAINS(t.*, '''text between quotes'''))"));
207    }
208   
 
209  1 toggle @Test
210    public void filterWithEqualBoolean() throws Exception {
211    // GIVEN
212  1 Map<String, List<String>> filteringConditions = new HashMap<>();
213  1 filteringConditions.put("available", Arrays.asList("true"));
214   
215    // WHEN
216  1 Query query = QueryBuilder.inWorkspace(workspace)
217    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
218    .conditions(filteringConditions)
219    .build();
220   
221    // THEN
222  1 assertThat(query.getStatement(), containsString("AND t.available = 'true'"));
223    }
224   
 
225  1 toggle @Test
226    public void filterWithEqualNumber() throws Exception {
227    // GIVEN
228  1 Map<String, List<String>> filteringConditions = new HashMap<>();
229  1 filteringConditions.put("tourists", Arrays.asList("20"));
230   
231    // WHEN
232  1 Query query = QueryBuilder.inWorkspace(workspace)
233    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
234    .conditions(filteringConditions)
235    .build();
236   
237    // THEN
238  1 assertThat(query.getStatement(), containsString("AND t.tourists = CAST('20' AS LONG)"));
239    }
240   
 
241  1 toggle @Test
242    public void filterWithEqualString() throws Exception {
243    // GIVEN
244  1 Map<String, List<String>> filteringConditions = new HashMap<>();
245  1 filteringConditions.put("motto", Arrays.asList("If you believe, you can achieve."));
246   
247    // WHEN
248  1 Query query = QueryBuilder.inWorkspace(workspace)
249    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
250    .conditions(filteringConditions)
251    .build();
252   
253    // THEN
254  1 assertThat(query.getStatement(), containsString("AND t.motto = 'If you believe, you can achieve.'"));
255    }
256   
 
257  1 toggle @Test
258    public void filterWithParamWhoseNameContainsColon() throws Exception {
259    // GIVEN
260  1 Map<String, List<String>> filteringConditions = new HashMap<>();
261  1 filteringConditions.put(NodeTypes.Created.CREATED_BY, Arrays.asList("superuser"));
262   
263    // WHEN
264  1 Query query = QueryBuilder.inWorkspace(workspace)
265    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
266    .conditions(filteringConditions)
267    .build();
268   
269    // THEN
270  1 assertThat(query.getStatement(), containsString("AND t.[mgnl:createdBy] = 'superuser'"));
271    }
272   
 
273  1 toggle @Test
274    public void filterByIsoDateTime() throws Exception {
275    // GIVEN
276  1 Map<String, List<String>> filteringConditions = new HashMap<>();
277  1 filteringConditions.put(NodeTypes.LastModified.NAME, Arrays.asList("2015-01-26T23:17:02.000+07:00"));
278   
279    // WHEN
280  1 Query query = QueryBuilder.inWorkspace(workspace)
281    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
282    .conditions(filteringConditions)
283    .build();
284   
285    // THEN
286  1 assertThat(query.getStatement(), containsString("AND t.[mgnl:lastModified] = CAST('2015-01-26T23:17:02.000+07:00' AS DATE)"));
287    }
288   
 
289  1 toggle @Test
290    public void filterByIsoLocalDate() throws Exception {
291    // GIVEN
292  1 Map<String, List<String>> filteringConditions = new HashMap<>();
293  1 filteringConditions.put(NodeTypes.LastModified.NAME, Arrays.asList("2015-01-26"));
294   
295  1 ZonedDateTime expectedStartDate = ZonedDateTime.of(2015, 1, 26, 0, 0, 0, 0, ZoneId.systemDefault());
296  1 String expectedStartDateString = DATE_TIME_FORMATTER.format(expectedStartDate);
297   
298  1 LocalDate localDate = LocalDate.parse("2015-01-26", DATE_FORMATTER);
299  1 ZonedDateTime zonedDateTime = localDate.atTime(LocalTime.MAX).atZone(ZoneId.systemDefault());
300  1 String expectedEndDateString = zonedDateTime.format(DATE_TIME_FORMATTER);
301   
302    // WHEN
303  1 Query query = QueryBuilder.inWorkspace(workspace)
304    .nodeTypes(Arrays.asList(NodeTypes.Page.NAME))
305    .conditions(filteringConditions)
306    .build();
307   
308    // THEN
309  1 assertThat(query.getStatement(), containsString("AND t.[mgnl:lastModified] >= CAST('" + expectedStartDateString + "' AS DATE)" +
310    " AND t.[mgnl:lastModified] <= CAST('" + expectedEndDateString + "' AS DATE)"));
311    }
312   
 
313  1 toggle @Test
314    public void fullTextExpressionContainingJcrIllegalCharsShouldBeEscapedForLikeOperator() throws Exception {
315    // GIVEN
316  1 String keyword = "test%/:[]*|\t\n";
317   
318    // WHEN
319  1 Query query = QueryBuilder.inWorkspace(workspace)
320    .keyword(keyword)
321    .build();
322   
323    // THEN
324  1 assertThat(query.getStatement(), endsWith("LOWER(LOCALNAME(t)) LIKE 'test%25%2F%3A%5B%5D%2A%7C%09%0A%' OR CONTAINS(t.*, 'test%/:\\[\\]*|')"));
325    }
326   
 
327  1 toggle @Test
328    public void fullTextExpressionContainingSingleQuoteShouldBeEscaped() throws Exception {
329    // GIVEN
330  1 String keyword = "'text'";
331   
332    // WHEN
333  1 Query query = QueryBuilder.inWorkspace(workspace)
334    .keyword(keyword)
335    .build();
336   
337    // THEN
338  1 assertThat(query.getStatement(), endsWith("LOWER(LOCALNAME(t)) LIKE '''text''%' OR CONTAINS(t.*, '''text''')"));
339    }
340   
 
341  1 toggle @Test
342    public void filterValueContainingSingleQuoteShouldBeEscaped() throws Exception {
343    // GIVEN
344  1 Map<String, List<String>> filteringConditions = new HashMap<>();
345  1 filteringConditions.put("property", Arrays.asList("value'"));
346   
347    // WHEN
348  1 Query query = QueryBuilder.inWorkspace(workspace)
349    .conditions(filteringConditions)
350    .build();
351   
352    // THEN
353  1 assertThat(query.getStatement(), containsString("t.property = 'value'''"));
354    }
355   
 
356  1 toggle @Test
357    public void filterPropertyContainingSingleQuoteShouldBeEscaped() throws Exception {
358    // GIVEN
359  1 Map<String, List<String>> filteringConditions = new HashMap<>();
360  1 filteringConditions.put("property'", Arrays.asList("value"));
361   
362    // WHEN
363  1 Query query = QueryBuilder.inWorkspace(workspace)
364    .conditions(filteringConditions)
365    .build();
366   
367    // THEN
368  1 assertThat(query.getStatement(), containsString("t.property = 'value'"));
369    }
370   
 
371  1 toggle @Test
372    public void filterPropertyContainingBracketThrowsException() throws Exception {
373    // GIVEN
374  1 Map<String, List<String>> filteringConditions = new HashMap<>();
375  1 filteringConditions.put("property]", Arrays.asList("value"));
376   
377    // WHEN & THEN
378  1 assertThat(() -> QueryBuilder.inWorkspace(workspace).conditions(filteringConditions).build(),
379    throwsAnException(instanceOf(IllegalArgumentException.class)
380    .withMessage(containsString("Operator is invalid."))));
381    }
382   
 
383  1 toggle @Test
384    public void orderByClauseContainingBracketThrowsException() throws Exception {
385  1 assertThat(() -> QueryBuilder.inWorkspace(workspace).orderBy(Arrays.asList("test] desc")).build(),
386    throwsAnException(instanceOf(RuntimeRepositoryException.class)
387    .withMessage(containsString("javax.jcr.query.InvalidQueryException"))));
388    }
389   
 
390  1 toggle @Test
391    public void orderByClauseContainsASingleQuoteThrowsException() throws Exception {
392  1 assertThat(() -> QueryBuilder.inWorkspace(workspace).orderBy(Arrays.asList("test' desc")).build(),
393    throwsAnException(instanceOf(RuntimeRepositoryException.class)
394    .withMessage(containsString("javax.jcr.query.InvalidQueryException"))));
395    }
396   
 
397  1 toggle @Test
398    public void filterByMultiValueProperty() throws Exception {
399    // GIVEN
400  1 Map<String, List<String>> filteringConditions = new HashMap<>();
401  1 filteringConditions.put("title", Arrays.asList("first", "second"));
402   
403    // WHEN
404  1 Query query = QueryBuilder.inWorkspace(workspace)
405    .conditions(filteringConditions)
406    .build();
407   
408    // THEN
409  1 assertThat(query.getStatement(), containsString("SELECT t.* FROM [nt:base] AS t WHERE t.title = 'first' AND t.title = 'second'"));
410    }
411   
 
412  1 toggle @Test
413    public void filterByPropertyHavingOrOperator() throws Exception {
414    // GIVEN
415  1 Map<String, List<String>> filteringConditions = new HashMap<>();
416  1 filteringConditions.put("title", Arrays.asList("this|that"));
417   
418    // WHEN
419  1 Query query = QueryBuilder.inWorkspace(workspace)
420    .conditions(filteringConditions)
421    .build();
422   
423    // THEN
424  1 assertThat(query.getStatement(), containsString("SELECT t.* FROM [nt:base] AS t WHERE t.title = 'this' OR t.title = 'that'"));
425    }
426   
 
427  1 toggle @Test
428    public void filterByMultipleNames() throws Exception {
429    // GIVEN
430  1 Map<String, List<String>> filteringConditions = new HashMap<>();
431  1 filteringConditions.put("@name", Arrays.asList("this|that"));
432   
433    // WHEN
434  1 Query query = QueryBuilder.inWorkspace(workspace)
435    .conditions(filteringConditions)
436    .build();
437   
438    // THEN
439  1 assertThat(query.getStatement(), containsString("SELECT t.* FROM [nt:base] AS t WHERE LOWER(LOCALNAME(t)) LIKE 'this' OR LOWER(LOCALNAME(t)) LIKE 'that'"));
440    }
441    }