Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve security cloud test failures #68935

Merged
merged 11 commits into from
Jun 16, 2020
173 changes: 72 additions & 101 deletions x-pack/test/functional/page_objects/security_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export function SecurityPageProvider({ getService, getPageObjects }: FtrProvider
const testSubjects = getService('testSubjects');
const esArchiver = getService('esArchiver');
const userMenu = getService('userMenu');
const comboBox = getService('comboBox');
const PageObjects = getPageObjects(['common', 'header', 'settings', 'home', 'error']);

interface LoginOptions {
Expand Down Expand Up @@ -273,11 +274,7 @@ export function SecurityPageProvider({ getService, getPageObjects }: FtrProvider

async addIndexToRole(index: string) {
log.debug(`Adding index ${index} to role`);
const indexInput = await retry.try(() =>
find.byCssSelector('[data-test-subj="indicesInput0"] input')
);
await indexInput.type(index);
await indexInput.type('\n');
await comboBox.setCustom('indicesInput0', index);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attempts to address test flakyness by using the comboBox service to set input values, instead of whatever homegrown solution we had here. Failure screenshots indicated that the dropdown list was not dismissing properly in all cases, which caused clicks to other elements on the page to not be registered properly.

}

async addPrivilegeToRole(privilege: string) {
Expand Down Expand Up @@ -400,104 +397,78 @@ export function SecurityPageProvider({ getService, getPageObjects }: FtrProvider
}
}

addRole(roleName: string, roleObj: Role) {
async addRole(roleName: string, roleObj: Role) {
const self = this;

return (
this.clickNewRole()
.then(function () {
// We have to use non-test-subject selectors because this markup is generated by ui-select.
log.debug('roleObj.indices[0].names = ' + roleObj.elasticsearch.indices[0].names);
return testSubjects.append('roleFormNameInput', roleName);
})
.then(function () {
return find.setValue(
'[data-test-subj="indicesInput0"] input',
roleObj.elasticsearch.indices[0].names + '\n'
);
})
.then(function () {
return testSubjects.click('restrictDocumentsQuery0');
})
.then(function () {
if (roleObj.elasticsearch.indices[0].query) {
return testSubjects.setValue('queryInput0', roleObj.elasticsearch.indices[0].query);
}
})

// KibanaPrivilege
.then(async () => {
const globalPrivileges = (roleObj.kibana as any).global;
if (globalPrivileges) {
for (const privilegeName of globalPrivileges) {
const button = await testSubjects.find('addSpacePrivilegeButton');
await button.click();

const spaceSelector = await testSubjects.find('spaceSelectorComboBox');
await spaceSelector.click();

const globalSpaceOption = await find.byCssSelector(`#spaceOption_\\*`);
await globalSpaceOption.click();

const basePrivilegeSelector = await testSubjects.find('basePrivilegeComboBox');
await basePrivilegeSelector.click();

const privilegeOption = await find.byCssSelector(`#basePrivilege_${privilegeName}`);
await privilegeOption.click();

const createPrivilegeButton = await testSubjects.find('createSpacePrivilegeButton');
await createPrivilegeButton.click();
}
}
})

.then(function () {
function addPrivilege(privileges: string[]) {
return privileges.reduce(function (promise: Promise<any>, privilegeName: string) {
// We have to use non-test-subject selectors because this markup is generated by ui-select.
return promise
.then(() => self.addPrivilegeToRole(privilegeName))
.then(() => PageObjects.common.sleep(250));
}, Promise.resolve());
}
return addPrivilege(roleObj.elasticsearch.indices[0].privileges);
})
// clicking the Granted fields and removing the asterix
.then(async function () {
function addGrantedField(field: string[]) {
return field.reduce(function (promise: Promise<any>, fieldName: string) {
return promise
.then(function () {
return find.setValue('[data-test-subj="fieldInput0"] input', fieldName + '\n');
})
.then(function () {
return PageObjects.common.sleep(1000);
});
}, Promise.resolve());
}

if (roleObj.elasticsearch.indices[0].field_security) {
// Toggle FLS switch
await testSubjects.click('restrictFieldsQuery0');

// have to remove the '*'
return find
.clickByCssSelector(
'div[data-test-subj="fieldInput0"] [title="Remove * from selection in this group"] svg.euiIcon'
)
.then(function () {
return addGrantedField(roleObj.elasticsearch.indices[0].field_security!.grant!);
});
}
}) // clicking save button
.then(async () => {
log.debug('click save button');
await testSubjects.click('roleFormSaveButton');
})
.then(function () {
return PageObjects.common.sleep(5000);
})
);
await this.clickNewRole();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is largely similar to what we used to have, but I removed the promise chain in favor of a series of async functions. I find it easier to read and reason about. This also uses the comboBox service below, and removes the fixed wait of 5000ms


// We have to use non-test-subject selectors because this markup is generated by ui-select.
log.debug('roleObj.indices[0].names = ' + roleObj.elasticsearch.indices[0].names);
await testSubjects.append('roleFormNameInput', roleName);

for (const indexName of roleObj.elasticsearch.indices[0].names) {
await comboBox.setCustom('indicesInput0', indexName);
}

if (roleObj.elasticsearch.indices[0].query) {
await testSubjects.click('restrictDocumentsQuery0');
await testSubjects.setValue('queryInput0', roleObj.elasticsearch.indices[0].query);
}

const globalPrivileges = (roleObj.kibana as any).global;
if (globalPrivileges) {
for (const privilegeName of globalPrivileges) {
await testSubjects.click('addSpacePrivilegeButton');

await testSubjects.click('spaceSelectorComboBox');

const globalSpaceOption = await find.byCssSelector(`#spaceOption_\\*`);
await globalSpaceOption.click();

await testSubjects.click('basePrivilegeComboBox');

const privilegeOption = await find.byCssSelector(`#basePrivilege_${privilegeName}`);
await privilegeOption.click();

await testSubjects.click('createSpacePrivilegeButton');
}
}

function addPrivilege(privileges: string[]) {
return privileges.reduce(function (promise: Promise<any>, privilegeName: string) {
return promise
.then(() => self.addPrivilegeToRole(privilegeName))
.then(() => PageObjects.common.sleep(250));
}, Promise.resolve());
}

await addPrivilege(roleObj.elasticsearch.indices[0].privileges);

async function addGrantedField(fields: string[]) {
for (const entry of fields) {
await comboBox.setCustom('fieldInput0', entry);
}
}

// clicking the Granted fields and removing the asterix
if (roleObj.elasticsearch.indices[0].field_security) {
// Toggle FLS switch
await testSubjects.click('restrictFieldsQuery0');

// have to remove the '*'
await find.clickByCssSelector(
'div[data-test-subj="fieldInput0"] [title="Remove * from selection in this group"] svg.euiIcon'
);

await addGrantedField(roleObj.elasticsearch.indices[0].field_security!.grant!);
}

log.debug('click save button');
await testSubjects.click('roleFormSaveButton');

// Signifies that the role management page redirected back to the role grid page,
// and successfully refreshed the grid
await testSubjects.existOrFail('roleRow');
}

async selectRole(role: string) {
Expand Down