diff options
author | andre.schmid <andre.schmid@est.tech> | 2021-03-09 18:29:48 +0000 |
---|---|---|
committer | Christophe Closset <christophe.closset@intl.att.com> | 2021-03-22 16:37:22 +0000 |
commit | 1ccd74fb7723bc41424ca93902d68d351ce55462 (patch) | |
tree | 3b7ba6539b51e814e605f87b5f76c757f69086dd | |
parent | 00acf3d39898cc712e8f3fd2afb69f26bc922f61 (diff) |
Add Composition Page and create resource page/flow
Add UI Tests Composition Page, and create resource page and flow
Change-Id: I004a2e8123df669e7318eca7feb58f8b1210dd65
Issue-ID: SDC-3523, SDC-3524
Signed-off-by: andre.schmid <andre.schmid@est.tech>
31 files changed, 1610 insertions, 142 deletions
diff --git a/catalog-ui/src/app/ng2/components/logic/substitution-filter/substitution-filter.component.html b/catalog-ui/src/app/ng2/components/logic/substitution-filter/substitution-filter.component.html index 01329b70d1..81fc5b48ee 100644 --- a/catalog-ui/src/app/ng2/components/logic/substitution-filter/substitution-filter.component.html +++ b/catalog-ui/src/app/ng2/components/logic/substitution-filter/substitution-filter.component.html @@ -45,7 +45,7 @@ <div class="w-sdc-designer-sidebar-section-substitution-filter-footer"> <button class="w-sdc-designer-sidebar-section-substitution-filter-footer-action add-rule-btn tlv-btn blue" - data-tests-id="add-rule-button" + data-tests-id="add-substitution-filter-button" (click)="onAddSubstitutionFilter(PROPERTIES)" [disabled]="readonly"> {{'ADD_SUBSTITUTION_FILTER' | translate}} diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.html index 5511dc0ea8..61e2f5e744 100644 --- a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.html +++ b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.html @@ -12,7 +12,8 @@ <sdc-tab *ngFor="let tab of tabs" [titleIcon]="tab.titleIcon" [active]="tab.isActive" - [tooltipText]="tab.tooltipText"> + [tooltipText]="tab.tooltipText" + [testId]="tab.testId"> <panel-tab [isActive]="tab.isActive" [component]="selectedComponent" diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.spec.ts index 6d96764b1c..d5c0b6093b 100644 --- a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.spec.ts +++ b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.spec.ts @@ -27,49 +27,113 @@ describe('composition-panel component', () => { let store: Store; const tabs = { - infoTab : {titleIcon: 'info-circle', component: InfoTabComponent, input: {}, isActive: true, tooltipText: 'Information'}, - policyProperties: { - titleIcon: 'settings-o', component: GroupOrPolicyPropertiesTab, input: {type: 'policy'}, isActive: false, tooltipText: 'Properties' - }, - policyTargets: {titleIcon: 'inputs-o', component: PolicyTargetsTabComponent, input: {}, isActive: false, tooltipText: 'Targets'}, - groupMembers: {titleIcon: 'inputs-o', component: GroupMembersTabComponent, input: {}, isActive: false, tooltipText: 'Members'}, - groupProperties: { - titleIcon: 'settings-o', component: GroupOrPolicyPropertiesTab, input: {type: 'group'}, isActive: false, tooltipText: 'Properties' - }, - deploymentArtifacts: { - titleIcon: 'deployment-artifacts-o', component: ArtifactsTabComponent, - input: { type: ArtifactGroupType.DEPLOYMENT}, isActive: false, tooltipText: 'Deployment Artifacts' - }, - apiArtifacts: { - titleIcon: 'api-o', component: ArtifactsTabComponent, - input: { type: ArtifactGroupType.SERVICE_API}, isActive: false, tooltipText: 'API Artifacts' - }, - infoArtifacts: { - titleIcon: 'info-square-o', component: ArtifactsTabComponent, - input: { type: ArtifactGroupType.INFORMATION}, isActive: false, tooltipText: 'Information Artifacts' - }, - properties: { - titleIcon: 'settings-o', component: PropertiesTabComponent, - input: {title: 'Properties and Attributes'}, isActive: false, tooltipText: 'Properties' - }, - reqAndCapabilities : { - titleIcon: 'req-capabilities-o', component: ReqAndCapabilitiesTabComponent, input: {}, - isActive: false, tooltipText: 'Requirements and Capabilities' - }, - substitutionFilter: { - titleIcon: 'composition-o', component: SubstitutionFilterTabComponent, input: {title: 'SUBSTITUTION FILTER'}, - isActive: false, tooltipText: 'Substitution Filter' - }, - inputs: {titleIcon: 'inputs-o', component: PropertiesTabComponent, input: {title: 'Inputs'}, isActive: false, tooltipText: 'Inputs'}, - settings: {titleIcon: 'settings-o', component: PropertiesTabComponent, input: {}, isActive: false, tooltipText: 'Settings'}, - interfaceOperations: { - titleIcon: 'composition-o', - component: InterfaceOperationsComponent, - input: {title: 'Interface Operations'}, - isActive: false, - tooltipText: 'Interface Operations' - } - }; + infoTab: { + titleIcon: 'info-circle', + component: InfoTabComponent, + input: {}, + isActive: true, + tooltipText: 'Information', + testId: 'detail-tab-information' + }, + policyProperties: { + titleIcon: 'settings-o', + component: GroupOrPolicyPropertiesTab, + input: {type: 'policy'}, + isActive: false, + tooltipText: 'Properties', + testId: 'detail-tab-policy-properties' + }, + policyTargets: { + titleIcon: 'inputs-o', + component: PolicyTargetsTabComponent, + input: {}, + isActive: false, + tooltipText: 'Targets', + testId: 'detail-tab-policy-targets' + }, + groupMembers: { + titleIcon: 'inputs-o', + component: GroupMembersTabComponent, + input: {}, + isActive: false, + tooltipText: 'Members', + testId: 'detail-tab-group-members' + }, + groupProperties: { + titleIcon: 'settings-o', + component: GroupOrPolicyPropertiesTab, + input: {type: 'group'}, + isActive: false, + tooltipText: 'Properties', + testId: 'detail-tab-group-properties' + }, + deploymentArtifacts: { + titleIcon: 'deployment-artifacts-o', + component: ArtifactsTabComponent, + input: {type: ArtifactGroupType.DEPLOYMENT}, + isActive: false, + tooltipText: 'Deployment Artifacts', + testId: 'detail-tab-deployment-artifacts' + }, + apiArtifacts: { + titleIcon: 'api-o', + component: ArtifactsTabComponent, + input: {type: ArtifactGroupType.SERVICE_API}, + isActive: false, + tooltipText: 'API Artifacts', + testId: 'detail-tab-api-artifacts' + }, + infoArtifacts: { + titleIcon: 'info-square-o', + component: ArtifactsTabComponent, + input: {type: ArtifactGroupType.INFORMATION}, + isActive: false, + tooltipText: 'Information Artifacts', + testId: 'detail-tab-information-artifacts' + }, + properties: { + titleIcon: 'settings-o', component: PropertiesTabComponent, + input: {title: 'Properties and Attributes'}, isActive: false, tooltipText: 'Properties', + testId: 'detail-tab-properties-attributes' + }, + reqAndCapabilities: { + titleIcon: 'req-capabilities-o', component: ReqAndCapabilitiesTabComponent, input: {}, + isActive: false, tooltipText: 'Requirements and Capabilities', + testId: 'detail-tab-requirements-capabilities' + }, + substitutionFilter: { + titleIcon: 'composition-o', + component: SubstitutionFilterTabComponent, + input: {title: 'SUBSTITUTION FILTER'}, + isActive: false, + tooltipText: 'Substitution Filter', + testId: 'detail-tab-substitution-filter' + }, + inputs: { + titleIcon: 'inputs-o', + component: PropertiesTabComponent, + input: {title: 'Inputs'}, + isActive: false, + tooltipText: 'Inputs', + testId: 'detail-tab-inputs' + }, + settings: { + titleIcon: 'settings-o', + component: PropertiesTabComponent, + input: {}, + isActive: false, + tooltipText: 'Settings', + testId: 'detail-tab-settings' + }, + interfaceOperations: { + titleIcon: 'composition-o', + component: InterfaceOperationsComponent, + input: {title: 'Interface Operations'}, + isActive: false, + tooltipText: 'Interface Operations', + testId: 'detail-tab-interface-operations' + } + }; beforeEach( async(() => { @@ -95,7 +159,6 @@ describe('composition-panel component', () => { const testInstance = new PolicyInstance(); fixture.componentInstance.initTabs(testInstance); - expect (fixture.componentInstance.tabs.length).toBe(3); expect (fixture.componentInstance.tabs[0]).toEqual(tabs.infoTab); expect (fixture.componentInstance.tabs[1]).toEqual(tabs.policyTargets); diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.ts index 2ef4e7c9a9..6ed73b3384 100644 --- a/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.ts +++ b/catalog-ui/src/app/ng2/pages/composition/panel/composition-panel.component.ts @@ -42,22 +42,134 @@ import {SubstitutionFilterTabComponent} from "./panel-tabs/substitution-filter-t import {InterfaceOperationsComponent} from "../interface-operatons/interface-operations.component"; const tabs = { - infoTab : {titleIcon: 'info-circle', component: InfoTabComponent, input: {}, isActive: true, tooltipText: 'Information'}, - policyProperties: {titleIcon: 'settings-o', component: GroupOrPolicyPropertiesTab, input: {type: 'policy'}, isActive: false, tooltipText: 'Properties'}, - policyTargets: {titleIcon: 'inputs-o', component: PolicyTargetsTabComponent, input: {}, isActive: false, tooltipText: 'Targets'}, - groupMembers: {titleIcon: 'inputs-o', component: GroupMembersTabComponent, input: {}, isActive: false, tooltipText: 'Members'}, - groupProperties: {titleIcon: 'settings-o', component: GroupOrPolicyPropertiesTab, input: {type: 'group'}, isActive: false, tooltipText: 'Properties'}, - deploymentArtifacts: {titleIcon: 'deployment-artifacts-o', component: ArtifactsTabComponent, input: { type: ArtifactGroupType.DEPLOYMENT}, isActive: false, tooltipText: 'Deployment Artifacts'}, - apiArtifacts: {titleIcon: 'api-o', component: ArtifactsTabComponent, input: { type: ArtifactGroupType.SERVICE_API}, isActive: false, tooltipText: 'API Artifacts'}, - infoArtifacts: {titleIcon: 'info-square-o', component: ArtifactsTabComponent, input: { type: ArtifactGroupType.INFORMATION}, isActive: false, tooltipText: 'Information Artifacts'}, - properties: {titleIcon: 'settings-o', component: PropertiesTabComponent, input: {title: 'Properties and Attributes'}, isActive: false, tooltipText: 'Properties'}, - reqAndCapabilities : { titleIcon: 'req-capabilities-o', component: ReqAndCapabilitiesTabComponent, input: {}, isActive: false, tooltipText: 'Requirements and Capabilities'}, - inputs: {titleIcon: 'inputs-o', component: PropertiesTabComponent, input: {title: 'Inputs'}, isActive: false, tooltipText: 'Inputs'}, - settings: {titleIcon: 'settings-o', component: PropertiesTabComponent, input: {}, isActive: false, tooltipText: 'Settings'}, - consumption: {titleIcon: 'api-o', component: ServiceConsumptionTabComponent, input: {title: 'OPERATION CONSUMPTION'}, isActive: false, tooltipText: 'Service Consumption'}, - dependencies: {titleIcon: 'archive', component: ServiceDependenciesTabComponent, input: {title: 'DIRECTIVES AND NODE FILTER'}, isActive: false, tooltipText: 'Service Dependencies'}, - substitutionFilter: {titleIcon: 'composition-o', component: SubstitutionFilterTabComponent, input: {title: 'SUBSTITUTION FILTER'}, isActive: false, tooltipText: 'Substitution Filter'}, - interfaceOperations: {titleIcon: 'composition-o', component: InterfaceOperationsComponent, input: {title: 'Interface Operations'}, isActive: false, tooltipText: 'Interface Operations'} + infoTab: { + titleIcon: 'info-circle', + component: InfoTabComponent, + input: {}, + isActive: true, + tooltipText: 'Information', + testId: 'detail-tab-information' + }, + policyProperties: { + titleIcon: 'settings-o', + component: GroupOrPolicyPropertiesTab, + input: {type: 'policy'}, + isActive: false, + tooltipText: 'Properties', + testId: 'detail-tab-policy-properties' + }, + policyTargets: { + titleIcon: 'inputs-o', + component: PolicyTargetsTabComponent, + input: {}, + isActive: false, + tooltipText: 'Targets', + testId: 'detail-tab-policy-targets' + }, + groupMembers: { + titleIcon: 'inputs-o', + component: GroupMembersTabComponent, + input: {}, + isActive: false, + tooltipText: 'Members', + testId: 'detail-tab-group-members' + }, + groupProperties: { + titleIcon: 'settings-o', + component: GroupOrPolicyPropertiesTab, + input: {type: 'group'}, + isActive: false, + tooltipText: 'Properties', + testId: 'detail-tab-group-properties' + }, + deploymentArtifacts: { + titleIcon: 'deployment-artifacts-o', + component: ArtifactsTabComponent, + input: {type: ArtifactGroupType.DEPLOYMENT}, + isActive: false, + tooltipText: 'Deployment Artifacts', + testId: 'detail-tab-deployment-artifacts' + }, + apiArtifacts: { + titleIcon: 'api-o', + component: ArtifactsTabComponent, + input: {type: ArtifactGroupType.SERVICE_API}, + isActive: false, + tooltipText: 'API Artifacts', + testId: 'detail-tab-api-artifacts' + }, + infoArtifacts: { + titleIcon: 'info-square-o', + component: ArtifactsTabComponent, + input: {type: ArtifactGroupType.INFORMATION}, + isActive: false, + tooltipText: 'Information Artifacts', + testId: 'detail-tab-information-artifacts' + }, + properties: { + titleIcon: 'settings-o', + component: PropertiesTabComponent, + input: {title: 'Properties and Attributes'}, + isActive: false, + tooltipText: 'Properties', + testId: 'detail-tab-properties-attributes' + }, + reqAndCapabilities: { + titleIcon: 'req-capabilities-o', + component: ReqAndCapabilitiesTabComponent, + input: {}, + isActive: false, + tooltipText: 'Requirements and Capabilities', + testId: 'detail-tab-requirements-capabilities' + }, + inputs: { + titleIcon: 'inputs-o', + component: PropertiesTabComponent, + input: {title: 'Inputs'}, + isActive: false, + tooltipText: 'Inputs', + testId: 'detail-tab-inputs' + }, + settings: { + titleIcon: 'settings-o', + component: PropertiesTabComponent, + input: {}, + isActive: false, + tooltipText: 'Settings', + testId: 'detail-tab-settings' + }, + consumption: { + titleIcon: 'api-o', + component: ServiceConsumptionTabComponent, + input: {title: 'OPERATION CONSUMPTION'}, + isActive: false, + tooltipText: 'Service Consumption', + testId: 'detail-tab-operation-consumption' + }, + dependencies: { + titleIcon: 'archive', + component: ServiceDependenciesTabComponent, + input: {title: 'DIRECTIVES AND NODE FILTER'}, + isActive: false, + tooltipText: 'Service Dependencies', + testId: 'detail-tab-directives-node-filter' + }, + substitutionFilter: { + titleIcon: 'composition-o', + component: SubstitutionFilterTabComponent, + input: {title: 'SUBSTITUTION FILTER'}, + isActive: false, + tooltipText: 'Substitution Filter', + testId: 'detail-tab-substitution-filter' + }, + interfaceOperations: { + titleIcon: 'composition-o', + component: InterfaceOperationsComponent, + input: {title: 'Interface Operations'}, + isActive: false, + tooltipText: 'Interface Operations', + testId: 'detail-tab-interface-operations' + } }; @Component({ diff --git a/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/utils/general/AtomicOperationUtils.java b/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/utils/general/AtomicOperationUtils.java index c69d70a66d..9c73275316 100644 --- a/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/utils/general/AtomicOperationUtils.java +++ b/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/utils/general/AtomicOperationUtils.java @@ -472,6 +472,9 @@ public final class AtomicOperationUtils { ComponentInstanceReqDetails componentInstanceDetails = ElementFactory.getComponentInstance(compInstParent); componentInstanceDetails.setPosX(positionX); componentInstanceDetails.setPosY(positionY); + if (componentInstanceDetails.getOriginType() == null){ + componentInstanceDetails.setOriginType(((Resource) compInstParent).getResourceType().toString()); + } RestResponse createComponentInstance = ComponentInstanceRestUtils.createComponentInstance(componentInstanceDetails, defaultUser, compContainer); if (validateState) { diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/CanvasNodeElement.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/CanvasNodeElement.java new file mode 100644 index 0000000000..044044f973 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/CanvasNodeElement.java @@ -0,0 +1,54 @@ +/* + * ============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; + +import java.util.Objects; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionCanvasComponent; + +/** + * Represents a node in the {@link CompositionCanvasComponent} + */ +@Getter +@AllArgsConstructor +public final class CanvasNodeElement { + + private final String name; + private final int positionX; + private final int positionY; + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final CanvasNodeElement that = (CanvasNodeElement) o; + return name.equals(that.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/ResourceCreateData.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/ResourceCreateData.java new file mode 100644 index 0000000000..ea63ead4f4 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/ResourceCreateData.java @@ -0,0 +1,45 @@ +/* + * ============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; + +import java.util.List; +import java.util.UUID; +import lombok.Data; + +/** + * Represents the necessary data to create a resource (VF, VFC or similar) + */ +@Data +public class ResourceCreateData { + + private String name; + private String category; + private List<String> tagList; + private String description; + private String contactId; + private String vendorName; + private String vendorRelease; + private String vendorModelNumber; + + public void setRandomName(final String prefix) { + final String randomPart = UUID.randomUUID().toString().split("-")[0]; + this.name = String.format("%s%s", prefix == null ? "" : prefix, randomPart); + } +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/exception/CompositionCanvasRuntimeException.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/exception/CompositionCanvasRuntimeException.java new file mode 100644 index 0000000000..6f3b839372 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/exception/CompositionCanvasRuntimeException.java @@ -0,0 +1,32 @@ +/* + * ============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.exception; + +public class CompositionCanvasRuntimeException extends RuntimeException { + + public CompositionCanvasRuntimeException(final String s) { + super(s); + } + + public CompositionCanvasRuntimeException(final String s, final Throwable throwable) { + super(s, throwable); + } + +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiNetworkServiceUiTests.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiNetworkServiceUiTests.java index 0854bec785..feb56416cb 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiNetworkServiceUiTests.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiNetworkServiceUiTests.java @@ -27,7 +27,6 @@ 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.Map; import java.util.Map.Entry; @@ -35,7 +34,6 @@ 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.ServiceCategoriesEnum; -import org.onap.sdc.backend.ci.tests.datatypes.enums.UserRoleEnum; import org.onap.sdc.frontend.ci.tests.datatypes.ServiceCreateData; import org.onap.sdc.frontend.ci.tests.exception.UnzipException; import org.onap.sdc.frontend.ci.tests.execute.setup.DriverFactory; @@ -231,3 +229,4 @@ public class EtsiNetworkServiceUiTests extends SetupCDTest { } } + diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/OnboardingFlowsUi.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/OnboardingFlowsUi.java index f2e6036967..cf562c766f 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/OnboardingFlowsUi.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/OnboardingFlowsUi.java @@ -52,11 +52,12 @@ import org.onap.sdc.frontend.ci.tests.dataProvider.OnbordingDataProviders; import org.onap.sdc.frontend.ci.tests.datatypes.CanvasElement; import org.onap.sdc.frontend.ci.tests.datatypes.CanvasManager; import org.onap.sdc.frontend.ci.tests.datatypes.DataTestIdEnum; +import org.onap.sdc.frontend.ci.tests.datatypes.ResourceCreateData; 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.CheckSoftwareVersionPropertyFlow; -import org.onap.sdc.frontend.ci.tests.flow.CreateResourceFlow; +import org.onap.sdc.frontend.ci.tests.flow.CreateResourceFromVspFlow; import org.onap.sdc.frontend.ci.tests.flow.CreateVspFlow; import org.onap.sdc.frontend.ci.tests.flow.ImportVspFlow; import org.onap.sdc.frontend.ci.tests.flow.exception.UiTestFlowRuntimeException; @@ -396,7 +397,7 @@ public class OnboardingFlowsUi extends SetupCDTest { final ImportVspFlow importVspFlow = new ImportVspFlow(webDriver, resourceName); final ResourceCreatePage resourceCreatePage = importVspFlow.run() .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return ResourceCreatePage")); - final CreateResourceFlow createResourceFlow = new CreateResourceFlow(webDriver, resourceName); + final CreateResourceFromVspFlow createResourceFlow = new CreateResourceFromVspFlow(webDriver, resourceName); createResourceFlow.run(resourceCreatePage); final CheckSoftwareVersionPropertyFlow checkSoftwareVersionPropertyFlow = diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateResourceFlow.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateResourceFlow.java index 09650570e7..bdd2b9272c 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateResourceFlow.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateResourceFlow.java @@ -20,34 +20,38 @@ package org.onap.sdc.frontend.ci.tests.flow; import com.aventstack.extentreports.Status; -import org.onap.sdc.frontend.ci.tests.pages.ResourceCreatePage; +import java.util.Optional; +import org.onap.sdc.frontend.ci.tests.datatypes.ResourceCreateData; 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.ResourceCreatePage; +import org.onap.sdc.frontend.ci.tests.pages.home.HomePage; import org.openqa.selenium.WebDriver; -import java.util.Optional; - /** * UI Flow for Resource creation */ public class CreateResourceFlow extends AbstractUiTestFlow { - private final String resourceName; + private final ResourceCreateData resourceCreateData; private ResourceCreatePage resourceCreatePage; - public CreateResourceFlow(final WebDriver webDriver, final String resourceName) { + public CreateResourceFlow(final WebDriver webDriver, final ResourceCreateData resourceCreateData) { super(webDriver); - this.resourceName = resourceName; + this.resourceCreateData = resourceCreateData; } @Override public Optional<ResourceCreatePage> run(final PageObject... pageObjects) { - resourceCreatePage = findParameter(pageObjects, ResourceCreatePage.class); - extendTest.log(Status.INFO, String.format("Creating the Resource '%s'", resourceName)); - resourceCreatePage.createResource(); + extendTest.log(Status.INFO, String.format("Creating the Resource '%s' from home page", resourceCreateData.getName())); + final HomePage homePage = findParameter(pageObjects, HomePage.class); + homePage.isLoaded(); + resourceCreatePage = homePage.clickOnAddVf(); + resourceCreatePage.fillForm(resourceCreateData); + resourceCreatePage.clickOnCreate(); ExtentTestActions.takeScreenshot(Status.INFO, "resource-created", - String.format("Resource '%s' was created", resourceName)); - return Optional.ofNullable(resourceCreatePage); + String.format("Resource '%s' was created", resourceCreateData.getName())); + return Optional.ofNullable(this.resourceCreatePage); } @Override diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateResourceFromVspFlow.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateResourceFromVspFlow.java new file mode 100644 index 0000000000..b4e83817a4 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateResourceFromVspFlow.java @@ -0,0 +1,59 @@ +/* + * ============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; + +import com.aventstack.extentreports.Status; +import org.onap.sdc.frontend.ci.tests.datatypes.ResourceCreateData; +import org.onap.sdc.frontend.ci.tests.pages.ResourceCreatePage; +import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions; +import org.onap.sdc.frontend.ci.tests.pages.PageObject; +import org.openqa.selenium.WebDriver; + +import java.util.Optional; + +/** + * UI Flow for Resource creation + */ +public class CreateResourceFromVspFlow extends AbstractUiTestFlow { + + private final String resourceName; + private ResourceCreatePage resourceCreatePage; + + public CreateResourceFromVspFlow(final WebDriver webDriver, final String resourceName) { + super(webDriver); + this.resourceName = resourceName; + } + + @Override + public Optional<ResourceCreatePage> run(final PageObject... pageObjects) { + resourceCreatePage = findParameter(pageObjects, ResourceCreatePage.class); + extendTest.log(Status.INFO, String.format("Creating the Resource '%s'", resourceName)); + resourceCreatePage.clickOnCreate(); + ExtentTestActions.takeScreenshot(Status.INFO, "resource-created", + String.format("Resource '%s' was created", resourceName)); + return Optional.ofNullable(resourceCreatePage); + } + + @Override + public Optional<ResourceCreatePage> getLandedPage() { + return Optional.ofNullable(resourceCreatePage); + } + +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateVspFlow.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateVspFlow.java index 3d3d4424ce..1da45b5397 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateVspFlow.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CreateVspFlow.java @@ -140,9 +140,8 @@ public class CreateVspFlow extends AbstractUiTestFlow { private void goToHomePage(final TopNavComponent topNavComponent) { extendTest.log(Status.INFO, "Accessing the Home page to import the created VSP"); topNavComponent.isLoaded(); - topNavComponent.clickOnHome(); + homePage = topNavComponent.clickOnHome(); GeneralUIUtils.ultimateWait(); - homePage = new HomePage(webDriver, topNavComponent); homePage.isLoaded(); ExtentTestActions.takeScreenshot(Status.INFO, "home-is-loaded", "The Home page is loaded."); } diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourceCreatePage.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourceCreatePage.java index bb4ccb9b6d..025c42a987 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourceCreatePage.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourceCreatePage.java @@ -26,51 +26,102 @@ import static org.hamcrest.core.Is.is; import lombok.AllArgsConstructor; import lombok.Getter; import org.onap.sdc.frontend.ci.tests.datatypes.LifeCycleStateEnum; +import org.onap.sdc.frontend.ci.tests.datatypes.ResourceCreateData; 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.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.ui.ExpectedConditions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.openqa.selenium.support.ui.Select; /** * Handles the Resource Create Page UI actions */ public class ResourceCreatePage extends AbstractPageObject { - private static final Logger LOGGER = LoggerFactory.getLogger(ResourceCreatePage.class); private final LoaderHelper loaderHelper; private final NotificationComponent notificationComponent; - private WebElement createBtn; + private final ResourceWorkspaceTopBarComponent topBarComponent; - public ResourceCreatePage(final WebDriver webDriver, final LoaderHelper loaderHelper, - final NotificationComponent notificationComponent) { + public ResourceCreatePage(final WebDriver webDriver) { super(webDriver); - this.loaderHelper = loaderHelper; - this.notificationComponent = notificationComponent; + loaderHelper = new LoaderHelper(webDriver); + notificationComponent = new NotificationComponent(webDriver); + topBarComponent = new ResourceWorkspaceTopBarComponent(webDriver); timeoutInSeconds = 5; } @Override public void isLoaded() { - LOGGER.debug("Waiting for element visibility with xpath '{}'", XpathSelector.FORM_LIFE_CYCLE_STATE.getXpath()); - final WebElement lifeCycleState = waitForElementVisibility(XpathSelector.FORM_LIFE_CYCLE_STATE.getXpath()); + topBarComponent.isLoaded(); + final String lifeCycleState = topBarComponent.getLifecycleState(); assertThat("Life cycle state should be as expected", - lifeCycleState.getText(), is(equalToIgnoringCase(LifeCycleStateEnum.IN_DESIGN.getValue()))); - createBtn = getWait() - .until(ExpectedConditions.elementToBeClickable(By.xpath(XpathSelector.CREATE_BTN.getXpath()))); + lifeCycleState, is(equalToIgnoringCase(LifeCycleStateEnum.IN_DESIGN.getValue()))); } /** * Creates the resource and wait for success notification. */ - public void createResource() { - createBtn.click(); - loaderHelper.waitForLoader(60); - notificationComponent.waitForNotification(NotificationType.SUCCESS, 60); + public void clickOnCreate() { + topBarComponent.clickOnCreate(); + loaderHelper.waitForLoader(20); + notificationComponent.waitForNotification(NotificationType.SUCCESS, 20); + } + + public void fillForm(final ResourceCreateData resourceCreateData) { + fillName(resourceCreateData.getName()); + setCategory(resourceCreateData.getCategory()); + fillDescription(resourceCreateData.getDescription()); + fillContactId(resourceCreateData.getContactId()); + fillVendorName(resourceCreateData.getVendorName()); + fillVendorRelease(resourceCreateData.getVendorRelease()); + fillVendorModelNumber(resourceCreateData.getVendorModelNumber()); + } + + public void fillName(final String name) { + setInputField(By.xpath(XpathSelector.NAME_INPUT.getXpath()), name); + } + + public void setCategory(final String category) { + setSelectField(By.xpath(XpathSelector.CATEGORY_SELECT.getXpath()), category); + } + + public void fillDescription(final String description) { + setTextAreaField(By.xpath(XpathSelector.DESCRIPTION_TEXT_AREA.getXpath()), description); + } + + public void fillContactId(final String contactId) { + setInputField(By.xpath(XpathSelector.CONTACT_ID_INPUT.getXpath()), contactId); + } + + public void fillVendorName(final String vendorName) { + setInputField(By.xpath(XpathSelector.VENDOR_NAME_INPUT.getXpath()), vendorName); + } + + public void fillVendorRelease(final String vendorRelease) { + setInputField(By.xpath(XpathSelector.VENDOR_RELEASE_INPUT.getXpath()), vendorRelease); + } + + public void fillVendorModelNumber(final String vendorModelNumber) { + setInputField(By.xpath(XpathSelector.VENDOR_MODEL_NUMBER_INPUT.getXpath()), vendorModelNumber); + } + + private void setSelectField(final By locator, final String value) { + if (value == null) { + return; + } + new Select(findElement(locator)).selectByVisibleText(value); + } + + private void setInputField(final By locator, final String value) { + if (value == null) { + return; + } + findElement(locator).sendKeys(value); + } + + private void setTextAreaField(final By locator, final String value) { + setInputField(locator, value); } /** @@ -78,8 +129,13 @@ public class ResourceCreatePage extends AbstractPageObject { */ @AllArgsConstructor private enum XpathSelector { - CREATE_BTN("create/save", "//button[@data-tests-id='%s']"), - FORM_LIFE_CYCLE_STATE("formlifecyclestate", "//span[@data-tests-id='%s']"); + NAME_INPUT("name", "//input[@data-tests-id='%s']"), + CATEGORY_SELECT("selectGeneralCategory", "//select[@data-tests-id='%s']"), + DESCRIPTION_TEXT_AREA("description", "//textarea[@data-tests-id='%s']"), + CONTACT_ID_INPUT("contactId", "//input[@data-tests-id='%s']"), + VENDOR_NAME_INPUT("vendorName", "//input[@data-tests-id='%s']"), + VENDOR_RELEASE_INPUT("vendorRelease", "//input[@data-tests-id='%s']"), + VENDOR_MODEL_NUMBER_INPUT("resourceVendorModelNumber", "//input[@data-tests-id='%s']"); @Getter private final String id; 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 b58a3adc8a..f94b3030a7 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 @@ -21,6 +21,7 @@ package org.onap.sdc.frontend.ci.tests.pages; import lombok.AllArgsConstructor; import lombok.Getter; +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.By; import org.openqa.selenium.WebDriver; @@ -84,6 +85,11 @@ public class ResourceLeftSideMenu extends AbstractPageObject { return new ServiceCreatePage(webDriver); } + public CompositionPage clickOnCompositionMenuItem() { + wrappingElement.findElement(By.xpath(XpathSelector.COMPOSITION_MENU.getXpath())).click(); + return new CompositionPage(webDriver); + } + /** * Enum that contains identifiers and xpath expressions to elements related to the enclosing page object. */ @@ -92,6 +98,7 @@ public class ResourceLeftSideMenu extends AbstractPageObject { MAIN_DIV("w-sdc-left-sidebar", "//div[@class='%s']"), PROPERTIES_ASSIGNMENT_MENU("Properties AssignmentLeftSideMenu", "//*[@data-tests-id='%s']"), GENERAL_MENU("GeneralLeftSideMenu", "//*[@data-tests-id='%s']"), + COMPOSITION_MENU("CompositionLeftSideMenu", "//*[@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/pages/ServiceComponentPage.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ServiceComponentPage.java index 254a0ece50..a33bdc387c 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ServiceComponentPage.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ServiceComponentPage.java @@ -19,6 +19,7 @@ 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; @@ -28,6 +29,13 @@ public class ServiceComponentPage extends AbstractPageObject { 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) { @@ -52,4 +60,8 @@ public class ServiceComponentPage extends AbstractPageObject { return resourceLeftSideMenu.clickOnToscaArtifactsMenuItem(); } + public CompositionPage goToComposition() { + return resourceLeftSideMenu.clickOnCompositionMenuItem(); + } + } diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/TopNavComponent.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/TopNavComponent.java index 56b584af8c..33deabbae0 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/TopNavComponent.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/TopNavComponent.java @@ -23,6 +23,7 @@ import java.util.List; import lombok.AllArgsConstructor; import lombok.Getter; import org.onap.sdc.frontend.ci.tests.execute.setup.DriverFactory; +import org.onap.sdc.frontend.ci.tests.pages.home.HomePage; import org.onap.sdc.frontend.ci.tests.utilities.GeneralUIUtils; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; @@ -65,25 +66,40 @@ public class TopNavComponent extends AbstractPageObject { /** * Clicks on home link inside the first breadcrumb arrow. */ - public void clickOnHome() { + public HomePage clickOnHome() { hoverToBreadcrumbArrow(0); final By homeButtonLocator = By.xpath(XpathSelector.SUB_MENU_BUTTON_HOME.getXpath()); - getWait().until(ExpectedConditions.visibilityOfElementLocated(homeButtonLocator)); - getWait().until(ExpectedConditions.elementToBeClickable(homeButtonLocator)).click(); - getWait() - .until(ExpectedConditions.visibilityOfElementLocated(By.xpath(XpathSelector.REPOSITORY_ICON.getXpath()))); + waitForElementVisibility(homeButtonLocator); + waitToBeClickable(homeButtonLocator).click(); + return new HomePage(webDriver, this); } public boolean isHomeSelected() { final By homeLinkLocator = By.xpath(XpathSelector.MAIN_MENU_LINK_HOME.getXpath()); - getWait().until(ExpectedConditions.visibilityOfElementLocated(homeLinkLocator)); - final WebElement homeLinkElement = findElement(homeLinkLocator); + final WebElement homeLinkElement = waitForElementVisibility(homeLinkLocator); final WebElement homeLinkParentElement = homeLinkElement.findElement(By.xpath("./..")); final String aClass = homeLinkParentElement.getAttribute("class"); return "selected".equals(aClass); } /** + * Click on one of the items of the top nav breadcrumb based on the given position. + * The first item in the breadcrumb is position 0. + * + * @param position the position of the breadcrumb item + */ + public void clickOnBreadCrumb(final int position) { + if (position < 0) { + throw new IllegalStateException("The position cannot be less that zero"); + } + waitForElementVisibility(By.xpath(String.format("//*[@data-tests-id='breadcrumbs-button-%s']", position))).click(); + } + + public void waitRepositoryToBeClickable() { + waitToBeClickable(XpathSelector.REPOSITORY_ICON.getXpath()); + } + + /** * Clicks on the VSP repository icon. * * @return the next page object diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/VspRepositoryModalComponent.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/VspRepositoryModalComponent.java index 0cf7dbd501..4cbe805fde 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/VspRepositoryModalComponent.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/VspRepositoryModalComponent.java @@ -28,8 +28,6 @@ import java.util.List; import lombok.AllArgsConstructor; import lombok.Getter; import org.onap.sdc.frontend.ci.tests.utilities.GeneralUIUtils; -import org.onap.sdc.frontend.ci.tests.utilities.LoaderHelper; -import org.onap.sdc.frontend.ci.tests.utilities.NotificationComponent; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; @@ -70,7 +68,7 @@ public class VspRepositoryModalComponent extends AbstractPageObject { findSubElements(wrappingElement, By.className(XpathSelector.RESULTS_CONTAINER_DIV.getId())); vspResultList.get(listPosition).click(); GeneralUIUtils.clickOnElementByTestId(XpathSelector.IMPORT_VSP_BTN.getId()); - return new ResourceCreatePage(webDriver, new LoaderHelper(), new NotificationComponent(webDriver)); + return new ResourceCreatePage(webDriver); } /** diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionApiArtifactsTab.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionApiArtifactsTab.java new file mode 100644 index 0000000000..df611a8089 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionApiArtifactsTab.java @@ -0,0 +1,50 @@ +/* + * ============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; + +/** + * Represents the composition page, details panel, API Artifacts tab + */ +public class CompositionApiArtifactsTab extends AbstractPageObject { + + public CompositionApiArtifactsTab(final WebDriver webDriver) { + super(webDriver); + } + + @Override + public void isLoaded() { + waitForElementVisibility(By.xpath(XpathSelector.API_ARTIFACTS_TAB.getXpath())); + } + + @AllArgsConstructor + @Getter + private enum XpathSelector { + API_ARTIFACTS_TAB("//artifacts-tab[.//header[contains(text(), 'API Artifacts')]]"); + + private final String xpath; + + } +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionCanvasComponent.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionCanvasComponent.java new file mode 100644 index 0000000000..6ecea473c5 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionCanvasComponent.java @@ -0,0 +1,249 @@ +/* + * ============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 com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Optional; +import java.util.Random; +import java.util.Set; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.onap.sdc.backend.ci.tests.datatypes.enums.UserRoleEnum; +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.pages.AbstractPageObject; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.Point; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CompositionCanvasComponent extends AbstractPageObject { + + private static final Logger LOGGER = LoggerFactory.getLogger(CompositionCanvasComponent.class); + private static final String nodePositionJs = "var cy = window.jQuery('.sdc-composition-graph-wrapper').cytoscape('get');%n" + + "var n = cy.nodes('[name=\"%s\"]');%n" + + "var nPos = n.renderedPosition();%n" + + "return JSON.stringify({%n" + + " x: nPos.x,%n" + + " y: nPos.y%n" + + "})"; + + private static final String getNodesJs = "var cy = window.jQuery('.sdc-composition-graph-wrapper').cytoscape('get');\n" + + "var nodes = [];" + + "cy.nodes().forEach((node) => {nodes.push(JSON.stringify({name: node.data('name'), position: node.renderedPosition()}))});\n" + + "return nodes;"; + + private final CompositionElementsComponent compositionElementsComponent; + private final CompositionDetailSideBarComponent compositionDetailSideBarComponent; + + private WebElement canvasWebElement; + private Set<CanvasNodeElement> canvasElementList; + private int canvasCenterX; + private int canvasCenterY; + private int canvasWidth; + private int canvasHeight; + + public CompositionCanvasComponent(final WebDriver webDriver) { + super(webDriver); + compositionElementsComponent = new CompositionElementsComponent(webDriver); + compositionDetailSideBarComponent = new CompositionDetailSideBarComponent(webDriver); + } + + @Override + public void isLoaded() { + //waiting the canvas data to be load and animation finishes. + new Actions(webDriver).pause(Duration.ofSeconds(2)).perform(); + canvasWebElement = waitToBeClickable(XpathSelector.CANVAS_ELEMENT.getXpath()); + compositionElementsComponent.isLoaded(); + compositionDetailSideBarComponent.isLoaded(); + loadCanvas(); + loadElements(); + } + + private void loadCanvas() { + canvasWidth = canvasWebElement.getSize().getWidth(); + canvasHeight = canvasWebElement.getSize().getHeight(); + 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() { + canvasElementList = new HashSet<>(); + final Object nodeListObj = ((JavascriptExecutor) webDriver).executeScript(getNodesJs); + if (!(nodeListObj instanceof ArrayList)) { + return; + } + final ArrayList<String> nodeList = (ArrayList<String>) nodeListObj; + if (nodeList.isEmpty()) { + return; + } + nodeList.forEach(nodeString -> { + final JsonObject node = new JsonParser().parse(nodeString).getAsJsonObject(); + final JsonObject position = node.get("position").getAsJsonObject(); + final CanvasNodeElement canvasElement = + new CanvasNodeElement(node.get("name").getAsString(), position.get("x").getAsInt(), position.get("y").getAsInt()); + canvasElementList.add(canvasElement); + }); + } + + public void selectNode(final String elementName) { + final Optional<CanvasNodeElement> canvasElementOptional = canvasElementList.stream() + .filter(canvasNodeElement -> canvasNodeElement.getName().equals(elementName)) + .findFirst(); + if (canvasElementOptional.isEmpty()) { + throw new CompositionCanvasRuntimeException(String.format("Given element '%s' does not exist on the element list", elementName)); + } + final CanvasNodeElement canvasNodeElement = canvasElementOptional.get(); + final Point positionFromCenter = calculateOffsetFromCenter(canvasNodeElement.getPositionX(), + canvasNodeElement.getPositionY()); + final Actions actions = new Actions(webDriver); + int offsetFromElementCenter = 10; + actions.moveToElement(canvasWebElement, positionFromCenter.getX() - offsetFromElementCenter, + positionFromCenter.getY() + offsetFromElementCenter) + .pause(Duration.ofSeconds(1)) + .click() + .perform(); + ExtentTestActions.takeScreenshot(Status.INFO, "canvas-node-selected", String.format("'%s' was selected", elementName)); + } + + public ComponentInstance createNodeOnServiceCanvas(final String serviceName, final String serviceVersion, final String resourceName, + final String resourceVersion) { + final Point freePositionInCanvas = getFreePositionInCanvas(20); + final Point pointFromCanvasCenter = calculateOffsetFromCenter(freePositionInCanvas); + try { + final Service service = + AtomicOperationUtils.getServiceObjectByNameAndVersion(UserRoleEnum.DESIGNER, serviceName, serviceVersion); + final Resource resourceToAdd = + AtomicOperationUtils.getResourceObjectByNameAndVersion(UserRoleEnum.DESIGNER, resourceName, resourceVersion); + final ComponentInstance componentInstance = AtomicOperationUtils + .addComponentInstanceToComponentContainer(resourceToAdd, service, UserRoleEnum.DESIGNER, true, + String.valueOf(pointFromCanvasCenter.getX()), String.valueOf(pointFromCanvasCenter.getY())) + .left().value(); + + LOGGER.debug("Created instance {} in the Service {}", componentInstance.getName(), serviceName); + return componentInstance; + } catch (final Exception e) { + throw new CompositionCanvasRuntimeException("Could not create node through the API", e); + } + } + + private Point getFreePositionInCanvas(int maxAttempts) { + boolean isPositionFree; + final int minSpace = 150; + for (int attemptCount = 0; attemptCount < maxAttempts; attemptCount++) { + final Point randomPositionInCanvas = getRandomPositionInCanvas(); + isPositionFree = canvasElementList.stream() + .noneMatch(canvasNodeElement -> Math.abs(canvasNodeElement.getPositionX() - randomPositionInCanvas.getX()) < minSpace + && Math.abs(canvasNodeElement.getPositionX() - randomPositionInCanvas.getY()) < minSpace); + if (isPositionFree) { + return randomPositionInCanvas; + } + } + throw new CompositionCanvasRuntimeException("Could not find a free Canvas position"); + } + + private Point getRandomPositionInCanvas() { + final Random random = new Random(); + int x = random.nextInt(canvasWidth); + final int maxAllowedWidth = canvasWidth - getRightMarginWidth(); + final int minAllowedWidth = 30; + if (x > maxAllowedWidth) { + x = x - getRightMarginWidth(); + } else if (x < minAllowedWidth) { + x = x + minAllowedWidth; + } + int bottomMargin = 0; + int heightTopMargin = 100; + int y = random.nextInt(canvasHeight); + int maxAllowedHeight = canvasHeight - bottomMargin; + + if (y > maxAllowedHeight) { + y = y - bottomMargin; + } else if (y < heightTopMargin) { + y = y + heightTopMargin; + } + LOGGER.debug("Generated random position in canvas [{},{}]", x, y); + + return new Point(x, y); + } + + private int getRightMarginWidth() { + int canvasIconsOffset = 100; + final Dimension sideBarSize = compositionDetailSideBarComponent.getSize(); + return sideBarSize.getWidth() + canvasIconsOffset; + } + + private Point calculateOffsetFromCenter(final Point point) { + return calculateOffsetFromCenter(point.getX(), point.getY()); + } + + private Point calculateOffsetFromCenter(final int xPosition, final int yPosition) { + final int positionX = xPosition - canvasCenterX; + final int positionY = yPosition - canvasCenterY; + return new Point(positionX, positionY); + } + + public ImmutablePair<Integer, Integer> getElementPositionByName(final String elementName) { + final String scriptJs = String.format(nodePositionJs, elementName); + final Object position = ((JavascriptExecutor) webDriver).executeScript(scriptJs); + final JsonObject positionAsJson = new JsonParser().parse(position.toString()).getAsJsonObject(); + int xElement = positionAsJson.get("x").getAsInt(); + int yElement = positionAsJson.get("y").getAsInt(); + return new ImmutablePair<>(xElement, yElement); + } + + /** + * Enum that contains identifiers and xpath expressions to elements related to the enclosing page object. + */ + @AllArgsConstructor + private enum XpathSelector { + CANVAS_ELEMENT("canvas", "//*[@data-tests-id='%s']//canvas[1]"); + + @Getter + private final String id; + private final String xpathFormat; + + public String getXpath() { + return String.format(xpathFormat, id); + } + } +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionDeploymentArtifactsTab.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionDeploymentArtifactsTab.java new file mode 100644 index 0000000000..2dbd6ba6f1 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionDeploymentArtifactsTab.java @@ -0,0 +1,50 @@ +/* + * ============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; + +/** + * Represents the composition page, details panel, Deployment Artifacts tab + */ +public class CompositionDeploymentArtifactsTab extends AbstractPageObject { + + public CompositionDeploymentArtifactsTab(final WebDriver webDriver) { + super(webDriver); + } + + @Override + public void isLoaded() { + waitForElementVisibility(By.xpath(XpathSelector.DEPLOYMENT_ARTIFACTS_TAB.getXpath())); + } + + @AllArgsConstructor + @Getter + private enum XpathSelector { + DEPLOYMENT_ARTIFACTS_TAB("//artifacts-tab[.//header[contains(text(), 'Deployment Artifacts')]]"); + + private final String xpath; + + } +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionDetailSideBarComponent.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionDetailSideBarComponent.java new file mode 100644 index 0000000000..214885ac3d --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionDetailSideBarComponent.java @@ -0,0 +1,124 @@ +/* + * ============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.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.onap.sdc.frontend.ci.tests.pages.AbstractPageObject; +import org.openqa.selenium.By; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +public class CompositionDetailSideBarComponent extends AbstractPageObject { + + private WebElement wrappingElement; + + public CompositionDetailSideBarComponent(final WebDriver webDriver) { + super(webDriver); + } + + @Override + public void isLoaded() { + wrappingElement = waitForElementVisibility(By.xpath(XpathSelector.MAIN_ELEMENT_DIV.getXpath())); + } + + public String getSelectedComponentName() { + return wrappingElement.findElement(By.xpath(XpathSelector.DETAIL_COMPONENT_NAME_DIV.getXpath())).getText(); + } + + public void checkComponentIsSelected(final String componentName) { + assertThat("The selected component should be as expected", getSelectedComponentName(), is(componentName)); + } + + public Dimension getSize() { + final WebElement sideBarToggle = waitForElementVisibility(XpathSelector.DETAIL_SIDE_BAR_TOGGLE_DIV.getXpath()); + if (!sideBarToggle.getAttribute("class").contains("active")) { + return new Dimension(0, 0); + } + + return wrappingElement.getSize(); + } + + public AbstractPageObject selectTab(final CompositionDetailTabName tabName) { + final WebElement tabElement = wrappingElement.findElement(By.xpath(tabName.getXpathSelector().getXpath())); + tabElement.click(); + switch (tabName) { + case INFORMATION: + return new CompositionInformationTab(webDriver); + case INPUTS: + return new CompositionInputsTab(webDriver); + case DEPLOYMENT_ARTIFACTS: + return new CompositionDeploymentArtifactsTab(webDriver); + case INFORMATIONAL_ARTIFACTS: + return new CompositionInformationalArtifactsTab(webDriver); + case API_ARTIFACTS: + return new CompositionApiArtifactsTab(webDriver); + case SUBSTITUTION_FILTER: + return new CompositionSubstitutionFilterTab(webDriver); + default: + throw new IllegalStateException("Not yet implemented: " + tabName); + } + } + + /** + * Enum that contains identifiers and xpath expressions to elements related to the enclosing page object. + */ + @AllArgsConstructor + private enum XpathSelector { + MAIN_ELEMENT_DIV("w-sdc-designer-sidebar", "//div[@class='%s']"), + DETAIL_SIDE_BAR_TOGGLE_DIV("w-sdc-designer-sidebar-toggle", "//div[contains(concat(' ',normalize-space(@class),' '),' %s ')]"), + DETAIL_HEADER("w-sdc-designer-sidebar-head", "//div[@data-tests-id='%s']"), + DETAIL_COMPONENT_NAME_DIV("selectedCompTitle", "//div[@data-tests-id='%s']"), + TAB_LIST("sdc-tabs-list", "//ul[@class='%s']/li"), + INFORMATION_TAB("detail-tab-information", "//li[@data-tests-id='%s']"), + 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']"), + API_ARTIFACTS_TAB("detail-tab-api-artifacts", "//li[@data-tests-id='%s']"), + SUBSTITUTION_FILTER_TAB("detail-tab-substitution-filter", "//li[@data-tests-id='%s']"); + + @Getter + private final String id; + private final String xpathFormat; + + public String getXpath() { + return String.format(xpathFormat, id); + } + } + + @Getter + @AllArgsConstructor + public enum CompositionDetailTabName { + INFORMATION(XpathSelector.INFORMATION_TAB), + INPUTS(XpathSelector.INPUTS_TAB), + DEPLOYMENT_ARTIFACTS(XpathSelector.DEPLOYMENT_ARTIFACTS_TAB), + INFORMATIONAL_ARTIFACTS(XpathSelector.INFORMATION_ARTIFACTS_TAB), + API_ARTIFACTS(XpathSelector.API_ARTIFACTS_TAB), + SUBSTITUTION_FILTER(XpathSelector.SUBSTITUTION_FILTER_TAB); + + private final XpathSelector xpathSelector; + + } +} + diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionElementsComponent.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionElementsComponent.java new file mode 100644 index 0000000000..a4fc8b9019 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionElementsComponent.java @@ -0,0 +1,92 @@ +/* + * ============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 java.time.Duration; +import java.util.Optional; +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.interactions.Actions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CompositionElementsComponent extends AbstractPageObject { + + private static final Logger LOGGER = LoggerFactory.getLogger(CompositionElementsComponent.class); + + private WebElement wrappingElement; + + public CompositionElementsComponent(final WebDriver webDriver) { + super(webDriver); + } + + @Override + public void isLoaded() { + final By xpath = By.xpath(XpathSelector.MAIN_ELEMENT.getXpath()); + wrappingElement = waitToBeClickable(xpath); + } + + public Optional<WebElement> searchElement(final String elementName) { + final WebElement searchElementInput = wrappingElement.findElement(By.xpath(XpathSelector.SEARCH_INPUT.getXpath())); + searchElementInput.sendKeys(elementName); + new Actions(webDriver).pause(Duration.ofSeconds(1)).perform(); + try { + final WebElement accordionElement = waitForElementVisibility("//div[@class='sdc-accordion-header']"); + final String aClass = accordionElement.getAttribute("class"); + if (!aClass.contains("open")) { + accordionElement.click(); + } + return Optional.ofNullable(waitToBeClickable(XpathSelector.ELEMENT_DIV.getXpath(elementName))); + } catch (final Exception e) { + LOGGER.debug("Could not find element " + elementName, e); + return Optional.empty(); + } + } + + /** + * Enum that contains identifiers and xpath expressions to elements related to the enclosing page object. + */ + @AllArgsConstructor + private enum XpathSelector { + MAIN_ELEMENT("composition-palette", "//composition-palette"), + SEARCH_INPUT("searchAsset-input", "//*[@data-tests-id='%s']"), + ELEMENT_DIV("//*[@data-tests-id='%s']"); + + @Getter + private String id; + private final String xpathFormat; + + XpathSelector(final String xpathFormat) { + this.xpathFormat = xpathFormat; + } + + public String getXpath() { + return String.format(xpathFormat, id); + } + + public String getXpath(final String... params) { + return String.format(xpathFormat, params); + } + } +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInformationTab.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInformationTab.java new file mode 100644 index 0000000000..b911c632c7 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInformationTab.java @@ -0,0 +1,50 @@ +/* + * ============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; + +/** + * Represents the composition page, details panel, Information tab + */ +public class CompositionInformationTab extends AbstractPageObject { + + public CompositionInformationTab(final WebDriver webDriver) { + super(webDriver); + } + + @Override + public void isLoaded() { + waitForElementVisibility(By.xpath(XpathSelector.INFORMATION_TAB.getXPath())); + } + + @AllArgsConstructor + @Getter + private enum XpathSelector { + INFORMATION_TAB("//panel-info-tab"); + + private final String xPath; + + } +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInformationalArtifactsTab.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInformationalArtifactsTab.java new file mode 100644 index 0000000000..401dd7988e --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInformationalArtifactsTab.java @@ -0,0 +1,50 @@ +/* + * ============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; + +/** + * Represents the composition page, details panel, Informational Artifacts tab + */ +public class CompositionInformationalArtifactsTab extends AbstractPageObject { + + public CompositionInformationalArtifactsTab(final WebDriver webDriver) { + super(webDriver); + } + + @Override + public void isLoaded() { + waitForElementVisibility(By.xpath(XpathSelector.INFORMATIONAL_ARTIFACTS_TAB.getXpath())); + } + + @AllArgsConstructor + @Getter + private enum XpathSelector { + INFORMATIONAL_ARTIFACTS_TAB("//artifacts-tab[.//header[contains(text(), 'Informational Artifacts')]]"); + + private final String xpath; + + } +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInputsTab.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInputsTab.java new file mode 100644 index 0000000000..08f5074a84 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionInputsTab.java @@ -0,0 +1,50 @@ +/* + * ============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; + +/** + * Represents the composition page, details panel, Inputs tab + */ +public class CompositionInputsTab extends AbstractPageObject { + + public CompositionInputsTab(final WebDriver webDriver) { + super(webDriver); + } + + @Override + public void isLoaded() { + waitForElementVisibility(By.xpath(XpathSelector.INPUTS_TAB.getXPath())); + } + + @AllArgsConstructor + @Getter + private enum XpathSelector { + INPUTS_TAB("//properties-tab[.//header[contains(text(), 'Inputs')]]"); + + private final String xPath; + + } +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionPage.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionPage.java new file mode 100644 index 0000000000..c013247a28 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionPage.java @@ -0,0 +1,87 @@ +/* + * ============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 org.onap.sdc.frontend.ci.tests.pages.AbstractPageObject; +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.openecomp.sdc.be.model.ComponentInstance; +import org.openqa.selenium.WebDriver; + +/** + * Represents the Component (Service, VF, VFC, etc.) Composition Page + */ +public class CompositionPage extends AbstractPageObject { + + private final ResourceWorkspaceTopBarComponent resourceWorkspaceTopBarComponent; + private final TopNavComponent topNavComponent; + private final CompositionElementsComponent compositionElementsComponent; + private final CompositionCanvasComponent compositionCanvasComponent; + private final CompositionDetailSideBarComponent compositionDetailSideBarComponent; + + public CompositionPage(final WebDriver webDriver) { + super(webDriver); + topNavComponent = new TopNavComponent(webDriver); + resourceWorkspaceTopBarComponent = new ResourceWorkspaceTopBarComponent(webDriver); + compositionElementsComponent = new CompositionElementsComponent(webDriver); + compositionCanvasComponent = new CompositionCanvasComponent(webDriver); + compositionDetailSideBarComponent = new CompositionDetailSideBarComponent(webDriver); + } + + @Override + public void isLoaded() { + compositionElementsComponent.isLoaded(); + resourceWorkspaceTopBarComponent.isLoaded(); + topNavComponent.isLoaded(); + compositionCanvasComponent.isLoaded(); + compositionDetailSideBarComponent.isLoaded(); + } + + public ComponentInstance addNodeToCompositionUsingApi(final String serviceName, final String serviceVersion, final String resourceName, + final String resourceVersion) { + return compositionCanvasComponent.createNodeOnServiceCanvas(serviceName, serviceVersion, resourceName, resourceVersion); + } + + /** + * Select a node in the canvas + * + * @param nodeName the node name to select + */ + public void selectNode(final String nodeName) { + compositionCanvasComponent.selectNode(nodeName); + compositionDetailSideBarComponent.checkComponentIsSelected(nodeName); + } + + public ServiceComponentPage goToServiceGeneral() { + topNavComponent.clickOnBreadCrumb(1); + return new ServiceComponentPage(webDriver); + } + + /** + * Get the composition page detail sidebar component + * + * @return the composition detail sideBar component + */ + public CompositionDetailSideBarComponent getDetailSideBar() { + return compositionDetailSideBarComponent; + } + +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionSubstitutionFilterTab.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionSubstitutionFilterTab.java new file mode 100644 index 0000000000..d279e1f07d --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/CompositionSubstitutionFilterTab.java @@ -0,0 +1,52 @@ +/* + * ============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; + +/** + * Represents the composition page, details panel, Substitution Filters tab + */ +public class CompositionSubstitutionFilterTab extends AbstractPageObject { + + public CompositionSubstitutionFilterTab(final WebDriver webDriver) { + super(webDriver); + } + + @Override + public void isLoaded() { + waitForElementVisibility(By.xpath(XpathSelector.SUBSTITUTION_FILTER_TAB.getXPath())); + waitForElementVisibility(By.xpath(XpathSelector.ADD_SUBSTITUTION_FILTER_BTN.getXPath())); + } + + @AllArgsConstructor + @Getter + private enum XpathSelector { + SUBSTITUTION_FILTER_TAB("//substitution-filter-tab"), + ADD_SUBSTITUTION_FILTER_BTN("//button[@data-tests-id='add-substitution-filter-button']"); + + private final String xPath; + + } +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/home/HomePage.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/home/HomePage.java index f39f21d482..563dd11452 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/home/HomePage.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/home/HomePage.java @@ -25,6 +25,10 @@ import static org.hamcrest.core.Is.is; 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; import org.openqa.selenium.By; @@ -47,7 +51,10 @@ public class HomePage extends AbstractPageObject { @Override public void isLoaded() { + waitToBeClickable(XpathSelector.HOME_RIGHT_CONTAINER.getXpath()); + waitToBeClickable(XpathSelector.HOME_SIDE_BAR.getXpath()); topNavComponent.isLoaded(); + topNavComponent.waitRepositoryToBeClickable(); assertThat("The Home tab should be selected", topNavComponent.isHomeSelected(), is(true)); } @@ -57,23 +64,98 @@ public class HomePage extends AbstractPageObject { * @return the following service create page */ public ServiceCreatePage clickOnAddService() { - hoverToAddArea(); - final By addServiceBtnLocator = By.xpath(XpathSelector.ADD_SERVICE_BTN.getXpath()); - waitForElementVisibility(addServiceBtnLocator); - final WebElement addServiceBtn = findElement(addServiceBtnLocator); - addServiceBtn.click(); + clickOnAdd(By.xpath(XpathSelector.ADD_SERVICE_BTN.getXpath())); return new ServiceCreatePage(webDriver); } /** + * Clicks on the add VF button. + * + * @return the following resource create page + */ + public ResourceCreatePage clickOnAddVf() { + clickOnAdd(By.xpath(XpathSelector.ADD_VF_BTN.getXpath())); + return new ResourceCreatePage(webDriver); + } + + /** + * Clicks on the add CR button. + * + * @return the following resource create page + */ + public ResourceCreatePage clickOnAddCr() { + clickOnAdd(By.xpath(XpathSelector.ADD_CR_BTN.getXpath())); + return new ResourceCreatePage(webDriver); + } + + /** + * Clicks on the add PNF button. + * + * @return the following resource create page + */ + public ResourceCreatePage clickOnAddPnf() { + clickOnAdd(By.xpath(XpathSelector.ADD_PNF_BTN.getXpath())); + return new ResourceCreatePage(webDriver); + } + + /** + * Clicks on the Import VFC button. + * + * @return the following resource create page + */ + public ResourceCreatePage clickOnImportVfc() { + clickOnImport(By.xpath(XpathSelector.IMPORT_VFC_BTN.getXpath())); + return new ResourceCreatePage(webDriver); + } + + public AbstractPageObject clickOnComponent(final String component) { + WebElement element = waitForElementVisibility(By.xpath(XpathSelector.COMPONENT.getXpath(component))); + final WebElement componentTypeDiv = element.findElement(By.xpath("./../../../div[contains(@class, 'sdc-tile-header')]/div")); + final String text = componentTypeDiv.getText(); + element.click(); + if ("S".equals(text)) { + return new ServiceComponentPage(webDriver, topNavComponent, + new ResourceLeftSideMenu(webDriver), new ResourceWorkspaceTopBarComponent(webDriver)); + } + + throw new UnsupportedOperationException("Return not yet implemented for " + text); + } + + + private void clickOnAdd(final By locator) { + hoverToAddArea(); + waitForElementVisibility(locator); + findElement(locator).click(); + } + + private void clickOnImport(final By locator) { + hoverToImportArea(); + waitForElementVisibility(locator); + findElement(locator).click(); + } + + /** * Hovers to the Add buttons area. * * @return the add buttons area element */ public WebElement hoverToAddArea() { + return hoverTo(By.xpath(XpathSelector.ADD_BUTTONS_AREA.getXpath())); + } + + /** + * Hovers to the Import buttons area. + * + * @return the Import buttons area element + */ + public WebElement hoverToImportArea() { + return hoverTo(By.xpath(XpathSelector.IMPORT_BUTTONS_AREA.getXpath())); + } + + + private WebElement hoverTo(final By locator) { + final WebElement addButtonsAreaElement = findElement(locator); final Actions actions = new Actions(webDriver); - final By addButtonsAreaLocator = By.xpath(XpathSelector.ADD_BUTTONS_AREA.getXpath()); - final WebElement addButtonsAreaElement = findElement(addButtonsAreaLocator); actions.moveToElement(addButtonsAreaElement).build().perform(); return addButtonsAreaElement; } @@ -83,15 +165,31 @@ public class HomePage extends AbstractPageObject { */ @AllArgsConstructor private enum XpathSelector { + HOME_RIGHT_CONTAINER("w-sdc-main-right-container", "//div[@class='%s']"), + HOME_SIDE_BAR("w-sdc-left-sidebar", "//div[@class='%s']"), ADD_SERVICE_BTN("createServiceButton", "//*[@data-tests-id='%s']"), - ADD_BUTTONS_AREA("AddButtonsArea", "//*[@data-tests-id='%s']"); + ADD_VF_BTN("createResourceButton", "//*[@data-tests-id='%s']"), + ADD_PNF_BTN("createPNFButton", "//*[@data-tests-id='%s']"), + ADD_CR_BTN("createCRButton", "//*[@data-tests-id='%s']"), + IMPORT_VFC_BTN("fileimportVFCbutton", "//*[@data-tests-id='%s']"), + ADD_BUTTONS_AREA("AddButtonsArea", "//*[@data-tests-id='%s']"), + IMPORT_BUTTONS_AREA("importButtonsArea", "//*[@data-tests-id='%s']"), + COMPONENT("//*[@data-tests-id='%s']"); @Getter - private final String id; + private String id; private final String xpathFormat; + XpathSelector(final String xpathFormat) { + this.xpathFormat = xpathFormat; + } + public String getXpath() { return String.format(xpathFormat, id); } + + public String getXpath(String... parameters) { + return String.format(xpathFormat, parameters); + } } } 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 4149a91a2a..d8f57db7e6 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 @@ -19,40 +19,25 @@ package org.onap.sdc.frontend.ci.tests.utilities; -import lombok.NoArgsConstructor; -import org.onap.sdc.frontend.ci.tests.execute.setup.DriverFactory; +import org.onap.sdc.frontend.ci.tests.pages.AbstractPageObject; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; -import org.openqa.selenium.support.ui.ExpectedConditions; -import org.openqa.selenium.support.ui.WebDriverWait; -@NoArgsConstructor -public class LoaderHelper { +public class LoaderHelper extends AbstractPageObject { - private WebDriver webDriver; + private final By loaderLocator = By.xpath("//*[@data-tests-id='loader' or @class='tlv-loader']"); public LoaderHelper(final WebDriver webDriver) { - this.webDriver = webDriver; + super(webDriver); } - private final By locator = By.className("tlv-loader"); - public void waitForLoader(final int timeout) { - waitForLoaderVisibility(5); - waitForLoaderInvisibility(timeout); + waitForElementVisibility(loaderLocator, 5); + waitForElementInvisibility(loaderLocator, timeout); } - private void waitForLoaderVisibility(final int timeout) { - getWait(timeout) - .until(ExpectedConditions.visibilityOfElementLocated(locator)); - } + @Override + public void isLoaded() { - private void waitForLoaderInvisibility(int timeout) { - getWait(timeout).until(ExpectedConditions.invisibilityOfElementLocated(locator)); } - - private WebDriverWait getWait(final int timeout) { - return new WebDriverWait(webDriver == null ? DriverFactory.getDriver() : webDriver, timeout); - } - } diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/utilities/MouseUtils.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/utilities/MouseUtils.java new file mode 100644 index 0000000000..3bcca470ed --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/utilities/MouseUtils.java @@ -0,0 +1,70 @@ +/* + * ============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.utilities; + +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebDriver; + +public class MouseUtils { + + private MouseUtils() { + + } + + /** + * Using Javascript, it creates a mouse pointer image that will follow the mouse pointer on screen, making the mouse visible to the user during + * the test. + * + * @param webDriver the selenium webdriver + * @see <a href="https://gist.github.com/primaryobjects/70087610d9aef0f4bddbe2101dda7649">github gist</a> + * @see <a href="https://stackoverflow.com/questions/35867776/visualize-show-mouse-cursor-position-in-selenium-2-tests-for-example-phpunit/35867777#35867777">stack + * overflow</a> + */ + public static void enableMouseDebug(final WebDriver webDriver) { + final String mousePointerScript = "// Create mouse following image.\n" + + "var seleniumFollowerImg = document.createElement(\"img\");\n" + + "\n" + + "// Set image properties.\n" + + "seleniumFollowerImg.setAttribute('src', 'data:image/png;base64,'\n" + + " + 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAQAAACGG/bgAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAA'\n" + + " + 'HsYAAB7GAZEt8iwAAAAHdElNRQfgAwgMIwdxU/i7AAABZklEQVQ4y43TsU4UURSH8W+XmYwkS2I0'\n" + + " + '9CRKpKGhsvIJjG9giQmliHFZlkUIGnEF7KTiCagpsYHWhoTQaiUUxLixYZb5KAAZZhbunu7O/PKf'\n" + + " + 'e+fcA+/pqwb4DuximEqXhT4iI8dMpBWEsWsuGYdpZFttiLSSgTvhZ1W/SvfO1CvYdV1kPghV68a3'\n" + + " + '0zzUWZH5pBqEui7dnqlFmLoq0gxC1XfGZdoLal2kea8ahLoqKXNAJQBT2yJzwUTVt0bS6ANqy1ga'\n" + + " + 'VCEq/oVTtjji4hQVhhnlYBH4WIJV9vlkXLm+10R8oJb79Jl1j9UdazJRGpkrmNkSF9SOz2T71s7M'\n" + + " + 'SIfD2lmmfjGSRz3hK8l4w1P+bah/HJLN0sys2JSMZQB+jKo6KSc8vLlLn5ikzF4268Wg2+pPOWW6'\n" + + " + 'ONcpr3PrXy9VfS473M/D7H+TLmrqsXtOGctvxvMv2oVNP+Av0uHbzbxyJaywyUjx8TlnPY2YxqkD'\n" + + " + 'dAAAAABJRU5ErkJggg==');\n" + + "seleniumFollowerImg.setAttribute('id', 'selenium_mouse_follower');\n" + + "seleniumFollowerImg.setAttribute('style', 'position: absolute; z-index: 99999999999; pointer-events: none;');\n" + + "\n" + + "// Add mouse follower to the web page.\n" + + "document.body.appendChild(seleniumFollowerImg);\n" + + "\n" + + "document.onmousemove = function(e) {\n" + + " const mousePointer = document.getElementById('selenium_mouse_follower');\n" + + " mousePointer.style.left = e.pageX + 'px';\n" + + " mousePointer.style.top = e.pageY + 'px';\n" + + "}"; + + ((JavascriptExecutor) webDriver).executeScript(mousePointerScript); + } + +} |