/*
* (C) Copyright 2014 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:
* dmetzler
* Vladimir Pasquier <vpasquier@nuxeo.com>
*/
package org.nuxeo.ecm.restapi.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Map;
import javax.inject.Inject;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.nuxeo.ecm.automation.core.trace.Trace;
import org.nuxeo.ecm.automation.core.trace.TracerFactory;
import org.nuxeo.ecm.automation.core.util.PaginableDocumentModelList;
import org.nuxeo.ecm.core.api.Blob;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.test.annotations.Granularity;
import org.nuxeo.ecm.core.test.annotations.RepositoryConfig;
import org.nuxeo.ecm.restapi.server.jaxrs.adapters.OperationAdapter;
import org.nuxeo.ecm.restapi.server.jaxrs.blob.BlobAdapter;
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.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
/**
* @since 5.7.2 - Test the Rest binding to run operations
*/
@RunWith(FeaturesRunner.class)
@Features({ RestServerFeature.class })
@LocalDeploy({ "org.nuxeo.ecm.platform.restapi.test:operation-contrib.xml" })
@Jetty(port = 18090)
@RepositoryConfig(cleanup = Granularity.METHOD, init = RestServerInit.class)
public class OperationBindingTest extends BaseTest {
private static final Integer TIMEOUT = Integer.valueOf(1000 * 60 * 5); // 5min
private static String PARAMS = "{\"params\":{\"one\":\"1\",\"two\": 2}}";
@Inject
protected TracerFactory factory;
@Override
@Before
public void doBefore() throws Exception {
super.doBefore();
// Activate trace mode
if (!factory.getRecordingState()) {
factory.toggleRecording();
}
}
@Test
public void itCanRunAnOperationOnaDocument() throws Exception {
// Given a document and an operation
DocumentModel note = RestServerInit.getNote(0, session);
// When i call the REST binding on the document resource
ClientResponse response = getResponse(RequestType.POSTREQUEST, "id/" + note.getId() + "/@"
+ OperationAdapter.NAME + "/testOp", PARAMS);
// Then the operation is called on the document
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
// Then the operation is called on all children documents
Trace trace = factory.getTrace("testOp");
assertEquals(1, trace.getCalls().size());
Map<?, ?> parameters = trace.getCalls().get(0).getVariables();
assertEquals("1", parameters.get("one"));
assertEquals(2, parameters.get("two"));
assertEquals(note.getId(), ((DocumentModel) trace.getOutput()).getId());
}
@Test
public void itCanRunAChainOnADocument() throws Exception {
// Given a document and an operation
DocumentModel note = RestServerInit.getNote(0, session);
// When i call the REST binding on the document resource
ClientResponse response = getResponse(RequestType.POSTREQUEST, "id/" + note.getId() + "/@"
+ OperationAdapter.NAME + "/testChain", "{}");
// Then the operation is called twice on the document
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
// Then the operation is called on all children documents
Trace trace = factory.getTrace("testChain");
assertEquals(2, trace.getCalls().size());
Map<?, ?> parameters = trace.getCalls().get(0).getParameters();
assertEquals("One", parameters.get("one"));
assertEquals(2L, parameters.get("two"));
assertEquals(note.getId(), ((DocumentModel) trace.getOutput()).getId());
parameters = trace.getCalls().get(1).getParameters();
assertEquals(4L, parameters.get("two"));
assertEquals("Two", parameters.get("one"));
}
@Test
public void itCanRunAChainOnMutlipleDocuments() throws Exception {
// Given a folder
DocumentModel folder = RestServerInit.getFolder(1, session);
// When i call the REST binding on the children resource
getResponse(RequestType.POSTREQUEST, "id/" + folder.getId() + "/@children/@" + OperationAdapter.NAME
+ "/testOp", PARAMS);
// Then the operation is called on all children documents
Trace trace = factory.getTrace("testOp");
assertEquals(1, trace.getCalls().size());
assertEquals(session.getChildren(folder.getRef()).size(),
((PaginableDocumentModelList) trace.getOutput()).size());
}
@Test
public void itCanRunAutomationWithBlob() throws Exception {
// Given a file
DocumentModel file = RestServerInit.getFile(1, session);
// When i call the REST binding on the blob resource
getResponse(RequestType.POSTREQUEST, "id/" + file.getId() + "/@" + BlobAdapter.NAME + "/file:content/@"
+ OperationAdapter.NAME + "/testOp", PARAMS);
// Then the operation is called on a document blob
Trace trace = factory.getTrace("testOp");
assertTrue(trace.getOutput() instanceof Blob);
}
@Test
public void automationResourceIsAlsoAvailableBehindAPIRoot() throws Exception {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
client.setConnectTimeout(TIMEOUT);
client.setReadTimeout(TIMEOUT);
client.addFilter(new HTTPBasicAuthFilter("Administrator", "Administrator"));
WebResource wr = client.resource("http://localhost:18090/api/v1/automation/doc");
Builder builder = wr.accept(MediaType.TEXT_HTML);
ClientResponse response = builder.get(ClientResponse.class);
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
}
/**
* @since 7.1
*/
@Test
public void itShouldReturnCustomHttpStatusWhenSuccess()
throws Exception {
String param = "{\"params\":{\"isFailing\":\"false\"}}";
ClientResponse response = getResponse(RequestType.POSTREQUEST,
"@" + OperationAdapter.NAME + "/Test.HttpStatus", param);
assertEquals(206, response.getStatus());
}
/**
* @since 7.1
*/
@Test
public void itShouldReturnCustomHttpStatusWhenFailure()
throws Exception {
String param = "{\"params\":{\"isFailing\":\"true\"}}";
ClientResponse response = getResponse(RequestType.POSTREQUEST,
"@" + OperationAdapter.NAME + "/Test.HttpStatus", param);
assertEquals(405, response.getStatus());
}
}