From 381840c2bde243477cf9b6d35b79bacdf9b4028a Mon Sep 17 00:00:00 2001 From: Alan Davis Date: Sat, 31 Jan 2015 09:33:48 +0000 Subject: [PATCH] Merged HEAD-BUG-FIX (5.1/Cloud) to HEAD (5.0/Cloud) 85731: MNT-12461: Bring back the changes of MNT-11660 - moved the new test from web-framework-commons to web-client, where it belongs (w-f-c shouldn't depend on remote-api) - renamed the test FormUIGetRestApiIT because it is an integration test, not a unit test - disabled the execution of this test. Needs more work to sort it out - probably missing dependencies 85650: Reverse Merge HEAD-BUG-FIX (5.0/Cloud) << Breaks the build >> 85615: Merged V4.2-BUG-FIX (4.2.4) to HEAD-BUG-FIX (5.0/Cloud) <> 80815: Fix Build (pt2) Reverse Merge HEAD-BUG-FIX (5.0/Cloud) 80357: Merged V4.2-BUG-FIX (4.2.4) to HEAD-BUG-FIX (5.0/Cloud) 79075: Merged V4.2.3 (4.2.3) to V4.2-BUG-FIX (4.2.4) 78918: Merged DEV to V4.2.3 (4.2.3) 78889: MNT-11660 : Share textarea.ftl appears even when the aspect of the property is not applied Was added new unit test. 79079: Merged V4.2.3 (4.2.3) to V4.2-BUG-FIX (4.2.4) 78994: Merged DEV to PATCHES/V4.2.3 78981 : MNT-11660 : Share textarea.ftl appears even when the aspect of the property is not applied Updated some code for unit test. 79081: Merged V4.2.3 (4.2.3) to V4.2-BUG-FIX (4.2.4) 79043: MNT-11660 : Share textarea.ftl appears even when the aspect of the property is not applied Added webframeworkcommons classpath for unit test in build.xml . 79138: MNT-11660 : Share textarea.ftl appears even when the aspect of the property is not applied Rename config file for test and update unit test source. 79140: MNT-11660 : Share textarea.ftl appears even when the aspect of the property is not applied Deleted old config file for test. 79283: MNT-11660 : Share textarea.ftl appears even when the aspect of the property is not applied Added info messages to unit test 80123: MNT-11660 : Share textarea.ftl appears even when the aspect of the property is not applied Added info messages and log to unit test. 80207: MNT-11660 : Share textarea.ftl appears even when the aspect of the property is not applied Updated the freemarker template for test webscript 80261: MNT-11660 : Share textarea.ftl appears even when the aspect of the property is not applied Updated unit test. 80302: MNT-11660 : Share textarea.ftl appears even when the aspect of the property is not applied Updated unit test. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@94515 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- pom.xml | 20 +- .../web/scripts/forms/FormUIGetRestApiIT.java | 389 ++++++++++++++++++ .../test/components/form/form.get.desc.xml | 5 + .../test/components/form/form.get.html.ftl | 23 ++ .../test/components/form/form.lib.ftl | 92 +++++ ...-application-context-webframework-test.xml | 26 ++ .../test-config-custom-forms.xml | 83 ++++ 7 files changed, 635 insertions(+), 3 deletions(-) create mode 100644 source/test-java/org/alfresco/web/scripts/forms/FormUIGetRestApiIT.java create mode 100644 source/test-resources/alfresco/site-webscripts/org/alfresco/test/components/form/form.get.desc.xml create mode 100644 source/test-resources/alfresco/site-webscripts/org/alfresco/test/components/form/form.get.html.ftl create mode 100644 source/test-resources/alfresco/site-webscripts/org/alfresco/test/components/form/form.lib.ftl create mode 100644 source/test-resources/alfresco/web-scripts-application-context-webframework-test.xml create mode 100644 source/test-resources/test-config-custom-forms.xml diff --git a/pom.xml b/pom.xml index d3e2f28571..c54337038e 100644 --- a/pom.xml +++ b/pom.xml @@ -151,6 +151,20 @@ tests test + + org.alfresco + alfresco-remote-api + ${project.version} + tests + test + + + org.springframework.extensions.surf + spring-webscripts + ${project.version} + tests + test + org.springframework spring-test @@ -428,9 +442,9 @@ - **/org/alfresco/web/app/servlet/DefaultRemoteUserMapperTest.java - **/org/alfresco/web/app/servlet/KerberosRemoteUserMapperTest.java - **/org/alfresco/web/forms/FormsTest.java + diff --git a/source/test-java/org/alfresco/web/scripts/forms/FormUIGetRestApiIT.java b/source/test-java/org/alfresco/web/scripts/forms/FormUIGetRestApiIT.java new file mode 100644 index 0000000000..15b53913c2 --- /dev/null +++ b/source/test-java/org/alfresco/web/scripts/forms/FormUIGetRestApiIT.java @@ -0,0 +1,389 @@ +/* + * 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.web.scripts.forms; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.model.Repository; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.ApplicationContextHelper; +import org.alfresco.util.GUID; +import org.alfresco.web.config.forms.FormConfigElement; +import org.alfresco.web.config.forms.FormField; +import org.alfresco.web.config.forms.FormsConfigElement; +import org.alfresco.web.config.forms.NodeTypeEvaluator; +import org.json.JSONException; +import org.json.JSONObject; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.extensions.config.Config; +import org.springframework.extensions.config.ConfigSource; +import org.springframework.extensions.config.source.ClassPathConfigSource; +import org.springframework.extensions.config.xml.XMLConfigService; +import org.springframework.extensions.surf.exception.ConnectorServiceException; +import org.springframework.extensions.webscripts.TestWebScriptServer; +import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.PostRequest; +import org.springframework.extensions.webscripts.TestWebScriptServer.Response; +import org.springframework.extensions.webscripts.connector.ResponseStatus; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONTokener; +import org.alfresco.repo.web.scripts.servlet.LocalTestRunAsAuthenticatorFactory; + +public class FormUIGetRestApiIT extends TestCase +{ + private static final Log log = LogFactory.getLog(FormUIGetRestApiIT.class); + + private final static String[] CONFIG_LOCATIONS = new String[] { "classpath:alfresco/application-context.xml", "classpath:alfresco/web-scripts-application-context.xml", + "classpath:alfresco/web-scripts-application-context-webframework-test.xml" }; + + private static ClassPathXmlApplicationContext ctx = (ClassPathXmlApplicationContext) ApplicationContextHelper.getApplicationContext(CONFIG_LOCATIONS); + + private static TestWebScriptServer server = (TestWebScriptServer) ctx.getBean("webscripts.web.framework.test"); + + protected NodeService nodeService; + protected FileFolderService fileFolderService; + protected Repository repositoryHelper; + protected NodeRef containerNodeRef; + protected TransactionService transactionService; + + private NodeRef folderWithoutAspect = null; + private NodeRef folderWithAspect = null; + + @Override + public void setUp() throws Exception + { + super.setUp(); + + this.fileFolderService = (FileFolderService) ctx.getBean("FileFolderService"); + this.repositoryHelper = (Repository) ctx.getBean("repositoryHelper"); + this.nodeService = (NodeService) ctx.getBean("NodeService"); + this.transactionService = (TransactionService) ctx.getBean("transactionService"); + + server.setServletAuthenticatorFactory(new LocalTestRunAsAuthenticatorFactory()); + + NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome(); + String guid = GUID.generate(); + + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName()); + + folderWithoutAspect = fileFolderService.create(companyHomeNodeRef, "folder_" + guid, ContentModel.TYPE_FOLDER).getNodeRef(); + assertNotNull("Doesn't create folder", folderWithoutAspect); + + folderWithAspect = fileFolderService.create(companyHomeNodeRef, "folder_aspect_" + guid, ContentModel.TYPE_FOLDER).getNodeRef(); + assertNotNull("Doesn't create folder", folderWithoutAspect); + // add 'dublincore' aspect + Map aspectProps = new HashMap(1); + aspectProps.put(ContentModel.PROP_SUBJECT, "Test subject"); + nodeService.addAspect(folderWithAspect, ContentModel.ASPECT_DUBLINCORE, aspectProps); + } + + @Override + public void tearDown() + { + if (folderWithoutAspect != null && fileFolderService.exists(folderWithoutAspect)) + { + fileFolderService.delete(folderWithoutAspect); + } + + if (folderWithAspect != null && fileFolderService.exists(folderWithAspect)) + { + fileFolderService.delete(folderWithAspect); + } + } + + public void testMNT11660() throws Exception + { + FormUIGet formUIGet = (FormUIGetExtend) ctx.getBean("webscript.org.alfresco.test.components.form.form.get"); + assertNotNull("'FormUIGetExtend' bean for test is null.", formUIGet); + + ConfigSource configSource = new ClassPathConfigSource("test-config-custom-forms.xml"); + XMLConfigService svc = new XMLConfigService(configSource); + svc.initConfig(); + + formUIGet.setConfigService(svc); + + GetRequest requestWithAspect = new GetRequest("/test/components/form?htmlid=template_default-formContainer&itemKind=node&itemId=" + folderWithAspect.toString() + + "&formId=null&mode=view"); + Response rspFormWithAspect = server.submitRequest(requestWithAspect.getMethod(), requestWithAspect.getFullUri(), requestWithAspect.getHeaders(), + requestWithAspect.getBody(), requestWithAspect.getEncoding(), requestWithAspect.getType()); + + assertEquals("The status of response is " + rspFormWithAspect.getStatus(), 200, rspFormWithAspect.getStatus()); + + String contentWithAspect = rspFormWithAspect.getContentAsString(); + log.info("Response form for node with dublincore aspect status is " + rspFormWithAspect.getStatus() + " content is " + contentWithAspect); + assertNotNull("Response content for 'contentWithAspect' is null", contentWithAspect); + assertTrue("Return the following content: " + contentWithAspect, contentWithAspect.contains("My Set")); + + GetRequest requestWithoutAspect = new GetRequest("/test/components/form?htmlid=template_default-formContainer&itemKind=node&itemId=" + folderWithoutAspect.toString() + + "&formId=null&mode=view"); + Response rspFormWithoutAspect = server.submitRequest(requestWithoutAspect.getMethod(), requestWithoutAspect.getFullUri(), requestWithoutAspect.getHeaders(), + requestWithoutAspect.getBody(), requestWithoutAspect.getEncoding(), requestWithoutAspect.getType()); + + assertEquals("The status of response is " + rspFormWithoutAspect.getStatus(), 200, rspFormWithoutAspect.getStatus()); + + String contentWithoutAspect = rspFormWithoutAspect.getContentAsString(); + log.info("Response form for node without aspect status is " + rspFormWithoutAspect.getStatus() + " content is " + contentWithoutAspect); + assertNotNull("Response content for 'contentWithoutAspect' is null", contentWithoutAspect); + assertFalse("Return the following content: " + contentWithoutAspect, contentWithoutAspect.contains("My Set")); + } + + private static class FormUIGetExtend extends FormUIGet + { + @Override + protected FormConfigElement getFormConfig(String itemId, String formId) + { + FormConfigElement formConfig = null; + + Config configResult = this.configService.getConfig(itemId); + FormsConfigElement formsConfig = (FormsConfigElement) configResult.getConfigElement(CONFIG_FORMS); + + assertNotNull("The ConfigElement object doesn't exist", formsConfig); + + if (formsConfig != null) + { + // Extract the form we are looking for + if (formsConfig != null) + { + // try and retrieve the specified form + if (formId != null && formId.length() > 0) + { + formConfig = formsConfig.getForm(formId); + } + + // fall back to the default form + if (formConfig == null) + { + formConfig = formsConfig.getDefaultForm(); + } + } + } + assertNotNull("The ConfigElement object doesn't exist", formConfig); + + return formConfig; + } + + private String getStringFromInputStream(InputStream is) + { + + BufferedReader br = null; + StringBuilder sb = new StringBuilder(); + + String line; + try + { + + br = new BufferedReader(new InputStreamReader(is)); + while ((line = br.readLine()) != null) + { + sb.append(line); + } + + } + catch (IOException e) + { + e.printStackTrace(); + } + finally + { + if (br != null) + { + try + { + br.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + + assertTrue("StringBuilder has 0 length", sb.length() > 0); + + return sb.toString(); + + } + + @Override + protected org.springframework.extensions.webscripts.connector.Response retrieveFormDefinition(String itemKind, String itemId, List visibleFields, + FormConfigElement formConfig) + { + org.springframework.extensions.webscripts.connector.Response response = null; + try + { + assertEquals("Parameter 'itemKind' isn't 'node' value", "node", itemKind); + assertFalse("itemId is empty", itemId != null && itemId.isEmpty()); + assertTrue("Visible fields are empty", visibleFields.size() > 0); + assertEquals("Form config 'name' field isn't 'form' value", "form", formConfig.getName()); + + ByteArrayInputStream bais = generateFormDefPostBody(itemKind, itemId, visibleFields, formConfig); + assertTrue("Can't read bytes from ByteArrayInputStream ", bais.available() > 0); + + String json = getStringFromInputStream(bais); + + log.info("Request 'formdefinitions' json is: " + json); + + PostRequest request = new PostRequest("/api/formdefinitions", json, "application/json"); + + org.springframework.extensions.webscripts.TestWebScriptServer.Response responseTest = server.submitRequest(request.getMethod(), request.getFullUri(), + request.getHeaders(), request.getBody(), request.getEncoding(), request.getType()); + + if (responseTest.getStatus() == 200) + { + JSONObject jsonParsedObject = new JSONObject(new JSONTokener(responseTest.getContentAsString())); + assertNotNull("JSON from responseTest is null", jsonParsedObject); + + Object dataObj = jsonParsedObject.get("data"); + assertEquals(JSONObject.class, dataObj.getClass()); + JSONObject rootDataObject = (JSONObject)dataObj; + + String item = (String)rootDataObject.get("item"); + String submissionUrl = (String)rootDataObject.get("submissionUrl"); + String type = (String)rootDataObject.get("type"); + JSONObject definitionObject = (JSONObject)rootDataObject.get("definition"); + JSONObject formDataObject = (JSONObject)rootDataObject.get("formData"); + + assertNotNull("Item is null ", item); + assertNotNull("Submission url is null ", submissionUrl); + assertNotNull("Type is null ", type); + assertNotNull("Definition is null ", definitionObject); + assertNotNull("Form data is null ", formDataObject); + + log.info("Response form 'formdefinitions' json 'data' is: " + dataObj); + + ResponseStatus status = new ResponseStatus(); + status.setCode(responseTest.getStatus()); + assertFalse("Response content is empty", responseTest.getContentAsString().isEmpty()); + response = new org.springframework.extensions.webscripts.connector.Response(responseTest.getContentAsString(), status); + assertNotNull("Response data is null.", response.getText()); + } + else + { + assertEquals("Response /api/formdefinitions is not 200 status", 200, responseTest.getStatus()); + } + + } + catch (Exception e) + { + log.error("Response form 'formdefinitions' exception : " + e.getMessage()); + } + + return response; + } + + @Override + protected Field generateFieldModel(ModelContext context, String fieldName, FormField fieldConfig) + { + Field field = null; + + try + { + // make sure the field is not ambiguous + if (isFieldAmbiguous(context, fieldName)) + { + field = generateTransientFieldModel(fieldName, "/org/alfresco/components/form/controls/ambiguous.ftl"); + } + else + { + JSONObject fieldDefinition = discoverFieldDefinition(context, fieldName); + + if (fieldDefinition != null) + { + // create the initial field model + field = new Field(); + + // populate the model with the appropriate data + processFieldIdentification(context, field, fieldDefinition, fieldConfig); + processFieldState(context, field, fieldDefinition, fieldConfig); + processFieldText(context, field, fieldDefinition, fieldConfig); + processFieldData(context, field, fieldDefinition, fieldConfig); + processFieldContent(context, field, fieldDefinition, fieldConfig); + } + else + { + // the field does not have a definition but may be a 'transient' field + field = generateTransientFieldModel(context, fieldName, fieldDefinition, fieldConfig); + } + } + } + catch (JSONException je) + { + field = null; + log.error("Generate field model exception: " + je.getMessage()); + } + + log.info("Generated field model " + fieldName + " is null"); + + return field; + } + +} + + public static class NodeTypeEvaluatorExtend extends NodeTypeEvaluator + { + protected String callMetadataService(String nodeString) throws ConnectorServiceException + { + GetRequest request = new GetRequest("/api/metadata?nodeRef=" + nodeString + "&shortQNames=true"); + Response response = null; + String jsonResponse = null; + try + { + response = server.submitRequest(request.getMethod(), request.getFullUri(), request.getHeaders(), request.getBody(), request.getEncoding(), request.getType()); + + if (response != null) + { + jsonResponse = response.getContentAsString(); + } + } + catch (UnsupportedEncodingException e) + { + throw new AlfrescoRuntimeException(e.getMessage()); + } + catch (IOException e) + { + throw new AlfrescoRuntimeException(e.getMessage()); + } + + assertNotNull("Response /api/metadata is null", jsonResponse); + + log.info("Response /api/metadata json is: " + jsonResponse); + + return jsonResponse; + } + } +} diff --git a/source/test-resources/alfresco/site-webscripts/org/alfresco/test/components/form/form.get.desc.xml b/source/test-resources/alfresco/site-webscripts/org/alfresco/test/components/form/form.get.desc.xml new file mode 100644 index 0000000000..bc2b8a154c --- /dev/null +++ b/source/test-resources/alfresco/site-webscripts/org/alfresco/test/components/form/form.get.desc.xml @@ -0,0 +1,5 @@ + + Form Component + Component that renders a form based on a repository form model + /test/components/form + \ No newline at end of file diff --git a/source/test-resources/alfresco/site-webscripts/org/alfresco/test/components/form/form.get.html.ftl b/source/test-resources/alfresco/site-webscripts/org/alfresco/test/components/form/form.get.html.ftl new file mode 100644 index 0000000000..d57611f8b1 --- /dev/null +++ b/source/test-resources/alfresco/site-webscripts/org/alfresco/test/components/form/form.get.html.ftl @@ -0,0 +1,23 @@ + <#import "form.lib.ftl" as formLib /> + + <#if error?exists> +
${error}
+ <#elseif form?exists> + <#assign formId=args.htmlid?js_string?html + "-form"> + <#assign formUI><#if args.formUI??>${args.formUI}<#else>true + + <@formLib.renderFormContainer formId=formId> + <#list form.structure as item> + <#if item.kind == "set"> + <#if item.children?size > 0> + <@formLib.renderSet set=item /> + + <#else> + <@formLib.renderField field=form.fields[item.id] /> + + + + + <#else> +
Form doesn't exist
+ \ No newline at end of file diff --git a/source/test-resources/alfresco/site-webscripts/org/alfresco/test/components/form/form.lib.ftl b/source/test-resources/alfresco/site-webscripts/org/alfresco/test/components/form/form.lib.ftl new file mode 100644 index 0000000000..cf23143c6e --- /dev/null +++ b/source/test-resources/alfresco/site-webscripts/org/alfresco/test/components/form/form.lib.ftl @@ -0,0 +1,92 @@ +<#macro renderFormContainer formId> +
+ <#if form.showCaption?? && form.showCaption> +
*${msg("form.required.fields")}
+ + + <#if form.mode != "view"> +
+ + + <#if form.mode == "create" && form.destination?? && form.destination?length > 0> + + + + <#if form.mode != "view" && form.redirect?? && form.redirect?length > 0> + + + +
+ <#nested> +
+ + <#if form.mode != "view"> + <@renderFormButtons formId=formId /> +
+ +
+ + +<#macro renderFormButtons formId> +
+ <#if form.showSubmitButton?? && form.showSubmitButton> +   + + <#if form.showResetButton?? && form.showResetButton> +   + + <#if form.showCancelButton?? && form.showCancelButton> + + +
+ + +<#macro renderField field> + <#if field.control?? && field.control.template??> + <#assign fieldHtmlId=args.htmlid?html + "_" + field.id > + <#include "${field.control.template}" /> + + + +<#macro renderSet set> +
+ <#if set.appearance??> + <#if set.appearance == "fieldset"> +
${set.label} + <#elseif set.appearance == "bordered-panel"> +
+
${set.label}
+
+ <#elseif set.appearance == "panel"> +
+
${set.label}
+
+ <#elseif set.appearance == "title"> +
${set.label}
+ <#elseif set.appearance == "whitespace"> +
+ + + + <#if set.template??> + <#include "${set.template}" /> + <#else> + <#list set.children as item> + <#if item.kind == "set"> + <@renderSet set=item /> + <#else> + <@renderField field=form.fields[item.id] /> + + + + + <#if set.appearance??> + <#if set.appearance == "fieldset"> +
+ <#elseif set.appearance == "panel" || set.appearance == "bordered-panel"> +
+ + + + + diff --git a/source/test-resources/alfresco/web-scripts-application-context-webframework-test.xml b/source/test-resources/alfresco/web-scripts-application-context-webframework-test.xml new file mode 100644 index 0000000000..baf345b5ec --- /dev/null +++ b/source/test-resources/alfresco/web-scripts-application-context-webframework-test.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + true + alfresco/site-webscripts + + + + + + + + + + + + \ No newline at end of file diff --git a/source/test-resources/test-config-custom-forms.xml b/source/test-resources/test-config-custom-forms.xml new file mode 100644 index 0000000000..c306d43989 --- /dev/null +++ b/source/test-resources/test-config-custom-forms.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + 255 + + + + + + + + true + + + + + true + aspect=cm:taggable + /api/tag/workspace/SpacesStore + tag + + + + + true + + + + + + + 10 + + + + + 255 + + + + +
+
+
+
\ No newline at end of file