Repository: jhipster/jhipster-control-center (ts)

Issue:
Instances page: consistency
We need consistency:
- url: http://localhost:1337/applications/jhi-applications
- navbar menu: Applications > Services
- title of page: Applications Instances

I'd suggest to change:
- url: http://localhost:1337/applications/instances
-navbar menu: Applications > Instances
- title of page: Applications Instances

What do you think ?

Pull request description:
transform applications component to instance component
url: http://localhost:1337/applications/instances
navbar menu: Applications > Instances
title of page: Applications Instances

Fix #13

Patch:
diff --git a/src/main/webapp/app/applications/applications-modal.component.ts b/src/main/webapp/app/applications/applications-modal.component.ts
deleted file mode 100644
index 82754dc..0000000
--- a/src/main/webapp/app/applications/applications-modal.component.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import ApplicationsService, { Application } from './applications.service';
-import { Component, Inject, Prop, Vue } from 'vue-property-decorator';
-
-@Component
-export default class JhiApplicationsModal extends Vue {
-  public activeProfiles: any = null;
-  @Prop() currentApplication!: Application;
-  @Prop() currentRoute!: any;
-  @Inject('applicationsService') private applicationsService: () => ApplicationsService;
-
-  public mounted(): void {
-    this.refreshProfile();
-  }
-
-  /** Update profile of current application */
-  public refreshProfile(): void {
-    /* istanbul ignore else */
-    if (this.currentApplication.serviceId !== 'consul') {
-      this.applicationsService()
-        .findActiveProfiles(this.currentRoute)
-        .then(res => {
-          this.activeProfiles = res.data;
-        })
-        .catch(error => {
-          this.activeProfiles = error.error;
-        });
-    } else {
-      this.activeProfiles = {};
-    }
-  }
-}
diff --git a/src/main/webapp/app/applications/applications.component.ts b/src/main/webapp/app/applications/applications.component.ts
deleted file mode 100644
index 3e127fd..0000000
--- a/src/main/webapp/app/applications/applications.component.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import ApplicationsService, { Application, Instance } from './applications.service';
-import { Component, Inject, Vue } from 'vue-property-decorator';
-import JhiApplicationsModal from './applications-modal.vue';
-import { Subject } from 'rxjs';
-import { takeUntil } from 'rxjs/operators';
-
-@Component({
-  components: {
-    'applications-modal': JhiApplicationsModal
-  }
-})
-export default class JhiApplications extends Vue {
-  public applications?: Array<Application> = null;
-  public applicationsRoute: Array<any> = null;
-  public currentApplication: Application = null;
-  public currentRoute: any = null;
-  public applicationModal: any = null;
-  private unsubscribe$ = new Subject();
-  @Inject('applicationsService') private applicationsService: () => ApplicationsService;
-
-  public mounted(): void {
-    this.refreshApplicationsData();
-    this.refreshApplicationsRoute();
-  }
-
-  /** Update applicationsData which contains list of applications */
-  public refreshApplicationsData(): void {
-    this.applicationsService()
-      .findAll()
-      .pipe(takeUntil(this.unsubscribe$))
-      .subscribe(applications => {
-        this.applications = applications;
-      });
-  }
-
-  /** Update applicationsRoute which contains list of routes */
-  public refreshApplicationsRoute(): void {
-    this.applicationsService()
-      .findAllGatewayRoute()
-      .then(res => {
-        this.applicationsRoute = res.data;
-      })
-      .catch(error => {
-        this.applicationsRoute = error.error;
-      });
-  }
-
-  /** Display details about an application in a b-modal */
-  public showApplication(application: any, uri: string): void {
-    this.currentApplication = application;
-    for (let i = 0; i < this.applicationsRoute.length; i++) {
-      if (this.applicationsRoute[i].uri === uri) {
-        this.currentRoute = this.applicationsRoute[i].route_id;
-        break;
-      }
-    }
-    this.applicationModal = <any>this.$refs.applicationModal;
-    this.applicationModal.show();
-  }
-
-  /* istanbul ignore next */
-  beforeDestroy(): any {
-    // prevent memory leak when component destroyed
-    this.unsubscribe$.next();
-    this.unsubscribe$.complete();
-  }
-}
diff --git a/src/main/webapp/app/applications/applications.service.ts b/src/main/webapp/app/applications/applications.service.ts
deleted file mode 100644
index 08e6288..0000000
--- a/src/main/webapp/app/applications/applications.service.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import axios, { AxiosPromise } from 'axios';
-import Vue from 'vue';
-import Component from 'vue-class-component';
-import { Observable } from 'rxjs';
-
-export interface Application {
-  constructor: Function;
-  serviceId: string;
-  instance: Instance;
-}
-
-export type Instance = { [key in InstanceKey]?: any };
-
-export type InstanceKey = 'instanceId' | 'uri' | 'serviceId' | 'port' | 'secure' | 'metadata';
-
-@Component
-export default class ApplicationsService extends Vue {
-  /** get all applications instances */
-  public findAll(): Observable<Array<Application>> {
-    return Observable.create(observer => {
-      axios
-        .get('api/services/instances')
-        .then(res => {
-          // generate application list from http request
-          const applications = this.parseJsonArrayApplicationsToArray(res.data);
-          observer.next(applications);
-          observer.complete();
-        })
-        .catch(error => {
-          observer.error(error);
-        });
-    });
-  }
-
-  /** get all gateway routes of applications instances */
-  public findAllGatewayRoute(): AxiosPromise<any> {
-    return axios.get('management/gateway/routes');
-  }
-
-  /** get active profiles of an application instance */
-  public findActiveProfiles(gatewayRoute: string): AxiosPromise<any> {
-    return axios.get('gateway/' + String(gatewayRoute) + '/management/info');
-  }
-
-  /** convert json array of applications to array of applications */
-  parseJsonArrayApplicationsToArray(data: any): Array<Application> {
-    const applications: Array<Application> = [];
-    data.map(application => {
-      const app = new class implements Application {
-        serviceId: string;
-        instance: Instance;
-      }();
-      app.serviceId = application.serviceId;
-      app.instance = application;
-      applications.push(app);
-    });
-    return applications;
-  }
-}
diff --git a/src/main/webapp/app/applications/instance/instance-modal.component.ts b/src/main/webapp/app/applications/instance/instance-modal.component.ts
new file mode 100644
index 0000000..bbcb52c
--- /dev/null
+++ b/src/main/webapp/app/applications/instance/instance-modal.component.ts
@@ -0,0 +1,31 @@
+import InstanceService, { Instance } from './instance.service';
+import { Component, Inject, Prop, Vue } from 'vue-property-decorator';
+
+@Component
+export default class JhiInstanceModal extends Vue {
+  public activeProfiles: any = null;
+  @Prop() selectedInstance!: Instance;
+  @Prop() selectedInstanceRoute!: any;
+  @Inject('instanceService') private instanceService: () => InstanceService;
+
+  public mounted(): void {
+    this.refreshProfile();
+  }
+
+  /** Update profile of current application instance */
+  public refreshProfile(): void {
+    /* istanbul ignore else */
+    if (this.selectedInstance.serviceId !== 'consul') {
+      this.instanceService()
+        .findActiveProfiles(this.selectedInstanceRoute)
+        .then(res => {
+          this.activeProfiles = res.data;
+        })
+        .catch(error => {
+          this.activeProfiles = error.error;
+        });
+    } else {
+      this.activeProfiles = {};
+    }
+  }
+}
diff --git a/src/main/webapp/app/applications/applications-modal.vue b/src/main/webapp/app/applications/instance/instance-modal.vue
similarity index 74%
rename from src/main/webapp/app/applications/applications-modal.vue
rename to src/main/webapp/app/applications/instance/instance-modal.vue
index df5e62b..83f0a78 100644
--- a/src/main/webapp/app/applications/applications-modal.vue
+++ b/src/main/webapp/app/applications/instance/instance-modal.vue
@@ -1,6 +1,6 @@
 <template>
     <div class="modal-body pad">
