]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Isolate each RBD component 33520/head
authorTiago Melo <tmelo@suse.com>
Thu, 12 Mar 2020 23:27:41 +0000 (22:27 -0100)
committerTiago Melo <tmelo@suse.com>
Fri, 13 Mar 2020 00:01:24 +0000 (23:01 -0100)
Before when you accessed any RBD component, you were loading all 4 components
at the same time and each was doing frequent requests to the server.

Now it only loads 1 at a time.

Fixes: https://tracker.ceph.com/issues/44278
Signed-off-by: Tiago Melo <tmelo@suse.com>
20 files changed:
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/block.module.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.html [deleted file]
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.scss [deleted file]
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.spec.ts [deleted file]
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.ts [deleted file]
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-namespace-list/rbd-namespace-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-namespace-list/rbd-namespace-list.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.html [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.scss [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-tabs/rbd-tabs.component.html [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-tabs/rbd-tabs.component.scss [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-tabs/rbd-tabs.component.spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-tabs/rbd-tabs.component.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.spec.ts

index c592e29386b755631a09a4e24e2e052a8daad48a..a3b06bb39e725c13861557d5d2d9cb1e4800a1b2 100644 (file)
@@ -30,12 +30,13 @@ import { RbdConfigurationFormComponent } from './rbd-configuration-form/rbd-conf
 import { RbdConfigurationListComponent } from './rbd-configuration-list/rbd-configuration-list.component';
 import { RbdDetailsComponent } from './rbd-details/rbd-details.component';
 import { RbdFormComponent } from './rbd-form/rbd-form.component';
-import { RbdImagesComponent } from './rbd-images/rbd-images.component';
 import { RbdListComponent } from './rbd-list/rbd-list.component';
 import { RbdNamespaceFormModalComponent } from './rbd-namespace-form/rbd-namespace-form-modal.component';
 import { RbdNamespaceListComponent } from './rbd-namespace-list/rbd-namespace-list.component';
+import { RbdPerformanceComponent } from './rbd-performance/rbd-performance.component';
 import { RbdSnapshotFormModalComponent } from './rbd-snapshot-form/rbd-snapshot-form-modal.component';
 import { RbdSnapshotListComponent } from './rbd-snapshot-list/rbd-snapshot-list.component';
+import { RbdTabsComponent } from './rbd-tabs/rbd-tabs.component';
 import { RbdTrashListComponent } from './rbd-trash-list/rbd-trash-list.component';
 import { RbdTrashMoveModalComponent } from './rbd-trash-move-modal/rbd-trash-move-modal.component';
 import { RbdTrashPurgeModalComponent } from './rbd-trash-purge-modal/rbd-trash-purge-modal.component';
@@ -84,7 +85,6 @@ import { RbdTrashRestoreModalComponent } from './rbd-trash-restore-modal/rbd-tra
     RbdSnapshotFormModalComponent,
     RbdTrashListComponent,
     RbdTrashMoveModalComponent,
-    RbdImagesComponent,
     RbdTrashRestoreModalComponent,
     RbdTrashPurgeModalComponent,
     IscsiTargetDetailsComponent,
@@ -93,7 +93,9 @@ import { RbdTrashRestoreModalComponent } from './rbd-trash-restore-modal/rbd-tra
     IscsiTargetIqnSettingsModalComponent,
     IscsiTargetDiscoveryModalComponent,
     RbdConfigurationListComponent,
-    RbdConfigurationFormComponent
+    RbdConfigurationFormComponent,
+    RbdTabsComponent,
+    RbdPerformanceComponent
   ],
   exports: [RbdConfigurationListComponent, RbdConfigurationFormComponent]
 })
@@ -110,7 +112,22 @@ const routes: Routes = [
     canActivate: [FeatureTogglesGuardService],
     data: { breadcrumbs: 'Images' },
     children: [
-      { path: '', component: RbdImagesComponent },
+      { path: '', component: RbdListComponent },
+      {
+        path: 'namespaces',
+        component: RbdNamespaceListComponent,
+        data: { breadcrumbs: 'Namespaces' }
+      },
+      {
+        path: 'trash',
+        component: RbdTrashListComponent,
+        data: { breadcrumbs: 'Trash' }
+      },
+      {
+        path: 'performance',
+        component: RbdPerformanceComponent,
+        data: { breadcrumbs: 'Overall Performance' }
+      },
       {
         path: URLVerbs.CREATE,
         component: RbdFormComponent,
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.html
deleted file mode 100644 (file)
index 1b7f59c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<div>
-  <tabset>
-    <tab heading="Images"
-         i18n-heading
-         id="tab1">
-      <cd-rbd-list></cd-rbd-list>
-    </tab>
-    <tab heading="Namespaces"
-         i18n-heading>
-      <cd-rbd-namespace-list></cd-rbd-namespace-list>
-    </tab>
-    <tab heading="Trash"
-         i18n-heading>
-      <cd-rbd-trash-list></cd-rbd-trash-list>
-    </tab>
-    <tab heading="Overall Performance"
-         *ngIf="grafanaPermission.read"
-         i18n-heading>
-      <cd-grafana [grafanaPath]="'rbd-overview?'"
-                  uid="41FrpeUiz"
-                  grafanaStyle="two">
-      </cd-grafana>
-    </tab>
-  </tabset>
-</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.scss
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.spec.ts
deleted file mode 100644 (file)
index 1a5c035..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-import { HttpClientTestingModule } from '@angular/common/http/testing';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { RouterTestingModule } from '@angular/router/testing';
-
-import { TabsModule } from 'ngx-bootstrap/tabs';
-import { TooltipModule } from 'ngx-bootstrap/tooltip';
-import { ToastrModule } from 'ngx-toastr';
-
-import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
-import { TaskListService } from '../../../shared/services/task-list.service';
-import { SharedModule } from '../../../shared/shared.module';
-import { RbdConfigurationListComponent } from '../rbd-configuration-list/rbd-configuration-list.component';
-import { RbdDetailsComponent } from '../rbd-details/rbd-details.component';
-import { RbdListComponent } from '../rbd-list/rbd-list.component';
-import { RbdNamespaceListComponent } from '../rbd-namespace-list/rbd-namespace-list.component';
-import { RbdSnapshotListComponent } from '../rbd-snapshot-list/rbd-snapshot-list.component';
-import { RbdTrashListComponent } from '../rbd-trash-list/rbd-trash-list.component';
-import { RbdImagesComponent } from './rbd-images.component';
-
-describe('RbdImagesComponent', () => {
-  let component: RbdImagesComponent;
-  let fixture: ComponentFixture<RbdImagesComponent>;
-
-  configureTestBed({
-    declarations: [
-      RbdDetailsComponent,
-      RbdImagesComponent,
-      RbdListComponent,
-      RbdNamespaceListComponent,
-      RbdSnapshotListComponent,
-      RbdTrashListComponent,
-      RbdConfigurationListComponent
-    ],
-    imports: [
-      HttpClientTestingModule,
-      RouterTestingModule,
-      SharedModule,
-      TabsModule.forRoot(),
-      ToastrModule.forRoot(),
-      TooltipModule.forRoot()
-    ],
-    providers: [TaskListService, i18nProviders]
-  });
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(RbdImagesComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-images/rbd-images.component.ts
deleted file mode 100644 (file)
index bf99a77..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-
-import { Permission } from '../../../shared/models/permissions';
-import { AuthStorageService } from '../../../shared/services/auth-storage.service';
-
-@Component({
-  selector: 'cd-rbd-images',
-  templateUrl: './rbd-images.component.html',
-  styleUrls: ['./rbd-images.component.scss']
-})
-export class RbdImagesComponent implements OnInit {
-  grafanaPermission: Permission;
-
-  constructor(private authStorageService: AuthStorageService) {
-    this.grafanaPermission = this.authStorageService.getPermissions().grafana;
-  }
-
-  ngOnInit() {}
-}
index e539e5c081d183837aa4820008d663dfaa7f822f..fbf6aa0a19ac16289ee09aea46aa8b9253ebe88a 100644 (file)
@@ -1,3 +1,5 @@
+<cd-rbd-tabs></cd-rbd-tabs>
+
 <cd-view-cache *ngFor="let viewCacheStatus of viewCacheStatusList"
                [status]="viewCacheStatus.status"
                [statusFor]="viewCacheStatus.statusFor"></cd-view-cache>
index 5647abcf29e8222f71b79b43ceefe7e43c27aed0..9da640e4822a1f2124a95fabadb3eb11523fc035 100644 (file)
@@ -26,6 +26,7 @@ import { SharedModule } from '../../../shared/shared.module';
 import { RbdConfigurationListComponent } from '../rbd-configuration-list/rbd-configuration-list.component';
 import { RbdDetailsComponent } from '../rbd-details/rbd-details.component';
 import { RbdSnapshotListComponent } from '../rbd-snapshot-list/rbd-snapshot-list.component';
+import { RbdTabsComponent } from '../rbd-tabs/rbd-tabs.component';
 import { RbdListComponent } from './rbd-list.component';
 import { RbdModel } from './rbd-model';
 
@@ -55,7 +56,8 @@ describe('RbdListComponent', () => {
       RbdListComponent,
       RbdDetailsComponent,
       RbdSnapshotListComponent,
-      RbdConfigurationListComponent
+      RbdConfigurationListComponent,
+      RbdTabsComponent
     ],
     providers: [TaskListService, i18nProviders]
   });
index e8b09382fa31e0cb638cfe1947dbdeb86e235435..46e27179eb6282f7498200adc795976f05b8df8d 100644 (file)
@@ -1,3 +1,5 @@
+<cd-rbd-tabs></cd-rbd-tabs>
+
 <cd-table [data]="namespaces"
           (fetchData)="refresh()"
           columnMode="flex"
index ac45d9f5f20c7fa0d7a8a7c08db391f011f85de0..426c912c859a5ac1892591874d131dcfc42d5c4e 100644 (file)
@@ -2,11 +2,13 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { RouterTestingModule } from '@angular/router/testing';
 
+import { TabsModule } from 'ngx-bootstrap/tabs';
 import { ToastrModule } from 'ngx-toastr';
 
 import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
 import { TaskListService } from '../../../shared/services/task-list.service';
 import { SharedModule } from '../../../shared/shared.module';
+import { RbdTabsComponent } from '../rbd-tabs/rbd-tabs.component';
 import { RbdNamespaceListComponent } from './rbd-namespace-list.component';
 
 describe('RbdNamespaceListComponent', () => {
@@ -14,8 +16,14 @@ describe('RbdNamespaceListComponent', () => {
   let fixture: ComponentFixture<RbdNamespaceListComponent>;
 
   configureTestBed({
-    declarations: [RbdNamespaceListComponent],
-    imports: [SharedModule, HttpClientTestingModule, RouterTestingModule, ToastrModule.forRoot()],
+    declarations: [RbdNamespaceListComponent, RbdTabsComponent],
+    imports: [
+      SharedModule,
+      HttpClientTestingModule,
+      RouterTestingModule,
+      ToastrModule.forRoot(),
+      TabsModule.forRoot()
+    ],
     providers: [TaskListService, i18nProviders]
   });
 
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.html
new file mode 100644 (file)
index 0000000..002c8e5
--- /dev/null
@@ -0,0 +1,6 @@
+<cd-rbd-tabs></cd-rbd-tabs>
+
+<cd-grafana [grafanaPath]="'rbd-overview?'"
+            uid="41FrpeUiz"
+            grafanaStyle="two">
+</cd-grafana>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.scss
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.spec.ts
new file mode 100644 (file)
index 0000000..1bb1e9b
--- /dev/null
@@ -0,0 +1,31 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../shared/shared.module';
+import { RbdTabsComponent } from '../rbd-tabs/rbd-tabs.component';
+import { RbdPerformanceComponent } from './rbd-performance.component';
+
+describe('RbdPerformanceComponent', () => {
+  let component: RbdPerformanceComponent;
+  let fixture: ComponentFixture<RbdPerformanceComponent>;
+
+  configureTestBed({
+    imports: [HttpClientTestingModule, RouterTestingModule, SharedModule, TabsModule.forRoot()],
+    declarations: [RbdPerformanceComponent, RbdTabsComponent],
+    providers: i18nProviders
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(RbdPerformanceComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-performance/rbd-performance.component.ts
new file mode 100644 (file)
index 0000000..3071f3a
--- /dev/null
@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'cd-rbd-performance',
+  templateUrl: './rbd-performance.component.html',
+  styleUrls: ['./rbd-performance.component.scss']
+})
+export class RbdPerformanceComponent {
+  constructor() {}
+}
index a65e82e45fc036337b03f34ea75c35911ff615c9..4e4936171ca15dcdb548629fe5adda290f0a4fc9 100644 (file)
@@ -4,6 +4,7 @@ import { RouterTestingModule } from '@angular/router/testing';
 
 import { I18n } from '@ngx-translate/i18n-polyfill';
 import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
+import { TabsModule } from 'ngx-bootstrap/tabs';
 import { ToastrModule } from 'ngx-toastr';
 import { Subject, throwError as observableThrowError } from 'rxjs';
 
@@ -27,6 +28,7 @@ import { NotificationService } from '../../../shared/services/notification.servi
 import { SummaryService } from '../../../shared/services/summary.service';
 import { TaskListService } from '../../../shared/services/task-list.service';
 import { RbdSnapshotFormModalComponent } from '../rbd-snapshot-form/rbd-snapshot-form-modal.component';
+import { RbdTabsComponent } from '../rbd-tabs/rbd-tabs.component';
 import { RbdSnapshotListComponent } from './rbd-snapshot-list.component';
 import { RbdSnapshotModel } from './rbd-snapshot.model';
 
@@ -45,15 +47,16 @@ describe('RbdSnapshotListComponent', () => {
   };
 
   configureTestBed({
-    declarations: [RbdSnapshotListComponent],
+    declarations: [RbdSnapshotListComponent, RbdTabsComponent],
     imports: [
-      DataTableModule,
-      ComponentsModule,
-      ToastrModule.forRoot(),
       ApiModule,
+      ComponentsModule,
+      DataTableModule,
       HttpClientTestingModule,
+      PipesModule,
       RouterTestingModule,
-      PipesModule
+      TabsModule.forRoot(),
+      ToastrModule.forRoot()
     ],
     providers: [
       { provide: AuthStorageService, useValue: fakeAuthStorageService },
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-tabs/rbd-tabs.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-tabs/rbd-tabs.component.html
new file mode 100644 (file)
index 0000000..bc241a5
--- /dev/null
@@ -0,0 +1,23 @@
+<tabset>
+  <tab heading="Images"
+       i18n-heading
+       [active]="url === '/block/rbd'"
+       (selectTab)="navigateTo('/block/rbd')">
+  </tab>
+  <tab heading="Namespaces"
+       i18n-heading
+       [active]="url === '/block/rbd/namespaces'"
+       (selectTab)="navigateTo('/block/rbd/namespaces')">
+  </tab>
+  <tab heading="Trash"
+       i18n-heading
+       [active]="url === '/block/rbd/trash'"
+       (selectTab)="navigateTo('/block/rbd/trash')">
+  </tab>
+  <tab heading="Overall Performance"
+       i18n-heading
+       *ngIf="grafanaPermission.read"
+       [active]="url === '/block/rbd/performance'"
+       (selectTab)="navigateTo('/block/rbd/performance')">
+  </tab>
+</tabset>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-tabs/rbd-tabs.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-tabs/rbd-tabs.component.scss
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-tabs/rbd-tabs.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-tabs/rbd-tabs.component.spec.ts
new file mode 100644 (file)
index 0000000..7d7b15d
--- /dev/null
@@ -0,0 +1,27 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { RbdTabsComponent } from './rbd-tabs.component';
+
+describe('RbdTabsComponent', () => {
+  let component: RbdTabsComponent;
+  let fixture: ComponentFixture<RbdTabsComponent>;
+
+  configureTestBed({
+    imports: [TabsModule.forRoot(), RouterTestingModule],
+    declarations: [RbdTabsComponent]
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(RbdTabsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-tabs/rbd-tabs.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-tabs/rbd-tabs.component.ts
new file mode 100644 (file)
index 0000000..36923df
--- /dev/null
@@ -0,0 +1,27 @@
+import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+
+import { Permission } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
+
+@Component({
+  selector: 'cd-rbd-tabs',
+  templateUrl: './rbd-tabs.component.html',
+  styleUrls: ['./rbd-tabs.component.scss']
+})
+export class RbdTabsComponent implements OnInit {
+  grafanaPermission: Permission;
+  url: string;
+
+  constructor(private authStorageService: AuthStorageService, private router: Router) {
+    this.grafanaPermission = this.authStorageService.getPermissions().grafana;
+  }
+
+  ngOnInit() {
+    this.url = this.router.url;
+  }
+
+  navigateTo(url: string) {
+    this.router.navigate([url]);
+  }
+}
index 8d55aea515cc81c46b22518f2d96695ca0a092d4..ac9bc04c8f70d8609814dec47a816495104dfeb2 100644 (file)
@@ -1,3 +1,5 @@
+<cd-rbd-tabs></cd-rbd-tabs>
+
 <cd-view-cache *ngFor="let viewCacheStatus of viewCacheStatusList"
                [status]="viewCacheStatus.status"
                [statusFor]="viewCacheStatus.statusFor"></cd-view-cache>
index 9a2a351a8c2816193c1955edda6d151c6838fe68..8c83ceb9b70e5d00bb8a26b438ef2f47f42f2aac 100644 (file)
@@ -2,6 +2,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { RouterTestingModule } from '@angular/router/testing';
 
+import { TabsModule } from 'ngx-bootstrap/tabs';
 import { ToastrModule } from 'ngx-toastr';
 import { of } from 'rxjs';
 
@@ -17,6 +18,7 @@ import { ExecutingTask } from '../../../shared/models/executing-task';
 import { SummaryService } from '../../../shared/services/summary.service';
 import { TaskListService } from '../../../shared/services/task-list.service';
 import { SharedModule } from '../../../shared/shared.module';
+import { RbdTabsComponent } from '../rbd-tabs/rbd-tabs.component';
 import { RbdTrashListComponent } from './rbd-trash-list.component';
 
 describe('RbdTrashListComponent', () => {
@@ -26,8 +28,14 @@ describe('RbdTrashListComponent', () => {
   let rbdService: RbdService;
 
   configureTestBed({
-    declarations: [RbdTrashListComponent],
-    imports: [SharedModule, HttpClientTestingModule, RouterTestingModule, ToastrModule.forRoot()],
+    declarations: [RbdTrashListComponent, RbdTabsComponent],
+    imports: [
+      HttpClientTestingModule,
+      RouterTestingModule,
+      SharedModule,
+      TabsModule.forRoot(),
+      ToastrModule.forRoot()
+    ],
     providers: [TaskListService, i18nProviders]
   });