]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Add a unit test form helper class
authorStephan Müller <smueller@suse.com>
Thu, 2 Aug 2018 10:50:24 +0000 (12:50 +0200)
committerStephan Müller <smueller@suse.com>
Tue, 30 Oct 2018 11:03:35 +0000 (12:03 +0100)
This class helps testing forms, most methods were outsourced from the
pool form test suite.

Fixes: https://tracker.ceph.com/issues/36467
Signed-off-by: Stephan Müller <smueller@suse.com>
src/pybind/mgr/dashboard/HACKING.rst
src/pybind/mgr/dashboard/frontend/src/testing/unit-test-helper.ts

index 83f7ff2109216e66f52daacf4a096a2d70c3aa5d..0e7983928c3f62c0bcaeca096c48eb8a95f48780 100644 (file)
@@ -79,6 +79,34 @@ We added 2 npm scripts to help run these tools:
 - ``npm run lint``, will check frontend files against all linters
 - ``npm run fix``, will try to fix all the detected linting errors
 
+Writing Unit Tests
+~~~~~~~~~~~~~~~~~~
+
+To write unit tests most efficient we have a small collection of tools,
+we use within test suites.
+
+Those tools can be found under
+``src/pybind/mgr/dashboard/frontend/src/testing/``, especially take
+a look at ``unit-test-helper.ts``.
+
+There you will be able to find:
+
+``configureTestBed`` that replaces the initial ``TestBed``
+methods. It takes the same arguments as ``TestBed.configureTestingModule``.
+Using it will run your tests a lot faster in development, as it doesn't
+recreate everything from scratch on every test. To use the default behaviour
+pass ``true`` as the second argument.
+
+``PermissionHelper`` to help determine if
+the correct actions are shown based on the current permissions and selection
+in a list.
+
+``FormHelper`` which makes testing a form a lot easier
+with a few simple methods. It allows you to set a control or multiple
+controls, expect if a control is valid or has an error or just do both with
+one method. Additional you can expect a template element or multiple elements
+to be visible in the rendered template.
+
 Running Unit Tests
 ~~~~~~~~~~~~~~~~~~
 
index 8e1cc2b461f13cc107ac5a110a7377230731ae35..bd396d34462c57f1e1f7585f386f2d2096173285 100644 (file)
@@ -1,8 +1,11 @@
-import { async, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { AbstractControl } from '@angular/forms';
+import { By } from '@angular/platform-browser';
 
 import * as _ from 'lodash';
 
 import { TableActionsComponent } from '../app/shared/datatable/table-actions/table-actions.component';
+import { CdFormGroup } from '../app/shared/forms/cd-form-group';
 import { Permission } from '../app/shared/models/permissions';
 import { _DEV_ } from '../unit-test-configuration';
 
@@ -89,3 +92,90 @@ export class PermissionHelper {
     this.tableActions.selection.update();
   }
 }
+
+export class FormHelper {
+  form: CdFormGroup;
+
+  constructor(form: CdFormGroup) {
+    this.form = form;
+  }
+
+  /**
+   * Changes multiple values in multiple controls
+   */
+  setMultipleValues(values: { [controlName: string]: any }, markAsDirty?: boolean) {
+    Object.keys(values).forEach((key) => {
+      this.setValue(key, values[key], markAsDirty);
+    });
+  }
+
+  /**
+   * Changes the value of a control
+   */
+  setValue(control: AbstractControl | string, value: any, markAsDirty?: boolean): AbstractControl {
+    control = this.getControl(control);
+    if (markAsDirty) {
+      control.markAsDirty();
+    }
+    control.setValue(value);
+    return control;
+  }
+
+  private getControl(control: AbstractControl | string): AbstractControl {
+    if (typeof control === 'string') {
+      return this.form.get(control);
+    }
+    return control;
+  }
+
+  /**
+   * Change the value of the control and expect the control to be valid afterwards.
+   */
+  expectValidChange(control: AbstractControl | string, value: any, markAsDirty?: boolean) {
+    this.expectValid(this.setValue(control, value, markAsDirty));
+  }
+
+  /**
+   * Expect that the given control is valid.
+   */
+  expectValid(control: AbstractControl | string) {
+    // 'isValid' would be false for disabled controls
+    expect(this.getControl(control).errors).toBe(null);
+  }
+
+  /**
+   * Change the value of the control and expect a specific error.
+   */
+  expectErrorChange(
+    control: AbstractControl | string,
+    value: any,
+    error: string,
+    markAsDirty?: boolean
+  ) {
+    this.expectError(this.setValue(control, value, markAsDirty), error);
+  }
+
+  /**
+   * Expect a specific error for the given control.
+   */
+  expectError(control: AbstractControl | string, error: string) {
+    expect(this.getControl(control).hasError(error)).toBeTruthy();
+  }
+
+  /**
+   * Expect a list of id elements to be visible or not.
+   */
+  expectIdElementsVisible(fixture: ComponentFixture<any>, ids: string[], visibility: boolean) {
+    fixture.detectChanges();
+    ids.forEach((css) => {
+      this.expectElementVisible(fixture, `#${css}`, visibility);
+    });
+  }
+
+  /**
+   * Expect a specific element in fixture to be visible or not.
+   */
+  expectElementVisible(fixture: ComponentFixture<any>, css: string, visibility: boolean) {
+    expect(Boolean(fixture.debugElement.query(By.css(css)))).toBe(visibility);
+  }
+}