Enrich 'Import VFC UI test' 11/120911/2
authorvasraz <vasyl.razinkov@est.tech>
Mon, 26 Apr 2021 13:52:08 +0000 (14:52 +0100)
committervasraz <vasyl.razinkov@est.tech>
Tue, 27 Apr 2021 15:09:16 +0000 (16:09 +0100)
Import a node types which contains interface operations with an implementation and inputs

Change-Id: Ibf778747b69c60514d94985fc13097403ae1dd56
Signed-off-by: Vasyl Razinkov <vasyl.razinkov@est.tech>
Issue-ID: SDC-3567

catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/input-param-row/input-param-row.component.html
catalog-ui/src/app/ng2/pages/composition/interface-operatons/operation-creator/interface-operation-handler.component.html
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/pages/ResourceCreatePage.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/CompositionInterfaceOperationsModal.java [new file with mode: 0644]
integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInterfaceOperationsTab.java [new file with mode: 0644]
integration-tests/src/test/resources/Files/VFCs/org.openecomp.resource.VFC-child.yml

index 80aceea..156b657 100644 (file)
@@ -21,6 +21,7 @@
 <div class="cell field-input-name">
     <sdc-input
         [(value)]="input.name"
+        testId="interface-operation-input-name"
         (valueChange)="onChange()">
     </sdc-input>
 </div>
@@ -28,9 +29,9 @@
 <div class="cell field-input-value">
     <sdc-input
         [(value)]="input.toscaDefaultValue"
+        testId="interface-operation-input-value"
         (valueChange)="onChange()">
     </sdc-input>
-
 </div>
 
 <div class="cell remove" *ngIf="!readonly">
index cd2d606..f711020 100644 (file)
 -->
 
 <div class="operation-handler">
-  <loader [display]="isLoading" [size]="'large'" [relative]="true"></loader>
+    <loader [display]="isLoading" [size]="'large'" [relative]="true"></loader>
 
-  <form class="w-sdc-form">
+    <form class="w-sdc-form">
 
-    <div class="side-by-side">
-      <div class="form-item">
-        <sdc-input
-            label="{{ 'OPERATION_INTERFACE_TYPE' | translate }}"
-            [(value)]="interfaceType"
-            [disabled]="true">
-        </sdc-input>
-      </div>
+        <div class="side-by-side">
+            <div class="form-item">
+                <sdc-input
+                    label="{{ 'OPERATION_INTERFACE_TYPE' | translate }}"
+                    [(value)]="interfaceType"
+                    [disabled]="true">
+                </sdc-input>
+            </div>
 
-      <div class="form-item">
-        <sdc-input
-            label="{{ 'OPERATION_NAME' | translate }}"
-            [(value)]="operationToUpdate.name"
-            [disabled]="true">
-        </sdc-input>
-      </div>
-    </div>
+            <div class="form-item">
+                <sdc-input
+                    label="{{ 'OPERATION_NAME' | translate }}"
+                    [(value)]="operationToUpdate.name"
+                    [disabled]="true">
+                </sdc-input>
+            </div>
+        </div>
 
-    <div class="i-sdc-form-item">
-      <sdc-input
-          label="{{'OPERATION_DESCRIPTION' | translate}}"
-          [(value)]="operationToUpdate.description"
-          (valueChange)="onDescriptionChange($event)">
-      </sdc-input>
-    </div>
+        <div class="i-sdc-form-item">
+            <sdc-input
+                label="{{'OPERATION_DESCRIPTION' | translate}}"
+                [(value)]="operationToUpdate.description"
+                testId="interface-operation-description"
+                (valueChange)="onDescriptionChange($event)">
+            </sdc-input>
+        </div>
 
-    <div class="i-sdc-form-item">
-      <sdc-input
-          label="{{'IMPLEMENTATION_NAME' | translate}}"
-          [(value)]="operationToUpdate.implementation.artifactName">
-      </sdc-input>
-    </div>
+        <div class="i-sdc-form-item">
+            <sdc-input
+                label="{{'IMPLEMENTATION_NAME' | translate}}"
+                testId="interface-operation-implementation-name"
+                [(value)]="operationToUpdate.implementation.artifactName">
+            </sdc-input>
+        </div>
 
