summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvasraz <vasyl.razinkov@est.tech>2021-05-05 10:52:16 +0100
committerChristophe Closset <christophe.closset@intl.att.com>2021-05-06 07:05:14 +0000
commit92a380e5856be904b064a9136f93b4b45ec93834 (patch)
treead07b72e0eef2583b51e5578f0e97eed784ee050
parent00b288e068b418ab0ff00ff64ee204adbb4ba382 (diff)
Increase Import VFC UI test coverage
Change-Id: Ie51411304fefe6b8ee3aa437b980f1e12bbc4707 Signed-off-by: Vasyl Razinkov <vasyl.razinkov@est.tech> Issue-ID: SDC-3566
-rw-r--r--catalog-ui/src/app/ng2/pages/workspace/attributes/attribute-modal.component.html35
-rw-r--r--catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.component.html45
-rw-r--r--catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.component.ts344
-rw-r--r--integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ImportVfcUiTest.java73
-rw-r--r--integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AttributeModal.java118
-rw-r--r--integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AttributesPage.java126
-rw-r--r--integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ComponentPage.java8
-rw-r--r--integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourceLeftSideMenu.java19
-rw-r--r--integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/utilities/LoaderHelper.java3
9 files changed, 539 insertions, 232 deletions
diff --git a/catalog-ui/src/app/ng2/pages/workspace/attributes/attribute-modal.component.html b/catalog-ui/src/app/ng2/pages/workspace/attributes/attribute-modal.component.html
index 094045e8b4..590217d0a5 100644
--- a/catalog-ui/src/app/ng2/pages/workspace/attributes/attribute-modal.component.html
+++ b/catalog-ui/src/app/ng2/pages/workspace/attributes/attribute-modal.component.html
@@ -5,14 +5,14 @@
<!-- ATTRIBUTE NAME - MANDATORY -->
<div>
<sdc-input
- #attributeName
- label="Name"
- [required]="true"
- [(value)]="attributeToEdit.name"
- [disabled]="isEdit"
- name="attributeName"
- testId="attributeName"
- [maxLength]="255">
+ #attributeName
+ label="Name"
+ [required]="true"
+ [(value)]="attributeToEdit.name"
+ [disabled]="isEdit"
+ name="attributeName"
+ testId="attributeName"
+ [maxLength]="255">
</sdc-input>
<sdc-validation [validateElement]="attributeName" (validityChanged)="onValidityChange($event, 'name')">
<sdc-required-validator message="{{'VALIDATION_ERROR_REQUIRED' | translate : { 'field' : 'Name' } }}"></sdc-required-validator>
@@ -38,6 +38,7 @@
<!-- ATTRIBUTE TYPE - MANDATORY -->
<sdc-dropdown #attributeType [disabled]="false" label="Type" [required]="true"
[selectedOption]="toDropDownOption(this.attributeToEdit.type)" placeHolder="Choose Type"
+ testId="attributeType"
[options]="types" (changed)="onTypeSelected($event)">
<sdc-validation [validateElement]="attributeType" (validityChanged)="onValidityChange($event, 'type')">
<sdc-required-validator message="'required field'"></sdc-required-validator>
@@ -48,15 +49,15 @@
<!-- ATTRIBUTE DEFAULT VALUE TEXT - OPTIONAL -->
<div *ngIf="attributeToEdit.type != 'boolean'">
<sdc-input
- #_default
- [required]="false"
- label="Default Value"
- [(value)]="attributeToEdit._default"
- [disabled]="false"
- name="_default"
- testId="defaultValue"
- [maxLength]="255"
- (valueChange)="defaultValueChanged()">
+ #_default
+ [required]="false"
+ label="Default Value"
+ [(value)]="attributeToEdit._default"
+ [disabled]="false"
+ name="_default"
+ testId="defaultValue"
+ [maxLength]="255"
+ (valueChange)="defaultValueChanged()">
</sdc-input>
<sdc-validation [validateElement]="_default" (validityChanged)="onValidityChange($event, 'default')">
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.component.html b/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.component.html
index 6d50bbe11b..a04849a7f6 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.component.html
+++ b/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.component.html
@@ -17,27 +17,27 @@
<div class="action-bar-wrapper">
<svg-icon-label
- *ngIf="!(this.isViewOnly$ | async)"
- class="add-attr-icon"
- [name]="'plus'"
- [mode]="'primary'"
- [size]="'medium'"
- [label]="'Add'"
- [labelPlacement]="'right'"
- [labelClassName]="'externalActionLabel'"
- (click)="onAddAttribute()">
+ *ngIf="!(this.isViewOnly$ | async)"
+ class="add-attr-icon"
+ [name]="'plus'"
+ [mode]="'primary'"
+ [size]="'medium'"
+ [label]="'Add'"
+ [labelPlacement]="'right'"
+ [labelClassName]="'externalActionLabel'"
+ (click)="onAddAttribute()">
</svg-icon-label>
</div>
<ngx-datatable
- columnMode="flex"
- [footerHeight]="0"
- [limit]="50"
- [headerHeight]="40"
- [rowHeight]="35"
- [rows]="attributes"
- #componentAttributesTable
- (activate)="onExpandRow($event)">
+ columnMode="flex"
+ [footerHeight]="0"
+ [limit]="50"
+ [headerHeight]="40"
+ [rowHeight]="35"
+ [rows]="attributes"
+ #componentAttributesTable
+ (activate)="onExpandRow($event)">
<ngx-datatable-row-detail [rowHeight]="80">
<ng-template let-row="row" let-expanded="expanded" ngx-datatable-row-detail-template>
@@ -48,9 +48,10 @@
<ngx-datatable-column [resizeable]="false" name="Name" [flexGrow]="2">
<ng-template ngx-datatable-cell-template let-row="row" let-expanded="expanded">
- <div class="expand-collapse-cell">
+ <div class="expand-collapse-cell" [attr.data-tests-id]="'attrib-name_'+row.name">
<svg-icon [clickable]="true" class="expand-collapse-icon"
- [name]="expanded ? 'caret1-up-o': 'caret1-down-o'" [mode]="'primary'"
+ [name]="expanded ? 'caret1-up-o': 'caret1-down-o'"
+ [mode]="'primary'"
[size]="'medium'"></svg-icon>
<span>{{ row.name }}</span>
</div>
@@ -76,14 +77,16 @@
<svg-icon [clickable]="true"
[mode]="'primary2'"
[name]="'edit-o'"
+ [testId]="'edit_'+row.name"
[size]="'medium'"
(click)="onEditAttribute($event, row)">
</svg-icon>
<svg-icon [clickable]="true"
[mode]="'primary2'"
[name]="'trash-o'"
- (click)="onDeleteAttribute($event, row)"
- [size]="'medium'">
+ [testId]="'delete_'+row.name"
+ [size]="'medium'"
+ (click)="onDeleteAttribute($event, row)">
</svg-icon>
</div>
</ng-template>
diff --git a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.component.ts b/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.component.ts
index ca8d5460e8..d85755bce8 100644
--- a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.component.ts
+++ b/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.component.ts
@@ -1,188 +1,186 @@
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { Select } from '@ngxs/store';
-import { IAttributeModel } from 'app/models';
+import {Component, OnInit, ViewChild} from '@angular/core';
+import {Select} from '@ngxs/store';
+import {IAttributeModel} from 'app/models';
import * as _ from 'lodash';
-import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
-import { ModalComponent } from 'onap-ui-angular/dist/modals/modal.component';
-import { AttributeModel } from '../../../../models';
-import { Resource } from '../../../../models';
-import { ModalsHandler } from '../../../../utils';
-import { TopologyTemplateService } from '../../../../ng2/services/component-services/topology-template.service';
-import { TranslateService } from '../../../../ng2/shared/translator/translate.service';
-import { WorkspaceState } from '../../../../ng2/store/states/workspace.state';
-import { WorkspaceService } from '../../../../ng2/pages/workspace/workspace.service';
-import { AttributeModalComponent } from '../../../../ng2/pages/workspace/attributes/attribute-modal.component';
+import {SdcUiCommon, SdcUiComponents, SdcUiServices} from 'onap-ui-angular';
+import {ModalComponent} from 'onap-ui-angular/dist/modals/modal.component';
+import {AttributeModel, Resource} from '../../../../models';
+import {ModalsHandler} from '../../../../utils';
+import {TopologyTemplateService} from '../../../../ng2/services/component-services/topology-template.service';
+import {TranslateService} from '../../../../ng2/shared/translator/translate.service';
+import {WorkspaceState} from '../../../../ng2/store/states/workspace.state';
+import {WorkspaceService} from '../../../../ng2/pages/workspace/workspace.service';
+import {AttributeModalComponent} from '../../../../ng2/pages/workspace/attributes/attribute-modal.component';
@Component({
- selector: 'attributes',
- templateUrl: './attributes.component.html',
- styleUrls: ['./attributes.component.less', '../../../../../assets/styles/table-style.less']
+ selector: 'attributes',
+ templateUrl: './attributes.component.html',
+ styleUrls: ['./attributes.component.less', '../../../../../assets/styles/table-style.less']
})
export class AttributesComponent implements OnInit {
- @Select(WorkspaceState.isViewOnly)
- isViewOnly$: boolean;
-
- @ViewChild('componentAttributesTable')
- private table: any;
-
- private componentType: string;
- private componentUid: string;
-
- private attributes: IAttributeModel[] = [];
- private temp: IAttributeModel[] = [];
- private customModalInstance: ModalComponent;
-
- constructor(private workspaceService: WorkspaceService,
- private topologyTemplateService: TopologyTemplateService,
- private modalsHandler: ModalsHandler,
- private modalService: SdcUiServices.ModalService,
- private loaderService: SdcUiServices.LoaderService,
- private translateService: TranslateService) {
-
- this.componentType = this.workspaceService.metadata.componentType;
- this.componentUid = this.workspaceService.metadata.uniqueId;
- }
-
- ngOnInit(): void {
- this.asyncInitComponent();
- }
-
- async asyncInitComponent() {
- this.loaderService.activate();
- const response = await this.topologyTemplateService.getComponentAttributes(this.componentType, this.componentUid);
- this.attributes = response.attributes;
- this.temp = [...response.attributes];
- this.loaderService.deactivate();
- }
+ @Select(WorkspaceState.isViewOnly)
+ isViewOnly$: boolean;
+
+ @ViewChild('componentAttributesTable')
+ private table: any;
+
+ private componentType: string;
+ private componentUid: string;
+
+ private attributes: IAttributeModel[] = [];
+ private temp: IAttributeModel[] = [];
+ private customModalInstance: ModalComponent;
+
+ constructor(private workspaceService: WorkspaceService,
+ private topologyTemplateService: TopologyTemplateService,
+ private modalsHandler: ModalsHandler,
+ private modalService: SdcUiServices.ModalService,
+ private loaderService: SdcUiServices.LoaderService,
+ private translateService: TranslateService) {
+
+ this.componentType = this.workspaceService.metadata.componentType;
+ this.componentUid = this.workspaceService.metadata.uniqueId;
+ }
+
+ ngOnInit(): void {
+ this.asyncInitComponent();
+ }
+
+ async asyncInitComponent() {
+ this.loaderService.activate();
+ const response = await this.topologyTemplateService.getComponentAttributes(this.componentType, this.componentUid);
+ this.attributes = response.attributes;
+ this.temp = [...response.attributes];
+ this.loaderService.deactivate();
+ }
+
+ getAttributes(): IAttributeModel[] {
+ return this.attributes;
+ }
+
+ addOrUpdateAttribute = async (attribute: AttributeModel, isEdit: boolean) => {
+ this.loaderService.activate();
+ let attributeFromServer: AttributeModel;
+ this.temp = [...this.attributes];
+
+ const deactivateLoader = () => {
+ this.loaderService.deactivate();
+ return undefined;
+ };
- getAttributes(): IAttributeModel[] {
- return this.attributes;
+ if (isEdit) {
+ attributeFromServer = await this.topologyTemplateService
+ .updateAttributeAsync(this.componentType, this.componentUid, attribute)
+ .catch(deactivateLoader);
+ if (attributeFromServer) {
+ const indexOfUpdatedAttribute = _.findIndex(this.temp, (e) => e.uniqueId === attributeFromServer.uniqueId);
+ this.temp[indexOfUpdatedAttribute] = attributeFromServer;
+ }
+ } else {
+ attributeFromServer = await this.topologyTemplateService
+ .addAttributeAsync(this.componentType, this.componentUid, attribute)
+ .catch(deactivateLoader);
+ if (attributeFromServer) {
+ this.temp.push(attributeFromServer);
+ }
}
-
- addOrUpdateAttribute = async (attribute: AttributeModel, isEdit: boolean) => {
- this.loaderService.activate();
- let attributeFromServer: AttributeModel;
- this.temp = [...this.attributes];
-
- const deactivateLoader = () => {
- this.loaderService.deactivate();
- return undefined;
- };
-
- if (isEdit) {
- attributeFromServer = await this.topologyTemplateService
- .updateAttributeAsync(this.componentType, this.componentUid, attribute)
- .catch(deactivateLoader);
- if (attributeFromServer) {
- const indexOfUpdatedAttribute = _.findIndex(this.temp, (e) => e.uniqueId === attributeFromServer.uniqueId);
- this.temp[indexOfUpdatedAttribute] = attributeFromServer;
- }
- } else {
- attributeFromServer = await this.topologyTemplateService
- .addAttributeAsync(this.componentType, this.componentUid, attribute)
- .catch(deactivateLoader);
- if (attributeFromServer) {
- this.temp.push(attributeFromServer);
- }
+ this.attributes = this.temp;
+ this.loaderService.deactivate();
+ }
+
+ deleteAttribute = async (attributeToDelete: AttributeModel) => {
+ this.loaderService.activate();
+ this.temp = [...this.attributes];
+ const res = await this.topologyTemplateService.deleteAttributeAsync(this.componentType, this.componentUid, attributeToDelete);
+ _.remove(this.temp, (attr) => attr.uniqueId === attributeToDelete.uniqueId);
+ this.attributes = this.temp;
+ this.loaderService.deactivate();
+ };
+
+ openAddEditModal(selectedRow: AttributeModel, isEdit: boolean) {
+ const component = new Resource(undefined, undefined, undefined);
+ component.componentType = this.componentType;
+ component.uniqueId = this.componentUid;
+
+ const title: string = this.translateService.translate('ATTRIBUTE_DETAILS_MODAL_TITLE');
+ const attributeModalConfig = {
+ title,
+ size: 'md',
+ type: SdcUiCommon.ModalType.custom,
+ buttons: [
+ {
+ id: 'save',
+ text: 'Save',
+ // spinner_position: Placement.left,
+ size: 'sm',
+ callback: () => this.modalCallBack(isEdit),
+ closeModal: true,
+ disabled: false,
}
- this.attributes = this.temp;
- this.loaderService.deactivate();
- }
-
- deleteAttribute = async (attributeToDelete: AttributeModel) => {
- this.loaderService.activate();
- this.temp = [...this.attributes];
- const res = await this.topologyTemplateService.deleteAttributeAsync(this.componentType, this.componentUid, attributeToDelete);
- _.remove(this.temp, (attr) => attr.uniqueId === attributeToDelete.uniqueId);
- this.attributes = this.temp;
- this.loaderService.deactivate();
+ ] as SdcUiCommon.IModalButtonComponent[]
};
- openAddEditModal(selectedRow: AttributeModel, isEdit: boolean) {
- const component = new Resource(undefined, undefined, undefined);
- component.componentType = this.componentType;
- component.uniqueId = this.componentUid;
-
- const title: string = this.translateService.translate('ATTRIBUTE_DETAILS_MODAL_TITLE');
- const attributeModalConfig = {
- title,
- size: 'md',
- type: SdcUiCommon.ModalType.custom,
- buttons: [
- {
- id: 'save',
- text: 'Save',
- // spinner_position: Placement.left,
- size: 'sm',
- callback: () => this.modalCallBack(isEdit),
- closeModal: true,
- disabled: false,
- }
- ] as SdcUiCommon.IModalButtonComponent[]
- };
-
- this.customModalInstance = this.modalService.openCustomModal(attributeModalConfig, AttributeModalComponent, { attributeToEdit: selectedRow });
- this.customModalInstance.innerModalContent.instance.
- onValidationChange.subscribe((isValid) => this.customModalInstance.getButtonById('save').disabled = !isValid);
- }
-
- /***********************
- * Call Backs from UI *
- ***********************/
-
- /**
- * Called when 'Add' is clicked
- */
- onAddAttribute() {
- this.openAddEditModal(new AttributeModel(), false);
- }
-
- /**
- * Called when 'Edit' button is clicked
- */
- onEditAttribute(event, row) {
- event.stopPropagation();
-
- const attributeToEdit: AttributeModel = new AttributeModel(row);
- this.openAddEditModal(attributeToEdit, true);
- }
-
- /**
- * Called when 'Delete' button is clicked
- */
- onDeleteAttribute(event, row: AttributeModel) {
- event.stopPropagation();
- const onOk = () => {
- this.deleteAttribute(row);
- };
-
- const title: string = this.translateService.translate('ATTRIBUTE_VIEW_DELETE_MODAL_TITLE');
- const message: string = this.translateService.translate('ATTRIBUTE_VIEW_DELETE_MODAL_TEXT');
- const okButton = new SdcUiComponents.ModalButtonComponent();
- okButton.testId = 'OK';
- okButton.text = 'OK';
- okButton.type = SdcUiCommon.ButtonType.info;
- okButton.closeModal = true;
- okButton.callback = onOk;
-
- this.modalService.openInfoModal(title, message, 'delete-modal', [okButton]);
- }
-
- onExpandRow(event) {
- if (event.type === 'click') {
- this.table.rowDetail.toggleExpandRow(event.row);
- }
- }
+ this.customModalInstance = this.modalService.openCustomModal(attributeModalConfig, AttributeModalComponent, {attributeToEdit: selectedRow});
+ this.customModalInstance.innerModalContent.instance.onValidationChange.subscribe((isValid) => this.customModalInstance.getButtonById('save').disabled = !isValid);
+ }
+
+ /***********************
+ * Call Backs from UI *
+ ***********************/
+
+ /**
+ * Called when 'Add' is clicked
+ */
+ onAddAttribute() {
+ this.openAddEditModal(new AttributeModel(), false);
+ }
+
+ /**
+ * Called when 'Edit' button is clicked
+ */
+ onEditAttribute(event, row) {
+ event.stopPropagation();
+
+ const attributeToEdit: AttributeModel = new AttributeModel(row);
+ this.openAddEditModal(attributeToEdit, true);
+ }
+
+ /**
+ * Called when 'Delete' button is clicked
+ */
+ onDeleteAttribute(event, row: AttributeModel) {
+ event.stopPropagation();
+ const onOk = () => {
+ this.deleteAttribute(row);
+ };
- /**
- * Callback from Modal after "Save" is clicked
- *
- * @param {boolean} isEdit - Whether modal is edit or add attribute
- */
- modalCallBack = (isEdit: boolean) => {
- const attribute: AttributeModel = this.customModalInstance.innerModalContent.instance.attributeToEdit;
- this.addOrUpdateAttribute(attribute, isEdit);
+ const title: string = this.translateService.translate('ATTRIBUTE_VIEW_DELETE_MODAL_TITLE');
+ const message: string = this.translateService.translate('ATTRIBUTE_VIEW_DELETE_MODAL_TEXT', {name: row.name});
+ const okButton = new SdcUiComponents.ModalButtonComponent();
+ okButton.testId = 'OK';
+ okButton.text = 'OK';
+ okButton.type = SdcUiCommon.ButtonType.info;
+ okButton.closeModal = true;
+ okButton.callback = onOk;
+
+ this.modalService.openInfoModal(title, message, 'delete-modal', [okButton]);
+ }
+
+ onExpandRow(event) {
+ if (event.type === 'click') {
+ this.table.rowDetail.toggleExpandRow(event.row);
}
+ }
+
+ /**
+ * Callback from Modal after "Save" is clicked
+ *
+ * @param {boolean} isEdit - Whether modal is edit or add attribute
+ */
+ modalCallBack = (isEdit: boolean) => {
+ const attribute: AttributeModel = this.customModalInstance.innerModalContent.instance.attributeToEdit;
+ this.addOrUpdateAttribute(attribute, isEdit);
+ }
}
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ImportVfcUiTest.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ImportVfcUiTest.java
index a571c1b9f6..b3538e32d1 100644
--- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ImportVfcUiTest.java
+++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/ImportVfcUiTest.java
@@ -19,11 +19,11 @@
package org.onap.sdc.frontend.ci.tests.execute.sanity;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.anEmptyMap;
import static org.hamcrest.Matchers.empty;
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.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@@ -32,6 +32,7 @@ import com.aventstack.extentreports.Status;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
+import org.apache.commons.collections.MapUtils;
import org.onap.sdc.backend.ci.tests.datatypes.enums.ComponentType;
import org.onap.sdc.backend.ci.tests.datatypes.enums.ResourceCategoryEnum;
import org.onap.sdc.backend.ci.tests.utils.general.ElementFactory;
@@ -46,7 +47,10 @@ 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.AttributeModal;
+import org.onap.sdc.frontend.ci.tests.pages.AttributesPage;
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.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;
@@ -69,6 +73,7 @@ public class ImportVfcUiTest extends SetupCDTest {
private HomePage homePage;
private ResourceCreateData vfcCreateData;
private ResourceCreateData vfCreateData;
+ private ComponentInstance createdComponentInstance;
@BeforeClass
public void beforeClass() {
@@ -97,13 +102,15 @@ public class ImportVfcUiTest extends SetupCDTest {
// TC - Import hierarchy of VFCs
fileName = "org.openecomp.resource.VFC-child.yml";
createVfcFlow = createVFC(fileName);
- componentPage = createVfcFlow.getLandedPage()
- .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return ResourceCreatePage"));
+ componentPage = createVfcFlow.getLandedPage().orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return ResourceCreatePage"));
+ componentPage.isLoaded();
+
+ componentPage = manageAttributes(componentPage);
componentPage.isLoaded();
componentPage.certifyComponent();
componentPage.isLoaded();
- yamlObject = downloadToscaArtifact(createVfcFlow.getLandedPage().get());
+ yamlObject = downloadToscaArtifact(componentPage);
checkMetadata(yamlObject, vfcCreateData);
checkNodeTypes(yamlObject);
homePage.getTopNavComponent().clickOnHome();
@@ -126,6 +133,32 @@ public class ImportVfcUiTest extends SetupCDTest {
}
+ private ComponentPage manageAttributes(final ComponentPage componentPage) {
+ final AttributesPage attributesPage = componentPage.goToAttributes();
+ attributesPage.isLoaded();
+
+ assertTrue(attributesPage.isAttributePresent("test_1"));
+ assertTrue(attributesPage.isAttributePresent("test_2"));
+ assertTrue(attributesPage.isAttributePresent("test_3"));
+ assertTrue(attributesPage.isAttributePresent("test_4"));
+
+ attributesPage.deleteAttribute("test_2");
+ assertFalse(attributesPage.isAttributePresent("test_2"));
+ ExtentTestActions.takeScreenshot(Status.INFO, "attributesPage.deleteAttribute", "Attribute 'test_2' successfully deleted");
+ attributesPage.addAttribute(new AttributeModal.AttributeData("test_9", "Additional attribute added from UI", "string", "one More Attribute"));
+ attributesPage.isLoaded();
+ assertTrue(attributesPage.isAttributePresent("test_9"));
+ ExtentTestActions.takeScreenshot(Status.INFO, "attributesPage.addAttribute", "Additional Attribute 'test_9' successfully added");
+
+ attributesPage.editAttribute(new AttributeModal.AttributeData("test_9", "Additional attribute added from UI".toUpperCase(), "string",
+ "one More Attribute".toUpperCase()));
+ attributesPage.isLoaded();
+ assertTrue(attributesPage.isAttributePresent("test_9"));
+ ExtentTestActions.takeScreenshot(Status.INFO, "attributesPage.editAttribute", "Additional Attribute 'test_9' successfully altered");
+
+ return attributesPage.clickOnGeneralMenuItem(ResourceCreatePage.class);
+ }
+
private CompositionPage addInterfaceOperations(final ComponentPage componentPage) {
final AddNodeToCompositionFlow addNodeToCompositionFlow = addNodeToCompositionFlow(componentPage);
final CompositionPage compositionPage = addNodeToCompositionFlow.getLandedPage()
@@ -133,7 +166,7 @@ public class ImportVfcUiTest extends SetupCDTest {
final CompositionDetailSideBarComponent detailSideBar = compositionPage.getDetailSideBar();
detailSideBar.isLoaded();
- final ComponentInstance createdComponentInstance = addNodeToCompositionFlow.getCreatedComponentInstance()
+ createdComponentInstance = addNodeToCompositionFlow.getCreatedComponentInstance()
.orElseThrow(() -> new UiTestFlowRuntimeException("Expecting a ComponentInstance"));
compositionPage.selectNode(createdComponentInstance.getName());
@@ -288,32 +321,38 @@ public class ImportVfcUiTest extends SetupCDTest {
final Map<String, Object> mapEntry = getMapEntry(map, "node_types");
final Map<String, Object> nodeTypes = getMapEntry(mapEntry, mapEntry.keySet().iterator().next());
- assertNotNull(nodeTypes);
+ assertFalse(MapUtils.isEmpty(nodeTypes));
assertEquals("aDescription", nodeTypes.get("description"));
final Map<String, Object> properties = getMapEntry(nodeTypes, "properties");
- assertThat(properties, not(anEmptyMap()));
+ assertFalse(MapUtils.isEmpty(properties));
final Map<String, Object> attributes = getMapEntry(nodeTypes, "attributes");
- assertThat(attributes, not(anEmptyMap()));
+ assertFalse(MapUtils.isEmpty(attributes));
final Map<String, Object> interfaces = getMapEntry(nodeTypes, "interfaces");
- assertThat(interfaces, not(anEmptyMap()));
+ assertFalse(MapUtils.isEmpty(interfaces));
}
private void checkTopologyTemplate(final Map<String, Object> map) {
- final Map<String, Object> mapEntry = getMapEntry(map, "topology_template");
- assertNotNull(mapEntry);
+ final Map<String, Object> topologyTemplate = getMapEntry(map, "topology_template");
+ assertNotNull(topologyTemplate);
+
+ final Map<String, Object> inputs = getMapEntry(topologyTemplate, "inputs");
+ assertFalse(MapUtils.isEmpty(inputs));
- final Map<String, Object> properties = getMapEntry(mapEntry, "inputs");
- assertThat(properties, not(anEmptyMap()));
+ final Map<String, Object> nodeTemplates = getMapEntry(topologyTemplate, "node_templates");
+ assertFalse(MapUtils.isEmpty(nodeTemplates));
- final Map<String, Object> attributes = getMapEntry(mapEntry, "node_templates");
- assertThat(attributes, not(anEmptyMap()));
+ final Map<String, Object> attributes = getMapEntry((Map<String, Object>) nodeTemplates.get(createdComponentInstance.getName()), "attributes");
+ assertFalse(MapUtils.isEmpty(attributes));
+ assertEquals(4, attributes.keySet().stream()
+ .filter(s -> (s.contains("test_1") || s.contains("test_3") || s.contains("test_4") || s.contains("test_9")) && !s.contains("test_2"))
+ .count());
- final Map<String, Object> interfaces = getMapEntry(mapEntry, "substitution_mappings");
- assertThat(interfaces, not(anEmptyMap()));
+ final Map<String, Object> substitutionMappings = getMapEntry(topologyTemplate, "substitution_mappings");
+ assertFalse(MapUtils.isEmpty(substitutionMappings));
}
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AttributeModal.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AttributeModal.java
new file mode 100644
index 0000000000..bd1330d8cf
--- /dev/null
+++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AttributeModal.java
@@ -0,0 +1,118 @@
+/*
+ * ============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;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+/**
+ * Handles the 'Attributes' Edit Modal UI actions
+ */
+public class AttributeModal extends AbstractPageObject {
+
+ private WebElement wrappingElement;
+
+ public AttributeModal(final WebDriver webDriver) {
+ super(webDriver);
+ }
+
+ @Override
+ public void isLoaded() {
+ waitForElementVisibility(By.xpath(XpathSelector.TITLE_DIV.getXPath()));
+ waitForElementVisibility(By.xpath(XpathSelector.SAVE_BTN.getXPath()));
+ wrappingElement = findElement(By.xpath(XpathSelector.ATTR_CONTAINER_DIV.getXPath()));
+ }
+
+ public void fillForm(final AttributeData attributeData, final boolean isUpdate) {
+ if (!isUpdate) {
+ editName(attributeData.getAttributeName());
+ }
+ editDescription(attributeData.getDescription());
+ editType(attributeData.getAttributeType());
+ editDefaultValue(attributeData.getDefaultValue());
+ }
+
+ private void editName(final String attributeName) {
+ final WebElement webElement = waitForElementVisibility(By.xpath(XpathSelector.ATTRIBUTE_NAME_INPUT.getXPath()));
+ webElement.clear();
+ webElement.sendKeys(attributeName);
+ }
+
+ private void editDescription(final String description) {
+ final WebElement webElement = waitForElementVisibility(By.xpath(XpathSelector.DESCRIPTION_INPUT.getXPath()));
+ webElement.clear();
+ webElement.sendKeys(description);
+ }
+
+ private void editType(final String attributeType) {
+ waitToBeClickable(By.xpath(XpathSelector.ATTRIBUT_TYPE_ICON.getXPath())).click();
+ final WebElement element = waitForElementVisibility(By.xpath(XpathSelector.DROPDOWN_RESULTS.getXPath()));
+ element.findElement(By.xpath(XpathSelector.ATTRIBUTE_TYPE_LI.getXPath(attributeType))).click();
+ }
+
+ private void editDefaultValue(final String defaultValue) {
+ final WebElement webElement = waitForElementVisibility(By.xpath(XpathSelector.DEFAULT_VALUE_INPUT.getXPath()));
+ webElement.clear();
+ webElement.sendKeys(defaultValue);
+ }
+
+ public void clickSave() {
+ waitToBeClickable(By.xpath(XpathSelector.SAVE_BTN.getXPath())).click();
+ }
+
+ @Getter
+ @AllArgsConstructor
+ public static class AttributeData {
+
+ private final String attributeName;
+ private final String description;
+ private final String attributeType;
+ private final String defaultValue;
+ }
+
+ /**
+ * Enum that contains identifiers and xpath expressions to elements related to the enclosing page object.
+ */
+ @AllArgsConstructor
+ private enum XpathSelector {
+ TITLE_DIV("//div[contains(@class,'title') and contains(text(), ' Attribute Details')]"),
+ ATTR_CONTAINER_DIV("//div[@class='attr-container']"),
+ ATTRIBUTE_NAME_INPUT("//input[@data-tests-id='attributeName']"),
+ DESCRIPTION_INPUT("//textarea[@data-tests-id='description']"),
+ ATTRIBUTE_TYPE_LI("//li[@data-tests-id='%s']"),
+ ATTRIBUT_TYPE_ICON("//div[@data-tests-id='attributeType-icon']"),
+ DROPDOWN_RESULTS("//ul[contains(@class,'dropdown-results')]"),
+ ATTRIBUTE_TYPE_DIV("//div[@data-tests-id='attributeType']"),
+ DEFAULT_VALUE_INPUT("//input[@data-tests-id='defaultValue']"),
+ SAVE_BTN("//button[@data-tests-id='button-save']");
+
+ @Getter
+ private final String xPath;
+
+ public String getXPath(final String... xpathParams) {
+ return String.format(xPath, xpathParams);
+ }
+
+ }
+
+}
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AttributesPage.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AttributesPage.java
new file mode 100644
index 0000000000..47b29b9f23
--- /dev/null
+++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AttributesPage.java
@@ -0,0 +1,126 @@
+/*
+ * ============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;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.onap.sdc.frontend.ci.tests.pages.AttributeModal.AttributeData;
+import org.onap.sdc.frontend.ci.tests.utilities.LoaderHelper;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+/**
+ * Handles the 'Attributes' Page UI actions
+ */
+public class AttributesPage extends ComponentPage {
+
+ private WebElement wrappingElement;
+
+ public AttributesPage(final WebDriver webDriver) {
+ super(webDriver);
+ }
+
+ @Override
+ public void isLoaded() {
+ super.isLoaded();
+ waitForElementVisibility(By.xpath(XpathSelector.MAIN_DIV.getXpath()));
+ waitForElementVisibility(By.xpath(XpathSelector.TITLE_DIV.getXpath()));
+ waitForElementVisibility(By.xpath(XpathSelector.ATTRIBUTES_DIV.getXpath()));
+ wrappingElement = findElement(By.xpath(XpathSelector.ATTRIBUTES_DIV.getXpath()));
+ }
+
+ public boolean isAttributePresent(final String attributeName) {
+ try {
+ final WebElement element = wrappingElement.findElement(By.xpath(XpathSelector.ATTRIBUTES_NAME_SPAN.getXpath(attributeName)));
+ return element != null;
+ } catch (final Exception e) {
+ return false;
+ }
+ }
+
+ public void addAttribute(final AttributeData attributeData) {
+ final AttributeModal attributeModal = clickOnAdd();
+ attributeModal.isLoaded();
+ attributeModal.fillForm(attributeData, false);
+ attributeModal.clickSave();
+ loaderHelper.waitForLoader(LoaderHelper.XpathSelector.SDC_LOADER_LARGE, 5);
+ }
+
+ public AttributeModal clickOnAdd() {
+ waitToBeClickable(By.xpath(XpathSelector.ADD_BTN.getXpath())).click();
+ return new AttributeModal(webDriver);
+ }
+
+ public AttributeModal clickOnEdit(final String attributeName) {
+ waitToBeClickable(By.xpath(XpathSelector.EDIT_BTN.getXpath(attributeName))).click();
+ return new AttributeModal(webDriver);
+ }
+
+ public void deleteAttribute(final String attributeName) {
+ if (attributeName == null) {
+ return;
+ }
+ waitForElementVisibility(By.xpath(XpathSelector.DELETE_BTN.getXpath(attributeName))).click();
+ waitToBeClickable(By.xpath(XpathSelector.DELETE_ATTRIBUTE_CONFIRM_BTN.getXpath())).click();
+ waitForElementInvisibility(By.xpath(XpathSelector.DELETE_BTN.getXpath(attributeName)), 5);
+ }
+
+ public void editAttribute(final AttributeData attributeData) {
+ final AttributeModal attributeModal = clickOnEdit(attributeData.getAttributeName());
+ attributeModal.isLoaded();
+ attributeModal.fillForm(attributeData, true);
+ attributeModal.clickSave();
+ loaderHelper.waitForLoader(LoaderHelper.XpathSelector.SDC_LOADER_LARGE, 5);
+ }
+
+ /**
+ * Enum that contains identifiers and xpath expressions to elements related to the enclosing page object.
+ */
+ @AllArgsConstructor
+ private enum XpathSelector {
+ MAIN_DIV("w-sdc-main-right-container", "//div[@class='%s']"),
+ TITLE_DIV("workspace-tab-title", "//div[contains(@class,'%s') and contains(text(), 'Attributes')]"),
+ ATTRIBUTES_DIV("workspace-attributes", "//div[@class='%s']"),
+ ADD_BTN("svg-icon-label", "//span[contains(@class,'%s') and contains(text(), 'Add')]"),
+ ATTRIBUTES_NAME_SPAN("//div[@data-tests-id='attrib-name_%s']"),
+ EDIT_BTN("//div[contains(@class,'svg-icon') and @data-tests-id='edit_%s']"),
+ DELETE_BTN("//div[contains(@class,'svg-icon') and @data-tests-id='delete_%s']"),
+ DELETE_ATTRIBUTE_CONFIRM_BTN("delete-modal-button-ok", "//button[@data-tests-id='%s']");
+
+ @Getter
+ private String id;
+ private final String xpathFormat;
+
+ XpathSelector(final String xpathFormat) {
+ this.xpathFormat = xpathFormat;
+ }
+
+ public String getXpath(final String... xpathParams) {
+ return String.format(xpathFormat, xpathParams);
+ }
+
+ public String getXpath() {
+ return String.format(xpathFormat, id);
+ }
+
+ }
+
+}
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ComponentPage.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ComponentPage.java
index 68087f6261..8bbbf5a655 100644
--- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ComponentPage.java
+++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ComponentPage.java
@@ -91,6 +91,14 @@ public class ComponentPage extends AbstractPageObject {
return resourceLeftSideMenu.clickOnAttributesOutputsMenuItem();
}
+ public AttributesPage goToAttributes() {
+ return resourceLeftSideMenu.clickOnAttributesMenuItem();
+ }
+
+ public <T extends ComponentPage> T clickOnGeneralMenuItem(Class<? extends T> clazz) {
+ return resourceLeftSideMenu.clickOnGeneralMenuItem(clazz);
+ }
+
public ResourcePropertiesAssignmentPage goToPropertiesAssignment() {
return resourceLeftSideMenu.clickOnPropertiesAssignmentMenuItem();
}
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourceLeftSideMenu.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourceLeftSideMenu.java
index 9b860d5ab0..413d4b4a6b 100644
--- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourceLeftSideMenu.java
+++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourceLeftSideMenu.java
@@ -75,6 +75,16 @@ public class ResourceLeftSideMenu extends AbstractPageObject {
}
/**
+ * Clicks on the 'Attributes' menu item.
+ *
+ * @return the next page object
+ */
+ public AttributesPage clickOnAttributesMenuItem() {
+ wrappingElement.findElement(By.xpath(XpathSelector.ATTRIBUTES_MENU.getXpath())).click();
+ return new AttributesPage(webDriver);
+ }
+
+ /**
* Clicks on the TOSCA artifacts menu item.
*
* @return the next page object
@@ -85,13 +95,13 @@ public class ResourceLeftSideMenu extends AbstractPageObject {
}
/**
- * Clicks on the TOSCA artifacts menu item.
+ * Clicks on the 'General' menu item.
*
* @return the next page object
*/
- public ServiceCreatePage clickOnGeneralMenuItem() {
+ public <T extends ComponentPage> T clickOnGeneralMenuItem(Class<? extends T> clazz) {
wrappingElement.findElement(By.xpath(XpathSelector.GENERAL_MENU.getXpath())).click();
- return new ServiceCreatePage(webDriver);
+ return (T) new ComponentPage(webDriver);
}
public CompositionPage clickOnCompositionMenuItem() {
@@ -106,9 +116,12 @@ public class ResourceLeftSideMenu extends AbstractPageObject {
private enum XpathSelector {
MAIN_DIV("w-sdc-left-sidebar", "//div[@class='%s']"),
PROPERTIES_ASSIGNMENT_MENU("Properties AssignmentLeftSideMenu", "//*[@data-tests-id='%s']"),
+ PROPERTIES_MENU("PropertiesLeftSideMenu", "//*[@data-tests-id='%s']"),
ATTRIBUTES_OUTPUTS_MENU("Attributes & OutputsLeftSideMenu", "//*[@data-tests-id='%s']"),
+ ATTRIBUTES_MENU("AttributesLeftSideMenu", "//*[@data-tests-id='%s']"),
GENERAL_MENU("GeneralLeftSideMenu", "//*[@data-tests-id='%s']"),
COMPOSITION_MENU("CompositionLeftSideMenu", "//*[@data-tests-id='%s']"),
+ REQUIREMENT_CAPABILITY_MENU("Req. & CapabilitiesLeftSideMenu", "//*[@data-tests-id='%s']"),
TOSCA_ARTIFACTS_MENU("TOSCA ArtifactsLeftSideMenu", "//*[@data-tests-id='%s']");
@Getter
diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/utilities/LoaderHelper.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/utilities/LoaderHelper.java
index 6406c2a460..4c0356ff46 100644
--- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/utilities/LoaderHelper.java
+++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/utilities/LoaderHelper.java
@@ -79,7 +79,8 @@ public class LoaderHelper extends AbstractPageObject {
@AllArgsConstructor
@Getter
public enum XpathSelector {
- LOADER_WITH_LOADER_BACKGROUND("//*[contains(@class, 'sdc-loader-background')]");
+ LOADER_WITH_LOADER_BACKGROUND("//*[contains(@class, 'sdc-loader-background')]"),
+ SDC_LOADER_LARGE("//div[@data-tests-id='loader']");
private final String xpath;
}