Improve ETSI NS UI test 53/120353/2
authorandre.schmid <andre.schmid@est.tech>
Fri, 9 Apr 2021 08:59:07 +0000 (09:59 +0100)
committerChristophe Closset <christophe.closset@intl.att.com>
Mon, 12 Apr 2021 08:37:05 +0000 (08:37 +0000)
- import a ETSI VNF that has the tosca.capabilities.nfv.VirtualLinkable
requirement;
- externalize the tosca.capabilities.nfv.VirtualLinkable requirement
and certify the imported ETSI VNF;
- on the created ETSI NS Service (already existing flow), adds two
instances of the imported ETSI VNF and a NsVirtualLink;
- create a relationship between the two ETSI VNF to the NsVirtualLink,
through the tosca.capabilities.nfv.VirtualLinkable requirement/
capability;
- checks for the new nodes and relationship in the generated ETSI NS
package.

Change-Id: I57fa3079f473c7afcb7569941f870233ce7bdcca
Issue-ID: SDC-3550
Signed-off-by: André Schmid <andre.schmid@est.tech>
30 files changed:
catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/req-capabilities-tab/requirement-list/requirement-list.component.html
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/composition/RelationshipInformation.java [new file with mode: 0644]
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiNetworkServiceUiTests.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiOnboardVnfCnfUiTests.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ImportVfcUiTest.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/AddNodeToCompositionFlow.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CheckEtsiNsPropertiesFlow.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateVlmFlow.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateVspFlow.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/DownloadCsarArtifactFlow.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/EditServicePropertiesFlow.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/composition/CreateRelationshipFlow.java [new file with mode: 0644]
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AbstractPageObject.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ComponentCertificationModal.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ComponentPage.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourceCreatePage.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourceLeftSideMenu.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourceWorkspaceTopBarComponent.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ServiceComponentPage.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/TopNavComponent.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionCanvasComponent.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionDetailSideBarComponent.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionPage.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionRequirementsCapabilitiesTab.java [new file with mode: 0644]
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/RelationshipWizardComponent.java [new file with mode: 0644]
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/RelationshipWizardRequirementCapabilityComponent.java [new file with mode: 0644]
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/home/HomePage.java
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/utilities/LoaderHelper.java
integration-tests/src/test/resources/Files/VNFs/etsi-vnf-virtual-linkable.csar [new file with mode: 0644]
integration-tests/src/test/resources/ci/testSuites/frontend/onapUiSanity.xml

index 291b103..ebaed04 100644 (file)
@@ -17,7 +17,7 @@
                          *ngIf="isInstanceSelected">
                         <checkbox
                                 class="checkbox-label"
-                                data-tests-id="checkbox-mark-as-external"
+                                [attr.data-tests-id]="'checkbox-mark-as-external-' + requirement.name"
                                 [label]="'External'"
                                 (checkedChange)="onMarkAsExternal(requirement)"
                                 [(checked)]="requirement.external"
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/composition/RelationshipInformation.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/composition/RelationshipInformation.java
new file mode 100644 (file)
index 0000000..4e2b0d5
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.sdc.frontend.ci.tests.datatypes.composition;
+
+import lombok.Data;
+
+/**
+ * Holds information about a relationship between two nodes/component instances.
+ */
+@Data
+public class RelationshipInformation {
+
+    final String fromNode;
+    final String fromCapability;
+    final String toNode;
+    final String toRequirement;
+
+}
index 0826113..22bde40 100644 (file)
@@ -22,32 +22,54 @@ package org.onap.sdc.frontend.ci.tests.execute.sanity;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.hasKey;
+import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.junit.Assert.fail;
 
+import com.aventstack.extentreports.Status;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
 import org.apache.commons.io.FilenameUtils;
 import org.junit.jupiter.api.Assertions;
+import org.onap.sdc.backend.ci.tests.datatypes.enums.ComponentType;
 import org.onap.sdc.backend.ci.tests.datatypes.enums.ServiceCategoriesEnum;
+import org.onap.sdc.backend.ci.tests.datatypes.enums.XnfTypeEnum;
+import org.onap.sdc.backend.ci.tests.utils.general.ElementFactory;
+import org.onap.sdc.frontend.ci.tests.datatypes.ComponentData;
 import org.onap.sdc.frontend.ci.tests.datatypes.ServiceCreateData;
+import org.onap.sdc.frontend.ci.tests.datatypes.composition.RelationshipInformation;
 import org.onap.sdc.frontend.ci.tests.exception.UnzipException;
 import org.onap.sdc.frontend.ci.tests.execute.setup.DriverFactory;
+import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions;
 import org.onap.sdc.frontend.ci.tests.execute.setup.SetupCDTest;
+import org.onap.sdc.frontend.ci.tests.flow.AddNodeToCompositionFlow;
 import org.onap.sdc.frontend.ci.tests.flow.CheckEtsiNsPropertiesFlow;
+import org.onap.sdc.frontend.ci.tests.flow.CreateResourceFromVspFlow;
 import org.onap.sdc.frontend.ci.tests.flow.CreateServiceFlow;
+import org.onap.sdc.frontend.ci.tests.flow.CreateVlmFlow;
+import org.onap.sdc.frontend.ci.tests.flow.CreateVspFlow;
 import org.onap.sdc.frontend.ci.tests.flow.DownloadCsarArtifactFlow;
 import org.onap.sdc.frontend.ci.tests.flow.EditServicePropertiesFlow;
+import org.onap.sdc.frontend.ci.tests.flow.ImportVspFlow;
+import org.onap.sdc.frontend.ci.tests.flow.composition.CreateRelationshipFlow;
 import org.onap.sdc.frontend.ci.tests.flow.exception.UiTestFlowRuntimeException;
+import org.onap.sdc.frontend.ci.tests.pages.ComponentPage;
+import org.onap.sdc.frontend.ci.tests.pages.ResourceCreatePage;
 import org.onap.sdc.frontend.ci.tests.pages.ServiceComponentPage;
 import org.onap.sdc.frontend.ci.tests.pages.TopNavComponent;
+import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionDetailSideBarComponent;
+import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionDetailSideBarComponent.CompositionDetailTabName;
+import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionPage;
+import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionRequirementsCapabilitiesTab;
 import org.onap.sdc.frontend.ci.tests.pages.component.workspace.ToscaArtifactsPage;
 import org.onap.sdc.frontend.ci.tests.pages.home.HomePage;
 import org.onap.sdc.frontend.ci.tests.utilities.FileHandling;
