Skip to content

Commit

Permalink
mgr/dashboard: E2E Test for RBD Mirroring and Images (ceph#29381)
Browse files Browse the repository at this point in the history
mgr/dashboard: E2E Test for RBD Mirroring and Images

Reviewed-by: Stephan Müller <[email protected]>
Reviewed-by: Tiago Melo <[email protected]>
  • Loading branch information
Lenz Grimmer authored Aug 19, 2019
2 parents 06e34da + 3a83c29 commit a9e6eb5
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 7 deletions.
40 changes: 40 additions & 0 deletions src/pybind/mgr/dashboard/frontend/e2e/block/images.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { Helper } from '../helper.po';

describe('Images page', () => {
let images: Helper['images'];
let pools: Helper['pools'];

beforeAll(() => {
images = new Helper().images;
pools = new Helper().pools;
});

afterEach(() => {
Expand All @@ -30,4 +32,42 @@ describe('Images page', () => {
expect(images.getTabText(2)).toEqual('Overall Performance');
});
});

describe('create, edit & delete image test', () => {
const poolName = 'e2e_images_pool';
const imageName = 'e2e_images_image';
const newImageName = 'e2e_images_image_new';

beforeAll(() => {
pools.navigateTo('create'); // Need pool for image testing
pools.create(poolName, 8, 'rbd').then(() => {
pools.navigateTo();
pools.exist(poolName, true);
});
images.navigateTo();
});

it('should create image', () => {
images.createImage(imageName, poolName, '1');
expect(images.getTableCell(imageName).isPresent()).toBe(true);
});

it('should edit image', () => {
images.editImage(imageName, poolName, newImageName, '2');
expect(images.getTableCell(newImageName).isPresent()).toBe(true);
});

it('should delete image', () => {
images.deleteImage(newImageName);
expect(images.getTableCell(newImageName).isPresent()).toBe(false);
});

afterAll(() => {
pools.navigateTo(); // Deletes images test pool
pools.delete(poolName).then(() => {
pools.navigateTo();
pools.exist(poolName, false);
});
});
});
});
89 changes: 88 additions & 1 deletion src/pybind/mgr/dashboard/frontend/e2e/block/images.po.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,92 @@
import { $, $$, browser, by, element } from 'protractor';
import { Helper } from '../helper.po';
import { PageHelper } from '../page-helper.po';

export class ImagesPageHelper extends PageHelper {
pages = { index: '/#/block/rbd' };
pages = {
index: '/#/block/rbd',
create: '/#/block/rbd/create'
};

// Creates a block image and fills in the name, pool, and size fields. Then checks
// if the image is present in the Images table.
createImage(name, pool, size) {
this.navigateTo('create');

// Need the string '[value="<pool>"]' to find the pool in the dropdown menu
const getPoolName = `[value="${pool}"]`;

element(by.id('name')).sendKeys(name); // Enter in image name

// Select image pool
element(by.id('pool')).click();
element(by.cssContainingText('select[name=pool] option', pool)).click();
$(getPoolName).click();
expect(element(by.id('pool')).getAttribute('class')).toContain('ng-valid'); // check if selected

// Enter in the size of the image
element(by.id('size')).click();
element(by.id('size')).sendKeys(size);

// Click the create button and wait for image to be made
element(by.cssContainingText('button', 'Create RBD'))
.click()
.then(() => {
browser.wait(Helper.EC.presenceOf(this.getTableCell(name)), Helper.TIMEOUT);
});
}

editImage(name, pool, newName, newSize) {
const base_url = '/#/block/rbd/edit/';
const editURL = base_url
.concat(pool)
.concat('/')
.concat(name);
browser.get(editURL);

element(by.id('name')).click(); // click name box and send new name
element(by.id('name')).clear();
element(by.id('name')).sendKeys(newName);
element(by.id('size')).click();
element(by.id('size')).clear();
element(by.id('size')).sendKeys(newSize); // click the size box and send new size

element(by.cssContainingText('button', 'Edit RBD'))
.click()
.then(() => {
this.navigateTo();
browser
.wait(Helper.EC.elementToBeClickable(this.getTableCell(newName)), Helper.TIMEOUT)
.then(() => {
this.getTableCell(newName).click();
expect(
element
.all(by.css('.table.table-striped.table-bordered'))
.first()
.getText()
).toMatch(newSize);
}); // click edit button and wait to make sure new owner is present in table
});
}

deleteImage(name) {
this.navigateTo();

// wait for table to load
browser.wait(Helper.EC.elementToBeClickable(this.getTableCell(name)), Helper.TIMEOUT);
this.getTableCell(name).click(); // click on the image you want to delete in the table
$$('.table-actions button.dropdown-toggle')
.first()
.click(); // click toggle menu
$('li.delete.ng-star-inserted').click(); // click delete
// wait for pop-up to be visible (checks for title of pop-up)
browser.wait(Helper.EC.visibilityOf($('.modal-body')), Helper.TIMEOUT).then(() => {
$('.custom-control-label').click(); // click confirmation checkbox
element(by.cssContainingText('button', 'Delete RBD'))
.click()
.then(() => {
browser.wait(Helper.EC.stalenessOf(this.getTableCell(name)), Helper.TIMEOUT);
});
});
}
}
32 changes: 32 additions & 0 deletions src/pybind/mgr/dashboard/frontend/e2e/block/mirroring.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { Helper } from '../helper.po';

describe('Mirroring page', () => {
let mirroring: Helper['mirroring'];
let pools: Helper['pools'];

beforeAll(() => {
mirroring = new Helper().mirroring;
pools = new Helper().pools;
});

afterEach(() => {
Expand All @@ -30,4 +32,34 @@ describe('Mirroring page', () => {
expect(mirroring.getTabText(2)).toEqual('Ready');
});
});

describe('checks that edit mode functionality shows in the pools table', () => {
const poolName = 'mirrorpoolrq';

beforeAll(() => {
pools.navigateTo('create'); // Need pool for mirroring testing
pools.create(poolName, 8, 'rbd').then(() => {
pools.navigateTo();
pools.exist(poolName, true);
});
});

it('tests editing mode for pools', () => {
mirroring.navigateTo();
expect(mirroring.editMirror(poolName, 'Pool'));
expect(mirroring.getFirstTableCellWithText('pool').isPresent()).toBe(true);
expect(mirroring.editMirror(poolName, 'Image'));
expect(mirroring.getFirstTableCellWithText('image').isPresent()).toBe(true);
expect(mirroring.editMirror(poolName, 'Disabled'));
expect(mirroring.getFirstTableCellWithText('disabled').isPresent()).toBe(true);
});

afterAll(() => {
pools.navigateTo(); // Deletes mirroring test pool
pools.delete(poolName).then(() => {
pools.navigateTo();
pools.exist(poolName, false);
});
});
});
});
45 changes: 45 additions & 0 deletions src/pybind/mgr/dashboard/frontend/e2e/block/mirroring.po.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,50 @@
import { $, browser, by, element } from 'protractor';
import { Helper } from '../helper.po';
import { PageHelper } from '../page-helper.po';

export class MirroringPageHelper extends PageHelper {
pages = { index: '/#/block/mirroring' };

// Goes to the mirroring page and edits a pool in the Pool table. Clicks on the
// pool and chooses a option (either pool, image, or disabled)
editMirror(name, option) {
this.navigateTo();
// Clicks the pool in the table
browser
.wait(Helper.EC.elementToBeClickable(this.getFirstTableCellWithText(name)), Helper.TIMEOUT)
.then(() => {
this.getFirstTableCellWithText(name).click();
});

// Clicks the Edit Mode button
const editModeButton = element(by.cssContainingText('button', 'Edit Mode'));
browser.wait(Helper.EC.elementToBeClickable(editModeButton), Helper.TIMEOUT).then(() => {
editModeButton.click();
});
// Clicks the drop down in the edit pop-up, then clicks the Update button
browser.wait(Helper.EC.visibilityOf($('.modal-content')), Helper.TIMEOUT).then(() => {
const mirrorDrop = element(by.id('mirrorMode'));
this.moveClick(mirrorDrop);
element(by.cssContainingText('select[name=mirrorMode] option', option)).click();
});
// Clicks update button and checks if the mode has been changed
element(by.cssContainingText('button', 'Update'))
.click()
.then(() => {
browser
.wait(
Helper.EC.stalenessOf(
element(by.cssContainingText('.modal-dialog', 'Edit pool mirror mode'))
),
Helper.TIMEOUT
)
.then(() => {
const val = option.toLowerCase(); // used since entries in table are lower case
browser.wait(
Helper.EC.visibilityOf(this.getFirstTableCellWithText(val)),
Helper.TIMEOUT
);
});
});
}
}
37 changes: 31 additions & 6 deletions src/pybind/mgr/dashboard/frontend/e2e/pools/pools.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class PoolPageHelper extends PageHelper {
}

@PageHelper.restrictTo(pages.create)
create(name: string, placement_groups: number): promise.Promise<any> {
create(name: string, placement_groups: number, ...apps: string[]): promise.Promise<any> {
const nameInput = $('input[name=name]');
nameInput.clear();
if (!this.isPowerOf2(placement_groups)) {
Expand All @@ -45,12 +45,33 @@ export class PoolPageHelper extends PageHelper {
$('input[name=pgNum]')
.sendKeys(protractor.Key.CONTROL, 'a', protractor.Key.NULL, placement_groups)
.then(() => {
this.setApplications(apps);
return element(by.css('cd-submit-button')).click();
});
});
});
}