-    <div class="separator-buttons">
-      <tab tabTitle="Inputs"></tab>
-      <a class="add-param-link add-btn"
-         [ngClass]="{'disabled': readonly}"
-         (click)="onAddInput()">{{'OPERATION_ADD_INPUT' | translate}}
-      </a>
-    </div>
+        <div class="separator-buttons">
+            <tab tabTitle="Inputs"></tab>
+            <a class="add-param-link add-btn"
+               [ngClass]="{'disabled': readonly}"
+               (click)="onAddInput()">{{'OPERATION_ADD_INPUT' | translate}}
+            </a>
+        </div>
 
-    <div class="generic-table">
-      <div class="header-row table-row">
-        <span class="cell header-cell field-input-name">{{ 'OPERATION_PARAM_NAME' | translate }}</span>
-        <span class="cell header-cell field-input-value">{{ 'OPERATION_INPUT_VALUE' | translate }}</span>
-        <span class="cell header-cell remove">●●●</span>
-      </div>
-      <div class="empty-msg data-row" *ngIf="!inputs.length">
-        <div>{{ 'OPERATION_INPUT_EMPTY' | translate }}</div>
-      </div>
-      <input-param-row
-          *ngFor="let inputParameter of inputs"
-          class="data-row"
-          [input]="inputParameter"
-          [onRemoveInput]="onRemoveInput"
-          [validityChanged]="validityChanged">
-      </input-param-row>
-    </div>
+        <div class="generic-table">
+            <div class="header-row table-row">
+                <span class="cell header-cell field-input-name">{{ 'OPERATION_PARAM_NAME' | translate }}</span>
+                <span class="cell header-cell field-input-value">{{ 'OPERATION_INPUT_VALUE' | translate }}</span>
+                <span class="cell header-cell remove">●●●</span>
+            </div>
+            <div class="empty-msg data-row" *ngIf="!inputs.length">
+                <div>{{ 'OPERATION_INPUT_EMPTY' | translate }}</div>
+            </div>
+            <input-param-row
+                *ngFor="let inputParameter of inputs"
+                class="data-row"
+                [input]="inputParameter"
+                [onRemoveInput]="onRemoveInput"
+                [validityChanged]="validityChanged">
+            </input-param-row>
+        </div>
 
-  </form>
+    </form>
 </div>
index 9c733f6..a571c1b 100644 (file)
@@ -25,8 +25,10 @@ import static org.hamcrest.Matchers.emptyString;
 import static org.hamcrest.Matchers.not;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
+import com.aventstack.extentreports.Status;
 import java.util.Arrays;
 import java.util.Map;
 import java.util.Optional;
@@ -37,6 +39,7 @@ import org.onap.sdc.frontend.ci.tests.datatypes.ComponentData;
 import org.onap.sdc.frontend.ci.tests.datatypes.ResourceCreateData;
 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.CreateVfFlow;
@@ -44,10 +47,16 @@ 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.ComponentPage;
+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.CompositionInformationTab;
+import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionInterfaceOperationsModal;
+import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionInterfaceOperationsTab;
 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.FileHandling;
+import org.openecomp.sdc.be.model.ComponentInstance;
 import org.openqa.selenium.WebDriver;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -105,20 +114,71 @@ public class ImportVfcUiTest extends SetupCDTest {
         componentPage = createVfFlow.getLandedPage().orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return ResourceCreatePage"));
         componentPage.isLoaded();
 
-        final AddNodeToCompositionFlow addNodeToCompositionFlow = addNodeToCompositionFlow(componentPage);
-
-        final CompositionPage compositionPage = addNodeToCompositionFlow.getLandedPage()
-            .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return CompositionPage"));
+        final CompositionPage compositionPage = addInterfaceOperations(componentPage);
         componentPage = compositionPage.goToGeneral();
         componentPage.isLoaded();
         componentPage.certifyComponent();
         componentPage.isLoaded();
+
         yamlObject = downloadToscaArtifact(componentPage);
         checkMetadata(yamlObject, vfCreateData);
         checkTopologyTemplate(yamlObject);
 
     }
 
