diff options
16 files changed, 316 insertions, 173 deletions
diff --git a/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java index 5a2eb59d2..bf33eff94 100644 --- a/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java @@ -42,10 +42,13 @@ import com.xebialabs.restito.semantics.Condition; import com.xebialabs.restito.server.StubServer; import io.joshworks.restclient.http.HttpResponse; import io.joshworks.restclient.http.JsonNode; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Collections; import java.util.Map; import org.glassfish.grizzly.http.Method; import org.glassfish.grizzly.http.util.HttpStatus; +import org.jetbrains.annotations.NotNull; import org.onap.vid.utils.Logging; import org.springframework.http.HttpMethod; import org.testng.annotations.AfterMethod; @@ -76,11 +79,20 @@ public class SyncRestClientForHttpServerTest { syncRestClient.destroy(); } + @NotNull + private String getTestUrl(String protocol) { + try { + return new URI(protocol, null, "127.0.0.1" , stubServer.getPort(), "/test", null, null).toString(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + @Test public void testJsonResponseFromGet() throws JsonProcessingException { // given stubGetCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient .get(url, Collections.emptyMap(), Collections.emptyMap()); @@ -97,7 +109,7 @@ public class SyncRestClientForHttpServerTest { public void testObjectResponseFromGet() throws JsonProcessingException { // given stubGetCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<SyncRestClientModel.TestModel> testModelHttpResponse = syncRestClient .get(url, Collections.emptyMap(), Collections.emptyMap(), SyncRestClientModel.TestModel.class); @@ -114,7 +126,7 @@ public class SyncRestClientForHttpServerTest { public void testJsonResponseFromPost() throws JsonProcessingException { // given stubPostCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient.post(url, Collections.emptyMap(), testObject); // then @@ -130,7 +142,7 @@ public class SyncRestClientForHttpServerTest { public void test404JsonResponseFromPost() throws JsonProcessingException { // given stubPostCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient .post(url, Collections.emptyMap(), NOT_EXISTING_OBJECT); @@ -146,7 +158,7 @@ public class SyncRestClientForHttpServerTest { // given stubPostCall(); Map headers = ImmutableMap.<String, String>builder().put("Authorization", "Basic anyHash").build(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient.post(url, headers, testObject); // then @@ -160,7 +172,7 @@ public class SyncRestClientForHttpServerTest { public void testFailedJsonResponseFromPost() throws JsonProcessingException { // given stubPostCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when stubServer.stop(); syncRestClient.post(url, Collections.emptyMap(), testObject); @@ -170,7 +182,7 @@ public class SyncRestClientForHttpServerTest { public void testObjectResponseFromPost() throws JsonProcessingException { // given stubPostCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<SyncRestClientModel.TestModel> objectHttpResponse = syncRestClient .post(url, Collections.emptyMap(), testObject, SyncRestClientModel.TestModel.class); @@ -187,7 +199,7 @@ public class SyncRestClientForHttpServerTest { public void testJsonResponseFromPut() throws JsonProcessingException { // given stubPutCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient.put(url, Collections.emptyMap(), testObject); // then @@ -203,7 +215,7 @@ public class SyncRestClientForHttpServerTest { public void testObjectResponseFromPut() throws JsonProcessingException { // given stubPutCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<SyncRestClientModel.TestModel> modelHttpResponse = syncRestClient .put(url, Collections.emptyMap(), testObject, SyncRestClientModel.TestModel.class); @@ -220,7 +232,7 @@ public class SyncRestClientForHttpServerTest { public void testJsonResponseFromDelete() throws JsonProcessingException { // given stubDeleteCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient.delete(url, Collections.emptyMap()); // then @@ -236,7 +248,7 @@ public class SyncRestClientForHttpServerTest { public void testObjectResponseFromDelete() throws JsonProcessingException { // given stubDeleteCall(); - String url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String url = getTestUrl("http"); // when HttpResponse<SyncRestClientModel.TestModel> modelHttpResponse = syncRestClient .delete(url, Collections.emptyMap(), SyncRestClientModel.TestModel.class); @@ -253,8 +265,8 @@ public class SyncRestClientForHttpServerTest { public void testRedirectToHttp() throws JsonProcessingException { // given stubGetCall(); - String secured_url = "https://0.0.0.0:" + stubServer.getPort() + "/test"; - String available_url = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String secured_url = getTestUrl("https");; + String available_url = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient .get(secured_url, Collections.emptyMap(), Collections.emptyMap()); diff --git a/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java index 645b5eac0..27cd81e70 100644 --- a/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java @@ -42,8 +42,8 @@ import com.xebialabs.restito.semantics.Condition; import com.xebialabs.restito.server.StubServer; import io.joshworks.restclient.http.HttpResponse; import io.joshworks.restclient.http.JsonNode; - -import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.KeyStoreException; @@ -55,13 +55,13 @@ import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; - import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.ssl.SSLContextBuilder; import org.glassfish.grizzly.http.Method; +import org.jetbrains.annotations.NotNull; import org.onap.vid.utils.Logging; import org.springframework.http.HttpMethod; import org.testng.annotations.AfterMethod; @@ -91,12 +91,21 @@ public class SyncRestClientForHttpsServerTest { stubServer.stop(); } + @NotNull + private String getTestUrl(String protocol) { + try { + return new URI(protocol, null, "127.0.0.1" , stubServer.getPort(), "/test", null, null).toString(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + @Test public void testJsonResponseFromGet() throws JsonProcessingException { // given stubGetCall(); - String securedUrl = "https://0.0.0.0:" + stubServer.getPort() + "/test"; - String notSecuredUrl = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String securedUrl = getTestUrl("https"); + String notSecuredUrl = getTestUrl("http"); // when HttpResponse<JsonNode> jsonNodeHttpResponse = syncRestClient .get(securedUrl, Collections.emptyMap(), Collections.emptyMap()); @@ -115,8 +124,8 @@ public class SyncRestClientForHttpsServerTest { // given stubServer.run(); stubGetCall(); - String securedUrl = "https://0.0.0.0:" + stubServer.getPort() + "/test"; - String notSecuredUrl = "http://0.0.0.0:" + stubServer.getPort() + "/test"; + String securedUrl = getTestUrl("https"); + String notSecuredUrl = getTestUrl("http"); // when HttpResponse<SyncRestClientModel.TestModel> testModelHttpResponse = syncRestClient .get(securedUrl, Collections.emptyMap(), Collections.emptyMap(), SyncRestClientModel.TestModel.class); diff --git a/vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json b/vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json index 04b09616e..a8417e3a9 100644 --- a/vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json +++ b/vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json @@ -44,9 +44,9 @@ "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", "instanceName": "zolson57arlba007", "action": "Create", - "platformName": "NETWORK-CLOUD", - "lcpCloudRegionId": "olson57a", - "tenantId": "dcb28ad99c7341748830c9dc307f85eb", + "platformName": "xxx1", + "lcpCloudRegionId": "hvf6", + "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77", "instanceParams": [ {} ], @@ -66,8 +66,8 @@ }, "instanceName": "zolson57arlba007_lba_Base_01", "action": "Create", - "lcpCloudRegionId": "olson57a", - "tenantId": "dcb28ad99c7341748830c9dc307f85eb", + "lcpCloudRegionId": "hvf6", + "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77", "instanceParams": [ {} ], @@ -89,8 +89,8 @@ }, "instanceName": "zolson57arlba007_lba_dj_01", "action": "Create", - "lcpCloudRegionId": "olson57a", - "tenantId": "dcb28ad99c7341748830c9dc307f85eb", + "lcpCloudRegionId": "hvf6", + "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77", "instanceParams": [ {} ], @@ -106,7 +106,7 @@ "isFailed": false, "statusMessage": null, "position": null, - "lineOfBusiness": "EMANUEL-CONSUMER" + "lineOfBusiness": "zzz1" } }, "networks": {}, diff --git a/vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts index 1c91d02ca..fa628d4b5 100644 --- a/vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts @@ -2,7 +2,6 @@ /// <reference types="Cypress" /> import {JsonBuilder} from '../../support/jsonBuilders/jsonBuilder'; import {ServiceModel} from '../../support/jsonBuilders/models/service.model'; -import * as _ from 'lodash'; describe('A la carte', function () { describe('check service name', () => { @@ -242,11 +241,11 @@ describe('A la carte', function () { '2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2', ]; - addVfModule(vnfName, vfModulesNames[0], 'mimazepubi', 'hvf6', '', 'AINWebTool-15-D-iftach', false, false, false) + cy.addALaCarteVfModule(vnfName, vfModulesNames[0], 'mimazepubi', 'hvf6', '', 'AINWebTool-15-D-iftach', false, false, false) .then(() => { - addVfModule(vnfName, vfModulesNames[1], 'puwesovabe', 'AAIAIC25', 'my region', 'USP-SIP-IC-24335-T-01', true, true, false) + cy.addALaCarteVfModule(vnfName, vfModulesNames[1], 'puwesovabe', 'AAIAIC25', 'my region', 'USP-SIP-IC-24335-T-01', true, true, false) .then(() => { - addVfModule(vnfName, vfModulesNames[2], 'bnmgtrx', 'hvf6', '', 'AINWebTool-15-D-iftach', false, false, true) + cy.addALaCarteVfModule(vnfName, vfModulesNames[2], 'bnmgtrx', 'hvf6', '', 'AINWebTool-15-D-iftach', false, false, true) .then(() => { cy.getReduxState().then((state) => { const vfModules = state.service.serviceInstance['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].vnfs[vnfName].vfModules; @@ -284,28 +283,7 @@ describe('A la carte', function () { .get('.error').contains(INSTANCE_NAME_NOT_MANDATORY_MESSAGE); } - function addVfModule(vnfName: string, vfModuleName: string, instanceName: string, lcpRegion: string, legacyRegion: string, tenant: string, rollback: boolean, sdncPreLoad: boolean, deleteVgName: boolean): Chainable<any> { - return cy.getElementByDataTestsId('node-' + vnfName).click({force: true}).then(() => { - cy.getElementByDataTestsId('node-' + vfModuleName + '-add-btn').click({force: true}).then(() => { - cy.getElementByDataTestsId('instanceName').clear().type(instanceName, {force: true}).then(() => { - if (deleteVgName) { - cy.getElementByDataTestsId('volumeGroupName').clear(); - } - }).then(() => { - cy.selectDropdownOptionByText('lcpRegion', lcpRegion); - if (!_.isEmpty(legacyRegion)) { - cy.typeToInput("lcpRegionText", legacyRegion); - } - cy.selectDropdownOptionByText('tenant', tenant); - cy.selectDropdownOptionByText('rollback', String(rollback)); - if (sdncPreLoad) { - cy.getElementByDataTestsId('sdncPreLoad').check(); - } - cy.getElementByDataTestsId('form-set').click({force: true}); - }); - }); - }); - } + }); diff --git a/vid-webpack-master/cypress/integration/iFrames/drawingBoard.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/drawingBoard.e2e.ts index b678702ff..133dbe72a 100644 --- a/vid-webpack-master/cypress/integration/iFrames/drawingBoard.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/drawingBoard.e2e.ts @@ -17,6 +17,22 @@ describe('Drawing board', function () { cy.screenshot(); }); + function addSameVnfMultipleTimes() { + cy.openIframe('app/ui/#/servicePlanning?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'); + const vnfNodeName = 'node-2017-488_PASQUALE-vPE 0'; + cy.drawingBoardPressAddButtonByElementName(vnfNodeName).get('i').should('have.class', 'fa-plus-circle'); + cy.drawingBoardPressAddButtonByElementName(vnfNodeName).click({force: true}); + cy.fillVnfPopup(true).then(() => { + cy.drawingBoardPressAddButtonByElementName(vnfNodeName).click({force: true}); + cy.fillVnfPopup().then(() => { + cy.drawingBoardPressAddButtonByElementName(vnfNodeName).click({force: true}); + cy.fillVnfPopup().then(() => { + cy.drawingBoardNumberOfExistingElementsShouldContains(3); + }); + }); + }); + } + describe('duplicate', () => { it('delete vf module reduce the number of vf modules ', function () { @@ -40,18 +56,7 @@ describe('Drawing board', function () { it('create new vf module update the number of vf modules ', () => { cy.readFile('cypress/support/jsonBuilders/mocks/jsons/emptyServiceRedux.json').then((res) => { cy.setReduxState(<any>res); - cy.openIframe('app/ui/#/servicePlanning?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'); - cy.drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').get('i').should('have.class', 'fa-plus-circle'); - cy.drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').click({force: true}); - cy.fillVnfPopup(true).then(() => { - cy.drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').click({force: true}); - cy.fillVnfPopup().then(() => { - cy.drawingBoardPressAddButtonByElementName('node-2017-488_PASQUALE-vPE 0').click({force: true}); - cy.fillVnfPopup().then(() => { - cy.drawingBoardNumberOfExistingElementsShouldContains(3); - }); - }); - }); + addSameVnfMultipleTimes(); }); }); @@ -238,6 +243,32 @@ describe('Drawing board', function () { }); + describe('default max instances value', () => { + + it('when there is no maxCountInstances for vfModule, it can be added unlimited times', () => { + let reduxState = getReduxWithVNFS(false); + (<any> reduxState.global.flags)['FLAG_2002_UNLIMITED_MAX'] = true; + cy.setReduxState(<any>reduxState); + cy.openIframe('app/ui/#/servicePlanning?serviceModelId=6e59c5de-f052-46fa-aa7e-2fca9d674c44'); + const vfModuleName = 'vf_vgeraldine0..VfVgeraldine..vflorence_gpb..module-2'; + const vnfName = "VF_vGeraldine 0"; + cy.addMacroVfModule(vnfName, vfModuleName, 'module-1'); + cy.addMacroVfModule(vnfName, vfModuleName, 'module-2'); + cy.addMacroVfModule(vnfName, vfModuleName, 'module-3'); + cy.getElementByDataTestsId('node-d6557200-ecf2-4641-8094-5393ae3aae60-VF_vGeraldine 0').click(); + cy.getElementByDataTestsId('node-41708296-e443-4c71-953f-d9a010f059e1-vf_vgeraldine0..VfVgeraldine..vflorence_gpb..module-2').should('have.length', 3); + }); + + it('when there is no max_instances for VNF, it can be added multiple times ', () => { + cy.readFile('cypress/support/jsonBuilders/mocks/jsons/emptyServiceRedux.json').then((reduxState) => { + reduxState.global['flags'] = { 'FLAG_2002_UNLIMITED_MAX' : true }; + delete reduxState.service.serviceHierarchy['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].vnfs['2017-488_PASQUALE-vPE 0'].properties.max_instances; + cy.setReduxState(<any>reduxState); + addSameVnfMultipleTimes(); + }); + }); + }); + describe('multiple tests', () => { it('remove vfModule with missing data should update deploy button status', () => { let res = getReduxWithVFModuleMissingData(); @@ -6285,7 +6316,7 @@ describe('Drawing board', function () { } } - function getReduxWithVNFS(isEcompGeneratedNaming: boolean) { + function getReduxWithVNFS(isEcompGeneratedNaming: boolean){ return { "global": { "name": null, diff --git a/vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts index 8eb70b1fe..afad68747 100644 --- a/vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts +++ b/vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts @@ -1,10 +1,13 @@ +import ObjectLike = Cypress.ObjectLike; + describe('Drawing Board: Instantiation Templates', function () { - describe('Load Page and Deploy', () => { + describe('Instantiation templates ', () => { beforeEach(() => { cy.clearSessionStorage(); cy.setTestApiParamToVNF(); + cy.initAAIMock(); cy.initVidMock(); cy.initDrawingBoardUserPermission(); cy.login(); @@ -16,41 +19,28 @@ describe('Drawing Board: Instantiation Templates', function () { cy.screenshot(); }); - it(`Given a stored template - when click "deploy" - then a coherent request should be sent upon deploy`, function () { - const serviceModelId = '6cfeeb18-c2b0-49df-987a-da47493c8e38'; - const templateUuid = "46390edd-7100-46b2-9f18-419bd24fb60b"; - - const drawingBoardAction = `RECREATE`; - const templateTopologyEndpoint = "templateTopology"; - - // Given... + describe('Load Page and Deploy', () => { - cy.route(`**/rest/models/services/${serviceModelId}`, - 'fixture:../support/jsonBuilders/mocks/jsons/instantiationTemplates/templates__service_model.json') - .as('serviceModel'); + it(`Given a stored template - when click "deploy" - then a coherent request should be sent upon deploy`, function () { - cy.route(`**/asyncInstantiation/${templateTopologyEndpoint}/${templateUuid}`, - 'fixture:../../../vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json') - .as('templateTopology'); + loadDrawingBoardWithRecreateMode(); - // When... - - cy.openIframe(`app/ui/#/servicePlanning/${drawingBoardAction}` + - `?jobId=${templateUuid}` + - `&serviceModelId=${serviceModelId}`); + // Then... + cy.getElementByDataTestsId("node-vProbe_NC_VNF 0").should('be.visible'); + assertThatBodyFromDeployRequestEqualsToTemplateFromBackEnd(); + }); - cy.wait('@serviceModel'); - cy.wait('@templateTopology'); - cy.getElementByDataTestsId("node-vProbe_NC_VNF 0").should('be.visible'); + it('View a template’s details as expected', ()=> { - cy.getDrawingBoardDeployBtn().click(); + loadDrawingBoardWithRecreateMode(); - // Then... + // Then... + cy.drawingBoardTreeOpenContextMenuByElementDataTestId("node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0") + .drawingBoardTreeClickOnContextMenuOptionByName('Edit') + .getElementByDataTestsId("lcpRegion").should('contain', 'hvf6') + .getElementByDataTestsId("cancelButton").click(); - cy.wait('@expectedPostAsyncInstantiation').then(xhr => { - cy.readFile('../vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json').then((expectedResult) => { - convertRollbackOnFailureValueFromStringToBoolean(expectedResult); - cy.deepCompare(xhr.request.body, expectedResult); + assertThatBodyFromDeployRequestEqualsToTemplateFromBackEnd(); }); }); @@ -58,12 +48,54 @@ describe('Drawing Board: Instantiation Templates', function () { }); +function loadDrawingBoardWithRecreateMode() { + const serviceModelId = '6cfeeb18-c2b0-49df-987a-da47493c8e38'; + const templateUuid = "46390edd-7100-46b2-9f18-419bd24fb60b"; + + const drawingBoardAction = `RECREATE`; + const templateTopologyEndpoint = "templateTopology"; + cy.route(`**/rest/models/services/${serviceModelId}`, + 'fixture:../support/jsonBuilders/mocks/jsons/instantiationTemplates/templates__service_model.json') + .as('serviceModel'); + + cy.route(`**/asyncInstantiation/${templateTopologyEndpoint}/${templateUuid}`, + 'fixture:../../../vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json') + .as('templateTopology'); + + // When... + + cy.openIframe(`app/ui/#/servicePlanning/${drawingBoardAction}` + + `?jobId=${templateUuid}` + + `&serviceModelId=${serviceModelId}`); + + cy.wait('@serviceModel'); + cy.wait('@templateTopology'); +} + +function assertThatBodyFromDeployRequestEqualsToTemplateFromBackEnd() { + cy.getDrawingBoardDeployBtn().click(); + cy.wait('@expectedPostAsyncInstantiation').then(xhr => { + cy.readFile('../vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json').then((expectedResult) => { + convertRollbackOnFailureValueFromStringToBoolean(expectedResult); + + let xhrBodyWithoutIsDirtyField = removeIsDirtyFieldFromXhrRequestBody(xhr); + cy.deepCompare(xhrBodyWithoutIsDirtyField, expectedResult); + }); + }); +} + //We use this function because the deployService() on drawing-board-header.component class // changes rollbackOnFailure value from string type to boolean. function convertRollbackOnFailureValueFromStringToBoolean(expectedResult: any) { expectedResult.rollbackOnFailure = Boolean(expectedResult.rollbackOnFailure); } +function removeIsDirtyFieldFromXhrRequestBody(xhr : any) { + let xhrTempBody = JSON.parse(JSON.stringify(xhr.request.body)); + delete xhrTempBody.isDirty; + return xhrTempBody; +} + function mockAsyncBulkResponse() { cy.server().route({ url: Cypress.config('baseUrl') + '/asyncInstantiation/bulk', @@ -72,5 +104,3 @@ describe('Drawing Board: Instantiation Templates', function () { response: "[]", }).as("expectedPostAsyncInstantiation"); } - -}); diff --git a/vid-webpack-master/cypress/support/steps/fill.vfModule.step.ts b/vid-webpack-master/cypress/support/steps/fill.vfModule.step.ts index d2977832d..b87e773f9 100644 --- a/vid-webpack-master/cypress/support/steps/fill.vfModule.step.ts +++ b/vid-webpack-master/cypress/support/steps/fill.vfModule.step.ts @@ -1,10 +1,12 @@ declare namespace Cypress { interface Chainable { - fillVFModulePopup: typeof FillVFModulePopup + fillVFModulePopup: typeof fillVFModulePopup; + addALaCarteVfModule: typeof addALaCarteVfModule; + addMacroVfModule: typeof addMacroVfModule; } } -function FillVFModulePopup(vnfName: string, vfModuleName: string, instanceName: string, lcpRegion: string, tenant: string, rollback: boolean, sdncPreLoad: boolean): Chainable<any> { +function fillVFModulePopup(vnfName: string, vfModuleName: string, instanceName: string, lcpRegion: string, tenant: string, rollback: boolean, sdncPreLoad: boolean): Chainable<any> { cy.getElementByDataTestsId('node-' + vnfName).click({force: true}); cy.getElementByDataTestsId('node-' + vfModuleName + '-add-btn').click({force: true}); cy.getElementByDataTestsId('instanceName').last().type(instanceName, {force: true}); @@ -21,4 +23,40 @@ function FillVFModulePopup(vnfName: string, vfModuleName: string, instanceName: } -Cypress.Commands.add('fillVFModulePopup', FillVFModulePopup); +function addMacroVfModule(vnfName: string, vfModuleName: string, instanceName: string): Chainable<any> { + return cy.getElementByDataTestsId('node-' + vnfName).click({force: true}).then(() => { + cy.getElementByDataTestsId('node-' + vfModuleName + '-add-btn').click({force: true}).then(() => { + cy.getElementByDataTestsId('instanceName').clear().type(instanceName, {force: true}).then(() => { + cy.getElementByDataTestsId('form-set').click({force: true}); + }) + }) + }); +} + +function addALaCarteVfModule(vnfName: string, vfModuleName: string, instanceName: string, lcpRegion: string, legacyRegion: string, + tenant: string, rollback: boolean, sdncPreLoad: boolean, deleteVgName: boolean): Chainable<any> { + return cy.getElementByDataTestsId('node-' + vnfName).click({force: true}).then(() => { + cy.getElementByDataTestsId('node-' + vfModuleName + '-add-btn').click({force: true}).then(() => { + cy.getElementByDataTestsId('instanceName').clear().type(instanceName, {force: true}).then(() => { + if (deleteVgName) { + cy.getElementByDataTestsId('volumeGroupName').clear(); + } + }).then(() => { + cy.selectDropdownOptionByText('lcpRegion', lcpRegion); + if (legacyRegion) { + cy.typeToInput("lcpRegionText", legacyRegion); + } + cy.selectDropdownOptionByText('tenant', tenant); + cy.selectDropdownOptionByText('rollback', String(rollback)); + if (sdncPreLoad) { + cy.getElementByDataTestsId('sdncPreLoad').check(); + } + cy.getElementByDataTestsId('form-set').click({force: true}); + }); + }); + }); +} + +Cypress.Commands.add('fillVFModulePopup', fillVFModulePopup); +Cypress.Commands.add('addALaCarteVfModule', addALaCarteVfModule); +Cypress.Commands.add('addMacroVfModule', addMacroVfModule); diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts index 225d84b4c..276c0aeb2 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts @@ -17,6 +17,8 @@ import {AaiService} from "../../../../../shared/services/aaiService/aai.service" import {HttpClient, HttpHandler} from "@angular/common/http"; import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service"; import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; +import {instance, mock, when} from "ts-mockito"; +import each from "jest-each"; class MockAppStore<T> { getState() { @@ -44,7 +46,8 @@ describe('VFModule Model Info', () => { let _vfModuleUpgradePopupService : VfModuleUpgradePopupService; let _iframeService : IframeService; let _componentInfoService : ComponentInfoService; - let _featureFlagsService : FeatureFlagsService; + let mockFeatureFlagsService: FeatureFlagsService = mock(FeatureFlagsService); + let mockFeatureFlagsServiceInstance: FeatureFlagsService = instance(mockFeatureFlagsService); beforeAll(done => (async () => { @@ -62,7 +65,7 @@ describe('VFModule Model Info', () => { AaiService, HttpClient, HttpHandler, - {provide: FeatureFlagsService, useClass: MockFeatureFlagsService}, + {provide: FeatureFlagsService, useValue: mockFeatureFlagsServiceInstance}, ComponentInfoService ] }); @@ -70,9 +73,9 @@ describe('VFModule Model Info', () => { injector = getTestBed(); _sharedTreeService = injector.get(SharedTreeService); - _componentInfoService = injector.get(ComponentInfoService) - _featureFlagsService = injector.get(FeatureFlagsService); - vfModuleModel = new VFModuleModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _vfModulePopupService, _vfModuleUpgradePopupService, _iframeService,_featureFlagsService, MockNgRedux.getInstance(),_componentInfoService); + _componentInfoService = injector.get(ComponentInfoService); + vfModuleModel = new VFModuleModelInfo(_dynamicInputsService, _sharedTreeService, _dialogService, _vfModulePopupService, _vfModuleUpgradePopupService, + _iframeService, mockFeatureFlagsServiceInstance, MockNgRedux.getInstance(),_componentInfoService); })().then(done).catch(done.fail)); @@ -480,6 +483,33 @@ describe('VFModule Model Info', () => { expect(actualVNFInfo).toEqual(expectedVNFInfo); }); + each([ + ["maxCountInstances 3, currentNodeCount 1, flag on",{maxCountInstances:3}, 1, {FLAG_2002_UNLIMITED_MAX: true}, false], + ["maxCountInstances 3, currentNodeCount 3, flag on",{maxCountInstances:3}, 3, {FLAG_2002_UNLIMITED_MAX: true}, true], + ["no maxCountInstances, currentNodeCount 0, flag off",{}, 0, {FLAG_2002_UNLIMITED_MAX: false}, false], + ["no maxCountInstances, currentNodeCount 1, flag off",{}, 1, {FLAG_2002_UNLIMITED_MAX: false}, true], + ["no maxCountInstances, currentNodeCount 1, no flags",{}, 1, null, true], + ["no maxCountInstances, currentNodeCount 0, flag on",{}, 0, {FLAG_2002_UNLIMITED_MAX: true}, false], + ["no maxCountInstances, currentNodeCount 1, flag on",{}, 1, {FLAG_2002_UNLIMITED_MAX: true}, false], + ["no maxCountInstances, currentNodeCount 1000, flag on",{}, 1000, {FLAG_2002_UNLIMITED_MAX: true}, false], + ]).test('isVFModuleReachedLimit: %s', (desc, properties, currentNodeCount, flags, expected) => { + + const node = { data: { + name : 'vfModuleName' + }}; + + const serviceHierarchy = { + servicedId :{ + vfModules : { + vfModuleName : { + properties + }}}}; + + when(mockFeatureFlagsService.getAllFlags()).thenReturn(flags); + + expect(vfModuleModel.isVFModuleReachedLimit(node, serviceHierarchy, 'servicedId', currentNodeCount)).toEqual(expected); + }); + function getVFModule(){ return { "uuid":"522159d5-d6e0-4c2a-aa44-5a542a12a830", diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts index e182b8a6f..1ce452793 100644 --- a/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts +++ b/vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts @@ -8,10 +8,7 @@ import {VfModuleInstance} from "../../../../../shared/models/vfModuleInstance"; import {VfModule} from "../../../../../shared/models/vfModule"; import {NgRedux} from "@angular-redux/store"; import {ITreeNode} from "angular-tree-component/dist/defs/api"; -import { - GenericFormPopupComponent, - PopupType -} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component"; +import {GenericFormPopupComponent, PopupType} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component"; import {DialogService} from "ng2-bootstrap-modal"; import {VfModulePopuopService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popuop.service"; import {AppState} from "../../../../../shared/store/reducers"; @@ -19,19 +16,13 @@ import {MessageBoxData} from "../../../../../shared/components/messageBox/messag import {MessageBoxService} from "../../../../../shared/components/messageBox/messageBox.service"; import {AvailableNodeIcons} from "../../../available-models-tree/available-models-tree.service"; import {IframeService} from "../../../../../shared/utils/iframe.service"; -import { - deleteActionVfModuleInstance, deleteVFModuleField, - removeVfModuleInstance, - undoDeleteVfModuleInstance, - undoUgradeVFModule, updateVFModuleField, - updateVFModulePosition, - upgradeVFModule -} from "../../../../../shared/storeUtil/utils/vfModule/vfModule.actions"; +import {deleteActionVfModuleInstance, deleteVFModuleField, removeVfModuleInstance, undoDeleteVfModuleInstance, undoUgradeVFModule, updateVFModulePosition, upgradeVFModule} from "../../../../../shared/storeUtil/utils/vfModule/vfModule.actions"; import {ComponentInfoService} from "../../../component-info/component-info.service"; import {ComponentInfoType} from "../../../component-info/component-info-model"; import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component"; import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service"; import {FeatureFlagsService, Features} from "../../../../../shared/services/featureFlag/feature-flags.service"; +import {Utils} from "../../../../../shared/utils/utils"; export class VFModuleModelInfo implements ILevelNodeInfo { constructor(private _dynamicInputsService: DynamicInputsService, @@ -301,12 +292,16 @@ export class VFModuleModelInfo implements ILevelNodeInfo { } isVFModuleReachedLimit(node: any, serviceHierarchy: any, serviceModelId: string, currentNodeCount: number): boolean { - let maxNodes: number = 1; + const flags = this._featureFlagsService.getAllFlags(); let vnfModules = serviceHierarchy[serviceModelId].vfModules; - if (vnfModules[node.data.name]) { - maxNodes = vnfModules[node.data.name].properties.maxCountInstances || 1; + const maxInstances = vnfModules[node.data.name] + ? Utils.getMaxVfModule(vnfModules[node.data.name].properties, flags) + : null; + if (_.isNil(maxInstances)) { + return false; } - return !(maxNodes > currentNodeCount); + + return !(maxInstances > currentNodeCount); } getMenuAction(node: ITreeNode, serviceModelId: string): { [methodName: string]: { method: Function, visible: Function, enable: Function } } { diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html index f9da42607..f9a11eab1 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html @@ -61,7 +61,7 @@ (click)="openTemplateModal()" ><span>Template</span></button> <button - *ngIf=isInstantiationStatusFilterFlagOn() + *ngIf="isShowPreviousInstantiationBtn" [attr.data-tests-id]="'ShowPreviousInstancesButton'" type="button" class="btn btn-success submit" (click)="formPopupDetails.onOtherAction(formPopupDetails.that, dynamicForm)"> diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss index 5057b44a5..18416dae6 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss @@ -134,7 +134,7 @@ $grid-border: 1px #d2d2d2 solid; } .submit { - width: 120px; + min-width: 120px; height: 36px; background: #009fdb; border-radius: 2px; diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts index 159871f45..3939e44ff 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts @@ -46,6 +46,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole type: PopupType; uuidData: UUIDData; showTemplateBtn: boolean = false; + isShowPreviousInstantiationBtn: boolean = false; isUpdateMode: boolean; node: ITreeNode = null; hasGeneralApiError: boolean = false; @@ -85,29 +86,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole .subscribe(params => { console.log('changed'); if (params['serviceModelId'] && params['isCreate'] == "true") { - this._genericFormPopupService.initReduxOnCreateNewService().then((serviceModelId: string) => { - this.uuidData = <any>{ - bulkSize: 1, - isMacro: this._store.getState().service.serviceHierarchy[serviceModelId].service.vidNotions.instantiationType === 'Macro', - type: PopupType.SERVICE, - serviceId: serviceModelId, - popupService: this._servicePopupService, - }; - this.showTemplateBtn = !!this._store.getState().global.flags["FLAG_2004_INSTANTIATION_TEMPLATES_POPUP"]; - - this.uuidData.popupService.closeDialogEvent.subscribe((that) => { - this.closeDialog(that); - }); - - this.formPopupDetails = this.uuidData.popupService.getGenericFormPopupDetails( - this.uuidData['serviceId'], - null, - null, - this.node, - this.uuidData, - false - ); - }); + this.onInitForCreateNewServicePopup(); } }); @@ -125,6 +104,34 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole } } + private onInitForCreateNewServicePopup() { + this._genericFormPopupService.initReduxOnCreateNewService().then((serviceModelId: string) => { + this.uuidData = <any>{ + bulkSize: 1, + isMacro: this._store.getState().service.serviceHierarchy[serviceModelId].service.vidNotions.instantiationType === 'Macro', + type: PopupType.SERVICE, + serviceId: serviceModelId, + popupService: this._servicePopupService, + }; + this.showTemplateBtn = !!this._store.getState().global.flags["FLAG_2004_INSTANTIATION_TEMPLATES_POPUP"]; + + this.isShowPreviousInstantiationBtn = !!this._store.getState().global.flags["FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER"]; + + this.uuidData.popupService.closeDialogEvent.subscribe((that) => { + this.closeDialog(that); + }); + + this.formPopupDetails = this.uuidData.popupService.getGenericFormPopupDetails( + this.uuidData['serviceId'], + null, + null, + this.node, + this.uuidData, + false + ); + }); + } + hasSomeError(formPopupDetails: FormPopupDetails, form: FormGroup): boolean { if (_.isNil(formPopupDetails)) return false; else { @@ -148,9 +155,6 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole this._dialogService.addDialog(InstantiationTemplatesModalComponent, {}); } - isInstantiationStatusFilterFlagOn() { - return FeatureFlagsService.getFlagState(Features.FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER, this._store); - } } diff --git a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts index c18b20d7e..1d44a9e5e 100644 --- a/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts +++ b/vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts @@ -38,7 +38,7 @@ export class BasicPopupService { return new VNFModel(rawModel, flags); } case 'vfModules' : { - return new VfModule(rawModel); + return new VfModule(rawModel, flags); } case 'networks' : { return new NetworkModel(rawModel, flags); diff --git a/vid-webpack-master/src/app/shared/models/vfModule.ts b/vid-webpack-master/src/app/shared/models/vfModule.ts index c75202124..8f92ba428 100644 --- a/vid-webpack-master/src/app/shared/models/vfModule.ts +++ b/vid-webpack-master/src/app/shared/models/vfModule.ts @@ -1,4 +1,5 @@ import {NodeModel, NodeModelResponseInterface} from "./nodeModel"; +import {Utils} from "../utils/utils"; export interface Properties{ @@ -23,7 +24,7 @@ export class VfModule extends NodeModel { modelCustomizationName: string; volumeGroupAllowed : boolean; - constructor(vf?: VFModuleResponseInterface) { + constructor(vf?: VFModuleResponseInterface, flags?: { [key: string]: boolean }) { super(vf); if(vf){ this.customizationUuid = vf.customizationUuid; @@ -32,7 +33,7 @@ export class VfModule extends NodeModel { } if (vf && vf.properties) { this.min = vf.properties.minCountInstances; - this.max = vf.properties.maxCountInstances; + this.max = Utils.getMaxVfModule(vf.properties, flags); this.initial = vf.properties.initialCount; this.rollbackOnFailure = true } diff --git a/vid-webpack-master/src/app/shared/utils/util.spec.ts b/vid-webpack-master/src/app/shared/utils/util.spec.ts index 4b39764f5..ae39238c2 100644 --- a/vid-webpack-master/src/app/shared/utils/util.spec.ts +++ b/vid-webpack-master/src/app/shared/utils/util.spec.ts @@ -1,24 +1,8 @@ import {Utils} from "./utils"; -import {TestBed} from "@angular/core/testing"; import each from "jest-each"; describe('Util', () => { - let util: Utils; - - beforeAll(done => (async () => { - TestBed.configureTestingModule({ - - }); - await TestBed.compileComponents(); - - util = new Utils(); - - })().then(done).catch(done.fail)); - - test('should be defined', () => { - expect(util).toBeDefined(); - }); test('hasContents should return false if object is undefined or null or empty', () => { expect(Utils.hasContents(undefined)).toBeFalsy(); @@ -40,4 +24,28 @@ describe('Util', () => { expect(Utils.isALaCarte(instantiationType)).toEqual(expected); }); + each([ + ["empty properties, empty flags",{}, {}, 1], + ["null properties, undefined flags",null, undefined, 1], + ["max_instances 3, flag is on", {max_instances:3}, {FLAG_2002_UNLIMITED_MAX: true}, 3], + ["max_instances 3, flag is off", {max_instances:3}, {FLAG_2002_UNLIMITED_MAX: false}, 3], + ["null properties, flag is on", null, {FLAG_2002_UNLIMITED_MAX: true}, null], + ["null properties, flag is off", null, {FLAG_2002_UNLIMITED_MAX: false}, 1], + ["undefined properties, flag is off", undefined, {FLAG_2002_UNLIMITED_MAX: false}, 1], + ]).test('getMaxFirstLevel %s', (desc, properties, flags, expected) => { + expect(Utils.getMaxFirstLevel(properties, flags)).toEqual(expected); + }); + + each([ + ["empty properties, empty flags",{}, {}, 1], + ["null properties, undefined flags",null, undefined, 1], + ["wrong field, flag is on", {max_instances:3}, {FLAG_2002_UNLIMITED_MAX: true}, null], + ["maxCountInstances 3, flag is on", {maxCountInstances:3}, {FLAG_2002_UNLIMITED_MAX: true}, 3], + ["maxCountInstances 3, flag is off", {maxCountInstances:3}, {FLAG_2002_UNLIMITED_MAX: true}, 3], + ]).test('getMaxFirstLevel %s', (desc, properties, flags, expected) => { + expect(Utils.getMaxVfModule(properties, flags)).toEqual(expected); + }); + + + }); diff --git a/vid-webpack-master/src/app/shared/utils/utils.ts b/vid-webpack-master/src/app/shared/utils/utils.ts index cd7ebdff6..3db770738 100644 --- a/vid-webpack-master/src/app/shared/utils/utils.ts +++ b/vid-webpack-master/src/app/shared/utils/utils.ts @@ -3,11 +3,18 @@ import * as _ from 'lodash' export class Utils { static getMaxFirstLevel(properties, flags: { [key: string]: boolean }) : number | null{ - if (flags && !!flags['FLAG_2002_UNLIMITED_MAX']) { - return !_.isNil(properties) && !_.isNil(properties.max_instances) ? properties.max_instances : null; - } else { - return properties.max_instances || 1; + return this.getMaxInstancesAllowed(properties, 'max_instances', flags) + } + + static getMaxVfModule(properties, flags: { [key: string]: boolean }) : number | null{ + return this.getMaxInstancesAllowed(properties, 'maxCountInstances', flags) + } + + static getMaxInstancesAllowed(properties, filedName: string, flags: { [key: string]: boolean }) : number | null{ + if (!_.isNil(properties) && !_.isNil(properties[filedName])) { + return properties[filedName]; } + return (flags && !!flags['FLAG_2002_UNLIMITED_MAX']) ? null : 1; } public static clampNumber = (number, min, max) => { |