+import org.openecomp.sdc.be.model.ComponentInstance;
 import org.openqa.selenium.WebDriver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -59,16 +81,32 @@ public class EtsiNetworkServiceUiTests extends SetupCDTest {
     private static final Logger LOGGER = LoggerFactory.getLogger(EtsiNetworkServiceUiTests.class);
 
     private WebDriver webDriver;
+    private ComponentInstance virtualLinkableVnf1;
+    private ComponentInstance virtualLinkableVnf2;
+    private ComponentInstance nsVirtualLink;
 
     @Test
-    public void createEtsiNetworkService() throws UnzipException {
+    public void etsiNetworkServiceTest() throws UnzipException {
         webDriver = DriverFactory.getDriver();
 
-        final CreateServiceFlow createServiceFlow = createService();
+        createVlm();
+        final String resourceName = createVsp();
+        ResourceCreatePage resourceCreatePage = importVsp(resourceName);
+        resourceCreatePage = createAndCertifyVf(resourceName, resourceCreatePage);
+        resourceCreatePage.isLoaded();
+        final HomePage homePage = resourceCreatePage.goToHomePage();
+        homePage.isLoaded();
+
+        final ServiceCreateData serviceCreateData = createServiceFormData();
+        final CreateServiceFlow createServiceFlow = createService(serviceCreateData);
+
         final CheckEtsiNsPropertiesFlow checkEtsiNsPropertiesFlow = checkServiceProperties();
-        final ServiceComponentPage serviceComponentPage = checkEtsiNsPropertiesFlow.getLandedPage()
+        ServiceComponentPage serviceComponentPage = checkEtsiNsPropertiesFlow.getLandedPage()
             .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected ServiceComponentPage"));
 
+        //adding node
+        addNodesAndCreateRelationships(resourceName, serviceCreateData, serviceComponentPage);
+
         final Map<String, Object> propertyMap = createPropertyToEditMap();
         editProperties(serviceComponentPage, propertyMap);
 
@@ -83,11 +121,120 @@ public class EtsiNetworkServiceUiTests extends SetupCDTest {
         checkEtsiNsPackage(createServiceFlow.getServiceCreateData().getName(), downloadedCsarName, propertyMap);
     }
 
-    private CreateServiceFlow createService() {
-        final ServiceCreateData serviceCreateData = createServiceFormData();
+    private void addNodesAndCreateRelationships(final String resourceName, final ServiceCreateData serviceCreateData,
+                                                final ServiceComponentPage serviceComponentPage) {
+        //add first VF node
+        final ComponentData parentComponent = new ComponentData();
+        parentComponent.setName(serviceCreateData.getName());
+        parentComponent.setVersion("0.1");
+        parentComponent.setComponentType(ComponentType.SERVICE);
+        final ComponentData resourceToAdd = new ComponentData();
+        resourceToAdd.setName(resourceName);
+        resourceToAdd.setVersion("1.0");
+        resourceToAdd.setComponentType(ComponentType.RESOURCE);
+        CompositionPage compositionPage = serviceComponentPage.goToComposition();
+        AddNodeToCompositionFlow addNodeToCompositionFlow = addNodeToComposition(parentComponent, resourceToAdd, compositionPage);
+        virtualLinkableVnf1 = addNodeToCompositionFlow.getCreatedComponentInstance()
+            .orElseThrow(() -> new UiTestFlowRuntimeException("Could not get the created component instance"));
+        //add second VF node
+        addNodeToCompositionFlow = addNodeToComposition(parentComponent, resourceToAdd, compositionPage);
+        virtualLinkableVnf2 = addNodeToCompositionFlow.getCreatedComponentInstance()
+            .orElseThrow(() -> new UiTestFlowRuntimeException("Could not get the created component instance"));
+        //add NsVirtualLink node
+        final ComponentData nsVirtualLinkToAdd = new ComponentData();
+        nsVirtualLinkToAdd.setName("NsVirtualLink");
+        nsVirtualLinkToAdd.setVersion("1.0");
+        nsVirtualLinkToAdd.setComponentType(ComponentType.RESOURCE);
+        addNodeToCompositionFlow = addNodeToComposition(parentComponent, nsVirtualLinkToAdd, compositionPage);
+        nsVirtualLink = addNodeToCompositionFlow.getCreatedComponentInstance()
+            .orElseThrow(() -> new UiTestFlowRuntimeException("Could not get the created component instance"));
+
+        //create a relationship from NsVirtualLink to first VF
+        final String virtualLinkableCapability = "tosca.capabilities.nfv.VirtualLinkable";
+        compositionPage = createRelationship(compositionPage, nsVirtualLink.getName(), virtualLinkableCapability,
+            virtualLinkableVnf1.getName(), virtualLinkableCapability);
+        CreateRelationshipFlow createRelationshipFlow;
+        //create a relationship from NsVirtualLink to second VF
+        final RelationshipInformation relationshipInfoVirtualLinkToVnf2 =
+            new RelationshipInformation(nsVirtualLink.getName(), virtualLinkableCapability, virtualLinkableVnf2.getName(), virtualLinkableCapability);
+        createRelationshipFlow = new CreateRelationshipFlow(webDriver, relationshipInfoVirtualLinkToVnf2);
+        compositionPage = (CompositionPage) createRelationshipFlow.run(compositionPage)
+            .orElseThrow(() -> new UiTestFlowRuntimeException("Expecting a CompositionPage instance"));
+        compositionPage.goToServiceGeneral();
+    }
+
+    private ResourceCreatePage createAndCertifyVf(final String resourceName, final ResourceCreatePage resourceCreatePage) {
+        final CreateResourceFromVspFlow createResourceFlow = new CreateResourceFromVspFlow(webDriver, resourceName);
+        final ResourceCreatePage resourceCreatePage1 = createResourceFlow.run(resourceCreatePage)
+            .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return ResourceCreatePage"));
+        resourceCreatePage1.isLoaded();
+        final CompositionPage compositionPage = resourceCreatePage1.goToComposition();
+        compositionPage.isLoaded();
+        //selecting node
+        final String mgmtPortNodeName = "mgmt_port";
+        compositionPage.selectNode(mgmtPortNodeName);
+        final CompositionDetailSideBarComponent detailSideBar = compositionPage.getDetailSideBar();
+        detailSideBar.isLoaded();
+        //going to requirements and capabilities tab and externalizing requirement
+        final CompositionRequirementsCapabilitiesTab compositionRequirementsCapabilitiesTab =
+            (CompositionRequirementsCapabilitiesTab) detailSideBar.selectTab(CompositionDetailTabName.REQUIREMENTS_CAPABILITIES);
+        compositionRequirementsCapabilitiesTab.isLoaded();
+        ExtentTestActions.takeScreenshot(Status.INFO, "requirement-capabilities-tab-loaded", "Requirement and Capabilities tab is loaded");
+        compositionRequirementsCapabilitiesTab.clickOnRequirements();
+        final String externalVirtualLinkRequirement = "external_virtual_link";
+        getExtendTest().log(Status.INFO,
+            String.format("Externalizing requirement '%s' in node '%s'", externalVirtualLinkRequirement, mgmtPortNodeName));
+        compositionRequirementsCapabilitiesTab.toggleRequirementAsExternal(externalVirtualLinkRequirement);
+        ExtentTestActions.takeScreenshot(Status.INFO, "requirement-externalized",
+            String.format("Requirement '%s' of node '%s' was externalized", externalVirtualLinkRequirement, mgmtPortNodeName));
+
+        final ComponentPage componentPage = compositionPage.goToGeneral();
+        componentPage.isLoaded();
+        componentPage.certifyComponent();
+        return resourceCreatePage1;
+    }
+
+    private CompositionPage createRelationship(final CompositionPage compositionPage, final String fromComponentInstanceName,
+                                               final String fromCapability, final String toComponentInstanceName, final String toRequirement) {
+        final RelationshipInformation relationshipInformation =
+            new RelationshipInformation(fromComponentInstanceName, fromCapability, toComponentInstanceName, toRequirement);
+        CreateRelationshipFlow createRelationshipFlow = new CreateRelationshipFlow(webDriver, relationshipInformation);
+        return (CompositionPage) createRelationshipFlow.run(compositionPage)
+            .orElseThrow(() -> new UiTestFlowRuntimeException("Expecting a CompositionPage instance"));
+    }
+
+    private ResourceCreatePage importVsp(final String resourceName) {
+        final ImportVspFlow importVspFlow = new ImportVspFlow(webDriver, resourceName);
+        return importVspFlow.run()
+            .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return ResourceCreatePage"));
+    }
+
+    private String createVsp() {
+        final String resourceName = ElementFactory.addRandomSuffixToName(ElementFactory.getResourcePrefix());
+        final String virtualLinkableVnf = "etsi-vnf-virtual-linkable.csar";
+        final String rootFolder = org.onap.sdc.backend.ci.tests.utils.general.FileHandling.getXnfRepositoryPath(XnfTypeEnum.VNF);
+        final CreateVspFlow createVspFlow = new CreateVspFlow(webDriver, resourceName, virtualLinkableVnf, rootFolder);
+        createVspFlow.run(new TopNavComponent(webDriver));
+        return resourceName;
+    }
+
+    private void createVlm() {
+        getExtendTest().log(Status.INFO, "Creating a VLM");
+        final CreateVlmFlow createVlmFlow = new CreateVlmFlow(webDriver);
+        createVlmFlow.run();
+    }
+
+    public AddNodeToCompositionFlow addNodeToComposition(final ComponentData parentComponent, final ComponentData resourceToAdd,
+                                                         CompositionPage compositionPage) {
+
+        final AddNodeToCompositionFlow addNodeToCompositionFlow = new AddNodeToCompositionFlow(webDriver, parentComponent, resourceToAdd);
+        addNodeToCompositionFlow.run(compositionPage);
+        return addNodeToCompositionFlow;
+    }
+
+    private CreateServiceFlow createService(final ServiceCreateData serviceCreateData) {
         final CreateServiceFlow createServiceFlow = new CreateServiceFlow(webDriver, serviceCreateData);
-        final TopNavComponent topNavComponent = new TopNavComponent(webDriver);
-        createServiceFlow.run(new HomePage(webDriver, topNavComponent));
+        createServiceFlow.run(new HomePage(webDriver));
         return createServiceFlow;
     }
 
@@ -167,51 +314,84 @@ public class EtsiNetworkServiceUiTests extends SetupCDTest {
     }
 
     private void checkNsCsar(final String expectedServiceName, final String expectedServiceNodeType, final Map<String, Object> expectedPropertiesMap,
-                             final byte[] nsCsar) {
-        try {
-            final Map<String, byte[]> csarFileMap = FileHandling.getFilesFromZip(nsCsar);
-            final String mainDefinitionFile = String.format("Definitions/%s.yaml", expectedServiceName);
-            final byte[] mainDefinitionFileBytes = csarFileMap.get(mainDefinitionFile);
-            if (mainDefinitionFileBytes == null) {
-                Assertions.fail(String.format("Could not find the Main Definition file in '%s'", mainDefinitionFile));
-            }
+                             final byte[] nsCsar) throws UnzipException {
+        final Map<String, byte[]> csarFileMap = FileHandling.getFilesFromZip(nsCsar);
 
-            final Map<String, Object> mainDefinitionYamlMap = loadYamlObject(mainDefinitionFileBytes);
-            final Map<String, Object> topologyTemplateTosca = getMapEntry(mainDefinitionYamlMap, "topology_template");
-            assertThat(String.format("'%s' should contain a topology_template entry", mainDefinitionFile), topologyTemplateTosca, notNullValue());
-            final Map<String, Object> substitutionMappingsTosca = getMapEntry(topologyTemplateTosca, "substitution_mappings");
-            assertThat(String.format("'%s' should contain a substitution_mappings entry", mainDefinitionFile), substitutionMappingsTosca, notNullValue());
-            final String nodeType = (String) substitutionMappingsTosca.get("node_type");
-            assertThat("substitution_mappings->node_type should be as expected", nodeType, is(expectedServiceNodeType));
-
-            final Map<String, Object> nodeTemplatesTosca = getMapEntry(topologyTemplateTosca, "node_templates");
-            assertThat(String.format("'%s' should contain a node_templates entry", mainDefinitionFile), nodeTemplatesTosca, notNullValue());
-            final Map<String, Object> serviceNodeTemplate = getMapEntry(nodeTemplatesTosca, expectedServiceNodeType);
-            assertThat(String.format("'%s' should contain a '%s' entry in node_templates", mainDefinitionFile, expectedServiceNodeType),
-                serviceNodeTemplate, notNullValue());
-            final Map<String, Object> properties = getMapEntry(serviceNodeTemplate, "properties");
-            assertThat(String.format("'%s' node template in '%s' should contain a properties entry", expectedServiceNodeType, mainDefinitionFile),
-                properties, notNullValue());
-            assertThat(String.format("'%s' node template should contain '%s' properties", expectedServiceNodeType, expectedPropertiesMap.size()),
-                properties.size(), is(expectedPropertiesMap.size()));
-            for (final Entry<String, Object> expectedPropertyEntry : expectedPropertiesMap.entrySet()) {
-                final String expectedPropertyName = expectedPropertyEntry.getKey();
-                assertThat(String.format("'%s' node template should contain the property '%s'", expectedServiceNodeType, expectedPropertyName),
-                    properties, hasKey(expectedPropertyName));
-                final Object expectedPropertyValue = expectedPropertyEntry.getValue();
-                if (expectedPropertyValue != null) {
-                    final Object actualPropertyValue = properties.get(expectedPropertyName);
-                    final String msg = String.format("The property '%s', in '%s' node template should have the expected value '%s'",
-                        expectedPropertyName, expectedServiceNodeType, actualPropertyValue);
-                    assertThat(msg, actualPropertyValue, is(expectedPropertyValue));
-                }
+        final String mainDefinitionFile = String.format("Definitions/%s.yaml", expectedServiceName);
+        final byte[] mainDefinitionFileBytes = csarFileMap.get(mainDefinitionFile);
+        if (mainDefinitionFileBytes == null) {
+            fail(String.format("Could not find the Main Definition file in '%s'", mainDefinitionFile));
+        }
+
+        final Map<String, Object> mainDefinitionYamlMap = loadYamlObject(mainDefinitionFileBytes);
+        final Map<String, Object> topologyTemplateTosca = getMapEntry(mainDefinitionYamlMap, "topology_template");
+        assertThat(String.format("'%s' should contain a topology_template entry", mainDefinitionFile), topologyTemplateTosca, notNullValue());
+        final Map<String, Object> substitutionMappingsTosca = getMapEntry(topologyTemplateTosca, "substitution_mappings");
+        assertThat(String.format("'%s' should contain a substitution_mappings entry", mainDefinitionFile), substitutionMappingsTosca, notNullValue());
+        final String nodeType = (String) substitutionMappingsTosca.get("node_type");
+        assertThat("substitution_mappings->node_type should be as expected", nodeType, is(expectedServiceNodeType));
+
+        final Map<String, Object> nodeTemplatesTosca = getMapEntry(topologyTemplateTosca, "node_templates");
+        assertThat(String.format("'%s' should contain a node_templates entry", mainDefinitionFile), nodeTemplatesTosca, notNullValue());
+
+        checkVirtualLinkableNode(mainDefinitionFile, virtualLinkableVnf1, nodeTemplatesTosca);
+        checkVirtualLinkableNode(mainDefinitionFile, virtualLinkableVnf2, nodeTemplatesTosca);
+        //checking tosca.nodes.nfv.NsVirtualLink node
+        final Map<String, Object> nsVirtualLinkNode = getMapEntry(nodeTemplatesTosca, nsVirtualLink.getName());
+        assertThat(String.format("'%s' should contain a '%s' entry in node_templates", mainDefinitionFile, nsVirtualLink.getName()),
+            nsVirtualLinkNode, notNullValue());
+        assertThat(String.format("Type from '%s' should be as expected", nsVirtualLink.getName()),
+            nsVirtualLinkNode.get("type"), is("tosca.nodes.nfv.NsVirtualLink"));
+
+        //checking the main service node
+        final Map<String, Object> serviceNodeTemplate = getMapEntry(nodeTemplatesTosca, expectedServiceNodeType);
+        assertThat(String.format("'%s' should contain a '%s' entry in node_templates", mainDefinitionFile, expectedServiceNodeType),
+            serviceNodeTemplate, notNullValue());
+        final Map<String, Object> properties = getMapEntry(serviceNodeTemplate, "properties");
+        assertThat(String.format("'%s' node template in '%s' should contain a properties entry", expectedServiceNodeType, mainDefinitionFile),
+            properties, notNullValue());
+        assertThat(String.format("'%s' node template should contain '%s' properties", expectedServiceNodeType, expectedPropertiesMap.size()),
+            properties.size(), is(expectedPropertiesMap.size()));
+        for (final Entry<String, Object> expectedPropertyEntry : expectedPropertiesMap.entrySet()) {
+            final String expectedPropertyName = expectedPropertyEntry.getKey();
+            assertThat(String.format("'%s' node template should contain the property '%s'", expectedServiceNodeType, expectedPropertyName),
+                properties, hasKey(expectedPropertyName));
+            final Object expectedPropertyValue = expectedPropertyEntry.getValue();
+            if (expectedPropertyValue != null) {
+                final Object actualPropertyValue = properties.get(expectedPropertyName);
+                final String msg = String.format("The property '%s', in '%s' node template should have the expected value '%s'",
+                    expectedPropertyName, expectedServiceNodeType, actualPropertyValue);
+                assertThat(msg, actualPropertyValue, is(expectedPropertyValue));
             }
+        }
+    }
 
-        } catch (final UnzipException e) {
-            final String errorMsg = "Could not unzip Network Service CSAR.";
-            LOGGER.info(errorMsg, e);
-            fail(String.format("%s Error: %s", errorMsg, e.getMessage()));
+    private void checkVirtualLinkableNode(final String mainDefinitionFileName, final ComponentInstance virtualLinkableVnf,
+                                          final Map<String, Object> nodeTemplatesTosca) {
+        final Map<String, Object> virtualLinkableVnfNode = getMapEntry(nodeTemplatesTosca, virtualLinkableVnf.getName());
+        assertThat(String.format("'%s' should contain a '%s' entry in node_templates", mainDefinitionFileName, virtualLinkableVnf.getName()),
+            virtualLinkableVnfNode, notNullValue());
+        assertThat(String.format("Type from '%s' should be as expected", virtualLinkableVnf.getName()),
+            virtualLinkableVnfNode.get("type"), is("org.openecomp.resource.EtsiVnfVirtualLinkable"));
+        final Object requirementsObj = virtualLinkableVnfNode.get("requirements");
+        assertThat(String.format("'%s' should contain a requirements entry in node_templates", virtualLinkableVnf.getName()),
+            requirementsObj, notNullValue());
+        if (!(requirementsObj instanceof List)) {
+            fail(String.format("Requirements in '%s' is not a list", virtualLinkableVnf.getName()));
         }
+        final var requirements = (List<Map<String, Object>>) requirementsObj;
+        assertThat(String.format("'%s' should contain only one requirement", virtualLinkableVnf.getName()), requirements, hasSize(1));
+        final Map<String, Object> externalVirtualLinkRequirement = getMapEntry(requirements.get(0), "external_virtual_link");
+        assertThat(String.format("'%s' should contain the requirement 'external_virtual_link'", virtualLinkableVnf.getName()),
+            externalVirtualLinkRequirement, notNullValue());
+        assertThat(
+            String.format("Requirement 'external_virtual_link' in '%s' should contain the capability 'virtual_linkable'",
+                virtualLinkableVnf.getName()),
+            externalVirtualLinkRequirement.get("capability"), is("virtual_linkable"));
+        assertThat(
+            String.format("Requirement 'external_virtual_link' in '%s' should relate to the node '%s'",
+                virtualLinkableVnf.getName(), nsVirtualLink.getName()),
+            externalVirtualLinkRequirement.get("node"), is(nsVirtualLink.getName()));
     }
 
     private Map<String, Object> getMapEntry(final Map<String, Object> yamlObj, final String entryName) {
index 40716bf..d420d46 100644 (file)
@@ -126,9 +126,8 @@ public class EtsiOnboardVnfCnfUiTests extends SetupCDTest {
         ComponentPage componentPage = loadComponentPage();
         final CompositionPage compositionPage = (CompositionPage) addNodeToCompositionFlow.run(componentPage.goToComposition())
             .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return CompositionPage"));
-        compositionPage.isLoaded();
-             ExtentTestActions.takeScreenshot(Status.INFO, "node-added-to-composition",
-                   String.format("Resource '%s' was added to composition", serviceCreateData.getName()));
+        ExtentTestActions.takeScreenshot(Status.INFO, "node-added-to-composition",
+            String.format("Resource '%s' was added to composition", serviceCreateData.getName()));
         componentPage = compositionPage.goToGeneral();
         componentPage.isLoaded();
         componentPage.certifyComponent();
@@ -187,7 +186,7 @@ public class EtsiOnboardVnfCnfUiTests extends SetupCDTest {
     }
 
     /**
-     * Download the generated packag
+     * Download the generated package
      *
      * @return DownloadToscaCsarFlow
      */
index af2c959..fee4a0d 100644 (file)
@@ -43,7 +43,7 @@ import org.onap.sdc.frontend.ci.tests.flow.CreateVfFlow;
 import org.onap.sdc.frontend.ci.tests.flow.CreateVfcFlow;
 import org.onap.sdc.frontend.ci.tests.flow.DownloadCsarArtifactFlow;
 import org.onap.sdc.frontend.ci.tests.flow.exception.UiTestFlowRuntimeException;
-import org.onap.sdc.frontend.ci.tests.pages.ResourceCreatePage;
+import org.onap.sdc.frontend.ci.tests.pages.ComponentPage;
 import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionPage;
 import org.onap.sdc.frontend.ci.tests.pages.component.workspace.ToscaArtifactsPage;
 import org.onap.sdc.frontend.ci.tests.pages.home.HomePage;
@@ -74,9 +74,13 @@ public class ImportVfcUiTest extends SetupCDTest {
         String fileName = "org.openecomp.resource.VFC-root.yml";
         CreateVfcFlow createVfcFlow = createVFC(fileName);
 
-        createVfcFlow.getLandedPage().get().clickOnCertify();
+        ComponentPage componentPage = createVfcFlow.getLandedPage()
+            .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return ResourceCreatePage"));
+        componentPage.isLoaded();
+        componentPage.certifyComponent();
+        componentPage.isLoaded();
 
-        Map<String, Object> yamlObject = downloadToscaArtifact(createVfcFlow.getLandedPage().get());
+        Map<String, Object> yamlObject = downloadToscaArtifact(componentPage);
         checkMetadata(yamlObject, vfcCreateData);
         checkNodeTypes(yamlObject);
         homePage.getTopNavComponent().clickOnHome();
@@ -84,7 +88,9 @@ public class ImportVfcUiTest extends SetupCDTest {
         // TC - Import hierarchy of VFCs
         fileName = "org.openecomp.resource.VFC-child.yml";
         createVfcFlow = createVFC(fileName);
-        createVfcFlow.getLandedPage().get().clickOnCertify();
+        componentPage = createVfcFlow.getLandedPage().orElseThrow();
+        componentPage.certifyComponent();
+        componentPage.isLoaded();
 
         yamlObject = downloadToscaArtifact(createVfcFlow.getLandedPage().get());
         checkMetadata(yamlObject, vfcCreateData);
@@ -94,21 +100,26 @@ public class ImportVfcUiTest extends SetupCDTest {
         // TC - Import VFC with interface inputs
         // TC - Import VFC with attributes
         final CreateVfFlow createVfFlow = createVF();
+        componentPage = createVfFlow.getLandedPage()
+            .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return ResourceCreatePage"));
+        componentPage.isLoaded();
+
+        final AddNodeToCompositionFlow addNodeToCompositionFlow = addNodeToCompositionFlow(componentPage);
 
-        final AddNodeToCompositionFlow addNodeToCompositionFlow = addNodeToCompositionFlow(createVfFlow);
         final CompositionPage compositionPage = addNodeToCompositionFlow.getLandedPage()
             .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return CompositionPage"));
-        compositionPage.isLoaded();
-        final ResourceCreatePage resourceCreatePage = compositionPage.goToGeneral();
-        resourceCreatePage.isLoaded();
-        resourceCreatePage.clickOnCertify();
-        yamlObject = downloadToscaArtifact(createVfFlow.getLandedPage().get());
+        componentPage = compositionPage.goToGeneral();
+        componentPage.isLoaded();
+        componentPage.certifyComponent();
+        componentPage.isLoaded();
+        yamlObject = downloadToscaArtifact(componentPage);
         checkMetadata(yamlObject, vfCreateData);
         checkTopologyTemplate(yamlObject);
 
     }
 
-    private AddNodeToCompositionFlow addNodeToCompositionFlow(final CreateVfFlow createVfFlow) {
+    private AddNodeToCompositionFlow addNodeToCompositionFlow(final ComponentPage componentPage) {
+        componentPage.isLoaded();
         final ComponentData parentComponent = new ComponentData();
         parentComponent.setName(vfCreateData.getName());
         parentComponent.setVersion("0.1");
@@ -118,14 +129,12 @@ public class ImportVfcUiTest extends SetupCDTest {
         componentToAdd.setVersion("1.0");
         componentToAdd.setComponentType(ComponentType.RESOURCE);
         final AddNodeToCompositionFlow addNodeToCompositionFlow = new AddNodeToCompositionFlow(webDriver, parentComponent, componentToAdd);
-        final ResourceCreatePage resourceCreatePage = createVfFlow.getLandedPage()
-            .orElseThrow(() -> new UiTestFlowRuntimeException("Expecting a ResourceCreatePage"));
-        addNodeToCompositionFlow.run(resourceCreatePage.goToComposition());
+        addNodeToCompositionFlow.run(componentPage.goToComposition());
         return addNodeToCompositionFlow;
     }
 
-    private Map<String, Object> downloadToscaArtifact(final ResourceCreatePage resourceCreatePage) throws UnzipException {
-        final DownloadCsarArtifactFlow downloadCsarArtifactFlow = downloadCsarArtifact(resourceCreatePage);
+    private Map<String, Object> downloadToscaArtifact(final ComponentPage componentPage) throws UnzipException {
+        final DownloadCsarArtifactFlow downloadCsarArtifactFlow = downloadCsarArtifact(componentPage);
         final ToscaArtifactsPage toscaArtifactsPage = downloadCsarArtifactFlow.getLandedPage()
             .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected ToscaArtifactsPage"));
 
@@ -156,10 +165,10 @@ public class ImportVfcUiTest extends SetupCDTest {
         return new Yaml().load(new String(mainDefinitionFileBytes));
     }
 
-    private DownloadCsarArtifactFlow downloadCsarArtifact(final ResourceCreatePage resourceCreatePage) {
+    private DownloadCsarArtifactFlow downloadCsarArtifact(final ComponentPage componentPage) {
         final DownloadCsarArtifactFlow downloadCsarArtifactFlow = new DownloadCsarArtifactFlow(webDriver);
         downloadCsarArtifactFlow.setWaitBeforeGetTheFile(5L);
-        downloadCsarArtifactFlow.run(resourceCreatePage);
+        downloadCsarArtifactFlow.run(componentPage);
         return downloadCsarArtifactFlow;
     }
 
index 07d5429..93b9361 100644 (file)
@@ -4,6 +4,7 @@ import com.aventstack.extentreports.Status;
 import java.util.Objects;
 import java.util.Optional;
 import org.onap.sdc.frontend.ci.tests.datatypes.ComponentData;
+import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions;
 import org.onap.sdc.frontend.ci.tests.pages.ComponentPage;
 import org.onap.sdc.frontend.ci.tests.pages.PageObject;
 import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionPage;
@@ -36,6 +37,9 @@ public class AddNodeToCompositionFlow extends AbstractUiTestFlow {
         final ComponentPage componentPage = compositionPage.goToGeneral();
         componentPage.isLoaded();
         compositionPage = componentPage.goToComposition();
+        compositionPage.isLoaded();
+        ExtentTestActions.takeScreenshot(Status.INFO, "component-instance-created",
+            String.format("Component instance '%s' of type '%s' created", createdComponentInstance.getName(), componentToAdd.getName()));
         return Optional.of(this.compositionPage);
     }
 
index e767dce..343c7f6 100644 (file)
@@ -62,15 +62,7 @@ public class CheckEtsiNsPropertiesFlow extends AbstractUiTestFlow {
     @Override
     public Optional<ServiceComponentPage> run(final PageObject... pageObjects) {
         extendTest.log(Status.INFO, "Checking ETSI NFV Network Service properties");
-        serviceComponentPage = getParameter(pageObjects, ServiceComponentPage.class)
-            .orElseGet(() -> {
-                final TopNavComponent topNavComponent = getParameter(pageObjects, TopNavComponent.class).orElse(new TopNavComponent(webDriver));
-                final ResourceLeftSideMenu resourceLeftSideMenu =
-                    getParameter(pageObjects, ResourceLeftSideMenu.class).orElse(new ResourceLeftSideMenu(webDriver));
-                final ResourceWorkspaceTopBarComponent workspaceTopBarComponent =
-                    getParameter(pageObjects, ResourceWorkspaceTopBarComponent.class).orElse(new ResourceWorkspaceTopBarComponent(webDriver));
-                return new ServiceComponentPage(webDriver, topNavComponent, resourceLeftSideMenu, workspaceTopBarComponent);
-            });
+        serviceComponentPage = getParameter(pageObjects, ServiceComponentPage.class).orElseGet(() -> new ServiceComponentPage(webDriver));
         serviceComponentPage.isLoaded();
         final ResourcePropertiesAssignmentPage resourcePropertiesAssignmentPage = serviceComponentPage.goToPropertiesAssignment();
         checkProperty(resourcePropertiesAssignmentPage, "descriptor_id");
index 8b6a391..2f17f16 100644 (file)
@@ -43,13 +43,14 @@ public class CreateVlmFlow extends AbstractUiTestFlow {
     }
 
     @Override
-    public Optional<? extends PageObject> run(PageObject... pageObjects) {
-        extendTest.log(Status.INFO, String.format("Starting flow to create a VLM"));
+    public Optional<? extends PageObject> run(final PageObject... pageObjects) {
+        extendTest.log(Status.INFO, "Starting flow to create a VLM");
         final TopNavComponent topNavComponent = getParameter(pageObjects, TopNavComponent.class)
             .orElse(new TopNavComponent(webDriver));
         extendTest.log(Status.INFO, "Accessing the Onboard Home Page to create a VLM");
         topNavComponent.isLoaded();
         final OnboardHomePage onboardHomePage = goToOnboardHomePage(topNavComponent);
+        onboardHomePage.isLoaded();
         final VlmOverviewPage vlmOverviewPage = createNewVlm(onboardHomePage);
         submitVlm(vlmOverviewPage);
         goToHomePage(topNavComponent);
index aa0d1c6..948b865 100644 (file)
@@ -43,8 +43,7 @@ public class CreateVspFlow extends AbstractUiTestFlow {
     private final String rootFolder;
     private HomePage homePage;
 
-    public CreateVspFlow(final WebDriver webDriver, final String resourceName, final String packageFile,
-                         final String rootFolder) {
+    public CreateVspFlow(final WebDriver webDriver, final String resourceName, final String packageFile, final String rootFolder) {
         super(webDriver);
         this.resourceName = resourceName;
         this.packageFile = packageFile;
index 621d512..b93266e 100644 (file)
@@ -50,7 +50,7 @@ public class DownloadCsarArtifactFlow extends AbstractUiTestFlow {
     @Override
     public Optional<PageObject> run(final PageObject... pageObjects) {
         final ComponentPage componentPage = findParameter(pageObjects, ComponentPage.class);
-        toscaArtifactsPage = (ToscaArtifactsPage) componentPage.goToToscaArtifacts();
+        toscaArtifactsPage = componentPage.goToToscaArtifacts();
         toscaArtifactsPage.isLoaded();
 
         toscaArtifactsPage.clickOnDownload("Tosca Model");
index 716d386..f7b255d 100644 (file)
@@ -25,11 +25,8 @@ import java.util.Optional;
 import org.apache.commons.collections4.MapUtils;
 import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions;
 import org.onap.sdc.frontend.ci.tests.pages.PageObject;
-import org.onap.sdc.frontend.ci.tests.pages.ResourceLeftSideMenu;
 import org.onap.sdc.frontend.ci.tests.pages.ResourcePropertiesAssignmentPage;
-import org.onap.sdc.frontend.ci.tests.pages.ResourceWorkspaceTopBarComponent;
 import org.onap.sdc.frontend.ci.tests.pages.ServiceComponentPage;
-import org.onap.sdc.frontend.ci.tests.pages.TopNavComponent;
 import org.openqa.selenium.WebDriver;
 
 public class EditServicePropertiesFlow extends AbstractUiTestFlow {
@@ -44,15 +41,7 @@ public class EditServicePropertiesFlow extends AbstractUiTestFlow {
 
     @Override
     public Optional<ServiceComponentPage> run(final PageObject... pageObjects) {
-        serviceComponentPage = getParameter(pageObjects, ServiceComponentPage.class)
-            .orElseGet(() -> {
-                final TopNavComponent topNavComponent = getParameter(pageObjects, TopNavComponent.class).orElse(new TopNavComponent(webDriver));
-                final ResourceLeftSideMenu resourceLeftSideMenu =
-                    getParameter(pageObjects, ResourceLeftSideMenu.class).orElse(new ResourceLeftSideMenu(webDriver));
-                final ResourceWorkspaceTopBarComponent workspaceTopBarComponent =
-                    getParameter(pageObjects, ResourceWorkspaceTopBarComponent.class).orElse(new ResourceWorkspaceTopBarComponent(webDriver));
-                return new ServiceComponentPage(webDriver, topNavComponent, resourceLeftSideMenu, workspaceTopBarComponent);
-            });
+        serviceComponentPage = getParameter(pageObjects, ServiceComponentPage.class).orElseGet(() -> new ServiceComponentPage(webDriver));
         serviceComponentPage.isLoaded();
         final ResourcePropertiesAssignmentPage resourcePropertiesAssignmentPage = serviceComponentPage.goToPropertiesAssignment();
         if (MapUtils.isEmpty(propertiesMap)) {
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/composition/CreateRelationshipFlow.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/composition/CreateRelationshipFlow.java
new file mode 100644 (file)
index 0000000..99fbc46
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.sdc.frontend.ci.tests.flow.composition;
+
+import com.aventstack.extentreports.Status;
+import java.util.Optional;
+import org.onap.sdc.frontend.ci.tests.datatypes.composition.RelationshipInformation;
+import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions;
+import org.onap.sdc.frontend.ci.tests.flow.AbstractUiTestFlow;
+import org.onap.sdc.frontend.ci.tests.pages.PageObject;
+import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionPage;
+import org.onap.sdc.frontend.ci.tests.pages.component.workspace.RelationshipWizardComponent;
+import org.onap.sdc.frontend.ci.tests.pages.component.workspace.RelationshipWizardRequirementCapabilityComponent;
+import org.openqa.selenium.WebDriver;
+
+/**
+ * Creates a relationship between two nodes/component instances
+ */
+public class CreateRelationshipFlow extends AbstractUiTestFlow {
+
+    private final RelationshipInformation relationshipInformation;
+    private CompositionPage compositionPage;
+
+    public CreateRelationshipFlow(final WebDriver webDriver, final RelationshipInformation relationshipInformation) {
+        super(webDriver);
+        this.relationshipInformation = relationshipInformation;
+    }
+
+    @Override
+    public Optional<? extends PageObject> run(final PageObject... pageObjects) {
+        compositionPage = findParameter(pageObjects, CompositionPage.class);
+        compositionPage.isLoaded();
+        final RelationshipWizardComponent relationshipWizardComponent = compositionPage
+            .createLink(relationshipInformation.getFromNode(), relationshipInformation.getToNode());
+        final RelationshipWizardRequirementCapabilityComponent requirementCapabilityComponent =
+            new RelationshipWizardRequirementCapabilityComponent(webDriver);
+        requirementCapabilityComponent.isLoaded();
+        requirementCapabilityComponent.selectRequirementOrCapability(relationshipInformation.getFromCapability());
+        ExtentTestActions.takeScreenshot(Status.INFO, "capability-selected",
+            String.format("Selected capability '%s'", relationshipInformation.getFromCapability()));
+        relationshipWizardComponent.clickOnNext();
+        requirementCapabilityComponent.isLoaded();
+        requirementCapabilityComponent.selectRequirementOrCapability(relationshipInformation.getToRequirement());
+        ExtentTestActions.takeScreenshot(Status.INFO, "requirement-selected",
+            String.format("Selected requirement '%s'", relationshipInformation.getToRequirement()));
+        relationshipWizardComponent.clickOnNext();
+        relationshipWizardComponent.clickOnNext();
+        relationshipWizardComponent.clickOnFinish();
+        compositionPage.isLoaded();
+        ExtentTestActions.takeScreenshot(Status.INFO, "relationship-created",
+            String.format("Relationship from '%s' to '%s' created", relationshipInformation.getFromNode(), relationshipInformation.getToNode()));
+        return Optional.of(compositionPage);
+    }
+
+    @Override
+    public Optional<CompositionPage> getLandedPage() {
+        return Optional.of(compositionPage);
+    }
+}
index 5983970..1ad049f 100644 (file)
@@ -150,6 +150,17 @@ public abstract class AbstractPageObject implements PageObject {
             .until(ExpectedConditions.visibilityOfElementLocated(locator));
     }
 
+    /**
+     * Waits for the visibility of a list of elements matched by the locator.
+     *
+     * @param locator the locator to find the elements
+     * @return the list of elements found if any visible
+     */
+    protected List<WebElement> waitForAllElementsVisibility(final By locator) {
+        return getWait(timeoutInSeconds)
+            .until(ExpectedConditions.visibilityOfAllElementsLocatedBy(locator));
+    }
+
     /**
      * Waits for element invisibility with the default timeout.
      *
index 9232307..f308bd6 100644 (file)
@@ -41,24 +41,41 @@ public class ComponentCertificationModal extends AbstractPageObject {
     }
 
     public void isLoaded() {
-        LOGGER.debug("Finding element with xpath '{}'", XpathSelector.MODAL_DIV.getXpath());
-        wrappingElement = waitForElementVisibility(XpathSelector.MODAL_DIV.getXpath());
+        LOGGER.debug("Finding element with xpath '{}'", XpathSelector.MAIN_MODAL_DIV.getXpath());
+        waitForElementVisibility(XpathSelector.COMMIT_COMMENT_TXT.getXpath());
+        waitToBeClickable(XpathSelector.CANCEL_BUTTON.getXpath());
+        wrappingElement = waitForElementVisibility(XpathSelector.MAIN_MODAL_DIV.getXpath());
     }
 
     /**
-     * Fills commit text area with a default message.
+     * Fills commit text area with given message.
+     *
+     * @param comment the comment message
      */
-    public void fillCommentWithDefaultMessage() {
+    public void fillComment(final String comment) {
         final WebElement commentTxt = wrappingElement.findElement(By.xpath(XpathSelector.COMMIT_COMMENT_TXT.getXpath()));
-        commentTxt.sendKeys("UI Integration Test");
+        commentTxt.sendKeys(comment);
     }
 
     /**
-     * Clicks on the modal submit and confirms success.
+     * Click on the Ok button, submitting the certification.
      */
-    public void submit() {
-        final WebElement commitAndSubmitBtn = wrappingElement.findElement(By.xpath(XpathSelector.MODAL_OK_BTN.getXpath()));
-        commitAndSubmitBtn.click();
+    public void clickOnOkButton() {
+        wrappingElement.findElement(By.xpath(XpathSelector.OK_BUTTON.getXpath())).click();
+    }
+
+    /**
+     * Click on the "x" to close the dialog.
+     */
+    public void clickOnCloseButton() {
+        wrappingElement.findElement(By.xpath(XpathSelector.CLOSE_X_BUTTON.getXpath())).click();
+    }
+
+    /**
+     * Click on the cancel button, closing the dialog.
+     */
+    public void clickOnCancelButton() {
+        wrappingElement.findElement(By.xpath(XpathSelector.CANCEL_BUTTON.getXpath())).click();
     }
 
     /**
@@ -66,10 +83,11 @@ public class ComponentCertificationModal extends AbstractPageObject {
      */
     @AllArgsConstructor
     private enum XpathSelector {
-        MODAL_DIV("sdc-modal-type-custom", "//div[contains(@class, '%s')]"),
+        MAIN_MODAL_DIV("sdc-modal-type-custom", "//div[contains(@class, '%s')]"),
         COMMIT_COMMENT_TXT("checkindialog", "//textarea[@data-tests-id='%s']"),
-        MODAL_OK_BTN("confirm-modal-button-ok", "//button[@data-tests-id='%s']"),
-        MODAL_CANCEL_BTN("confirm-modal-button-cancel", "//button[@data-tests-id='%s']");
+        OK_BUTTON("confirm-modal-button-ok", "//button[@data-tests-id='%s']"),
+        CANCEL_BUTTON("confirm-modal-button-cancel", "//button[@data-tests-id='%s']"),
+        CLOSE_X_BUTTON("confirm-modal-close", "//button[@data-tests-id='%s']");
 
         @Getter
         private final String id;
index bb30af1..3a95a6f 100644 (file)
  */
 package org.onap.sdc.frontend.ci.tests.pages;
 
+import org.onap.sdc.frontend.ci.tests.datatypes.LifeCycleStateEnum;
 import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionPage;
 import org.onap.sdc.frontend.ci.tests.pages.component.workspace.ToscaArtifactsPage;
+import org.onap.sdc.frontend.ci.tests.pages.home.HomePage;
+import org.onap.sdc.frontend.ci.tests.utilities.LoaderHelper;
+import org.onap.sdc.frontend.ci.tests.utilities.NotificationComponent;
+import org.onap.sdc.frontend.ci.tests.utilities.NotificationComponent.NotificationType;
 import org.openqa.selenium.WebDriver;
 
 public class ComponentPage extends AbstractPageObject {
 
-    private final TopNavComponent topNavComponent;
-    private final ResourceLeftSideMenu resourceLeftSideMenu;
-    private final ResourceWorkspaceTopBarComponent workspaceTopBarComponent;
+    protected final TopNavComponent topNavComponent;
+    protected final ResourceLeftSideMenu resourceLeftSideMenu;
+    protected final ResourceWorkspaceTopBarComponent workspaceTopBarComponent;
+    protected final LoaderHelper loaderHelper;
+    protected final NotificationComponent notificationComponent;
 
     public ComponentPage(final WebDriver webDriver) {
         super(webDriver);
-        this.topNavComponent = new TopNavComponent(webDriver);
-        this.resourceLeftSideMenu = new ResourceLeftSideMenu(webDriver);
-        this.workspaceTopBarComponent = new ResourceWorkspaceTopBarComponent(webDriver);
+        topNavComponent = new TopNavComponent(webDriver);
+        resourceLeftSideMenu = new ResourceLeftSideMenu(webDriver);
+        workspaceTopBarComponent = new ResourceWorkspaceTopBarComponent(webDriver);
+        loaderHelper = new LoaderHelper(webDriver);
+        notificationComponent = new NotificationComponent(webDriver);
     }
 
     @Override
@@ -42,6 +51,10 @@ public class ComponentPage extends AbstractPageObject {
         workspaceTopBarComponent.isLoaded();
     }
 
+    public HomePage goToHomePage() {
+        return topNavComponent.clickOnHome();
+    }
+
     public ToscaArtifactsPage goToToscaArtifacts() {
         return resourceLeftSideMenu.clickOnToscaArtifactsMenuItem();
     }
@@ -50,8 +63,29 @@ public class ComponentPage extends AbstractPageObject {
         return resourceLeftSideMenu.clickOnCompositionMenuItem();
     }
 
+    public ResourcePropertiesAssignmentPage goToPropertiesAssignment() {
+        return resourceLeftSideMenu.clickOnPropertiesAssignmentMenuItem();
+    }
+
     public void certifyComponent() {
-        workspaceTopBarComponent.certifyComponent();
+        workspaceTopBarComponent.certifyResource();
+    }
+
+    /**
+     * Creates the resource and wait for success notification.
+     */
+    public void clickOnCreate() {
+        workspaceTopBarComponent.clickOnCreate();
+        loaderHelper.waitForLoader(20);
+        notificationComponent.waitForNotification(NotificationType.SUCCESS, 20);
+    }
+
+    public String getLifecycleState() {
+        return workspaceTopBarComponent.getLifecycleState();
+    }
+
+    public boolean isInDesign() {
+        return LifeCycleStateEnum.IN_DESIGN.getValue().equalsIgnoreCase(getLifecycleState());
     }
 
 }
index 6dc98c4..83641d4 100644 (file)
@@ -23,36 +23,19 @@ import java.util.List;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 import org.onap.sdc.frontend.ci.tests.datatypes.ResourceCreateData;
-import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionPage;
-import org.onap.sdc.frontend.ci.tests.pages.component.workspace.ToscaArtifactsPage;
-import org.onap.sdc.frontend.ci.tests.utilities.LoaderHelper;
-import org.onap.sdc.frontend.ci.tests.utilities.NotificationComponent;
-import org.onap.sdc.frontend.ci.tests.utilities.NotificationComponent.NotificationType;
 import org.openqa.selenium.By;
 import org.openqa.selenium.Keys;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.ui.Select;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Handles the Resource Create Page UI actions
  */
 public class ResourceCreatePage extends ComponentPage {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(ResourceCreatePage.class);
-    private final LoaderHelper loaderHelper;
-    private final NotificationComponent notificationComponent;
-    private final ResourceWorkspaceTopBarComponent topBarComponent;
-    private final ResourceLeftSideMenu resourceLeftSideMenu;
-
     public ResourceCreatePage(final WebDriver webDriver) {
         super(webDriver);
-        this.loaderHelper = new LoaderHelper(webDriver);
-        this.notificationComponent = new NotificationComponent(webDriver);
-        this.resourceLeftSideMenu = new ResourceLeftSideMenu(webDriver);
-        this.topBarComponent = new ResourceWorkspaceTopBarComponent(webDriver);
         timeoutInSeconds = 5;
     }
 
@@ -64,38 +47,6 @@ public class ResourceCreatePage extends ComponentPage {
         waitForElementVisibility(By.xpath(XpathSelector.DESCRIPTION_TEXT_AREA.getXpath()));
     }
 
-    /**
-     * Creates the resource and wait for success notification.
-     */
-    public void clickOnCreate() {
-        topBarComponent.clickOnCreate();
-        loaderHelper.waitForLoader(20);
-        notificationComponent.waitForNotification(NotificationType.SUCCESS, 20);
-    }
-
-    /**
-     * Certifies the resource and wait for success notification.
-     */
-    public void clickOnCertify() {
-        topBarComponent.clickOnCertify();
-        final ComponentCertificationModal componentCertificationModal = new ComponentCertificationModal(webDriver);
-        componentCertificationModal.isLoaded();
-        componentCertificationModal.fillCommentWithDefaultMessage();
-        componentCertificationModal.submit();
-        loaderHelper.waitForLoader(20);
-        notificationComponent.waitForNotification(NotificationType.SUCCESS, 20);
-    }
-
-    public ToscaArtifactsPage goToToscaArtifacts() {
-        resourceLeftSideMenu.isLoaded();
-        return resourceLeftSideMenu.clickOnToscaArtifactsMenuItem();
-    }
-
-    public CompositionPage goToComposition() {
-        resourceLeftSideMenu.isLoaded();
-        return resourceLeftSideMenu.clickOnCompositionMenuItem();
-    }
-
     public void fillForm(final ResourceCreateData resourceCreateData) {
         fillName(resourceCreateData.getName());
         setCategory(resourceCreateData.getCategory());
index f94b303..c6366b3 100644 (file)
@@ -26,7 +26,6 @@ import org.onap.sdc.frontend.ci.tests.pages.component.workspace.ToscaArtifactsPa
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.ui.ExpectedConditions;
 
 /**
  * Handles the Resource Page Left Side Menu UI actions
@@ -43,6 +42,7 @@ public class ResourceLeftSideMenu extends AbstractPageObject {
     @Override
     public void isLoaded() {
         wrappingElement = getWrappingElement();
+        waitToBeClickable(By.xpath(XpathSelector.GENERAL_MENU.getXpath()));
     }
 
     /**
@@ -51,8 +51,7 @@ public class ResourceLeftSideMenu extends AbstractPageObject {
      * @return the enclosing element
      */
     public WebElement getWrappingElement() {
-        return getWait()
-            .until(ExpectedConditions.visibilityOfElementLocated(By.className(XpathSelector.MAIN_DIV.getId())));
+        return waitForElementVisibility(By.className(XpathSelector.MAIN_DIV.getId()));
     }
 
     /**
index 9af7e73..1b92b5b 100644 (file)
@@ -60,16 +60,19 @@ public class ResourceWorkspaceTopBarComponent extends AbstractPageObject {
         waitToBeClickable(XpathSelector.CREATE_BTN.getXpath()).click();
     }
 
-    public void clickOnCertify() {
+    public ComponentCertificationModal clickOnCertify() {
         waitToBeClickable(XpathSelector.CERTIFY_BTN.getXpath()).click();
+        return new ComponentCertificationModal(webDriver);
     }
 
-    public void certifyComponent() {
-        clickOnCertify();
-        final ComponentCertificationModal componentCertificationModal = new ComponentCertificationModal(webDriver);
+    /**
+     * Certify the resource and wait for success notification.
+     */
+    public void certifyResource() {
+        final ComponentCertificationModal componentCertificationModal = clickOnCertify();
         componentCertificationModal.isLoaded();
-        componentCertificationModal.fillCommentWithDefaultMessage();
-        componentCertificationModal.submit();
+        componentCertificationModal.fillComment("Certifying for the UI Integration Test");
+        componentCertificationModal.clickOnOkButton();
         notificationComponent.waitForNotification(NotificationType.SUCCESS, 20);
     }
 
index d2b5167..d15c2ef 100644 (file)
 
 package org.onap.sdc.frontend.ci.tests.pages;
 
-import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionPage;
-import org.onap.sdc.frontend.ci.tests.pages.component.workspace.ToscaArtifactsPage;
 import org.openqa.selenium.WebDriver;
 
 public class ServiceComponentPage extends ComponentPage {
 
-    private final TopNavComponent topNavComponent;
-    private final ResourceLeftSideMenu resourceLeftSideMenu;
-    private final ResourceWorkspaceTopBarComponent workspaceTopBarComponent;
-
     public ServiceComponentPage(final WebDriver webDriver) {
         super(webDriver);
-        this.topNavComponent = new TopNavComponent(webDriver);
-        this.resourceLeftSideMenu = new ResourceLeftSideMenu(webDriver);
-        this.workspaceTopBarComponent = new ResourceWorkspaceTopBarComponent(webDriver);
-    }
-
-    public ServiceComponentPage(final WebDriver webDriver, final TopNavComponent topNavComponent,
-                                final ResourceLeftSideMenu resourceLeftSideMenu,
-                                final ResourceWorkspaceTopBarComponent workspaceTopBarComponent) {
-        super(webDriver);
-        this.topNavComponent = topNavComponent;
-        this.resourceLeftSideMenu = resourceLeftSideMenu;
-        this.workspaceTopBarComponent = workspaceTopBarComponent;
     }
 
     @Override
     public void isLoaded() {
-        topNavComponent.isLoaded();
-        resourceLeftSideMenu.isLoaded();
-        workspaceTopBarComponent.isLoaded();
-    }
-
-    public ResourcePropertiesAssignmentPage goToPropertiesAssignment() {
-        return resourceLeftSideMenu.clickOnPropertiesAssignmentMenuItem();
-    }
-
-    public ToscaArtifactsPage goToToscaArtifacts() {
-        return resourceLeftSideMenu.clickOnToscaArtifactsMenuItem();
-    }
-
-    public CompositionPage goToComposition() {
-        return resourceLeftSideMenu.clickOnCompositionMenuItem();
+        super.isLoaded();
     }
 
 }
index 88b682b..3c560f4 100644 (file)
@@ -19,6 +19,7 @@
 
 package org.onap.sdc.frontend.ci.tests.pages;
 
+import java.time.Duration;
 import java.util.List;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
@@ -28,7 +29,6 @@ import org.openqa.selenium.By;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.interactions.Actions;
-import org.openqa.selenium.support.ui.ExpectedConditions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -116,7 +116,6 @@ public class TopNavComponent extends AbstractPageObject {
      * @return the next page object
      */
     public OnboardHomePage clickOnOnboard() {
-        waitForElementInvisibility(By.xpath(XpathSelector.SDC_LOADER_BACKGROUND.getXpath()));
         wrappingElement.findElement(By.xpath(XpathSelector.MAIN_MENU_ONBOARD_BTN.getXpath())).click();
         return new OnboardHomePage(DriverFactory.getDriver(), new OnboardHeaderComponent(DriverFactory.getDriver()));
     }
@@ -129,11 +128,9 @@ public class TopNavComponent extends AbstractPageObject {
      */
     public WebElement hoverToBreadcrumbArrow(final int arrowPosition) {
         final Actions actions = new Actions(webDriver);
-        final List<WebElement> arrowElementList = getWait()
-            .until(
-                ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath(XpathSelector.ARROW_DROPDOWN.getXpath())));
+        final List<WebElement> arrowElementList = waitForAllElementsVisibility(By.xpath(XpathSelector.ARROW_DROPDOWN.getXpath()));
         final WebElement selectedArrowElement = arrowElementList.get(arrowPosition);
-        actions.moveByOffset(20, 20).moveToElement(selectedArrowElement).perform();
+        actions.moveByOffset(20, 20).moveToElement(selectedArrowElement).pause(Duration.ofMillis(500)).perform();
         return selectedArrowElement;
     }
 
@@ -147,8 +144,7 @@ public class TopNavComponent extends AbstractPageObject {
         MAIN_MENU_LINK_HOME("main-menu-button-home", "//*[@data-tests-id='%s']"),
         ARROW_DROPDOWN("triangle-dropdown", "//li[contains(@class, '%s')]"),
         MAIN_MENU_ONBOARD_BTN("main-menu-button-onboard", "//a[@data-tests-id='%s']"),
-        REPOSITORY_ICON("repository-icon", "//*[@data-tests-id='%s']"),
-        SDC_LOADER_BACKGROUND("sdc-loader-global-wrapper sdc-loader-background", "//div[@class='%s']");
+        REPOSITORY_ICON("repository-icon", "//*[@data-tests-id='%s']");
 
         @Getter
         private final String id;
index f339412..7b8ebf5 100644 (file)
@@ -37,6 +37,7 @@ import org.onap.sdc.backend.ci.tests.utils.general.AtomicOperationUtils;
 import org.onap.sdc.frontend.ci.tests.datatypes.CanvasNodeElement;
 import org.onap.sdc.frontend.ci.tests.exception.CompositionCanvasRuntimeException;
 import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions;
+import org.onap.sdc.frontend.ci.tests.flow.exception.UiTestFlowRuntimeException;
 import org.onap.sdc.frontend.ci.tests.pages.AbstractPageObject;
 import org.openecomp.sdc.be.model.ComponentInstance;
 import org.openecomp.sdc.be.model.Resource;
@@ -99,12 +100,6 @@ public class CompositionCanvasComponent extends AbstractPageObject {
         canvasCenterX = canvasWidth / 2;
         canvasCenterY = canvasHeight / 2;
         LOGGER.debug("Canvas with size [{}, {}] and center [{}, {}]", canvasWidth, canvasHeight, canvasCenterX, canvasCenterY);
-        final String scriptJS = "var cy = window.jQuery('.sdc-composition-graph-wrapper').cytoscape('get');\n"
-            + "return JSON.stringify({width: cy.width(), height: cy.height()});";
-        final Object sizeObj = ((JavascriptExecutor) webDriver).executeScript(scriptJS);
-        final JsonObject size = new JsonParser().parse(sizeObj.toString()).getAsJsonObject();
-
-        LOGGER.debug("Canvas with size [{}, {}]", size.get("width"), size.get("height"));
     }
 
     private void loadElements() {
@@ -250,6 +245,49 @@ public class CompositionCanvasComponent extends AbstractPageObject {
         return new ImmutablePair<>(xElement, yElement);
     }
 
+    public RelationshipWizardComponent createLink(final String fromNodeName, final String toNodeName) {
+        final CanvasNodeElement fromCanvasElement = canvasElementList.stream()
+            .filter(canvasNodeElement -> canvasNodeElement.getName().equals(fromNodeName)).findFirst()
+            .orElseThrow(() -> new UiTestFlowRuntimeException(String.format("Could not find node '%s'", fromNodeName)));
+        final CanvasNodeElement toCanvasElement = canvasElementList.stream()
+            .filter(canvasNodeElement -> canvasNodeElement.getName().equals(toNodeName)).findFirst()
+            .orElseThrow(() -> new UiTestFlowRuntimeException(String.format("Could not find node '%s'", toNodeName)));
+
+        final Point greenPlusPosition = getElementGreenPlusPosition(fromCanvasElement.getName());
+        final Point greenPlusPositionFromCenter = calculateOffsetFromCenter(greenPlusPosition);
+        final Point toElementPositionFromCenter = calculateOffsetFromCenter(toCanvasElement.getPositionX(), toCanvasElement.getPositionY());
+        new Actions(webDriver)
+            .moveToElement(canvasWebElement, greenPlusPositionFromCenter.getX(), greenPlusPositionFromCenter.getY())
+            .moveByOffset(3, 3).moveByOffset(-3, -3)
+            .pause(Duration.ofSeconds(2))
+            .clickAndHold()
+            .pause(Duration.ofSeconds(1))
+            .moveToElement(canvasWebElement, toElementPositionFromCenter.getX(), toElementPositionFromCenter.getY())
+            .pause(Duration.ofSeconds(1))
+            .release()
+            .perform();
+        return new RelationshipWizardComponent(webDriver);
+    }
+
+    public Point getElementGreenPlusPosition(final String elementName) {
+        String scriptJS = "var cy = window.jQuery('.sdc-composition-graph-wrapper').cytoscape('get');\n"
+            + "var cyZoom = cy.zoom();\n"
+            + "var n = cy.nodes('[name=\"" + elementName + "\"]');\n"
+            + "var nPos = n.renderedPosition();\n"
+            + "var nData = n.data();\n"
+            + "var nImgSize = nData.imgWidth;\n"
+            + "var shiftSize = (nImgSize-18)*cyZoom/2;\n"
+            + "return JSON.stringify({\n"
+            + "\tx: nPos.x + shiftSize,\n"
+            + "\ty: nPos.y - shiftSize\n"
+            + "});";
+        final String o = (String) ((JavascriptExecutor) webDriver).executeScript(scriptJS);
+        final JsonObject node = new JsonParser().parse(o).getAsJsonObject();
+        final int x = node.get("x").getAsInt();
+        final int y = node.get("y").getAsInt();
+        return new Point(x, y);
+    }
+
     /**
      * Enum that contains identifiers and xpath expressions to elements related to the enclosing page object.
      */
index 214885a..b80b28c 100644 (file)
@@ -76,6 +76,8 @@ public class CompositionDetailSideBarComponent extends AbstractPageObject {
                 return new CompositionApiArtifactsTab(webDriver);
             case SUBSTITUTION_FILTER:
                 return new CompositionSubstitutionFilterTab(webDriver);
+            case REQUIREMENTS_CAPABILITIES:
+                return new CompositionRequirementsCapabilitiesTab(webDriver);
             default:
                 throw new IllegalStateException("Not yet implemented: " + tabName);
         }
@@ -95,6 +97,7 @@ public class CompositionDetailSideBarComponent extends AbstractPageObject {
         INPUTS_TAB("detail-tab-inputs", "//li[@data-tests-id='%s']"),
         DEPLOYMENT_ARTIFACTS_TAB("detail-tab-deployment-artifacts", "//li[@data-tests-id='%s']"),
         INFORMATION_ARTIFACTS_TAB("detail-tab-information-artifacts", "//li[@data-tests-id='%s']"),
+        REQUIREMENTS_CAPABILITIES_TAB("detail-tab-requirements-capabilities", "//li[@data-tests-id='%s']"),
         API_ARTIFACTS_TAB("detail-tab-api-artifacts", "//li[@data-tests-id='%s']"),
         SUBSTITUTION_FILTER_TAB("detail-tab-substitution-filter", "//li[@data-tests-id='%s']");
 
@@ -115,7 +118,8 @@ public class CompositionDetailSideBarComponent extends AbstractPageObject {
         DEPLOYMENT_ARTIFACTS(XpathSelector.DEPLOYMENT_ARTIFACTS_TAB),
         INFORMATIONAL_ARTIFACTS(XpathSelector.INFORMATION_ARTIFACTS_TAB),
         API_ARTIFACTS(XpathSelector.API_ARTIFACTS_TAB),
-        SUBSTITUTION_FILTER(XpathSelector.SUBSTITUTION_FILTER_TAB);
+        SUBSTITUTION_FILTER(XpathSelector.SUBSTITUTION_FILTER_TAB),
+        REQUIREMENTS_CAPABILITIES(XpathSelector.REQUIREMENTS_CAPABILITIES_TAB);
 
         private final XpathSelector xpathSelector;
 
index fb07aec..8dfc6e8 100644 (file)
@@ -20,7 +20,7 @@
 package org.onap.sdc.frontend.ci.tests.pages.component.workspace;
 
 import org.onap.sdc.frontend.ci.tests.pages.AbstractPageObject;
-import org.onap.sdc.frontend.ci.tests.pages.ResourceCreatePage;
+import org.onap.sdc.frontend.ci.tests.pages.ComponentPage;
 import org.onap.sdc.frontend.ci.tests.pages.ResourceWorkspaceTopBarComponent;
 import org.onap.sdc.frontend.ci.tests.pages.ServiceComponentPage;
 import org.onap.sdc.frontend.ci.tests.pages.TopNavComponent;
@@ -66,6 +66,10 @@ public class CompositionPage extends AbstractPageObject {
         return compositionCanvasComponent.createNodeOnResourceCanvas(serviceName, serviceVersion, resourceName, resourceVersion);
     }
 
+    public RelationshipWizardComponent createLink(final String fromNodeName, final String toNodeName) {
+        return compositionCanvasComponent.createLink(fromNodeName, toNodeName);
+    }
+
     /**
      * Select a node in the canvas
      *
@@ -76,9 +80,9 @@ public class CompositionPage extends AbstractPageObject {
         compositionDetailSideBarComponent.checkComponentIsSelected(nodeName);
     }
 
-    public ResourceCreatePage goToGeneral() {
+    public ComponentPage goToGeneral() {
         topNavComponent.clickOnBreadCrumb(1);
-        return new ResourceCreatePage(webDriver);
+        return new ComponentPage(webDriver);
     }
 
     public ServiceComponentPage goToServiceGeneral() {
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionRequirementsCapabilitiesTab.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionRequirementsCapabilitiesTab.java
new file mode 100644 (file)
index 0000000..bee2d3a
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.sdc.frontend.ci.tests.pages.component.workspace;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.onap.sdc.frontend.ci.tests.flow.exception.UiTestFlowRuntimeException;
+import org.onap.sdc.frontend.ci.tests.pages.AbstractPageObject;
+import org.onap.sdc.frontend.ci.tests.utilities.LoaderHelper;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Represents the composition page, details panel, Substitution Filters tab.
+ */
+public class CompositionRequirementsCapabilitiesTab extends AbstractPageObject {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(CompositionRequirementsCapabilitiesTab.class);
+
+    private Map<String, WebElement> checkboxExternalRequirementMap;
+    private final LoaderHelper loaderHelper;
+
+    public CompositionRequirementsCapabilitiesTab(final WebDriver webDriver) {
+        super(webDriver);
+        loaderHelper = new LoaderHelper(webDriver);
+    }
+
+    @Override
+    public void isLoaded() {
+        waitForElementVisibility(By.xpath(XpathSelector.REQ_CAPABILITIES_TAB.getXPath()));
+        waitForElementVisibility(By.xpath(XpathSelector.CAPABILITIES_ACCORDION.getXPath()));
+        waitForElementVisibility(By.xpath(XpathSelector.REQUIREMENTS_ACCORDION.getXPath()));
+    }
+
+    public void clickOnRequirements() {
+        waitForElementVisibility(XpathSelector.REQUIREMENTS_ACCORDION.getXPath()).click();
+        loadRequirements();
+    }
+
+    public void clickOnCapabilities() {
+        waitForElementVisibility(XpathSelector.CAPABILITIES_ACCORDION.getXPath()).click();
+    }
+
+    private void loadRequirements() {
+        final List<WebElement> webElements = waitForAllElementsVisibility(By.xpath("//checkbox[@data-tests-id]"));
+        checkboxExternalRequirementMap = new HashMap<>();
+        webElements.forEach(webElement -> {
+            final String dataTestsId = webElement.getAttribute("data-tests-id");
+            checkboxExternalRequirementMap.put(dataTestsId.substring("checkbox-mark-as-external-".length()), webElement);
+        });
+    }
+
+    public void toggleRequirementAsExternal(final String requirementName) {
+        LOGGER.debug("Externalizing the requirement '{}'", requirementName);
+        if (checkboxExternalRequirementMap == null) {
+            throw new UiTestFlowRuntimeException("The requirements checkbox map is not loaded. Did you call clickOnRequirements?");
+        }
+        final WebElement element = checkboxExternalRequirementMap.get(requirementName);
+        if (element == null) {
+            fail(String.format("Could not find requirement '%s'", requirementName));
+        }
+        element.click();
+        loaderHelper.waitForLoader(LoaderHelper.XpathSelector.LOADER_WITH_LOADER_BACKGROUND, 10);
+    }
+
+
+    @AllArgsConstructor
+    @Getter
+    private enum XpathSelector {
+        REQ_CAPABILITIES_TAB("//req-capabilities-tab"),
+        CAPABILITIES_ACCORDION("//div[@data-tests-id='Capabilities-accordion']"),
+        REQUIREMENTS_ACCORDION("//div[@data-tests-id='Requirements-accordion']");
+
+        private final String xPath;
+
+    }
+}
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/RelationshipWizardComponent.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/RelationshipWizardComponent.java
new file mode 100644 (file)
index 0000000..51ade3a
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.sdc.frontend.ci.tests.pages.component.workspace;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.onap.sdc.frontend.ci.tests.pages.AbstractPageObject;
+import org.openqa.selenium.WebDriver;
+
+/**
+ * Represents the relationship wizard dialog that is used when creating a relationship between two nodes in the composition screen.
+ */
+public class RelationshipWizardComponent extends AbstractPageObject {
+
+    public RelationshipWizardComponent(final WebDriver webDriver) {
+        super(webDriver);
+    }
+
+    @Override
+    public void isLoaded() {
+        waitForElementVisibility(XpathSelector.WIZARD.getXpath());
+        waitForElementVisibility(XpathSelector.CANCEL_BUTTON.getXpath());
+        waitForElementVisibility(XpathSelector.NEXT_BUTTON.getXpath());
+    }
+
+    public void clickOnNext() {
+        waitToBeClickable(XpathSelector.NEXT_BUTTON.getXpath()).click();
+    }
+
+    public void clickOnBack() {
+        waitToBeClickable(XpathSelector.BACK_BUTTON.getXpath()).click();
+    }
+
+    public void clickOnCancel() {
+        waitToBeClickable(XpathSelector.CANCEL_BUTTON.getXpath()).click();
+    }
+
+    public void clickOnFinish() {
+        waitToBeClickable(XpathSelector.FINISH_BUTTON.getXpath()).click();
+    }
+
+    /**
+     * Enum that contains identifiers and xpath expressions to elements related to the enclosing page object.
+     */
+    @AllArgsConstructor
+    private enum XpathSelector {
+        WIZARD("//multi-steps-wizard"),
+        WIZARD_FOOTER("//multi-steps-wizard//div[@class='ng2-modal-footer']"),
+        CANCEL_BUTTON(WIZARD_FOOTER.getXpath() + "//button[text()='Cancel']"),
+        NEXT_BUTTON(WIZARD_FOOTER.getXpath() + "//div[contains(@class, 'white-arrow-next')]/.."),
+        BACK_BUTTON(WIZARD_FOOTER.getXpath() + "//div[contains(@class, 'blue-arrow-back')]/.."),
+        FINISH_BUTTON(WIZARD_FOOTER.getXpath() + "//button[contains(text(), 'Finish')]");
+
+        @Getter
+        private final String xpath;
+    }
+}
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/RelationshipWizardRequirementCapabilityComponent.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/RelationshipWizardRequirementCapabilityComponent.java
new file mode 100644 (file)
index 0000000..0b3d776
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.sdc.frontend.ci.tests.pages.component.workspace;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.onap.sdc.frontend.ci.tests.pages.AbstractPageObject;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.Select;
+
+/**
+ * Represents the relationship/capability screen from the relationship wizard dialog.
+ */
+public class RelationshipWizardRequirementCapabilityComponent extends AbstractPageObject {
+
+    private WebElement wrappingElement;
+
+    public RelationshipWizardRequirementCapabilityComponent(final WebDriver webDriver) {
+        super(webDriver);
+    }
+
+    @Override
+    public void isLoaded() {
+        wrappingElement = waitForElementVisibility(XpathSelector.REQUIREMENT_CAPABILITY.getXpath());
+    }
+
+    /**
+     * Select a requirement or capability from the <select> by the name.
+     * @param requirementOrCapabilityName the requirement/capability name
+     */
+    public void selectRequirementOrCapability(final String requirementOrCapabilityName) {
+        final Select reqCapSelect = new Select(wrappingElement.findElement(By.xpath(XpathSelector.SELECT_REQUIREMENT_CAPABILITY.getXpath())));
+        reqCapSelect.selectByVisibleText(requirementOrCapabilityName);
+    }
+
+    /**
+     * Enum that contains identifiers and xpath expressions to elements related to the enclosing page object.
+     */
+    @AllArgsConstructor
+    private enum XpathSelector {
+        REQUIREMENT_CAPABILITY("//select-requirement-or-capability"),
+        SELECT_REQUIREMENT_CAPABILITY("//select[@data-tests-id='value-select']");
+
+        @Getter
+        private final String xpath;
+    }
+
+}
index 94568ca..c0d58e0 100644 (file)
@@ -27,8 +27,6 @@ import lombok.AllArgsConstructor;
 import lombok.Getter;
 import org.onap.sdc.frontend.ci.tests.pages.AbstractPageObject;
 import org.onap.sdc.frontend.ci.tests.pages.ResourceCreatePage;
-import org.onap.sdc.frontend.ci.tests.pages.ResourceLeftSideMenu;
-import org.onap.sdc.frontend.ci.tests.pages.ResourceWorkspaceTopBarComponent;
 import org.onap.sdc.frontend.ci.tests.pages.ServiceComponentPage;
 import org.onap.sdc.frontend.ci.tests.pages.ServiceCreatePage;
 import org.onap.sdc.frontend.ci.tests.pages.TopNavComponent;
@@ -127,8 +125,7 @@ public class HomePage extends AbstractPageObject {
         final String text = componentTypeDiv.getText();
         element.click();
         if ("S".equals(text)) {
-            return new ServiceComponentPage(webDriver, topNavComponent,
-                new ResourceLeftSideMenu(webDriver), new ResourceWorkspaceTopBarComponent(webDriver));
+            return new ServiceComponentPage(webDriver);
         }
 
         throw new UnsupportedOperationException("Return not yet implemented for " + text);
index b45d329..6406c2a 100644 (file)
 
 package org.onap.sdc.frontend.ci.tests.utilities;
 
+import lombok.AllArgsConstructor;
+import lombok.Getter;
 import org.onap.sdc.frontend.ci.tests.pages.AbstractPageObject;
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebDriver;
 
 public class LoaderHelper extends AbstractPageObject {
 
-    private final By loaderLocator = By.xpath("//*[@data-tests-id='loader' or @class='tlv-loader' or @class='sdc-loader' or @class='sdc-loader-global-wrapper sdc-loader-background']");
+    private final By loaderLocator = By.xpath(
+        "//*[@data-tests-id='loader' or @class='tlv-loader' or @class='sdc-loader' or @class='sdc-loader-global-wrapper sdc-loader-background']");
 
     public LoaderHelper(final WebDriver webDriver) {
         super(webDriver);
     }
 
+    /**
+     * Wait for the loader to be visible and then invisible.
+     *
+     * @param timeout the time in seconds to wait for the loader.
+     * @deprecated this method uses a generic locator to find for the loader, but the selector is not generic enough to every loader and can find
+     * unrelated loaders on the screen. Use {@link #waitForLoader(XpathSelector, int)} instead, where it is possible to use a specific loader
+     * selector.
+     */
+    @Deprecated
     public void waitForLoader(final int timeout) {
         waitForElementVisibility(loaderLocator, timeout);
         waitForElementInvisibility(loaderLocator, timeout);
     }
 
+    /**
+     * Wait for the loader to be visible and then invisible.
+     *
+     * @param xpathSelector    the xpath to find the loader
+     * @param timeoutInSeconds the time in seconds to wait for the loader.
+     */
+    public void waitForLoader(final XpathSelector xpathSelector, final int timeoutInSeconds) {
+        final By xpath = By.xpath(xpathSelector.getXpath());
+        try {
+            waitForElementVisibility(xpath, timeoutInSeconds);
+        } catch (final Exception ignored) {
+            //if no loader is visible anymore, just ignore
+        }
+        waitForElementInvisibility(xpath, timeoutInSeconds);
+    }
+
     public void waitForLoaderInvisibility(final int timeout) {
         waitForElementInvisibility(loaderLocator, timeout);
     }
 
     @Override
     public void isLoaded() {
+        //is loaded is not applicable to this component.
+    }
+
+    /**
+     * Enum that contains identifiers and xpath expressions to elements related to the enclosing page object.
+     */
+    @AllArgsConstructor
+    @Getter
+    public enum XpathSelector {
+        LOADER_WITH_LOADER_BACKGROUND("//*[contains(@class, 'sdc-loader-background')]");
 
+        private final String xpath;
     }
 }
diff --git a/integration-tests/src/test/resources/Files/VNFs/etsi-vnf-virtual-linkable.csar b/integration-tests/src/test/resources/Files/VNFs/etsi-vnf-virtual-linkable.csar
new file mode 100644 (file)
index 0000000..929833c
Binary files /dev/null and b/integration-tests/src/test/resources/Files/VNFs/etsi-vnf-virtual-linkable.csar differ
index a834ffd..9a4eab1 100644 (file)
         </methods>
       </class>
       <class name="org.onap.sdc.frontend.ci.tests.execute.sanity.GAB"/>
-      <class name="org.onap.sdc.frontend.ci.tests.execute.sanity.EtsiNetworkServiceUiTests">
-        <methods>
-          <include name="createEtsiNetworkService"/>
-        </methods>
-      </class>
+      <class name="org.onap.sdc.frontend.ci.tests.execute.sanity.EtsiNetworkServiceUiTests"/>
       <class name="org.onap.sdc.frontend.ci.tests.execute.sanity.EtsiOnboardVnfCnfUiTests">
         <methods>
           <include name="createVlm"/>