From 5de247e6a5220be75e2f4653032e01f6f88b6d16 Mon Sep 17 00:00:00 2001 From: Patrick Seidensal Date: Mon, 19 Aug 2019 13:03:58 +0200 Subject: [PATCH] mgr/dashboard: migrate E2E mgr modules to async/await Fixes: https://tracker.ceph.com/issues/40693 Signed-off-by: Patrick Seidensal --- .../e2e/cluster/mgr-modules.e2e-spec.ts | 42 +-- .../frontend/e2e/cluster/mgr-modules.po.ts | 248 ++++++++---------- .../mgr/dashboard/frontend/e2e/helper.po.ts | 3 + .../dashboard/frontend/e2e/page-helper.po.ts | 6 +- 4 files changed, 130 insertions(+), 169 deletions(-) diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.e2e-spec.ts index 0da02af6b39..b99c1aa1ed0 100644 --- a/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.e2e-spec.ts +++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.e2e-spec.ts @@ -4,60 +4,60 @@ describe('Manager modules page', () => { let mgrmodules: Helper['mgrmodules']; beforeAll(() => { - mgrmodules = new Helper().mgrmodules; + mgrmodules = new Helper().mgrModules; }); - afterEach(() => { - Helper.checkConsole(); + afterEach(async () => { + await Helper.checkConsole(); }); describe('breadcrumb test', () => { - beforeAll(() => { - mgrmodules.navigateTo(); + beforeAll(async () => { + await mgrmodules.navigateTo(); }); - it('should open and show breadcrumb', () => { - expect(mgrmodules.getBreadcrumbText()).toEqual('Manager modules'); + it('should open and show breadcrumb', async () => { + expect(await mgrmodules.getBreadcrumbText()).toEqual('Manager modules'); }); }); describe('verifies editing functionality for manager modules', () => { - beforeAll(() => { - mgrmodules.navigateTo(); + beforeAll(async () => { + await mgrmodules.navigateTo(); }); - it('should test editing on ansible module', () => { + it('should test editing on ansible module', async () => { const ansibleArr = [['rq', 'ca_bundle'], ['colts', 'server_location']]; - mgrmodules.editMgrModule('ansible', ansibleArr); + await mgrmodules.editMgrModule('ansible', ansibleArr); }); - it('should test editing on deepsea module', () => { + it('should test editing on deepsea module', async () => { const deepseaArr = [ ['rq', 'salt_api_eauth'], ['alm', 'salt_api_password'], ['bu', 'salt_api_url'], ['sox', 'salt_api_username'] ]; - mgrmodules.editMgrModule('deepsea', deepseaArr); + await mgrmodules.editMgrModule('deepsea', deepseaArr); }); - it('should test editing on diskprediction_local module', () => { + it('should test editing on diskprediction_local module', async () => { const diskpredLocalArr = [['11', 'predict_interval'], ['0122', 'sleep_interval']]; - mgrmodules.editMgrModule('diskprediction_local', diskpredLocalArr); + await mgrmodules.editMgrModule('diskprediction_local', diskpredLocalArr); }); - it('should test editing on balancer module', () => { + it('should test editing on balancer module', async () => { const balancerArr = [['rq', 'pool_ids']]; - mgrmodules.editMgrModule('balancer', balancerArr); + await mgrmodules.editMgrModule('balancer', balancerArr); }); - it('should test editing on dashboard module', () => { + it('should test editing on dashboard module', async () => { const dashboardArr = [['rq', 'AUDIT_API_ENABLED'], ['rafa', 'GRAFANA_API_PASSWORD']]; - mgrmodules.editMgrModule('dashboard', dashboardArr); + await mgrmodules.editMgrModule('dashboard', dashboardArr); }); - it('should test editing on devicehealth module', () => { - mgrmodules.editDevicehealth('1987', 'sox', '1999', '2020', '456', '567'); + it('should test editing on devicehealth module', async () => { + await mgrmodules.editDevicehealth('1987', 'sox', '1999', '2020', '456', '567'); }); }); }); diff --git a/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.po.ts index 4d6bd91825e..56ac261292a 100644 --- a/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.po.ts +++ b/src/pybind/mgr/dashboard/frontend/e2e/cluster/mgr-modules.po.ts @@ -12,74 +12,58 @@ export class ManagerModulesPageHelper extends PageHelper { // The need to click the module repeatedly in the table is to ensure // that the values in the details tab updated. This fixed a bug I experienced. - editMgrModule(name: string, tuple: string[][]) { + async editMgrModule(name: string, tuple: string[][]) { // Selects the Manager Module and then fills in the desired fields. // Doesn't check/uncheck boxes because it is not reflected in the details table. // DOES NOT WORK FOR ALL MGR MODULES, for example, Device health - this.navigateTo(); - browser.wait(Helper.EC.elementToBeClickable(this.getTableCell(name)), Helper.TIMEOUT); - this.getTableCell(name).click(); - element(by.cssContainingText('button', 'Edit')).click(); + await this.navigateTo(); + await browser.wait(Helper.EC.elementToBeClickable(this.getTableCell(name)), Helper.TIMEOUT); + await this.getTableCell(name).click(); + await element(by.cssContainingText('button', 'Edit')).click(); for (const entry of tuple) { // Clears fields and adds edits - this.inputClear(element(by.id(entry[1]))); - element(by.id(entry[1])).sendKeys(entry[0]); + await this.inputClear(element(by.id(entry[1]))); + await element(by.id(entry[1])).sendKeys(entry[0]); } - element(by.cssContainingText('button', 'Update')) - .click() - .then(() => { - // Checks if edits appear - this.navigateTo(); - browser.wait(Helper.EC.visibilityOf(this.getTableCell(name)), Helper.TIMEOUT).then(() => { - this.getTableCell(name) - .click() - .then(() => { - for (const entry of tuple) { - browser.wait( - Helper.EC.textToBePresentInElement($$('.datatable-body').last(), entry[0]), - Helper.TIMEOUT - ); - } - }); - }); - }); + await element(by.cssContainingText('button', 'Update')).click(); + // Checks if edits appear + await this.navigateTo(); + await browser.wait(Helper.EC.visibilityOf(this.getTableCell(name)), Helper.TIMEOUT); + await this.getTableCell(name).click(); + for (const entry of tuple) { + await browser.wait( + Helper.EC.textToBePresentInElement($$('.datatable-body').last(), entry[0]), + Helper.TIMEOUT + ); + } // Clear mgr module of all edits made to it - this.navigateTo(); - browser.wait(Helper.EC.elementToBeClickable(this.getTableCell(name)), Helper.TIMEOUT); - this.getTableCell(name).click(); - element(by.cssContainingText('button', 'Edit')).click(); + await this.navigateTo(); + await browser.wait(Helper.EC.elementToBeClickable(this.getTableCell(name)), Helper.TIMEOUT); + await this.getTableCell(name).click(); + await element(by.cssContainingText('button', 'Edit')).click(); // Clears the editable fields for (const entry of tuple) { - this.inputClear(element(by.id(entry[1]))); + await this.inputClear(element(by.id(entry[1]))); } // Checks that clearing represents in details tab of module - element(by.cssContainingText('button', 'Update')) - .click() - .then(() => { - this.navigateTo(); - browser.wait(Helper.EC.visibilityOf(this.getTableCell(name)), Helper.TIMEOUT).then(() => { - this.getTableCell(name) - .click() - .then(() => { - for (const entry of tuple) { - browser.wait( - Helper.EC.not( - Helper.EC.textToBePresentInElement($$('.datatable-body').last(), entry[0]) - ), - Helper.TIMEOUT - ); - } - }); - }); - }); + await element(by.cssContainingText('button', 'Update')).click(); + await this.navigateTo(); + await browser.wait(Helper.EC.visibilityOf(this.getTableCell(name)), Helper.TIMEOUT); + await this.getTableCell(name).click(); + for (const entry of tuple) { + await browser.wait( + Helper.EC.not(Helper.EC.textToBePresentInElement($$('.datatable-body').last(), entry[0])), + Helper.TIMEOUT + ); + } } - editDevicehealth( + async editDevicehealth( threshhold?: string, pooln?: string, retention?: string, @@ -91,7 +75,7 @@ export class ManagerModulesPageHelper extends PageHelper { // Selects the Devicehealth manager module, then fills in the desired fields, including all fields except // checkboxes. Clicking checkboxes has been a notable issue in Protractor, therefore they were omitted in this // version of the tests. Could be added in a future PR. Then checks if these edits appear in the details table. - this.navigateTo(); + await this.navigateTo(); let devHealthArray: [string, string][]; devHealthArray = [ [threshhold, 'mark_out_threshold'], @@ -102,111 +86,85 @@ export class ManagerModulesPageHelper extends PageHelper { [warn, 'warn_threshold'] ]; - browser.wait(Helper.EC.elementToBeClickable(this.getTableCell('devicehealth')), Helper.TIMEOUT); - this.getTableCell('devicehealth').click(); - element(by.cssContainingText('button', 'Edit')) - .click() - .then(() => { - for (let i = 0, devHealthTuple; (devHealthTuple = devHealthArray[i]); i++) { - if (devHealthTuple[0] !== undefined) { - // Clears and inputs edits - this.inputClear(element(by.id(devHealthTuple[1]))); - element(by.id(devHealthTuple[1])).sendKeys(devHealthTuple[0]); - } - } - }); - - element(by.cssContainingText('button', 'Update')) - .click() - .then(() => { - this.navigateTo(); - browser - .wait(Helper.EC.visibilityOf(this.getTableCell('devicehealth')), Helper.TIMEOUT) - .then(() => { - // Checks for visibility of devicehealth in table - this.getTableCell('devicehealth') - .click() - .then(() => { - for (let i = 0, devHealthTuple; (devHealthTuple = devHealthArray[i]); i++) { - if (devHealthTuple[0] !== undefined) { - browser.wait(function() { - // Repeatedly reclicks the module to check if edits has been done - element( - by.cssContainingText('.datatable-body-cell-label', 'devicehealth') - ).click(); - return Helper.EC.textToBePresentInElement( - $$('.datatable-body').last(), - devHealthTuple[0] - ); - }, Helper.TIMEOUT); - } - } - }); - }); - }); + await browser.wait( + Helper.EC.elementToBeClickable(this.getTableCell('devicehealth')), + Helper.TIMEOUT + ); + await this.getTableCell('devicehealth').click(); + await element(by.cssContainingText('button', 'Edit')).click(); + for (let i = 0, devHealthTuple; (devHealthTuple = devHealthArray[i]); i++) { + if (devHealthTuple[0] !== undefined) { + // Clears and inputs edits + await this.inputClear(element(by.id(devHealthTuple[1]))); + await element(by.id(devHealthTuple[1])).sendKeys(devHealthTuple[0]); + } + } + + await element(by.cssContainingText('button', 'Update')).click(); + await this.navigateTo(); + await browser.wait(Helper.EC.visibilityOf(this.getTableCell('devicehealth')), Helper.TIMEOUT); + // Checks for visibility of devicehealth in table + await this.getTableCell('devicehealth').click(); + for (let i = 0, devHealthTuple; (devHealthTuple = devHealthArray[i]); i++) { + if (devHealthTuple[0] !== undefined) { + await browser.wait(async function() { + // Repeatedly reclicks the module to check if edits has been done + await element(by.cssContainingText('.datatable-body-cell-label', 'devicehealth')).click(); + return Helper.EC.textToBePresentInElement( + $$('.datatable-body').last(), + devHealthTuple[0] + ); + }, Helper.TIMEOUT); + } + } // Inputs old values into devicehealth fields. This manager module doesnt allow for updates // to be made when the values are cleared. Therefore, I restored them to their original values // (on my local run of ceph-dev, this is subject to change i would assume). I'd imagine there is a // better way of doing this. - this.navigateTo(); - browser.wait(Helper.EC.elementToBeClickable(this.getTableCell('devicehealth')), Helper.TIMEOUT); // checks ansible - this.getTableCell('devicehealth').click(); - element(by.cssContainingText('button', 'Edit')) - .click() - .then(() => { - this.inputClear(element(by.id('mark_out_threshold'))); - element(by.id('mark_out_threshold')).sendKeys('2419200'); + await this.navigateTo(); + await browser.wait( + Helper.EC.elementToBeClickable(this.getTableCell('devicehealth')), + Helper.TIMEOUT + ); // checks ansible + await this.getTableCell('devicehealth').click(); + await element(by.cssContainingText('button', 'Edit')).click(); + await this.inputClear(element(by.id('mark_out_threshold'))); + await element(by.id('mark_out_threshold')).sendKeys('2419200'); - this.inputClear(element(by.id('pool_name'))); - element(by.id('pool_name')).sendKeys('device_health_metrics'); + await this.inputClear(element(by.id('pool_name'))); + await element(by.id('pool_name')).sendKeys('device_health_metrics'); - this.inputClear(element(by.id('retention_period'))); - element(by.id('retention_period')).sendKeys('15552000'); + await this.inputClear(element(by.id('retention_period'))); + await element(by.id('retention_period')).sendKeys('15552000'); - this.inputClear(element(by.id('scrape_frequency'))); - element(by.id('scrape_frequency')).sendKeys('86400'); + await this.inputClear(element(by.id('scrape_frequency'))); + await element(by.id('scrape_frequency')).sendKeys('86400'); - this.inputClear(element(by.id('sleep_interval'))); - element(by.id('sleep_interval')).sendKeys('600'); + await this.inputClear(element(by.id('sleep_interval'))); + await element(by.id('sleep_interval')).sendKeys('600'); - this.inputClear(element(by.id('warn_threshold'))); - element(by.id('warn_threshold')).sendKeys('7257600'); - }); + await this.inputClear(element(by.id('warn_threshold'))); + await element(by.id('warn_threshold')).sendKeys('7257600'); // Checks that clearing represents in details tab of ansible - browser - .wait(Helper.EC.elementToBeClickable(element(by.cssContainingText('button', 'Update')))) - .then(() => { - element(by.cssContainingText('button', 'Update')) - .click() - .then(() => { - this.navigateTo(); - browser - .wait(Helper.EC.visibilityOf(this.getTableCell('devicehealth')), Helper.TIMEOUT) - .then(() => { - this.getTableCell('devicehealth') - .click() - .then(() => { - for (let i = 0, devHealthTuple; (devHealthTuple = devHealthArray[i]); i++) { - if (devHealthTuple[0] !== undefined) { - browser.wait(function() { - // Repeatedly reclicks the module to check if clearing has been done - element( - by.cssContainingText('.datatable-body-cell-label', 'devicehealth') - ).click(); - return Helper.EC.not( - Helper.EC.textToBePresentInElement( - $$('.datatable-body').last(), - devHealthTuple[0] - ) - ); - }, Helper.TIMEOUT); - } - } - }); - }); - }); - }); + await browser.wait( + Helper.EC.elementToBeClickable(element(by.cssContainingText('button', 'Update'))) + ); + await element(by.cssContainingText('button', 'Update')).click(); + await this.navigateTo(); + await browser.wait(Helper.EC.visibilityOf(this.getTableCell('devicehealth')), Helper.TIMEOUT); + await this.getTableCell('devicehealth').click(); + for (let i = 0, devHealthTuple; (devHealthTuple = devHealthArray[i]); i++) { + if (devHealthTuple[0] !== undefined) { + await browser.wait(async function() { + // Repeatedly reclicks the module to check if clearing has been done + await element(by.cssContainingText('.datatable-body-cell-label', 'devicehealth')).click(); + return Helper.EC.not( + Helper.EC.textToBePresentInElement($$('.datatable-body').last(), devHealthTuple[0]) + ); + }, Helper.TIMEOUT); + } + } } } diff --git a/src/pybind/mgr/dashboard/frontend/e2e/helper.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/helper.po.ts index 38ea45b457a..fffd600094e 100644 --- a/src/pybind/mgr/dashboard/frontend/e2e/helper.po.ts +++ b/src/pybind/mgr/dashboard/frontend/e2e/helper.po.ts @@ -1,5 +1,6 @@ import { browser } from 'protractor'; import { ImagesPageHelper } from './block/images.po'; +import { ManagerModulesPageHelper } from './cluster/mgr-modules.po'; import { MonitorsPageHelper } from './cluster/monitors.po'; import { OSDsPageHelper } from './cluster/osds.po'; import { FilesystemsPageHelper } from './filesystems/filesystems.po'; @@ -27,6 +28,7 @@ export class Helper { filesystems: FilesystemsPageHelper; osds: OSDsPageHelper; monitors: MonitorsPageHelper; + mgrModules: ManagerModulesPageHelper; constructor() { this.pools = new PoolPageHelper(); @@ -42,6 +44,7 @@ export class Helper { this.filesystems = new FilesystemsPageHelper(); this.osds = new OSDsPageHelper(); this.monitors = new MonitorsPageHelper(); + this.mgrModules = new ManagerModulesPageHelper(); } /** diff --git a/src/pybind/mgr/dashboard/frontend/e2e/page-helper.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/page-helper.po.ts index 6e2067e8139..2e7026ddd63 100644 --- a/src/pybind/mgr/dashboard/frontend/e2e/page-helper.po.ts +++ b/src/pybind/mgr/dashboard/frontend/e2e/page-helper.po.ts @@ -155,9 +155,9 @@ export abstract class PageHelper { } // used when .clear() does not work on a text box, sends a Ctrl + a, BACKSPACE - inputClear(elem) { - elem.sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'a')); - elem.sendKeys(protractor.Key.BACK_SPACE); + async inputClear(elem) { + await elem.sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'a')); + await elem.sendKeys(protractor.Key.BACK_SPACE); } async navigateTo(page = null) { -- 2.39.5