+    private CompositionPage addInterfaceOperations(final ComponentPage componentPage) {
+        final AddNodeToCompositionFlow addNodeToCompositionFlow = addNodeToCompositionFlow(componentPage);
+        final CompositionPage compositionPage = addNodeToCompositionFlow.getLandedPage()
+            .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return CompositionPage"));
+        final CompositionDetailSideBarComponent detailSideBar = compositionPage.getDetailSideBar();
+        detailSideBar.isLoaded();
+
+        final ComponentInstance createdComponentInstance = addNodeToCompositionFlow.getCreatedComponentInstance()
+            .orElseThrow(() -> new UiTestFlowRuntimeException("Expecting a ComponentInstance"));
+
+        compositionPage.selectNode(createdComponentInstance.getName());
+
+        CompositionInterfaceOperationsTab compositionInterfaceOperationsTab =
+            (CompositionInterfaceOperationsTab) detailSideBar.selectTab(CompositionDetailTabName.INTERFACE_OPERATIONS);
+        compositionInterfaceOperationsTab.isLoaded();
+        ExtentTestActions.takeScreenshot(Status.INFO, "compositionInterfaceOperationsTab", "Composition Interface Operations Tab opened");
+        assertTrue(compositionInterfaceOperationsTab.isOperationPresent("create"));
+        CompositionInterfaceOperationsModal compositionInterfaceOperationsModal = compositionInterfaceOperationsTab.clickOnOperation("create");
+        compositionInterfaceOperationsModal.isLoaded();
+        ExtentTestActions
+            .takeScreenshot(Status.INFO, "compositionInterfaceOperationsTab.clickOnOperation", "Composition Interface Operations Modal opened");
+        compositionInterfaceOperationsModal.clickOnDelete();
+        ExtentTestActions.takeScreenshot(Status.INFO, "compositionInterfaceOperationsModal.clickOnDelete", "Input deleted");
+        compositionInterfaceOperationsModal.addInput();
+        ExtentTestActions.takeScreenshot(Status.INFO, "compositionInterfaceOperationsModal.addInput", "Adding Input");
+
+        final CompositionInterfaceOperationsModal.InterfaceOperationsData interfaceOperationsData = new CompositionInterfaceOperationsModal.InterfaceOperationsData
+            ("This is CREATE operation", "fullPath/to/my/newImplementation.sh", "second", "9876");
+        compositionInterfaceOperationsModal.updateInterfaceOperation(interfaceOperationsData);
+        compositionInterfaceOperationsTab.isLoaded();
+
+        final CompositionInformationTab compositionInformationTab =
+            (CompositionInformationTab) detailSideBar.selectTab(CompositionDetailTabName.INFORMATION);
+        compositionInformationTab.isLoaded();
+
+        compositionInterfaceOperationsTab =
+            (CompositionInterfaceOperationsTab) detailSideBar.selectTab(CompositionDetailTabName.INTERFACE_OPERATIONS);
+        compositionInterfaceOperationsTab.isLoaded();
+
+        assertTrue(compositionInterfaceOperationsTab.isOperationPresent("create"));
+        assertTrue(compositionInterfaceOperationsTab.isDescriptionPresent());
+        ExtentTestActions.takeScreenshot(Status.INFO, "isDescriptionPresent", "Description is present");
+        compositionInterfaceOperationsModal = compositionInterfaceOperationsTab.clickOnOperation("create");
+        compositionInterfaceOperationsModal.isLoaded();
+        ExtentTestActions
+            .takeScreenshot(Status.INFO, "compositionInterfaceOperationsTab.clickOnOperation", "Composition Interface Operations Modal opened");
+
+        checkCompositionInterfaceOperations(compositionInterfaceOperationsModal, interfaceOperationsData);
+        compositionInterfaceOperationsModal.clickOnCancel();
+        compositionInterfaceOperationsTab.isLoaded();
+        return compositionPage;
+    }
+
     private AddNodeToCompositionFlow addNodeToCompositionFlow(final ComponentPage componentPage) {
         componentPage.isLoaded();
         final ComponentData parentComponent = new ComponentData();
@@ -256,4 +316,12 @@ public class ImportVfcUiTest extends SetupCDTest {
         assertThat(interfaces, not(anEmptyMap()));
 
     }
+
+    private void checkCompositionInterfaceOperations(final CompositionInterfaceOperationsModal compositionInterfaceOperationsModal,
+                                                     final CompositionInterfaceOperationsModal.InterfaceOperationsData interfaceOperationsData) {
+        assertEquals(interfaceOperationsData.getDescription(), compositionInterfaceOperationsModal.getDescription());
+        assertEquals(interfaceOperationsData.getImplementationName(), compositionInterfaceOperationsModal.getImplementationName());
+        assertEquals(interfaceOperationsData.getInputName(), compositionInterfaceOperationsModal.getInputName());
+        assertEquals(interfaceOperationsData.getInputValue(), compositionInterfaceOperationsModal.getInputValue());
+    }
 }
