]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.spec.ts
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / block / rbd-form / rbd-form.component.spec.ts
index 9d15d10cfe69f95b9259deda36f8304f7f316403..e9727240292bf6dd64016838bb194334d80e9c2d 100644 (file)
@@ -1,13 +1,14 @@
 import { HttpClientTestingModule } from '@angular/common/http/testing';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ReactiveFormsModule } from '@angular/forms';
-import { ActivatedRoute } from '@angular/router';
+import { ActivatedRoute, Router } from '@angular/router';
 import { RouterTestingModule } from '@angular/router/testing';
 import { TooltipModule } from 'ngx-bootstrap/tooltip';
 
-import { ToastModule } from 'ng2-toastr';
+import { ToastrModule } from 'ngx-toastr';
 
 import { By } from '@angular/platform-browser';
+import { of } from 'rxjs';
 import { ActivatedRouteStub } from '../../../../testing/activated-route-stub';
 import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
 import { RbdService } from '../../../shared/api/rbd.service';
@@ -21,12 +22,15 @@ describe('RbdFormComponent', () => {
   let fixture: ComponentFixture<RbdFormComponent>;
   let activatedRoute: ActivatedRouteStub;
 
+  const queryNativeElement = (cssSelector) =>
+    fixture.debugElement.query(By.css(cssSelector)).nativeElement;
+
   configureTestBed({
     imports: [
       HttpClientTestingModule,
       ReactiveFormsModule,
       RouterTestingModule,
-      ToastModule.forRoot(),
+      ToastrModule.forRoot(),
       SharedModule,
       TooltipModule
     ],
@@ -36,7 +40,8 @@ describe('RbdFormComponent', () => {
         provide: ActivatedRoute,
         useValue: new ActivatedRouteStub({ pool: 'foo', name: 'bar', snap: undefined })
       },
-      i18nProviders
+      i18nProviders,
+      RbdService
     ]
   });
 
@@ -78,10 +83,148 @@ describe('RbdFormComponent', () => {
   describe('test image configuration component', () => {
     it('is visible', () => {
       fixture.detectChanges();
-      expect(
-        fixture.debugElement.query(By.css('cd-rbd-configuration-form')).nativeElement.parentElement
-          .hidden
-      ).toBe(false);
+      expect(queryNativeElement('cd-rbd-configuration-form').parentElement.hidden).toBe(false);
+    });
+  });
+
+  describe('tests for feature flags', () => {
+    let deepFlatten, layering, exclusiveLock, objectMap, journaling, fastDiff;
+    const defaultFeatures = [
+      // Supposed to be enabled by default
+      'deep-flatten',
+      'exclusive-lock',
+      'fast-diff',
+      'layering',
+      'object-map'
+    ];
+    const allFeatureNames = [
+      'deep-flatten',
+      'layering',
+      'exclusive-lock',
+      'object-map',
+      'journaling',
+      'fast-diff'
+    ];
+    const setFeatures = (features) => {
+      component.features = features;
+      component.featuresList = component.objToArray(features);
+      component.createForm();
+    };
+    const getFeatureNativeElements = () => allFeatureNames.map((f) => queryNativeElement(`#${f}`));
+
+    it('should convert feature flags correctly in the constructor', () => {
+      setFeatures({
+        one: { desc: 'one', allowEnable: true, allowDisable: true },
+        two: { desc: 'two', allowEnable: true, allowDisable: true },
+        three: { desc: 'three', allowEnable: true, allowDisable: true }
+      });
+      expect(component.featuresList).toEqual([
+        { desc: 'one', key: 'one', allowDisable: true, allowEnable: true },
+        { desc: 'two', key: 'two', allowDisable: true, allowEnable: true },
+        { desc: 'three', key: 'three', allowDisable: true, allowEnable: true }
+      ]);
+    });
+
+    describe('test edit form flags', () => {
+      const prepare = (pool: string, image: string, enabledFeatures: string[]): void => {
+        const rbdService = TestBed.get(RbdService);
+        spyOn(rbdService, 'get').and.returnValue(
+          of({
+            name: image,
+            pool_name: pool,
+            features_name: enabledFeatures
+          })
+        );
+        spyOn(rbdService, 'defaultFeatures').and.returnValue(of(defaultFeatures));
+        component.router = { url: `/block/rbd/edit/${pool}/${image}` } as Router;
+        fixture.detectChanges();
+        [
+          deepFlatten,
+          layering,
+          exclusiveLock,
+          objectMap,
+          journaling,
+          fastDiff
+        ] = getFeatureNativeElements();
+      };
+
+      it('should have the interlock feature for flags disabled, if one feature is not set', () => {
+        prepare('rbd', 'foobar', ['deep-flatten', 'exclusive-lock', 'layering', 'object-map']);
+
+        expect(objectMap.disabled).toBe(false);
+        expect(fastDiff.disabled).toBe(false);
+
+        expect(objectMap.checked).toBe(true);
+        expect(fastDiff.checked).toBe(false);
+
+        fastDiff.click();
+        fastDiff.click();
+
+        expect(objectMap.checked).toBe(true); // Shall not be disabled by `fast-diff`!
+      });
+
+      it('should not disable object-map when fast-diff is unchecked', () => {
+        prepare('rbd', 'foobar', ['deep-flatten', 'exclusive-lock', 'layering', 'object-map']);
+
+        fastDiff.click();
+        fastDiff.click();
+
+        expect(objectMap.checked).toBe(true); // Shall not be disabled by `fast-diff`!
+      });
+
+      it('should not enable fast-diff when object-map is checked', () => {
+        prepare('rbd', 'foobar', ['deep-flatten', 'exclusive-lock', 'layering', 'object-map']);
+
+        objectMap.click();
+        objectMap.click();
+
+        expect(fastDiff.checked).toBe(false); // Shall not be disabled by `fast-diff`!
+      });
+    });
+
+    describe('test create form flags', () => {
+      beforeEach(() => {
+        const rbdService = TestBed.get(RbdService);
+        spyOn(rbdService, 'defaultFeatures').and.returnValue(of(defaultFeatures));
+        component.router = { url: '/block/rbd/create' } as Router;
+        fixture.detectChanges();
+        [
+          deepFlatten,
+          layering,
+          exclusiveLock,
+          objectMap,
+          journaling,
+          fastDiff
+        ] = getFeatureNativeElements();
+      });
+
+      it('should initialize the checkboxes correctly', () => {
+        expect(deepFlatten.disabled).toBe(false);
+        expect(layering.disabled).toBe(false);
+        expect(exclusiveLock.disabled).toBe(false);
+        expect(objectMap.disabled).toBe(false);
+        expect(journaling.disabled).toBe(false);
+        expect(fastDiff.disabled).toBe(false);
+
+        expect(deepFlatten.checked).toBe(true);
+        expect(layering.checked).toBe(true);
+        expect(exclusiveLock.checked).toBe(true);
+        expect(objectMap.checked).toBe(true);
+        expect(journaling.checked).toBe(false);
+        expect(fastDiff.checked).toBe(true);
+      });
+
+      it('should disable features if their requirements are not met (exclusive-lock)', () => {
+        exclusiveLock.click(); // unchecks exclusive-lock
+        expect(objectMap.disabled).toBe(true);
+        expect(journaling.disabled).toBe(true);
+        expect(fastDiff.disabled).toBe(true);
+      });
+
+      it('should disable features if their requirements are not met (object-map)', () => {
+        objectMap.click(); // unchecks object-map
+        expect(fastDiff.disabled).toBe(true);
+      });
     });
   });
 });