Skip to content

Commit

Permalink
[8.x] [Spaces Management] Fix issue with enabled features selection w…
Browse files Browse the repository at this point in the history
…hen space solution is unselected (#194352) (#194486)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Spaces Management] Fix issue with enabled features selection when
space solution is unselected
(#194352)](#194352)

<!--- Backport version: 9.4.3 -->

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

<!--BACKPORT [{"author":{"name":"Tim
Sullivan","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-09-30T20:22:36Z","message":"[Spaces
Management] Fix issue with enabled features selection when space
solution is unselected (#194352)\n\n## Summary\r\n\r\nResolves
https://github.com/elastic/kibana/issues/192812\r\n\r\nThe feature PR
for the new UX in Spaces Management introduced a new\r\nediting screen
for Spaces. Inadvertently, it introduced a bug where the\r\nuser's
selection of visible features is ignored unless the user
has\r\nexplicitly selected a solution view. This PR fixes that issue as
well as\r\nadds tests to prevent any future regressions.\r\n\r\nAlso,
this PR fixes an issue where the space initials could be left\r\nblank,
which was another regression.\r\n\r\n### Checklist\r\n\r\nDelete any
items that are not applicable to this PR.\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n\r\n---------\r\n\r\nCo-authored-by:
Elena Shostak
<[email protected]>","sha":"0d421e537c7a302d88dd75cd54cae2f2b8bcfb19","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Security","release_note:skip","v9.0.0","v8.16.0","backport:version"],"title":"[Spaces
Management] Fix issue with enabled features selection when space
solution is
unselected","number":194352,"url":"https://github.com/elastic/kibana/pull/194352","mergeCommit":{"message":"[Spaces
Management] Fix issue with enabled features selection when space
solution is unselected (#194352)\n\n## Summary\r\n\r\nResolves
https://github.com/elastic/kibana/issues/192812\r\n\r\nThe feature PR
for the new UX in Spaces Management introduced a new\r\nediting screen
for Spaces. Inadvertently, it introduced a bug where the\r\nuser's
selection of visible features is ignored unless the user
has\r\nexplicitly selected a solution view. This PR fixes that issue as
well as\r\nadds tests to prevent any future regressions.\r\n\r\nAlso,
this PR fixes an issue where the space initials could be left\r\nblank,
which was another regression.\r\n\r\n### Checklist\r\n\r\nDelete any
items that are not applicable to this PR.\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n\r\n---------\r\n\r\nCo-authored-by:
Elena Shostak
<[email protected]>","sha":"0d421e537c7a302d88dd75cd54cae2f2b8bcfb19"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/194352","number":194352,"mergeCommit":{"message":"[Spaces
Management] Fix issue with enabled features selection when space
solution is unselected (#194352)\n\n## Summary\r\n\r\nResolves
https://github.com/elastic/kibana/issues/192812\r\n\r\nThe feature PR
for the new UX in Spaces Management introduced a new\r\nediting screen
for Spaces. Inadvertently, it introduced a bug where the\r\nuser's
selection of visible features is ignored unless the user
has\r\nexplicitly selected a solution view. This PR fixes that issue as
well as\r\nadds tests to prevent any future regressions.\r\n\r\nAlso,
this PR fixes an issue where the space initials could be left\r\nblank,
which was another regression.\r\n\r\n### Checklist\r\n\r\nDelete any
items that are not applicable to this PR.\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n\r\n---------\r\n\r\nCo-authored-by:
Elena Shostak
<[email protected]>","sha":"0d421e537c7a302d88dd75cd54cae2f2b8bcfb19"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Tim Sullivan <[email protected]>
  • Loading branch information
kibanamachine and tsullivan authored Sep 30, 2024
1 parent 8618d89 commit 84d4a5a
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,10 @@ export class FeatureTable extends Component<Props, {}> {
const accordion = (
<EuiFlexGroup key={category.id} alignItems="baseline" responsive={false} gutterSize="s">
<EuiFlexItem grow={false}>
<EuiCheckbox {...checkboxProps} />
<EuiCheckbox
{...checkboxProps}
data-test-subj={`featureCategoryCheckbox_${category.id}`}
/>
</EuiFlexItem>
<EuiFlexItem grow={1}>
<EuiAccordion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,76 @@ describe('EditSpaceSettings', () => {
expect(navigateSpy).toHaveBeenCalledTimes(1);
});

it('submits the disabled features list when the solution view is undefined', async () => {
const features = [
new KibanaFeature({
id: 'feature-1',
name: 'feature 1',
app: [],
category: DEFAULT_APP_CATEGORIES.kibana,
privileges: null,
}),
];

const spaceToUpdate = {
id: 'existing-space',
name: 'Existing Space',
description: 'hey an existing space',
color: '#aabbcc',
initials: 'AB',
disabledFeatures: [],
solution: undefined,
};

render(
<TestComponent>
<EditSpaceSettingsTab
space={spaceToUpdate}
history={history}
features={features}
allowFeatureVisibility={true}
allowSolutionVisibility={true}
reloadWindow={reloadWindow}
/>
</TestComponent>
);

// update the space visible features
const feature1Checkbox = screen.getByTestId('featureCheckbox_feature-1');
expect(feature1Checkbox).toBeChecked();
await act(async () => {
await userEvent.click(feature1Checkbox);
});
await waitFor(() => {
expect(feature1Checkbox).not.toBeChecked();
});

expect(screen.getByTestId('space-edit-page-user-impact-warning')).toBeInTheDocument();
expect(screen.queryByTestId('confirmModalTitleText')).not.toBeInTheDocument();

const updateButton = screen.getByTestId('save-space-button');
await act(async () => {
await userEvent.click(updateButton);
});

expect(screen.getByTestId('confirmModalTitleText')).toBeInTheDocument();

const confirmButton = screen.getByTestId('confirmModalConfirmButton');
await act(async () => {
await userEvent.click(confirmButton);
});

await waitFor(() => {
expect(updateSpaceSpy).toHaveBeenCalledWith({
...spaceToUpdate,
imageUrl: '',
disabledFeatures: ['feature-1'],
});
});

expect(navigateSpy).toHaveBeenCalledTimes(1);
});

it('empties the disabled features list when the solution view non-classic', async () => {
const features = [
new KibanaFeature({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { EuiCallOut, EuiSpacer } from '@elastic/eui';
import React, { useCallback, useState } from 'react';
import React, { useCallback, useMemo, useState } from 'react';

import type { ScopedHistory } from '@kbn/core-application-browser';
import type { KibanaFeature } from '@kbn/features-plugin/common';
Expand All @@ -18,6 +18,7 @@ import { EditSpaceTabFooter } from './footer';
import { useEditSpaceServices } from './provider';
import type { Space } from '../../../common';
import { SOLUTION_VIEW_CLASSIC } from '../../../common/constants';
import { getSpaceInitials } from '../../space_avatar';
import { ConfirmDeleteModal } from '../components';
import { ConfirmAlterActiveSpaceModal } from '../components/confirm_alter_active_space_modal';
import { CustomizeSpace } from '../components/customize_space';
Expand All @@ -42,6 +43,11 @@ export const EditSpaceSettingsTab: React.FC<Props> = ({ space, features, history
imageUrl: imageAvatarSelected ? space.imageUrl : '',
});

// space initials are blank by default, they must be calculated
const getSpaceFromFormValues = (newFormValues: CustomizeSpaceFormValues) => {
return { ...newFormValues, initials: getSpaceInitials(newFormValues) };
};

const [isDirty, setIsDirty] = useState(false); // track if unsaved changes have been made
const [isLoading, setIsLoading] = useState(false); // track if user has just clicked the Update button
const [showUserImpactWarning, setShowUserImpactWarning] = useState(false);
Expand Down Expand Up @@ -137,7 +143,7 @@ export const EditSpaceSettingsTab: React.FC<Props> = ({ space, features, history
setIsLoading(true);

let disabledFeatures: string[] | undefined;
if (spaceClone.solution === SOLUTION_VIEW_CLASSIC) {
if (!spaceClone.solution || spaceClone.solution === SOLUTION_VIEW_CLASSIC) {
disabledFeatures = spaceClone.disabledFeatures;
}

Expand Down Expand Up @@ -181,13 +187,27 @@ export const EditSpaceSettingsTab: React.FC<Props> = ({ space, features, history
[backToSpacesList, notifications.toasts, formValues, spacesManager, logger, props]
);

const validator = useMemo(() => new SpaceValidator(), []);

const onClickSubmit = useCallback(() => {
validator.enableValidation();
const validationResult = validator.validateForSave(
formValues,
true,
props.allowSolutionVisibility
);

if (validationResult.isInvalid) {
// invalid form input fields will show the error message
return;
}

if (showUserImpactWarning) {
setShowAlteringActiveSpaceDialog(true);
} else {
performSave({ requiresReload: false });
}
}, [performSave, showUserImpactWarning]);
}, [validator, formValues, props.allowSolutionVisibility, performSave, showUserImpactWarning]);

const doShowAlteringActiveSpaceDialog = () => {
return (
Expand Down Expand Up @@ -245,15 +265,13 @@ export const EditSpaceSettingsTab: React.FC<Props> = ({ space, features, history
);
};

const validator = new SpaceValidator();

return (
<>
{doShowAlteringActiveSpaceDialog()}
{doShowConfirmDeleteSpaceDialog()}

<CustomizeSpace
space={formValues}
space={getSpaceFromFormValues(formValues)}
onChange={onChangeSpaceSettings}
editingExistingSpace={true}
validator={validator}
Expand All @@ -263,7 +281,7 @@ export const EditSpaceSettingsTab: React.FC<Props> = ({ space, features, history
<>
<EuiSpacer />
<SolutionView
space={formValues}
space={getSpaceFromFormValues(formValues)}
onChange={onSolutionViewChange}
validator={validator}
isEditing={true}
Expand All @@ -276,7 +294,7 @@ export const EditSpaceSettingsTab: React.FC<Props> = ({ space, features, history
<EuiSpacer />
<EditSpaceEnabledFeatures
features={features}
space={formValues}
space={getSpaceFromFormValues(formValues)}
onChange={onChangeFeatures}
/>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
* 2.0.
*/

import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../ftr_provider_context';

export default function ({ getPageObjects, getService }: FtrProviderContext) {
const kibanaServer = getService('kibanaServer');
const PageObjects = getPageObjects(['common', 'settings', 'security', 'spaceSelector']);
const testSubjects = getService('testSubjects');
const spacesService = getService('spaces');
const find = getService('find');

describe('edit space', () => {
Expand Down Expand Up @@ -69,5 +71,55 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await testSubjects.missingOrFail('searchSideNav');
});
});

describe('API-created Space', () => {
before(async () => {
await spacesService.create({
id: 'foo-space',
name: 'Foo Space',
disabledFeatures: [],
color: '#AABBCC',
});
});

after(async () => {
await spacesService.delete('foo-space');
});

it('enabled features can be changed while the solution view remains unselected', async () => {
const securityFeatureCheckboxId = 'featureCategoryCheckbox_securitySolution';

await PageObjects.common.navigateToUrl('management', 'kibana/spaces/edit/foo-space', {
shouldUseHashForSubUrl: false,
});

await testSubjects.existOrFail('spaces-view-page');

// ensure security feature is selected by default
expect(await testSubjects.isChecked(securityFeatureCheckboxId)).to.be(true);

// Do not set a solution view first!

await PageObjects.spaceSelector.toggleFeatureCategoryCheckbox('securitySolution');
//
// ensure security feature now unselected
expect(await testSubjects.isChecked(securityFeatureCheckboxId)).to.be(false);

await testSubjects.existOrFail('space-edit-page-user-impact-warning');

await PageObjects.spaceSelector.clickSaveSpaceCreation();

await testSubjects.click('confirmModalConfirmButton');

await testSubjects.existOrFail('spaces-view-page');

await testSubjects.click('foo-space-hyperlink');

await testSubjects.existOrFail('spaces-view-page');

// ensure security feature is still unselected
expect(await testSubjects.isChecked(securityFeatureCheckboxId)).to.be(false);
});
});
});
}
4 changes: 4 additions & 0 deletions x-pack/test/functional/page_objects/space_selector_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ export class SpaceSelectorPageObject extends FtrService {
await this.testSubjects.click(`featureCategoryButton_${categoryName}`);
}

async toggleFeatureCategoryCheckbox(categoryName: string) {
await this.testSubjects.click(`featureCategoryCheckbox_${categoryName}`);
}

async clickOnDescriptionOfSpace() {
await this.testSubjects.click('descriptionSpaceText');
}
Expand Down

0 comments on commit 84d4a5a

Please sign in to comment.