From: Patrick Seidensal Date: Fri, 16 Aug 2019 12:39:54 +0000 (+0200) Subject: mgr/dashboard: migrate E2E buckets to async/await X-Git-Tag: v15.1.0~1745^2~31 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=4511bf17c9de90acb86f5fab8de1d48d49b9264a;p=ceph-ci.git mgr/dashboard: migrate E2E buckets to async/await Fixes: https://tracker.ceph.com/issues/40693 Signed-off-by: Patrick Seidensal --- diff --git a/src/pybind/mgr/dashboard/frontend/e2e/rgw/buckets.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/e2e/rgw/buckets.e2e-spec.ts index c1415899128..ce864dca847 100644 --- a/src/pybind/mgr/dashboard/frontend/e2e/rgw/buckets.e2e-spec.ts +++ b/src/pybind/mgr/dashboard/frontend/e2e/rgw/buckets.e2e-spec.ts @@ -1,57 +1,63 @@ +import { $ } from 'protractor'; import { Helper } from '../helper.po'; describe('RGW buckets page', () => { let buckets: Helper['buckets']; - beforeAll(() => { - buckets = new Helper().buckets; - buckets.navigateTo(); + beforeAll(async () => { + const helper = new Helper(); + buckets = helper.buckets; }); - afterEach(() => { - Helper.checkConsole(); + afterEach(async () => { + await Helper.checkConsole(); }); - describe('breadcrumb test', () => { - it('should open and show breadcrumb', () => { - expect(buckets.getBreadcrumbText()).toEqual('Buckets'); - }); + it('should open and show breadcrumb', async () => { + await buckets.navigateTo(); + expect(await $('.breadcrumb-item.active').getText()).toBe('Buckets'); }); - describe('create, edit & delete bucket test', () => { - it('should create bucket', () => { - buckets.create( - '000test', - '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', - 'default-placement' - ); - expect(buckets.getTableCell('000test').isPresent()).toBe(true); - }); + it('should create bucket', async () => { + await buckets.navigateTo('create'); + await buckets.create( + '000test', + '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', + 'default-placement' + ); + expect(await buckets.getTableCell('000test').isPresent()).toBe(true); + }); - it('should edit bucket', () => { - buckets.edit('000test', 'dev'); - expect(buckets.getTable().getText()).toMatch('dev'); - }); + it('should edit bucket', async () => { + await buckets.navigateTo(); + await buckets.edit('000test', 'dev'); + expect(await buckets.getTable().getText()).toMatch('dev'); + }); - it('should delete bucket', () => { - buckets.delete('000test'); - expect(buckets.getTableCell('000test').isPresent()).toBe(false); - }); + it('should delete bucket', async () => { + await buckets.navigateTo(); + await buckets.delete('000test'); + expect(buckets.getTableCell('000test').isPresent()).toBe(false); }); describe('Invalid Input in Create and Edit tests', () => { - it('should test invalid inputs in create fields', () => { - buckets.invalidCreate(); + it('should test invalid inputs in create fields', async () => { + await buckets.navigateTo('create'); + await buckets.testInvalidCreate(); }); - it('should test invalid input in edit owner field', () => { - buckets.create( + it('should test invalid input in edit owner field', async () => { + await buckets.navigateTo('create'); + await buckets.create( '000rq', '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', 'default-placement' ); - buckets.invalidEdit('000rq'); - buckets.delete('000rq'); + + await buckets.testInvalidEdit('000rq'); + + await buckets.navigateTo(); + await buckets.delete('000rq'); }); }); }); diff --git a/src/pybind/mgr/dashboard/frontend/e2e/rgw/buckets.po.ts b/src/pybind/mgr/dashboard/frontend/e2e/rgw/buckets.po.ts index ae7f9af6e63..e86ad1b2aa4 100644 --- a/src/pybind/mgr/dashboard/frontend/e2e/rgw/buckets.po.ts +++ b/src/pybind/mgr/dashboard/frontend/e2e/rgw/buckets.po.ts @@ -2,210 +2,201 @@ import { $, browser, by, element } from 'protractor'; import { Helper } from '../helper.po'; import { PageHelper } from '../page-helper.po'; -export class BucketsPageHelper extends PageHelper { - pages = { - index: '/#/rgw/bucket', - create: '/#/rgw/bucket/create' - }; - - create(name, owner, placementTarget) { - this.navigateTo('create'); +const pages = { + index: '/#/rgw/bucket', + create: '/#/rgw/bucket/create' +}; +export class BucketsPageHelper extends PageHelper { + pages = pages; + + /** + * TODO add check to verify the existance of the bucket! + * TODO let it print a meaningful error message (for devs) if it does not exist! + */ + @PageHelper.restrictTo(pages.create) + async create(name: string, owner: string, placementTarget: string) { // Enter in bucket name - element(by.id('bid')).sendKeys(name); + await element(by.id('bid')).sendKeys(name); // Select bucket owner - element(by.id('owner')).click(); - element(by.cssContainingText('select[name=owner] option', owner)).click(); + await element(by.id('owner')).click(); + await element(by.cssContainingText('select[name=owner] option', owner)).click(); expect(element(by.id('owner')).getAttribute('class')).toContain('ng-valid'); // Select bucket placement target: - element(by.id('owner')).click(); - element(by.cssContainingText('select[name=placement-target] option', placementTarget)).click(); + await element(by.id('owner')).click(); + await element( + by.cssContainingText('select[name=placement-target] option', placementTarget) + ).click(); expect(element(by.id('placement-target')).getAttribute('class')).toContain('ng-valid'); // Click the create button and wait for bucket to be made const createButton = element(by.cssContainingText('button', 'Create Bucket')); - createButton.click().then(() => { - browser.wait( - Helper.EC.presenceOf(this.getTableCell(name)), - Helper.TIMEOUT, - 'Timed out waiting for bucket creation' - ); - }); - } + await createButton.click(); - edit(name, new_owner) { - this.navigateTo(); - - browser.wait(Helper.EC.elementToBeClickable(this.getTableCell(name)), 10000); // wait for table to load - this.getTableCell(name).click(); // click on the bucket you want to edit in the table - element(by.cssContainingText('button', 'Edit')).click(); // click button to move to edit page - - expect(this.getBreadcrumbText()).toEqual('Edit'); + return browser.wait( + Helper.EC.presenceOf(this.getTableCell(name)), + Helper.TIMEOUT, + 'Timed out waiting for bucket creation' + ); + } + @PageHelper.restrictTo(pages.index) + async edit(name: string, new_owner: string) { + await this.getTableCell(name).click(); // click on the bucket you want to edit in the table + await element(by.cssContainingText('button', 'Edit')).click(); // click button to move to edit page + expect(await this.getBreadcrumbText()).toEqual('Edit'); expect(element(by.css('input[name=placement-target]')).getAttribute('value')).toBe( 'default-placement' ); + await element(by.id('owner')).click(); // click owner dropdown menu + await element(by.cssContainingText('select[name=owner] option', new_owner)).click(); // select the new user + await element(by.cssContainingText('button', 'Edit Bucket')).click(); - const ownerDropDown = element(by.id('owner')); - ownerDropDown.click(); // click owner dropdown menu - - element(by.cssContainingText('select[name=owner] option', new_owner)).click(); // select the new user - const editbutton = element(by.cssContainingText('button', 'Edit Bucket')); - editbutton.click().then(() => { - // wait to be back on buckets page with table visible - browser.wait( - Helper.EC.elementToBeClickable(this.getTableCell(name)), - 10000, - 'Could not return to buckets page and load table after editing bucket' - ); - - // click on edited bucket and check its details table for edited owner field - this.getTableCell(name).click(); - const element_details_table = element - .all(by.css('.table.table-striped.table-bordered')) - .first(); - expect(element_details_table.getText()).toMatch(new_owner); - }); - } + // wait to be back on buckets page with table visible + await browser.wait( + Helper.EC.elementToBeClickable(this.getTableCell(name)), + 10000, + 'Could not return to buckets page and load table after editing bucket' + ); - delete(name) { - this.navigateTo(); + // click on edited bucket and check its details table for edited owner field + const promise = await this.getTableCell(name).click(); + const element_details_table = element + .all(by.css('.table.table-striped.table-bordered')) + .first(); + expect(element_details_table.getText()).toMatch(new_owner); + return promise; + } + @PageHelper.restrictTo(pages.index) + async delete(name) { // wait for table to load - browser.wait(Helper.EC.elementToBeClickable(this.getTableCell(name)), 10000); + await browser.wait(Helper.EC.elementToBeClickable(this.getTableCell(name)), Helper.TIMEOUT); - this.getTableCell(name).click(); // click on the bucket you want to delete in the table - $('.table-actions button.dropdown-toggle').click(); // click toggle menu - $('li.delete a').click(); // click delete + await this.getTableCell(name).click(); // click on the bucket you want to delete in the table + await $('.table-actions button.dropdown-toggle').click(); // click toggle menu + await $('li.delete a').click(); // click delete // wait for pop-up to be visible (checks for title of pop-up) - browser.wait(Helper.EC.visibilityOf($('.modal-title.float-left')), 10000).then(() => { - browser.wait(Helper.EC.visibilityOf($('.custom-control-label')), 5000); - $('.custom-control-label').click(); - element(by.cssContainingText('button', 'Delete bucket')) - .click() - .then(() => { - this.navigateTo(); - browser.wait(Helper.EC.not(Helper.EC.presenceOf(this.getTableCell(name))), 10000); - }); - }); + await browser.wait(Helper.EC.visibilityOf($('.modal-title.float-left')), Helper.TIMEOUT); + await browser.wait(Helper.EC.visibilityOf($('.custom-control-label')), Helper.TIMEOUT); + await $('.custom-control-label').click(); + await element(by.cssContainingText('button', 'Delete bucket')).click(); + await this.navigateTo(); + return browser.wait( + Helper.EC.not(Helper.EC.presenceOf(this.getTableCell(name))), + Helper.TIMEOUT + ); } - invalidCreate() { - this.navigateTo('create'); - expect(this.getBreadcrumbText()).toEqual('Create'); - + async testInvalidCreate() { + await this.navigateTo('create'); const nameInputField = element(by.id('bid')); // Grabs name box field const ownerDropDown = element(by.id('owner')); // Grab owner field // Gives an invalid name (too short), then waits for dashboard to determine validity - nameInputField.sendKeys('rq'); + await nameInputField.sendKeys('rq'); - this.moveClick(ownerDropDown); // To trigger a validation + await ownerDropDown.click(); // To trigger a validation - browser.wait( - function() { + await browser.wait( + async () => { // Waiting for website to decide if name is valid or not - return nameInputField.getAttribute('class').then(function(classValue) { - return classValue.indexOf('ng-pending') === -1; - }); + const klass = await nameInputField.getAttribute('class'); + return !klass.includes('ng-pending'); }, 5000, 'Timed out waiting for dashboard to decide bucket name validity' ); // Check that name input field was marked invalid in the css - expect(nameInputField.getAttribute('class')).toContain('ng-invalid'); + expect(await nameInputField.getAttribute('class')).toContain('ng-invalid'); // Check that error message was printed under name input field - expect(element(by.css('#bid + .invalid-feedback')).getText()).toMatch( + expect(await element(by.css('#bid + .invalid-feedback')).getText()).toMatch( 'The value is not valid.' ); // Test invalid owner input - this.moveClick(ownerDropDown); // Clicks the Owner drop down on the Create Bucket page + await ownerDropDown.click(); // Clicks the Owner drop down on the Create Bucket page // select some valid option. The owner drop down error message will not appear unless a valid user was selected at // one point before the invalid placeholder user is selected. - element(by.cssContainingText('select[name=owner] option', 'dev')).click(); + await element(by.cssContainingText('select[name=owner] option', 'dev')).click(); - this.moveClick(ownerDropDown); // Clicks the Owner drop down on the Create Bucket page + await ownerDropDown.click(); // select the first option, which is invalid because it is a placeholder - element(by.cssContainingText('select[name=owner] option', 'Select a user')).click(); + await element(by.cssContainingText('select[name=owner] option', 'Select a user')).click(); - this.moveClick(nameInputField); // To trigger a validation + await nameInputField.click(); // Check that owner drop down field was marked invalid in the css - expect(element(by.id('owner')).getAttribute('class')).toContain('ng-invalid'); + expect(await element(by.id('owner')).getAttribute('class')).toContain('ng-invalid'); // Check that error message was printed under owner drop down field - expect(element(by.css('#owner + .invalid-feedback')).getText()).toMatch( + expect(await element(by.css('#owner + .invalid-feedback')).getText()).toMatch( 'This field is required.' ); // Check invalid placement target input - this.moveClick(ownerDropDown); - element(by.cssContainingText('select[name=owner] option', 'dev')).click(); + await ownerDropDown.click(); + await element(by.cssContainingText('select[name=owner] option', 'dev')).click(); // The drop down error message will not appear unless a valid option is previsously selected. - element( + await element( by.cssContainingText('select[name=placement-target] option', 'default-placement') ).click(); - element( + await element( by.cssContainingText('select[name=placement-target] option', 'Select a placement target') ).click(); - this.moveClick(nameInputField); // To trigger a validation - expect(element(by.id('placement-target')).getAttribute('class')).toContain('ng-invalid'); - expect(element(by.css('#placement-target + .invalid-feedback')).getText()).toMatch( + await nameInputField.click(); // Trigger validation + expect(await element(by.id('placement-target')).getAttribute('class')).toContain('ng-invalid'); + expect(await element(by.css('#placement-target + .invalid-feedback')).getText()).toMatch( 'This field is required.' ); // Clicks the Create Bucket button but the page doesn't move. Done by testing // for the breadcrumb - this.moveClick(element(by.cssContainingText('button', 'Create Bucket'))); // Clicks Create Bucket button - expect(this.getBreadcrumbText()).toEqual('Create'); + await element(by.cssContainingText('button', 'Create Bucket')).click(); // Clicks Create Bucket button + expect(await this.getBreadcrumbText()).toEqual('Create'); // content in fields seems to subsist through tests if not cleared, so it is cleared - nameInputField.clear().then(() => { - element(by.cssContainingText('button', 'Cancel')).click(); - }); + await nameInputField.clear(); + return element(by.cssContainingText('button', 'Cancel')).click(); } - invalidEdit(name) { - this.navigateTo(); + async testInvalidEdit(name) { + await this.navigateTo(); - browser.wait( + await browser.wait( Helper.EC.elementToBeClickable(this.getTableCell(name)), 10000, 'Failed waiting for bucket to be present in table' ); // wait for table to load - this.getTableCell(name).click(); // click on the bucket you want to edit in the table - element(by.cssContainingText('button', 'Edit')).click(); // click button to move to edit page + await this.getTableCell(name).click(); // click on the bucket you want to edit in the table + await element(by.cssContainingText('button', 'Edit')).click(); // click button to move to edit page - expect(this.getBreadcrumbText()).toEqual('Edit'); + expect(await this.getBreadcrumbText()).toEqual('Edit'); // Chooses 'Select a user' rather than a valid owner on Edit Bucket page // and checks if it's an invalid input const ownerDropDown = element(by.id('owner')); - browser.wait(Helper.EC.elementToBeClickable(ownerDropDown), 5000); + await browser.wait(Helper.EC.elementToBeClickable(ownerDropDown), Helper.TIMEOUT); + await ownerDropDown.click(); // Clicks the Owner drop down on the Create Bucket page - this.moveClick(ownerDropDown); // Clicks the Owner drop down on the Create Bucket page // select the first option, which is invalid because it is a placeholder - element(by.cssContainingText('select[name=owner] option', 'Select a user')).click(); + await element(by.cssContainingText('select[name=owner] option', 'Select a user')).click(); // Changes when updated to bootstrap 4 -> Error message takes a long time to appear unless another field - // is clicked on. For that reason, I'm having the test click on the nedit button before checking for errors - element(by.cssContainingText('button', 'Edit Bucket')).click(); + // is clicked on. For that reason, I'm having the test click on the edit button before checking for errors + await element(by.cssContainingText('button', 'Edit Bucket')).click(); // Check that owner drop down field was marked invalid in the css - expect(element(by.id('owner')).getAttribute('class')).toContain('ng-invalid'); + expect(await element(by.id('owner')).getAttribute('class')).toContain('ng-invalid'); // Check that error message was printed under owner drop down field - expect(element(by.css('#owner + .invalid-feedback')).getText()).toMatch( + expect(await element(by.css('#owner + .invalid-feedback')).getText()).toMatch( 'This field is required.' ); - // Clicks the Edit Bucket button but the page doesn't move. Done by testing for - // breadcrumb - element(by.cssContainingText('button', 'Edit Bucket')).click(); // Gets the Edit button and clicks it - expect(this.getBreadcrumbText()).toEqual('Edit'); + expect(await this.getBreadcrumbText()).toEqual('Edit'); } }