mirror of
https://github.com/ansible/awx.git
synced 2026-01-15 11:50:42 -03:30
Merge pull request #8781 from marshmalien/setting-ldap-edit-forms
Add all LDAP (Default, 1-5) setting forms Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
commit
d88ed19edf
@ -6,6 +6,7 @@ import 'codemirror/mode/javascript/javascript';
|
||||
import 'codemirror/mode/yaml/yaml';
|
||||
import 'codemirror/mode/jinja2/jinja2';
|
||||
import 'codemirror/lib/codemirror.css';
|
||||
import 'codemirror/addon/display/placeholder';
|
||||
|
||||
const LINE_HEIGHT = 24;
|
||||
const PADDING = 12;
|
||||
@ -55,6 +56,17 @@ const CodeMirror = styled(ReactCodeMirror)`
|
||||
background-color: var(--pf-c-form-control--disabled--BackgroundColor);
|
||||
}
|
||||
`}
|
||||
${props =>
|
||||
props.options &&
|
||||
props.options.placeholder &&
|
||||
`
|
||||
.CodeMirror-empty {
|
||||
pre.CodeMirror-placeholder {
|
||||
color: var(--pf-c-form-control--placeholder--Color);
|
||||
height: 100% !important;
|
||||
}
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
function CodeMirrorInput({
|
||||
@ -66,6 +78,7 @@ function CodeMirrorInput({
|
||||
rows,
|
||||
fullHeight,
|
||||
className,
|
||||
placeholder,
|
||||
}) {
|
||||
// Workaround for CodeMirror bug: If CodeMirror renders in a modal on the
|
||||
// modal's initial render, it appears as an empty box due to mis-calculated
|
||||
@ -92,6 +105,7 @@ function CodeMirrorInput({
|
||||
smartIndent: false,
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
placeholder,
|
||||
readOnly,
|
||||
}}
|
||||
fullHeight={fullHeight}
|
||||
|
||||
@ -6,12 +6,13 @@ import {
|
||||
waitForElement,
|
||||
} from '../../../../testUtils/enzymeHelpers';
|
||||
import { SettingsAPI } from '../../../api';
|
||||
import { SettingsProvider } from '../../../contexts/Settings';
|
||||
import mockAllOptions from '../shared/data.allSettingOptions.json';
|
||||
import mockLDAP from '../shared/data.ldapSettings.json';
|
||||
import LDAP from './LDAP';
|
||||
|
||||
jest.mock('../../../api/models/Settings');
|
||||
SettingsAPI.readCategory.mockResolvedValue({
|
||||
data: {},
|
||||
});
|
||||
SettingsAPI.readCategory.mockResolvedValue({ data: mockLDAP });
|
||||
|
||||
describe('<LDAP />', () => {
|
||||
let wrapper;
|
||||
@ -39,9 +40,14 @@ describe('<LDAP />', () => {
|
||||
initialEntries: ['/settings/ldap/default/edit'],
|
||||
});
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<LDAP />, {
|
||||
context: { router: { history } },
|
||||
});
|
||||
wrapper = mountWithContexts(
|
||||
<SettingsProvider value={mockAllOptions.actions}>
|
||||
<LDAP />
|
||||
</SettingsProvider>,
|
||||
{
|
||||
context: { router: { history } },
|
||||
}
|
||||
);
|
||||
});
|
||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||
expect(wrapper.find('LDAPEdit').length).toBe(1);
|
||||
|
||||
@ -1,25 +1,250 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { Button } from '@patternfly/react-core';
|
||||
import { CardBody, CardActionsRow } from '../../../../components/Card';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useHistory, useRouteMatch } from 'react-router-dom';
|
||||
import { Formik } from 'formik';
|
||||
import { Form } from '@patternfly/react-core';
|
||||
import { CardBody } from '../../../../components/Card';
|
||||
import ContentError from '../../../../components/ContentError';
|
||||
import ContentLoading from '../../../../components/ContentLoading';
|
||||
import { FormSubmitError } from '../../../../components/FormField';
|
||||
import {
|
||||
FormColumnLayout,
|
||||
FormFullWidthLayout,
|
||||
} from '../../../../components/FormLayout';
|
||||
import { useSettings } from '../../../../contexts/Settings';
|
||||
import { RevertAllAlert, RevertFormActionGroup } from '../../shared';
|
||||
import {
|
||||
BooleanField,
|
||||
ChoiceField,
|
||||
EncryptedField,
|
||||
InputField,
|
||||
ObjectField,
|
||||
} from '../../shared/SharedFields';
|
||||
import { formatJson } from '../../shared/settingUtils';
|
||||
import useModal from '../../../../util/useModal';
|
||||
import useRequest from '../../../../util/useRequest';
|
||||
import { SettingsAPI } from '../../../../api';
|
||||
|
||||
function filterByPrefix(data, prefix) {
|
||||
return Object.keys(data)
|
||||
.filter(key => key.includes(prefix))
|
||||
.reduce((obj, key) => {
|
||||
obj[key] = data[key];
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function LDAPEdit() {
|
||||
const history = useHistory();
|
||||
const { isModalOpen, toggleModal, closeModal } = useModal();
|
||||
const { PUT: options } = useSettings();
|
||||
const {
|
||||
params: { category },
|
||||
} = useRouteMatch('/settings/ldap/:category/edit');
|
||||
const ldapCategory =
|
||||
category === 'default' ? 'AUTH_LDAP_' : `AUTH_LDAP_${category}_`;
|
||||
|
||||
const { isLoading, error, request: fetchLDAP, result: ldap } = useRequest(
|
||||
useCallback(async () => {
|
||||
const { data } = await SettingsAPI.readCategory('ldap');
|
||||
|
||||
const mergedData = {};
|
||||
Object.keys(data).forEach(key => {
|
||||
if (!options[key]) {
|
||||
return;
|
||||
}
|
||||
mergedData[key] = options[key];
|
||||
mergedData[key].value = data[key];
|
||||
});
|
||||
|
||||
const allCategories = {
|
||||
AUTH_LDAP_1_: filterByPrefix(mergedData, 'AUTH_LDAP_1_'),
|
||||
AUTH_LDAP_2_: filterByPrefix(mergedData, 'AUTH_LDAP_2_'),
|
||||
AUTH_LDAP_3_: filterByPrefix(mergedData, 'AUTH_LDAP_3_'),
|
||||
AUTH_LDAP_4_: filterByPrefix(mergedData, 'AUTH_LDAP_4_'),
|
||||
AUTH_LDAP_5_: filterByPrefix(mergedData, 'AUTH_LDAP_5_'),
|
||||
AUTH_LDAP_: Object.assign({}, mergedData),
|
||||
};
|
||||
Object.keys({
|
||||
...allCategories.AUTH_LDAP_1_,
|
||||
...allCategories.AUTH_LDAP_2_,
|
||||
...allCategories.AUTH_LDAP_3_,
|
||||
...allCategories.AUTH_LDAP_4_,
|
||||
...allCategories.AUTH_LDAP_5_,
|
||||
}).forEach(keyToOmit => {
|
||||
delete allCategories.AUTH_LDAP_[keyToOmit];
|
||||
});
|
||||
|
||||
return allCategories[ldapCategory];
|
||||
}, [options, ldapCategory]),
|
||||
null
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
fetchLDAP();
|
||||
}, [fetchLDAP]);
|
||||
|
||||
const { error: submitError, request: submitForm } = useRequest(
|
||||
useCallback(
|
||||
async values => {
|
||||
await SettingsAPI.updateAll(values);
|
||||
history.push(`/settings/ldap/${category}/details`);
|
||||
},
|
||||
[history, category]
|
||||
),
|
||||
null
|
||||
);
|
||||
|
||||
const handleSubmit = async form => {
|
||||
await submitForm({
|
||||
[`${ldapCategory}BIND_DN`]: form[`${ldapCategory}BIND_DN`],
|
||||
[`${ldapCategory}BIND_PASSWORD`]: form[`${ldapCategory}BIND_PASSWORD`],
|
||||
[`${ldapCategory}DENY_GROUP`]: form[`${ldapCategory}DENY_GROUP`],
|
||||
[`${ldapCategory}GROUP_TYPE`]: form[`${ldapCategory}GROUP_TYPE`],
|
||||
[`${ldapCategory}REQUIRE_GROUP`]: form[`${ldapCategory}REQUIRE_GROUP`],
|
||||
[`${ldapCategory}SERVER_URI`]: form[`${ldapCategory}SERVER_URI`],
|
||||
[`${ldapCategory}START_TLS`]: form[`${ldapCategory}START_TLS`],
|
||||
[`${ldapCategory}USER_DN_TEMPLATE`]: form[
|
||||
`${ldapCategory}USER_DN_TEMPLATE`
|
||||
],
|
||||
[`${ldapCategory}GROUP_SEARCH`]: formatJson(
|
||||
form[`${ldapCategory}GROUP_SEARCH`]
|
||||
),
|
||||
[`${ldapCategory}GROUP_TYPE_PARAMS`]: formatJson(
|
||||
form[`${ldapCategory}GROUP_TYPE_PARAMS`]
|
||||
),
|
||||
[`${ldapCategory}ORGANIZATION_MAP`]: formatJson(
|
||||
form[`${ldapCategory}ORGANIZATION_MAP`]
|
||||
),
|
||||
[`${ldapCategory}TEAM_MAP`]: formatJson(form[`${ldapCategory}TEAM_MAP`]),
|
||||
[`${ldapCategory}USER_ATTR_MAP`]: formatJson(
|
||||
form[`${ldapCategory}USER_ATTR_MAP`]
|
||||
),
|
||||
[`${ldapCategory}USER_FLAGS_BY_GROUP`]: formatJson(
|
||||
form[`${ldapCategory}USER_FLAGS_BY_GROUP`]
|
||||
),
|
||||
[`${ldapCategory}USER_SEARCH`]: formatJson(
|
||||
form[`${ldapCategory}USER_SEARCH`]
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
const handleRevertAll = async () => {
|
||||
const defaultValues = Object.assign(
|
||||
...Object.entries(ldap).map(([key, value]) => ({
|
||||
[key]: value.default,
|
||||
}))
|
||||
);
|
||||
await submitForm(defaultValues);
|
||||
closeModal();
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
history.push(`/settings/ldap/${category}/details`);
|
||||
};
|
||||
|
||||
const initialValues = fields =>
|
||||
Object.keys(fields).reduce((acc, key) => {
|
||||
if (fields[key].type === 'list' || fields[key].type === 'nested object') {
|
||||
const emptyDefault = fields[key].type === 'list' ? '[]' : '{}';
|
||||
acc[key] = fields[key].value
|
||||
? JSON.stringify(fields[key].value, null, 2)
|
||||
: emptyDefault;
|
||||
} else {
|
||||
acc[key] = fields[key].value ?? '';
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
function LDAPEdit({ i18n }) {
|
||||
return (
|
||||
<CardBody>
|
||||
{i18n._(t`Edit form coming soon :)`)}
|
||||
<CardActionsRow>
|
||||
<Button
|
||||
aria-label={i18n._(t`Cancel`)}
|
||||
component={Link}
|
||||
to="/settings/ldap/details"
|
||||
>
|
||||
{i18n._(t`Cancel`)}
|
||||
</Button>
|
||||
</CardActionsRow>
|
||||
{isLoading && <ContentLoading />}
|
||||
{!isLoading && error && <ContentError error={error} />}
|
||||
{!isLoading && ldap && (
|
||||
<Formik initialValues={initialValues(ldap)} onSubmit={handleSubmit}>
|
||||
{formik => (
|
||||
<Form autoComplete="off" onSubmit={formik.handleSubmit}>
|
||||
<FormColumnLayout>
|
||||
<InputField
|
||||
name={`${ldapCategory}SERVER_URI`}
|
||||
config={ldap[`${ldapCategory}SERVER_URI`]}
|
||||
/>
|
||||
<EncryptedField
|
||||
name={`${ldapCategory}BIND_PASSWORD`}
|
||||
config={ldap[`${ldapCategory}BIND_PASSWORD`]}
|
||||
/>
|
||||
<ChoiceField
|
||||
name={`${ldapCategory}GROUP_TYPE`}
|
||||
config={ldap[`${ldapCategory}GROUP_TYPE`]}
|
||||
/>
|
||||
<BooleanField
|
||||
name={`${ldapCategory}START_TLS`}
|
||||
config={ldap[`${ldapCategory}START_TLS`]}
|
||||
/>
|
||||
<FormFullWidthLayout>
|
||||
<InputField
|
||||
name={`${ldapCategory}BIND_DN`}
|
||||
config={ldap[`${ldapCategory}BIND_DN`]}
|
||||
/>
|
||||
<InputField
|
||||
name={`${ldapCategory}USER_DN_TEMPLATE`}
|
||||
config={ldap[`${ldapCategory}USER_DN_TEMPLATE`]}
|
||||
/>
|
||||
<InputField
|
||||
name={`${ldapCategory}REQUIRE_GROUP`}
|
||||
config={ldap[`${ldapCategory}REQUIRE_GROUP`]}
|
||||
/>
|
||||
<InputField
|
||||
name={`${ldapCategory}DENY_GROUP`}
|
||||
config={ldap[`${ldapCategory}DENY_GROUP`]}
|
||||
/>
|
||||
</FormFullWidthLayout>
|
||||
<ObjectField
|
||||
name={`${ldapCategory}USER_SEARCH`}
|
||||
config={ldap[`${ldapCategory}USER_SEARCH`]}
|
||||
/>
|
||||
<ObjectField
|
||||
name={`${ldapCategory}GROUP_SEARCH`}
|
||||
config={ldap[`${ldapCategory}GROUP_SEARCH`]}
|
||||
/>
|
||||
<ObjectField
|
||||
name={`${ldapCategory}USER_ATTR_MAP`}
|
||||
config={ldap[`${ldapCategory}USER_ATTR_MAP`]}
|
||||
/>
|
||||
<ObjectField
|
||||
name={`${ldapCategory}GROUP_TYPE_PARAMS`}
|
||||
config={ldap[`${ldapCategory}GROUP_TYPE_PARAMS`]}
|
||||
/>
|
||||
<ObjectField
|
||||
name={`${ldapCategory}USER_FLAGS_BY_GROUP`}
|
||||
config={ldap[`${ldapCategory}USER_FLAGS_BY_GROUP`]}
|
||||
/>
|
||||
<ObjectField
|
||||
name={`${ldapCategory}ORGANIZATION_MAP`}
|
||||
config={ldap[`${ldapCategory}ORGANIZATION_MAP`]}
|
||||
/>
|
||||
<ObjectField
|
||||
name={`${ldapCategory}TEAM_MAP`}
|
||||
config={ldap[`${ldapCategory}TEAM_MAP`]}
|
||||
/>
|
||||
{submitError && <FormSubmitError error={submitError} />}
|
||||
</FormColumnLayout>
|
||||
<RevertFormActionGroup
|
||||
onCancel={handleCancel}
|
||||
onSubmit={formik.handleSubmit}
|
||||
onRevert={toggleModal}
|
||||
/>
|
||||
{isModalOpen && (
|
||||
<RevertAllAlert
|
||||
onClose={closeModal}
|
||||
onRevertAll={handleRevertAll}
|
||||
/>
|
||||
)}
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
)}
|
||||
</CardBody>
|
||||
);
|
||||
}
|
||||
|
||||
export default withI18n()(LDAPEdit);
|
||||
export default LDAPEdit;
|
||||
|
||||
@ -1,16 +1,265 @@
|
||||
import React from 'react';
|
||||
import { mountWithContexts } from '../../../../../testUtils/enzymeHelpers';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { useRouteMatch } from 'react-router-dom';
|
||||
import {
|
||||
mountWithContexts,
|
||||
waitForElement,
|
||||
} from '../../../../../testUtils/enzymeHelpers';
|
||||
import mockAllOptions from '../../shared/data.allSettingOptions.json';
|
||||
import mockLDAP from '../../shared/data.ldapSettings.json';
|
||||
import { SettingsProvider } from '../../../../contexts/Settings';
|
||||
import { SettingsAPI } from '../../../../api';
|
||||
import LDAPEdit from './LDAPEdit';
|
||||
|
||||
jest.mock('../../../../api/models/Settings');
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useRouteMatch: jest.fn(),
|
||||
}));
|
||||
SettingsAPI.readCategory.mockResolvedValue({ data: mockLDAP });
|
||||
|
||||
describe('<LDAPEdit />', () => {
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
wrapper = mountWithContexts(<LDAPEdit />);
|
||||
let history;
|
||||
|
||||
beforeEach(async () => {
|
||||
history = createMemoryHistory({
|
||||
initialEntries: ['/settings/ldap/default/edit'],
|
||||
});
|
||||
useRouteMatch.mockImplementation(() => ({
|
||||
url: '/settings/ldap/default/edit',
|
||||
path: '/settings/ldap/:category/edit',
|
||||
params: { category: 'default' },
|
||||
}));
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<SettingsProvider value={mockAllOptions.actions}>
|
||||
<LDAPEdit />
|
||||
</SettingsProvider>,
|
||||
{
|
||||
context: { router: { history } },
|
||||
}
|
||||
);
|
||||
});
|
||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('initially renders without crashing', () => {
|
||||
expect(wrapper.find('LDAPEdit').length).toBe(1);
|
||||
});
|
||||
|
||||
test('should display expected form fields', async () => {
|
||||
expect(wrapper.find('FormGroup[label="LDAP Server URI"]').length).toBe(1);
|
||||
expect(wrapper.find('FormGroup[label="LDAP Bind DN"]').length).toBe(1);
|
||||
expect(wrapper.find('FormGroup[label="LDAP Bind Password"]').length).toBe(
|
||||
1
|
||||
);
|
||||
expect(wrapper.find('FormGroup[label="LDAP User Search"]').length).toBe(1);
|
||||
expect(
|
||||
wrapper.find('FormGroup[label="LDAP User DN Template"]').length
|
||||
).toBe(1);
|
||||
expect(
|
||||
wrapper.find('FormGroup[label="LDAP User Attribute Map"]').length
|
||||
).toBe(1);
|
||||
expect(wrapper.find('FormGroup[label="LDAP Group Search"]').length).toBe(1);
|
||||
expect(wrapper.find('FormGroup[label="LDAP Group Type"]').length).toBe(1);
|
||||
expect(
|
||||
wrapper.find('FormGroup[label="LDAP Group Type Parameters"]').length
|
||||
).toBe(1);
|
||||
expect(wrapper.find('FormGroup[label="LDAP Require Group"]').length).toBe(
|
||||
1
|
||||
);
|
||||
expect(wrapper.find('FormGroup[label="LDAP Deny Group"]').length).toBe(1);
|
||||
expect(wrapper.find('FormGroup[label="LDAP Start TLS"]').length).toBe(1);
|
||||
expect(
|
||||
wrapper.find('FormGroup[label="LDAP User Flags By Group"]').length
|
||||
).toBe(1);
|
||||
expect(
|
||||
wrapper.find('FormGroup[label="LDAP Organization Map"]').length
|
||||
).toBe(1);
|
||||
expect(wrapper.find('FormGroup[label="LDAP Team Map"]').length).toBe(1);
|
||||
expect(
|
||||
wrapper.find('FormGroup[fieldId="AUTH_LDAP_SERVER_URI"]').length
|
||||
).toBe(1);
|
||||
expect(
|
||||
wrapper.find('FormGroup[fieldId="AUTH_LDAP_5_SERVER_URI"]').length
|
||||
).toBe(0);
|
||||
});
|
||||
|
||||
test('should successfully send default values to api on form revert all', async () => {
|
||||
expect(SettingsAPI.updateAll).toHaveBeenCalledTimes(0);
|
||||
expect(wrapper.find('RevertAllAlert')).toHaveLength(0);
|
||||
await act(async () => {
|
||||
wrapper
|
||||
.find('button[aria-label="Revert all to default"]')
|
||||
.invoke('onClick')();
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('RevertAllAlert')).toHaveLength(1);
|
||||
await act(async () => {
|
||||
wrapper
|
||||
.find('RevertAllAlert button[aria-label="Confirm revert all"]')
|
||||
.invoke('onClick')();
|
||||
});
|
||||
wrapper.update();
|
||||
expect(SettingsAPI.updateAll).toHaveBeenCalledTimes(1);
|
||||
expect(SettingsAPI.updateAll).toHaveBeenCalledWith({
|
||||
AUTH_LDAP_BIND_DN: '',
|
||||
AUTH_LDAP_BIND_PASSWORD: '',
|
||||
AUTH_LDAP_CONNECTION_OPTIONS: {
|
||||
OPT_NETWORK_TIMEOUT: 30,
|
||||
OPT_REFERRALS: 0,
|
||||
},
|
||||
AUTH_LDAP_DENY_GROUP: null,
|
||||
AUTH_LDAP_GROUP_SEARCH: [],
|
||||
AUTH_LDAP_GROUP_TYPE: 'MemberDNGroupType',
|
||||
AUTH_LDAP_GROUP_TYPE_PARAMS: {
|
||||
member_attr: 'member',
|
||||
name_attr: 'cn',
|
||||
},
|
||||
AUTH_LDAP_ORGANIZATION_MAP: {},
|
||||
AUTH_LDAP_REQUIRE_GROUP: null,
|
||||
AUTH_LDAP_SERVER_URI: '',
|
||||
AUTH_LDAP_START_TLS: false,
|
||||
AUTH_LDAP_TEAM_MAP: {},
|
||||
AUTH_LDAP_USER_ATTR_MAP: {},
|
||||
AUTH_LDAP_USER_DN_TEMPLATE: null,
|
||||
AUTH_LDAP_USER_FLAGS_BY_GROUP: {},
|
||||
AUTH_LDAP_USER_SEARCH: [],
|
||||
});
|
||||
});
|
||||
|
||||
test('should successfully send request to api on form submission', async () => {
|
||||
act(() => {
|
||||
wrapper
|
||||
.find(
|
||||
'FormGroup[fieldId="AUTH_LDAP_BIND_PASSWORD"] button[aria-label="Revert"]'
|
||||
)
|
||||
.invoke('onClick')();
|
||||
wrapper
|
||||
.find(
|
||||
'FormGroup[fieldId="AUTH_LDAP_BIND_DN"] button[aria-label="Revert"]'
|
||||
)
|
||||
.invoke('onClick')();
|
||||
wrapper.find('input#AUTH_LDAP_SERVER_URI').simulate('change', {
|
||||
target: {
|
||||
value: 'ldap://mock.example.com',
|
||||
name: 'AUTH_LDAP_SERVER_URI',
|
||||
},
|
||||
});
|
||||
wrapper.find('CodeMirrorInput#AUTH_LDAP_TEAM_MAP').invoke('onChange')(
|
||||
'{\n"LDAP Sales":{\n"organization":\n"mock org"\n}\n}'
|
||||
);
|
||||
});
|
||||
wrapper.update();
|
||||
await act(async () => {
|
||||
wrapper.find('Form').invoke('onSubmit')();
|
||||
});
|
||||
expect(SettingsAPI.updateAll).toHaveBeenCalledTimes(1);
|
||||
expect(SettingsAPI.updateAll).toHaveBeenCalledWith({
|
||||
AUTH_LDAP_BIND_DN: '',
|
||||
AUTH_LDAP_BIND_PASSWORD: '',
|
||||
AUTH_LDAP_DENY_GROUP: '',
|
||||
AUTH_LDAP_GROUP_SEARCH: [],
|
||||
AUTH_LDAP_GROUP_TYPE: 'MemberDNGroupType',
|
||||
AUTH_LDAP_GROUP_TYPE_PARAMS: { name_attr: 'cn', member_attr: 'member' },
|
||||
AUTH_LDAP_ORGANIZATION_MAP: {},
|
||||
AUTH_LDAP_REQUIRE_GROUP: 'CN=Tower Users,OU=Users,DC=example,DC=com',
|
||||
AUTH_LDAP_SERVER_URI: 'ldap://mock.example.com',
|
||||
AUTH_LDAP_START_TLS: false,
|
||||
AUTH_LDAP_USER_ATTR_MAP: {},
|
||||
AUTH_LDAP_USER_DN_TEMPLATE: 'uid=%(user)s,OU=Users,DC=example,DC=com',
|
||||
AUTH_LDAP_USER_FLAGS_BY_GROUP: {},
|
||||
AUTH_LDAP_USER_SEARCH: [],
|
||||
AUTH_LDAP_TEAM_MAP: {
|
||||
'LDAP Sales': {
|
||||
organization: 'mock org',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should navigate to ldap default detail on successful submission', async () => {
|
||||
await act(async () => {
|
||||
wrapper.find('Form').invoke('onSubmit')();
|
||||
});
|
||||
expect(history.location.pathname).toEqual('/settings/ldap/default/details');
|
||||
});
|
||||
|
||||
test('should navigate to ldap default detail when cancel is clicked', async () => {
|
||||
await act(async () => {
|
||||
wrapper.find('button[aria-label="Cancel"]').invoke('onClick')();
|
||||
});
|
||||
expect(history.location.pathname).toEqual('/settings/ldap/default/details');
|
||||
});
|
||||
|
||||
test('should display error message on unsuccessful submission', async () => {
|
||||
const error = {
|
||||
response: {
|
||||
data: { detail: 'An error occurred' },
|
||||
},
|
||||
};
|
||||
SettingsAPI.updateAll.mockImplementation(() => Promise.reject(error));
|
||||
expect(wrapper.find('FormSubmitError').length).toBe(0);
|
||||
expect(SettingsAPI.updateAll).toHaveBeenCalledTimes(0);
|
||||
await act(async () => {
|
||||
wrapper.find('Form').invoke('onSubmit')();
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('FormSubmitError').length).toBe(1);
|
||||
expect(SettingsAPI.updateAll).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('should display ContentError on throw', async () => {
|
||||
SettingsAPI.readCategory.mockImplementationOnce(() =>
|
||||
Promise.reject(new Error())
|
||||
);
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<SettingsProvider value={mockAllOptions.actions}>
|
||||
<LDAPEdit />
|
||||
</SettingsProvider>
|
||||
);
|
||||
});
|
||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||
expect(wrapper.find('ContentError').length).toBe(1);
|
||||
});
|
||||
|
||||
test('should display ldap category 5 edit form', async () => {
|
||||
history = createMemoryHistory({
|
||||
initialEntries: ['/settings/ldap/5/edit'],
|
||||
});
|
||||
useRouteMatch.mockImplementation(() => ({
|
||||
url: '/settings/ldap/5/edit',
|
||||
path: '/settings/ldap/:category/edit',
|
||||
params: { category: '5' },
|
||||
}));
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<SettingsProvider value={mockAllOptions.actions}>
|
||||
<LDAPEdit />
|
||||
</SettingsProvider>,
|
||||
{
|
||||
context: { router: { history } },
|
||||
}
|
||||
);
|
||||
});
|
||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||
expect(
|
||||
wrapper.find('FormGroup[fieldId="AUTH_LDAP_SERVER_URI"]').length
|
||||
).toBe(0);
|
||||
expect(
|
||||
wrapper.find('FormGroup[fieldId="AUTH_LDAP_5_SERVER_URI"]').length
|
||||
).toBe(1);
|
||||
expect(
|
||||
wrapper.find('FormGroup[fieldId="AUTH_LDAP_5_SERVER_URI"] input').props()
|
||||
.value
|
||||
).toEqual('ldap://ldap5.example.com');
|
||||
});
|
||||
});
|
||||
|
||||
@ -17,10 +17,10 @@ import { FormFullWidthLayout } from '../../../components/FormLayout';
|
||||
import Popover from '../../../components/Popover';
|
||||
import {
|
||||
combine,
|
||||
required,
|
||||
url,
|
||||
integer,
|
||||
minMaxValue,
|
||||
required,
|
||||
url,
|
||||
} from '../../../util/validators';
|
||||
import RevertButton from './RevertButton';
|
||||
|
||||
@ -51,6 +51,7 @@ const SettingGroup = withI18n()(
|
||||
isRequired={isRequired}
|
||||
label={label}
|
||||
validated={validated}
|
||||
id={fieldId}
|
||||
labelIcon={
|
||||
<>
|
||||
<Popover
|
||||
@ -84,13 +85,13 @@ const BooleanField = withI18n()(
|
||||
>
|
||||
<Switch
|
||||
id={name}
|
||||
ouiaId={name}
|
||||
isChecked={field.value}
|
||||
isDisabled={disabled}
|
||||
label={i18n._(t`On`)}
|
||||
labelOff={i18n._(t`Off`)}
|
||||
onChange={checked => helpers.setValue(checked)}
|
||||
aria-label={ariaLabel || config.label}
|
||||
ouiaId={ariaLabel || config.label}
|
||||
/>
|
||||
</SettingGroup>
|
||||
) : null;
|
||||
@ -242,11 +243,13 @@ const ObjectField = withI18n()(({ i18n, name, config, isRequired = false }) => {
|
||||
>
|
||||
<CodeMirrorInput
|
||||
{...field}
|
||||
fullHeight
|
||||
id={name}
|
||||
mode="javascript"
|
||||
onChange={value => {
|
||||
helpers.setValue(value);
|
||||
}}
|
||||
mode="javascript"
|
||||
placeholder={JSON.stringify(config?.placeholder, null, 2)}
|
||||
/>
|
||||
</SettingGroup>
|
||||
</FormFullWidthLayout>
|
||||
|
||||
@ -109,7 +109,7 @@
|
||||
"AUTH_LDAP_4_USER_FLAGS_BY_GROUP": {},
|
||||
"AUTH_LDAP_4_ORGANIZATION_MAP": {},
|
||||
"AUTH_LDAP_4_TEAM_MAP": {},
|
||||
"AUTH_LDAP_5_SERVER_URI": "",
|
||||
"AUTH_LDAP_5_SERVER_URI": "ldap://ldap5.example.com",
|
||||
"AUTH_LDAP_5_BIND_DN": "",
|
||||
"AUTH_LDAP_5_BIND_PASSWORD": "",
|
||||
"AUTH_LDAP_5_START_TLS": false,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user