Merge "Adding filter (Implement in FE) + cypress + tests"
authorEylon Malin <eylon.malin@intl.att.com>
Thu, 12 Dec 2019 12:27:34 +0000 (12:27 +0000)
committerGerrit Code Review <gerrit@onap.org>
Thu, 12 Dec 2019 12:27:34 +0000 (12:27 +0000)
16 files changed:
vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpServerTest.java
vid-app-common/src/test/java/org/onap/vid/client/SyncRestClientForHttpsServerTest.java
vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json
vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts
vid-webpack-master/cypress/integration/iFrames/drawingBoard.e2e.ts
vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts
vid-webpack-master/cypress/support/steps/fill.vfModule.step.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html
vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.scss
vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.ts
vid-webpack-master/src/app/shared/models/vfModule.ts
vid-webpack-master/src/app/shared/utils/util.spec.ts
vid-webpack-master/src/app/shared/utils/utils.ts

index 5a2eb59..bf33eff 100644 (file)
@@ -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());
index 645b5ea..27cd81e 100644 (file)
@@ -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);
index 04b0961..a8417e3 100644 (file)
@@ -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": [
               {}
             ],
       "isFailed": false,
       "statusMessage": null,
       "position": null,
-      "lineOfBusiness": "EMANUEL-CONSUMER"
+      "lineOfBusiness": "zzz1"
     }
   },
   "networks": {},
index 1c91d02..fa628d4 100644 (file)
@@ -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});
-          });
-        });
-      });
-    }
+
 
 
   });
index b678702..133dbe7 100644 (file)
@@ -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,
index 8eb70b1..afad687 100644 (file)
@@ -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");
   }
-
-});
index d297783..b87e773 100644 (file)
@@ -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);
index 225d84b..276c0ae 100644 (file)
@@ -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",
index e182b8a..1ce4527 100644 (file)
@@ -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 } } {
index f9da426..f9a11ea 100644 (file)
@@ -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)">
index 159871f..3939e44 100644 (file)
@@ -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);
-  }
 }
 
 
index c18b20d..1d44a9e 100644 (file)
@@ -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);
index c752021..8f92ba4 100644 (file)
@@ -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
     }
index 4b39764..ae39238 100644 (file)
@@ -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);
+  });
+
+
+
 });
index cd7ebdf..3db7707 100644 (file)
@@ -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) => {