index d6e023a..686f63c 100644 (file)
@@ -92,7 +92,7 @@ public class ResourceCreatePage extends ComponentPage {
     }
 
     private void fillDescription(final String description) {
-        setTextAreaField(By.xpath(XpathSelector.DESCRIPTION_TEXT_AREA.getXpath()), description);
+        setInputField(By.xpath(XpathSelector.DESCRIPTION_TEXT_AREA.getXpath()), description);
     }
 
     private void fillContactId(final String contactId) {
@@ -125,10 +125,6 @@ public class ResourceCreatePage extends ComponentPage {
         findElement(locator).sendKeys(value);
     }
 
-    private void setTextAreaField(final By locator, final String value) {
-        setInputField(locator, value);
-    }
-
     /**
      * Enum that contains identifiers and xpath expressions to elements related to the enclosing page object.
      */
index b80b28c..346f639 100644 (file)
@@ -78,6 +78,8 @@ public class CompositionDetailSideBarComponent extends AbstractPageObject {
                 return new CompositionSubstitutionFilterTab(webDriver);
             case REQUIREMENTS_CAPABILITIES:
                 return new CompositionRequirementsCapabilitiesTab(webDriver);
+            case INTERFACE_OPERATIONS:
+                return new CompositionInterfaceOperationsTab(webDriver);
             default:
                 throw new IllegalStateException("Not yet implemented: " + tabName);
         }
@@ -99,6 +101,7 @@ public class CompositionDetailSideBarComponent extends AbstractPageObject {
         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']"),
+        INTERFACE_OPERATIONS_TAB("detail-tab-interface-operations", "//li[@data-tests-id='%s']"),
         SUBSTITUTION_FILTER_TAB("detail-tab-substitution-filter", "//li[@data-tests-id='%s']");
 
         @Getter
@@ -119,6 +122,7 @@ public class CompositionDetailSideBarComponent extends AbstractPageObject {
         INFORMATIONAL_ARTIFACTS(XpathSelector.INFORMATION_ARTIFACTS_TAB),
         API_ARTIFACTS(XpathSelector.API_ARTIFACTS_TAB),
         SUBSTITUTION_FILTER(XpathSelector.SUBSTITUTION_FILTER_TAB),
+        INTERFACE_OPERATIONS(XpathSelector.INTERFACE_OPERATIONS_TAB),
         REQUIREMENTS_CAPABILITIES(XpathSelector.REQUIREMENTS_CAPABILITIES_TAB);
 
         private final XpathSelector xpathSelector;
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInterfaceOperationsModal.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInterfaceOperationsModal.java
new file mode 100644 (file)
index 0000000..434885c
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * ============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 com.aventstack.extentreports.Status;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions;
+import org.onap.sdc.frontend.ci.tests.pages.AbstractPageObject;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+/**
+ * Represents the Composition Interface Operations Modal.
+ */
+public class CompositionInterfaceOperationsModal extends AbstractPageObject {
+
+    public CompositionInterfaceOperationsModal(final WebDriver webDriver) {
+        super(webDriver);
+    }
+
+    @Override
+    public void isLoaded() {
+        waitForElementVisibility(By.xpath(XpathSelector.TITLE_SPAN.getXPath()));
+        waitForElementVisibility(By.xpath(XpathSelector.INTERFACE_NAME_LABEL.getXPath()));
+        waitForElementVisibility(By.xpath(XpathSelector.OPERATION_NAME_LABEL.getXPath()));
+        waitForElementVisibility(By.xpath(XpathSelector.INPUT_NAME_SPAN.getXPath()));
+        waitForElementVisibility(By.xpath(XpathSelector.INPUT_VALUE_SPAN.getXPath()));
+
+        waitToBeClickable(By.xpath(XpathSelector.ADD_INPUT_BTN.getXPath()));
+        waitToBeClickable(By.xpath(XpathSelector.SAVE_BTN.getXPath()));
+        waitToBeClickable(By.xpath(XpathSelector.CANCEL_BTN.getXPath()));
+    }
+
+    public void clickOnSave() {
+        waitToBeClickable(By.xpath(XpathSelector.SAVE_BTN.getXPath())).click();
+    }
+
+    public void clickOnCancel() {
+        waitToBeClickable(By.xpath(XpathSelector.CANCEL_BTN.getXPath())).click();
+    }
+
+    public void clickOnDelete() {
+        waitToBeClickable(By.xpath(XpathSelector.DELELE_BTN.getXPath())).click();
+    }
+
+    public void updateInterfaceOperation(final InterfaceOperationsData interfaceOperationsData) {
+        fillDescription(interfaceOperationsData.getDescription());
+        fillImplementationName(interfaceOperationsData.getImplementationName());
+        fillInputName(interfaceOperationsData.getInputName());
+        fillInputValue(interfaceOperationsData.getInputValue());
+        clickOnSave();
+    }
+
+    private void fillDescription(final String description) {
+        setInputField(By.xpath(XpathSelector.INTERFACE_OPERATION_DESCRIPTION_INPUT.getXPath()), description);
+    }
+
+    private void fillImplementationName(final String implementationName) {
+        setInputField(By.xpath(XpathSelector.INTERFACE_OPERATION_IMPLEMENTATION_NAME_INPUT.getXPath()), implementationName);
+    }
+
+    private void fillInputName(final String inputName) {
+        setInputField(By.xpath(XpathSelector.FIELD_INPUT_NAME_INPUT.getXPath()), inputName);
+    }
+
+    private void fillInputValue(final String inputValue) {
+        setInputField(By.xpath(XpathSelector.FIELD_INPUT_VALUE_INPUT.getXPath()), inputValue);
+    }
+
+    private void setInputField(final By locator, final String value) {
+        if (value == null) {
+            return;
+        }
+        final WebElement webElement = findElement(locator);
+        webElement.clear();
+        webElement.sendKeys(value);
+        ExtentTestActions.takeScreenshot(Status.INFO, value, value);
+    }
+
+    public void addInput() {
+        waitToBeClickable(By.xpath(XpathSelector.ADD_INPUT_BTN.getXPath())).click();
+    }
+
+    public String getDescription() {
+        return findElement(By.xpath(XpathSelector.INTERFACE_OPERATION_DESCRIPTION_INPUT.getXPath())).getAttribute("value");
+    }
+
+    public String getImplementationName() {
+        return findElement(By.xpath(XpathSelector.INTERFACE_OPERATION_IMPLEMENTATION_NAME_INPUT.getXPath())).getAttribute("value");
+    }
+
+    public String getInputName() {
+        return findElement(By.xpath(XpathSelector.FIELD_INPUT_NAME_INPUT.getXPath())).getAttribute("value");
+    }
+
+    public String getInputValue() {
+        return findElement(By.xpath(XpathSelector.FIELD_INPUT_VALUE_INPUT.getXPath())).getAttribute("value");
+    }
+
+    @Getter
+    @AllArgsConstructor
+    public static class InterfaceOperationsData {
+
+        private final String description;
+        private final String implementationName;
+        private final String inputName;
+        private final String inputValue;
+    }
+
+    @AllArgsConstructor
+    private enum XpathSelector {
+        TITLE_SPAN("//span[@class='title' and contains(text(), 'Edit Operation')]"),
+        ADD_INPUT_BTN("//a[contains(@class,'add-param-link add-btn') and contains(text(), 'Add Input')]"),
+        DELELE_BTN("//svg-icon[@name='trash-o']"),
+        SAVE_BTN("//button[@data-tests-id='Save']"),
+        CANCEL_BTN("//button[@data-tests-id='Cancel']"),
+        INTERFACE_NAME_LABEL("//label[contains(@class,'sdc-input') and contains(text(), 'Interface Name')]"),
+        OPERATION_NAME_LABEL("//label[contains(@class,'sdc-input') and contains(text(), 'Operation Name')]"),
+        INTERFACE_OPERATION_DESCRIPTION_INPUT("//input[@data-tests-id='interface-operation-description']"),
+        INTERFACE_OPERATION_IMPLEMENTATION_NAME_INPUT("//input[@data-tests-id='interface-operation-implementation-name']"),
+        INPUT_NAME_SPAN("//span[contains(@class,'field-input-name') and contains(text(), 'Name')]"),
+        INPUT_VALUE_SPAN("//span[contains(@class,'field-input-value') and contains(text(), 'Value')]"),
+        FIELD_INPUT_NAME_INPUT("//input[@data-tests-id='interface-operation-input-name']"),
+        FIELD_INPUT_VALUE_INPUT("//input[@data-tests-id='interface-operation-input-value']");
+
+        @Getter
+        private final String xPath;
+
+    }
+}
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInterfaceOperationsTab.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInterfaceOperationsTab.java
new file mode 100644 (file)
index 0000000..c672939
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * ============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.assertNotNull;
+
+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;
+
+/**
+ * Represents the Composition Interface Operations tab.
+ */
+public class CompositionInterfaceOperationsTab extends AbstractPageObject {
+
+    private WebElement webElement;
+
+    public CompositionInterfaceOperationsTab(final WebDriver webDriver) {
+        super(webDriver);
+    }
+
+    @Override
+    public void isLoaded() {
+        waitForElementVisibility(By.xpath(XpathSelector.INTERFACE_OPERATIONS.getXPath()));
+        waitForElementVisibility(By.xpath(XpathSelector.INTERFACE_NAME_SPAN.getXPath()));
+        webElement = findElement(By.xpath(XpathSelector.OPERATION_LIST.getXPath()));
+    }
+
+    public boolean isOperationPresent(final String operationName) {
+        try {
+            final WebElement webElementInterfaceRow = webElement.findElement(By.xpath(XpathSelector.INTERFACE_ROW.getXPath()));
+            webElementInterfaceRow.findElement(By.xpath(XpathSelector.FIELD_NAME_SPAN.getXPath(operationName)));
+        } catch (final Exception e) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean isDescriptionPresent() {
+        try {
+            final WebElement webElementInterfaceRow = webElement.findElement(By.xpath(XpathSelector.INTERFACE_ROW.getXPath()));
+            final WebElement rowElement = webElementInterfaceRow.findElement(By.xpath(XpathSelector.FIELD_DESCRIPTION_SPAN.getXPath()));
+            return rowElement != null && !rowElement.getText().isEmpty();
+        } catch (final Exception e) {
+            return false;
+        }
+    }
+
+    public CompositionInterfaceOperationsModal clickOnOperation(final String operationName) {
+        final WebElement webElementInterfaceRow = webElement.findElement(By.xpath(XpathSelector.INTERFACE_ROW.getXPath()));
+        webElementInterfaceRow.findElement(By.xpath(XpathSelector.FIELD_NAME_SPAN.getXPath(operationName))).click();
+        return new CompositionInterfaceOperationsModal(webDriver);
+    }
+
+    @AllArgsConstructor
+    private enum XpathSelector {
+        INTERFACE_OPERATIONS("//div[@class='interface-operations']"),
+        OPERATION_LIST("//div[@class='operation-list']"),
+        EXPAND_COLLAPSE("//div[@class='expand-collapse']"),
+        INTERFACE_ACCORDION("//div[@class='interface-accordion']"),
+        INTERFACE_ROW("//div[contains(@class,'interface-row')]"),
+        INTERFACE_NAME_SPAN("//span[@class='interface-name']"),
+        FIELD_NAME_SPAN("//span[contains(@class,'field-name') and contains(text(), '%s')]"),
+        FIELD_DESCRIPTION_SPAN("//span[contains(@class,'field-description')]");
+
+        @Getter
+        private final String xPath;
+
+        public String getXPath(final String... xpathParams) {
+            return String.format(xPath, xpathParams);
+        }
+
+    }
+}
index 2c00cbd..e86349a 100644 (file)
@@ -10,15 +10,27 @@ node_types:
       test_1:
         type: string
         default: 'MydefaultValue'
-
       test_2:
         type: integer
         default: 266305
-
       test_3:
         type: string
         default: 'TestValue3'
-
       test_4:
         type: boolean
-        default: true
\ No newline at end of file
+        default: true
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        inputs:
+          url_path:
+            type: string
+        operations:
+          create:
+            description: 'My create Desc'
+            implementation: path/to/my/implementation.sh
+            inputs:
+              first:
+                type: string
+                default: '1234'
+                description: My inputs Desc