private setApplications(apps: string[]) {
if (!apps || apps.length === 0) {
return;
}
element(by.css('.float-left.mr-2.select-menu-edit'))
.click()
.then(() => {
browser
.wait(
Helper.EC.visibilityOf(element(by.css('.popover-content.popover-body'))),
Helper.TIMEOUT
)
.then(() =>
apps.forEach((app) =>
element(by.cssContainingText('.select-menu-item-content', app)).click()
)
);
});
}

@PageHelper.restrictTo(pages.index)
delete(name: string): promise.Promise<any> {
return this.getTableCellByContent(name).then((tableCell: ElementFinder) => {
Expand All @@ -61,13 +82,17 @@ export class PoolPageHelper extends PageHelper {
return $('li.delete a') // click on "delete" menu item
.click()
.then(() => {
const getConfirmationCheckbox = () => $('#confirmation');
browser
.wait(() => EC.visibilityOf(getConfirmationCheckbox()), Helper.TIMEOUT)
.wait(Helper.EC.visibilityOf($('.custom-control-label')), Helper.TIMEOUT)
.then(() => {
this.moveClick(getConfirmationCheckbox()).then(() => {
return element(by.cssContainingText('button', 'Delete Pool')).click(); // Click Delete item
});
const getConfirmationCheckbox = () => $('.custom-control-label');
browser
.wait(Helper.EC.visibilityOf(getConfirmationCheckbox()), Helper.TIMEOUT)
.then(() => {
this.moveClick(getConfirmationCheckbox()).then(() => {
return element(by.cssContainingText('button', 'Delete Pool')).click(); // Click Delete item
});
});
});
});
});
Expand Down

0 comments on commit a9e6eb5

Please sign in to comment.