-        <div v-if="currentApplication && currentRoute">
+        <div v-if="selectedInstance && selectedInstanceRoute">
             <div class="table">
                 <table class="table table-bordered">
                     <tbody>
@@ -9,8 +9,8 @@
                                 <div>URI</div>
                             </td>
                             <td class="text-left">
-                                <a :href="currentApplication.instance.uri" target="_blank">
-                                    {{currentApplication.instance.uri}}
+                                <a :href="selectedInstance.uri" target="_blank">
+                                    {{selectedInstance.uri}}
                                 </a>
                             </td>
                         </tr>
@@ -19,7 +19,7 @@
                                 Port
                             </td>
                             <td class="text-left">
-                                {{currentApplication.instance.port}}
+                                {{selectedInstance.port}}
                             </td>
                         </tr>
                         <tr>
@@ -27,7 +27,7 @@
                                 Secure
                             </td>
                             <td class="text-left">
-                                {{currentApplication.instance.secure}}
+                                {{selectedInstance.secure}}
                             </td>
                         </tr>
                         <tr>
@@ -36,7 +36,7 @@
                             </td>
                             <td class="text-left">
                                 <span class="badge badge-pill badge-info">
-                                    {{currentRoute}}
+                                    {{selectedInstanceRoute}}
                                 </span>
                             </td>
                         </tr>
@@ -50,32 +50,32 @@
                                 </span>
                             </td>
                         </tr>
-                        <tr v-if="currentApplication.instance.metadata && currentApplication.instance.metadata.profile">
+                        <tr v-if="selectedInstance.metadata && selectedInstance.metadata.profile">
                             <td class="text-left">
                                 Profile
                             </td>
                             <td class="text-left">
-                                <span class="badge badge-pill badge-primary">{{currentApplication.instance.metadata.profile}}</span>
+                                <span class="badge badge-pill badge-primary">{{selectedInstance.metadata.profile}}</span>
                             </td>
                         </tr>
-                        <tr v-if="currentApplication.instance.metadata && currentApplication.instance.metadata.version">
+                        <tr v-if="selectedInstance.metadata && selectedInstance.metadata.version">
                             <td class="text-left">
                                 Version
                             </td>
                             <td class="text-left">
-                                <span class="badge badge-pill badge-primary">{{currentApplication.instance.metadata.version}}</span>
+                                <span class="badge badge-pill badge-primary">{{selectedInstance.metadata.version}}</span>
                             </td>
                         </tr>
                     </tbody>
                 </table>
             </div>
         </div>
