Merge "RoleManageController up"
diff --git a/ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/scheduler/client/HttpsBasicClient.java b/ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/scheduler/client/HttpsBasicClient.java
index d618a6e..c79d6c0 100644
--- a/ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/scheduler/client/HttpsBasicClient.java
+++ b/ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/scheduler/client/HttpsBasicClient.java
@@ -77,8 +77,7 @@
 	public static Client getClient() throws Exception {
 		String methodName = "getClient";
 		ClientConfig config = new ClientConfig();
-		//config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
-		//config.getClasses().add(org.onap.aai.util.CustomJacksonJaxBJsonProvider.class);
+
 	
 		SSLContext ctx = null;
 		
@@ -87,17 +86,17 @@
 			SimpleDateFormat dateFormat = DateUtil.getDateFormat();
 			config.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
 			
-			String truststore_path = SchedulerProperties.getProperty(SchedulerProperties.VID_TRUSTSTORE_FILENAME);
+			String truststorePath = SchedulerProperties.getProperty(SchedulerProperties.VID_TRUSTSTORE_FILENAME);
 			logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + " " + methodName + " "
 				+ "truststore_path=" +
-				truststore_path);
-			String truststore_password = SchedulerProperties.getProperty(SchedulerProperties.VID_TRUSTSTORE_PASSWD_X);
+				truststorePath);
+			String truststorePassword = SchedulerProperties.getProperty(SchedulerProperties.VID_TRUSTSTORE_PASSWD_X);
 			
 			
-			String decrypted_truststore_password = Password.deobfuscate(truststore_password);
+			String decryptedTruststorePassword = Password.deobfuscate(truststorePassword);
 			//logger.debug(dateFormat.format(new Date()) + " " + methodName + " decrypted_truststore_password=" + decrypted_truststore_password);
 			
-			File tr = new File (truststore_path);
+			File tr = new File (truststorePath);
 			logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + " " + methodName + " absolute "
 				+ "truststore path=" + tr.getAbsolutePath());
 			
@@ -105,8 +104,8 @@
 			//String keystore_password = SystemProperties.getProperty(AAIProperties.AAI_KEYSTORE_PASSWD_X);
 			//String decrypted_keystore_password = EncryptedPropValue.decryptTriple(keystore_password);
 			
