diff --git a/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/pom.xml b/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/pom.xml index 3ce49c08..8ae1a146 100644 --- a/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/pom.xml +++ b/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/pom.xml @@ -218,6 +218,14 @@ + + ${groupId} + ${artifactId} + ${version} + tests + false + ${project.build.directory}/extensions + org.alfresco.maven alfresco-rad @@ -264,6 +272,20 @@ + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + + test-jar + + + + + diff --git a/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/src/test/java/platformsample/CustomContentModelIT.java b/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/src/test/java/platformsample/CustomContentModelIT.java new file mode 100644 index 00000000..5769e654 --- /dev/null +++ b/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/src/test/java/platformsample/CustomContentModelIT.java @@ -0,0 +1,191 @@ +#set($symbol_pound='#') +#set($symbol_dollar='$') +#set($symbol_escape='\' ) +/** + * Copyright (C) 2017 Alfresco Software Limited. + *

+ * This file is part of the Alfresco SDK project. + *

+ * 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. + */ +package ${package}.platformsample; + +import org.alfresco.model.ContentModel; +import org.alfresco.rad.test.AbstractAlfrescoIT; +import org.alfresco.rad.test.AlfrescoTestRunner; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.nodelocator.CompanyHomeNodeLocator; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Integration Test sample for a custom content model. + * See {@link DemoComponentIT} for more info. + * + * @author martin.bergljung@alfresco.com + * @since 3.0 + */ +@RunWith(value = AlfrescoTestRunner.class) +public class CustomContentModelIT extends AbstractAlfrescoIT { + private static final String ACME_MODEL_NS = "{http://www.acme.org/model/content/1.0}"; + private static final String ACME_MODEL_LOCALNAME = "contentModel"; + private static final String ACME_DOCUMENT_TYPE = "document"; + private static final String ACME_SECURITY_CLASSIFIED_ASPECT = "securityClassified"; + private static final String ACME_DOCUMENT_ID_PROPNAME = "documentId"; + + @Test + public void testCustomContentModelPresence() { + Collection allContentModels = getServiceRegistry().getDictionaryService().getAllModels(); + QName customContentModelQName = createQName(ACME_MODEL_LOCALNAME); + assertTrue("Custom content model " + customContentModelQName.toString() + + " is not present", allContentModels.contains(customContentModelQName)); + } + + @Test + public void testCreateAcmeDocument() { + // Create the ACME Doc file + QName type = createQName(ACME_DOCUMENT_TYPE); + String textContent = "Hello World!"; + String documentId = "DOC001"; + Map nodeProperties = new HashMap<>(); + nodeProperties.put(createQName(ACME_DOCUMENT_ID_PROPNAME), documentId); + nodeProperties.put(createQName("securityClassification"), "Company Confidential"); + NodeRef nodeRef = createNode("AcmeFile.txt", type, nodeProperties); + addFileContent(nodeRef, textContent); + + // Add an Aspect to the file (could be a custom aspect...) + Map aspectProperties = new HashMap<>(); + aspectProperties.put(ContentModel.PROP_TITLE, "Some Doc Title"); + aspectProperties.put(ContentModel.PROP_DESCRIPTION, "Some Doc Description"); + getServiceRegistry().getNodeService().addAspect(nodeRef, ContentModel.ASPECT_TITLED, aspectProperties); + + // Assert that the file is created correctly + assertEquals("Invalid type", type, getServiceRegistry().getNodeService().getType(nodeRef)); + assertTrue("Missing security aspect", + getServiceRegistry().getNodeService().hasAspect(nodeRef, createQName(ACME_SECURITY_CLASSIFIED_ASPECT))); + assertTrue("Missing titled aspect", + getServiceRegistry().getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_TITLED)); + assertEquals("Invalid property value", documentId, + getServiceRegistry().getNodeService().getProperty(nodeRef, createQName(ACME_DOCUMENT_ID_PROPNAME))); + readTextContent(nodeRef).equals(textContent); + + // Clean up node + if (nodeRef != null) { + getServiceRegistry().getNodeService().deleteNode(nodeRef); + } + } + + /** + * ==================== Helper Methods ============================================================================ + */ + + /** + * Create a QName for the ACME content model + * + * @param localname the local content model name without namespace specified + * @return the full ACME QName including namespace + */ + private QName createQName(String localname) { + return QName.createQName(ACME_MODEL_NS + localname); + } + + /** + * Create a new node, such as a file or a folder, with passed in type and properties + * + * @param name the name of the file or folder + * @param type the content model type + * @param properties the properties from the content model + * @return the Node Reference for the newly created node + */ + private NodeRef createNode(String name, QName type, Map properties) { + NodeRef parentFolderNodeRef = getCompanyHomeNodeRef(); + QName associationType = ContentModel.ASSOC_CONTAINS; + QName associationQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, + QName.createValidLocalName(name)); + properties.put(ContentModel.PROP_NAME, name); + ChildAssociationRef parentChildAssocRef = getServiceRegistry().getNodeService().createNode( + parentFolderNodeRef, associationType, associationQName, type, properties); + + return parentChildAssocRef.getChildRef(); + } + + /** + * Add some text content to a file node + * + * @param nodeRef the node reference for the file that should have some text content added to it + * @param fileContent the text content + */ + private void addFileContent(NodeRef nodeRef, String fileContent) { + boolean updateContentPropertyAutomatically = true; + ContentWriter writer = getServiceRegistry().getContentService().getWriter(nodeRef, ContentModel.PROP_CONTENT, + updateContentPropertyAutomatically); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.setEncoding("UTF-8"); + writer.putContent(fileContent); + } + + /** + * Read text content for passed in file Node Reference + * + * @param nodeRef the node reference for a file containing text + * @return the text content + */ + private String readTextContent(NodeRef nodeRef) { + ContentReader reader = getServiceRegistry().getContentService().getReader(nodeRef, ContentModel.PROP_CONTENT); + if (reader == null) { + return ""; // Maybe it was a folder after all + } + + InputStream is = reader.getContentInputStream(); + try { + return IOUtils.toString(is, "UTF-8"); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } finally { + if (is != null) { + try { + is.close(); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + } + + /** + * Get the node reference for the /Company Home top folder in Alfresco. + * Use the standard node locator service. + * + * @return the node reference for /Company Home + */ + private NodeRef getCompanyHomeNodeRef() { + return getServiceRegistry().getNodeLocatorService().getNode(CompanyHomeNodeLocator.NAME, null, null); + } +} diff --git a/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/src/test/java/platformsample/DemoComponentIT.java b/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/src/test/java/platformsample/DemoComponentIT.java new file mode 100644 index 00000000..9b7b4f60 --- /dev/null +++ b/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/src/test/java/platformsample/DemoComponentIT.java @@ -0,0 +1,67 @@ +#set($symbol_pound='#') +#set($symbol_dollar='$') +#set($symbol_escape='\' ) +/** + * Copyright (C) 2017 Alfresco Software Limited. + *

+ * This file is part of the Alfresco SDK project. + *

+ * 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. + */ +package ${package}.platformsample; + +import org.alfresco.rad.test.AbstractAlfrescoIT; +import org.alfresco.rad.test.AlfrescoTestRunner; +import org.alfresco.rad.test.Remote; +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.repository.NodeRef; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Integration Test of the DemoComponent using the Alfresco Test Runner. + * The Alfresco Test Runner (i.e. AlfrescoTestRunner.class) will check if it is running in an Alfresco instance, + * if so it will execute normally locally. On the other hand, if it detects no + * Alfresco Spring context, then it will make a call to a custom Web Script that + * will execute this test in the running container remotely. The remote location is + * determined by the @Remote config. + * + * @author martin.bergljung@alfresco.com + * @since 3.0 + */ +@RunWith(value = AlfrescoTestRunner.class) +public class DemoComponentIT extends AbstractAlfrescoIT { + + @Test + public void testGetCompanyHome() { + DemoComponent demoComponent = (DemoComponent) getApplicationContext().getBean("${package}.DemoComponent"); + NodeRef companyHome = demoComponent.getCompanyHome(); + assertNotNull(companyHome); + String companyHomePath = getServiceRegistry().getNodeService().getPath(companyHome).toPrefixString(getServiceRegistry().getNamespaceService()); + assertNotNull(companyHomePath); + assertEquals("/app:company_home", companyHomePath); + } + + @Test + public void testChildNodesCount() { + DemoComponent demoComponent = (DemoComponent) getApplicationContext().getBean("${package}.DemoComponent"); + NodeRef companyHome = demoComponent.getCompanyHome(); + int childNodeCount = demoComponent.childNodesCount(companyHome); + assertNotNull(childNodeCount); + // There are 7 folders by default under Company Home + assertEquals(7, childNodeCount); + } +} \ No newline at end of file diff --git a/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/src/test/java/platformsample/HelloWorldWebScriptIT.java b/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/src/test/java/platformsample/HelloWorldWebScriptIT.java new file mode 100644 index 00000000..31e20703 --- /dev/null +++ b/archetypes/alfresco-platform-jar-archetype/src/main/resources/archetype-resources/src/test/java/platformsample/HelloWorldWebScriptIT.java @@ -0,0 +1,85 @@ +#set($symbol_pound='#') +#set($symbol_dollar='$') +#set($symbol_escape='\' ) +/** + * Copyright (C) 2017 Alfresco Software Limited. + *

+ * This file is part of the Alfresco SDK project. + *

+ * 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. + */ +package ${package}.platformsample; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Integration Test (IT) for Hello World web script. + * + * @author martin.bergljung@alfresco.com + * @version 1.0 + * @since 3.0 + */ +public class HelloWorldWebScriptIT { + + private static final String ACS_ENDPOINT_PROP = "acs.endpoint.path"; + private static final String ACS_DEFAULT_ENDPOINT = "http://localhost:8080/alfresco"; + + @Test + public void testWebScriptCall() throws Exception { + String webscriptURL = getPlatformEndpoint() + "/service/sample/helloworld"; + String expectedResponse = "Message: 'Hello from JS!' 'HelloFromJava'"; + + // Login credentials for Alfresco Repo + CredentialsProvider provider = new BasicCredentialsProvider(); + UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("admin", "admin"); + provider.setCredentials(AuthScope.ANY, credentials); + + // Create HTTP Client with credentials + CloseableHttpClient httpclient = HttpClientBuilder.create() + .setDefaultCredentialsProvider(provider) + .build(); + + // Execute Web Script call + try { + HttpGet httpget = new HttpGet(webscriptURL); + HttpResponse httpResponse = httpclient.execute(httpget); + assertEquals("Incorrect HTTP Response Status", + HttpStatus.SC_OK, httpResponse.getStatusLine().getStatusCode()); + HttpEntity entity = httpResponse.getEntity(); + assertNotNull("Response from Web Script is null", entity); + assertEquals("Incorrect Web Script Response", expectedResponse, EntityUtils.toString(entity)); + } finally { + httpclient.close(); + } + } + + private String getPlatformEndpoint() { + final String platformEndpoint = System.getProperty(ACS_ENDPOINT_PROP); + return StringUtils.isNotBlank(platformEndpoint) ? platformEndpoint : ACS_DEFAULT_ENDPOINT; + } +} \ No newline at end of file diff --git a/archetypes/archetypes-it/src/test/java/org/alfresco/maven/archetype/PlatformJarArchetypeIT.java b/archetypes/archetypes-it/src/test/java/org/alfresco/maven/archetype/PlatformJarArchetypeIT.java index 1aee782f..d54fcbb9 100644 --- a/archetypes/archetypes-it/src/test/java/org/alfresco/maven/archetype/PlatformJarArchetypeIT.java +++ b/archetypes/archetypes-it/src/test/java/org/alfresco/maven/archetype/PlatformJarArchetypeIT.java @@ -32,11 +32,19 @@ public class PlatformJarArchetypeIT extends AbstractArchetypeIT { LOGGER.info("Building the generated project {}", archetypeProperties.getProjectArtifactId()); LOGGER.info("---------------------------------------------------------------------"); - // Since creating the archetype was successful, we now want to actually build the generated project + // Since creating the archetype was successful, we now want to actually build the generated project executing the integration tests + // Execute a purge to ensure old data don't make the test fail + ProcessBuilder purge = getProcessBuilder("purge"); + purge.start().waitFor(); + ProcessBuilder pb = getProcessBuilder("build_test"); + pb.start().waitFor(); + + // Verify the execution of the integration tests of the project were successful Verifier verifier = new Verifier(projectPath); verifier.setAutoclean(false); - verifier.executeGoal("install"); + verifier.setLogFileName(LOG_FILENAME); printVerifierLog("PROJECT BUILD", verifier, LOGGER); verifier.verifyErrorFreeLog(); + verifier.verifyTextInLog("Tests run: 5, Failures: 0, Errors: 0, Skipped: 0"); } }