/* * (C) Copyright 2016 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Gabriel Barata <gbarata@nuxeo.com */ package org.nuxeo.ecm.restapi.server.jaxrs.search.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.inject.Inject; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import org.codehaus.jackson.JsonNode; import org.junit.Test; import org.junit.runner.RunWith; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.test.CoreFeature; import org.nuxeo.ecm.core.test.annotations.Granularity; import org.nuxeo.ecm.core.test.annotations.RepositoryConfig; import org.nuxeo.ecm.platform.query.api.PageProviderDefinition; import org.nuxeo.ecm.platform.query.api.PageProviderService; import org.nuxeo.ecm.platform.test.PlatformFeature; import org.nuxeo.ecm.restapi.test.BaseTest; import org.nuxeo.ecm.restapi.test.RestServerFeature; import org.nuxeo.runtime.api.Framework; import org.nuxeo.runtime.test.runner.Deploy; import org.nuxeo.runtime.test.runner.Features; import org.nuxeo.runtime.test.runner.FeaturesRunner; import org.nuxeo.runtime.test.runner.Jetty; import org.nuxeo.runtime.test.runner.LocalDeploy; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.core.util.MultivaluedMapImpl; /** * Test the various ways to perform queries via search endpoint. * * @since 8.3 */ @RunWith(FeaturesRunner.class) @Features({ RestServerFeature.class, PlatformFeature.class }) @Jetty(port = 18090) @Deploy({ "org.nuxeo.ecm.platform.userworkspace.core", "org.nuxeo.ecm.platform.userworkspace.types", "org.nuxeo.ecm.platform.webapp.types", "org.nuxeo.ecm.platform.contentview.jsf", "org.nuxeo.search.ui", "org.nuxeo.ecm.platform.search.core", "org.nuxeo.ecm.platform.restapi.server.search" }) @LocalDeploy("org.nuxeo.ecm.platform.restapi.test:pageprovider-test-contrib.xml") @RepositoryConfig(cleanup = Granularity.METHOD, init = RestServerInit.class) public class SearchTest extends BaseTest { @Inject protected CoreFeature coreFeature; protected static final String QUERY_EXECUTE_PATH = "search/lang/NXQL/execute"; protected static final String SAVED_SEARCH_PATH = "search/saved"; protected String getSearchPageProviderPath(String providerName) { return "search/pp/" + providerName; } protected String getSavedSearchPath(String id) { return "search/saved/" + id; } protected String getSavedSearchExecutePath(String id) { return "search/saved/" + id + "/execute"; } protected String getSearchPageProviderExecutePath(String providerName) { return "search/pp/" + providerName + "/execute"; } @Test public void iCanPerformQueriesOnRepository() throws IOException { // Given a repository, when I perform a query in NXQL on it MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.putSingle("query", "SELECT * FROM Document WHERE ecm:isVersion = 0"); ClientResponse response = getResponse(RequestType.GET, QUERY_EXECUTE_PATH, queryParams); // Then I get document listing as result assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(20, getLogEntries(node).size()); // Given parameters as page size and ordered parameters queryParams.clear(); queryParams.add("pageSize", "2"); queryParams.add("queryParams", "$currentUser"); queryParams.add("query", "select * from Document where " + "dc:creator = ?"); // Given a repository, when I perform a query in NXQL on it response = getResponse(RequestType.GET, QUERY_EXECUTE_PATH, queryParams); // Then I get document listing as result assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); node = mapper.readTree(response.getEntityInputStream()); assertEquals(2, getLogEntries(node).size()); } @Test public void iCanPerformQueriesWithNamedParametersOnRepository() throws IOException { // Given a repository and named parameters, when I perform a query in // NXQL on it DocumentModel folder = RestServerInit.getFolder(1, session); MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("query", "SELECT * FROM Document WHERE " + "ecm:parentId = :parentIdVar AND\n" + " ecm:mixinType != 'HiddenInNavigation' AND dc:title " + "IN (:note1,:note2)\n" + " AND ecm:isCheckedInVersion = 0 AND " + "ecm:currentLifeCycleState !=\n" + " 'deleted'"); queryParams.add("note1", "Note 1"); queryParams.add("note2", "Note 2"); queryParams.add("parentIdVar", folder.getId()); ClientResponse response = getResponse(RequestType.GET, QUERY_EXECUTE_PATH, queryParams); // Then I get document listing as result assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(2, getLogEntries(node).size()); } @Test public void iCanPerformPageProviderOnRepository() throws IOException { // Given a repository, when I perform a pageprovider on it DocumentModel folder = RestServerInit.getFolder(1, session); MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("queryParams", folder.getId()); ClientResponse response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("TEST_PP"), queryParams); // Then I get document listing as result assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(2, getLogEntries(node).size()); } @Test public void iCanPerformPageProviderWithNamedParametersOnRepository() throws IOException { // Given a repository, when I perform a pageprovider on it DocumentModel folder = RestServerInit.getFolder(1, session); MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("note1", "Note 1"); queryParams.add("note2", "Note 2"); queryParams.add("parentIdVar", folder.getId()); ClientResponse response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("TEST_PP_PARAM"), queryParams); // Then I get document listing as result assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(2, getLogEntries(node).size()); } @Test public void iCanPerformPageProviderWithQuickFilter() throws IOException { // Given a repository, when I perform a pageprovider on it DocumentModel folder = RestServerInit.getFolder(1, session); MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("quickFilters", "testQF,testQF2"); queryParams.add("parentIdVar", folder.getId()); ClientResponse response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("TEST_PP_QUICK_FILTER"), queryParams); // Then I get document listing as result assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(2, getLogEntries(node).size()); assertTrue(node.get("quickFilters").isArray()); assertEquals(3, node.get("quickFilters").size()); for (JsonNode qf : node.get("quickFilters")) { String name = qf.get("name").getTextValue(); boolean active = qf.get("active").getBooleanValue(); assertEquals("testQF".equals(name) || "testQF2".equals(name), active); } } /** * @since 8.4 */ @Test public void iDontAlterPageProviderDefWithQuickFilter() throws IOException { // Given a repository, when I perform a pageprovider on it MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("quickFilters", "testQF,testQF2"); ClientResponse response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("TEST_PP_QUICK_FILTER2"), queryParams); // Then I get document listing as result assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(2, getLogEntries(node).size()); response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("TEST_PP_QUICK_FILTER2")); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); node = mapper.readTree(response.getEntityInputStream()); assertEquals(20, getLogEntries(node).size()); } /** * @since 8.4 */ @Test public void iCanUseAssociativeQuickFilter() throws IOException { // Given a repository, when I perform a pageprovider on it with quick filters MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("quickFilters", "testQF4,testQF"); ClientResponse response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("TEST_PP_QUICK_FILTER2"), queryParams); // Then I get document listing as result assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); int nbResult = getLogEntries(node).size(); // When I set the quick filtes the toeher way around queryParams = new MultivaluedMapImpl(); queryParams.add("quickFilters", "testQF,testQF4"); response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("TEST_PP_QUICK_FILTER2"), queryParams); // Then I expect the same number of result assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); node = mapper.readTree(response.getEntityInputStream()); assertEquals(nbResult, getLogEntries(node).size()); } @Test public void iCanPerformPageProviderWithNamedParametersInvalid() throws Exception { ClientResponse response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("namedParamProviderInvalid")); assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals( "Failed to execute query: SELECT * FROM Document where dc:title=:foo, Lexical Error: Illegal character <:> at offset 38", getErrorMessage(node)); } @Test public void iCanPerformPageProviderWithNamedParametersAndDoc() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("np:title", "Folder 0"); ClientResponse response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("namedParamProviderWithDoc"), queryParams); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(1, getLogEntries(node).size()); } @Test public void iCanPerformPageProviderWithNamedParametersAndDocInvalid() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("np:title", "Folder 0"); ClientResponse response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("namedParamProviderWithDocInvalid"), queryParams); assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals( "Failed to execute query: SELECT * FROM Document where dc:title=:foo, Lexical Error: Illegal character <:> at offset 38", getErrorMessage(node)); } @Test public void iCanPerformPageProviderWithNamedParametersInWhereClause() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("parameter1", "Folder 0"); ClientResponse response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("namedParamProviderWithWhereClause"), queryParams); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(1, getLogEntries(node).size()); // retry without params response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("namedParamProviderWithWhereClause")); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); node = mapper.readTree(response.getEntityInputStream()); assertEquals(2, getLogEntries(node).size()); } @Test public void iCanPerformPageProviderWithNamedParametersInWhereClauseWithDoc() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("np:title", "Folder 0"); ClientResponse response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("namedParamProviderWithWhereClauseWithDoc"), queryParams); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(1, getLogEntries(node).size()); // retry without params response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("namedParamProviderWithWhereClauseWithDoc")); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); node = mapper.readTree(response.getEntityInputStream()); assertEquals(2, getLogEntries(node).size()); } @Test public void iCanPerformPageProviderWithNamedParametersComplex() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add("parameter1", "Folder 0"); queryParams.add("np:isCheckedIn", Boolean.FALSE.toString()); queryParams.add("np:dateMin", "2007-01-30 01:02:03+04:00"); queryParams.add("np:dateMax", "2007-03-23 01:02:03+04:00"); ClientResponse response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("namedParamProviderComplex"), queryParams); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(1, getLogEntries(node).size()); // remove filter on dates queryParams.remove("np:dateMin"); queryParams.remove("np:dateMax"); response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("namedParamProviderComplex"), queryParams); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); node = mapper.readTree(response.getEntityInputStream()); assertEquals(1, getLogEntries(node).size()); queryParams.remove("parameter1"); response = getResponse(RequestType.GET, getSearchPageProviderExecutePath("namedParamProviderComplex"), queryParams); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); node = mapper.readTree(response.getEntityInputStream()); assertEquals(2, getLogEntries(node).size()); } @Test public void iCanGetPageProviderDefinition() throws IOException { ClientResponse response = getResponse(RequestType.GET, getSearchPageProviderPath("namedParamProviderComplex")); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); PageProviderService pageProviderService = Framework.getService(PageProviderService.class); PageProviderDefinition def = pageProviderService.getPageProviderDefinition("namedParamProviderComplex"); assertEquals(def.getName(), node.get("name").getTextValue()); } @Test public void iCanSaveSearchByQuery() throws IOException { String data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"query\": \"select * from Document where dc:creator = ?\",\n" + " \"queryLanguage\": \"NXQL\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\"\n," + " \"contentViewData\": \"{" + "\\\"viewVar\\\": \\\"value\\\"" + "}\"\n" + "}"; ClientResponse response = getResponse(RequestType.POST, SAVED_SEARCH_PATH, data); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("savedSearch", node.get("entity-type").getTextValue()); assertEquals("search by query", node.get("title").getTextValue()); assertEquals("select * from Document where dc:creator = ?", node.get("query").getTextValue()); assertEquals("NXQL", node.get("queryLanguage").getTextValue()); assertEquals("$currentUser", node.get("queryParams").getTextValue()); assertEquals("2", node.get("pageSize").getTextValue()); assertEquals("{\"viewVar\": \"value\"}", node.get("contentViewData").getTextValue()); } @Test public void iCanSaveSearchByPageProvider() throws IOException { DocumentModel folder = RestServerInit.getFolder(1, session); String data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by page provider\",\n" + " \"pageProviderName\": \"TEST_PP\",\n" + " \"queryParams\": \"" + folder.getId() + "\",\n" + " \"contentViewData\": \"{" + "\\\"viewVar\\\": \\\"value\\\"" + "}\"\n" + "}"; ClientResponse response = getResponse(RequestType.POST, SAVED_SEARCH_PATH, data); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("savedSearch", node.get("entity-type").getTextValue()); assertEquals("search by page provider", node.get("title").getTextValue()); assertEquals("TEST_PP", node.get("pageProviderName").getTextValue()); assertEquals(folder.getId(), node.get("queryParams").getTextValue()); assertEquals("{\"viewVar\": \"value\"}", node.get("contentViewData").getTextValue()); } @Test public void iCanSaveDefaultSearch() throws IOException { String data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by page provider 2\",\n" + " \"pageProviderName\": \"default_search\",\n" + " \"pageSize\": \"2\",\n" + " \"params\": {\n" + " \"ecm_fulltext\": \"Note*\",\n" + " \"dc_modified_agg\": [\"last24h\"]\n" + " },\n" + " \"contentViewData\": \"{" + "\\\"viewVar\\\": \\\"value\\\"" + "}\"\n" + "}"; Map<String, String> headers = new HashMap<>(); headers.put("x-nxdocumentproperties", "default_search"); ClientResponse response = getResponse(RequestType.POST, SAVED_SEARCH_PATH, data, headers); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("savedSearch", node.get("entity-type").getTextValue()); assertEquals("search by page provider 2", node.get("title").getTextValue()); assertEquals("default_search", node.get("pageProviderName").getTextValue()); assertEquals("2", node.get("pageSize").getTextValue()); assertEquals("{\"viewVar\": \"value\"}", node.get("contentViewData").getTextValue()); assertTrue(node.has("params")); node = node.get("params"); assertEquals("Note*", node.get("defaults:ecm_fulltext").getTextValue()); assertEquals(1, node.get("defaults:dc_modified_agg").size()); assertEquals("last24h", node.get("defaults:dc_modified_agg").get(0).getTextValue()); } @Test public void iCantSaveSearchInvalidParams() throws IOException { String data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"query\": \"select * from Document where dc:creator = ?\",\n" + " \"queryLanguage\": \"NXQL\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\"\n" + "}"; ClientResponse response = getResponse(RequestType.POST, SAVED_SEARCH_PATH, data); assertInvalidTitle(response); data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"query\": \"select * from Document where dc:creator = ?\",\n" + " \"queryLanguage\": \"NXQL\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\",\n" + " \"pageProviderName\": \"TEST_PP\"\n" + "}"; response = getResponse(RequestType.POST, SAVED_SEARCH_PATH, data); assertMixedQueryAndPageProvider(response); data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"query\": \"select * from Document where dc:creator = ?\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\",\n" + " \"pageProviderName\": \"TEST_PP\"\n" + "}"; response = getResponse(RequestType.POST, SAVED_SEARCH_PATH, data); assertMixedQueryAndPageProvider(response); data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"queryLanguage\": \"NXQL\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\",\n" + " \"pageProviderName\": \"TEST_PP\"\n" + "}"; response = getResponse(RequestType.POST, SAVED_SEARCH_PATH, data); assertMixedQueryAndPageProvider(response); data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"query\": \"select * from Document where dc:creator = ?\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\"\n" + "}"; response = getResponse(RequestType.POST, SAVED_SEARCH_PATH, data); assertMissingQueryLanguage(response); data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"queryLanguage\": \"NXQL\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\"\n" + "}"; response = getResponse(RequestType.POST, SAVED_SEARCH_PATH, data); assertMissingQuery(response); data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\"\n" + "}"; response = getResponse(RequestType.POST, SAVED_SEARCH_PATH, data); assertMissingParams(response); } @Test public void iCanGetSavedSearchByQuery() throws IOException { ClientResponse response = getResponse(RequestType.GET, getSavedSearchPath(RestServerInit.getSavedSearchId(1, session))); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("savedSearch", node.get("entity-type").getTextValue()); assertEquals("my saved search 1", node.get("title").getTextValue()); assertEquals("select * from Document where dc:creator = ?", node.get("query").getTextValue()); assertEquals("NXQL", node.get("queryLanguage").getTextValue()); assertEquals("$currentUser", node.get("queryParams").getTextValue()); assertEquals("2", node.get("pageSize").getTextValue()); } @Test public void iCanGetSavedSearchByPageProvider() throws IOException { ClientResponse response = getResponse(RequestType.GET, getSavedSearchPath(RestServerInit.getSavedSearchId(2, session))); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("savedSearch", node.get("entity-type").getTextValue()); assertEquals("my saved search 2", node.get("title").getTextValue()); assertEquals("TEST_PP", node.get("pageProviderName").getTextValue()); DocumentModel folder = RestServerInit.getFolder(1, session); assertEquals(folder.getId(), node.get("queryParams").getTextValue()); } @Test public void iCantGetSavedSearchInvalidId() throws IOException { ClientResponse response = getResponse(RequestType.GET, getSavedSearchPath("-1")); assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("unknown id: -1", getErrorMessage(node)); } @Test public void iCanUpdateSearchByQuery() throws IOException { String data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"my search 1\",\n" + " \"query\": \"select * from Document where dc:creator = ?\",\n" + " \"queryLanguage\": \"NXQL\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"1\",\n" + " \"contentViewData\": \"{" + "\\\"viewVar\\\": \\\"another value\\\"" + "}\"\n" + "}"; ClientResponse response = getResponse(RequestType.PUT, getSavedSearchPath(RestServerInit.getSavedSearchId(1, session)), data); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("savedSearch", node.get("entity-type").getTextValue()); assertEquals("my search 1", node.get("title").getTextValue()); assertEquals("select * from Document where dc:creator = ?", node.get("query").getTextValue()); assertEquals("NXQL", node.get("queryLanguage").getTextValue()); assertEquals("$currentUser", node.get("queryParams").getTextValue()); assertEquals("1", node.get("pageSize").getTextValue()); assertEquals("{\"viewVar\": \"another value\"}", node.get("contentViewData").getTextValue()); } @Test public void iCanUpdateSearchByPageProvider() throws IOException { String data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"my search 2\",\n" + " \"pageProviderName\": \"TEST_PP\",\n" + " \"contentViewData\": \"{" + "\\\"viewVar\\\": \\\"another value\\\"" + "}\"\n" + "}"; ClientResponse response = getResponse(RequestType.PUT, getSavedSearchPath(RestServerInit.getSavedSearchId(2, session)), data); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("savedSearch", node.get("entity-type").getTextValue()); assertEquals("my search 2", node.get("title").getTextValue()); assertEquals("TEST_PP", node.get("pageProviderName").getTextValue()); assertNull(node.get("queryParams").getTextValue()); assertEquals("{\"viewVar\": \"another value\"}", node.get("contentViewData").getTextValue()); } @Test public void iCantUpdateSearchInvalidId() throws IOException { String data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"my search 1\",\n" + " \"query\": \"select * from Document where dc:creator = ?\",\n" + " \"queryLanguage\": \"NXQL\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"1\",\n" + " \"contentViewData\": \"{" + "\\\"viewVar\\\": \\\"another value\\\"" + "}\"\n" + "}"; ClientResponse response = getResponse(RequestType.PUT, getSavedSearchPath("-1"), data); assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("unknown id: -1", getErrorMessage(node)); } @Test public void iCantUpdateSearchInvalidQueryOrPageProvider() throws IOException { String data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"query\": \"select * from Document where dc:creator = ?\",\n" + " \"queryLanguage\": \"NXQL\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"1\"\n" + "}"; ClientResponse response = getResponse(RequestType.PUT, getSavedSearchPath(RestServerInit.getSavedSearchId(1, session)), data); assertInvalidTitle(response); data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"query\": \"select * from Document where dc:creator = ?\",\n" + " \"queryLanguage\": \"NXQL\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\",\n" + " \"pageProviderName\": \"TEST_PP\"\n" + "}"; response = getResponse(RequestType.PUT, getSavedSearchPath(RestServerInit.getSavedSearchId(1, session)), data); assertMixedQueryAndPageProvider(response); data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"query\": \"select * from Document where dc:creator = ?\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\",\n" + " \"pageProviderName\": \"TEST_PP\"\n" + "}"; response = getResponse(RequestType.PUT, getSavedSearchPath(RestServerInit.getSavedSearchId(1, session)), data); assertMixedQueryAndPageProvider(response); data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"queryLanguage\": \"NXQL\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\",\n" + " \"pageProviderName\": \"TEST_PP\"\n" + "}"; response = getResponse(RequestType.PUT, getSavedSearchPath(RestServerInit.getSavedSearchId(1, session)), data); assertMixedQueryAndPageProvider(response); data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"query\": \"select * from Document where dc:creator = ?\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\"\n" + "}"; response = getResponse(RequestType.PUT, getSavedSearchPath(RestServerInit.getSavedSearchId(1, session)), data); assertMissingQueryLanguage(response); data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"queryLanguage\": \"NXQL\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\"\n" + "}"; response = getResponse(RequestType.PUT, getSavedSearchPath(RestServerInit.getSavedSearchId(1, session)), data); assertMissingQuery(response); data = "{\n" + " \"entity-type\": \"savedSearch\",\n" + " \"title\": \"search by query\",\n" + " \"queryParams\": \"$currentUser\",\n" + " \"pageSize\": \"2\"\n" + "}"; response = getResponse(RequestType.PUT, getSavedSearchPath(RestServerInit.getSavedSearchId(1, session)), data); assertMissingParams(response); } @Test public void iCanDeleteSearch() throws IOException { ClientResponse response = getResponse(RequestType.DELETE, getSavedSearchPath(RestServerInit.getSavedSearchId(1, session))); assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus()); } @Test public void iCantDeleteSearchInvalidId() throws IOException { ClientResponse response = getResponse(RequestType.DELETE, getSavedSearchPath("-1")); assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); } @Test public void iCanExecuteSavedSearchByQuery() throws IOException { ClientResponse response = getResponse(RequestType.GET, getSavedSearchExecutePath(RestServerInit.getSavedSearchId(1, session))); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(2, getLogEntries(node).size()); } @Test public void iCanExecuteSavedSearchByQueryWithParams() throws IOException { MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.putSingle("pageSize", "5"); ClientResponse response = getResponse(RequestType.GET, getSavedSearchExecutePath(RestServerInit.getSavedSearchId(1, session)), queryParams); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(5, getLogEntries(node).size()); } @Test public void iCanExecuteSavedSearchByPageProvider() throws IOException { ClientResponse response = getResponse(RequestType.GET, getSavedSearchExecutePath(RestServerInit.getSavedSearchId(2, session))); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(2, getLogEntries(node).size()); } @Test public void iCanExecuteDefaultSavedSearch() throws IOException { // this saved search uses ecm:fulltext so some databases doing async fulltext indexing will need a pause coreFeature.getStorageConfiguration().waitForFulltextIndexing(); ClientResponse response = getResponse(RequestType.GET, getSavedSearchExecutePath(RestServerInit.getSavedSearchId(3, session))); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals(2, getLogEntries(node).size()); } @Test public void iCanSearchSavedSearches() throws IOException { ClientResponse response = getResponse(RequestType.GET, SAVED_SEARCH_PATH); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertTrue(node.isContainerNode()); assertTrue(node.has("entries")); assertTrue(node.get("entries").isArray()); assertEquals(3, node.get("entries").size()); } @Test public void iCanSearchSavedSearchesParamPageProvider() throws IOException { MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.putSingle("pageProvider", "TEST_PP"); ClientResponse response = getResponse(RequestType.GET, SAVED_SEARCH_PATH, queryParams); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertTrue(node.isContainerNode()); assertTrue(node.has("entries")); assertTrue(node.get("entries").isArray()); assertEquals(1, node.get("entries").size()); node = node.get("entries").get(0); assertEquals("my saved search 2", node.get("title").getTextValue()); assertEquals("TEST_PP", node.get("pageProviderName").getTextValue()); DocumentModel folder = RestServerInit.getFolder(1, session); assertEquals(folder.getId(), node.get("queryParams").getTextValue()); } private void assertInvalidTitle(ClientResponse response) throws IOException { assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("title cannot be empty", getErrorMessage(node)); } private void assertMixedQueryAndPageProvider(ClientResponse response) throws IOException { assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("query and page provider parameters are mutually exclusive" + " (query, queryLanguage, pageProviderName)", getErrorMessage(node)); } private void assertMissingParams(ClientResponse response) throws IOException { assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("query or page provider parameters are missing" + " (query, queryLanguage, pageProviderName)", getErrorMessage(node)); } private void assertMissingQueryLanguage(ClientResponse response) throws IOException { assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("queryLanguage parameter is missing", getErrorMessage(node)); } private void assertMissingQuery(ClientResponse response) throws IOException { assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); JsonNode node = mapper.readTree(response.getEntityInputStream()); assertEquals("query parameter is missing", getErrorMessage(node)); } }