Provide input name when declaring service property as input
[sdc.git] / integration-tests / src / test / java / org / onap / sdc / frontend / ci / tests / pages / ResourcePropertiesAssignmentTab.java
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 Nordix Foundation
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19
20 package org.onap.sdc.frontend.ci.tests.pages;
21
22 import static org.junit.jupiter.api.Assertions.assertTrue;
23
24 import com.aventstack.extentreports.Status;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import java.util.stream.Collectors;
31 import lombok.AllArgsConstructor;
32 import lombok.Getter;
33 import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions;
34 import org.onap.sdc.frontend.ci.tests.utilities.LoaderHelper;
35 import org.onap.sdc.frontend.ci.tests.utilities.NotificationComponent;
36 import org.onap.sdc.frontend.ci.tests.utilities.NotificationComponent.NotificationType;
37 import org.openqa.selenium.By;
38 import org.openqa.selenium.WebDriver;
39 import org.openqa.selenium.WebElement;
40 import org.openqa.selenium.support.ui.Select;
41
42 /**
43  * Handles the Resource Properties Assignment Properties Tab UI actions
44  */
45 public class ResourcePropertiesAssignmentTab extends AbstractPageObject {
46
47     private WebElement wrappingElement;
48     private LoaderHelper loaderHelper;
49     private NotificationComponent notificationComponent;
50
51     public ResourcePropertiesAssignmentTab(final WebDriver webDriver) {
52         super(webDriver);
53         notificationComponent = new NotificationComponent(webDriver);
54         loaderHelper = new LoaderHelper(webDriver);
55     }
56
57     @Override
58     public void isLoaded() {
59        wrappingElement = waitForElementVisibility(XpathSelector.MAIN_DIV.getXpath());
60        waitForElementVisibility(XpathSelector.PROPERTIES_TAB.getXpath());
61        isPropertiesTableLoaded();
62     }
63
64     /**
65      * Waits for the table of properties to load
66      */
67     private void isPropertiesTableLoaded() {
68         waitForElementVisibility(By.xpath(XpathSelector.PROPERTIES_TABLE.getXpath()), 5);
69         waitForElementInvisibility(By.xpath(XpathSelector.NO_DATA_MESSAGE.getXpath()), 5);
70     }
71
72     /**
73      * Gets the software_version property values.
74      *
75      * @return the list of software versions found
76      */
77     public List<String> getSoftwareVersionProperty() {
78         isPropertiesTableLoaded();
79         final By swVersionCheckboxLocator = By.xpath(XpathSelector.SOFTWARE_VERSION_PROPERTY_CHECKBOX.getXpath());
80         waitForElementVisibility(swVersionCheckboxLocator, 5);
81
82         final List<String> softwareVersionList = new ArrayList<>();
83         final List<WebElement> elements = wrappingElement.findElements(By.xpath(XpathSelector.SOFTWARE_VERSION_INPUT.getXpath()));
84         for (final WebElement element : elements) {
85             softwareVersionList.add(element.getAttribute("value"));
86         }
87
88         return softwareVersionList;
89     }
90
91     /**
92      * Sets a property value
93      * @param propertyName the property name
94      * @param value the property value
95      */
96     public void setPropertyValue(final String propertyName, final Object value) {
97         if (value == null) {
98             return;
99         }
100
101         if (value instanceof String) {
102             setStringPropertyValue(propertyName, (String) value);
103             return;
104         }
105
106         if (value instanceof Integer) {
107             setStringPropertyValue(propertyName, ((Integer) value).toString());
108             return;
109         }
110
111         if (value instanceof Boolean) {
112             setBooleanPropertyValue(propertyName);
113             return;
114         }
115
116         if (value instanceof Map) {
117             setComplexPropertyValue(propertyName, value);
118             return;
119         }
120
121         if (value instanceof List) {
122             setComplexPropertyValue(propertyName, value);
123             return;
124         }
125
126         throw new UnsupportedOperationException("Cannot set property value of type: " + value.getClass());
127     }
128
129     /**
130      * Gets the property value. Only properties with a text value like string, float, integer or a list of string, float, integer are supported.
131      *
132      * @param propertyName the property name
133      * @return the value of the given property
134      */
135     public Object getPropertyValue(final String propertyName) {
136         isPropertiesTableLoaded();
137         final Map<String, String> propertyNamesAndTypes = getPropertyNamesAndTypes();
138         final String propertyType = propertyNamesAndTypes.get(propertyName);
139         final WebElement propertyRow = getPropertyRow(propertyName);
140         switch (propertyType) {
141             case "string":
142             case "float":
143             case "integer":
144                 final WebElement propertyInput = propertyRow.findElement(By.xpath(XpathSelector.INPUT_PROPERTY.getXpath(propertyName)));
145                 return propertyInput.getAttribute("value");
146             case "list":
147                 final List<WebElement> elements = propertyRow
148                     .findElements(By.xpath(XpathSelector.INPUT_PROPERTY_LIST_STRING_TYPE_VALUE.getXpath(propertyName)));
149                 return elements.stream().map(webElement -> webElement.getAttribute("value")).collect(Collectors.toList());
150             default:
151                 throw new UnsupportedOperationException(String.format("Retrieve value of property type %s is not yet supported", propertyType));
152         }
153     }
154
155     /**
156      * Checks if a property exists.
157      * @param propertyName the property name
158      * @return the value of the property
159      */
160     public boolean isPropertyPresent(final String propertyName) {
161         isPropertiesTableLoaded();
162         try {
163             waitForElementVisibility(By.xpath(XpathSelector.PROPERTY_CHECKBOX.getXpath(propertyName)), 5);
164         } catch (final Exception ignored) {
165             return false;
166         }
167         return true;
168     }
169
170     /**
171      * Saves a property
172      */
173     public void saveProperties() {
174         final WebElement saveBtn = waitForElementVisibility(By.xpath(XpathSelector.PROPERTY_SAVE_BTN.getXpath()));
175         assertTrue(saveBtn.isEnabled(), "Property save button should be enabled.");
176         saveBtn.click();
177         loaderHelper.waitForLoaderInvisibility(20);
178         notificationComponent.waitForNotification(NotificationType.SUCCESS, 20);
179     }
180
181     /**
182      * Adds a property
183      * @param propertiesMap the properties map to be added
184      */
185     public void addProperties(final Map<String, String> propertiesMap) {
186         isPropertiesTableLoaded();
187         propertiesMap.forEach((propertyName, propertyType) -> {
188             final By addPropertyButtonLocator = By.xpath(XpathSelector.PROPERTY_ADD_BTN.getXpath());
189             waitForElementVisibility(addPropertyButtonLocator, 30);
190             final WebElement addPropertyRightColumn = findElement(By.xpath(XpathSelector.PROPERTY_ADD_RIGHT_COLUMN_DIV.getXpath()));
191             final WebElement propertyAddButton = addPropertyRightColumn.findElement(addPropertyButtonLocator);
192             assertTrue(propertyAddButton.isDisplayed(), "Property add button should be enabled.");
193             propertyAddButton.click();
194             createProperty(propertyName, propertyType);
195             verifyProperty(propertyName);
196             ExtentTestActions.takeScreenshot(Status.INFO, "added-property",
197                 String.format("Property '%s' was created on component", propertyName));
198         });
199     }
200
201     /**
202      * Creates a map based on property names and data types
203      */
204     public Map<String, String> getPropertyNamesAndTypes() {
205         isPropertiesTableLoaded();
206         final Map<String, String> namesAndTypes = new HashMap<>();
207         final List<WebElement> names = findElements(By.xpath(XpathSelector.PROPERTY_NAMES.getXpath()));
208         final List<WebElement> types = findElements(By.xpath(XpathSelector.PROPERTY_TYPES.getXpath()));
209
210         for (int i = 0;i < names.size();i++) {
211             namesAndTypes.put(names.get(i).getAttribute("innerText"), types.get(i).getAttribute("innerText"));
212         }
213
214         return namesAndTypes;
215     }
216
217     /**
218      * Gets the property row element for the given propertyName
219      * @param propertyName the property name
220      * @return the property row element
221      */
222     private WebElement getPropertyRow(String propertyName) {
223         final By propertyCheckboxLocator = By.xpath(XpathSelector.PROPERTY_CHECKBOX.getXpath(propertyName));
224         final WebElement propertyCheckbox = waitForElementVisibility(propertyCheckboxLocator, 5);
225         return propertyCheckbox.findElement(By.xpath("./../../.."));
226     }
227
228     /**
229      * Sets a String value to a TOSCA property.
230      * @param propertyName the property name
231      * @param value property value to be set
232      */
233     private void setStringPropertyValue(final String propertyName, final String value) {
234         if (value == null) {
235             return;
236         }
237         isPropertiesTableLoaded();
238         getPropertyRow(propertyName).findElement(By.xpath(XpathSelector.INPUT_PROPERTY.getXpath(propertyName))).sendKeys(value);
239     }
240
241     /**
242      * Sets a boolean value to a TOSCA property.
243      * @param propertyName
244      */
245     private void setBooleanPropertyValue(final String propertyName) {
246         isPropertiesTableLoaded();
247         new Select(getPropertyRow(propertyName).findElement(By.xpath(XpathSelector.SELECT_INPUT_PROPERTY.getXpath(propertyName)))).
248             selectByVisibleText("TRUE");
249     }
250
251     /**
252      * Sets a complex property  type value to a TOSCA property. It handles List and Map
253      * @param propertyName the property name
254      * @param objectValue the property complex type value
255      */
256     private void setComplexPropertyValue(final String propertyName, final Object objectValue) {
257         if (objectValue == null) {
258             return;
259         }
260         isPropertiesTableLoaded();
261         final WebElement addToListLink = getPropertyRow(propertyName)
262             .findElement(By.xpath(XpathSelector.PROPERTY_ADD_VALUE_COMPLEX_TYPE.getXpath(propertyName)));
263         if (objectValue instanceof List) {
264             setValueFromList(propertyName, (List) objectValue, addToListLink);
265         }
266         if (objectValue instanceof Map) {
267             setValueFromMap(propertyName, (Map<?, ?>) objectValue, addToListLink);
268         }
269     }
270
271     /**
272      * Sets a value to a complex (List) property type.
273      * @param propertyName the property name
274      * @param values the List of values to be added to the given property name
275      * @param addToListLink the link to add the input value
276      */
277     private void setValueFromList(final String propertyName, final List<String> values, final WebElement addToListLink) {
278         final AtomicInteger inputIndex = new AtomicInteger(0);
279         values.forEach(value -> {
280             addToListLink.click();
281             final WebElement propertyInput = addToListLink.findElement(By.xpath(XpathSelector.INPUT_PROPERTY_COMPLEX_TYPE_VALUE.getXpath(
282                 String.valueOf(new StringBuilder(propertyName).append(".").append(inputIndex)))));
283             propertyInput.sendKeys(value);
284             inputIndex.getAndIncrement();
285         });
286     }
287
288     /**
289      * Sets a value to a complex (Map) property type.
290      * @param propertyName the property name
291      * @param values the Map of values to be added to the given property name
292      * @param addToListLink the link to add the input value
293      */
294     private void setValueFromMap(final String propertyName, final Map<?, ?> values, final WebElement addToListLink) {
295         final AtomicInteger inputIndex = new AtomicInteger(0);
296         values.forEach((key, value) -> {
297             addToListLink.click();
298             WebElement propertyInput;
299             // Add Key
300             propertyInput = addToListLink.findElement(By.xpath(XpathSelector.INPUT_PROPERTY_COMPLEX_TYPE_KEY.getXpath(
301                 String.valueOf(new StringBuilder(propertyName).append(".").append(inputIndex)))));
302             propertyInput.sendKeys(key.toString());
303             // Add Value
304             propertyInput = addToListLink.findElement(By.xpath(XpathSelector.INPUT_PROPERTY_COMPLEX_TYPE_VALUE.getXpath(
305                 String.valueOf(new StringBuilder(propertyName).append(".").append(inputIndex)))));
306             propertyInput.sendKeys(value.toString());
307             inputIndex.getAndIncrement();
308         });
309     }
310
311     /**
312      * Fills the creation property modal.
313      * @param propertyName the property name to be created
314      * @param propertyType the property type to be selected
315      */
316     private void createProperty(final String propertyName, final String propertyType) {
317         final AddPropertyModal addPropertyModal = new AddPropertyModal(webDriver);
318         addPropertyModal.isLoaded();
319         addPropertyModal.fillPropertyForm(propertyName, propertyType);
320         addPropertyModal.clickOnCreate();
321     }
322
323     /**
324      * Verifies if the added property is displayed on the UI.
325      * @param propertyName the property name to be found
326      */
327     private void verifyProperty(final String propertyName) {
328         final By propertyCheckboxLocator = By.xpath(XpathSelector.PROPERTY_CHECKBOX.getXpath(propertyName));
329         final WebElement propertyCheckbox = waitForElementVisibility(propertyCheckboxLocator, 5);
330         assertTrue(propertyCheckbox.isDisplayed(), String.format("%s Property should be displayed", propertyName));
331         assertTrue(this.getPropertyNamesAndTypes().containsKey(propertyName),
332             String.format("%s Property should be listed but found %s", propertyName, this.getPropertyNamesAndTypes().toString()));
333     }
334
335     /**
336      * select property
337      */
338     public void selectProperty(String propertyName){
339         isPropertyPresent(propertyName);
340         waitToBeClickable(By.xpath(ResourcePropertiesAssignmentTab.XpathSelector.PROPERTY_CHECKBOX.getXpath(propertyName))).click();
341     }
342
343     public void loadComponentInstanceProperties(final String instanceName){
344         waitToBeClickable(By.xpath(ResourcePropertiesAssignmentTab.XpathSelector.INSTANCE_SPAN.getXpath(instanceName))).click();
345     }
346
347     public void clickOnDeclareInput(final String inputName){
348         waitToBeClickable(By.xpath(ResourcePropertiesAssignmentTab.XpathSelector.DECLARE_INPUT_BTN.getXpath())).click();
349         declareInputWithSetInputName(inputName);
350     }
351
352     private void declareInputWithSetInputName(final String inputName) {
353         final By setInputNameLocator = By.xpath(XpathSelector.SET_INPUT_NAME_FIELD.getXpath());
354         final WebElement inputNameField = waitForElementVisibility(setInputNameLocator, 5);
355         inputNameField.sendKeys(inputName);
356         waitToBeClickable(By.xpath(XpathSelector.INPUT_NAME_SAVE_BTN.getXpath())).click();
357     }
358
359     public void loadCompositionTab(){
360         waitToBeClickable(By.xpath(ResourcePropertiesAssignmentTab.XpathSelector.COMPOSITION_TAB.getXpath())).click();
361     }
362
363     /**
364      * Enum that contains identifiers and xpath expressions to elements related to the enclosing page object.
365      */
366     @AllArgsConstructor
367     private enum XpathSelector {
368         MAIN_DIV("w-sdc-main-right-container", "//div[@class='%s']"),
369         PROPERTIES_TAB("//*[contains(@data-tests-id, 'Properties') and contains(@class, 'active')]"),
370         PROPERTIES_TABLE("properties-table", "//div[contains(@class,'%s')]"),
371         NO_DATA_MESSAGE("no-data", "//div[contains(@class,'%s') and text()='No data to display']"),
372         SOFTWARE_VERSION_PROPERTY_CHECKBOX("software_versions", "//checkbox[@data-tests-id='%s']"),
373         SOFTWARE_VERSION_INPUT("value-prop-software_versions", "//input[starts-with(@data-tests-id,'%s')]"),
374         PROPERTY_CHECKBOX("//checkbox[@data-tests-id='%s']"),
375         SET_INPUT_NAME_FIELD("//*[@id=\"myText\"]"),
376         PROPERTY_SAVE_BTN("properties-save-button", "//button[@data-tests-id='%s']"),
377         PROPERTY_ADD_RIGHT_COLUMN_DIV("right-column", "//div[@class='%s']"),
378         PROPERTY_ADD_BTN("add-btn", "//div[contains(@class,'%s')]"),
379         PROPERTY_ADD_VALUE_COMPLEX_TYPE("//a[contains(@data-tests-id, 'add-to-list-%s')]"),
380         INPUT_PROPERTY_COMPLEX_TYPE_KEY("//input[contains(@data-tests-id, 'value-prop-key-%s')]"),
381         INPUT_PROPERTY_COMPLEX_TYPE_VALUE("//input[contains(@data-tests-id, 'value-prop-%s')]"),
382         INPUT_PROPERTY_LIST_STRING_TYPE_VALUE("//input[starts-with(@data-tests-id, 'value-prop-%s')]"),
383         INPUT_PROPERTY("//input[@data-tests-id='value-prop-%s']"),
384         SELECT_INPUT_PROPERTY("//select[@data-tests-id='value-prop-%s']"),
385         PROPERTY_TYPES("//*[contains(@data-tests-id, 'propertyType')]"),
386         PROPERTY_NAMES("//*[contains(@data-tests-id, 'propertyName')]"),
387         DECLARE_INPUT_BTN("declare-button declare-input", "//button[@data-tests-id='%s']"),
388         INPUT_NAME_SAVE_BTN("//button[@data-tests-id='Save']"),
389         COMPOSITION_TAB("Composition", "//div[contains(@class,'tab') and contains(text(), '%s')]"),
390         INSTANCE_SPAN("//span[@data-tests-id='%s']");
391
392         @Getter
393         private String id;
394         private final String xpathFormat;
395
396         XpathSelector(final String xpathFormat) {
397             this.xpathFormat = xpathFormat;
398         }
399
400         public String getXpath() {
401             return String.format(xpathFormat, id);
402         }
403
404         public String getXpath(final Object... xpathParams) {
405             return String.format(xpathFormat, xpathParams);
406         }
407     }
408
409 }