]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Fixes regression in device selection modal 35875/head
authorStephan Müller <smueller@suse.com>
Wed, 1 Jul 2020 14:30:55 +0000 (16:30 +0200)
committerStephan Müller <smueller@suse.com>
Wed, 1 Jul 2020 16:22:26 +0000 (18:22 +0200)
The 'ExpressionChangedAfterItHasBeenCheckedError' has recently
shown up in device selection modal in OSD creation form. It looks
like it's a regression due to the modal switch (PR #35370). Which was
merged yesterday and it had worked on Monday.

Fixes: https://tracker.ceph.com/issues/46303
Signed-off-by: Stephan Müller <smueller@suse.com>
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-devices-selection-groups/osd-devices-selection-groups.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-devices-selection-modal/osd-devices-selection-modal.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-devices-selection-modal/osd-devices-selection-modal.component.ts
src/pybind/mgr/dashboard/frontend/src/testing/unit-test-helper.ts

index 2d7d51614533532cc4a911d274ee55cd05e79cb8..893f981498782edac4c9ff6b095ead4ec7fbc3fd 100644 (file)
@@ -8,7 +8,8 @@ import { ToastrModule } from 'ngx-toastr';
 import {
   configureTestBed,
   FixtureHelper,
-  i18nProviders
+  i18nProviders,
+  Mocks
 } from '../../../../../testing/unit-test-helper';
 import { SharedModule } from '../../../../shared/shared.module';
 import { InventoryDevice } from '../../inventory/inventory-devices/inventory-device.model';
