mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Enterprise Search] Create reusable Group and Engine assignment selectors (#101790)
* Create AssignmentSelectors These components will be used in both the Role Mapping and User flyouts to create and edit role mappings and users, respectively * Implement AssignmentSelectors in components
This commit is contained in:
parent
a9a834a105
commit
d7d67df5eb
8 changed files with 393 additions and 199 deletions
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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 '../../../__mocks__/react_router';
|
||||
import '../../../__mocks__/shallow_useeffect.mock';
|
||||
import { DEFAULT_INITIAL_APP_DATA } from '../../../../../common/__mocks__';
|
||||
import { setMockActions, setMockValues } from '../../../__mocks__/kea_logic';
|
||||
import { engines } from '../../__mocks__/engines.mock';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { waitFor } from '@testing-library/dom';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { EuiComboBox, EuiComboBoxOptionOption, EuiRadioGroup } from '@elastic/eui';
|
||||
|
||||
import { asRoleMapping } from '../../../shared/role_mapping/__mocks__/roles';
|
||||
|
||||
import { EngineAssignmentSelector } from './engine_assignment_selector';
|
||||
|
||||
describe('EngineAssignmentSelector', () => {
|
||||
const mockRole = DEFAULT_INITIAL_APP_DATA.appSearch.role;
|
||||
const actions = {
|
||||
initializeRoleMappings: jest.fn(),
|
||||
initializeRoleMapping: jest.fn(),
|
||||
handleSaveMapping: jest.fn(),
|
||||
handleEngineSelectionChange: jest.fn(),
|
||||
handleAccessAllEnginesChange: jest.fn(),
|
||||
handleAttributeValueChange: jest.fn(),
|
||||
handleAttributeSelectorChange: jest.fn(),
|
||||
handleDeleteMapping: jest.fn(),
|
||||
handleRoleChange: jest.fn(),
|
||||
handleAuthProviderChange: jest.fn(),
|
||||
resetState: jest.fn(),
|
||||
};
|
||||
|
||||
const mockValues = {
|
||||
attributes: [],
|
||||
elasticsearchRoles: [],
|
||||
hasAdvancedRoles: true,
|
||||
dataLoading: false,
|
||||
roleType: 'admin',
|
||||
roleMappings: [asRoleMapping],
|
||||
attributeValue: '',
|
||||
attributeName: 'username',
|
||||
availableEngines: engines,
|
||||
selectedEngines: new Set(),
|
||||
accessAllEngines: false,
|
||||
availableAuthProviders: [],
|
||||
multipleAuthProvidersConfig: true,
|
||||
selectedAuthProviders: [],
|
||||
myRole: {
|
||||
availableRoleTypes: mockRole.ability.availableRoleTypes,
|
||||
},
|
||||
roleMappingErrors: [],
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
setMockActions(actions);
|
||||
setMockValues(mockValues);
|
||||
});
|
||||
|
||||
it('renders', () => {
|
||||
setMockValues({ ...mockValues, roleMapping: asRoleMapping });
|
||||
const wrapper = shallow(<EngineAssignmentSelector />);
|
||||
|
||||
expect(wrapper.find(EuiRadioGroup)).toHaveLength(1);
|
||||
expect(wrapper.find(EuiComboBox)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('sets initial selected state when accessAllEngines is true', () => {
|
||||
setMockValues({ ...mockValues, accessAllEngines: true });
|
||||
const wrapper = shallow(<EngineAssignmentSelector />);
|
||||
|
||||
expect(wrapper.find(EuiRadioGroup).prop('idSelected')).toBe('all');
|
||||
});
|
||||
|
||||
it('handles all/specific engines radio change', () => {
|
||||
const wrapper = shallow(<EngineAssignmentSelector />);
|
||||
const radio = wrapper.find(EuiRadioGroup);
|
||||
radio.simulate('change', { target: { checked: false } });
|
||||
|
||||
expect(actions.handleAccessAllEnginesChange).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it('handles engine checkbox click', async () => {
|
||||
const wrapper = shallow(<EngineAssignmentSelector />);
|
||||
await waitFor(() =>
|
||||
((wrapper.find(EuiComboBox).props() as unknown) as {
|
||||
onChange: (a: EuiComboBoxOptionOption[]) => void;
|
||||
}).onChange([{ label: engines[0].name, value: engines[0].name }])
|
||||
);
|
||||
wrapper.update();
|
||||
|
||||
expect(actions.handleEngineSelectionChange).toHaveBeenCalledWith([engines[0].name]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
import { useActions, useValues } from 'kea';
|
||||
|
||||
import { EuiComboBox, EuiFormRow, EuiHorizontalRule, EuiRadioGroup } from '@elastic/eui';
|
||||
|
||||
import { RoleOptionLabel } from '../../../shared/role_mapping';
|
||||
|
||||
import { roleHasScopedEngines } from '../../utils/role/has_scoped_engines';
|
||||
|
||||
import {
|
||||
ENGINE_REQUIRED_ERROR,
|
||||
ALL_ENGINES_LABEL,
|
||||
ALL_ENGINES_DESCRIPTION,
|
||||
SPECIFIC_ENGINES_LABEL,
|
||||
SPECIFIC_ENGINES_DESCRIPTION,
|
||||
ENGINE_ASSIGNMENT_LABEL,
|
||||
} from './constants';
|
||||
import { RoleMappingsLogic } from './role_mappings_logic';
|
||||
|
||||
export const EngineAssignmentSelector: React.FC = () => {
|
||||
const { handleAccessAllEnginesChange, handleEngineSelectionChange } = useActions(
|
||||
RoleMappingsLogic
|
||||
);
|
||||
|
||||
const {
|
||||
accessAllEngines,
|
||||
availableEngines,
|
||||
roleType,
|
||||
selectedEngines,
|
||||
selectedOptions,
|
||||
} = useValues(RoleMappingsLogic);
|
||||
|
||||
const hasEngineAssignment = selectedEngines.size > 0 || accessAllEngines;
|
||||
|
||||
const engineOptions = [
|
||||
{
|
||||
id: 'all',
|
||||
label: <RoleOptionLabel label={ALL_ENGINES_LABEL} description={ALL_ENGINES_DESCRIPTION} />,
|
||||
},
|
||||
{
|
||||
id: 'specific',
|
||||
label: (
|
||||
<RoleOptionLabel
|
||||
label={SPECIFIC_ENGINES_LABEL}
|
||||
description={SPECIFIC_ENGINES_DESCRIPTION}
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiHorizontalRule />
|
||||
<EuiFormRow>
|
||||
<EuiRadioGroup
|
||||
options={engineOptions}
|
||||
disabled={!roleHasScopedEngines(roleType)}
|
||||
idSelected={accessAllEngines ? 'all' : 'specific'}
|
||||
onChange={(id) => handleAccessAllEnginesChange(id === 'all')}
|
||||
legend={{
|
||||
children: <span>{ENGINE_ASSIGNMENT_LABEL}</span>,
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow isInvalid={!hasEngineAssignment} error={[ENGINE_REQUIRED_ERROR]}>
|
||||
<EuiComboBox
|
||||
data-test-subj="enginesSelect"
|
||||
selectedOptions={selectedOptions}
|
||||
options={availableEngines.map(({ name }) => ({ label: name, value: name }))}
|
||||
onChange={(options) => {
|
||||
handleEngineSelectionChange(options.map(({ value }) => value as string));
|
||||
}}
|
||||
fullWidth
|
||||
isDisabled={accessAllEngines || !roleHasScopedEngines(roleType)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -13,16 +13,14 @@ import { engines } from '../../__mocks__/engines.mock';
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import { waitFor } from '@testing-library/dom';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { EuiComboBox, EuiComboBoxOptionOption, EuiRadioGroup } from '@elastic/eui';
|
||||
|
||||
import { AttributeSelector, RoleSelector, RoleMappingFlyout } from '../../../shared/role_mapping';
|
||||
import { asRoleMapping } from '../../../shared/role_mapping/__mocks__/roles';
|
||||
|
||||
import { STANDARD_ROLE_TYPES } from './constants';
|
||||
|
||||
import { EngineAssignmentSelector } from './engine_assignment_selector';
|
||||
import { RoleMapping } from './role_mapping';
|
||||
|
||||
describe('RoleMapping', () => {
|
||||
|
@ -73,6 +71,7 @@ describe('RoleMapping', () => {
|
|||
|
||||
expect(wrapper.find(AttributeSelector)).toHaveLength(1);
|
||||
expect(wrapper.find(RoleSelector)).toHaveLength(1);
|
||||
expect(wrapper.find(EngineAssignmentSelector)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('only passes standard role options for non-advanced roles', () => {
|
||||
|
@ -82,33 +81,6 @@ describe('RoleMapping', () => {
|
|||
expect(wrapper.find(RoleSelector).prop('roleOptions')).toHaveLength(STANDARD_ROLE_TYPES.length);
|
||||
});
|
||||
|
||||
it('sets initial selected state when accessAllEngines is true', () => {
|
||||
setMockValues({ ...mockValues, accessAllEngines: true });
|
||||
const wrapper = shallow(<RoleMapping />);
|
||||
|
||||
expect(wrapper.find(EuiRadioGroup).prop('idSelected')).toBe('all');
|
||||
});
|
||||
|
||||
it('handles all/specific engines radio change', () => {
|
||||
const wrapper = shallow(<RoleMapping />);
|
||||
const radio = wrapper.find(EuiRadioGroup);
|
||||
radio.simulate('change', { target: { checked: false } });
|
||||
|
||||
expect(actions.handleAccessAllEnginesChange).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it('handles engine checkbox click', async () => {
|
||||
const wrapper = shallow(<RoleMapping />);
|
||||
await waitFor(() =>
|
||||
((wrapper.find(EuiComboBox).props() as unknown) as {
|
||||
onChange: (a: EuiComboBoxOptionOption[]) => void;
|
||||
}).onChange([{ label: engines[0].name, value: engines[0].name }])
|
||||
);
|
||||
wrapper.update();
|
||||
|
||||
expect(actions.handleEngineSelectionChange).toHaveBeenCalledWith([engines[0].name]);
|
||||
});
|
||||
|
||||
it('enables flyout when attribute value is valid', () => {
|
||||
setMockValues({
|
||||
...mockValues,
|
||||
|
|
|
@ -9,47 +9,23 @@ import React from 'react';
|
|||
|
||||
import { useActions, useValues } from 'kea';
|
||||
|
||||
import {
|
||||
EuiComboBox,
|
||||
EuiForm,
|
||||
EuiFormRow,
|
||||
EuiHorizontalRule,
|
||||
EuiRadioGroup,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
import { EuiForm, EuiSpacer } from '@elastic/eui';
|
||||
|
||||
import {
|
||||
AttributeSelector,
|
||||
RoleSelector,
|
||||
RoleOptionLabel,
|
||||
RoleMappingFlyout,
|
||||
} from '../../../shared/role_mapping';
|
||||
import { AttributeSelector, RoleSelector, RoleMappingFlyout } from '../../../shared/role_mapping';
|
||||
import { AppLogic } from '../../app_logic';
|
||||
import { AdvanceRoleType } from '../../types';
|
||||
|
||||
import { roleHasScopedEngines } from '../../utils/role/has_scoped_engines';
|
||||
|
||||
import {
|
||||
ADVANCED_ROLE_TYPES,
|
||||
STANDARD_ROLE_TYPES,
|
||||
ENGINE_REQUIRED_ERROR,
|
||||
ALL_ENGINES_LABEL,
|
||||
ALL_ENGINES_DESCRIPTION,
|
||||
SPECIFIC_ENGINES_LABEL,
|
||||
SPECIFIC_ENGINES_DESCRIPTION,
|
||||
ENGINE_ASSIGNMENT_LABEL,
|
||||
} from './constants';
|
||||
import { ADVANCED_ROLE_TYPES, STANDARD_ROLE_TYPES } from './constants';
|
||||
import { EngineAssignmentSelector } from './engine_assignment_selector';
|
||||
import { RoleMappingsLogic } from './role_mappings_logic';
|
||||
|
||||
export const RoleMapping: React.FC = () => {
|
||||
const { myRole } = useValues(AppLogic);
|
||||
|
||||
const {
|
||||
handleAccessAllEnginesChange,
|
||||
handleAttributeSelectorChange,
|
||||
handleAttributeValueChange,
|
||||
handleAuthProviderChange,
|
||||
handleEngineSelectionChange,
|
||||
handleRoleChange,
|
||||
handleSaveMapping,
|
||||
closeRoleMappingFlyout,
|
||||
|
@ -61,7 +37,6 @@ export const RoleMapping: React.FC = () => {
|
|||
attributeValue,
|
||||
attributes,
|
||||
availableAuthProviders,
|
||||
availableEngines,
|
||||
elasticsearchRoles,
|
||||
hasAdvancedRoles,
|
||||
multipleAuthProvidersConfig,
|
||||
|
@ -69,7 +44,6 @@ export const RoleMapping: React.FC = () => {
|
|||
roleType,
|
||||
selectedEngines,
|
||||
selectedAuthProviders,
|
||||
selectedOptions,
|
||||
roleMappingErrors,
|
||||
} = useValues(RoleMappingsLogic);
|
||||
|
||||
|
@ -90,22 +64,6 @@ export const RoleMapping: React.FC = () => {
|
|||
? [...standardRoleOptions, ...advancedRoleOptions]
|
||||
: standardRoleOptions;
|
||||
|
||||
const engineOptions = [
|
||||
{
|
||||
id: 'all',
|
||||
label: <RoleOptionLabel label={ALL_ENGINES_LABEL} description={ALL_ENGINES_DESCRIPTION} />,
|
||||
},
|
||||
{
|
||||
id: 'specific',
|
||||
label: (
|
||||
<RoleOptionLabel
|
||||
label={SPECIFIC_ENGINES_LABEL}
|
||||
description={SPECIFIC_ENGINES_DESCRIPTION}
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<RoleMappingFlyout
|
||||
disabled={attributeValueInvalid || !hasEngineAssignment}
|
||||
|
@ -135,35 +93,7 @@ export const RoleMapping: React.FC = () => {
|
|||
onChange={handleRoleChange}
|
||||
label="Role"
|
||||
/>
|
||||
|
||||
{hasAdvancedRoles && (
|
||||
<>
|
||||
<EuiHorizontalRule />
|
||||
<EuiFormRow>
|
||||
<EuiRadioGroup
|
||||
options={engineOptions}
|
||||
disabled={!roleHasScopedEngines(roleType)}
|
||||
idSelected={accessAllEngines ? 'all' : 'specific'}
|
||||
onChange={(id) => handleAccessAllEnginesChange(id === 'all')}
|
||||
legend={{
|
||||
children: <span>{ENGINE_ASSIGNMENT_LABEL}</span>,
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow isInvalid={!hasEngineAssignment} error={[ENGINE_REQUIRED_ERROR]}>
|
||||
<EuiComboBox
|
||||
data-test-subj="enginesSelect"
|
||||
selectedOptions={selectedOptions}
|
||||
options={availableEngines.map(({ name }) => ({ label: name, value: name }))}
|
||||
onChange={(options) => {
|
||||
handleEngineSelectionChange(options.map(({ value }) => value as string));
|
||||
}}
|
||||
fullWidth
|
||||
isDisabled={accessAllEngines || !roleHasScopedEngines(roleType)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</>
|
||||
)}
|
||||
{hasAdvancedRoles && <EngineAssignmentSelector />}
|
||||
</EuiForm>
|
||||
</RoleMappingFlyout>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* 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 '../../../__mocks__/react_router';
|
||||
import '../../../__mocks__/shallow_useeffect.mock';
|
||||
import { setMockActions, setMockValues } from '../../../__mocks__/kea_logic';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { waitFor } from '@testing-library/dom';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { EuiComboBox, EuiComboBoxOptionOption, EuiRadioGroup } from '@elastic/eui';
|
||||
|
||||
import { wsRoleMapping } from '../../../shared/role_mapping/__mocks__/roles';
|
||||
|
||||
import { GroupAssignmentSelector } from './group_assignment_selector';
|
||||
|
||||
describe('GroupAssignmentSelector', () => {
|
||||
const initializeRoleMappings = jest.fn();
|
||||
const initializeRoleMapping = jest.fn();
|
||||
const handleSaveMapping = jest.fn();
|
||||
const handleGroupSelectionChange = jest.fn();
|
||||
const handleAllGroupsSelectionChange = jest.fn();
|
||||
const handleAttributeValueChange = jest.fn();
|
||||
const handleAttributeSelectorChange = jest.fn();
|
||||
const handleDeleteMapping = jest.fn();
|
||||
const handleRoleChange = jest.fn();
|
||||
const handleAuthProviderChange = jest.fn();
|
||||
const resetState = jest.fn();
|
||||
const groups = [
|
||||
{
|
||||
name: 'Group 1',
|
||||
id: 'g1',
|
||||
},
|
||||
{
|
||||
name: 'Group 2',
|
||||
id: 'g2',
|
||||
},
|
||||
];
|
||||
const mockValues = {
|
||||
attributes: [],
|
||||
elasticsearchRoles: [],
|
||||
dataLoading: false,
|
||||
roleType: 'admin',
|
||||
roleMappings: [wsRoleMapping],
|
||||
attributeValue: '',
|
||||
attributeName: 'username',
|
||||
availableGroups: groups,
|
||||
selectedGroups: new Set(),
|
||||
includeInAllGroups: false,
|
||||
availableAuthProviders: [],
|
||||
multipleAuthProvidersConfig: true,
|
||||
selectedAuthProviders: [],
|
||||
roleMappingErrors: [],
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
setMockActions({
|
||||
initializeRoleMappings,
|
||||
initializeRoleMapping,
|
||||
handleSaveMapping,
|
||||
handleGroupSelectionChange,
|
||||
handleAllGroupsSelectionChange,
|
||||
handleAttributeValueChange,
|
||||
handleAttributeSelectorChange,
|
||||
handleDeleteMapping,
|
||||
handleRoleChange,
|
||||
handleAuthProviderChange,
|
||||
resetState,
|
||||
});
|
||||
setMockValues(mockValues);
|
||||
});
|
||||
|
||||
it('renders', () => {
|
||||
setMockValues({ ...mockValues, GroupAssignmentSelector: wsRoleMapping });
|
||||
const wrapper = shallow(<GroupAssignmentSelector />);
|
||||
|
||||
expect(wrapper.find(EuiRadioGroup)).toHaveLength(1);
|
||||
expect(wrapper.find(EuiComboBox)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('sets initial selected state when includeInAllGroups is true', () => {
|
||||
setMockValues({ ...mockValues, includeInAllGroups: true });
|
||||
const wrapper = shallow(<GroupAssignmentSelector />);
|
||||
|
||||
expect(wrapper.find(EuiRadioGroup).prop('idSelected')).toBe('all');
|
||||
});
|
||||
|
||||
it('handles all/specific groups radio change', () => {
|
||||
const wrapper = shallow(<GroupAssignmentSelector />);
|
||||
const radio = wrapper.find(EuiRadioGroup);
|
||||
radio.simulate('change', { target: { checked: false } });
|
||||
|
||||
expect(handleAllGroupsSelectionChange).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it('handles group checkbox click', async () => {
|
||||
const wrapper = shallow(<GroupAssignmentSelector />);
|
||||
await waitFor(() =>
|
||||
((wrapper.find(EuiComboBox).props() as unknown) as {
|
||||
onChange: (a: EuiComboBoxOptionOption[]) => void;
|
||||
}).onChange([{ label: groups[0].name, value: groups[0].name }])
|
||||
);
|
||||
wrapper.update();
|
||||
|
||||
expect(handleGroupSelectionChange).toHaveBeenCalledWith([groups[0].name]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
import { useActions, useValues } from 'kea';
|
||||
|
||||
import { EuiComboBox, EuiFormRow, EuiHorizontalRule, EuiRadioGroup } from '@elastic/eui';
|
||||
|
||||
import { RoleOptionLabel } from '../../../shared/role_mapping';
|
||||
|
||||
import {
|
||||
GROUP_ASSIGNMENT_INVALID_ERROR,
|
||||
GROUP_ASSIGNMENT_LABEL,
|
||||
ALL_GROUPS_LABEL,
|
||||
ALL_GROUPS_DESCRIPTION,
|
||||
SPECIFIC_GROUPS_LABEL,
|
||||
SPECIFIC_GROUPS_DESCRIPTION,
|
||||
} from './constants';
|
||||
|
||||
import { RoleMappingsLogic } from './role_mappings_logic';
|
||||
|
||||
export const GroupAssignmentSelector: React.FC = () => {
|
||||
const { handleAllGroupsSelectionChange, handleGroupSelectionChange } = useActions(
|
||||
RoleMappingsLogic
|
||||
);
|
||||
|
||||
const { includeInAllGroups, availableGroups, selectedGroups, selectedOptions } = useValues(
|
||||
RoleMappingsLogic
|
||||
);
|
||||
|
||||
const hasGroupAssignment = selectedGroups.size > 0 || includeInAllGroups;
|
||||
|
||||
const groupOptions = [
|
||||
{
|
||||
id: 'all',
|
||||
label: <RoleOptionLabel label={ALL_GROUPS_LABEL} description={ALL_GROUPS_DESCRIPTION} />,
|
||||
},
|
||||
{
|
||||
id: 'specific',
|
||||
label: (
|
||||
<RoleOptionLabel label={SPECIFIC_GROUPS_LABEL} description={SPECIFIC_GROUPS_DESCRIPTION} />
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiHorizontalRule />
|
||||
<EuiFormRow>
|
||||
<EuiRadioGroup
|
||||
options={groupOptions}
|
||||
idSelected={includeInAllGroups ? 'all' : 'specific'}
|
||||
onChange={(id) => handleAllGroupsSelectionChange(id === 'all')}
|
||||
legend={{
|
||||
children: <span>{GROUP_ASSIGNMENT_LABEL}</span>,
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow isInvalid={!hasGroupAssignment} error={[GROUP_ASSIGNMENT_INVALID_ERROR]}>
|
||||
<EuiComboBox
|
||||
data-test-subj="groupsSelect"
|
||||
selectedOptions={selectedOptions}
|
||||
options={availableGroups.map(({ name, id }) => ({ label: name, value: id }))}
|
||||
onChange={(options) => {
|
||||
handleGroupSelectionChange(options.map(({ value }) => value as string));
|
||||
}}
|
||||
fullWidth
|
||||
isDisabled={includeInAllGroups}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -11,14 +11,12 @@ import { setMockActions, setMockValues } from '../../../__mocks__/kea_logic';
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import { waitFor } from '@testing-library/dom';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { EuiComboBox, EuiComboBoxOptionOption, EuiRadioGroup } from '@elastic/eui';
|
||||
|
||||
import { AttributeSelector, RoleSelector, RoleMappingFlyout } from '../../../shared/role_mapping';
|
||||
import { wsRoleMapping } from '../../../shared/role_mapping/__mocks__/roles';
|
||||
|
||||
import { GroupAssignmentSelector } from './group_assignment_selector';
|
||||
import { RoleMapping } from './role_mapping';
|
||||
|
||||
describe('RoleMapping', () => {
|
||||
|
@ -83,33 +81,7 @@ describe('RoleMapping', () => {
|
|||
|
||||
expect(wrapper.find(AttributeSelector)).toHaveLength(1);
|
||||
expect(wrapper.find(RoleSelector)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('sets initial selected state when includeInAllGroups is true', () => {
|
||||
setMockValues({ ...mockValues, includeInAllGroups: true });
|
||||
const wrapper = shallow(<RoleMapping />);
|
||||
|
||||
expect(wrapper.find(EuiRadioGroup).prop('idSelected')).toBe('all');
|
||||
});
|
||||
|
||||
it('handles all/specific groups radio change', () => {
|
||||
const wrapper = shallow(<RoleMapping />);
|
||||
const radio = wrapper.find(EuiRadioGroup);
|
||||
radio.simulate('change', { target: { checked: false } });
|
||||
|
||||
expect(handleAllGroupsSelectionChange).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it('handles group checkbox click', async () => {
|
||||
const wrapper = shallow(<RoleMapping />);
|
||||
await waitFor(() =>
|
||||
((wrapper.find(EuiComboBox).props() as unknown) as {
|
||||
onChange: (a: EuiComboBoxOptionOption[]) => void;
|
||||
}).onChange([{ label: groups[0].name, value: groups[0].name }])
|
||||
);
|
||||
wrapper.update();
|
||||
|
||||
expect(handleGroupSelectionChange).toHaveBeenCalledWith([groups[0].name]);
|
||||
expect(wrapper.find(GroupAssignmentSelector)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('enables flyout when attribute value is valid', () => {
|
||||
|
|
|
@ -9,35 +9,15 @@ import React from 'react';
|
|||
|
||||
import { useActions, useValues } from 'kea';
|
||||
|
||||
import {
|
||||
EuiComboBox,
|
||||
EuiForm,
|
||||
EuiFormRow,
|
||||
EuiHorizontalRule,
|
||||
EuiRadioGroup,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
import { EuiForm, EuiSpacer } from '@elastic/eui';
|
||||
|
||||
import {
|
||||
AttributeSelector,
|
||||
RoleSelector,
|
||||
RoleOptionLabel,
|
||||
RoleMappingFlyout,
|
||||
} from '../../../shared/role_mapping';
|
||||
import { AttributeSelector, RoleSelector, RoleMappingFlyout } from '../../../shared/role_mapping';
|
||||
|
||||
import { Role } from '../../types';
|
||||
|
||||
import {
|
||||
ADMIN_ROLE_TYPE_DESCRIPTION,
|
||||
USER_ROLE_TYPE_DESCRIPTION,
|
||||
GROUP_ASSIGNMENT_INVALID_ERROR,
|
||||
GROUP_ASSIGNMENT_LABEL,
|
||||
ALL_GROUPS_LABEL,
|
||||
ALL_GROUPS_DESCRIPTION,
|
||||
SPECIFIC_GROUPS_LABEL,
|
||||
SPECIFIC_GROUPS_DESCRIPTION,
|
||||
} from './constants';
|
||||
import { ADMIN_ROLE_TYPE_DESCRIPTION, USER_ROLE_TYPE_DESCRIPTION } from './constants';
|
||||
|
||||
import { GroupAssignmentSelector } from './group_assignment_selector';
|
||||
import { RoleMappingsLogic } from './role_mappings_logic';
|
||||
|
||||
interface RoleType {
|
||||
|
@ -56,24 +36,9 @@ const roleOptions = [
|
|||
},
|
||||
] as RoleType[];
|
||||
|
||||
const groupOptions = [
|
||||
{
|
||||
id: 'all',
|
||||
label: <RoleOptionLabel label={ALL_GROUPS_LABEL} description={ALL_GROUPS_DESCRIPTION} />,
|
||||
},
|
||||
{
|
||||
id: 'specific',
|
||||
label: (
|
||||
<RoleOptionLabel label={SPECIFIC_GROUPS_LABEL} description={SPECIFIC_GROUPS_DESCRIPTION} />
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
export const RoleMapping: React.FC = () => {
|
||||
const {
|
||||
handleSaveMapping,
|
||||
handleGroupSelectionChange,
|
||||
handleAllGroupsSelectionChange,
|
||||
handleAttributeValueChange,
|
||||
handleAttributeSelectorChange,
|
||||
handleRoleChange,
|
||||
|
@ -87,13 +52,11 @@ export const RoleMapping: React.FC = () => {
|
|||
roleType,
|
||||
attributeValue,
|
||||
attributeName,
|
||||
availableGroups,
|
||||
selectedGroups,
|
||||
includeInAllGroups,
|
||||
availableAuthProviders,
|
||||
multipleAuthProvidersConfig,
|
||||
selectedAuthProviders,
|
||||
selectedOptions,
|
||||
roleMapping,
|
||||
roleMappingErrors,
|
||||
} = useValues(RoleMappingsLogic);
|
||||
|
@ -132,29 +95,7 @@ export const RoleMapping: React.FC = () => {
|
|||
onChange={handleRoleChange}
|
||||
label="Role"
|
||||
/>
|
||||
<EuiHorizontalRule />
|
||||
<EuiFormRow>
|
||||
<EuiRadioGroup
|
||||
options={groupOptions}
|
||||
idSelected={includeInAllGroups ? 'all' : 'specific'}
|
||||
onChange={(id) => handleAllGroupsSelectionChange(id === 'all')}
|
||||
legend={{
|
||||
children: <span>{GROUP_ASSIGNMENT_LABEL}</span>,
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow isInvalid={!hasGroupAssignment} error={[GROUP_ASSIGNMENT_INVALID_ERROR]}>
|
||||
<EuiComboBox
|
||||
data-test-subj="groupsSelect"
|
||||
selectedOptions={selectedOptions}
|
||||
options={availableGroups.map(({ name, id }) => ({ label: name, value: id }))}
|
||||
onChange={(options) => {
|
||||
handleGroupSelectionChange(options.map(({ value }) => value as string));
|
||||
}}
|
||||
fullWidth
|
||||
isDisabled={includeInAllGroups}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<GroupAssignmentSelector />
|
||||
</EuiForm>
|
||||
</RoleMappingFlyout>
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue