]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / cluster / osd / osd-list / osd-list.component.spec.ts
diff --git a/ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts b/ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts
new file mode 100644 (file)
index 0000000..d775fb0
--- /dev/null
@@ -0,0 +1,224 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { By } from '@angular/platform-browser';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalService } from 'ngx-bootstrap/modal';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+import { EMPTY, of } from 'rxjs';
+
+import {
+  configureTestBed,
+  i18nProviders,
+  PermissionHelper
+} from '../../../../../testing/unit-test-helper';
+import { OsdService } from '../../../../shared/api/osd.service';
+import { ConfirmationModalComponent } from '../../../../shared/components/confirmation-modal/confirmation-modal.component';
+import { CriticalConfirmationModalComponent } from '../../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { TableActionsComponent } from '../../../../shared/datatable/table-actions/table-actions.component';
+import { CdTableAction } from '../../../../shared/models/cd-table-action';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { Permissions } from '../../../../shared/models/permissions';
+import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { SharedModule } from '../../../../shared/shared.module';
+import { PerformanceCounterModule } from '../../../performance-counter/performance-counter.module';
+import { OsdDetailsComponent } from '../osd-details/osd-details.component';
+import { OsdPerformanceHistogramComponent } from '../osd-performance-histogram/osd-performance-histogram.component';
+import { OsdReweightModalComponent } from '../osd-reweight-modal/osd-reweight-modal.component';
+import { OsdListComponent } from './osd-list.component';
+
+describe('OsdListComponent', () => {
+  let component: OsdListComponent;
+  let fixture: ComponentFixture<OsdListComponent>;
+  let modalServiceShowSpy: jasmine.Spy;
+
+  const fakeAuthStorageService = {
+    getPermissions: () => {
+      return new Permissions({ osd: ['read', 'update', 'create', 'delete'] });
+    }
+  };
+
+  const getTableAction = (name) => component.tableActions.find((action) => action.name === name);
+
+  const setFakeSelection = () => {
+    // Default data and selection
+    const selection = [{ id: 1 }];
+    const data = [{ id: 1 }];
+
+    // Table data and selection
+    component.selection = new CdTableSelection();
+    component.selection.selected = selection;
+    component.selection.update();
+    component.osds = data;
+    component.permissions = fakeAuthStorageService.getPermissions();
+  };
+
+  const openActionModal = (actionName) => {
+    setFakeSelection();
+    getTableAction(actionName).click();
+  };
+
+  /**
+   * The following modals are called after the information about their
+   * safety to destroy/remove/mark them lost has been retrieved, hence
+   * we will have to fake its request to be able to open those modals.
+   */
+  const mockSafeToDestroy = () => {
+    spyOn(TestBed.get(OsdService), 'safeToDestroy').and.callFake(() =>
+      of({ 'safe-to-destroy': true })
+    );
+  };
+
+  configureTestBed({
+    imports: [
+      HttpClientTestingModule,
+      PerformanceCounterModule,
+      TabsModule.forRoot(),
+      SharedModule,
+      ReactiveFormsModule,
+      RouterTestingModule
+    ],
+    declarations: [OsdListComponent, OsdDetailsComponent, OsdPerformanceHistogramComponent],
+    providers: [
+      { provide: AuthStorageService, useValue: fakeAuthStorageService },
+      TableActionsComponent,
+      BsModalService,
+      i18nProviders
+    ]
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(OsdListComponent);
+    fixture.detectChanges();
+    component = fixture.componentInstance;
+    modalServiceShowSpy = spyOn(TestBed.get(BsModalService), 'show').and.stub();
+  });
+
+  it('should create', () => {
+    fixture.detectChanges();
+    expect(component).toBeTruthy();
+  });
+
+  describe('show table actions as defined', () => {
+    let tableActions: TableActionsComponent;
+    let scenario: { fn; empty; single };
+    let permissionHelper: PermissionHelper;
+
+    const getTableActionComponent = () => {
+      fixture.detectChanges();
+      return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance;
+    };
+
+    beforeEach(() => {
+      permissionHelper = new PermissionHelper(component.permissions.osd, () =>
+        getTableActionComponent()
+      );
+      scenario = {
+        fn: () => tableActions.getCurrentButton().name,
+        single: 'Scrub',
+        empty: 'Scrub'
+      };
+      tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1);
+    });
+
+    it('shows action button', () => permissionHelper.testScenarios(scenario));
+
+    it('shows all actions', () => {
+      expect(tableActions.tableActions.length).toBe(9);
+      expect(tableActions.tableActions).toEqual(component.tableActions);
+    });
+  });
+
+  describe('test table actions in submenu', () => {
+    beforeEach(fakeAsync(() => {
+      // The menu needs a click to render the dropdown!
+      const dropDownToggle = fixture.debugElement.query(By.css('.dropdown-toggle'));
+      dropDownToggle.triggerEventHandler('click', null);
+      tick();
+      fixture.detectChanges();
+    }));
+
+    it('has all menu entries disabled', () => {
+      const tableActionElement = fixture.debugElement.query(By.directive(TableActionsComponent));
+      const toClassName = TestBed.get(TableActionsComponent).toClassName;
+      const getActionClasses = (action: CdTableAction) =>
+        tableActionElement.query(By.css('.' + toClassName(action.name))).classes;
+
+      component.tableActions.forEach((action) => {
+        expect(getActionClasses(action).disabled).toBe(true);
+      });
+    });
+  });
+
+  describe('tests if all modals are opened correctly', () => {
+    /**
+     * Helper function to check if a function opens a modal
+     *
+     * @param modalClass - The expected class of the modal
+     */
+    const expectOpensModal = (actionName: string, modalClass): void => {
+      openActionModal(actionName);
+
+      // @TODO: check why tsc is complaining when passing 'expectationFailOutput' param.
+      expect(modalServiceShowSpy.calls.any()).toBeTruthy();
+      expect(modalServiceShowSpy.calls.first().args[0]).toBe(modalClass);
+
+      modalServiceShowSpy.calls.reset();
+    };
+
+    it('opens the reweight modal', () => {
+      expectOpensModal('Reweight', OsdReweightModalComponent);
+    });
+
+    it('opens all confirmation modals', () => {
+      const modalClass = ConfirmationModalComponent;
+      expectOpensModal('Mark Out', modalClass);
+      expectOpensModal('Mark In', modalClass);
+      expectOpensModal('Mark Down', modalClass);
+    });
+
+    it('opens all critical confirmation modals', () => {
+      const modalClass = CriticalConfirmationModalComponent;
+      mockSafeToDestroy();
+      expectOpensModal('Mark Lost', modalClass);
+      expectOpensModal('Purge', modalClass);
+      expectOpensModal('Destroy', modalClass);
+    });
+  });
+
+  describe('tests if the correct methods are called on confirmation', () => {
+    const expectOsdServiceMethodCalled = (
+      actionName: string,
+      osdServiceMethodName: string
+    ): void => {
+      const osdServiceSpy = spyOn(TestBed.get(OsdService), osdServiceMethodName).and.callFake(
+        () => EMPTY
+      );
+      openActionModal(actionName);
+      const initialState = modalServiceShowSpy.calls.first().args[1].initialState;
+      const submit = initialState.onSubmit || initialState.submitAction;
+      submit.call(component);
+
+      expect(osdServiceSpy.calls.count()).toBe(1);
+      expect(osdServiceSpy.calls.first().args[0]).toBe(1);
+
+      // Reset spies to be able to recreate them
+      osdServiceSpy.calls.reset();
+      modalServiceShowSpy.calls.reset();
+    };
+
+    it('calls the corresponding service methods in confirmation modals', () => {
+      expectOsdServiceMethodCalled('Mark Out', 'markOut');
+      expectOsdServiceMethodCalled('Mark In', 'markIn');
+      expectOsdServiceMethodCalled('Mark Down', 'markDown');
+    });
+
+    it('calls the corresponding service methods in critical confirmation modals', () => {
+      mockSafeToDestroy();
+      expectOsdServiceMethodCalled('Mark Lost', 'markLost');
+      expectOsdServiceMethodCalled('Purge', 'purge');
+      expectOsdServiceMethodCalled('Destroy', 'destroy');
+    });
+  });
+});