Note, the 'multiClick' selection mode does not render a checkbox in the header column, this is only available in 'checkbox' mode, but this mode only allows the selection of a row by clicking the checkbox, it's not possible to select a row by clicking somewhere within it. Because of that the 'multiClick' mode is preferred.
Signed-off-by: Volker Theile <vtheile@suse.com>
getTableRows() {
return $$('datatable-row-wrapper');
}
+
+ /**
+ * Uncheck all checked table rows.
+ */
+ async uncheckAllTableRows() {
+ await $$('.datatable-body-cell-label .datatable-checkbox input[type=checkbox]:checked').each(
+ (e: ElementFinder) => e.click()
+ );
+ }
}
describe('RGW buckets page', () => {
let buckets: BucketsPageHelper;
+ const bucket_name = '000test';
beforeAll(async () => {
buckets = new BucketsPageHelper();
await BucketsPageHelper.checkConsole();
});
- it('should open and show breadcrumb', async () => {
- await buckets.navigateTo();
- await expect($('.breadcrumb-item.active').getText()).toBe('Buckets');
- });
+ describe('breadcrumb tests', () => {
+ beforeEach(async () => {
+ await buckets.navigateTo();
+ });
- it('should create bucket', async () => {
- await buckets.navigateTo('create');
- await buckets.create(
- '000test',
- '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
- 'default-placement'
- );
- await expect(buckets.getFirstTableCellWithText('000test').isPresent()).toBe(true);
+ it('should open and show breadcrumb', async () => {
+ await expect($('.breadcrumb-item.active').getText()).toBe('Buckets');
+ });
});
- it('should edit bucket', async () => {
- await buckets.navigateTo();
- await buckets.edit('000test', 'dev');
- await expect(buckets.getTable().getText()).toMatch('dev');
- });
+ describe('create, edit & delete bucket tests', () => {
+ beforeEach(async () => {
+ await buckets.navigateTo();
+ await buckets.uncheckAllTableRows();
+ });
+
+ it('should create bucket', async () => {
+ await buckets.navigateTo('create');
+ await buckets.create(
+ bucket_name,
+ '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
+ 'default-placement'
+ );
+ await expect(buckets.getFirstTableCellWithText(bucket_name).isPresent()).toBe(true);
+ });
+
+ it('should edit bucket', async () => {
+ await buckets.edit(bucket_name, 'dev');
+ await expect(buckets.getTable().getText()).toMatch('dev');
+ });
- it('should delete bucket', async () => {
- await buckets.navigateTo();
- await buckets.delete('000test');
+ it('should delete bucket', async () => {
+ await buckets.delete(bucket_name);
+ });
});
describe('Invalid Input in Create and Edit tests', () => {
it('should test invalid inputs in create fields', async () => {
- await buckets.navigateTo('create');
await buckets.testInvalidCreate();
});
'0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
'default-placement'
);
-
await buckets.testInvalidEdit('000rq');
-
await buckets.navigateTo();
+ await buckets.uncheckAllTableRows();
await buckets.delete('000rq');
});
});
@PageHelper.restrictTo(pages.index)
async edit(name: string, new_owner: string) {
- await this.getFirstTableCellWithText(name).click(); // click on the bucket you want to edit in the table
+ await this.waitClickableAndClick(this.getFirstTableCellWithText(name)); // wait for table to load and click
await element(by.cssContainingText('button', 'Edit')).click(); // click button to move to edit page
await this.waitTextToBePresent(this.getBreadcrumb(), 'Edit');
await expect(element(by.css('input[name=placement-target]')).getAttribute('value')).toBe(
await expect(versioningValueCell.getText()).toEqual(this.versioningStateEnabled);
// Disable versioning:
- await this.getFirstTableCellWithText(name).click(); // click on the bucket you want to edit in the table
+ await this.uncheckAllTableRows();
+ await this.waitClickableAndClick(this.getFirstTableCellWithText(name)); // wait for table to load and click
await element(by.cssContainingText('button', 'Edit')).click(); // click button to move to edit page
await this.waitTextToBePresent(this.getBreadcrumb(), 'Edit');
await element(by.css('input[id=suspended]')).click();
async testInvalidEdit(name) {
await this.navigateTo();
- await this.waitClickableAndClick(
- this.getFirstTableCellWithText(name),
- 'Failed waiting for bucket to be present in table'
- ); // wait for table to load
+ await this.waitClickableAndClick(this.getFirstTableCellWithText(name)); // wait for table to load and click
await element(by.cssContainingText('button', 'Edit')).click(); // click button to move to edit page
await this.waitTextToBePresent(this.getBreadcrumb(), 'Edit');
await UsersPageHelper.checkConsole();
});
- describe('breadcrumb test', () => {
- beforeAll(async () => {
+ describe('breadcrumb tests', () => {
+ beforeEach(async () => {
await users.navigateTo();
});
});
});
- describe('create, edit & delete user test', () => {
- beforeAll(async () => {
+ describe('create, edit & delete user tests', () => {
+ beforeEach(async () => {
await users.navigateTo();
+ await users.uncheckAllTableRows();
});
it('should create user', async () => {
+ await users.navigateTo('create');
await users.create(user_name, 'Some Name', 'original@website.com', '1200');
await expect(users.getFirstTableCellWithText(user_name).isPresent()).toBe(true);
});
it('should edit users full name, email and max buckets', async () => {
await users.edit(user_name, 'Another Identity', 'changed@othersite.com', '1969');
- // checks for succsessful editing are done within edit function
});
it('should delete user', async () => {
});
});
- describe('Invalid input test', () => {
- beforeAll(async () => {
- await users.navigateTo();
- });
-
+ describe('Invalid input tests', () => {
it('should put invalid input into user creation form and check fields are marked invalid', async () => {
await users.invalidCreate();
});
import { protractor } from 'protractor/built/ptor';
import { PageHelper } from '../page-helper.po';
+const pages = {
+ index: '/#/rgw/user',
+ create: '/#/rgw/user/create'
+};
+
export class UsersPageHelper extends PageHelper {
- pages = {
- index: '/#/rgw/user',
- create: '/#/rgw/user/create'
- };
+ pages = pages;
+ @PageHelper.restrictTo(pages.create)
async create(username, fullname, email, maxbuckets) {
- await this.navigateTo('create');
-
// Enter in username
await element(by.id('uid')).sendKeys(username);
await this.waitPresence(this.getFirstTableCellWithText(username));
}
+ @PageHelper.restrictTo(pages.index)
async edit(name, new_fullname, new_email, new_maxbuckets) {
- await this.navigateTo();
-
await this.waitClickableAndClick(this.getFirstTableCellWithText(name)); // wait for table to load and click
await element(by.cssContainingText('button', 'Edit')).click(); // click button to move to edit page
async invalidCreate() {
const uname = '000invalid_create_user';
// creating this user in order to check that you can't give two users the same name
+ await this.navigateTo('create');
await this.create(uname, 'xxx', 'xxx@xxx', '1');
await this.navigateTo('create');
async invalidEdit() {
const uname = '000invalid_edit_user';
// creating this user to edit for the test
+ await this.navigateTo('create');
await this.create(uname, 'xxx', 'xxx@xxx', '1');
await this.navigateTo();
<cd-table [data]="osds"
(fetchData)="getOsdList()"
[columns]="columns"
- selectionType="multi"
+ selectionType="multiClick"
(updateSelection)="updateSelection($event)"
[updateSelectionOnRefresh]="'never'">
it('should have columns that are sortable', () => {
fixture.detectChanges();
- expect(component.columns.every((column) => Boolean(column.prop))).toBeTruthy();
+ expect(
+ component.columns
+ .filter((column) => !column.checkboxable)
+ .every((column) => Boolean(column.prop))
+ ).toBeTruthy();
});
describe('getOsdList', () => {
[data]="buckets"
[columns]="columns"
columnMode="flex"
- selectionType="multi"
+ selectionType="multiClick"
(updateSelection)="updateSelection($event)"
identifier="bid"
(fetchData)="getBucketList($event)">
expect(tableActions).toEqual({
'create,update,delete': {
actions: ['Create', 'Edit', 'Delete'],
- primary: { multiple: 'Create', executing: 'Edit', single: 'Edit', no: 'Create' }
+ primary: { multiple: 'Delete', executing: 'Edit', single: 'Edit', no: 'Create' }
},
'create,update': {
actions: ['Create', 'Edit'],
},
'create,delete': {
actions: ['Create', 'Delete'],
- primary: { multiple: 'Create', executing: 'Delete', single: 'Delete', no: 'Create' }
+ primary: { multiple: 'Delete', executing: 'Create', single: 'Create', no: 'Create' }
},
create: {
actions: ['Create'],
},
'update,delete': {
actions: ['Edit', 'Delete'],
- primary: { multiple: 'Edit', executing: 'Edit', single: 'Edit', no: 'Edit' }
+ primary: { multiple: 'Delete', executing: 'Edit', single: 'Edit', no: 'Edit' }
},
update: {
actions: ['Edit'],
permission: 'create',
icon: Icons.add,
routerLink: () => this.urlBuilder.getCreate(),
- name: this.actionLabels.CREATE
+ name: this.actionLabels.CREATE,
+ canBePrimary: (selection: CdTableSelection) => !selection.hasSelection
};
const editAction: CdTableAction = {
permission: 'update',
permission: 'delete',
icon: Icons.destroy,
click: () => this.deleteAction(),
- name: this.actionLabels.DELETE
+ disable: () => !this.selection.hasSelection,
+ name: this.actionLabels.DELETE,
+ canBePrimary: (selection: CdTableSelection) => selection.hasMultiSelection
};
this.tableActions = [addAction, editAction, deleteAction];
}
[data]="users"
[columns]="columns"
columnMode="flex"
- selectionType="multi"
+ selectionType="multiClick"
(updateSelection)="updateSelection($event)"
identifier="uid"
(fetchData)="getUserList($event)">
expect(tableActions).toEqual({
'create,update,delete': {
actions: ['Create', 'Edit', 'Delete'],
- primary: { multiple: 'Create', executing: 'Edit', single: 'Edit', no: 'Create' }
+ primary: { multiple: 'Delete', executing: 'Edit', single: 'Edit', no: 'Create' }
},
'create,update': {
actions: ['Create', 'Edit'],
},
'create,delete': {
actions: ['Create', 'Delete'],
- primary: { multiple: 'Create', executing: 'Delete', single: 'Delete', no: 'Create' }
+ primary: { multiple: 'Delete', executing: 'Create', single: 'Create', no: 'Create' }
},
create: {
actions: ['Create'],
},
'update,delete': {
actions: ['Edit', 'Delete'],
- primary: { multiple: 'Edit', executing: 'Edit', single: 'Edit', no: 'Edit' }
+ primary: { multiple: 'Delete', executing: 'Edit', single: 'Edit', no: 'Edit' }
},
update: {
actions: ['Edit'],
permission: 'create',
icon: Icons.add,
routerLink: () => this.urlBuilder.getCreate(),
- name: this.actionLabels.CREATE
+ name: this.actionLabels.CREATE,
+ canBePrimary: (selection: CdTableSelection) => !selection.hasSelection
};
const editAction: CdTableAction = {
permission: 'update',
permission: 'delete',
icon: Icons.destroy,
click: () => this.deleteAction(),
- name: this.actionLabels.DELETE
+ disable: () => !this.selection.hasSelection,
+ name: this.actionLabels.DELETE,
+ canBePrimary: (selection: CdTableSelection) => selection.hasMultiSelection
};
this.tableActions = [addAction, editAction, deleteAction];
}
let-offset="offset"
let-isVisible="isVisible">
<div class="page-count">
- <span *ngIf="selectionType == 'multi'">
- <cd-helper i18n>Press and hold control button to select multiple rows to execute a common action on.</cd-helper>
- </span>
<span *ngIf="selectionType">
{{ selectedCount }} <ng-container i18n="X selected">selected</ng-container> /
</span>
}
}
}
+
+ .cd-datatable-checkbox {
+ text-align: center;
+ }
}
@keyframes progress-loading {
c.resizeable = false;
}
});
+
+ this.initCheckboxColumn();
this.filterHiddenColumns();
// Load the data table content every N ms or at least once.
// Force showing the loading indicator if there are subscribers to the fetchData
}));
}
+ /**
+ * Add a column containing a checkbox if selectionType is 'multiClick'.
+ */
+ initCheckboxColumn() {
+ if (this.selectionType === 'multiClick') {
+ this.columns.unshift({
+ prop: undefined,
+ resizeable: false,
+ sortable: false,
+ draggable: false,
+ checkboxable: true,
+ canAutoResize: false,
+ cellClass: 'cd-datatable-checkbox',
+ width: 30
+ });
+ }
+ }
+
filterHiddenColumns() {
this.tableColumns = this.columns.filter((c) => !c.isHidden);
}