-        <div v-if="currentRoute && currentRoute.error">
+        <div v-if="selectedInstanceRoute && selectedInstanceRoute.error">
             <h4>Error</h4>
-            <pre>{{currentRoute.error}}</pre>
+            <pre>{{selectedInstanceRoute.error}}</pre>
         </div>
     </div>
 </template>
 
-<script lang="ts" src="./applications-modal.component.ts">
+<script lang="ts" src="./instance-modal.component.ts">
 </script>
diff --git a/src/main/webapp/app/applications/instance/instance.component.ts b/src/main/webapp/app/applications/instance/instance.component.ts
new file mode 100644
index 0000000..1a5e3ae
--- /dev/null
+++ b/src/main/webapp/app/applications/instance/instance.component.ts
@@ -0,0 +1,67 @@
+import { Component, Inject, Vue } from 'vue-property-decorator';
+import InstanceService, { Instance } from './instance.service';
+import InstanceModal from './instance-modal.vue';
+import { takeUntil } from 'rxjs/operators';
+import { Subject } from 'rxjs';
+
+@Component({
+  components: {
+    'instance-modal': InstanceModal
+  }
+})
+export default class JhiInstance extends Vue {
+  public instances?: Array<Instance> = null;
+  public instancesRoute: Array<any> = null;
+  public selectedInstance: Instance = null;
+  public selectedInstanceRoute: string = null;
+  public instanceModal: any = null;
+  private unsubscribe$ = new Subject();
+  @Inject('instanceService') private instanceService: () => InstanceService;
+
+  public mounted(): void {
+    this.refreshInstancesData();
+    this.refreshInstancesRoute();
+  }
+
+  /** Update instancesData which contains list of applications instances */
+  public refreshInstancesData(): void {
+    this.instanceService()
+      .findAll()
+      .pipe(takeUntil(this.unsubscribe$))
+      .subscribe(instances => {
+        this.instances = instances;
+      });
+  }
+
+  /** Update instancesRoute which contains list of routes */
+  public refreshInstancesRoute(): void {
+    this.instanceService()
+      .findAllGatewayRoute()
+      .then(res => {
+        this.instancesRoute = res.data;
+      })
+      .catch(error => {
+        this.instancesRoute = error.error;
+      });
+  }
+
+  /** Display details about an instance in a b-modal */
+  public showInstance(instance: Instance, uri: string): void {
+    this.selectedInstance = instance;
+    for (let i = 0; i < this.instancesRoute.length; i++) {
+      if (this.instancesRoute[i].uri === uri) {
+        this.selectedInstanceRoute = this.instancesRoute[i].route_id;
+        break;
+      }
+    }
+    this.instanceModal = <any>this.$refs.instanceModal;
+    this.instanceModal.show();
+  }
+
+  /* istanbul ignore next */
+  beforeDestroy(): any {
+    // prevent memory leak when component destroyed
+    this.unsubscribe$.next();
+    this.unsubscribe$.complete();
+  }
+}
diff --git a/src/main/webapp/app/applications/instance/instance.service.ts b/src/main/webapp/app/applications/instance/instance.service.ts
new file mode 100644
index 0000000..1e837b1
--- /dev/null
+++ b/src/main/webapp/app/applications/instance/instance.service.ts
@@ -0,0 +1,74 @@
+import axios, { AxiosPromise } from 'axios';
+import Vue from 'vue';
+import Component from 'vue-class-component';
+import { Observable } from 'rxjs';
+
+export interface Instance {
+  serviceId: string;
+  instanceId: string;
+  uri: string;
+  host: string;
+  port: number;
+  secure: boolean;
+  metadata: Metadata;
+}
+
+export type Metadata = { [key in MetadataKey]?: any };
+
+/** TODO check key from json result to add or modify */
+export type MetadataKey = 'profile' | 'version' | 'display-ribbon-on-profiles';
+
+@Component
+export default class InstanceService extends Vue {
+  /** get all instances */
+  public findAll(): Observable<Array<Instance>> {
+    return Observable.create(observer => {
+      axios
+        .get('api/services/instances')
+        .then(res => {
+          // generate instance list from http request
+          const applications = this.parseJsonArrayInstancesToArray(res.data);
+          observer.next(applications);
+          observer.complete();
+        })
+        .catch(error => {
+          observer.error(error);
+        });
+    });
+  }
+
+  /** get all gateway routes of instances */
+  public findAllGatewayRoute(): AxiosPromise<any> {
+    return axios.get('management/gateway/routes');
+  }
+
+  /** get active profiles of an instance */
+  public findActiveProfiles(gatewayRoute: string): AxiosPromise<any> {
+    return axios.get('gateway/' + String(gatewayRoute) + '/management/info');
+  }
+
+  /** convert json array of instances to array of instances */
+  parseJsonArrayInstancesToArray(data: any): Array<Instance> {
+    const instances: Array<Instance> = [];
+    data.map(instance => {
+      const inst = new class implements Instance {
+        serviceId: string;
+        instanceId: string;
+        uri: string;
+        host: string;
+        port: number;
+        secure: boolean;
+        metadata: Metadata;
+      }();
+      inst.serviceId = instance.serviceId;
+      inst.instanceId = instance.instanceId;
+      inst.uri = instance.uri;
+      inst.host = instance.host;
+      inst.port = instance.port;
+      inst.secure = instance.secure;
+      inst.metadata = instance.metadata;
+      instances.push(inst);
+    });
+    return instances;
+  }
+}
diff --git a/src/main/webapp/app/applications/applications.vue b/src/main/webapp/app/applications/instance/instance.vue
similarity index 55%
rename from src/main/webapp/app/applications/applications.vue
rename to src/main/webapp/app/applications/instance/instance.vue
index 631e204..4a6815d 100644
--- a/src/main/webapp/app/applications/applications.vue
+++ b/src/main/webapp/app/applications/instance/instance.vue
@@ -1,7 +1,7 @@
 <template>
     <div>
         <h2>
