From 022c1269a4733e29fa96a9a8ca25813cdc1b3d3e Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Fri, 28 Mar 2014 01:33:48 +0000 Subject: [PATCH] Hold ReST API Unit Tests * RM-1320, RM-1328, RM-1331, RM-1333 * added Mockito based framework for testing Java backed declarative web scripts and their templates git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@65762 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../rm-webscript-context.xml | 3 + .../script/hold/BaseHold.java | 75 ++++- .../script/hold/HoldsGet.java | 6 + rm-server/test/resources/testng.xml | 2 +- ...cordsManagementTypeFormFilterUnitTest.java | 2 +- .../hold/HoldServiceImplUnitTest.java | 3 +- .../evaluator/TransferEvaluatorUnitTest.java | 3 +- .../RecordMetadataBootstrapUnitTest.java | 3 +- .../record/RecordServiceImplUnitTest.java | 3 +- .../hold/BaseHoldWebScriptUnitTest.java | 39 +++ .../BaseHoldWebScriptWithContentUnitTest.java | 205 +++++++++++++ .../script/hold/HoldPostUnitTest.java | 100 +++++++ .../script/hold/HoldPutUnitTest.java | 100 +++++++ .../script/hold/HoldsGetUnitTest.java | 233 +++++++++++++++ .../{ => test}/AllUnitTestSuite.java | 10 +- .../{ => test/util}/BaseUnitTest.java | 85 +++++- .../test/util/BaseWebScriptUnitTest.java | 269 ++++++++++++++++++ .../test/util/WebScriptExceptionMatcher.java | 80 ++++++ 18 files changed, 1194 insertions(+), 27 deletions(-) create mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHoldWebScriptUnitTest.java create mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHoldWebScriptWithContentUnitTest.java create mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldPostUnitTest.java create mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldPutUnitTest.java create mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldsGetUnitTest.java rename rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/{ => test}/AllUnitTestSuite.java (77%) mode change 100755 => 100644 rename rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/{ => test/util}/BaseUnitTest.java (64%) mode change 100755 => 100644 create mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseWebScriptUnitTest.java create mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/WebScriptExceptionMatcher.java diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml index 344dd7f7d9..4b6a00922e 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml @@ -596,6 +596,9 @@ + + + diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHold.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHold.java index 107ea759af..b51e69d2bb 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHold.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHold.java @@ -25,7 +25,10 @@ import java.util.List; import java.util.Map; import org.alfresco.module.org_alfresco_module_rm.hold.HoldService; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; +import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -46,6 +49,15 @@ public abstract class BaseHold extends DeclarativeWebScript { /** Hold Service */ private HoldService holdService; + + /** record service */ + private RecordService recordService; + + /** record folder service */ + private RecordFolderService recordFolderService; + + /** node service */ + private NodeService nodeService; /** * Set the hold service @@ -56,6 +68,30 @@ public abstract class BaseHold extends DeclarativeWebScript { this.holdService = holdService; } + + /** + * @param recordFolderService record folder service + */ + public void setRecordFolderService(RecordFolderService recordFolderService) + { + this.recordFolderService = recordFolderService; + } + + /** + * @param recordService record service + */ + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + + /** + * @param nodeService node service + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } /** * Returns the hold service @@ -125,17 +161,33 @@ public abstract class BaseHold extends DeclarativeWebScript */ protected NodeRef getItemNodeRef(JSONObject json) { - String nodeRef = null; + String nodeRefString = null; try { - nodeRef = json.getString("nodeRef"); + nodeRefString = json.getString("nodeRef"); } catch (JSONException je) { throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not get the nodeRef from the json object.", je); } - return new NodeRef(nodeRef); + + NodeRef nodeRef = new NodeRef(nodeRefString); + + // ensure that the node exists + if (!nodeService.exists(nodeRef)) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Item being added to hold does not exist."); + } + + // ensure that the node we are adding to the hold is a record or + // record folder + if (!recordService.isRecord(nodeRef) && !recordFolderService.isRecordFolder(nodeRef)) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Items added to a hold must be either a record or record folder."); + } + + return nodeRef; } /** @@ -152,8 +204,21 @@ public abstract class BaseHold extends DeclarativeWebScript JSONArray holdsArray = json.getJSONArray("holds"); for (int i = 0; i < holdsArray.length(); i++) { - String nodeRef = holdsArray.getString(i); - holds.add(new NodeRef(nodeRef)); + NodeRef nodeRef = new NodeRef(holdsArray.getString(i)); + + // check the hold exists + if (!nodeService.exists(nodeRef)) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "The hold does not exist."); + } + + // check the noderef is actually a hold + if (!holdService.isHold(nodeRef)) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Items are being added to a node that isn't a hold."); + } + + holds.add(nodeRef); } } catch (JSONException je) diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldsGet.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldsGet.java index 0151b96097..f1e3d4c03e 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldsGet.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldsGet.java @@ -137,6 +137,12 @@ public class HoldsGet extends DeclarativeWebScript if (StringUtils.isNotBlank(storeType) && StringUtils.isNotBlank(storeId) && StringUtils.isNotBlank(id)) { filePlan = new NodeRef(new StoreRef(storeType, storeId), id); + + // check that this node is actually a file plan + if (!nodeService.exists(filePlan) || !filePlanService.isFilePlan(filePlan)) + { + throw new WebScriptException(Status.STATUS_NOT_FOUND, "The file plan provided could not be found."); + } } else { diff --git a/rm-server/test/resources/testng.xml b/rm-server/test/resources/testng.xml index efa5a5a821..cc24c41946 100644 --- a/rm-server/test/resources/testng.xml +++ b/rm-server/test/resources/testng.xml @@ -3,7 +3,7 @@ - + diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementTypeFormFilterUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementTypeFormFilterUnitTest.java index 277b40f510..0af4780f7e 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementTypeFormFilterUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementTypeFormFilterUnitTest.java @@ -33,8 +33,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.alfresco.module.org_alfresco_module_rm.BaseUnitTest; import org.alfresco.module.org_alfresco_module_rm.admin.RecordsManagementAdminService; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; import org.alfresco.repo.forms.Field; import org.alfresco.repo.forms.FieldDefinition; import org.alfresco.repo.forms.Form; diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/hold/HoldServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/hold/HoldServiceImplUnitTest.java index 9e39b48ca1..3588c9b706 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/hold/HoldServiceImplUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/hold/HoldServiceImplUnitTest.java @@ -41,7 +41,7 @@ import java.util.Map; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; -import org.alfresco.module.org_alfresco_module_rm.BaseUnitTest; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.NamespaceService; @@ -60,6 +60,7 @@ import org.mockito.stubbing.Answer; * Hold service implementation unit test * * @author Roy Wetherall + * @since 2.2 */ public class HoldServiceImplUnitTest extends BaseUnitTest { diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/TransferEvaluatorUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/TransferEvaluatorUnitTest.java index 25d626dc0e..b42c4ac96e 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/TransferEvaluatorUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/TransferEvaluatorUnitTest.java @@ -29,8 +29,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.alfresco.module.org_alfresco_module_rm.BaseUnitTest; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.RegexQNamePattern; @@ -42,6 +42,7 @@ import org.mockito.Spy; * Transfer evaluator unit test. * * @author Roy Wetherall + * @since 2.2 */ public class TransferEvaluatorUnitTest extends BaseUnitTest { diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordMetadataBootstrapUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordMetadataBootstrapUnitTest.java index e34ed315e7..1b7fd3eed9 100755 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordMetadataBootstrapUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordMetadataBootstrapUnitTest.java @@ -23,7 +23,7 @@ import static org.mockito.Mockito.verify; import java.util.HashMap; import java.util.Map; -import org.alfresco.module.org_alfresco_module_rm.BaseUnitTest; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; import org.alfresco.service.namespace.QName; import org.junit.Test; import org.mockito.InjectMocks; @@ -32,6 +32,7 @@ import org.mockito.InjectMocks; * Unit test for RecordMetadataBootstrap * * @author Roy Wetherall + * @since 2.2 */ public class RecordMetadataBootstrapUnitTest extends BaseUnitTest { diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java index 29bd736996..99ee3c2194 100755 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java @@ -26,7 +26,7 @@ import static org.mockito.Mockito.when; import java.util.Map; import java.util.Set; -import org.alfresco.module.org_alfresco_module_rm.BaseUnitTest; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; import org.apache.commons.collections.CollectionUtils; @@ -38,6 +38,7 @@ import org.mockito.InjectMocks; * Unit test for RecordServiceImpl * * @author Roy Wetherall + * @since 2.2 */ public class RecordServiceImplUnitTest extends BaseUnitTest { diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHoldWebScriptUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHoldWebScriptUnitTest.java new file mode 100644 index 0000000000..8fff00ec54 --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHoldWebScriptUnitTest.java @@ -0,0 +1,39 @@ +package org.alfresco.module.org_alfresco_module_rm.script.hold; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * Base hold web script unit test. + * + * @author Roy Wetherall + * @since 2.2 + */ +public abstract class BaseHoldWebScriptUnitTest extends BaseWebScriptUnitTest +{ + /** test holds */ + protected NodeRef hold1NodeRef; + protected NodeRef hold2NodeRef; + protected List holds; + + /** + * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before() + */ + @Override + public void before() + { + super.before(); + + // generate test holds + hold1NodeRef = generateHoldNodeRef("hold1"); + hold2NodeRef = generateHoldNodeRef("hold2"); + + // list of holds + holds = new ArrayList(2); + Collections.addAll(holds, hold1NodeRef, hold2NodeRef); + } +} diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHoldWebScriptWithContentUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHoldWebScriptWithContentUnitTest.java new file mode 100644 index 0000000000..73c2a53a5e --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/BaseHoldWebScriptWithContentUnitTest.java @@ -0,0 +1,205 @@ +package org.alfresco.module.org_alfresco_module_rm.script.hold; + +import static org.alfresco.module.org_alfresco_module_rm.test.util.WebScriptExceptionMatcher.badRequest; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.List; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.junit.Test; +import org.springframework.extensions.webscripts.WebScriptException; + +/** + * Base hold web script with content unit test. + * + * @author Roy Wetherall + * @since 2.2 + */ +public abstract class BaseHoldWebScriptWithContentUnitTest extends BaseHoldWebScriptUnitTest +{ + /** + * Helper method to build JSON content to send to hold webscripts. + */ + protected String buildContent(NodeRef nodeRef, List holds) + { + StringBuilder builder = new StringBuilder(255); + builder.append("{"); + + if (nodeRef != null) + { + builder.append("'nodeRef':'").append(nodeRef.toString()).append("'"); + } + + if (nodeRef != null && holds != null) + { + builder.append(","); + } + + if (holds != null) + { + builder.append("'holds':["); + + boolean bFirst = true; + for (NodeRef hold : holds) + { + if (bFirst == false) + { + builder.append(","); + } + else + { + bFirst = false; + } + + builder.append("'" + hold.toString() + "'"); + } + + builder.append("]"); + } + + builder.append("}"); + + return builder.toString(); + } + + /** + * Test for expected exception when invalid JSON sent + */ + @SuppressWarnings("unchecked") + @Test + public void sendInvalidJSON() throws Exception + { + // invalid JSON + String content = "invalid JSON"; + + // expected exception + exception.expect(WebScriptException.class); + exception.expect(badRequest()); + + // execute web script + executeWebScript(Collections.EMPTY_MAP, content); + } + + /** + * Test for expected exception when one of the holds doesn't exist. + */ + @SuppressWarnings("unchecked") + @Test + public void holdDoesNotExist() throws Exception + { + // setup interactions + when(mockedNodeService.exists(eq(hold1NodeRef))).thenReturn(false); + + // build content + String content = buildContent(record, holds); + + // expected exception + exception.expect(WebScriptException.class); + exception.expect(badRequest()); + + // execute web script + executeWebScript(Collections.EMPTY_MAP, content); + } + + /** + * Test for expected excpetion when the item being added to the hold + * does not exist. + */ + @SuppressWarnings("unchecked") + @Test + public void nodeRefDoesNotExist() throws Exception + { + // setup interactions + when(mockedNodeService.exists(eq(record))).thenReturn(false); + + // build content + String content = buildContent(record, holds); + + // expected exception + exception.expect(WebScriptException.class); + exception.expect(badRequest()); + + // execute web script + executeWebScript(Collections.EMPTY_MAP, content); + } + + /** + * Test for expected exception when hold information is missing from + * sent JSON. + */ + @SuppressWarnings("unchecked") + @Test + public void holdMissingFromContent() throws Exception + { + // build content + String content = buildContent(record, null); + + // expected exception + exception.expect(WebScriptException.class); + exception.expect(badRequest()); + + // execute web script + executeWebScript(Collections.EMPTY_MAP, content); + } + + /** + * Test for expected exception when noderef information is missing + * from send JSON. + */ + @SuppressWarnings("unchecked") + @Test + public void nodeRefMissingFromContent() throws Exception + { + // build content + String content = buildContent(null, holds); + + // expected exception + exception.expect(WebScriptException.class); + exception.expect(badRequest()); + + // execute web script + executeWebScript(Collections.EMPTY_MAP, content); + } + + /** + * Test for expected exception when adding an item to something + * that isn't a hold. + */ + @SuppressWarnings("unchecked") + @Test + public void holdIsNotAHold() throws Exception + { + // build json content to send to server + List notAHold = Collections.singletonList(recordFolder); + String content = buildContent(record, notAHold); + + // expected exception + exception.expect(WebScriptException.class); + exception.expect(badRequest()); + + // execute web script + executeWebScript(Collections.EMPTY_MAP, content); + } + + /** + * Test for expected exception when adding an item to a hold + * that isn't a record or record folder. + */ + @SuppressWarnings("unchecked") + @Test + public void nodeRefIsNotARecordOrRecordFolder() throws Exception + { + // build json content to send to server + List notAHold = Collections.singletonList(recordFolder); + String content = buildContent(filePlanComponent, notAHold); + + // expected exception + exception.expect(WebScriptException.class); + exception.expect(badRequest()); + + // execute web script + executeWebScript(Collections.EMPTY_MAP, content); + } +} diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldPostUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldPostUnitTest.java new file mode 100644 index 0000000000..5ae5db0c77 --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldPostUnitTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.module.org_alfresco_module_rm.script.hold; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.util.Collections; + +import org.json.JSONObject; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Spy; +import org.springframework.extensions.webscripts.DeclarativeWebScript; + +/** + * Hold ReST API POST implementation unit test. + * + * @author Roy Wetherall + * @since 2.2 + */ +public class HoldPostUnitTest extends BaseHoldWebScriptWithContentUnitTest +{ + /** classpath location of ftl template for web script */ + private static final String WEBSCRIPT_TEMPLATE = WEBSCRIPT_ROOT_RM + "hold.post.json.ftl"; + + /** HoldPost webscript instance */ + protected @Spy @InjectMocks HoldPost webScript; + + /** + * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest#getWebScript() + */ + @Override + protected DeclarativeWebScript getWebScript() + { + return webScript; + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest#getWebScriptTemplate() + */ + @Override + protected String getWebScriptTemplate() + { + return WEBSCRIPT_TEMPLATE; + } + + /** + * Test that a record can be added to holds. + */ + @SuppressWarnings("unchecked") + @Test + public void addRecordToHolds() throws Exception + { + // build json to send to server + String content = buildContent(record, holds); + + // execute web script + JSONObject json = executeJSONWebScript(Collections.EMPTY_MAP, content); + assertNotNull(json); + + // verify that the record was added to the holds + verify(mockedHoldService, times(1)).addToHolds(holds, record); + } + + /** + * Test that a record folder can be added to holds. + */ + @SuppressWarnings("unchecked") + @Test + public void addRecordFolderToHolds() throws Exception + { + // build json to send to server + String content = buildContent(recordFolder, holds); + + // execute web script + JSONObject json = executeJSONWebScript(Collections.EMPTY_MAP, content); + assertNotNull(json); + + // verify that the record was added to the holds + verify(mockedHoldService, times(1)).addToHolds(holds, recordFolder); + } +} diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldPutUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldPutUnitTest.java new file mode 100644 index 0000000000..1e3c163be2 --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldPutUnitTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.module.org_alfresco_module_rm.script.hold; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.util.Collections; + +import org.json.JSONObject; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Spy; +import org.springframework.extensions.webscripts.DeclarativeWebScript; + +/** + * Hold ReST API PUT implementation unit test. + * + * @author Roy Wetherall + * @since 2.2 + */ +public class HoldPutUnitTest extends BaseHoldWebScriptWithContentUnitTest +{ + /** classpath location of ftl template for web script */ + private static final String WEBSCRIPT_TEMPLATE = WEBSCRIPT_ROOT_RM + "hold.put.json.ftl"; + + /** HoldPut webscript instance */ + protected @Spy @InjectMocks HoldPut webScript; + + /** + * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest#getWebScript() + */ + @Override + protected DeclarativeWebScript getWebScript() + { + return webScript; + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest#getWebScriptTemplate() + */ + @Override + protected String getWebScriptTemplate() + { + return WEBSCRIPT_TEMPLATE; + } + + /** + * Test that a record can be removed from holds. + */ + @SuppressWarnings("unchecked") + @Test + public void removeRecordFromHolds() throws Exception + { + // build json to send to server + String content = buildContent(record, holds); + + // execute web script + JSONObject json = executeJSONWebScript(Collections.EMPTY_MAP, content); + assertNotNull(json); + + // verify that the record was removed from holds + verify(mockedHoldService, times(1)).removeFromHolds(holds, record); + } + + /** + * Test that a record folder can be removed from holds. + */ + @SuppressWarnings("unchecked") + @Test + public void removeRecordFolderFromHolds() throws Exception + { + // build json to send to server + String content = buildContent(recordFolder, holds); + + // execute web script + JSONObject json = executeJSONWebScript(Collections.EMPTY_MAP, content); + assertNotNull(json); + + // verify that the record was removed from holds + verify(mockedHoldService, times(1)).removeFromHolds(holds, recordFolder); + } +} diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldsGetUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldsGetUnitTest.java new file mode 100644 index 0000000000..2a8f197022 --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/hold/HoldsGetUnitTest.java @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.module.org_alfresco_module_rm.script.hold; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doReturn; +import static org.alfresco.module.org_alfresco_module_rm.test.util.WebScriptExceptionMatcher.fileNotFound; + +import java.util.Collections; +import java.util.Map; + +import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Spy; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.WebScriptException; + +/** + * Holds ReST API GET implementation unit test. + * + * @author Roy Wetherall + * @since 2.2 + */ +public class HoldsGetUnitTest extends BaseHoldWebScriptUnitTest +{ + /** classpath location of ftl template for web script */ + private static final String WEBSCRIPT_TEMPLATE = WEBSCRIPT_ROOT_RM + "holds.get.json.ftl"; + + /** HoldsGet webscript instance */ + protected @Spy @InjectMocks HoldsGet webScript; + + /** + * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest#getWebScript() + */ + @Override + protected DeclarativeWebScript getWebScript() + { + return webScript; + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest#getWebScriptTemplate() + */ + @Override + protected String getWebScriptTemplate() + { + return WEBSCRIPT_TEMPLATE; + } + + /** + * Test the outcome of calling the web script with an invalid file plan + */ + @Test + public void invalidFilePlan() throws Exception + { + // setup web script parameters + Map parameters = buildParameters + ( + "store_type", filePlan.getStoreRef().getProtocol(), + "store_id", filePlan.getStoreRef().getIdentifier(), + "id", "imadethisup" + ); + + // setup expected exception + exception.expect(WebScriptException.class); + exception.expect(fileNotFound()); + + // execute web script + executeWebScript(parameters); + } + + /** + * Test the outcome of calling the web script with no file plan specified + * and with no default file plan created. + */ + @SuppressWarnings("unchecked") + @Test + public void defaultFilePlanDoesNotExist() throws Exception + { + // setup expected exception + exception.expect(WebScriptException.class); + exception.expect(fileNotFound()); + + // execute web script + executeWebScript(Collections.EMPTY_MAP); + } + + /** + * Test the successful retrieval of holds defined for a specified file + * plan. + */ + @Test + public void getHoldsForFilePlan() throws Exception + { + // setup interactions + doReturn(holds).when(mockedHoldService).getHolds(filePlan); + + // setup web script parameters + Map parameters = buildParameters + ( + "store_type", filePlan.getStoreRef().getProtocol(), + "store_id", filePlan.getStoreRef().getIdentifier(), + "id", filePlan.getId() + ); + + // execute web script + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + + // check the JSON result + testForBothHolds(json); + } + + /** + * Test the retrieval of holds for the default file plan. + */ + @SuppressWarnings("unchecked") + @Test + public void getHoldsForDefaultFilePlan() throws Exception + { + // setup interactions + doReturn(holds).when(mockedHoldService).getHolds(filePlan); + doReturn(filePlan).when(mockedFilePlanService).getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID); + + // execute web script + JSONObject json = executeJSONWebScript(Collections.EMPTY_MAP); + assertNotNull(json); + + // check the JSON result + testForBothHolds(json); + } + + /** + * Test the retrieval of holds that hold a specified node. + */ + @Test + public void getHoldsThatNodeRefIsHeldBy() throws Exception + { + // setup interactions + doReturn(holds).when(mockedHoldService).heldBy(record, true); + + // setup web script parameters + Map parameters = buildParameters + ( + "store_type", filePlan.getStoreRef().getProtocol(), + "store_id", filePlan.getStoreRef().getIdentifier(), + "id", filePlan.getId(), + "itemNodeRef", record.toString() + ); + + // execute web script + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + + // check the JSON result + testForBothHolds(json); + + } + + /** + * Test the retrieval of holds that a node is not held in. + */ + @Test + public void getHoldsThatNodeRefIsNotHeldBy() throws Exception + { + // setup interactions + doReturn(holds).when(mockedHoldService).heldBy(record, false); + + // setup web script parameters + Map parameters = buildParameters + ( + "store_type", filePlan.getStoreRef().getProtocol(), + "store_id", filePlan.getStoreRef().getIdentifier(), + "id", filePlan.getId(), + "itemNodeRef", record.toString(), + "includedInHold", "false" + ); + + // execute web script + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + + // check the JSON result + testForBothHolds(json); + } + + /** + * Helper method to test JSON object for the presence of both test holds. + * + * @param json json result from web script + */ + private void testForBothHolds(JSONObject json) throws Exception + { + // check the JSON result + assertTrue(json.has("data")); + assertTrue(json.getJSONObject("data").has("holds")); + + JSONArray jsonHolds = json.getJSONObject("data").getJSONArray("holds"); + assertNotNull(jsonHolds); + assertEquals(2, jsonHolds.length()); + + JSONObject hold1 = jsonHolds.getJSONObject(0); + assertNotNull(hold1); + assertEquals("hold1", hold1.getString("name")); + assertEquals(hold1NodeRef.toString(), hold1.getString("nodeRef")); + + JSONObject hold2 = jsonHolds.getJSONObject(1); + assertNotNull(hold2); + assertEquals("hold2", hold2.getString("name")); + assertEquals(hold2NodeRef.toString(), hold2.getString("nodeRef")); + } +} diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/AllUnitTestSuite.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java old mode 100755 new mode 100644 similarity index 77% rename from rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/AllUnitTestSuite.java rename to rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java index f5d000dd29..ca1eb72d62 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/AllUnitTestSuite.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java @@ -16,13 +16,16 @@ * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ -package org.alfresco.module.org_alfresco_module_rm; +package org.alfresco.module.org_alfresco_module_rm.test; import org.alfresco.module.org_alfresco_module_rm.forms.RecordsManagementTypeFormFilterUnitTest; import org.alfresco.module.org_alfresco_module_rm.hold.HoldServiceImplUnitTest; import org.alfresco.module.org_alfresco_module_rm.jscript.app.evaluator.TransferEvaluatorUnitTest; import org.alfresco.module.org_alfresco_module_rm.record.RecordMetadataBootstrapUnitTest; import org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImplUnitTest; +import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldPostUnitTest; +import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldPutUnitTest; +import org.alfresco.module.org_alfresco_module_rm.script.hold.HoldsGetUnitTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @@ -40,7 +43,10 @@ import org.junit.runners.Suite.SuiteClasses; RecordServiceImplUnitTest.class, RecordsManagementTypeFormFilterUnitTest.class, HoldServiceImplUnitTest.class, - TransferEvaluatorUnitTest.class + TransferEvaluatorUnitTest.class, + HoldsGetUnitTest.class, + HoldPostUnitTest.class, + HoldPutUnitTest.class }) public class AllUnitTestSuite { diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/BaseUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseUnitTest.java old mode 100755 new mode 100644 similarity index 64% rename from rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/BaseUnitTest.java rename to rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseUnitTest.java index 40ea420c7d..43d52c48a0 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/BaseUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseUnitTest.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ -package org.alfresco.module.org_alfresco_module_rm; +package org.alfresco.module.org_alfresco_module_rm.test.util; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; @@ -29,6 +29,7 @@ import java.util.List; import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; +import org.alfresco.module.org_alfresco_module_rm.hold.HoldService; import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.record.RecordService; @@ -44,13 +45,19 @@ import org.alfresco.service.namespace.QNamePattern; import org.alfresco.util.GUID; import org.alfresco.util.collections.CollectionUtils; import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.ExpectedException; import org.mockito.Mock; import org.mockito.MockitoAnnotations; /** - * Unit test for RecordServiceImpl + * Base unit test. + *

+ * Contains core and records management service mocks ready for injection. Helper methods + * provide an easy way to build RM or Alfresco constructs for use in tests. * * @author Roy Wetherall + * @since 2.2 */ public class BaseUnitTest implements RecordsManagementModel { @@ -69,6 +76,11 @@ public class BaseUnitTest implements RecordsManagementModel @Mock(name="filePlanService") protected FilePlanService mockedFilePlanService; @Mock(name="recordFolderService") protected RecordFolderService mockedRecordFolderService; @Mock(name="recordService") protected RecordService mockedRecordService; + @Mock(name="holdService") protected HoldService mockedHoldService; + + /** expected exception rule */ + @Rule + public ExpectedException exception = ExpectedException.none(); /** * Test method setup @@ -78,19 +90,21 @@ public class BaseUnitTest implements RecordsManagementModel { MockitoAnnotations.initMocks(this); + // setup file plan filePlan = generateNodeRef(TYPE_FILE_PLAN); + doReturn(true).when(mockedFilePlanService).isFilePlan(filePlan); + + // setup basic file plan component filePlanComponent = generateNodeRef(); setupAsFilePlanComponent(filePlanComponent); - // set-up namespace service - when(mockedNamespaceService.getNamespaceURI(RM_PREFIX)).thenReturn(RM_URI); - when(mockedNamespaceService.getPrefixes(RM_URI)).thenReturn(CollectionUtils.unmodifiableSet(RM_PREFIX)); + // setup namespace service + doReturn(RM_URI).when(mockedNamespaceService).getNamespaceURI(RM_PREFIX); + doReturn(CollectionUtils.unmodifiableSet(RM_PREFIX)).when(mockedNamespaceService).getPrefixes(RM_URI); // setup record folder and record recordFolder = generateRecordFolder(); - doReturn(true).when(mockedRecordFolderService).isRecordFolder(recordFolder); record = generateRecord(); - doReturn(true).when(mockedRecordService).isRecord(record); // set record as child of record folder List result = new ArrayList(1); @@ -112,41 +126,84 @@ public class BaseUnitTest implements RecordsManagementModel return QName.createQName(RM_URI, GUID.generate()); } + /** + * Helper method to generate hold reference + * + * @param name hold name + * @return {@link NodeRef} node reference that will behave like a hold + */ + protected NodeRef generateHoldNodeRef(String name) + { + NodeRef hold = generateNodeRef(TYPE_HOLD); + doReturn(name).when(mockedNodeService).getProperty(hold, ContentModel.PROP_NAME); + doReturn(true).when(mockedHoldService).isHold(hold); + return hold; + } + + /** + * Helper method to generate record folder reference + * + * @return {@link NodeRef} node reference that will behave like a record folder + */ protected NodeRef generateRecordFolder() { NodeRef recordFolder = generateNodeRef(TYPE_RECORD_FOLDER); - setupAsFilePlanComponent(recordFolder); - return recordFolder; - + setupAsFilePlanComponent(recordFolder); + doReturn(true).when(mockedRecordFolderService).isRecordFolder(recordFolder); + return recordFolder; } + /** + * Helper method to generate a record node reference. + * + * @return {@link NodeRef} node reference that will behave like a record or type cm:content + */ protected NodeRef generateRecord() { NodeRef record = generateNodeRef(ContentModel.TYPE_CONTENT); setupAsFilePlanComponent(record); - doReturn(true).when(mockedNodeService).hasAspect(record, ASPECT_RECORD); + doReturn(true).when(mockedNodeService).hasAspect(record, ASPECT_RECORD); + doReturn(true).when(mockedRecordService).isRecord(record); return record; } + /** + * Helper method to setup a node reference as a file plan component. + * + * @param nodeRef {@link NodeRef} node reference that will now behave like a file plan component + */ protected void setupAsFilePlanComponent(NodeRef nodeRef) { doReturn(true).when(mockedNodeService).hasAspect(nodeRef, ASPECT_FILE_PLAN_COMPONENT); + doReturn(true).when(mockedFilePlanService).isFilePlanComponent(nodeRef); doReturn(filePlan).when(mockedFilePlanService).getFilePlan(nodeRef); doReturn(filePlan).when(mockedNodeService).getProperty(nodeRef, PROP_ROOT_NODEREF); } - + + /** + * Helper method to generate a node reference. + * + * @return {@link NodeRef} node reference that behaves like a node that exists in the spaces store + */ protected NodeRef generateNodeRef() { return generateNodeRef(null); } + /** + * Helper method to generate a node reference of a particular type. + * + * @param type content type qualified name + * @return {@link NodeRef} node reference that behaves like a node that exists in the spaces store with + * the content type provided + */ protected NodeRef generateNodeRef(QName type) { NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate()); - when(mockedNodeService.exists(nodeRef)).thenReturn(true); + when(mockedNodeService.exists(eq(nodeRef))).thenReturn(true); if (type != null) { - when(mockedNodeService.getType(nodeRef)).thenReturn(type); + when(mockedNodeService.getType(eq(nodeRef))).thenReturn(type); } return nodeRef; } diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseWebScriptUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseWebScriptUnitTest.java new file mode 100644 index 0000000000..2a0f18a927 --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseWebScriptUnitTest.java @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.module.org_alfresco_module_rm.test.util; + +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONObject; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.springframework.extensions.surf.util.Content; +import org.springframework.extensions.webscripts.Container; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Description; +import org.springframework.extensions.webscripts.Description.RequiredCache; +import org.springframework.extensions.webscripts.DescriptionExtension; +import org.springframework.extensions.webscripts.FormatRegistry; +import org.springframework.extensions.webscripts.Match; +import org.springframework.extensions.webscripts.ScriptProcessorRegistry; +import org.springframework.extensions.webscripts.SearchPath; +import org.springframework.extensions.webscripts.TemplateProcessorRegistry; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; +import org.springframework.extensions.webscripts.json.JSONUtils; +import org.springframework.extensions.webscripts.processor.FTLTemplateProcessor; + +import freemarker.cache.ClassTemplateLoader; +import freemarker.cache.TemplateLoader; + +/** + * Base Web Script Unit Test. + *

+ * Provides helper methods that mock the nessesery classes needed to execute + * a Java backed webscript that implements DeclarativeWebScript. + *

+ * Note that execution of java script controllers is not currently supported. + * + * @author Roy Wetherall + * @since 2.2 + */ +public abstract class BaseWebScriptUnitTest extends BaseUnitTest +{ + /** web script root folder for RM webscripts */ + protected static final String WEBSCRIPT_ROOT_RM = "alfresco/templates/webscripts/org/alfresco/rma/"; + + /** + * @return declarative webscript + */ + protected abstract DeclarativeWebScript getWebScript(); + + /** + * @return classpath location of webscript template + */ + protected abstract String getWebScriptTemplate(); + + /** + * Helper method to build a map of web script parameter values + * mimicking those provided on the URL + * + * @param values + * @return + */ + protected Map buildParameters(String ... values) + { + Map result = new HashMap(values.length/2); + for (int i = 0; i < values.length; i=i+2) + { + String key = values[i]; + String value = values[i+1]; + result.put(key, value); + } + return result; + } + + /** + * + * @param parameters + * @return + * @throws Exception + */ + protected JSONObject executeJSONWebScript(Map parameters) throws Exception + { + return executeJSONWebScript(parameters, null); + } + + /** + * Execute web script and convert result into a JSON object. + * + * @param parameters map of all parameter values + * @return {@link JSONObject} result, parsed into a JSON object + */ + protected JSONObject executeJSONWebScript(Map parameters, String content) throws Exception + { + String result = executeWebScript(parameters, content); + return new JSONObject(result); + } + + /** + * + * @param parameters + * @return + * @throws Exception + */ + protected String executeWebScript(Map parameters) throws Exception + { + return executeWebScript( parameters, null); + } + + /** + * Execute web script and return result as a string. + * + * @param parameters map of all parameter values + * @return {@link String} result of web script + */ + protected String executeWebScript(Map parameters, String content) throws Exception + { + DeclarativeWebScript webScript = getWebScript(); + String template = getWebScriptTemplate(); + + // initialise webscript + webScript.init(getMockedContainer(template), getMockedDescription()); + + // execute webscript + WebScriptResponse mockedResponse = getMockedWebScriptResponse(); + webScript.execute(getMockedWebScriptRequest(webScript, parameters, content), mockedResponse); + + // return results + return mockedResponse.getWriter().toString(); + } + + /** + * Helper method to get the mocked web script request. + * + * @param webScript declarative web script + * @param parameters web script parameter values + * @return {@link WebScriptRequest} mocked web script request + */ + @SuppressWarnings("rawtypes") + protected WebScriptRequest getMockedWebScriptRequest(DeclarativeWebScript webScript, final Map parameters, String content) throws Exception + { + Match match = new Match(null, parameters, null, webScript); + org.springframework.extensions.webscripts.Runtime mockedRuntime = mock(org.springframework.extensions.webscripts.Runtime.class); + + WebScriptRequest mockedRequest = mock(WebScriptRequest.class); + doReturn(match).when(mockedRequest).getServiceMatch(); + doReturn(mockedRuntime).when(mockedRequest).getRuntime(); + + if (content != null && !content.isEmpty()) + { + Content mockedContent = mock(Content.class); + doReturn(content).when(mockedContent).getContent(); + doReturn(mockedContent).when(mockedRequest).getContent(); + } + + String [] paramNames = (String[])parameters.keySet().toArray(new String[parameters.size()]); + doReturn(paramNames).when(mockedRequest).getParameterNames(); + doAnswer(new Answer() + { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable + { + String paramName = (String)invocation.getArguments()[0]; + return parameters.get(paramName); + } + + }).when(mockedRequest).getParameter(anyString()); + + doReturn(new String[0]).when(mockedRequest).getHeaderNames(); + doReturn("json").when(mockedRequest).getFormat(); + + return mockedRequest; + } + + /** + * Helper method to get mocked web script response + * + * @return {@link WebScriptResponse} mocked web script response + */ + protected WebScriptResponse getMockedWebScriptResponse() throws Exception + { + WebScriptResponse mockedResponse = mock(WebScriptResponse.class); + StringWriter writer = new StringWriter(); + doReturn(writer).when(mockedResponse).getWriter(); + return mockedResponse; + } + + /** + * Helper method to get mocked container object. + * + * @param template classpath location of webscripts ftl template + * @return {@link Container} mocked container + */ + protected Container getMockedContainer(String template) throws Exception + { + FormatRegistry mockedFormatRegistry = mock(FormatRegistry.class); + doReturn("application/json").when(mockedFormatRegistry).getMimeType(anyString(), anyString()); + + ScriptProcessorRegistry mockedScriptProcessorRegistry = mock(ScriptProcessorRegistry.class); + doReturn(null).when(mockedScriptProcessorRegistry).findValidScriptPath(anyString()); + + TemplateProcessorRegistry mockedTemplateProcessorRegistry = mock(TemplateProcessorRegistry.class); + doReturn(template).when(mockedTemplateProcessorRegistry).findValidTemplatePath(anyString()); + + FTLTemplateProcessor ftlTemplateProcessor = new FTLTemplateProcessor() + { + @Override + protected TemplateLoader getTemplateLoader() + { + return new ClassTemplateLoader(getClass(), "/"); + } + }; + ftlTemplateProcessor.init(); + + doReturn(ftlTemplateProcessor).when(mockedTemplateProcessorRegistry).getTemplateProcessor(anyString()); + + Container mockedContainer = mock(Container.class); + doReturn(mockedFormatRegistry).when(mockedContainer).getFormatRegistry(); + doReturn(mockedScriptProcessorRegistry).when(mockedContainer).getScriptProcessorRegistry(); + doReturn(mockedTemplateProcessorRegistry).when(mockedContainer).getTemplateProcessorRegistry(); + + Map containerTemplateParameters = new HashMap(5); + containerTemplateParameters.put("jsonUtils", new JSONUtils()); + doReturn(containerTemplateParameters).when(mockedContainer).getTemplateParameters(); + + SearchPath mockedSearchPath = mock(SearchPath.class); + doReturn(false).when(mockedSearchPath).hasDocument(anyString()); + doReturn(mockedSearchPath).when(mockedContainer).getSearchPath(); + + // setup description + Description mockDescription = mock(Description.class); + doReturn(mock(RequiredCache.class)).when(mockDescription).getRequiredCache(); + + return mockedContainer; + } + + /** + * Helper method to get mocked description class + * + * @return {@link DescriptionExtension} mocked description class + */ + protected Description getMockedDescription() + { + Description mockedDescription = mock(Description.class); + doReturn(mock(RequiredCache.class)).when(mockedDescription).getRequiredCache(); + return mockedDescription; + } +} diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/WebScriptExceptionMatcher.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/WebScriptExceptionMatcher.java new file mode 100644 index 0000000000..046b9fccf6 --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/WebScriptExceptionMatcher.java @@ -0,0 +1,80 @@ +package org.alfresco.module.org_alfresco_module_rm.test.util; + +import org.junit.internal.matchers.TypeSafeMatcher; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; + +/** + * Web script exception matcher. + *

+ * Allows use to check whether the raised web script exception has the correct + * status number or not. + * + * @author Roy Wetherall + * @since 2.2 + */ +@SuppressWarnings("deprecation") +public class WebScriptExceptionMatcher extends TypeSafeMatcher +{ + /** + * Helper method to create a matcher for the file not found (404) + * exception status. + * + * @return {@link WebScriptExceptionMatcher} + */ + public static WebScriptExceptionMatcher fileNotFound() + { + return new WebScriptExceptionMatcher(Status.STATUS_NOT_FOUND); + } + + /** + * Helper method to create a matcher for the bad request status (400) + * exception status. + * + * @return {@link WebScriptExceptionMatcher} + */ + public static WebScriptExceptionMatcher badRequest() + { + return new WebScriptExceptionMatcher(Status.STATUS_BAD_REQUEST); + } + + /** expected status */ + public int expectedStatus; + + /** actual status */ + public int actualStatus; + + /** + * Constructor + * + * @param expectedStatus expected status + */ + public WebScriptExceptionMatcher(int expectedStatus) + { + this.expectedStatus = expectedStatus; + } + + /** + * Determines if the expected outcome matches the actual + * outcome. + * + * @return true if matches, false otherwise + */ + @Override + public boolean matchesSafely(WebScriptException exception) + { + actualStatus = exception.getStatus(); + return (actualStatus == expectedStatus); + } + + /** + * Describe unexpected outcome. + */ + @Override + public void describeTo(org.hamcrest.Description description) + { + description.appendValue(actualStatus) + .appendText(" was found instead of ") + .appendValue(expectedStatus); + } +} \ No newline at end of file