-		    System.setProperty("javax.net.ssl.trustStore", truststore_path);
-		    System.setProperty("javax.net.ssl.trustStorePassword", decrypted_truststore_password);
+		    System.setProperty("javax.net.ssl.trustStore", truststorePath);
+		    System.setProperty("javax.net.ssl.trustStorePassword", decryptedTruststorePassword);
 			HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier(){
 			    public boolean verify(String string,SSLSession ssls) {
 			        return true;
@@ -134,9 +133,7 @@
 			ctx.init(kmf.getKeyManagers(), null, null);
 			*/
 			ctx.init(null, null, null);
-			//config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, 
-			//							new HTTPSProperties( , ctx));
-			
+
 			return ClientBuilder.newBuilder()
 				.sslContext(ctx)
 				.hostnameVerifier(new HostnameVerifier() {
@@ -148,17 +145,9 @@
 				.build()
 				.register(CustomJacksonJaxBJsonProvider.class);
 			
-		} catch (Exception e) {
-			logger.debug(EELFLoggerDelegate.debugLogger, "Error setting up config: exiting");
-			//System.out.println("Error setting up config: exiting");
-			e.printStackTrace();
-			return null;
-		}
-			
-		//Client client = ClientBuilder.newClient(config);
-		// uncomment this line to get more logging for the request/response
-		// client.addFilter(new LoggingFilter(System.out));
-		
-		//return client;
-	}
-}  
+        } catch (Exception e) {
+            logger.debug(EELFLoggerDelegate.debugLogger, "Error setting up config: exiting", e);
+            return null;
+        }
+    }
+}
diff --git a/ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/service/ApplicationsRestClientServiceImpl.java b/ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/service/ApplicationsRestClientServiceImpl.java
index 18dabfb..09d7804 100644
--- a/ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/service/ApplicationsRestClientServiceImpl.java
+++ b/ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/service/ApplicationsRestClientServiceImpl.java
@@ -133,7 +133,7 @@
 		logger.debug(EELFLoggerDelegate.debugLogger, "http response status=" + status);
 		MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE, Integer.toString(status));
 		if (!isHttpSuccess(status)) {
-			String errMsg = "Failed. Status=" + status + restPath +"; [" + ((ResponseImpl)response).getStatusInfo().getReasonPhrase().toString()
+			String errMsg = "Failed. Status=" + status + restPath +"; [" + ((ResponseImpl)response).getStatusInfo().getReasonPhrase()
 					+ "]";
 			URL url = null;
 			try {
@@ -255,7 +255,6 @@
 		Response response = getResponse(appId, restPath);
 
 		if (response != null) {
-			//verifyResponse(response);
 			verifyResponse(response,restPath);
 			/* It is not recommendable to use the implementation class org.apache.cxf.jaxrs.impl.ResponseImpl in the code, 
 			but had to force this in-order to prevent conflict with the ResponseImpl class of Jersey Client which 
@@ -278,13 +277,11 @@
 		Response response = getResponse(appId, restPath);
 
 		if (response != null) {
-			//verifyResponse(response);
 			verifyResponse(response,restPath);
 			/* It is not recommendable to use the implementation class org.apache.cxf.jaxrs.impl.ResponseImpl in the code, 
 			but had to force this in-order to prevent conflict with the ResponseImpl class of Jersey Client which 
 			doesn't work as expected. Created Portal-253 for tracking  */
-			String incomingJson = ((ResponseImpl)response).readEntity(String.class);
-			return incomingJson;
+			return ((ResponseImpl)response).readEntity(String.class);
 		}
 		
 		return "";
@@ -308,7 +305,6 @@
 		Response response = getResponse(appId, restPath);
 
 		if (response != null) {
-			//verifyResponse(response);
 			verifyResponse(response,restPath);
 			String str = ((ResponseImpl)response).readEntity(String.class);
 			EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
@@ -316,7 +312,6 @@
 			try {
 				t = mapper.readValue(str, clazz);
 			} catch (Exception e) {
-				e.printStackTrace();
 				EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
 			}
 		}
@@ -373,16 +368,12 @@
 		}
 
 		if (response != null) {
-			//verifyResponse(response);
 			verifyResponse(response,restPath);
-			// String contentType = response.getHeaderString("Content-Type");
 			if (clazz != null) {
 				String str = ((ResponseImpl)response).readEntity(String.class);
 				EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST result =", str);
 				try {
 					t = (T) gson.fromJson(str, clazz);
-
-					//t = gson.fromJson(str, clazz);
 				} catch (Exception e) {
 					EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
 				}
@@ -430,7 +421,6 @@
 		}
 
 		if (response != null) {
-			//verifyResponse(response);
 			verifyResponse(response,restPath);
 			String str = ((ResponseImpl)response).readEntity(String.class);
 			EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT result =", str);
diff --git a/ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/service/MicroserviceServiceImpl.java b/ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/service/MicroserviceServiceImpl.java
index b41d898..451500d 100644
--- a/ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/service/MicroserviceServiceImpl.java
+++ b/ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/service/MicroserviceServiceImpl.java
@@ -136,7 +136,6 @@
 			dataAccessService.executeNamedQuery("deleteMicroservice", params, null);
 
 		} catch (Exception e) {
-			e.printStackTrace();
 			logger.error(EELFLoggerDelegate.errorLogger, "deleteMicroservice failed", e);
 			throw e;
 		}
diff --git a/ecomp-portal-BE-os/pom.xml b/ecomp-portal-BE-os/pom.xml
index e8c8d5b..7ab6cc4 100644
--- a/ecomp-portal-BE-os/pom.xml
+++ b/ecomp-portal-BE-os/pom.xml
@@ -231,6 +231,11 @@
 			<artifactId>spring-tx</artifactId>
 			<version>${springframework.version}</version>
 		</dependency>
+		<dependency> 
+			<groupId>org.springframework</groupId> 
+			<artifactId>spring-expression</artifactId> 
+			<version>${springframework.version}</version> 
+		</dependency>
 		<dependency>
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-context-support</artifactId>
diff --git a/ecomp-portal-BE-os/src/main/webapp/WEB-INF/jsp/login.jsp b/ecomp-portal-BE-os/src/main/webapp/WEB-INF/jsp/login.jsp
index 99c5af4..2fc9ed3 100644
--- a/ecomp-portal-BE-os/src/main/webapp/WEB-INF/jsp/login.jsp
+++ b/ecomp-portal-BE-os/src/main/webapp/WEB-INF/jsp/login.jsp
@@ -45,7 +45,7 @@
 	value="<%=(SystemProperties.getProperty(SystemProperties.MOBILE_ENABLE)!= null && SystemProperties.getProperty(SystemProperties.MOBILE_ENABLE).trim().equals(\"true\"))%>" />
 
 <!DOCTYPE html>
-<html ng-app="abs">
+<html>
 	<head>
 		<link rel="shortcut icon" href="assets/images/1cc621d2.ecomp_logo.png">
 	    <title>
@@ -54,11 +54,8 @@
 		<meta charset="utf-8">
 		<meta http-equiv="X-UA-Compatible" content="IE=edge">
 		<meta name="viewport" content="width=device-width, initial-scale=1"> 
-	<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
+		<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
 		<script src="static/js/jquery-1.10.2.js" type="text/javascript"></script>
-		<script src= "static/ebz/angular_js/angular.js"></script> 
-		<script src= "static/ebz/angular_js/angular-sanitize.js"></script>
-		<script src= "static/ebz/angular_js/gestures.js"></script>
 		<style>
 			.terms {
 				font-family: Verdana,Arial,Helvetica, sans-serif;
@@ -103,7 +100,7 @@
 	<% 
        String frontUrl = SystemProperties.getProperty(EPSystemProperties.FE_URL);
     %>
-	<div ng-controller="externalLoginController">
+	<div>
 		<div class="centered style="-webkit-transform: translateZ(0);background:white, z-index:0;">
 			<div align="center" id="errorInfo" style="display:none; float:left; font-family: Arial; font-size:12px; margin-left:5px">
 				<span style="color:red">Invalid username or password. Please try again.</span>
@@ -119,7 +116,7 @@
 								<label class="login-txt">Login ID:</label>
 							</td>
 							<td>
-								<input type="text" class="login-input-text" ng-model="loginId" maxlength="30" />
+								<input type="text" class="login-input-text" id="loginId" maxlength="30" />
 							</td>
 						</tr>
 						<tr>
@@ -127,13 +124,13 @@
 								<label class="login-txt">Password:</label>
 							</td>
 							<td>
-								<input type="password" class="login-input-text" ng-model="password" maxlength="30" 
+								<input type="password" class="login-input-text" id="password" maxlength="30" 
 									onkeydown="if (event.keyCode == 13) document.getElementById('loginBtn').click()"/>
 							</td>
 						</tr>
 					</table> 
 					<br />
-					<a class="login-btn" id="loginBtn" ng-click="loginExternal();">LOGIN</a>
+					<a class="login-btn" id="loginBtn">LOGIN</a>
 				</div>
 				<br>
 			</div>
@@ -141,55 +138,36 @@
 		<br/><br/><br/><br/><br/><br/><br/>
     </div>
     </body>
-<script>
-var app=angular.module("abs", []);
-app.controller("externalLoginController", function ($scope) { 
-	// Table Data
 	
-	$scope.viewPerPage = 200;
-	$scope.currentPage = 2;
-	$scope.totalPage;
-	$scope.searchCategory = "";
-	$scope.searchString = "";
-	$scope.loginId="";
-	$scope.password="";
-	$scope.loginError=true;
-	$scope.viewPerPage = 200;
-	$scope.currentPage = 2;
-	$scope.totalPage;
-	$scope.searchCategory = "";
-	$scope.searchString = "";
-	$scope.loginId="";
-	$scope.password="";
-	$scope.loginUrl = "";
-	
-	$scope.loginExternal = function() {
-		var postData={loginId:$scope.loginId,password:$scope.password};
-		$.ajax({
-	            url: "open_source/login?",
-                type : "POST",
-		  		 dataType: 'json',
-		  		 contentType: 'application/json',
-		  		 data: JSON.stringify(postData),                
-                success:function (response){
-                  if(response.success=="success"){
-                    //window.location.href = 'applicationsHome';
-                    window.location.href= "<%=frontUrl%>",
-                    sessionStorage.setItem('userId',$scope.loginId)
-                  }else{
-                	$("#errorInfo span").text(response);
-                	//$("#errorInfo").text = response;
-                	$("#errorInfo").show();
-                  }
-                },
-                error:function( jqXHR, status,error ){
-                	$("#errorInfo").show();
-                }
-                
-        });
-
-    };
-});
-</script>
-	
+	<script>
+		$( document ).ready(function() {
+			$(".login-btn").click(function(){
+				var loginIdVal = $("#loginId").val();
+				var passwordVal = $("#password").val();
+				var postData={loginId:loginIdVal,password:passwordVal};
+				$.ajax({
+					url: "open_source/login?",
+					type : "POST",
+					dataType: 'json',
+					contentType: 'application/json',
+					data: JSON.stringify(postData),                
+					success:function (response){
+					  if(response.success=="success"){
+						//window.location.href = 'applicationsHome';
+						window.location.href= "<%=frontUrl%>",
+						sessionStorage.setItem('userId',loginIdVal)
+					  }else{
+						$("#errorInfo span").text(response);
+						//$("#errorInfo").text = response;
+						$("#errorInfo").show();
+					  }
+					},
+					error:function( jqXHR, status,error ){
+						$("#errorInfo").show();
+					}
+						
+				});
+			});
+		});
+	</script>
 </html>
diff --git a/pom.xml b/pom.xml
index 3fe2b71..e26a406 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,6 +41,7 @@
 		<!-- <sonar.exclusions>**/scripts/**/*,**.js</sonar.exclusions>  -->
 		<sonar.test.exclusions>**/test/**/*,**/tests/**/*</sonar.test.exclusions>
 		<enforcer.skip>false</enforcer.skip>
+		<sonar.scm.exclusions.disabled>true</sonar.scm.exclusions.disabled>
 	</properties>
 
 	<!-- Specify the repositories here to avoid coordination of ~/.m2/settings.xml 
diff --git a/portal-FE-common/src/app/layout/components/footer/footer.component.html b/portal-FE-common/src/app/layout/components/footer/footer.component.html
index 6caf2dd..47a53cd 100644
--- a/portal-FE-common/src/app/layout/components/footer/footer.component.html
+++ b/portal-FE-common/src/app/layout/components/footer/footer.component.html
@@ -41,6 +41,8 @@
             <a class="footer-link" href="{{footerLink}}" target="_blank">
             {{footerLinkText}}</a> {{footerMessage}}
             {{brandName}} Version: {{buildVersion}}
-      <h2 style="color:white; text-align: center;" class="logo-title"> <img src="{{footerLogoImagePath}}"> {{footerLogoText}}</h2>
+      <h2 style="color:white; text-align: center;" class="logo-title"> 
+        <img *ngIf="(footerLogoImagePath !='')" src="{{footerLogoImagePath}}"> {{footerLogoText}}
+      </h2>
       </div>	
 </footer>
\ No newline at end of file
diff --git a/portal-FE-common/src/app/layout/components/footer/footer.component.ts b/portal-FE-common/src/app/layout/components/footer/footer.component.ts
index 9d7559e..422a673 100644
--- a/portal-FE-common/src/app/layout/components/footer/footer.component.ts
+++ b/portal-FE-common/src/app/layout/components/footer/footer.component.ts
@@ -69,7 +69,6 @@
     this.footerLink = this.api.footerLink;
     this.footerLinkText = this.api.footerLinkText;
     this.footerMessage= this.api.footerMessage;
-    this.footerLogoImagePath = "assets/images/global.logo"
     if(this.api.footerLogoImagePath !=''){
       this.footerLogoImagePath= this.api.footerLogoImagePath;
     }
diff --git a/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.spec.ts b/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.spec.ts
index e0df154..1ecba2c 100644
--- a/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.spec.ts
+++ b/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.spec.ts
@@ -42,17 +42,59 @@
 import { FormsModule } from '@angular/forms';
 import { NgMaterialModule } from 'src/app/ng-material-module';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { WidgetOnboardingService } from 'src/app/shared/services/widget-onboarding/widget-onboarding.service';
+import { Observable } from 'rxjs';
+import { HttpClientModule } from '@angular/common/http';
 
 describe('WidgetOnboardingComponent', () => {
   let component: WidgetOnboardingComponent;
   let fixture: ComponentFixture<WidgetOnboardingComponent>;
+  let widgetList = [{"id" :"1",
+    "name":"ONAP-A",
+    "desc" :"desc",
+    "fileLocation" : "fileLocation",
+    "allowAllUser" : "allowAllUser",
+    "serviceId" : "serviceId",
+    "serviceURL" : "serviceURL",
+    "sortOrder" : "sortOrder",
+    "statusCode" : "statusCode",
+    "widgetRoles": "widgetRoles",
+    "appContent" : "appContent",
+    "appName" : "appName",
+    "file"  : "file",
+    "allUser": false,
+    "saving": "saving"},{"id" :"1",
+    "name":"ONAP-B",
+    "desc" :"desc",
+    "fileLocation" : "fileLocation",
+    "allowAllUser" : "allowAllUser",
+    "serviceId" : "serviceId",
+    "serviceURL" : "serviceURL",
+    "sortOrder" : "sortOrder",
+    "statusCode" : "statusCode",
+    "widgetRoles": "widgetRoles",
+    "appContent" : "appContent",
+    "appName" : "appName",
+    "file"  : "file",
+    "allUser": false,
+    "saving": "saving"}]
+
 
   beforeEach(async(() => {
+    let widgetOnboardingService: WidgetOnboardingService;
+    
+   // widgetOnboardingService = jasmine.createSpyObj('WidgetOnboardingService', ['getManagedWidgets']);
+    //widgetOnboardingService.getManagedWidgets.and.returnValue(Observable.of(widgetList));
     TestBed.configureTestingModule({
       declarations: [ WidgetOnboardingComponent ],
-      imports:[HttpClientTestingModule,FormsModule,NgMaterialModule,BrowserAnimationsModule],
+      imports:[HttpClientModule,FormsModule,NgMaterialModule,BrowserAnimationsModule],
+      providers:[WidgetOnboardingService]
     })
     .compileComponents();
+
+
+    widgetOnboardingService = TestBed.get(WidgetOnboardingService);
+    spyOn(widgetOnboardingService, 'getManagedWidgets').and.returnValue(Observable.of(widgetList));
   }));
 
   beforeEach(() => {
@@ -61,7 +103,14 @@
     fixture.detectChanges();
   });
 
+  
+
   it('should create', () => {
     expect(component).toBeTruthy();
   });
+  it('getOnboardingWidgets should return stubbed value', () => {
+    spyOn(component, 'getOnboardingWidgets').and.callThrough();
+    component.getOnboardingWidgets();
+    expect(component.getOnboardingWidgets).toHaveBeenCalledWith();
+  });
 });
diff --git a/portal-FE-common/src/app/shared/model/widget-onboarding/widget.ts b/portal-FE-common/src/app/shared/model/widget-onboarding/widget.ts
index ba1842f..930d598 100644
--- a/portal-FE-common/src/app/shared/model/widget-onboarding/widget.ts
+++ b/portal-FE-common/src/app/shared/model/widget-onboarding/widget.ts
@@ -5,29 +5,29 @@
  * Copyright © 2019 AT&T Intellectual Property. All rights reserved.
  * ===================================================================
  *
- * Unless otherwise specified?: any; all software contained herein is licensed
- * under the Apache License?: any; Version 2.0 (the "License");
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
  * you may not use this software 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?: any; software
- * distributed under the License is distributed on an "AS IS" BASIS?: any;
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND?: any; either express or implied.
+ * 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.
  *
- * Unless otherwise specified?: any; all documentation contained herein is licensed
- * under the Creative Commons License?: any; Attribution 4.0 Intl. (the "License");
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
  * you may not use this documentation except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *             https://creativecommons.org/licenses/by/4.0/
  *
- * Unless required by applicable law or agreed to in writing?: any; documentation
- * distributed under the License is distributed on an "AS IS" BASIS?: any;
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND?: any; either express or implied.
+ * Unless required by applicable law or agreed to in writing, documentation
+ * 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.
  *
@@ -51,4 +51,4 @@
     file  ?: any;
     allUser ?: boolean;
     saving ?: any
-}
\ No newline at end of file
+}
diff --git a/portal-FE-os/package.json b/portal-FE-os/package.json
index 77cef69..4371bc4 100644
--- a/portal-FE-os/package.json
+++ b/portal-FE-os/package.json
@@ -61,11 +61,13 @@
     "jasmine-core": "~2.99.1",
     "jasmine-spec-reporter": "~4.2.1",
     "karma": "~3.0.0",
-    "karma-chrome-launcher": "~2.2.0",
+    "karma-chrome-launcher": "^2.2.0",
     "karma-coverage-istanbul-reporter": "~2.0.1",
     "karma-jasmine": "~1.1.2",
     "karma-jasmine-html-reporter": "^0.2.2",
+    "karma-phantomjs-launcher": "^1.0.4",
     "protractor": "~5.4.0",
+    "puppeteer": "^2.1.1",
     "sonar-scanner": "^3.1.0",
     "ts-node": "~7.0.0",
     "tslint": "~5.11.0",
diff --git a/portal-FE-os/pom.xml b/portal-FE-os/pom.xml
index 21bdd50..fd497e1 100644
--- a/portal-FE-os/pom.xml
+++ b/portal-FE-os/pom.xml
@@ -4,7 +4,7 @@
 
 	<groupId>org.onap.portal</groupId>
 	<artifactId>portal-FE-os</artifactId>
-	<version>3.1.0</version>
+	<version>3.2.0</version>
 
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -18,6 +18,7 @@
 		<sonar.test.inclusions>**/*.spec.ts</sonar.test.inclusions>
 		<sonar.tests>src</sonar.tests>
 		<sonar.sourceEncoding>UTF-8</sonar.sourceEncoding>
+		<sonar.nodejs.executable>${project.basedir}\node\</sonar.nodejs.executable>
 	</properties>
 
 	<build>
diff --git a/portal-FE-os/src/karma.conf.js b/portal-FE-os/src/karma.conf.js
index b6e0042..154ad58 100644
--- a/portal-FE-os/src/karma.conf.js
+++ b/portal-FE-os/src/karma.conf.js
@@ -1,6 +1,7 @@
 // Karma configuration file, see link for more information
 // https://karma-runner.github.io/1.0/config/configuration-file.html
 
+process.env.CHROME_BIN = require('puppeteer').executablePath()
 module.exports = function (config) {
   config.set({
     basePath: '',
@@ -10,6 +11,7 @@
       require('karma-chrome-launcher'),
       require('karma-jasmine-html-reporter'),
       require('karma-coverage-istanbul-reporter'),
+      require('karma-phantomjs-launcher'),
       require('@angular-devkit/build-angular/plugins/karma')
     ],
     client: {
@@ -25,7 +27,7 @@
     colors: true,
     logLevel: config.LOG_INFO,
     autoWatch: true,
-    browsers: ['Chrome'],
+    browsers: ['ChromeHeadless'],
     singleRun: false
   });
 };
\ No newline at end of file