-            <span id="applications-page-heading">Applications Instances</span>
+            <span id="instances-page-heading">Applications Instances</span>
         </h2>
         <div class="table-responsive">
             <table class="table table-striped table-bordered table-responsive d-table">
@@ -13,15 +13,15 @@
                 </tr>
                 </thead>
                 <tbody>
-                <tr v-for="content in applications" :key="content.instance.instanceId">
+                <tr v-for="instance in instances" :key="instance.instanceId">
                     <td class="table-hover">
-                        <a :href="content.instance.uri" target="_blank">{{ content.instance.serviceId }}</a>
+                        <a :href="instance.uri" target="_blank">{{ instance.serviceId }}</a>
                     </td>
                     <td class="table-hover">
-                        <span class="badge badge-pill badge-light">{{ content.instance.instanceId }}</span>
+                        <span class="badge badge-pill badge-light">{{ instance.instanceId }}</span>
                     </td>
                     <td class="text-center">
-                        <a id="showDetail" class="hand" v-on:click="showApplication(content, content.instance.uri)" v-if="content">
+                        <a id="showDetail" class="hand" v-on:click="showInstance(instance, instance.uri)" v-if="instance">
                             <font-awesome-icon icon="eye"></font-awesome-icon>
                         </a>
                     </td>
@@ -29,15 +29,14 @@
                 </tbody>
             </table>
         </div>
-        <b-modal ref="applicationModal">
-            <h4 slot="modal-title" v-if="currentApplication && currentRoute" class="modal-title" id="showApplicationLabel">
-                <span class="text-capitalize">{{ currentApplication.serviceId }}</span>
+        <b-modal ref="instanceModal">
+            <h4 slot="modal-title" v-if="selectedInstance && selectedInstanceRoute" class="modal-title" id="showInstanceLabel">
+                <span class="text-capitalize">{{ selectedInstance.serviceId }}</span>
             </h4>
-            <applications-modal :current-application="currentApplication" :current-route="currentRoute"></applications-modal>
+            <instance-modal :selected-instance="selectedInstance" :selected-instance-route="selectedInstanceRoute"></instance-modal>
         </b-modal>
     </div>
 </template>
 
-<script lang="ts" src="./applications.component.ts">
+<script lang="ts" src="./instance.component.ts">
 </script>
-
diff --git a/src/main/webapp/app/core/jhi-navbar/jhi-navbar.vue b/src/main/webapp/app/core/jhi-navbar/jhi-navbar.vue
index e1f4fe0..946c806 100644
--- a/src/main/webapp/app/core/jhi-navbar/jhi-navbar.vue
+++ b/src/main/webapp/app/core/jhi-navbar/jhi-navbar.vue
@@ -68,9 +68,9 @@
                         <font-awesome-icon icon="cloud" />
                         <span>Applications</span>
                     </span>
-                    <b-dropdown-item to="/applications/jhi-applications">
+                    <b-dropdown-item to="/applications/instances">
                         <font-awesome-icon icon="th-list" />
-                        <span>Services</span>
+                        <span>Instances</span>
                     </b-dropdown-item>
                 </b-nav-item-dropdown>
                 <b-nav-item-dropdown
diff --git a/src/main/webapp/app/main.ts b/src/main/webapp/app/main.ts
index 0f1e0f5..66a1bc1 100644
--- a/src/main/webapp/app/main.ts
+++ b/src/main/webapp/app/main.ts
@@ -21,7 +21,7 @@ import AccountService from './account/account.service';
 import '../content/scss/vendor.scss';
 import AlertService from '@/shared/alert/alert.service';
 import ConfigurationService from '@/admin/configuration/configuration.service';
-import ApplicationsService from '@/applications/applications.service';
+import InstanceService from '@/applications/instance/instance.service';
 
 /* tslint:disable */
 
@@ -80,7 +80,7 @@ new Vue({
     // jhipster-needle-add-entity-service-to-main - JHipster will import entities services here
     accountService: () => accountService,
 
-    applicationsService: () => new ApplicationsService()
+    instanceService: () => new InstanceService()
   },
   store
 });
diff --git a/src/main/webapp/app/router/index.ts b/src/main/webapp/app/router/index.ts
index 99b7b74..cb4e03e 100644
--- a/src/main/webapp/app/router/index.ts
+++ b/src/main/webapp/app/router/index.ts
@@ -14,7 +14,7 @@ const JhiDocsComponent = () => import('../admin/docs/docs.vue');
 const JhiHealthComponent = () => import('../admin/health/health.vue');
 const JhiLogsComponent = () => import('../admin/logs/logs.vue');
 const JhiMetricsComponent = () => import('../admin/metrics/metrics.vue');
