metron-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mmiklav...@apache.org
Subject [17/24] metron git commit: METRON-1834: Migrate Elasticsearch from TransportClient to new Java REST API (mmiklavc via mmiklavc) closes apache/metron#1242
Date Fri, 16 Nov 2018 00:06:16 GMT
http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.spec.ts b/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.spec.ts
index 899a2b1..a953b32 100644
--- a/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.spec.ts
@@ -16,7 +16,6 @@
  * limitations under the License.
  */
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-import { Component, Input } from '@angular/core';
 
 import { SavedSearchesComponent } from './saved-searches.component';
 import { CollapseComponent } from '../../shared/collapse/collapse.component';
@@ -24,8 +23,8 @@ import { CenterEllipsesPipe } from '../../shared/pipes/center-ellipses.pipe';
 import { ColumnNameTranslatePipe } from '../../shared/pipes/column-name-translate.pipe';
 import { Router } from '@angular/router';
 import { SaveSearchService } from '../../service/save-search.service';
-import { MetronDialogBox } from '../../shared/metron-dialog-box';
 import { of } from 'rxjs';
+import { DialogService } from 'app/service/dialog.service';
 
 
 describe('SavedSearchesComponent', () => {
@@ -40,7 +39,7 @@ describe('SavedSearchesComponent', () => {
           listSavedSearches: jasmine.createSpy('listSavedSearches').and.returnValue(of([])),
           listRecentSearches: jasmine.createSpy('listRecentSearches').and.returnValue(of([])),
         } },
-        MetronDialogBox
+        DialogService
       ],
       declarations: [
         SavedSearchesComponent,

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.ts b/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.ts
index 2204179..ab182c0 100644
--- a/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/saved-searches/saved-searches.component.ts
@@ -22,9 +22,10 @@ import {forkJoin as observableForkJoin} from 'rxjs';
 
 import {SaveSearchService} from '../../service/save-search.service';
 import {SaveSearch} from '../../model/save-search';
-import {MetronDialogBox} from '../../shared/metron-dialog-box';
 import {NUM_SAVED_SEARCH} from '../../utils/constants';
 import {CollapseComponentData, CollapseComponentDataItems} from '../../shared/collapse/collapse-component-data';
+import { DialogService } from 'app/service/dialog.service';
+import { ConfirmationType } from 'app/model/confirmation-type';
 
 @Component({
   selector: 'app-saved-searches',
@@ -39,7 +40,7 @@ export class SavedSearchesComponent implements OnInit {
   recentSearches: CollapseComponentData = new CollapseComponentData();
   constructor(private router: Router,
               private saveSearchService: SaveSearchService,
-              private metronDialog: MetronDialogBox) {
+              private dialogService: DialogService) {
   }
 
   doDeleteRecentSearch(selectedSearch: SaveSearch) {
@@ -61,21 +62,33 @@ export class SavedSearchesComponent implements OnInit {
   }
 
   deleteRecentSearch($event) {
-    let selectedSearch = this.recentSearcheObj.find(savedSearch => savedSearch.name === $event.key);
-    this.metronDialog.showConfirmationMessage('Do you wish to delete recent search ' + selectedSearch.name).subscribe((result: boolean) => {
-      if (result) {
-        this.doDeleteRecentSearch(selectedSearch);
-      }
-    });
+    let selectedSearch = this.recentSearcheObj.find(
+      savedSearch => savedSearch.name === $event.key
+    );
+    const confirmedSubscription = this.dialogService
+      .launchDialog(
+        'Do you wish to delete recent search ' + selectedSearch.name
+      )
+      .subscribe(action => {
+        if (action === ConfirmationType.Confirmed) {
+          this.doDeleteRecentSearch(selectedSearch);
+        }
+        confirmedSubscription.unsubscribe();
+      });
   }
 
   deleteSearch($event) {
-    let selectedSearch = this.searches.find(savedSearch => savedSearch.name === $event.key);
-    this.metronDialog.showConfirmationMessage('Do you wish to delete saved search ' + selectedSearch.name).subscribe((result: boolean) => {
-      if (result) {
-        this.doDeleteSearch(selectedSearch);
-      }
-    });
+    let selectedSearch = this.searches.find(
+      savedSearch => savedSearch.name === $event.key
+    );
+    const confirmedSubscription = this.dialogService
+      .launchDialog('Do you wish to delete saved search ' + selectedSearch.name)
+      .subscribe(action => {
+        if (action === ConfirmationType.Confirmed) {
+          this.doDeleteSearch(selectedSearch);
+        }
+        confirmedSubscription.unsubscribe();
+      });
   }
 
   ngOnInit() {

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/app.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/app.component.html b/metron-interface/metron-alerts/src/app/app.component.html
index c3a5d3c..d94a6d7 100644
--- a/metron-interface/metron-alerts/src/app/app.component.html
+++ b/metron-interface/metron-alerts/src/app/app.component.html
@@ -30,6 +30,7 @@
         <router-outlet></router-outlet>
     </div>
     <router-outlet name="dialog" ></router-outlet>
+    <app-metron-dialog></app-metron-dialog>
 </div>
 
 

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/app.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/app.component.spec.ts b/metron-interface/metron-alerts/src/app/app.component.spec.ts
index ce38c22..1485904 100644
--- a/metron-interface/metron-alerts/src/app/app.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/app.component.spec.ts
@@ -21,6 +21,8 @@ import { AppComponent } from './app.component';
 import { Component } from '@angular/core';
 import { AuthenticationService } from './service/authentication.service';
 import { of } from 'rxjs';
+import { DialogService } from './service/dialog.service';
+import { MetronDialogComponent } from './shared/metron-dialog/metron-dialog.component';
 
 @Component({ selector: 'router-outlet', template: '' })
 class RouterOutletStubComponent {}
@@ -32,10 +34,12 @@ describe('AppComponent', () => {
   beforeEach(async(() => {
     TestBed.configureTestingModule({
       providers: [
+        DialogService,
         { provide: AuthenticationService, useValue: { onLoginEvent: of(true) } }
       ],
       declarations: [
         AppComponent,
+        MetronDialogComponent,
         RouterOutletStubComponent,
       ],
     }).compileComponents();

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/app.module.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/app.module.ts b/metron-interface/metron-alerts/src/app/app.module.ts
index 44e2650..a605b80 100644
--- a/metron-interface/metron-alerts/src/app/app.module.ts
+++ b/metron-interface/metron-alerts/src/app/app.module.ts
@@ -31,7 +31,6 @@ import {ConfigureTableService} from './service/configure-table.service';
 import {SaveSearchModule} from './alerts/save-search/save-search.module';
 import {SaveSearchService} from './service/save-search.service';
 import {SavedSearchesModule} from './alerts/saved-searches/saved-searches.module';
-import {MetronDialogBox} from './shared/metron-dialog-box';
 import {ConfigureRowsModule} from './alerts/configure-rows/configure-rows.module';
 import {SwitchModule} from './shared/switch/switch.module';
 import {ColumnNamesService} from './service/column-names.service';
@@ -47,6 +46,9 @@ import {MetaAlertsModule} from './alerts/meta-alerts/meta-alerts.module';
 import {SearchService} from './service/search.service';
 import { GlobalConfigService } from './service/global-config.service';
 import { DefaultHeadersInterceptor } from './http-interceptors/default-headers.interceptor';
+import { DialogService } from './service/dialog.service';
+import { MetronDialogComponent } from './shared/metron-dialog/metron-dialog.component';
+
 
 
 import {PcapModule} from './pcap/pcap.module';
@@ -57,7 +59,8 @@ export function initConfig(config: ColumnNamesService) {
 
 @NgModule({
   declarations: [
-    AppComponent
+    AppComponent,
+    MetronDialogComponent
   ],
   imports: [
     BrowserModule,
@@ -84,11 +87,12 @@ export function initConfig(config: ColumnNamesService) {
               ConfigureTableService,
               SearchService,
               SaveSearchService,
-              MetronDialogBox,
               ColumnNamesService,
               UpdateService,
               MetaAlertService,
-              GlobalConfigService],
+              GlobalConfigService,
+              DialogService,
+            ],
   bootstrap: [AppComponent]
 })
 

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/model/confirmation-type.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/model/confirmation-type.ts b/metron-interface/metron-alerts/src/app/model/confirmation-type.ts
new file mode 100644
index 0000000..5441a9e
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/model/confirmation-type.ts
@@ -0,0 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export enum ConfirmationType {
+  Confirmed = 'Confirmed',
+  Rejected = 'Rejected'
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/model/dialog-type.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/model/dialog-type.ts b/metron-interface/metron-alerts/src/app/model/dialog-type.ts
new file mode 100644
index 0000000..0cd398e
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/model/dialog-type.ts
@@ -0,0 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export enum DialogType {
+  Confirmation,
+  Error
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
index f767020..fdd75f7 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
@@ -35,11 +35,6 @@ export class PcapPanelComponent implements OnInit, OnDestroy {
   pdml: Pdml = null;
   pcapRequest: PcapRequest;
   resetPaginationForSearch: boolean;
-
-  statusSubscription: Subscription;
-  cancelSubscription: Subscription;
-  submitSubscription: Subscription;
-  getSubscription: Subscription;
   queryRunning = false;
   queryId: string;
   progressWidth = 0;
@@ -47,28 +42,33 @@ export class PcapPanelComponent implements OnInit, OnDestroy {
   savedPcapRequest: {};
   errorMsg: string;
   cancelConfirmMessage = 'Are you sure want to cancel the running query?';
+  subscriptions: {
+    [key: string]: Subscription
+  } = {};
 
   constructor(private pcapService: PcapService) { }
 
   ngOnInit() {
     this.pcapRequest = new PcapRequest();
-    this.pcapService.getRunningJob().subscribe((statusResponses: PcapStatusResponse[]) => {
+    this.subscriptions['runningJobSubscription'] = this.pcapService.getRunningJob().subscribe((statusResponses: PcapStatusResponse[]) => {
       if (statusResponses.length > 0) {
         // Assume the first job in the list is the running job
         this.queryRunning = true;
         let statusResponse = statusResponses[0];
         this.updateStatus(statusResponse);
         this.startPolling(statusResponse.jobId);
-        this.pcapService.getPcapRequest(statusResponse.jobId).subscribe((pcapRequest: PcapRequest) => {
-          this.pcapRequest = pcapRequest;
-        });
+        this.subscriptions['pcapRequestSubscription'] = this.pcapService.getPcapRequest(statusResponse.jobId).subscribe(
+          (pcapRequest: PcapRequest) => {
+            this.pcapRequest = pcapRequest;
+          }
+        );
       }
     });
   }
 
   changePage(page) {
     this.pagination.selectedPage = page;
-    this.pcapService.getPackets(this.queryId, this.pagination.selectedPage).toPromise().then(pdml => {
+    this.subscriptions['packetSubscription'] = this.pcapService.getPackets(this.queryId, this.pagination.selectedPage).subscribe(pdml => {
       this.pdml = pdml;
     });
   }
@@ -81,26 +81,28 @@ export class PcapPanelComponent implements OnInit, OnDestroy {
     this.pdml = null;
     this.progressWidth = 0;
     this.errorMsg = null;
-    this.submitSubscription = this.pcapService.submitRequest(pcapRequest).subscribe((submitResponse: PcapStatusResponse) => {
-      let id = submitResponse.jobId;
-      if (!id) {
-        this.errorMsg = submitResponse.description;
-        this.queryRunning = false;
-      } else {
-        this.startPolling(id);
+    this.subscriptions['submitSubscription'] = this.pcapService.submitRequest(pcapRequest).subscribe(
+      (submitResponse: PcapStatusResponse) => {
+        let id = submitResponse.jobId;
+        if (!id) {
+          this.errorMsg = submitResponse.description;
+          this.queryRunning = false;
+        } else {
+          this.startPolling(id);
+        }
+      }, (error: any) => {
+        this.errorMsg = `Response message: ${error.message}. Something went wrong with your query submission!`;
       }
-    }, (error: any) => {
-      this.errorMsg = `Response message: ${error.message}. Something went wrong with your query submission!`;
-    });
+    );
   }
 
   startPolling(id: string) {
     this.queryId = id;
     this.errorMsg = null;
-    this.statusSubscription = this.pcapService.pollStatus(id).subscribe((statusResponse: PcapStatusResponse) => {
+    this.subscriptions['statusSubscription'] = this.pcapService.pollStatus(id).subscribe((statusResponse: PcapStatusResponse) => {
       this.updateStatus(statusResponse);
     }, (error: any) => {
-      this.statusSubscription.unsubscribe();
+      this.subscriptions['statusSubscription'].unsubscribe();
       this.queryRunning = false;
       this.errorMsg = `Response message: ${error.message}. Something went wrong with your status request!`;
     });
@@ -109,9 +111,9 @@ export class PcapPanelComponent implements OnInit, OnDestroy {
   updateStatus(statusResponse: PcapStatusResponse) {
     if ('SUCCEEDED' === statusResponse.jobStatus) {
       this.pagination.total = statusResponse.pageTotal;
-      this.statusSubscription.unsubscribe();
+      this.subscriptions['statusSubscription'].unsubscribe();
       this.queryRunning = false;
-      this.pcapService.getPackets(this.queryId, this.pagination.selectedPage).toPromise().then(pdml => {
+      this.subscriptions['packetSubscription'] = this.pcapService.getPackets(this.queryId, this.pagination.selectedPage).subscribe(pdml => {
         this.pdml = pdml;
       }, (error: RestError) => {
         if (error.status === 404) {
@@ -121,7 +123,7 @@ export class PcapPanelComponent implements OnInit, OnDestroy {
         }
       });
     } else if ('FAILED' === statusResponse.jobStatus) {
-      this.statusSubscription.unsubscribe();
+      this.subscriptions['statusSubscription'].unsubscribe();
       this.queryRunning = false;
       this.errorMsg = `Query status: ${statusResponse.jobStatus}. Check your filter criteria and try again!`;
     } else if (this.progressWidth < 100) {
@@ -134,25 +136,19 @@ export class PcapPanelComponent implements OnInit, OnDestroy {
   }
 
   unsubscribeAll() {
-    if (this.cancelSubscription) {
-      this.cancelSubscription.unsubscribe();
-    }
-    if (this.statusSubscription) {
-      this.statusSubscription.unsubscribe();
-    }
-    if (this.submitSubscription) {
-      this.submitSubscription.unsubscribe();
-    }
+    Object.keys(this.subscriptions).forEach((key) => {
+      this.subscriptions[key].unsubscribe();
+    });
+    this.subscriptions = {};
   }
 
   cancelQuery() {
-    this.cancelSubscription = this.pcapService.cancelQuery(this.queryId)
+    this.subscriptions['cancelSubscription'] = this.pcapService.cancelQuery(this.queryId)
       .subscribe(() => {
         this.unsubscribeAll();
         this.queryId = '';
         this.queryRunning = false;
       }, (error: any) => {
-        this.cancelSubscription.unsubscribe();
         this.queryId = '';
         this.errorMsg = `Response message: ${error.message}. Something went wrong with the cancellation!`;
         this.queryRunning = false;

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/service/dialog.service.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/service/dialog.service.spec.ts b/metron-interface/metron-alerts/src/app/service/dialog.service.spec.ts
new file mode 100644
index 0000000..521d74c
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/service/dialog.service.spec.ts
@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { TestBed, inject } from '@angular/core/testing';
+
+import {
+  DialogService,
+  DialogParams
+} from './dialog.service';
+import { DialogType } from '../model/dialog-type';
+import { ConfirmationType } from '../model/confirmation-type';
+
+describe('DialogService', () => {
+  let dialogService: DialogService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      providers: [DialogService]
+    });
+    dialogService = TestBed.get(DialogService);
+  });
+
+  it('should be created', inject([DialogService], (service: DialogService) => {
+    expect(service).toBeTruthy();
+  }));
+
+  describe('confirm()', () => {
+
+    it('should emit a message with the correct params', () => {
+      const messageSpy = spyOn(dialogService.message, 'next');
+      const testMessage = 'this is a test';
+      let messageEmit: DialogParams = {
+        message: testMessage,
+        show: true,
+        dialogType: DialogType.Confirmation
+      };
+
+      dialogService.launchDialog(testMessage);
+      expect(messageSpy).toHaveBeenCalledWith(messageEmit);
+
+      messageEmit.dialogType = DialogType.Error;
+      dialogService.launchDialog(testMessage, DialogType.Error);
+    });
+
+  });
+
+  describe('cancel()', () => {
+    it('should emit ConfirmationType.Rejected', () => {
+      const messageSpy = spyOn(dialogService.confirmed, 'next');
+
+      dialogService.cancel();
+      expect(messageSpy).toHaveBeenCalledWith(ConfirmationType.Rejected);
+    });
+  });
+
+  describe('approve()', () => {
+    it('should emit ConfirmationType.Confirmed', () => {
+      const messageSpy = spyOn(dialogService.confirmed, 'next');
+
+      dialogService.approve();
+      expect(messageSpy).toHaveBeenCalledWith(ConfirmationType.Confirmed);
+    });
+  });
+});

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/service/dialog.service.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/service/dialog.service.ts b/metron-interface/metron-alerts/src/app/service/dialog.service.ts
new file mode 100644
index 0000000..ad758a0
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/service/dialog.service.ts
@@ -0,0 +1,55 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, Subject } from 'rxjs';
+import { ConfirmationType } from '../model/confirmation-type';
+import { DialogType } from '../model/dialog-type';
+
+@Injectable({
+  providedIn: 'root'
+})
+
+export class DialogParams {
+  show = false;
+  message = '';
+  dialogType = DialogType.Confirmation;
+}
+
+export class DialogService {
+  message = new BehaviorSubject<DialogParams>(new DialogParams());
+  confirmed = new Subject<ConfirmationType>();
+
+  constructor() {}
+
+  launchDialog(message: string, dialogType = DialogType.Confirmation): Subject<ConfirmationType> {
+    this.message.next({
+      message: message,
+      show: true,
+      dialogType: dialogType
+    });
+    return this.confirmed;
+  }
+
+  approve() {
+    this.confirmed.next(ConfirmationType.Confirmed);
+  }
+
+  cancel() {
+    this.confirmed.next(ConfirmationType.Rejected);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/shared/metron-dialog-box.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/metron-dialog-box.ts b/metron-interface/metron-alerts/src/app/shared/metron-dialog-box.ts
deleted file mode 100644
index aaa2791..0000000
--- a/metron-interface/metron-alerts/src/app/shared/metron-dialog-box.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {EventEmitter}     from '@angular/core';
-
-declare var $;
-
-export enum DialogType {
-  Confirmation, Error
-};
-
-export class MetronDialogBox {
-  private static dialogType = DialogType;
-
-  private getCancelButton(type: DialogType): string {
-    if (type === DialogType.Confirmation) {
-      return `<button type="button" class="btn btn-mine_shaft_2" data-dismiss="modal">Cancel</button>`;
-    }
-
-    return '';
-  }
-
-  private createDialogBox(message: string, type: DialogType) {
-    let cancelButtonHTML = this.getCancelButton(type);
-    let html = `<div class="metron-dialog modal"  data-backdrop="static" >
-                  <div class="modal-dialog modal-sm" role="document">
-                    <div class="modal-content">
-                      <div class="modal-header">
-                        <span class="modal-title"><b>` + MetronDialogBox.dialogType[type] + `</b></span>
-                        <button type="button" class="close" data-dismiss="modal" aria-label="Close"> 
-                            <span aria-hidden="true">&times;</span> 
-                        </button>
-                      </div>
-                      <div class="modal-body">
-                        <p>` +  message + `</p>
-                      </div>
-                      <div class="modal-footer">
-                        <button type="button" class="btn btn-all_ports">OK</button>`
-                        + cancelButtonHTML +
-                      `</div>
-                    </div>
-                  </div>
-                </div>`;
-
-    let element = document.createElement('div');
-    element.innerHTML = html;
-
-    document.body.appendChild(element);
-
-    return element;
-  }
-
-  public showConfirmationMessage(message: string, dialogType = DialogType.Confirmation): EventEmitter<boolean> {
-    message = message.replace(/\n/g, '<br>');
-    let eventEmitter = new EventEmitter<boolean>();
-    let element = this.createDialogBox(message, dialogType);
-
-    $(element).find('.metron-dialog').modal('show');
-
-    $(element).find('.btn-all_ports').on('click', function (e) {
-      $(element).find('.metron-dialog').modal('hide');
-      eventEmitter.emit(true);
-    });
-
-    $(element).find('.btn-mine_shaft_2').on('click', function (e) {
-      $(element).find('.metron-dialog').modal('hide');
-      eventEmitter.emit(false);
-    });
-
-    $(element).find('.metron-dialog').on('hidden.bs.modal', function (e) {
-      $(element).remove();
-    });
-
-    return eventEmitter;
-
-  }
-}

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.html b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.html
new file mode 100644
index 0000000..0308e97
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.html
@@ -0,0 +1,40 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<div>
+  <div *ngIf="showModal" class="metron-dialog modal show" [class.block]="showModal" data-backdrop="static" data-qe-id="modal">
+    <div class="modal-dialog modal-sm" role="document">
+      <div class="modal-content">
+        <div class="modal-header">
+          <span class="modal-title" data-qe-id="modal-title"><b>{{ dialogType }}</b></span>
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+            <span aria-hidden="true" (click)="cancel()">&times;</span>
+          </button>
+        </div>
+        <div class="modal-body">
+          <p data-qe-id="modal-message">{{ message }}</p>
+        </div>
+        <div class="modal-footer">
+          <button *ngIf="dialogType === 'Error'" type="button" class="btn btn-all_ports" (click)="cancel()" data-qe-id="modal-error-cancel">OK</button>
+          <button *ngIf="dialogType !== 'Error'" type="button" class="btn btn-all_ports" (click)="confirm()" data-qe-id="modal-confirm">OK</button>
+          <button *ngIf="dialogType !== 'Error'" type="button" class="btn btn-mine_shaft_2" data-dismiss="modal" (click)="cancel()" data-qe-id="modal-cancel">Cancel</button>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div class="modal-backdrop show" *ngIf="showModal"></div>
+</div>

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.scss
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.scss b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.scss
new file mode 100644
index 0000000..675242b
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.scss
@@ -0,0 +1,20 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ .block {
+    display: block;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.spec.ts b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.spec.ts
new file mode 100644
index 0000000..c5540a6
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.spec.ts
@@ -0,0 +1,127 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MetronDialogComponent } from './metron-dialog.component';
+import { DialogService } from 'app/service/dialog.service';
+import { DialogType } from 'app/model/dialog-type';
+
+describe('MetronDialogComponent', () => {
+  let component: MetronDialogComponent;
+  let fixture: ComponentFixture<MetronDialogComponent>;
+  let dialogService: DialogService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      declarations: [MetronDialogComponent],
+      providers: [DialogService]
+    });
+    fixture = TestBed.createComponent(MetronDialogComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+    dialogService = TestBed.get(DialogService);
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  it('should show when showModal is true', () => {
+    component.showModal = false;
+    fixture.detectChanges();
+    let modal = fixture.nativeElement.querySelector('[data-qe-id="modal"]');
+    expect(modal).toBeNull();
+
+    component.showModal = true;
+    fixture.detectChanges();
+    modal = fixture.nativeElement.querySelector('[data-qe-id="modal"]');
+    expect(modal).toBeTruthy();
+  });
+
+  it('should display the passed message', () => {
+    const testMessage = 'This is a confirmation message';
+    dialogService.launchDialog(testMessage);
+    fixture.detectChanges();
+    const modalMessage = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-message"]'
+    );
+    expect(modalMessage.textContent).toBe(testMessage);
+  });
+
+  it('should display the correct title based on the dialog type', () => {
+    dialogService.launchDialog('');
+    fixture.detectChanges();
+    let modalTitle = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-title"]'
+    );
+    expect(modalTitle.textContent).toBe('Confirmation');
+
+    dialogService.launchDialog('', DialogType.Error);
+    fixture.detectChanges();
+    modalTitle = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-title"]'
+    );
+    expect(modalTitle.textContent).toBe('Error');
+  });
+
+  it('should execute cancel() when the cancel button is clicked', () => {
+    dialogService.launchDialog('');
+    const cancelSpy = spyOn(component, 'cancel').and.callThrough();
+    fixture.detectChanges();
+
+    const cancelButton = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-cancel"]'
+    );
+    cancelButton.click();
+    expect(cancelSpy).toHaveBeenCalled();
+    expect(component.showModal).toBe(false);
+  });
+
+  it('should execute confirm() when the ok button is clicked', () => {
+    dialogService.launchDialog('');
+    const confirmSpy = spyOn(component, 'confirm').and.callThrough();
+    fixture.detectChanges();
+
+    const confirmButton = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-confirm"]'
+    );
+    confirmButton.click();
+    expect(confirmSpy).toHaveBeenCalled();
+    expect(component.showModal).toBe(false);
+  });
+
+  it('should only display a cancel() button when the dialog type is Error', () => {
+    dialogService.launchDialog('', DialogType.Error);
+    fixture.detectChanges();
+
+    const errorCancelButton = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-error-cancel"]'
+    );
+    expect(errorCancelButton).toBeTruthy();
+
+    const confirmCancelButton = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-cancel"]'
+    );
+    expect(confirmCancelButton).toBeNull();
+
+    const confirmApproveButton = fixture.nativeElement.querySelector(
+      '[data-qe-id="modal-confirm"]'
+    );
+    expect(confirmApproveButton).toBeNull();
+  });
+});

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.ts b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.ts
new file mode 100644
index 0000000..7ba71e5
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/shared/metron-dialog/metron-dialog.component.ts
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {
+  Component,
+  OnInit,
+  OnDestroy
+} from '@angular/core';
+import { DialogService } from '../../service/dialog.service';
+import { Subscription } from 'rxjs';
+
+export enum DialogType {
+  Confirmation,
+  Error
+}
+
+@Component({
+  selector: 'app-metron-dialog',
+  templateUrl: './metron-dialog.component.html',
+  styleUrls: ['./metron-dialog.component.scss']
+})
+export class MetronDialogComponent implements OnInit, OnDestroy {
+  public message: string;
+  public showModal = false;
+  public dialogType: string;
+  private subscription: Subscription;
+
+  constructor(private dialogService: DialogService) {}
+
+  ngOnInit(): void {
+    this.subscription = this.dialogService.message.subscribe(r => {
+      this.showModal = r.show;
+      this.message = r.message;
+      this.dialogType = DialogType[r.dialogType];
+    });
+
+  }
+
+  confirm(): void {
+    this.dialogService.approve();
+    this.showModal = false;
+  }
+
+  cancel(): void {
+    this.dialogService.cancel();
+    this.showModal = false;
+  }
+
+  ngOnDestroy() {
+    this.subscription.unsubscribe();
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-config/angular-cli.json
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/angular-cli.json b/metron-interface/metron-config/angular-cli.json
deleted file mode 100644
index 7e99b78..0000000
--- a/metron-interface/metron-config/angular-cli.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
-  "project": {
-    "version": "1.0.0-beta.15",
-    "name": "metron-config"
-  },
-  "apps": [
-    {
-      "root": "src",
-      "outDir": "dist",
-      "assets": "assets",
-      "index": "index.html",
-      "main": "main.ts",
-      "test": "test.ts",
-      "tsconfig": "tsconfig.json",
-      "prefix": "metron-config",
-      "mobile": false,
-      "styles": [
-        "../node_modules/bootstrap/dist/css/bootstrap.css",
-        "../node_modules/font-awesome/css/font-awesome.css",
-        "styles.scss"
-      ],
-      "scripts": [
-        "../node_modules/jquery/dist/jquery.js",
-        "../node_modules/tether/dist/js/tether.js",
-        "../node_modules/bootstrap/dist/js/bootstrap.js",
-        "../node_modules/ace-builds/src-noconflict/ace.js"
-      ],
-      "environments": {
-        "source": "environments/environment.ts",
-        "dev": "environments/environment.ts",
-        "prod": "environments/environment.prod.ts"
-      }
-    }
-  ],
-  "addons": [],
-  "packages": [],
-  "e2e": {
-    "protractor": {
-      "config": "./protractor.conf.js"
-    }
-  },
-  "test": {
-    "karma": {
-      "config": "./karma.conf.js"
-    }
-  },
-  "defaults": {
-    "styleExt": "scss",
-    "prefixInterfaces": false
-  }
-}

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-config/angular.json
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/angular.json b/metron-interface/metron-config/angular.json
new file mode 100644
index 0000000..06c4596
--- /dev/null
+++ b/metron-interface/metron-config/angular.json
@@ -0,0 +1,155 @@
+{
+  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
+  "version": 1,
+  "newProjectRoot": "projects",
+  "projects": {
+    "metron-config": {
+      "root": "",
+      "sourceRoot": "src",
+      "projectType": "application",
+      "architect": {
+        "build": {
+          "builder": "@angular-devkit/build-angular:browser",
+          "options": {
+            "outputPath": "dist",
+            "index": "src/index.html",
+            "main": "src/main.ts",
+            "tsConfig": "src/tsconfig.app.json",
+            "assets": [
+              "src/assets"
+            ],
+            "styles": [
+              "node_modules/bootstrap/dist/css/bootstrap.css",
+              "node_modules/font-awesome/css/font-awesome.css",
+              "src/styles.scss"
+            ],
+            "scripts": [
+              "node_modules/jquery/dist/jquery.js",
+              "node_modules/tether/dist/js/tether.js",
+              "node_modules/bootstrap/dist/js/bootstrap.js",
+              "node_modules/ace-builds/src-noconflict/ace.js"
+            ]
+          },
+          "configurations": {
+            "production": {
+              "optimization": true,
+              "outputHashing": "all",
+              "sourceMap": false,
+              "extractCss": true,
+              "namedChunks": false,
+              "aot": true,
+              "extractLicenses": true,
+              "vendorChunk": false,
+              "buildOptimizer": true,
+              "fileReplacements": [
+                {
+                  "replace": "src/environments/environment.ts",
+                  "with": "src/environments/environment.prod.ts"
+                }
+              ]
+            },
+            "e2e": {
+              "fileReplacements": [
+                {
+                  "replace": "src/environments/environment.ts",
+                  "with": "src/environments/environment.e2e.ts"
+                }
+              ]
+            }
+          }
+        },
+        "serve": {
+          "builder": "@angular-devkit/build-angular:dev-server",
+          "options": {
+            "browserTarget": "metron-config:build"
+          },
+          "configurations": {
+            "source": {
+              "browserTarget": "metron-config:build:source"
+            },
+            "dev": {
+              "browserTarget": "metron-config:build:dev"
+            },
+            "production": {
+              "browserTarget": "metron-config:build:production"
+            }
+          }
+        },
+        "extract-i18n": {
+          "builder": "@angular-devkit/build-angular:extract-i18n",
+          "options": {
+            "browserTarget": "metron-config:build"
+          }
+        },
+        "test": {
+          "builder": "@angular-devkit/build-angular:karma",
+          "options": {
+            "main": "src/test.ts",
+            "karmaConfig": "./karma.conf.js",
+            "polyfills": "src/polyfills.ts",
+            "tsConfig": "src/tsconfig.spec.json",
+            "scripts": [
+              "node_modules/jquery/dist/jquery.js",
+              "node_modules/tether/dist/js/tether.js",
+              "node_modules/bootstrap/dist/js/bootstrap.js",
+              "node_modules/ace-builds/src-noconflict/ace.js"
+            ],
+            "styles": [
+              "node_modules/bootstrap/dist/css/bootstrap.css",
+              "node_modules/font-awesome/css/font-awesome.css",
+              "src/vendor.scss",
+              "src/styles.scss"
+            ],
+            "assets": [
+              "src/assets",
+              "src/favicon.ico"
+            ]
+          }
+        },
+        "lint": {
+          "builder": "@angular-devkit/build-angular:tslint",
+          "options": {
+            "tsConfig": [
+              "src/tsconfig.app.json",
+              "src/tsconfig.spec.json"
+            ],
+            "exclude": []
+          }
+        }
+      }
+    },
+    "metron-config-e2e": {
+      "root": "e2e",
+      "sourceRoot": "e2e",
+      "projectType": "application",
+      "architect": {
+        "e2e": {
+          "builder": "@angular-devkit/build-angular:protractor",
+          "options": {
+            "protractorConfig": "./protractor.conf.js",
+            "devServerTarget": "metron-config:serve"
+          }
+        },
+        "lint": {
+          "builder": "@angular-devkit/build-angular:tslint",
+          "options": {
+            "tsConfig": [
+              "e2e/tsconfig.e2e.json"
+            ],
+            "exclude": []
+          }
+        }
+      }
+    }
+  },
+  "defaultProject": "metron-config",
+  "schematics": {
+    "@schematics/angular:component": {
+      "prefix": "metron-config",
+      "styleext": "scss"
+    },
+    "@schematics/angular:directive": {
+      "prefix": "metron-config"
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/metron/blob/8bf3b6ec/metron-interface/metron-config/karma.conf.js
----------------------------------------------------------------------
diff --git a/metron-interface/metron-config/karma.conf.js b/metron-interface/metron-config/karma.conf.js
index 6023550..aa71b96 100644
--- a/metron-interface/metron-config/karma.conf.js
+++ b/metron-interface/metron-config/karma.conf.js
@@ -15,50 +15,56 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 // Karma configuration file, see link for more information
 // https://karma-runner.github.io/0.13/config/configuration-file.html
 
+process.env.CHROME_BIN = require('puppeteer').executablePath()
+
 module.exports = function (config) {
   config.set({
     basePath: '',
-    frameworks: ['jasmine', 'angular-cli'],
+    frameworks: ['jasmine', '@angular-devkit/build-angular'],
     plugins: [
       require('karma-jasmine'),
       require('karma-chrome-launcher'),
-      require('karma-remap-istanbul'),
-      require('karma-phantomjs-launcher'),
-      require('angular-cli/plugins/karma')
+      require('karma-jasmine-html-reporter'),
+      require('karma-coverage-istanbul-reporter'),
+      require('@angular-devkit/build-angular/plugins/karma')
     ],
+    client:{
+      clearContext: false // leave Jasmine Spec Runner output visible in browser
+    },
     mime: {
       'text/x-typescript': ['ts','tsx']
     },
-    files: [
-      { pattern: './src/test.ts', watched: false },
-      { pattern: './src/assets/**', watched: false, included: false, nocache: false, served: true }
-    ],
-    proxies: {
-      '/assets': '/base/src/assets/'
-    },
-    preprocessors: {
-      './src/test.ts': ['angular-cli']
+    coverageIstanbulReporter: {
+      dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly', 'text-summary' ],
+      fixWebpackSourcePaths: true
     },
-    remapIstanbulReporter: {
-      reports: {
-        html: 'coverage',
-        lcovonly: './coverage/coverage.lcov'
-      }
-    },
-    angularCli: {
-      config: './angular-cli.json',
-      environment: 'dev'
-    },
-    reporters: ['progress', 'karma-remap-istanbul'],
+    captureTimeout: 30000,
+    browserDisconnectTolerance: 3,
+    browserDisconnectTimeout : 30000,
+    browserNoActivityTimeout : 30000,
+
+    reporters: config.angularCli && config.angularCli.codeCoverage
+      ? ['progress', 'coverage-istanbul']
+      : ['progress', 'kjhtml'],
     port: 9876,
     colors: true,
     logLevel: config.LOG_INFO,
     autoWatch: true,
-    browsers: ['PhantomJS'],
+    browsers: ['Chrome','ChromeHeadless'],
+    customLaunchers: {
+      ChromeHeadless: {
+        base: 'Chrome',
+        flags: [
+          '--no-sandbox',
+          '--headless',
+          '--disable-gpu',
+          '--remote-debugging-port=9222'
+        ]
+      }
+    },
     singleRun: false
   });
-};
+};
\ No newline at end of file


Mime
View raw message