[8.11] Adding user profiles tests for regular and serverless (#171554) (#171758)

# Backport

This will backport the following commits from `main` to `8.11`:
- [Adding user profiles tests for regular and serverless
(#171554)](https://github.com/elastic/kibana/pull/171554)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT
[{"author":{"name":"Kurt","email":"kc13greiner@users.noreply.github.com"},"sourceCommit":{"committedDate":"2023-11-22T15:43:03Z","message":"Adding
user profiles tests for regular and serverless (#171554)\n\n##
Summary\r\n\r\nAdding functional tests for User Profiles and Dark
Mode\r\n\r\n\r\n## Flaky Test Runner for new
tests\r\n\r\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4034\r\n🟢","sha":"66019dfe057734f4f45035e7df101822e1bcdcc5","branchLabelMapping":{"^v8.12.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport:prev-minor","v8.12.0"],"number":171554,"url":"https://github.com/elastic/kibana/pull/171554","mergeCommit":{"message":"Adding
user profiles tests for regular and serverless (#171554)\n\n##
Summary\r\n\r\nAdding functional tests for User Profiles and Dark
Mode\r\n\r\n\r\n## Flaky Test Runner for new
tests\r\n\r\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4034\r\n🟢","sha":"66019dfe057734f4f45035e7df101822e1bcdcc5"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v8.12.0","labelRegex":"^v8.12.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/171554","number":171554,"mergeCommit":{"message":"Adding
user profiles tests for regular and serverless (#171554)\n\n##
Summary\r\n\r\nAdding functional tests for User Profiles and Dark
Mode\r\n\r\n\r\n## Flaky Test Runner for new
tests\r\n\r\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4034\r\n🟢","sha":"66019dfe057734f4f45035e7df101822e1bcdcc5"}}]}]
BACKPORT-->

Co-authored-by: Kurt <kc13greiner@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2023-11-22 12:33:52 -05:00 committed by GitHub
parent 3aadaa37e4
commit 416cc7f8c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 343 additions and 3 deletions

View file

@ -345,6 +345,7 @@ enabled:
- x-pack/test/functional/apps/transform/feature_controls/config.ts
- x-pack/test/functional/apps/upgrade_assistant/config.ts
- x-pack/test/functional/apps/uptime/config.ts
- x-pack/test/functional/apps/user_profiles/config.ts
- x-pack/test/functional/apps/visualize/config.ts
- x-pack/test/functional/apps/watcher/config.ts
- x-pack/test/functional/config_security_basic.ts

View file

@ -138,7 +138,7 @@ const UserDetailsEditor: FunctionComponent<UserDetailsEditorProps> = ({ user })
labelAppend={<OptionalText />}
fullWidth
>
<FormField name="user.full_name" fullWidth />
<FormField name="user.full_name" data-test-subj={'userProfileFullName'} fullWidth />
</FormRow>
<FormRow
@ -153,7 +153,7 @@ const UserDetailsEditor: FunctionComponent<UserDetailsEditorProps> = ({ user })
labelAppend={<OptionalText />}
fullWidth
>
<FormField type="email" name="user.email" fullWidth />
<FormField type="email" name="user.email" data-test-subj={'userProfileEmail'} fullWidth />
</FormRow>
</EuiDescribedFormGroup>
);
@ -189,6 +189,7 @@ const UserSettingsEditor: FunctionComponent<UserSettingsEditorProps> = ({
<EuiKeyPadMenuItem
name={id}
label={label}
data-test-subj={`themeKeyPadItem${label}`}
checkable="single"
isSelected={idSelected === id}
isDisabled={isThemeOverridden}
@ -810,7 +811,11 @@ export const UserProfile: FunctionComponent<UserProfileProps> = ({ user, data })
</Form>
</KibanaPageTemplate.Section>
{formChanges.count > 0 ? (
<KibanaPageTemplate.BottomBar paddingSize="m" position="fixed">
<KibanaPageTemplate.BottomBar
paddingSize="m"
position="fixed"
data-test-subj={'userProfileBottomBar'}
>
<SaveChangesBottomBar />
</KibanaPageTemplate.BottomBar>
) : null}
@ -974,6 +979,7 @@ export const SaveChangesBottomBar: FunctionComponent = () => {
<EuiFlexItem grow={false}>
<EuiButton
onClick={formik.submitForm}
data-test-subj="saveProfileChangesButton"
isLoading={formik.isSubmitting}
isDisabled={formik.submitCount > 0 && !formik.isValid}
color="success"

View file

@ -0,0 +1,17 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrConfigProviderContext } from '@kbn/test';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const functionalConfig = await readConfigFile(require.resolve('../../config.base.js'));
return {
...functionalConfig.getAll(),
testFiles: [require.resolve('.')],
};
}

View file

@ -0,0 +1,14 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrProviderContext } from '../../ftr_provider_context';
export default ({ loadTestFile }: FtrProviderContext) => {
describe('User Profiles page', function () {
loadTestFile(require.resolve('./user_profiles'));
});
};

View file

@ -0,0 +1,160 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context';
export default ({ getPageObjects }: FtrProviderContext) => {
const pageObjects = getPageObjects(['common', 'userProfiles', 'settings']);
describe('User Profile Page', async () => {
before(async () => {});
describe('Details', async () => {
before(async () => {
await pageObjects.common.navigateToApp('security_account');
});
it('should set the full name', async () => {
await pageObjects.userProfiles.setFullNameInputField('Test User 2');
await pageObjects.userProfiles.saveUserProfileChanges();
let toast = await pageObjects.common.closeToast();
expect(toast).to.be('Profile updated');
await pageObjects.userProfiles.setFullNameInputField('test user');
await pageObjects.userProfiles.saveUserProfileChanges();
toast = await pageObjects.common.closeToast();
expect(toast).to.be('Profile updated');
});
it('should set the email', async () => {
await pageObjects.userProfiles.setEmailInputField('test@test.com');
await pageObjects.userProfiles.saveUserProfileChanges();
let toast = await pageObjects.common.closeToast();
expect(toast).to.be('Profile updated');
await pageObjects.userProfiles.setEmailInputField('', true);
await pageObjects.userProfiles.saveUserProfileChanges();
toast = await pageObjects.common.closeToast();
expect(toast).to.be('Profile updated');
});
});
describe('Change Password', async () => {
before(async () => {
await pageObjects.common.navigateToApp('security_account');
});
it('should set the current password and enter a new password, then submit', async () => {
const changePasswordButton = await pageObjects.userProfiles.getChangePasswordButton();
await changePasswordButton.click();
await pageObjects.userProfiles.setCurrentPasswordField('changeme');
await pageObjects.userProfiles.setNewPasswordField('changeme2');
await pageObjects.userProfiles.setConfirmPasswordField('changeme2');
const submitButton = await pageObjects.userProfiles.getChangePasswordFormSubmitButton();
await submitButton.click();
const initialToast = await pageObjects.common.closeToast();
expect(initialToast).to.be('Password successfully changed');
await changePasswordButton.click();
await pageObjects.userProfiles.setCurrentPasswordField('changeme2');
await pageObjects.userProfiles.setNewPasswordField('changeme');
await pageObjects.userProfiles.setConfirmPasswordField('changeme');
await submitButton.click();
const resetToast = await pageObjects.common.closeToast();
expect(resetToast).to.be('Password successfully changed');
});
});
describe('Theme', async () => {
it('should change theme based on the User Profile Theme control with default Adv. Settings value (light)', async () => {
await pageObjects.common.navigateToApp('security_account');
const themeKeyPadMenu = await pageObjects.userProfiles.getThemeKeypadMenu();
expect(themeKeyPadMenu).not.to.be(null);
await pageObjects.userProfiles.changeUserProfileTheme('Dark');
const darkModeTag = await pageObjects.userProfiles.getThemeTag();
expect(darkModeTag).to.be('v8dark');
await pageObjects.userProfiles.changeUserProfileTheme('Light');
const lightModeTag = await pageObjects.userProfiles.getThemeTag();
expect(lightModeTag).to.be('v8light');
await pageObjects.userProfiles.changeUserProfileTheme('Space default');
const spaceDefaultModeTag = await pageObjects.userProfiles.getThemeTag();
expect(spaceDefaultModeTag).to.be('v8light');
});
it('should change theme based on the User Profile Theme control with default Adv. Settings value set to dark', async () => {
await pageObjects.common.navigateToUrl('management', 'kibana/settings', {
basePath: '',
ensureCurrentUrl: false,
shouldLoginIfPrompted: false,
shouldUseHashForSubUrl: false,
});
let advancedSetting = await pageObjects.settings.getAdvancedSettingCheckbox(
'theme:darkMode'
);
expect(advancedSetting).to.be(null);
await pageObjects.settings.toggleAdvancedSettingCheckbox('theme:darkMode', true);
advancedSetting = await pageObjects.settings.getAdvancedSettingCheckbox('theme:darkMode');
expect(advancedSetting).to.be('true');
await pageObjects.common.navigateToApp('security_account');
let spaceDefaultModeTag = await pageObjects.userProfiles.getThemeTag();
expect(spaceDefaultModeTag).to.be('v8dark');
await pageObjects.userProfiles.changeUserProfileTheme('Light');
const lightModeTag = await pageObjects.userProfiles.getThemeTag();
expect(lightModeTag).to.be('v8light');
await pageObjects.userProfiles.changeUserProfileTheme('Dark');
const darkModeTag = await pageObjects.userProfiles.getThemeTag();
expect(darkModeTag).to.be('v8dark');
await pageObjects.userProfiles.changeUserProfileTheme('Space default');
spaceDefaultModeTag = await pageObjects.userProfiles.getThemeTag();
expect(spaceDefaultModeTag).to.be('v8dark');
await pageObjects.common.navigateToUrl('management', 'kibana/settings', {
basePath: '',
ensureCurrentUrl: false,
shouldLoginIfPrompted: false,
shouldUseHashForSubUrl: false,
});
await pageObjects.settings.toggleAdvancedSettingCheckbox('theme:darkMode', false);
advancedSetting = await pageObjects.settings.getAdvancedSettingCheckbox('theme:darkMode');
expect(advancedSetting).to.be(null);
});
});
});
};

View file

@ -48,6 +48,7 @@ import { StatusPageObject } from './status_page';
import { TagManagementPageObject } from './tag_management_page';
import { UpgradeAssistantPageObject } from './upgrade_assistant_page';
import { UptimePageObject } from './uptime_page';
import { UserProfilePageProvider } from './user_profile_page';
import { WatcherPageObject } from './watcher_page';
// just like services, PageObjects are defined as a map of
@ -95,5 +96,6 @@ export const pageObjects = {
tagManagement: TagManagementPageObject,
upgradeAssistant: UpgradeAssistantPageObject,
uptime: UptimePageObject,
userProfiles: UserProfilePageProvider,
watcher: WatcherPageObject,
};

View file

@ -0,0 +1,99 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';
export function UserProfilePageProvider({ getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const find = getService('find');
const browser = getService('browser');
const retry = getService('retry');
const getThemeTag = async (): Promise<void> => {
return await browser.execute('return __kbnThemeTag__');
};
const getSaveProfileChangesButton = async () => {
return await testSubjects.find('saveProfileChangesButton');
};
const getReloadWindowButton = async () => {
return await testSubjects.find('windowReloadButton');
};
const getThemeKeypadButton = async (option: string) => {
option = option[0].toUpperCase() + option.substring(1).toLowerCase();
return await testSubjects.find(`themeKeyPadItem${option}`);
};
const saveUserProfileChanges = async (): Promise<void> => {
let saveProfileChangesButton;
await retry.try(async () => {
saveProfileChangesButton = await getSaveProfileChangesButton();
expect(saveProfileChangesButton).not.to.be(null);
await saveProfileChangesButton.click();
});
};
const changeUserProfileTheme = async (theme: string): Promise<void> => {
const themeModeButton = await getThemeKeypadButton(theme);
expect(themeModeButton).not.to.be(null);
await themeModeButton.click();
await saveUserProfileChanges();
let reloadWindowButton;
await retry.try(async () => {
reloadWindowButton = await getReloadWindowButton();
expect(reloadWindowButton).not.to.be(null);
await reloadWindowButton.click();
});
};
return {
async getThemeKeypadMenu() {
return await find.byCssSelector('.euiKeyPadMenu');
},
async setFullNameInputField(newFullName: string) {
return await testSubjects.setValue('userProfileFullName', newFullName);
},
async setEmailInputField(newEmailAddress: string, clearWithKeyboard: boolean = false) {
return await testSubjects.setValue('userProfileEmail', newEmailAddress, {
clearWithKeyboard,
});
},
async getChangePasswordButton() {
return await testSubjects.find('openChangePasswordForm');
},
async setCurrentPasswordField(currentPassword: string) {
return await testSubjects.setValue(
'editUserChangePasswordCurrentPasswordInput',
currentPassword
);
},
async setNewPasswordField(newPassword: string) {
return await testSubjects.setValue('editUserChangePasswordNewPasswordInput', newPassword);
},
async setConfirmPasswordField(newPassword: string) {
return await testSubjects.setValue('editUserChangePasswordConfirmPasswordInput', newPassword);
},
async getChangePasswordFormSubmitButton() {
return await testSubjects.find('changePasswordFormSubmitButton');
},
getThemeTag,
saveUserProfileChanges,
changeUserProfileTheme,
};
}

View file

@ -11,5 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
describe('Serverless Common UI - Platform Security', function () {
loadTestFile(require.resolve('./api_keys'));
loadTestFile(require.resolve('./navigation/avatar_menu'));
loadTestFile(require.resolve('./user_profiles/user_profiles'));
});
}

View file

@ -0,0 +1,40 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getPageObjects }: FtrProviderContext) {
const pageObjects = getPageObjects(['svlCommonPage', 'common', 'userProfiles']);
describe('User Profile Page', async () => {
before(async () => {
await pageObjects.svlCommonPage.login();
});
describe('Theme', async () => {
it('should change theme based on the User Profile Theme control', async () => {
await pageObjects.common.navigateToApp('security_account');
const themeKeyPadMenu = await pageObjects.userProfiles.getThemeKeypadMenu();
expect(themeKeyPadMenu).not.to.be(null);
await pageObjects.userProfiles.changeUserProfileTheme('Dark');
const darkModeTag = await pageObjects.userProfiles.getThemeTag();
expect(darkModeTag).to.be('v8dark');
await pageObjects.userProfiles.changeUserProfileTheme('Light');
const lightModeTag = await pageObjects.userProfiles.getThemeTag();
expect(lightModeTag).to.be('v8light');
await pageObjects.userProfiles.changeUserProfileTheme('Space default');
const spaceDefaultModeTag = await pageObjects.userProfiles.getThemeTag();
expect(spaceDefaultModeTag).to.be('v8light');
});
});
});
}