-const JhiApplicationsComponent = () => import('../applications/applications.vue');
+const InstanceComponent = () => import('../applications/instance/instance.vue');
 
 /* tslint:disable */
 // jhipster-needle-add-entity-to-router-import - JHipster will import entities to the router here
@@ -74,9 +74,9 @@ export default new Router({
       meta: { authorities: [Authority.ADMIN] }
     },
     {
-      path: '/applications/jhi-applications',
-      name: 'JhiApplicationsComponent',
-      component: JhiApplicationsComponent,
+      path: '/applications/instances',
+      name: 'InstanceComponent',
+      component: InstanceComponent,
       meta: { authorities: [Authority.ADMIN] }
     }
     // jhipster-needle-add-entity-to-router - JHipster will add entities to the router here


Test patch:
diff --git a/src/test/javascript/spec/app/applications/applications-modal.component.spec.ts b/src/test/javascript/spec/app/applications/applications-modal.component.spec.ts
deleted file mode 100644
index b9671b2..0000000
--- a/src/test/javascript/spec/app/applications/applications-modal.component.spec.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { createLocalVue, Wrapper, shallowMount } from '@vue/test-utils';
-import * as config from '@/shared/config/config';
-import ApplicationsModal from '@/applications/applications-modal.vue';
-import ApplicationsModalClass from '@/applications/applications-modal.component';
-import axios from 'axios';
-import { Application } from '@/applications/applications.service';
-
-const localVue = createLocalVue();
-config.initVueApp(localVue);
-localVue.component('font-awesome-icon', {});
-const mockedApplicationsService = { findActiveProfiles: jest.spyOn(axios, 'get') };
-const app = {
-  serviceId: 'app1',
-  instance: {
-    instanceId: 'app1-id',
-    serviceId: 'app1',
-    port: 8080,
-    secure: false,
-    metadata: { someData: 'test' },
-    uri: 'http://127.0.0.01:8080'
-  }
-};
-
-describe('Applications Modal Component', () => {
-  let wrapper: Wrapper<ApplicationsModalClass>;
-  let applicationsModal: ApplicationsModalClass;
-
-  beforeEach(async () => {
-    wrapper = shallowMount<ApplicationsModalClass>(ApplicationsModal, {
-      propsData: {
-        currentApplication: app,
-        currentRoute: {}
-      },
-      localVue,
-      provide: {
-        applicationsService: () => mockedApplicationsService
-      }
-    });
-    applicationsModal = wrapper.vm;
-  });
-
-  it('should be a Vue instance', () => {
-    expect(wrapper.isVueInstance()).toBeTruthy();
-  });
-
-  describe('active profiles', () => {
-    it('should refresh profile', async () => {
-      // GIVEN
-      mockedApplicationsService.findActiveProfiles.mockReturnValue(Promise.resolve({}));
-      const route = mockedApplicationsService.findActiveProfiles.mock.calls[0][0];
-
-      // WHEN
-      applicationsModal.refreshProfile();
-      await applicationsModal.$nextTick();
-
-      // THEN
-      expect(mockedApplicationsService.findActiveProfiles).toHaveBeenCalledWith(route);
-    });
-
-    it('should get an error when refresh profile', async () => {
-      // GIVEN
-      mockedApplicationsService.findActiveProfiles.mockReturnValue(Promise.reject({}));
-      const route = mockedApplicationsService.findActiveProfiles.mock.calls[0][0];
-
-      // WHEN
-      applicationsModal.refreshProfile();
-      await applicationsModal.$nextTick();
-
-      // THEN
-      expect(mockedApplicationsService.findActiveProfiles).toHaveBeenCalledWith(route);
-    });
-  });
-});
diff --git a/src/test/javascript/spec/app/applications/applications.component.spec.ts b/src/test/javascript/spec/app/applications/applications.component.spec.ts
deleted file mode 100644
index a8ef1ad..0000000
--- a/src/test/javascript/spec/app/applications/applications.component.spec.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-import { shallowMount, createLocalVue, Wrapper, mount } from '@vue/test-utils';
-import axios from 'axios';
-import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
-import * as config from '@/shared/config/config';
-import Applications from '@/applications/applications.vue';
-import ApplicationsModal from '@/applications/applications-modal.vue';
-import ApplicationsClass from '@/applications/applications.component';
-import ApplicationsService from '@/applications/applications.service';
-
-const localVue = createLocalVue();
-const mockedAxios: any = axios;
-
-config.initVueApp(localVue);
-localVue.component('font-awesome-icon', FontAwesomeIcon);
-localVue.component('applications-modal', ApplicationsModal);
-localVue.directive('b-modal', {});
-
-jest.mock('axios', () => ({
-  get: jest.fn()
-}));
-
-const stubbedModal = {
-  template: '<div></div>',
-  methods: {
-    show() {}
-  }
-};
-
-describe('Applications Component', () => {
-  let wrapper: Wrapper<ApplicationsClass>;
-  let applications: ApplicationsClass;
-
-  beforeEach(() => {
-    mockedAxios.get.mockReturnValue(Promise.resolve({}));
-    wrapper = mount<ApplicationsClass>(Applications, {
-      localVue,
-      stubs: {
-        bModal: stubbedModal
-      },
-      provide: {
-        applicationsService: () => new ApplicationsService()
-      }
-    });
-    applications = wrapper.vm;
-  });
-
-  it('should be a Vue instance', () => {
-    expect(wrapper.isVueInstance()).toBeTruthy();
-  });
-
-  describe('should refresh list of applications data', () => {
-    it('should call refreshApplicationsData on init', async () => {
-      // GIVEN
-      mockedAxios.get.mockReturnValue(Promise.resolve({}));
-
-      // WHEN
-      applications.refreshApplicationsData();
-      await applications.$nextTick();
-
-      // THEN
-      expect(mockedAxios.get).toHaveBeenCalledWith('api/services/instances');
-    });
-    it('should handle error on refreshing applications data', async () => {
-      // GIVEN
-      mockedAxios.get.mockReturnValue(Promise.reject({}));
-
-      // WHEN
-      applications.refreshApplicationsData();
-      await applications.$nextTick();
-
-      // THEN
-      expect(mockedAxios.get).toHaveBeenCalledWith('api/services/instances');
-    });
-  });
-
-  describe('should refresh list of applications route data', () => {
-    it('should call refreshApplicationsRoute on init', async () => {
-      // GIVEN
-      mockedAxios.get.mockReturnValue(Promise.resolve({}));
-
-      // WHEN
-      applications.refreshApplicationsRoute();
-      await applications.$nextTick();
-
-      // THEN
-      expect(mockedAxios.get).toHaveBeenCalledWith('management/gateway/routes');
-    });
-    it('should handle error on refreshing applications route data', async () => {
-      // GIVEN
-      mockedAxios.get.mockReturnValue(Promise.reject({}));
-
-      // WHEN
-      applications.refreshApplicationsRoute();
-      await applications.$nextTick();
-
-      // THEN
-      expect(mockedAxios.get).toHaveBeenCalledWith('management/gateway/routes');
-    });
-  });
-
-  // TODO fix test for method showApplication
-  describe('should call showApplication', () => {
-    it('should show selected application', async () => {
-      // GIVEN
-      const spy = jest.spyOn(applications, 'showApplication');
-      const app = {
-        app1: [
-          {
-            instanceId: 'app1-id',
-            serviceId: 'app1',
-            host: '127.0.0.1',
-            port: 8080,
-            secure: false,
-            metadata: { someData: 'test' },
-            uri: 'http://127.0.0.01:8080',
-            scheme: null
-          }
-        ]
-      };
-      const uri = 'http://127.0.0.01:8080';
-      applications.applicationsRoute = [
-        { uri: 'http://127.0.0.01:8081', route_id: 'test2/test2-id' },
-        { uri: 'http://127.0.0.01:8080', route_id: 'test/test-id' }
-      ];
-
-      // WHEN
-      applications.showApplication(app, uri);
-      await applications.$nextTick();
-      // THEN
-      expect(spy).toHaveBeenCalled();
-      spy.mockRestore();
-    });
-  });
-});
diff --git a/src/test/javascript/spec/app/applications/instance/instance-modal.component.spec.ts b/src/test/javascript/spec/app/applications/instance/instance-modal.component.spec.ts
new file mode 100644
index 0000000..3f22d94
--- /dev/null
+++ b/src/test/javascript/spec/app/applications/instance/instance-modal.component.spec.ts
@@ -0,0 +1,70 @@
+import { createLocalVue, Wrapper, shallowMount } from '@vue/test-utils';
+import * as config from '@/shared/config/config';
+import axios from 'axios';
+import InstanceModalClass from '@/applications/instance/instance-modal.component';
+import InstanceModal from '@/applications/instance/instance-modal.vue';
+
+const localVue = createLocalVue();
+config.initVueApp(localVue);
+localVue.component('font-awesome-icon', {});
+const mockedInstanceService = { findActiveProfiles: jest.spyOn(axios, 'get') };
+const app = {
+  serviceId: 'app1',
+  instanceId: 'app1-id',
+  uri: 'http://127.0.0.1:8080',
+  host: '127.0.0.1',
+  port: 8080,
+  secure: false,
+  metadata: {}
+};
+
+describe('Instance Modal Component', () => {
+  let wrapper: Wrapper<InstanceModalClass>;
+  let instanceModal: InstanceModalClass;
+
+  beforeEach(async () => {
+    wrapper = shallowMount<InstanceModalClass>(InstanceModal, {
+      propsData: {
+        selectedInstance: app,
+        selectedInstanceRoute: {}
+      },
+      localVue,
+      provide: {
+        instanceService: () => mockedInstanceService
+      }
+    });
+    instanceModal = wrapper.vm;
+  });
+
+  it('should be a Vue instance', () => {
+    expect(wrapper.isVueInstance()).toBeTruthy();
+  });
+
+  describe('active profiles', () => {
+    it('should refresh profile', async () => {
+      // GIVEN
+      mockedInstanceService.findActiveProfiles.mockReturnValue(Promise.resolve({}));
+      const route = mockedInstanceService.findActiveProfiles.mock.calls[0][0];
+
+      // WHEN
+      instanceModal.refreshProfile();
+      await instanceModal.$nextTick();
+
+      // THEN
+      expect(mockedInstanceService.findActiveProfiles).toHaveBeenCalledWith(route);
+    });
+
+    it('should get an error when refresh profile', async () => {
+      // GIVEN
+      mockedInstanceService.findActiveProfiles.mockReturnValue(Promise.reject({}));
+      const route = mockedInstanceService.findActiveProfiles.mock.calls[0][0];
+
+      // WHEN
+      instanceModal.refreshProfile();
+      await instanceModal.$nextTick();
+
+      // THEN
+      expect(mockedInstanceService.findActiveProfiles).toHaveBeenCalledWith(route);
+    });
+  });
+});
diff --git a/src/test/javascript/spec/app/applications/instance/instance.component.spec.ts b/src/test/javascript/spec/app/applications/instance/instance.component.spec.ts
new file mode 100644
index 0000000..c9f26da
--- /dev/null
+++ b/src/test/javascript/spec/app/applications/instance/instance.component.spec.ts
@@ -0,0 +1,135 @@
+import { createLocalVue, Wrapper, mount } from '@vue/test-utils';
+import axios from 'axios';
+import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
+import * as config from '@/shared/config/config';
+import InstanceVue from '@/applications/instance/instance.vue';
+import InstanceModal from '@/applications/instance/instance-modal.vue';
+import InstanceClass from '@/applications/instance/instance.component';
+import InstanceService, { Instance, Metadata } from '@/applications/instance/instance.service';
+
+const localVue = createLocalVue();
+const mockedAxios: any = axios;
+
+config.initVueApp(localVue);
+localVue.component('font-awesome-icon', FontAwesomeIcon);
+localVue.component('instance-modal', InstanceModal);
+localVue.directive('b-modal', {});
+
+jest.mock('axios', () => ({
+  get: jest.fn()
+}));
+
+const stubbedModal = {
+  template: '<div></div>',
+  methods: {
+    show() {}
+  }
+};
+
+describe('Instance Component', () => {
+  let wrapper: Wrapper<InstanceClass>;
+  let instance: InstanceClass;
+
+  beforeEach(() => {
+    mockedAxios.get.mockReturnValue(Promise.resolve({}));
+    wrapper = mount<InstanceClass>(InstanceVue, {
+      localVue,
+      stubs: {
+        bModal: stubbedModal
+      },
+      provide: {
+        instanceService: () => new InstanceService()
+      }
+    });
+    instance = wrapper.vm;
+  });
+
+  it('should be a Vue instance', () => {
+    expect(wrapper.isVueInstance()).toBeTruthy();
+  });
+
+  describe('should refresh list of instance data', () => {
+    it('should call refreshInstancesData on init', async () => {
+      // GIVEN
+      mockedAxios.get.mockReturnValue(Promise.resolve({}));
+
+      // WHEN
+      instance.refreshInstancesData();
+      await instance.$nextTick();
+
+      // THEN
+      expect(mockedAxios.get).toHaveBeenCalledWith('api/services/instances');
+    });
+    it('should handle error on refreshing instance data', async () => {
+      // GIVEN
+      mockedAxios.get.mockReturnValue(Promise.reject({}));
+
+      // WHEN
+      instance.refreshInstancesData();
+      await instance.$nextTick();
+
+      // THEN
+      expect(mockedAxios.get).toHaveBeenCalledWith('api/services/instances');
+    });
+  });
+
+  describe('should refresh list of instance route data', () => {
+    it('should call refreshInstancesRoute on init', async () => {
+      // GIVEN
+      mockedAxios.get.mockReturnValue(Promise.resolve({}));
+
+      // WHEN
+      instance.refreshInstancesRoute();
+      await instance.$nextTick();
+
+      // THEN
+      expect(mockedAxios.get).toHaveBeenCalledWith('management/gateway/routes');
+    });
+    it('should handle error on refreshing instance route data', async () => {
+      // GIVEN
+      mockedAxios.get.mockReturnValue(Promise.reject({}));
+
+      // WHEN
+      instance.refreshInstancesRoute();
+      await instance.$nextTick();
+
+      // THEN
+      expect(mockedAxios.get).toHaveBeenCalledWith('management/gateway/routes');
+    });
+  });
+
+  describe('should call showInstance', () => {
+    it('should show selected instance', async () => {
+      // GIVEN
+      const spy = jest.spyOn(instance, 'showInstance');
+      const inst: Instance = new class implements Instance {
+        serviceId: string;
+        instanceId: string;
+        uri: string;
+        host: string;
+        port: number;
+        secure: boolean;
+        metadata: Metadata;
+      }();
+      inst.serviceId = 'app1';
+      inst.instanceId = 'app1-id';
+      inst.uri = 'http://127.0.0.01:8080';
+      inst.host = '127.0.0.1';
+      inst.port = 8080;
+      inst.secure = false;
+      inst.metadata = {};
+      const uri = 'http://127.0.0.01:8080';
+      instance.instancesRoute = [
+        { uri: 'http://127.0.0.01:8081', route_id: 'test2/test2-id' },
+        { uri: 'http://127.0.0.01:8080', route_id: 'test/test-id' }
+      ];
+
+      // WHEN
+      instance.showInstance(inst, uri);
+      await instance.$nextTick();
+      // THEN
+      expect(spy).toHaveBeenCalled();
+      spy.mockRestore();
+    });
+  });
+});
diff --git a/src/test/javascript/spec/app/applications/applications.service.spec.ts b/src/test/javascript/spec/app/applications/instance/instance.service.spec.ts
similarity index 59%
rename from src/test/javascript/spec/app/applications/applications.service.spec.ts
rename to src/test/javascript/spec/app/applications/instance/instance.service.spec.ts
index f8f6f03..edb7d9a 100644
--- a/src/test/javascript/spec/app/applications/applications.service.spec.ts
+++ b/src/test/javascript/spec/app/applications/instance/instance.service.spec.ts
@@ -1,6 +1,6 @@
-import ApplicationsService, { Application } from '@/applications/applications.service';
-import axios from 'axios';
+import InstanceService, { Instance } from '@/applications/instance/instance.service';
 import { Observable } from 'rxjs';
+import axios from 'axios';
 
 const mockedAxios: any = axios;
 jest.mock('axios', () => ({
@@ -10,45 +10,41 @@ jest.mock('axios', () => ({
 const data: Array<any> = [
   {
     serviceId: 'app1',
-    instance: {
-      instanceId: 'app1-id',
-      serviceId: 'app1',
-      port: 8080,
-      secure: false,
-      metadata: { someData: 'test' },
-      uri: 'http://127.0.0.01:8080'
-    }
+    instanceId: 'app1-id',
+    uri: 'http://127.0.0.1:8080',
+    host: '127.0.0.1',
+    port: 8080,
+    secure: false,
+    metadata: {}
   },
   {
     serviceId: 'app2',
-    instance: {
-      instanceId: 'app2-id',
-      serviceId: 'app2',
-      port: 8081,
-      secure: false,
-      metadata: { someData: 'test' },
-      uri: 'http://127.0.0.02:8081'
-    }
+    instanceId: 'app2-id',
+    uri: 'http://127.0.0.1:8081',
+    host: '127.0.0.1',
+    port: 8080,
+    secure: false,
+    metadata: {}
   }
 ];
 
-describe('Applications Service', () => {
-  let applicationsService: ApplicationsService;
+describe('Instance Service', () => {
+  let instanceService: InstanceService;
 
   beforeEach(() => {
-    applicationsService = new ApplicationsService();
+    instanceService = new InstanceService();
     mockedAxios.get.mockReset();
   });
 
-  it('should get list of applications', async () => {
-    const spy = jest.spyOn(applicationsService, 'findAll').mockReturnValue(Observable.of(data));
+  it('should get list of instances', async () => {
+    const spy = jest.spyOn(instanceService, 'findAll').mockReturnValue(Observable.of(data));
 
     expect(
-      applicationsService.findAll().subscribe(res => {
+      instanceService.findAll().subscribe(res => {
         expect(res).toEqual(data);
       })
     );
-    expect(applicationsService.parseJsonArrayApplicationsToArray(data)).toHaveLength(2);
+    expect(instanceService.parseJsonArrayInstancesToArray(data)).toHaveLength(2);
     expect(spy).toHaveBeenCalled();
   });
 
@@ -67,7 +63,7 @@ describe('Applications Service', () => {
     ];
     mockedAxios.get.mockImplementationOnce(() => Promise.resolve(routes));
 
-    await expect(applicationsService.findAllGatewayRoute()).resolves.toEqual(routes);
+    await expect(instanceService.findAllGatewayRoute()).resolves.toEqual(routes);
     expect(mockedAxios.get).toHaveBeenCalledWith('management/gateway/routes');
   });
 
@@ -75,7 +71,7 @@ describe('Applications Service', () => {
     const error = 'an error';
     mockedAxios.get.mockImplementationOnce(() => Promise.reject(error));
 
-    await expect(applicationsService.findAllGatewayRoute()).rejects.toEqual(error);
+    await expect(instanceService.findAllGatewayRoute()).rejects.toEqual(error);
     expect(mockedAxios.get).toHaveBeenCalledWith('management/gateway/routes');
   });
 
@@ -84,7 +80,7 @@ describe('Applications Service', () => {
     const route = 'test/test-id';
     mockedAxios.get.mockImplementationOnce(() => Promise.resolve(profiles));
 
-    await expect(applicationsService.findActiveProfiles(route)).resolves.toEqual(profiles);
+    await expect(instanceService.findActiveProfiles(route)).resolves.toEqual(profiles);
     expect(mockedAxios.get).toHaveBeenCalledWith('gateway/test/test-id/management/info');
   });
 
@@ -93,7 +89,7 @@ describe('Applications Service', () => {
     const route = 'test/test-id';
     mockedAxios.get.mockImplementationOnce(() => Promise.reject(error));
 
-    await expect(applicationsService.findActiveProfiles(route)).rejects.toEqual(error);
+    await expect(instanceService.findActiveProfiles(route)).rejects.toEqual(error);
     expect(mockedAxios.get).toHaveBeenCalledWith('gateway/test/test-id/management/info');
   });
 });