]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: improve overall E2E stability of navigation
authorPatrick Seidensal <pseidensal@suse.com>
Wed, 21 Aug 2019 07:16:02 +0000 (09:16 +0200)
committerPatrick Seidensal <pseidensal@suse.com>
Wed, 28 Aug 2019 07:38:48 +0000 (09:38 +0200)
The `navigateTo` method will check if a table exists on the table it has
been used to navigate to and if so, wait for the data of the table to
be loaded.

Fixes: https://tracker.ceph.com/issues/41349
Signed-off-by: Patrick Seidensal <pseidensal@suse.com>
src/pybind/mgr/dashboard/frontend/e2e/page-helper.po.ts
src/pybind/mgr/dashboard/frontend/protractor.conf.js

index 2e7026ddd633e0f79c49f77aef4f73143e6b3743..10b445b7d556a2b2d8cccc505b3f8ca27299be49 100644 (file)
@@ -8,6 +8,9 @@ import {
   ElementFinder,
   protractor
 } from 'protractor';
+import { Helper } from './helper.po';
+
+const EC = browser.ExpectedConditions;
 
 interface Pages {
   index: string;
@@ -22,7 +25,7 @@ export abstract class PageHelper {
    * mistakes.  It also reduces boilerplate code and by thus, increases
    * readability.
    */
-  static restrictTo(page): any {
+  static restrictTo(page): Function {
     return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
       const fn: Function = descriptor.value;
       descriptor.value = function(...args) {
@@ -40,6 +43,42 @@ export abstract class PageHelper {
     };
   }
 
+  /**
+   * This is a decorator to be used on methods which change the current page once, like `navigateTo`
+   * and `navigateBack` in this class do. It ensures that, if the new page contains a table, its
+   * data has been fully loaded. If no table is detected, it will return instantly.
+   */
+  static waitForTableData(): Function {
+    return (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => {
+      const fn: Function = descriptor.value;
+      descriptor.value = async function(...args) {
+        const result = fn.apply(this, args);
+
+        // If a table is on the new page, wait until it has gotten its data.
+        const implicitWaitTimeout = (await browser.getProcessedConfig()).implicitWaitTimeout;
+        await browser
+          .manage()
+          .timeouts()
+          .implicitlyWait(1000);
+
+        const tableCount = await element.all(by.css('cd-table')).count();
+        if (tableCount > 0) {
+          const progressBars = element.all(by.css('cd-table datatable-progress'));
+          await progressBars.each(async (progressBar) => {
+            await browser.wait(EC.not(EC.presenceOf(progressBar)), Helper.TIMEOUT);
+          });
+        }
+
+        await browser
+          .manage()
+          .timeouts()
+          .implicitlyWait(implicitWaitTimeout);
+
+        return result;
+      };
+    };
+  }
+
   async getBreadcrumbText(): Promise<string> {
     return $('.breadcrumb-item.active').getText();
   }
@@ -160,10 +199,16 @@ export abstract class PageHelper {
     await elem.sendKeys(protractor.Key.BACK_SPACE);
   }
 
+  @PageHelper.waitForTableData()
   async navigateTo(page = null) {
     page = page || 'index';
     const url = this.pages[page];
-    return browser.get(url);
+    await browser.get(url);
+  }
+
+  @PageHelper.waitForTableData()
+  async navigateBack() {
+    await browser.navigate().back();
   }
 
   getDataTable(): ElementArrayFinder {
index 5418c376017c1efd209ef35a353ee349b380a23f..4cbac9a47268dbe350fdfa226088b68910e86531 100644 (file)
@@ -3,9 +3,10 @@
 
 const { SpecReporter } = require('jasmine-spec-reporter');
 
-exports.config = {
+const config = {
   SELENIUM_PROMISE_MANAGER: false,
   allScriptsTimeout: 11000,
+  implicitWaitTimeout: 360000,
   specs: [
     './e2e/**/*.e2e-spec.ts'
   ],
@@ -40,9 +41,10 @@ exports.config = {
       imageToAscii: 'none',
       clearFoldersBeforeTest: true
     }],
+};
 
-  async onPrepare() {
-    browser.manage().timeouts().implicitlyWait(360000);
+config.onPrepare = async () => {
+    browser.manage().timeouts().implicitlyWait(exports.config.implicitWaitTimeout);
 
     require('ts-node').register({
       project: 'e2e/tsconfig.e2e.json'
@@ -69,4 +71,5 @@ exports.config = {
       });
     });
   }
-};
+
+exports.config = config;