From 63600cbfd177ece94e854446971d8e297e24d58f Mon Sep 17 00:00:00 2001 From: "andre.schmid" Date: Tue, 7 Sep 2021 18:29:51 +0100 Subject: [PATCH] Add integration tests for the ETSI 2.5.1 Model Adds integration tests for the ETSI SOL001 2.5.1 Model, that Onboards and Import a VSP created for the model, and check the resulting VF. Change-Id: I02e6ae86a544d98298cc3e4b270a84fb794bd204 Issue-ID: SDC-3719 Signed-off-by: andre.schmid --- .../data/providers/OnboardingDataProviders.java | 42 ++--- .../{XnfTypeEnum.java => PackageTypeEnum.java} | 2 +- .../ci/tests/utils/general/FileHandling.java | 99 ++++++----- .../ci/tests/utils/general/OnboardingUtils.java | 19 +- .../tests/dataProvider/OnbordingDataProviders.java | 16 +- .../ci/tests/datatypes/CategorySelect.java | 36 ++++ .../ci/tests/datatypes/ComponentProperty.java | 55 ++++++ .../sdc/frontend/ci/tests/datatypes/ModelName.java | 36 ++++ .../frontend/ci/tests/datatypes/VspCreateData.java | 39 +++++ .../ci/tests/datatypes/VspOnboardingProcedure.java | 26 +++ .../ci/tests/execute/sanity/EtsiModelUiTests.java | 195 +++++++++++++++++++++ .../execute/sanity/EtsiNetworkServiceUiTests.java | 65 ++++--- .../execute/sanity/EtsiOnboardVnfCnfUiTests.java | 10 +- .../ci/tests/execute/sanity/OnboardingFlowsUi.java | 14 +- .../tests/flow/CheckComponentPropertiesFlow.java | 86 +++++++++ .../ci/tests/flow/CheckEtsiNsPropertiesFlow.java | 92 ---------- .../sdc/frontend/ci/tests/flow/CreateVspFlow.java | 21 +-- .../ci/tests/pages/AbstractPageObject.java | 10 ++ .../ci/tests/pages/ResourceCreatePage.java | 14 +- .../pages/ResourcePropertiesAssignmentPage.java | 19 +- .../pages/ResourcePropertiesAssignmentTab.java | 37 +++- .../frontend/ci/tests/pages/VspCreationModal.java | 69 ++++++-- .../component/workspace/ToscaArtifactsPage.java | 4 +- .../Files/ETSI/Vnf-ETSI-SOL001-2.5.1.csar | Bin 0 -> 20197 bytes .../ci/testSuites/frontend/onapUiSanity.xml | 1 + openecomp-ui/src/nfvo-utils/i18n/en.json | 3 +- .../creation/SoftwareProductCreationView.jsx | 5 +- 27 files changed, 763 insertions(+), 252 deletions(-) rename integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/datatypes/enums/{XnfTypeEnum.java => PackageTypeEnum.java} (97%) create mode 100644 integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/CategorySelect.java create mode 100644 integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/ComponentProperty.java create mode 100644 integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/ModelName.java create mode 100644 integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/VspCreateData.java create mode 100644 integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/VspOnboardingProcedure.java create mode 100644 integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiModelUiTests.java create mode 100644 integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CheckComponentPropertiesFlow.java delete mode 100644 integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CheckEtsiNsPropertiesFlow.java create mode 100644 integration-tests/src/test/resources/Files/ETSI/Vnf-ETSI-SOL001-2.5.1.csar diff --git a/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/data/providers/OnboardingDataProviders.java b/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/data/providers/OnboardingDataProviders.java index 16c9521ac6..10d7b38899 100644 --- a/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/data/providers/OnboardingDataProviders.java +++ b/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/data/providers/OnboardingDataProviders.java @@ -30,7 +30,7 @@ import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; -import org.onap.sdc.backend.ci.tests.datatypes.enums.XnfTypeEnum; +import org.onap.sdc.backend.ci.tests.datatypes.enums.PackageTypeEnum; import org.onap.sdc.backend.ci.tests.utils.general.FileHandling; import org.onap.sdc.backend.ci.tests.utils.general.OnboardingUtils; import org.slf4j.Logger; @@ -40,7 +40,7 @@ import org.testng.annotations.DataProvider; public final class OnboardingDataProviders { private static final Logger LOGGER = LoggerFactory.getLogger(OnboardingDataProviders.class); - private static final String VNF_FILE_PATH = FileHandling.getXnfRepositoryPath(XnfTypeEnum.VNF); + private static final String VNF_FILE_PATH = FileHandling.getPackageRepositoryPath(PackageTypeEnum.VNF); private OnboardingDataProviders() { @@ -61,55 +61,55 @@ public final class OnboardingDataProviders { @DataProvider(name = "VNF_List", parallel = true) private static Object[][] vnfList() { - final List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(XnfTypeEnum.VNF); + final List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(PackageTypeEnum.VNF); LOGGER.debug(String.format("There are %s package file(s) to test", fileNamesFromFolder.size())); return provideData(fileNamesFromFolder, VNF_FILE_PATH); } @DataProvider(name = "PNF_List", parallel = true) private static Object[][] pnfList() { - return provideData(OnboardingUtils.getXnfNamesFileList(XnfTypeEnum.PNF), - FileHandling.getXnfRepositoryPath(XnfTypeEnum.PNF)); + return provideData(OnboardingUtils.getXnfNamesFileList(PackageTypeEnum.PNF), + FileHandling.getPackageRepositoryPath(PackageTypeEnum.PNF)); } @DataProvider(name = "CNF_List", parallel = true) private static Object[][] cnfList() { - final List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(XnfTypeEnum.CNF); + final List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(PackageTypeEnum.CNF); LOGGER.debug(String.format("There are %s package file(s) to test", fileNamesFromFolder.size())); - return provideData(fileNamesFromFolder, FileHandling.getXnfRepositoryPath(XnfTypeEnum.CNF)); + return provideData(fileNamesFromFolder, FileHandling.getPackageRepositoryPath(PackageTypeEnum.CNF)); } @DataProvider(name = "Invalid_CNF_List", parallel = true) private static Object[][] invalidCnfList() { - final List fileNamesFromFolder = OnboardingUtils.getInvalidXnfNamesFileList(XnfTypeEnum.CNF); + final List fileNamesFromFolder = OnboardingUtils.getInvalidXnfNamesFileList(PackageTypeEnum.CNF); LOGGER.debug(String.format("There are %s package file(s) to test", fileNamesFromFolder.size())); - return provideData(fileNamesFromFolder, FileHandling.getXnfRepositoryPath(XnfTypeEnum.CNF) + File.separator + OnboardingUtils.INVALID_XNFS_SUBPATH); + return provideData(fileNamesFromFolder, FileHandling.getPackageRepositoryPath(PackageTypeEnum.CNF) + File.separator + OnboardingUtils.INVALID_XNFS_SUBPATH); } @DataProvider(name = "CNF_Helm_Validator_List", parallel = true) private static Object[][] cnfForHelmValidatorList() { - final List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(XnfTypeEnum.CNF_HELM); + final List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(PackageTypeEnum.CNF_HELM); LOGGER.debug(String.format("There are %s package file(s) to test", fileNamesFromFolder.size())); - return provideData(fileNamesFromFolder, FileHandling.getXnfRepositoryPath(XnfTypeEnum.CNF_HELM)); + return provideData(fileNamesFromFolder, FileHandling.getPackageRepositoryPath(PackageTypeEnum.CNF_HELM)); } @DataProvider(name = "CNF_With_Warning_Helm_Validator_List", parallel = true) private static Object[][] cnfWithWarningForHelmValidatorList() { - final List fileNamesFromFolder = OnboardingUtils.getXnfNamesWithWarningsFileList(XnfTypeEnum.CNF_HELM); + final List fileNamesFromFolder = OnboardingUtils.getXnfNamesWithWarningsFileList(PackageTypeEnum.CNF_HELM); LOGGER.debug(String.format("There are %s package file(s) to test", fileNamesFromFolder.size())); - return provideData(fileNamesFromFolder, FileHandling.getXnfRepositoryPath(XnfTypeEnum.CNF_HELM) + File.separator + OnboardingUtils.WITH_WARNINGS_XNFS_SUBPATH); + return provideData(fileNamesFromFolder, FileHandling.getPackageRepositoryPath(PackageTypeEnum.CNF_HELM) + File.separator + OnboardingUtils.WITH_WARNINGS_XNFS_SUBPATH); } @DataProvider(name = "Invalid_CNF_Helm_Validator_List", parallel = true) private static Object[][] invalidCnfForHelmValidatorList() { - final List fileNamesFromFolder = OnboardingUtils.getInvalidXnfNamesFileList(XnfTypeEnum.CNF_HELM); + final List fileNamesFromFolder = OnboardingUtils.getInvalidXnfNamesFileList(PackageTypeEnum.CNF_HELM); LOGGER.debug(String.format("There are %s package file(s) to test", fileNamesFromFolder.size())); - return provideData(fileNamesFromFolder, FileHandling.getXnfRepositoryPath(XnfTypeEnum.CNF_HELM) + File.separator + OnboardingUtils.INVALID_XNFS_SUBPATH); + return provideData(fileNamesFromFolder, FileHandling.getPackageRepositoryPath(PackageTypeEnum.CNF_HELM) + File.separator + OnboardingUtils.INVALID_XNFS_SUBPATH); } @DataProvider(name = "Single_VNF", parallel = true) private static Object[][] singleVNF() { - final List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(XnfTypeEnum.VNF); + final List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(PackageTypeEnum.VNF); final List newList = new ArrayList<>(); newList.add(fileNamesFromFolder.get(0)); LOGGER.debug(String.format("There are %s zip file(s) to test", fileNamesFromFolder.size())); @@ -118,7 +118,7 @@ public final class OnboardingDataProviders { @DataProvider(name = "softwareInformationPnf", parallel = true) private static Object[][] softwareInformationPnf() { - final List pnfPackageFileNameList = OnboardingUtils.getXnfNamesFileList(XnfTypeEnum.PNF); + final List pnfPackageFileNameList = OnboardingUtils.getXnfNamesFileList(PackageTypeEnum.PNF); if (CollectionUtils.isEmpty(pnfPackageFileNameList)) { fail("Could not create softwareInformationPnf datasource"); } @@ -130,7 +130,7 @@ public final class OnboardingDataProviders { pnfPackage)); } - final String folderPath = FileHandling.getXnfRepositoryPath(XnfTypeEnum.PNF); + final String folderPath = FileHandling.getPackageRepositoryPath(PackageTypeEnum.PNF); final Object[][] parametersArray = new Object[1][]; parametersArray[0] = new Object[]{folderPath, softwareInformationPnfPackage.get(), Arrays.asList("5gDUv18.05.201", "5gDUv18.06.205")}; @@ -139,7 +139,7 @@ public final class OnboardingDataProviders { @DataProvider(name = "etsiVnfCnfOnboardPackages") private static Object[][] etsiVnf() { - final List vnfPackageFileNameList = OnboardingUtils.getXnfNamesFileList(XnfTypeEnum.ETSI); + final List vnfPackageFileNameList = OnboardingUtils.getXnfNamesFileList(PackageTypeEnum.ETSI); if (CollectionUtils.isEmpty(vnfPackageFileNameList)) { fail("Could not create etsiSingleVnfCnf datasource"); } @@ -153,7 +153,7 @@ public final class OnboardingDataProviders { etsiPackages)); } - final String folderPath = FileHandling.getXnfRepositoryPath(XnfTypeEnum.ETSI); + final String folderPath = FileHandling.getPackageRepositoryPath(PackageTypeEnum.ETSI); final Object[][] parametersArray = new Object[2][]; parametersArray[0] = new Object[]{folderPath, etsiPackages.get(0)}; parametersArray[1] = new Object[]{folderPath, etsiPackages.get(1)}; @@ -176,7 +176,7 @@ public final class OnboardingDataProviders { fail(String.format("Could not create vfcList datasource, one of the vfc file '%s' was not found", vfcFiles)); } - final String folderPath = FileHandling.getXnfRepositoryPath(XnfTypeEnum.VFC); + final String folderPath = FileHandling.getPackageRepositoryPath(PackageTypeEnum.VFC); final Object[][] parametersArray = new Object[2][]; parametersArray[0] = new Object[]{folderPath, vfcFiles.get(0)}; parametersArray[1] = new Object[]{folderPath, vfcFiles.get(1)}; diff --git a/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/datatypes/enums/XnfTypeEnum.java b/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/datatypes/enums/PackageTypeEnum.java similarity index 97% rename from integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/datatypes/enums/XnfTypeEnum.java rename to integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/datatypes/enums/PackageTypeEnum.java index 152612a77f..0e67cdaeb9 100644 --- a/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/datatypes/enums/XnfTypeEnum.java +++ b/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/datatypes/enums/PackageTypeEnum.java @@ -25,7 +25,7 @@ import lombok.Getter; @AllArgsConstructor @Getter -public enum XnfTypeEnum { +public enum PackageTypeEnum { CNF("CNF"), CNF_HELM("CNF_HELM"), diff --git a/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/utils/general/FileHandling.java b/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/utils/general/FileHandling.java index dcb3ecb14b..81ca398813 100644 --- a/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/utils/general/FileHandling.java +++ b/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/utils/general/FileHandling.java @@ -8,9 +8,9 @@ * 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. @@ -43,9 +43,9 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; import org.apache.commons.io.FileUtils; -import org.onap.sdc.backend.ci.tests.datatypes.enums.XnfTypeEnum; -import org.openecomp.sdc.be.model.DataTypeDefinition; import org.onap.sdc.backend.ci.tests.api.ComponentBaseTest; +import org.onap.sdc.backend.ci.tests.datatypes.enums.PackageTypeEnum; +import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.common.util.GeneralUtility; import org.yaml.snakeyaml.Yaml; @@ -59,9 +59,9 @@ public class FileHandling { Map map = (Map) yaml.load(inputStream); return map; } - + /** - * The method return map fetched objects by pattern from yaml file + * The method return map fetched objects by pattern from yaml file * @param yamlFile * @param pattern * @return @@ -72,19 +72,19 @@ public class FileHandling { Map objectMap = getObjectMapByPattern(yamlFileToMap, pattern); return objectMap; } - + @SuppressWarnings("unchecked") public static Map getObjectMapByPattern(Map parseUpdetedEnvFile, String pattern) { Map objectMap = null; - + Object objectUpdetedEnvFile = parseUpdetedEnvFile.get(pattern); if(objectUpdetedEnvFile instanceof HashMap){ objectMap = (Map) objectUpdetedEnvFile; } return objectMap; } - - + + public static Map parseDataTypesYaml(String filePath) throws Exception { @SuppressWarnings("unchecked") Map dataTypesMap = (Map) parseYamlFile(filePath); @@ -104,11 +104,11 @@ public class FileHandling { public static String getBasePath() { return System.getProperty("user.dir") + File.separator; } - + public static String getSdcVnfsPath() { return getBasePath() + Paths.get("..", "..", "sdc-vnfs").toString(); } - + public static String getDriversPath() { return getBasePath() + "src" + File.separator + "test" + File.separator + "resources" + File.separator + "ci" + File.separator + "drivers" + File.separator; @@ -117,7 +117,7 @@ public class FileHandling { public static String getResourcesFilesPath() { return getSdcVnfsPath()+ File.separator + "ui-tests" + File.separator + "Files" + File.separator; } - + public static String getResourcesEnvFilesPath() { return getBasePath() + File.separator + "src" + File.separator + "test" + File.separator + "resources" + File.separator + "Files" + File.separator + "ResourcesEnvFiles" +File.separator; @@ -132,14 +132,13 @@ public class FileHandling { return getCiFilesPath() + File.separator + "conf" + File.separator; } - - private static EnumMap XNF_REPOSITORY_PATHS_MAP = new EnumMap<>(Map.of( - XnfTypeEnum.PNF, getPnfRepositoryPath(), - XnfTypeEnum.CNF, getCnfRepositoryPath(), - XnfTypeEnum.CNF_HELM, getCnfRepositoryForHelmValidatorPath(), - XnfTypeEnum.VNF, getVnfRepositoryPath(), - XnfTypeEnum.ETSI, getEtsiRepositoryPath(), - XnfTypeEnum.VFC, getVfcRepositoryPath() + private static final EnumMap PACKAGE_REPOSITORY_PATHS_MAP = new EnumMap<>(Map.of( + PackageTypeEnum.PNF, getPnfRepositoryPath(), + PackageTypeEnum.CNF, getCnfRepositoryPath(), + PackageTypeEnum.CNF_HELM, getCnfRepositoryForHelmValidatorPath(), + PackageTypeEnum.VNF, getVnfRepositoryPath(), + PackageTypeEnum.ETSI, getEtsiRepositoryPath(), + PackageTypeEnum.VFC, getVfcRepositoryPath() )); public static String getVnfRepositoryPath() { @@ -162,14 +161,14 @@ public class FileHandling { private static String getVfcRepositoryPath() { return getFilePath("VFCs"); } - public static String getXnfRepositoryPath(XnfTypeEnum xnfTypeEnum) { - return XNF_REPOSITORY_PATHS_MAP.get(xnfTypeEnum); + public static String getPackageRepositoryPath(PackageTypeEnum packageTypeEnum) { + return PACKAGE_REPOSITORY_PATHS_MAP.get(packageTypeEnum); } public static String getPortMirroringRepositoryPath() { return getFilePath("PortMirroring"); } - + public static File getConfigFile(String configFileName) throws Exception { File configFile = new File(FileHandling.getBasePath() + File.separator + "conf" + File.separator + configFileName); if (!configFile.exists()) { @@ -182,13 +181,13 @@ public class FileHandling { try { File dir = new File(filepath); List filenames = new ArrayList(); - + FilenameFilter extensionFilter = new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(extension); } }; - + if (dir.isDirectory()) { for (File file : dir.listFiles(extensionFilter)) { filenames.add(file.getName()); @@ -206,13 +205,13 @@ public class FileHandling { List filenames = new ArrayList(); try { File dir = new File(filepath); - + FilenameFilter extensionFilter = new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(extension); } }; - + if (dir.isDirectory()) { for (File file : dir.listFiles(extensionFilter)) { filenames.add(file.getName()); @@ -225,18 +224,18 @@ public class FileHandling { } return filenames; } - + public static String[] getArtifactsFromZip(String filepath, String zipFilename){ try { ZipFile zipFile = new ZipFile(filepath + File.separator + zipFilename); Enumeration entries = zipFile.entries(); - + String[] artifactNames = new String[zipFile.size() - 1]; int i = 0; while(entries.hasMoreElements()){ ZipEntry nextElement = entries.nextElement(); - if (!nextElement.isDirectory()){ + if (!nextElement.isDirectory()){ if (!nextElement.getName().equals("MANIFEST.json")){ String name = nextElement.getName(); artifactNames[i++] = name; @@ -246,28 +245,28 @@ public class FileHandling { zipFile.close(); return artifactNames; } catch(ZipException zipEx) { - System.err.println("Error in zip file named : " + zipFilename); + System.err.println("Error in zip file named : " + zipFilename); zipEx.printStackTrace(); } catch (IOException e) { System.err.println("Unhandled exception : "); e.printStackTrace(); } - + return null; - + } public static List getFileNamesFromZip(String zipFileLocation){ try{ ZipFile zipFile = new ZipFile(zipFileLocation); Enumeration entries = zipFile.entries(); - + List artifactNames = new ArrayList<>(); int i = 0; while(entries.hasMoreElements()){ ZipEntry nextElement = entries.nextElement(); - if (!nextElement.isDirectory()){ + if (!nextElement.isDirectory()){ String name = nextElement.getName(); artifactNames.add(name); } @@ -276,7 +275,7 @@ public class FileHandling { return artifactNames; } catch(ZipException zipEx){ - System.err.println("Error in zip file named : " + zipFileLocation); + System.err.println("Error in zip file named : " + zipFileLocation); zipEx.printStackTrace(); } catch (IOException e) { System.err.println("Unhandled exception : "); @@ -284,7 +283,7 @@ public class FileHandling { } return null; } - + public static List getZipFileNamesFromFolder(String filepath) { List fileNamesListFromFolder = filterFileNamesListFromFolder(filepath, ".zip"); fileNamesListFromFolder.addAll(filterFileNamesListFromFolder(filepath, ".csar")); @@ -301,7 +300,7 @@ public class FileHandling { } return fileCounter; } - + /** * @param dirPath * @return last modified file name from dirPath directory @@ -336,7 +335,7 @@ public class FileHandling { System.out.println("Failed to clean " + dir); } } - + public static void createDirectory(String directoryPath) { File directory = new File(String.valueOf(directoryPath)); if (! directory.exists()){ @@ -385,7 +384,7 @@ public class FileHandling { return dir.getPath(); } - + public static boolean isFileDownloaded(String downloadPath, String fileName) { boolean flag = false; File dir = new File(downloadPath); @@ -396,13 +395,13 @@ public class FileHandling { } return flag; } - + public static String getMD5OfFile(File file) throws IOException { String content = FileUtils.readFileToString(file); String md5 = GeneralUtility.calculateMD5Base64EncodedByString(content); return md5; } - + public static File createEmptyFile(String fileToCreate) { File file= new File(fileToCreate); try { @@ -417,7 +416,7 @@ public class FileHandling { } return file; } - + public static File createEmptyFile(File fileToCreate) { try { if(fileToCreate.exists()){ @@ -431,9 +430,9 @@ public class FileHandling { } return fileToCreate; } - + public static void deleteFile(File file){ - + try{ if(file.exists()){ file.deleteOnExit(); @@ -446,8 +445,8 @@ public class FileHandling { } } - - + + /** * get file list from directory by extension array * @param directory @@ -455,10 +454,10 @@ public class FileHandling { * @return */ public static List getHeatAndHeatEnvArtifactsFromZip(File directory, String[] okFileExtensions){ - + List fileList = new ArrayList<>(); File[] files = directory.listFiles(); - + for (String extension : okFileExtensions){ for(File file : files){ if (file.getName().toLowerCase().endsWith(extension)){ diff --git a/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/utils/general/OnboardingUtils.java b/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/utils/general/OnboardingUtils.java index 6630345559..18ac63b349 100644 --- a/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/utils/general/OnboardingUtils.java +++ b/integration-tests/src/test/java/org/onap/sdc/backend/ci/tests/utils/general/OnboardingUtils.java @@ -24,8 +24,7 @@ package org.onap.sdc.backend.ci.tests.utils.general; import static org.onap.sdc.backend.ci.tests.utils.general.FileHandling.filterFileNamesListFromFolder; import java.io.File; -import java.nio.file.Paths; -import org.onap.sdc.backend.ci.tests.datatypes.enums.XnfTypeEnum; +import org.onap.sdc.backend.ci.tests.datatypes.enums.PackageTypeEnum; import org.onap.sdc.backend.ci.tests.datatypes.http.HttpHeaderEnum; import org.onap.sdc.backend.ci.tests.datatypes.http.HttpRequest; import org.onap.sdc.backend.ci.tests.datatypes.http.RestResponse; @@ -190,8 +189,8 @@ public class OnboardingUtils { * @return * The method returns XNF names list from Files directory under sdc repository */ - public static List getXnfNamesFileList(XnfTypeEnum xnfTypeEnum) { - String filepath = FileHandling.getXnfRepositoryPath(xnfTypeEnum); + public static List getXnfNamesFileList(PackageTypeEnum packageTypeEnum) { + String filepath = FileHandling.getPackageRepositoryPath(packageTypeEnum); List fileNamesFromFolder = FileHandling.getZipFileNamesFromFolder(filepath); fileNamesFromFolder.removeAll(excludeXnfList); return fileNamesFromFolder; @@ -201,8 +200,8 @@ public class OnboardingUtils { * @return * The method returns names list of invalid XNF packages from Files directory under sdc repository */ - public static List getInvalidXnfNamesFileList(XnfTypeEnum xnfTypeEnum) { - String filepath = FileHandling.getXnfRepositoryPath(xnfTypeEnum) + File.separator + INVALID_XNFS_SUBPATH; + public static List getInvalidXnfNamesFileList(PackageTypeEnum packageTypeEnum) { + String filepath = FileHandling.getPackageRepositoryPath(packageTypeEnum) + File.separator + INVALID_XNFS_SUBPATH; return FileHandling.getZipFileNamesFromFolder(filepath); } @@ -210,8 +209,8 @@ public class OnboardingUtils { * @return * The method returns names list of XNF packages with warnings from Files directory under sdc repository */ - public static List getXnfNamesWithWarningsFileList(XnfTypeEnum xnfTypeEnum) { - String filepath = FileHandling.getXnfRepositoryPath(xnfTypeEnum) + File.separator + WITH_WARNINGS_XNFS_SUBPATH; + public static List getXnfNamesWithWarningsFileList(PackageTypeEnum packageTypeEnum) { + String filepath = FileHandling.getPackageRepositoryPath(packageTypeEnum) + File.separator + WITH_WARNINGS_XNFS_SUBPATH; return FileHandling.getZipFileNamesFromFolder(filepath); } @@ -236,7 +235,7 @@ public class OnboardingUtils { * @return a list of VFC files */ public static List getVfcFilenameList() { - final String filepath = FileHandling.getXnfRepositoryPath(XnfTypeEnum.VFC); + final String filepath = FileHandling.getPackageRepositoryPath(PackageTypeEnum.VFC); List fileNamesListFromFolder = filterFileNamesListFromFolder(filepath, ".yml"); fileNamesListFromFolder.addAll(filterFileNamesListFromFolder(filepath, ".yaml")); return fileNamesListFromFolder; @@ -247,7 +246,7 @@ public class OnboardingUtils { * The method returns VNF names list from Files directory under sdc-vnfs repository excluding zip files that known as failed in tosca parser */ public static List getVnfNamesFileListExcludeToscaParserFailure() { - List fileNamesFromFolder = getXnfNamesFileList(XnfTypeEnum.VNF); + List fileNamesFromFolder = getXnfNamesFileList(PackageTypeEnum.VNF); fileNamesFromFolder.removeAll(excludeXnfListForToscaParser); return fileNamesFromFolder; } diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/dataProvider/OnbordingDataProviders.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/dataProvider/OnbordingDataProviders.java index 41b247c338..b49307e5dd 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/dataProvider/OnbordingDataProviders.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/dataProvider/OnbordingDataProviders.java @@ -21,7 +21,7 @@ package org.onap.sdc.frontend.ci.tests.dataProvider; -import org.onap.sdc.backend.ci.tests.datatypes.enums.XnfTypeEnum; +import org.onap.sdc.backend.ci.tests.datatypes.enums.PackageTypeEnum; import org.onap.sdc.backend.ci.tests.utils.general.OnboardingUtils; import org.onap.sdc.frontend.ci.tests.utilities.FileHandling; import org.openecomp.sdc.logging.api.Logger; @@ -52,25 +52,25 @@ public class OnbordingDataProviders { @DataProvider(name = "VNF_List", parallel = true) private static Object[][] VnfList() throws Exception { - List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(XnfTypeEnum.VNF); + List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(PackageTypeEnum.VNF); return provideData(fileNamesFromFolder, filepath); } @DataProvider(name = "CNF_List", parallel = true) private static Object[][] cnfList() { - List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(XnfTypeEnum.CNF); + List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(PackageTypeEnum.CNF); return provideData(fileNamesFromFolder, FileHandling.getCnfRepositoryPath()); } @DataProvider(name = "CNF_Helm_Validator_List", parallel = true) private static Object[][] cnfForHelmValidatorList() { - List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(XnfTypeEnum.CNF_HELM); + List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(PackageTypeEnum.CNF_HELM); return provideData(fileNamesFromFolder, FileHandling.getCnfForHelmValidatorRepositoryPath()); } @DataProvider(name = "CNF_With_Warning_Helm_Validator_List", parallel = true) private static Object[][] cnfWithWarningForHelmValidatorList() { - List fileNamesFromFolder = OnboardingUtils.getXnfNamesWithWarningsFileList(XnfTypeEnum.CNF_HELM); + List fileNamesFromFolder = OnboardingUtils.getXnfNamesWithWarningsFileList(PackageTypeEnum.CNF_HELM); Object[][] objects = provideData(fileNamesFromFolder, FileHandling.getCnfWithWarningForHelmValidatorRepositoryPath()); return objects; @@ -78,13 +78,13 @@ public class OnbordingDataProviders { @DataProvider(name = "Invalid_CNF_Helm_Validator_List", parallel = true) private static Object[][] invalidCnfForHelmValidatorList() { - List fileNamesFromFolder = OnboardingUtils.getInvalidXnfNamesFileList(XnfTypeEnum.CNF_HELM); + List fileNamesFromFolder = OnboardingUtils.getInvalidXnfNamesFileList(PackageTypeEnum.CNF_HELM); return provideData(fileNamesFromFolder, FileHandling.getInvalidCnfForHelmValidatorRepositoryPath()); } @DataProvider(name = "Invalid_CNF_List", parallel = true) private static Object[][] invalidCnfList() { - List fileNamesFromFolder = OnboardingUtils.getInvalidXnfNamesFileList(XnfTypeEnum.CNF); + List fileNamesFromFolder = OnboardingUtils.getInvalidXnfNamesFileList(PackageTypeEnum.CNF); return provideData(fileNamesFromFolder, FileHandling.getCnfRepositoryPath()); } @@ -110,7 +110,7 @@ public class OnbordingDataProviders { @DataProvider(name = "Single_Vsp_Test_Csar", parallel = true) private static Object[][] singleVspTestCsar() throws Exception { - List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(XnfTypeEnum.VNF); + List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(PackageTypeEnum.VNF); if (!fileNamesFromFolder.contains(VSP_VGW_CSAR)) { Assert.fail("Vsp Test file is not exits in the path"); } diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/CategorySelect.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/CategorySelect.java new file mode 100644 index 0000000000..41e5ba6dfd --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/CategorySelect.java @@ -0,0 +1,36 @@ +/* + * - + * ============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 lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Represents values in a category select html element + */ +@AllArgsConstructor +@Getter +public enum CategorySelect { + COMMON_NETWORK_RESOURCES("resourceNewCategory.network l4+.common network resources"); + + final String option; +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/ComponentProperty.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/ComponentProperty.java new file mode 100644 index 0000000000..4ee0e4ee84 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/ComponentProperty.java @@ -0,0 +1,55 @@ +/* + * - + * ============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.Map; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +/** + * Represents a property from a Component. + * + * @param the type of the property + */ +@Getter +@EqualsAndHashCode +public class ComponentProperty { + + private final String name; + @EqualsAndHashCode.Exclude + private final T value; + + public ComponentProperty(final String name) { + this.name = name; + this.value = null; + } + + public ComponentProperty(final String name, final T value) { + this.name = name; + if (!(value instanceof Map) && !(value instanceof String) && !(value instanceof List)) { + throw new UnsupportedOperationException("Properties should only be of type String, List or Map"); + } + this.value = value; + } + +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/ModelName.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/ModelName.java new file mode 100644 index 0000000000..d5df5df198 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/ModelName.java @@ -0,0 +1,36 @@ +/* + * - + * ============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 lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Stores default SDC model names + */ +@AllArgsConstructor +@Getter +public enum ModelName { + ETSI_SOL001_v2_5_1("ETSI SOL001 v2.5.1"); + + private String name; +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/VspCreateData.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/VspCreateData.java new file mode 100644 index 0000000000..ac0552289b --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/VspCreateData.java @@ -0,0 +1,39 @@ +/* + * - + * ============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 lombok.Data; + +/** + * Represents the data to create a VSP + */ +@Data +public class VspCreateData { + + private String name; + private String vendor; + private CategorySelect category; + private String description; + private VspOnboardingProcedure onboardingProcedure; + private String model; + +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/VspOnboardingProcedure.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/VspOnboardingProcedure.java new file mode 100644 index 0000000000..847798275a --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/datatypes/VspOnboardingProcedure.java @@ -0,0 +1,26 @@ +/* + * - + * ============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; + +public enum VspOnboardingProcedure { + MANUAL, NETWORK_PACKAGE +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiModelUiTests.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiModelUiTests.java new file mode 100644 index 0000000000..ce3254f296 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiModelUiTests.java @@ -0,0 +1,195 @@ +/* + * - + * ============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.execute.sanity; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.fail; + +import com.aventstack.extentreports.Status; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import org.onap.sdc.backend.ci.tests.datatypes.enums.PackageTypeEnum; +import org.onap.sdc.backend.ci.tests.utils.general.ElementFactory; +import org.onap.sdc.frontend.ci.tests.datatypes.CategorySelect; +import org.onap.sdc.frontend.ci.tests.datatypes.ComponentProperty; +import org.onap.sdc.frontend.ci.tests.datatypes.ModelName; +import org.onap.sdc.frontend.ci.tests.datatypes.VspCreateData; +import org.onap.sdc.frontend.ci.tests.datatypes.VspOnboardingProcedure; +import org.onap.sdc.frontend.ci.tests.exception.UnzipException; +import org.onap.sdc.frontend.ci.tests.execute.setup.DriverFactory; +import org.onap.sdc.frontend.ci.tests.execute.setup.SetupCDTest; +import org.onap.sdc.frontend.ci.tests.flow.CheckComponentPropertiesFlow; +import org.onap.sdc.frontend.ci.tests.flow.CreateResourceFromVspFlow; +import org.onap.sdc.frontend.ci.tests.flow.CreateVlmFlow; +import org.onap.sdc.frontend.ci.tests.flow.CreateVspFlow; +import org.onap.sdc.frontend.ci.tests.flow.DownloadCsarArtifactFlow; +import org.onap.sdc.frontend.ci.tests.flow.ImportVspFlow; +import org.onap.sdc.frontend.ci.tests.flow.exception.UiTestFlowRuntimeException; +import org.onap.sdc.frontend.ci.tests.pages.ComponentPage; +import org.onap.sdc.frontend.ci.tests.pages.ResourceCreatePage; +import org.onap.sdc.frontend.ci.tests.pages.ResourcePropertiesAssignmentPage; +import org.onap.sdc.frontend.ci.tests.pages.TopNavComponent; +import org.onap.sdc.frontend.ci.tests.pages.component.workspace.ToscaArtifactsPage; +import org.onap.sdc.frontend.ci.tests.utilities.FileHandling; +import org.openqa.selenium.WebDriver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; +import org.yaml.snakeyaml.Yaml; + +public class EtsiModelUiTests extends SetupCDTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(EtsiModelUiTests.class); + + private WebDriver webDriver; + + @Test + public void etsiNetworkServiceTest() throws UnzipException { + webDriver = DriverFactory.getDriver(); + + createVlm(); + final String resourceName = createVsp(); + ResourceCreatePage resourceCreatePage = importVsp(resourceName); + resourceCreatePage = createVf(resourceName, resourceCreatePage); + resourceCreatePage.isLoaded(); + final ResourcePropertiesAssignmentPage resourcePropertiesAssignmentPage = checkVfProperties(resourceCreatePage); + resourcePropertiesAssignmentPage.isLoaded(); + final DownloadCsarArtifactFlow downloadCsarArtifactFlow = downloadCsarArtifact(resourcePropertiesAssignmentPage); + final ToscaArtifactsPage toscaArtifactsPage = downloadCsarArtifactFlow.getLandedPage() + .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected ToscaArtifactsPage")); + toscaArtifactsPage.isLoaded(); + final String downloadedCsarName = toscaArtifactsPage.getDownloadedArtifactList().get(0); + checkCsarPackage(resourceName, downloadedCsarName); + toscaArtifactsPage.goToHomePage(); + } + + private ResourcePropertiesAssignmentPage checkVfProperties(final ComponentPage componentPage) { + final Set> componentPropertySet = Set.of( + new ComponentProperty<>("descriptor_id", "descriptor_id"), + new ComponentProperty<>("descriptor_version", "v1.0.1"), + new ComponentProperty<>("flavour_description", "flavour_description"), + new ComponentProperty<>("flavour_id", "flavour_id"), + new ComponentProperty<>("product_name", "product_name"), + new ComponentProperty<>("provider", "provider"), + new ComponentProperty<>("software_version", "v1.0.1"), + new ComponentProperty<>("vnfm_info", List.of("etsivnfm:v1.0.1")) + ); + + final CheckComponentPropertiesFlow checkComponentPropertiesFlow = new CheckComponentPropertiesFlow(componentPropertySet, webDriver); + final Optional run = checkComponentPropertiesFlow.run(componentPage); + return run.orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return ResourceCreatePage")); + } + + private ResourceCreatePage createVf(final String resourceName, final ResourceCreatePage resourceCreatePage) { + final CreateResourceFromVspFlow createResourceFlow = new CreateResourceFromVspFlow(webDriver, resourceName); + final ResourceCreatePage resourceCreatePage1 = createResourceFlow.run(resourceCreatePage) + .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return ResourceCreatePage")); + resourceCreatePage1.isLoaded(); + return resourceCreatePage1; + } + + private ResourceCreatePage importVsp(final String resourceName) { + final ImportVspFlow importVspFlow = new ImportVspFlow(webDriver, resourceName); + return importVspFlow.run() + .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected return ResourceCreatePage")); + } + + private String createVsp() { + final String resourceName = ElementFactory.addRandomSuffixToName(ElementFactory.getResourcePrefix()); + final String virtualLinkableVnf = "Vnf-ETSI-SOL001-2.5.1.csar"; + final String rootFolder = org.onap.sdc.backend.ci.tests.utils.general.FileHandling.getPackageRepositoryPath(PackageTypeEnum.ETSI); + var vspCreateData = new VspCreateData(); + vspCreateData.setName(resourceName); + vspCreateData.setCategory(CategorySelect.COMMON_NETWORK_RESOURCES); + vspCreateData.setDescription("description"); + vspCreateData.setOnboardingProcedure(VspOnboardingProcedure.NETWORK_PACKAGE); + vspCreateData.setModel(ModelName.ETSI_SOL001_v2_5_1.getName()); + final CreateVspFlow createVspFlow = new CreateVspFlow(webDriver, vspCreateData, virtualLinkableVnf, rootFolder); + createVspFlow.run(new TopNavComponent(webDriver)); + return resourceName; + } + + private void createVlm() { + getExtendTest().log(Status.INFO, "Creating a VLM"); + final CreateVlmFlow createVlmFlow = new CreateVlmFlow(webDriver); + createVlmFlow.run(); + } + + private DownloadCsarArtifactFlow downloadCsarArtifact(final ComponentPage componentPage) { + final DownloadCsarArtifactFlow downloadCsarArtifactFlow = new DownloadCsarArtifactFlow(webDriver); + downloadCsarArtifactFlow.run(componentPage); + return downloadCsarArtifactFlow; + } + + private void checkCsarPackage(final String serviceName, final String downloadedCsarName) throws UnzipException { + final String downloadFolderPath = getConfig().getDownloadAutomationFolder(); + final Map filesFromZip = FileHandling.getFilesFromZip(downloadFolderPath, downloadedCsarName); + final String mainDefinitionFileName = String.format("resource-%s-template.yml", serviceName.substring(0, 1).toUpperCase() + serviceName.substring(1).toLowerCase()); + final Path mainDefinitionFilePath = Path.of("Definitions", mainDefinitionFileName); + final byte[] mainDefinitionFile = filesFromZip.get(mainDefinitionFilePath.toString()); + final Map mainDefinitionYamlMap = loadYamlObject(mainDefinitionFile); + final Map topologyTemplateTosca = getMapEntry(mainDefinitionYamlMap, "topology_template"); + assertThat(String.format("'%s' should contain a topology_template entry", mainDefinitionFilePath), topologyTemplateTosca, notNullValue()); + final Map substitutionMappingsTosca = getMapEntry(topologyTemplateTosca, "substitution_mappings"); + assertThat(String.format("'%s' should contain a substitution_mappings entry", mainDefinitionFilePath), substitutionMappingsTosca, notNullValue()); + final var nodeType = (String) substitutionMappingsTosca.get("node_type"); + assertThat("substitution_mappings->node_type should be as expected", nodeType, is("org.openecomp.resource.EtsiDummyVnf")); + + final Map nodeTemplatesTosca = getMapEntry(topologyTemplateTosca, "node_templates"); + assertThat(String.format("'%s' should contain a node_templates entry", mainDefinitionFilePath), nodeTemplatesTosca, notNullValue()); + final var expectedNode1 = "external_connection_point"; + assertThat(String.format("'%s' should contain a node_template %s entry", mainDefinitionFilePath, expectedNode1), + nodeTemplatesTosca, hasKey(expectedNode1)); + final var expectedNode2 = "vnf_virtual_link"; + assertThat(String.format("'%s' should contain a node_template %s entry", mainDefinitionFilePath, expectedNode2), + nodeTemplatesTosca, hasKey(expectedNode2)); + final var notExpectedNode1 = "etsi_dummy_vnf"; + assertThat(String.format("'%s' should not contain a node_template %s entry, as it represents the substitutable node", + mainDefinitionFilePath, notExpectedNode1), + nodeTemplatesTosca, not(hasKey(notExpectedNode1)) + ); + } + + private Map getMapEntry(final Map yamlObj, final String entryName) { + try { + return (Map) yamlObj.get(entryName); + } catch (final Exception e) { + final String errorMsg = String.format("Could not get the '%s' entry.", entryName); + LOGGER.error(errorMsg, e); + fail(errorMsg + "Error message: " + e.getMessage()); + } + return null; + } + + private Map loadYamlObject(final byte[] mainDefinitionFileBytes) { + return new Yaml().load(new String(mainDefinitionFileBytes)); + } + +} + 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 b662148d8b..936fa6ee85 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 @@ -34,21 +34,26 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; +import java.util.Set; import org.apache.commons.io.FilenameUtils; import org.junit.jupiter.api.Assertions; import org.onap.sdc.backend.ci.tests.datatypes.enums.ComponentType; import org.onap.sdc.backend.ci.tests.datatypes.enums.ServiceCategoriesEnum; -import org.onap.sdc.backend.ci.tests.datatypes.enums.XnfTypeEnum; +import org.onap.sdc.backend.ci.tests.datatypes.enums.PackageTypeEnum; import org.onap.sdc.backend.ci.tests.utils.general.ElementFactory; +import org.onap.sdc.frontend.ci.tests.datatypes.CategorySelect; import org.onap.sdc.frontend.ci.tests.datatypes.ComponentData; +import org.onap.sdc.frontend.ci.tests.datatypes.ComponentProperty; import org.onap.sdc.frontend.ci.tests.datatypes.ServiceCreateData; +import org.onap.sdc.frontend.ci.tests.datatypes.VspCreateData; +import org.onap.sdc.frontend.ci.tests.datatypes.VspOnboardingProcedure; import org.onap.sdc.frontend.ci.tests.datatypes.composition.RelationshipInformation; import org.onap.sdc.frontend.ci.tests.exception.UnzipException; import org.onap.sdc.frontend.ci.tests.execute.setup.DriverFactory; import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions; import org.onap.sdc.frontend.ci.tests.execute.setup.SetupCDTest; import org.onap.sdc.frontend.ci.tests.flow.AddNodeToCompositionFlow; -import org.onap.sdc.frontend.ci.tests.flow.CheckEtsiNsPropertiesFlow; +import org.onap.sdc.frontend.ci.tests.flow.CheckComponentPropertiesFlow; import org.onap.sdc.frontend.ci.tests.flow.CreateResourceFromVspFlow; import org.onap.sdc.frontend.ci.tests.flow.CreateServiceFlow; import org.onap.sdc.frontend.ci.tests.flow.CreateVlmFlow; @@ -100,17 +105,17 @@ public class EtsiNetworkServiceUiTests extends SetupCDTest { final ServiceCreateData serviceCreateData = createServiceFormData(); final CreateServiceFlow createServiceFlow = createService(serviceCreateData); - final CheckEtsiNsPropertiesFlow checkEtsiNsPropertiesFlow = checkServiceProperties(); - ServiceComponentPage serviceComponentPage = checkEtsiNsPropertiesFlow.getLandedPage() + final CheckComponentPropertiesFlow checkComponentPropertiesFlow = checkServiceProperties(); + ComponentPage componentPage = checkComponentPropertiesFlow.getLandedPage() .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected ServiceComponentPage")); //adding node - addNodesAndCreateRelationships(resourceName, serviceCreateData, serviceComponentPage); + componentPage = addNodesAndCreateRelationships(resourceName, serviceCreateData, componentPage); final Map propertyMap = createPropertyToEditMap(); - editProperties(serviceComponentPage, propertyMap); + editProperties(componentPage, propertyMap); - final DownloadCsarArtifactFlow downloadCsarArtifactFlow = downloadCsarArtifact(serviceComponentPage); + final DownloadCsarArtifactFlow downloadCsarArtifactFlow = downloadCsarArtifact(componentPage); final ToscaArtifactsPage toscaArtifactsPage = downloadCsarArtifactFlow.getLandedPage() .orElseThrow(() -> new UiTestFlowRuntimeException("Missing expected ToscaArtifactsPage")); @@ -121,8 +126,8 @@ public class EtsiNetworkServiceUiTests extends SetupCDTest { checkEtsiNsPackage(createServiceFlow.getServiceCreateData().getName(), downloadedCsarName, propertyMap); } - private void addNodesAndCreateRelationships(final String resourceName, final ServiceCreateData serviceCreateData, - final ServiceComponentPage serviceComponentPage) { + private ServiceComponentPage addNodesAndCreateRelationships(final String resourceName, final ServiceCreateData serviceCreateData, + final ComponentPage componentPage) { //add first VF node final ComponentData parentComponent = new ComponentData(); parentComponent.setName(serviceCreateData.getName()); @@ -132,7 +137,7 @@ public class EtsiNetworkServiceUiTests extends SetupCDTest { resourceToAdd.setName(resourceName); resourceToAdd.setVersion("1.0"); resourceToAdd.setComponentType(ComponentType.RESOURCE); - CompositionPage compositionPage = serviceComponentPage.goToComposition(); + CompositionPage compositionPage = componentPage.goToComposition(); AddNodeToCompositionFlow addNodeToCompositionFlow = addNodeToComposition(parentComponent, resourceToAdd, compositionPage); virtualLinkableVnf1 = addNodeToCompositionFlow.getCreatedComponentInstance() .orElseThrow(() -> new UiTestFlowRuntimeException("Could not get the created component instance")); @@ -160,7 +165,9 @@ public class EtsiNetworkServiceUiTests extends SetupCDTest { createRelationshipFlow = new CreateRelationshipFlow(webDriver, relationshipInfoVirtualLinkToVnf2); compositionPage = (CompositionPage) createRelationshipFlow.run(compositionPage) .orElseThrow(() -> new UiTestFlowRuntimeException("Expecting a CompositionPage instance")); - compositionPage.goToServiceGeneral(); + final ServiceComponentPage serviceComponentPage = compositionPage.goToServiceGeneral(); + serviceComponentPage.isLoaded(); + return serviceComponentPage; } private ResourceCreatePage createAndCertifyVf(final String resourceName, final ResourceCreatePage resourceCreatePage) { @@ -212,8 +219,13 @@ public class EtsiNetworkServiceUiTests extends SetupCDTest { private String createVsp() { final String resourceName = ElementFactory.addRandomSuffixToName(ElementFactory.getResourcePrefix()); final String virtualLinkableVnf = "etsi-vnf-virtual-linkable.csar"; - final String rootFolder = org.onap.sdc.backend.ci.tests.utils.general.FileHandling.getXnfRepositoryPath(XnfTypeEnum.VNF); - final CreateVspFlow createVspFlow = new CreateVspFlow(webDriver, resourceName, virtualLinkableVnf, rootFolder); + final String rootFolder = org.onap.sdc.backend.ci.tests.utils.general.FileHandling.getPackageRepositoryPath(PackageTypeEnum.VNF); + var vspCreateData = new VspCreateData(); + vspCreateData.setName(resourceName); + vspCreateData.setCategory(CategorySelect.COMMON_NETWORK_RESOURCES); + vspCreateData.setDescription("description"); + vspCreateData.setOnboardingProcedure(VspOnboardingProcedure.NETWORK_PACKAGE); + final CreateVspFlow createVspFlow = new CreateVspFlow(webDriver, vspCreateData, virtualLinkableVnf, rootFolder); createVspFlow.run(new TopNavComponent(webDriver)); return resourceName; } @@ -238,20 +250,31 @@ public class EtsiNetworkServiceUiTests extends SetupCDTest { return createServiceFlow; } - private CheckEtsiNsPropertiesFlow checkServiceProperties() { - final CheckEtsiNsPropertiesFlow checkEtsiNsPropertiesFlow = new CheckEtsiNsPropertiesFlow(webDriver); - checkEtsiNsPropertiesFlow.run(); - return checkEtsiNsPropertiesFlow; + private CheckComponentPropertiesFlow checkServiceProperties() { + final Set> componentPropertySet = Set.of( + new ComponentProperty<>("descriptor_id"), + new ComponentProperty<>("designer"), + new ComponentProperty<>("flavour_id"), + new ComponentProperty<>("invariant_id"), + new ComponentProperty<>("name"), + new ComponentProperty<>("ns_profile"), + new ComponentProperty<>("version"), + new ComponentProperty<>("service_availability_level") + ); + + final var checkVfPropertiesFlow = new CheckComponentPropertiesFlow(componentPropertySet, webDriver); + checkVfPropertiesFlow.run(); + return checkVfPropertiesFlow; } - private void editProperties(final ServiceComponentPage serviceComponentPage, final Map propertyMap) { + private void editProperties(final ComponentPage componentPage, final Map propertyMap) { final EditComponentPropertiesFlow editComponentPropertiesFlow = new EditComponentPropertiesFlow(webDriver, propertyMap); - editComponentPropertiesFlow.run(serviceComponentPage); + editComponentPropertiesFlow.run(componentPage); } - private DownloadCsarArtifactFlow downloadCsarArtifact(final ServiceComponentPage serviceComponentPage) { + private DownloadCsarArtifactFlow downloadCsarArtifact(final ComponentPage componentPage) { final DownloadCsarArtifactFlow downloadCsarArtifactFlow = new DownloadCsarArtifactFlow(webDriver); - downloadCsarArtifactFlow.run(serviceComponentPage); + downloadCsarArtifactFlow.run(componentPage); return downloadCsarArtifactFlow; } diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiOnboardVnfCnfUiTests.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiOnboardVnfCnfUiTests.java index c149b24907..40b6990a67 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiOnboardVnfCnfUiTests.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/execute/sanity/EtsiOnboardVnfCnfUiTests.java @@ -32,8 +32,11 @@ import org.onap.sdc.backend.ci.tests.data.providers.OnboardingDataProviders; import org.onap.sdc.backend.ci.tests.datatypes.enums.ComponentType; import org.onap.sdc.backend.ci.tests.datatypes.enums.ServiceCategoriesEnum; import org.onap.sdc.backend.ci.tests.utils.general.ElementFactory; +import org.onap.sdc.frontend.ci.tests.datatypes.CategorySelect; import org.onap.sdc.frontend.ci.tests.datatypes.ComponentData; import org.onap.sdc.frontend.ci.tests.datatypes.ServiceCreateData; +import org.onap.sdc.frontend.ci.tests.datatypes.VspCreateData; +import org.onap.sdc.frontend.ci.tests.datatypes.VspOnboardingProcedure; import org.onap.sdc.frontend.ci.tests.exception.UnzipException; import org.onap.sdc.frontend.ci.tests.execute.setup.DriverFactory; import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions; @@ -96,7 +99,12 @@ public class EtsiOnboardVnfCnfUiTests extends SetupCDTest { * @param vnfCnfFile file to be onboarded */ private void runOnboardEtsiVnfCnf(final String resourceName, final String rootFolder, final String vnfCnfFile) { - final CreateVspFlow createVspFlow = new CreateVspFlow(webDriver, resourceName, vnfCnfFile, rootFolder); + var vspCreateData = new VspCreateData(); + vspCreateData.setName(resourceName); + vspCreateData.setCategory(CategorySelect.COMMON_NETWORK_RESOURCES); + vspCreateData.setDescription("description"); + vspCreateData.setOnboardingProcedure(VspOnboardingProcedure.NETWORK_PACKAGE); + final CreateVspFlow createVspFlow = new CreateVspFlow(webDriver, vspCreateData, vnfCnfFile, rootFolder); createVspFlow.run(topNavComponent); final ImportVspFlow importVspFlow = new ImportVspFlow(webDriver, resourceName); ResourceCreatePage resourceCreatePage = importVspFlow.run() 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 5d1b3b3a60..84f25d1cd9 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 @@ -41,7 +41,7 @@ import org.onap.sdc.backend.ci.tests.datatypes.ServiceReqDetails; import org.onap.sdc.backend.ci.tests.datatypes.VendorLicenseModel; import org.onap.sdc.backend.ci.tests.datatypes.VendorSoftwareProductObject; import org.onap.sdc.backend.ci.tests.datatypes.enums.UserRoleEnum; -import org.onap.sdc.backend.ci.tests.datatypes.enums.XnfTypeEnum; +import org.onap.sdc.backend.ci.tests.datatypes.enums.PackageTypeEnum; import org.onap.sdc.backend.ci.tests.utils.Utils; import org.onap.sdc.backend.ci.tests.utils.general.AtomicOperationUtils; import org.onap.sdc.backend.ci.tests.utils.general.ElementFactory; @@ -51,7 +51,10 @@ import org.onap.sdc.backend.ci.tests.utils.general.VendorSoftwareProductRestUtil 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.CategorySelect; import org.onap.sdc.frontend.ci.tests.datatypes.DataTestIdEnum; +import org.onap.sdc.frontend.ci.tests.datatypes.VspCreateData; +import org.onap.sdc.frontend.ci.tests.datatypes.VspOnboardingProcedure; 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; @@ -147,7 +150,7 @@ public class OnboardingFlowsUi extends SetupCDTest { @Test public void onboardVNFTestSanity() throws Exception { - List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(XnfTypeEnum.VNF); + List fileNamesFromFolder = OnboardingUtils.getXnfNamesFileList(PackageTypeEnum.VNF); String vnfFile = fileNamesFromFolder.get(0); ResourceReqDetails resourceReqDetails = ElementFactory.getDefaultResource(); ServiceReqDetails serviceReqDetails = ElementFactory.getDefaultService(); @@ -391,7 +394,12 @@ public class OnboardingFlowsUi extends SetupCDTest { String.format("Creating VSP '%s' by onboarding package '%s' with software version '%s'", resourceName, pnfFile, swVersionsToString)); final WebDriver webDriver = DriverFactory.getDriver(); - final CreateVspFlow createVspFlow = new CreateVspFlow(webDriver, resourceName, pnfFile, rootFolder); + var vspCreateData = new VspCreateData(); + vspCreateData.setName(resourceName); + vspCreateData.setCategory(CategorySelect.COMMON_NETWORK_RESOURCES); + vspCreateData.setDescription("description"); + vspCreateData.setOnboardingProcedure(VspOnboardingProcedure.NETWORK_PACKAGE); + final CreateVspFlow createVspFlow = new CreateVspFlow(webDriver, vspCreateData, pnfFile, rootFolder); createVspFlow.run(new TopNavComponent(webDriver)); final ImportVspFlow importVspFlow = new ImportVspFlow(webDriver, resourceName); diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CheckComponentPropertiesFlow.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CheckComponentPropertiesFlow.java new file mode 100644 index 0000000000..5796c846d1 --- /dev/null +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CheckComponentPropertiesFlow.java @@ -0,0 +1,86 @@ +/* + * ============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 static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import com.aventstack.extentreports.Status; +import java.util.Optional; +import java.util.Set; +import org.onap.sdc.frontend.ci.tests.datatypes.ComponentProperty; +import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions; +import org.onap.sdc.frontend.ci.tests.pages.ComponentPage; +import org.onap.sdc.frontend.ci.tests.pages.PageObject; +import org.onap.sdc.frontend.ci.tests.pages.ResourcePropertiesAssignmentPage; +import org.openqa.selenium.WebDriver; + +/** + * Check the properties in a Component + */ +public class CheckComponentPropertiesFlow extends AbstractUiTestFlow { + + private final Set> componentPropertySet; + private ResourcePropertiesAssignmentPage resourcePropertiesAssignmentPage; + + public CheckComponentPropertiesFlow(final Set> componentPropertySet, final WebDriver webDriver) { + super(webDriver); + this.componentPropertySet = componentPropertySet; + } + + /** + * Starts the flow in a {@link ComponentPage}. From there go to the {@link ResourcePropertiesAssignmentPage} and check for the + * properties. It does not require any page object, but can receive a {@link ComponentPage} + * + * @param pageObjects any required page object for the flow + * @return the {@link ComponentPage} + */ + @Override + public Optional run(final PageObject... pageObjects) { + extendTest.log(Status.INFO, "Checking component properties"); + final ComponentPage componentPage = getParameter(pageObjects, ComponentPage.class).orElseGet(() -> new ComponentPage(webDriver)); + componentPage.isLoaded(); + resourcePropertiesAssignmentPage = componentPage.goToPropertiesAssignment(); + resourcePropertiesAssignmentPage.isLoaded(); + if (componentPropertySet.isEmpty()) { + extendTest.log(Status.INFO, "Finished checking component properties. No properties were given."); + return Optional.of(resourcePropertiesAssignmentPage); + } + componentPropertySet.forEach(this::checkProperty); + ExtentTestActions.takeScreenshot(Status.INFO, "vf-properties-present", "VF properties are present"); + extendTest.log(Status.INFO, "Finished checking component properties"); + return Optional.of(resourcePropertiesAssignmentPage); + } + + @Override + public Optional getLandedPage() { + return Optional.ofNullable(resourcePropertiesAssignmentPage); + } + + private void checkProperty(final ComponentProperty componentProperty) { + extendTest.log(Status.INFO, String.format("Checking property '%s'", componentProperty)); + assertThat(String.format("'%s' property should be present", componentProperty), + resourcePropertiesAssignmentPage.isPropertyPresent(componentProperty.getName()), is(true)); + if (componentProperty.getValue() != null) { + final Object propertyValue = resourcePropertiesAssignmentPage.getPropertyValue(componentProperty.getName()); + assertThat("'%s' property should have the expected value", propertyValue, is(componentProperty.getValue())); + } + } +} diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CheckEtsiNsPropertiesFlow.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CheckEtsiNsPropertiesFlow.java deleted file mode 100644 index 343c7f670a..0000000000 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/flow/CheckEtsiNsPropertiesFlow.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * ============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 static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; - -import com.aventstack.extentreports.Status; -import java.util.Optional; -import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions; -import org.onap.sdc.frontend.ci.tests.pages.PageObject; -import org.onap.sdc.frontend.ci.tests.pages.ResourceLeftSideMenu; -import org.onap.sdc.frontend.ci.tests.pages.ResourcePropertiesAssignmentPage; -import org.onap.sdc.frontend.ci.tests.pages.ResourceWorkspaceTopBarComponent; -import org.onap.sdc.frontend.ci.tests.pages.ServiceComponentPage; -import org.onap.sdc.frontend.ci.tests.pages.TopNavComponent; -import org.openqa.selenium.WebDriver; - -/** - * Check the required properties in a Service of category ETSI NFV Network Service. - */ -public class CheckEtsiNsPropertiesFlow extends AbstractUiTestFlow { - - private ServiceComponentPage serviceComponentPage; - - public CheckEtsiNsPropertiesFlow(final WebDriver webDriver) { - super(webDriver); - } - - /** - * Starts the flow in the {@link ServiceComponentPage}. From there go to the {@link ResourcePropertiesAssignmentPage} and check for the - * properties. It does not require any page object, but can receive: - *
    - *
  • {@link ServiceComponentPage} or its children:
  • - *
      - *
    • {@link TopNavComponent}
    • - *
    • {@link ResourceLeftSideMenu}
    • - *
    • {@link ResourceWorkspaceTopBarComponent}
    • - *
    - *
- * - * @param pageObjects any required page object for the flow - * @return the {@link ServiceComponentPage} - */ - @Override - public Optional run(final PageObject... pageObjects) { - extendTest.log(Status.INFO, "Checking ETSI NFV Network Service properties"); - serviceComponentPage = getParameter(pageObjects, ServiceComponentPage.class).orElseGet(() -> new ServiceComponentPage(webDriver)); - serviceComponentPage.isLoaded(); - final ResourcePropertiesAssignmentPage resourcePropertiesAssignmentPage = serviceComponentPage.goToPropertiesAssignment(); - checkProperty(resourcePropertiesAssignmentPage, "descriptor_id"); - checkProperty(resourcePropertiesAssignmentPage, "designer"); - checkProperty(resourcePropertiesAssignmentPage, "flavour_id"); - checkProperty(resourcePropertiesAssignmentPage, "invariant_id"); - checkProperty(resourcePropertiesAssignmentPage, "name"); - checkProperty(resourcePropertiesAssignmentPage, "ns_profile"); - checkProperty(resourcePropertiesAssignmentPage, "version"); - checkProperty(resourcePropertiesAssignmentPage, "ns_profile"); - checkProperty(resourcePropertiesAssignmentPage, "service_availability_level"); - ExtentTestActions.takeScreenshot(Status.INFO, "etsi-ns-properties-present", "ETSI NS properties are present"); - extendTest.log(Status.INFO, "Finished checking ETSI NFV Network Service properties"); - return Optional.of(serviceComponentPage); - } - - @Override - public Optional getLandedPage() { - return Optional.ofNullable(serviceComponentPage); - } - - private void checkProperty(final ResourcePropertiesAssignmentPage resourcePropertiesAssignmentPage, final String propertyName) { - extendTest.log(Status.INFO, String.format("Checking property '%s'", propertyName)); - assertThat(String.format("'%s' property should be present", propertyName), - resourcePropertiesAssignmentPage.isPropertyPresent(propertyName), is(true)); - } -} 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 948b8650c8..4c9d91ce0f 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 @@ -24,6 +24,7 @@ import static org.hamcrest.core.Is.is; import com.aventstack.extentreports.Status; import java.util.Optional; +import org.onap.sdc.frontend.ci.tests.datatypes.VspCreateData; import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions; import org.onap.sdc.frontend.ci.tests.pages.OnboardHomePage; import org.onap.sdc.frontend.ci.tests.pages.PageObject; @@ -38,14 +39,14 @@ import org.openqa.selenium.WebDriver; */ public class CreateVspFlow extends AbstractUiTestFlow { - private final String resourceName; + private final VspCreateData vspCreateData; private final String packageFile; private final String rootFolder; private HomePage homePage; - public CreateVspFlow(final WebDriver webDriver, final String resourceName, final String packageFile, final String rootFolder) { + public CreateVspFlow(final WebDriver webDriver, final VspCreateData vspCreateData, final String packageFile, final String rootFolder) { super(webDriver); - this.resourceName = resourceName; + this.vspCreateData = vspCreateData; this.packageFile = packageFile; this.rootFolder = rootFolder; } @@ -53,7 +54,7 @@ public class CreateVspFlow extends AbstractUiTestFlow { @Override public Optional run(final PageObject... pageObjects) { extendTest.log(Status.INFO, - String.format("Creating VSP '%s' by onboarding ETSI VNF/CNF package '%s'", resourceName, packageFile)); + String.format("Creating VSP '%s' by onboarding ETSI VNF/CNF package '%s'", vspCreateData.getName(), packageFile)); final TopNavComponent topNavComponent = findParameter(pageObjects, TopNavComponent.class); extendTest.log(Status.INFO, "Accessing the Onboard Home Page"); topNavComponent.isLoaded(); @@ -93,15 +94,15 @@ public class CreateVspFlow extends AbstractUiTestFlow { extendTest.log(Status.INFO, "Creating a new VSP"); final VspCreationModal vspCreationModal = onboardHomePage.clickOnCreateNewVsp(); vspCreationModal.isLoaded(); - vspCreationModal.fillCreationForm(resourceName); + vspCreationModal.fillCreationForm(vspCreateData); ExtentTestActions.takeScreenshot(Status.INFO, "vsp-creation-form", "Creating VSP with given information"); final SoftwareProductOnboarding softwareProductOnboarding = vspCreationModal.clickOnCreate(); softwareProductOnboarding.isLoaded(); - extendTest.log(Status.INFO, String.format("VSP '%s' created", resourceName)); + extendTest.log(Status.INFO, String.format("VSP '%s' created", vspCreateData.getName())); final String actualResourceName = softwareProductOnboarding.getResourceName(); - assertThat(String.format("Should be in the Software Product '%s' page", resourceName), - actualResourceName, is(resourceName)); + assertThat(String.format("Should be in the Software Product '%s' page", vspCreateData.getName()), + actualResourceName, is(vspCreateData.getName())); return softwareProductOnboarding; } @@ -112,12 +113,12 @@ public class CreateVspFlow extends AbstractUiTestFlow { */ private void uploadPackage(final SoftwareProductOnboarding softwareProductOnboarding) { extendTest.log(Status.INFO, - String.format("Uploading package '%s' to VSP '%s'", packageFile, resourceName) + String.format("Uploading package '%s' to VSP '%s'", packageFile, vspCreateData.getName()) ); softwareProductOnboarding.uploadFile(rootFolder + packageFile); softwareProductOnboarding.attachmentScreenIsLoaded(); extendTest.log(Status.INFO, - String.format("Package '%s' was uploaded to VSP '%s'.", packageFile, resourceName) + String.format("Package '%s' was uploaded to VSP '%s'.", packageFile, vspCreateData.getName()) ); } diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AbstractPageObject.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AbstractPageObject.java index 1ad049ff13..47b655924c 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AbstractPageObject.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/AbstractPageObject.java @@ -74,6 +74,16 @@ public abstract class AbstractPageObject implements PageObject { return webDriver.findElement(locator); } + /** + * Find an element based on the provided xpath. + * + * @param xpath the xpath expression to search for the element + * @return the WebElement if found, otherwise throws an exception + */ + protected WebElement findElement(final String xpath) { + return webDriver.findElement(By.xpath(xpath)); + } + /** * Find elements based on the provided locator. * 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 686f63c552..196c560429 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 @@ -23,18 +23,13 @@ import java.util.List; import lombok.AllArgsConstructor; import lombok.Getter; import org.onap.sdc.frontend.ci.tests.datatypes.ResourceCreateData; -import org.onap.sdc.frontend.ci.tests.pages.component.workspace.CompositionPage; -import org.onap.sdc.frontend.ci.tests.pages.component.workspace.ToscaArtifactsPage; import org.onap.sdc.frontend.ci.tests.utilities.LoaderHelper; import org.onap.sdc.frontend.ci.tests.utilities.NotificationComponent; -import org.onap.sdc.frontend.ci.tests.utilities.NotificationComponent.NotificationType; import org.openqa.selenium.By; import org.openqa.selenium.Keys; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.Select; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Handles the Resource Create Page UI actions @@ -78,6 +73,15 @@ public class ResourceCreatePage extends ComponentPage { setInputField(By.xpath(XpathSelector.NAME_INPUT.getXpath()), name); } + /** + * Gets the name field value. + * + * @return the name field value + */ + public String getName() { + return findElement(XpathSelector.NAME_INPUT.getXpath()).getText(); + } + private void setCategory(final String category) { setSelectField(By.xpath(XpathSelector.CATEGORY_SELECT.getXpath()), category); } diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentPage.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentPage.java index 12ac5e492a..cb4345c7cc 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentPage.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentPage.java @@ -22,18 +22,16 @@ package org.onap.sdc.frontend.ci.tests.pages; import com.aventstack.extentreports.Status; import java.util.List; import java.util.Map; - +import lombok.AllArgsConstructor; +import lombok.Getter; import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; -import lombok.AllArgsConstructor; -import lombok.Getter; - /** * Handles the Resource Properties Assignment Page UI actions. */ -public class ResourcePropertiesAssignmentPage extends AbstractPageObject { +public class ResourcePropertiesAssignmentPage extends ComponentPage { private ResourcePropertiesAssignmentTab resourcePropertiesAssignmentTab; private ResourcePropertiesAssignmentInputTab resourcePropertiesAssignmentInputTab; @@ -46,6 +44,7 @@ public class ResourcePropertiesAssignmentPage extends AbstractPageObject { @Override public void isLoaded() { + super.isLoaded(); waitForElementVisibility((By.xpath(XpathSelector.MAIN_DIV.getXpath()))); waitForElementVisibility(By.xpath(XpathSelector.TITLE_DIV.getXpath())); resourcePropertiesAssignmentTab.isLoaded(); @@ -75,6 +74,16 @@ public class ResourcePropertiesAssignmentPage extends AbstractPageObject { resourcePropertiesAssignmentTab.setPropertyValue(propertyName, value); } + /** + * Retrieves a property value. + * + * @param propertyName the property name + * @return the property value + */ + public Object getPropertyValue(final String propertyName) { + return resourcePropertiesAssignmentTab.getPropertyValue(propertyName); + } + public boolean isPropertyPresent(final String propertyName) { return resourcePropertiesAssignmentTab.isPropertyPresent(propertyName); } diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentTab.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentTab.java index 32a20dd138..81ce7ffec1 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentTab.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/ResourcePropertiesAssignmentTab.java @@ -21,12 +21,15 @@ package org.onap.sdc.frontend.ci.tests.pages; import static org.junit.jupiter.api.Assertions.assertTrue; +import com.aventstack.extentreports.Status; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; - +import java.util.stream.Collectors; +import lombok.AllArgsConstructor; +import lombok.Getter; import org.onap.sdc.frontend.ci.tests.execute.setup.ExtentTestActions; import org.onap.sdc.frontend.ci.tests.utilities.LoaderHelper; import org.onap.sdc.frontend.ci.tests.utilities.NotificationComponent; @@ -36,11 +39,6 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.Select; -import com.aventstack.extentreports.Status; - -import lombok.AllArgsConstructor; -import lombok.Getter; - /** * Handles the Resource Properties Assignment Properties Tab UI actions */ @@ -128,6 +126,32 @@ public class ResourcePropertiesAssignmentTab extends AbstractPageObject { throw new UnsupportedOperationException("Cannot set property value of type: " + value.getClass()); } + /** + * Gets the property value. Only properties with a text value like string, float, integer or a list of string, float, integer are supported. + * + * @param propertyName the property name + * @return the value of the given property + */ + public Object getPropertyValue(final String propertyName) { + isPropertiesTableLoaded(); + final Map propertyNamesAndTypes = getPropertyNamesAndTypes(); + final String propertyType = propertyNamesAndTypes.get(propertyName); + final WebElement propertyRow = getPropertyRow(propertyName); + switch (propertyType) { + case "string": + case "float": + case "integer": + final WebElement propertyInput = propertyRow.findElement(By.xpath(XpathSelector.INPUT_PROPERTY.getXpath(propertyName))); + return propertyInput.getAttribute("value"); + case "list": + final List elements = propertyRow + .findElements(By.xpath(XpathSelector.INPUT_PROPERTY_LIST_STRING_TYPE_VALUE.getXpath(propertyName))); + return elements.stream().map(webElement -> webElement.getAttribute("value")).collect(Collectors.toList()); + default: + throw new UnsupportedOperationException(String.format("Retrieve value of property type %s is not yet supported", propertyType)); + } + } + /** * Checks if a property exists. * @param propertyName the property name @@ -346,6 +370,7 @@ public class ResourcePropertiesAssignmentTab extends AbstractPageObject { PROPERTY_ADD_VALUE_COMPLEX_TYPE("//a[contains(@data-tests-id, 'add-to-list-%s')]"), INPUT_PROPERTY_COMPLEX_TYPE_KEY("//input[contains(@data-tests-id, 'value-prop-key-%s')]"), INPUT_PROPERTY_COMPLEX_TYPE_VALUE("//input[contains(@data-tests-id, 'value-prop-%s')]"), + INPUT_PROPERTY_LIST_STRING_TYPE_VALUE("//input[starts-with(@data-tests-id, 'value-prop-%s')]"), INPUT_PROPERTY("//input[@data-tests-id='value-prop-%s']"), SELECT_INPUT_PROPERTY("//select[@data-tests-id='value-prop-%s']"), PROPERTY_TYPES("//*[contains(@data-tests-id, 'propertyType')]"), diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/VspCreationModal.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/VspCreationModal.java index 5950b2d895..4109911b0e 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/VspCreationModal.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/VspCreationModal.java @@ -21,7 +21,11 @@ package org.onap.sdc.frontend.ci.tests.pages; import lombok.AllArgsConstructor; import lombok.Getter; +import org.onap.sdc.frontend.ci.tests.datatypes.CategorySelect; +import org.onap.sdc.frontend.ci.tests.datatypes.VspCreateData; +import org.onap.sdc.frontend.ci.tests.datatypes.VspOnboardingProcedure; import org.openqa.selenium.By; +import org.openqa.selenium.Keys; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.Select; @@ -49,17 +53,17 @@ public class VspCreationModal extends AbstractPageObject { } /** - * Fills the creation form for the given vsp name. + * Fills the creation form with the given data. * - * @param vspName the name of the Vendor Software Product + * @param vspCreateData the data to fill the Vendor Software Product create form */ - public void fillCreationForm(final String vspName) { - fillName(vspName); - selectVendorFirstVendor(); - selectCategory("resourceNewCategory.network l4+.common network resources"); - fillDescription(vspName); - selectNetworkPackageOnboardingProcedure(); - selectDefaultModel(); + public void fillCreationForm(final VspCreateData vspCreateData) { + fillName(vspCreateData.getName()); + selectVendorOrElseAny(vspCreateData.getVendor()); + selectCategory(vspCreateData.getCategory()); + fillDescription(vspCreateData.getDescription()); + selectOnboardingProcedure(vspCreateData.getOnboardingProcedure()); + selectModel(vspCreateData.getModel()); } /** @@ -90,6 +94,19 @@ public class VspCreationModal extends AbstractPageObject { setInputValue(XpathSelector.DESCRIPTION_TXT, description); } + /** + * Selects the given vendor option. If a null value is given, selects the first option available. + * + * @param vendor the vendor option to select + */ + public void selectVendorOrElseAny(final String vendor) { + if (vendor == null) { + selectVendorFirstVendor(); + return; + } + setSelectValue(XpathSelector.VENDOR_SELECT, vendor); + } + /** * Selects the first vendor in the vendor list. */ @@ -104,20 +121,41 @@ public class VspCreationModal extends AbstractPageObject { clickElement(XpathSelector.DEFAULT_MODEL_RADIO); } + public void selectModel(final String model) { + if (model == null) { + selectDefaultModel(); + return; + } + clickElement(XpathSelector.OTHER_MODEL_RADIO); + final WebElement modelSelect = findSubElement(wrappingElement, XpathSelector.MODEL_SELECT.getXpath()); + modelSelect.sendKeys(model); + modelSelect.sendKeys(Keys.ENTER); + } + /** * Selects a category in the category list based on the option value. * * @param categoryOptionValue the option value */ - public void selectCategory(final String categoryOptionValue) { - setSelectValue(XpathSelector.CATEGORY_SELECT, categoryOptionValue); + public void selectCategory(final CategorySelect categoryOptionValue) { + setSelectValue(XpathSelector.CATEGORY_SELECT, categoryOptionValue.getOption()); } /** * Selects the network package onboarding procedure option. + * + * @param vspOnboardingProcedure the onboarding procedure to select */ - public void selectNetworkPackageOnboardingProcedure() { - wrappingElement.findElement(By.xpath(XpathSelector.ONBOARDING_METHOD_RADIO.getXpath())).click(); + public void selectOnboardingProcedure(final VspOnboardingProcedure vspOnboardingProcedure) { + if (VspOnboardingProcedure.MANUAL == vspOnboardingProcedure) { + wrappingElement.findElement(By.xpath(XpathSelector.ONBOARDING_MANUAL_PROCEDURE_RADIO.getXpath())).click(); + return; + } + if (VspOnboardingProcedure.NETWORK_PACKAGE == vspOnboardingProcedure) { + wrappingElement.findElement(By.xpath(XpathSelector.ONBOARDING_PACKAGE_PROCEDURE_RADIO.getXpath())).click(); + return; + } + throw new UnsupportedOperationException(String.format("Onboarding procedure option '%s' not yet supported", vspOnboardingProcedure)); } private void setInputValue(final XpathSelector inputTestId, final String value) { @@ -146,8 +184,11 @@ public class VspCreationModal extends AbstractPageObject { VENDOR_SELECT("new-vsp-vendor", "//select[@data-test-id='%s']"), CATEGORY_SELECT("new-vsp-category", "//select[@data-test-id='%s']"), DESCRIPTION_TXT("new-vsp-description", "//textarea[@data-test-id='%s']"), - ONBOARDING_METHOD_RADIO("new-vsp-creation-procedure-heat", "//input[@data-test-id='%s']/parent::label"), + ONBOARDING_PACKAGE_PROCEDURE_RADIO("new-vsp-creation-procedure-heat", "//input[@data-test-id='%s']/parent::label"), + ONBOARDING_MANUAL_PROCEDURE_RADIO("new-vsp-creation-procedure-manual", "//input[@data-test-id='%s']/parent::label"), DEFAULT_MODEL_RADIO("model-option-default", "//input[@data-test-id='%s']/parent::label"), + OTHER_MODEL_RADIO("model-option-other", "//input[@data-test-id='%s']/parent::label"), + MODEL_SELECT("model-option-select", "//div[@data-test-id='%s']//input"), CREATE_BTN("form-submit-button", "//*[@data-test-id='%s']"); @Getter diff --git a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/ToscaArtifactsPage.java b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/ToscaArtifactsPage.java index a691fba06e..f85c18a9d5 100644 --- a/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/ToscaArtifactsPage.java +++ b/integration-tests/src/test/java/org/onap/sdc/frontend/ci/tests/pages/component/workspace/ToscaArtifactsPage.java @@ -24,12 +24,12 @@ import java.util.ArrayList; import java.util.List; import lombok.AllArgsConstructor; import lombok.Getter; -import org.onap.sdc.frontend.ci.tests.pages.AbstractPageObject; +import org.onap.sdc.frontend.ci.tests.pages.ComponentPage; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; -public class ToscaArtifactsPage extends AbstractPageObject { +public class ToscaArtifactsPage extends ComponentPage { private final List downloadedArtifactList = new ArrayList<>(); private WebElement wrappingElement; diff --git a/integration-tests/src/test/resources/Files/ETSI/Vnf-ETSI-SOL001-2.5.1.csar b/integration-tests/src/test/resources/Files/ETSI/Vnf-ETSI-SOL001-2.5.1.csar new file mode 100644 index 0000000000000000000000000000000000000000..eb97b0c02fb67776ab71a2e899661467fcb40cdb GIT binary patch literal 20197 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 + diff --git a/openecomp-ui/src/nfvo-utils/i18n/en.json b/openecomp-ui/src/nfvo-utils/i18n/en.json index a5518efddd..7a2e66a4b3 100644 --- a/openecomp-ui/src/nfvo-utils/i18n/en.json +++ b/openecomp-ui/src/nfvo-utils/i18n/en.json @@ -387,7 +387,8 @@ "VendorSoftwareProduct/vendorName": "Vendor", "VendorSoftwareProduct/onboardingOrigin": "Onboarding Origin", "VendorSoftwareProduct/networkPackageName": "Network Package Name", - "vsp.model.select.label": "Other Models", + "vsp.model.select.other.label": "Other Models", + "vsp.model.select.label": "Select Model(s)", "EntitlementPool" : "Entitlement Pool", "EntitlementPool/name" : "Name", diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationView.jsx index 51e883427a..b52a18494c 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationView.jsx @@ -387,7 +387,7 @@ const ModelSelection = ({ data-test-id="model-option-default" /> @@ -413,6 +413,7 @@ const ModelSelection = ({ onMultiSelectChanged={onSelectChanged} value={selectedModelList} clearable={true} + data-test-id="model-option-select" placeholder={i18n('vsp.model.select.label')} multi /> -- 2.16.6