@@ -19,25 +20,7 @@ describe('OsdDevicesSelectionGroupsComponent', () => {
   let component: OsdDevicesSelectionGroupsComponent;
   let fixture: ComponentFixture<OsdDevicesSelectionGroupsComponent>;
   let fixtureHelper: FixtureHelper;
-  const devices: InventoryDevice[] = [
-    {
-      hostname: 'node0',
-      uid: '1',
-      path: 'sda',
-      sys_api: {
-        vendor: 'AAA',
-        model: 'aaa',
-        size: 1024,
-        rotational: 'false',
-        human_readable_size: '1 KB'
-      },
-      available: false,
-      rejected_reasons: [''],
-      device_id: 'AAA-aaa-id0',
-      human_readable_type: 'nvme/ssd',
-      osd_ids: []
-    }
-  ];
+  const devices: InventoryDevice[] = [Mocks.getInventoryDevice('node0', '1')];
 
   const buttonSelector = '.cd-col-form-input button';
   const getButton = () => {
index 91573a80649d969588ea9a5a4b4e46e6f90daeb8..6847104c67d72ad859abee402d8c5fad1b8d51f1 100644 (file)
@@ -7,7 +7,7 @@ import { RouterTestingModule } from '@angular/router/testing';
 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
 import { ToastrModule } from 'ngx-toastr';
 
-import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { configureTestBed, i18nProviders, Mocks } from '../../../../../testing/unit-test-helper';
 import { CdTableColumnFiltersChange } from '../../../../shared/models/cd-table-column-filters-change';
 import { SharedModule } from '../../../../shared/shared.module';
 import { InventoryDevice } from '../../inventory/inventory-devices/inventory-device.model';
@@ -17,25 +17,9 @@ import { OsdDevicesSelectionModalComponent } from './osd-devices-selection-modal
 describe('OsdDevicesSelectionModalComponent', () => {
   let component: OsdDevicesSelectionModalComponent;
   let fixture: ComponentFixture<OsdDevicesSelectionModalComponent>;
-  const devices: InventoryDevice[] = [
-    {
-      hostname: 'node0',
-      uid: '1',
-      path: 'sda',
-      sys_api: {
-        vendor: 'AAA',
-        model: 'aaa',
-        size: 1024,
-        rotational: 'false',
-        human_readable_size: '1 KB'
-      },
-      available: false,
-      rejected_reasons: [''],
-      device_id: 'AAA-aaa-id0',
-      human_readable_type: 'nvme/ssd',
-      osd_ids: []
-    }
-  ];
+  let timeoutFn: Function;
+
+  const devices: InventoryDevice[] = [Mocks.getInventoryDevice('node0', '1')];
 
   const expectSubmitButton = (enabled: boolean) => {
     const nativeElement = fixture.debugElement.nativeElement;
@@ -58,9 +42,28 @@ describe('OsdDevicesSelectionModalComponent', () => {
   });
 
   beforeEach(() => {
+    spyOn(window, 'setTimeout').and.callFake((fn) => (timeoutFn = fn));
+
     fixture = TestBed.createComponent(OsdDevicesSelectionModalComponent);
     component = fixture.componentInstance;
     component.devices = devices;
+
+    // Mocks InventoryDeviceComponent
+    component.inventoryDevices = {
+      columns: [
+        { name: 'Device path', prop: 'path' },
+        {
+          name: 'Type',
+          prop: 'human_readable_type'
+        },
+        {
+          name: 'Available',
+          prop: 'available'
+        }
+      ]
+    } as InventoryDevicesComponent;
+    // Mocks the update from the above component
+    component.filterColumns = ['path', 'human_readable_type'];
     fixture.detectChanges();
   });
 
@@ -72,6 +75,16 @@ describe('OsdDevicesSelectionModalComponent', () => {
     expectSubmitButton(false);
   });
 
+  it(
+    'should update requiredFilters after ngAfterViewInit is called to prevent ' +
+      'ExpressionChangedAfterItHasBeenCheckedError',
+    () => {
+      expect(component.requiredFilters).toEqual([]);
+      timeoutFn();
+      expect(component.requiredFilters).toEqual(['Device path', 'Type']);
+    }
+  );
+
   it('should enable submit button after filtering some devices', () => {
     const event: CdTableColumnFiltersChange = {
       filters: [
index deb613a3f0cce44eb406b8c16a0c7aa505253455..4f677ac147dcdc7d8ee2e76e0c1ed40f5b4af7ec 100644 (file)
@@ -54,7 +54,10 @@ export class OsdDevicesSelectionModalComponent implements AfterViewInit {
     const cols = _.filter(this.inventoryDevices.columns, (col) => {
       return this.filterColumns.includes(col.prop) && col.prop !== 'hostname';
     });
-    this.requiredFilters = _.map(cols, 'name');
+    // Fixes 'ExpressionChangedAfterItHasBeenCheckedError'
+    setTimeout(() => {
+      this.requiredFilters = _.map(cols, 'name');
+    }, 0);
   }
 
   createForm() {
index 8b12c377a39b9be82ba90904dbbf0237e1caa903..da024dc1990fc67028e913c03ab077b5a2c9f77b 100644 (file)
@@ -8,6 +8,7 @@ import { NgbModal, NgbNav, NgbNavItem } from '@ng-bootstrap/ng-bootstrap';
 import { I18n } from '@ngx-translate/i18n-polyfill';
 import { configureTestSuite } from 'ng-bullet';
 
+import { InventoryDevice } from '../app/ceph/cluster/inventory/inventory-devices/inventory-device.model';
 import { TableActionsComponent } from '../app/shared/datatable/table-actions/table-actions.component';
 import { Icons } from '../app/shared/enum/icons.enum';
 import { CdFormGroup } from '../app/shared/forms/cd-form-group';
@@ -549,6 +550,31 @@ export class Mocks {
     ];
     return rule;
   }
+
+  static getInventoryDevice(
+    hostname: string,
+    uid: string,
+    path = 'sda',
+    available = false
+  ): InventoryDevice {
+    return {
+      hostname,
+      uid,
+      path,
+      available,
+      sys_api: {
+        vendor: 'AAA',
+        model: 'aaa',
+        size: 1024,
+        rotational: 'false',
+        human_readable_size: '1 KB'
+      },
+      rejected_reasons: [''],
+      device_id: 'AAA-aaa-id0',
+      human_readable_type: 'nvme/ssd',
+      osd_ids: []
+    };
+  }
 }
 
 export class TabHelper {