mirror of
https://github.com/ansible/awx.git
synced 2026-01-24 07:51:23 -03:30
Show client id/secret in modal after successful application add
This commit is contained in:
parent
be08e0ce69
commit
957ab9bf7c
@ -8,7 +8,7 @@ import ApplicationForm from '../shared/ApplicationForm';
|
||||
import { ApplicationsAPI } from '../../../api';
|
||||
import { CardBody } from '../../../components/Card';
|
||||
|
||||
function ApplicationAdd() {
|
||||
function ApplicationAdd({ onSuccessfulAdd }) {
|
||||
const history = useHistory();
|
||||
const [submitError, setSubmitError] = useState(null);
|
||||
|
||||
@ -53,10 +53,9 @@ function ApplicationAdd() {
|
||||
const handleSubmit = async ({ ...values }) => {
|
||||
values.organization = values.organization.id;
|
||||
try {
|
||||
const {
|
||||
data: { id },
|
||||
} = await ApplicationsAPI.create(values);
|
||||
history.push(`/applications/${id}/details`);
|
||||
const { data } = await ApplicationsAPI.create(values);
|
||||
onSuccessfulAdd(data);
|
||||
history.push(`/applications/${data.id}/details`);
|
||||
} catch (err) {
|
||||
setSubmitError(err);
|
||||
}
|
||||
|
||||
@ -39,12 +39,16 @@ const options = {
|
||||
},
|
||||
};
|
||||
|
||||
const onSuccessfulAdd = jest.fn();
|
||||
|
||||
describe('<ApplicationAdd/>', () => {
|
||||
let wrapper;
|
||||
test('should render properly', async () => {
|
||||
ApplicationsAPI.readOptions.mockResolvedValue(options);
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<ApplicationAdd />);
|
||||
wrapper = mountWithContexts(
|
||||
<ApplicationAdd onSuccessfulAdd={onSuccessfulAdd} />
|
||||
);
|
||||
});
|
||||
expect(wrapper.find('ApplicationAdd').length).toBe(1);
|
||||
expect(wrapper.find('ApplicationForm').length).toBe(1);
|
||||
@ -59,9 +63,12 @@ describe('<ApplicationAdd/>', () => {
|
||||
|
||||
ApplicationsAPI.create.mockResolvedValue({ data: { id: 8 } });
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<ApplicationAdd />, {
|
||||
context: { router: { history } },
|
||||
});
|
||||
wrapper = mountWithContexts(
|
||||
<ApplicationAdd onSuccessfulAdd={onSuccessfulAdd} />,
|
||||
{
|
||||
context: { router: { history } },
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
@ -124,6 +131,7 @@ describe('<ApplicationAdd/>', () => {
|
||||
redirect_uris: 'http://www.google.com',
|
||||
});
|
||||
expect(history.location.pathname).toBe('/applications/8/details');
|
||||
expect(onSuccessfulAdd).toHaveBeenCalledWith({ id: 8 });
|
||||
});
|
||||
|
||||
test('should cancel form properly', async () => {
|
||||
@ -134,9 +142,12 @@ describe('<ApplicationAdd/>', () => {
|
||||
|
||||
ApplicationsAPI.create.mockResolvedValue({ data: { id: 8 } });
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<ApplicationAdd />, {
|
||||
context: { router: { history } },
|
||||
});
|
||||
wrapper = mountWithContexts(
|
||||
<ApplicationAdd onSuccessfulAdd={onSuccessfulAdd} />,
|
||||
{
|
||||
context: { router: { history } },
|
||||
}
|
||||
);
|
||||
});
|
||||
await act(async () => {
|
||||
wrapper.find('Button[aria-label="Cancel"]').prop('onClick')();
|
||||
@ -157,7 +168,9 @@ describe('<ApplicationAdd/>', () => {
|
||||
ApplicationsAPI.create.mockRejectedValue(error);
|
||||
ApplicationsAPI.readOptions.mockResolvedValue(options);
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<ApplicationAdd />);
|
||||
wrapper = mountWithContexts(
|
||||
<ApplicationAdd onSuccessfulAdd={onSuccessfulAdd} />
|
||||
);
|
||||
});
|
||||
await act(async () => {
|
||||
wrapper.find('Formik').prop('onSubmit')({
|
||||
@ -181,7 +194,9 @@ describe('<ApplicationAdd/>', () => {
|
||||
})
|
||||
);
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<ApplicationAdd />);
|
||||
wrapper = mountWithContexts(
|
||||
<ApplicationAdd onSuccessfulAdd={onSuccessfulAdd} />
|
||||
);
|
||||
});
|
||||
|
||||
wrapper.update();
|
||||
|
||||
@ -80,6 +80,7 @@ function ApplicationDetails({
|
||||
application.authorization_grant_type
|
||||
)}
|
||||
/>
|
||||
<Detail label={i18n._(t`Client ID`)} value={application.client_id} />
|
||||
<Detail
|
||||
label={i18n._(t`Redirect uris`)}
|
||||
value={application.redirect_uris}
|
||||
|
||||
@ -120,6 +120,9 @@ describe('<ApplicationDetails/>', () => {
|
||||
expect(wrapper.find('Detail[label="Client type"]').prop('value')).toBe(
|
||||
'Confidential'
|
||||
);
|
||||
expect(wrapper.find('Detail[label="Client ID"]').prop('value')).toBe(
|
||||
'b1dmj8xzkbFm1ZQ27ygw2ZeE9I0AXqqeL74fiyk4'
|
||||
);
|
||||
expect(wrapper.find('Button[aria-label="Edit"]').prop('to')).toBe(
|
||||
'/applications/10/edit'
|
||||
);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import { Card } from '@patternfly/react-core';
|
||||
import ApplicationForm from '../shared/ApplicationForm';
|
||||
import { ApplicationsAPI } from '../../../api';
|
||||
import { CardBody } from '../../../components/Card';
|
||||
@ -29,22 +29,18 @@ function ApplicationEdit({
|
||||
history.push(`/applications/${id}/details`);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<PageSection>
|
||||
<Card>
|
||||
<CardBody>
|
||||
<ApplicationForm
|
||||
onSubmit={handleSubmit}
|
||||
application={application}
|
||||
onCancel={handleCancel}
|
||||
authorizationOptions={authorizationOptions}
|
||||
clientTypeOptions={clientTypeOptions}
|
||||
submitError={submitError}
|
||||
/>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</PageSection>
|
||||
</>
|
||||
<Card>
|
||||
<CardBody>
|
||||
<ApplicationForm
|
||||
onSubmit={handleSubmit}
|
||||
application={application}
|
||||
onCancel={handleCancel}
|
||||
authorizationOptions={authorizationOptions}
|
||||
clientTypeOptions={clientTypeOptions}
|
||||
submitError={submitError}
|
||||
/>
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
export default ApplicationEdit;
|
||||
|
||||
@ -2,13 +2,19 @@ import React, { useState, useCallback } from 'react';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
ClipboardCopy,
|
||||
ClipboardCopyVariant,
|
||||
Modal,
|
||||
} from '@patternfly/react-core';
|
||||
import ApplicationsList from './ApplicationsList';
|
||||
import ApplicationAdd from './ApplicationAdd';
|
||||
import Application from './Application';
|
||||
import Breadcrumbs from '../../components/Breadcrumbs';
|
||||
import { Detail, DetailList } from '../../components/DetailList';
|
||||
|
||||
function Applications({ i18n }) {
|
||||
const [applicationModalSource, setApplicationModalSource] = useState(null);
|
||||
const [breadcrumbConfig, setBreadcrumbConfig] = useState({
|
||||
'/applications': i18n._(t`Applications`),
|
||||
'/applications/add': i18n._(t`Create New Application`),
|
||||
@ -36,7 +42,9 @@ function Applications({ i18n }) {
|
||||
<Breadcrumbs breadcrumbConfig={breadcrumbConfig} />
|
||||
<Switch>
|
||||
<Route path="/applications/add">
|
||||
<ApplicationAdd />
|
||||
<ApplicationAdd
|
||||
onSuccessfulAdd={app => setApplicationModalSource(app)}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="/applications/:id">
|
||||
<Application setBreadcrumb={buildBreadcrumbConfig} />
|
||||
@ -45,6 +53,48 @@ function Applications({ i18n }) {
|
||||
<ApplicationsList />
|
||||
</Route>
|
||||
</Switch>
|
||||
{applicationModalSource && (
|
||||
<Modal
|
||||
aria-label={i18n._(t`Application information`)}
|
||||
isOpen
|
||||
variant="medium"
|
||||
title={i18n._(t`Application information`)}
|
||||
onClose={() => setApplicationModalSource(null)}
|
||||
>
|
||||
<DetailList stacked>
|
||||
<Detail
|
||||
label={i18n._(t`Name`)}
|
||||
value={applicationModalSource.name}
|
||||
/>
|
||||
{applicationModalSource.client_id && (
|
||||
<Detail
|
||||
label={i18n._(t`Client ID`)}
|
||||
value={
|
||||
<ClipboardCopy
|
||||
isReadOnly
|
||||
variant={ClipboardCopyVariant.expansion}
|
||||
>
|
||||
{applicationModalSource.client_id}
|
||||
</ClipboardCopy>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{applicationModalSource.client_secret && (
|
||||
<Detail
|
||||
label={i18n._(t`Client secret`)}
|
||||
value={
|
||||
<ClipboardCopy
|
||||
isReadOnly
|
||||
variant={ClipboardCopyVariant.expansion}
|
||||
>
|
||||
{applicationModalSource.client_secret}
|
||||
</ClipboardCopy>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</DetailList>
|
||||
</Modal>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,25 +1,48 @@
|
||||
import React from 'react';
|
||||
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
|
||||
|
||||
import Applications from './Applications';
|
||||
|
||||
describe('<Applications />', () => {
|
||||
let pageWrapper;
|
||||
let pageSections;
|
||||
|
||||
beforeEach(() => {
|
||||
pageWrapper = mountWithContexts(<Applications />);
|
||||
pageSections = pageWrapper.find('PageSection');
|
||||
});
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
pageWrapper.unmount();
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('initially renders without crashing', () => {
|
||||
expect(pageWrapper.length).toBe(1);
|
||||
test('renders successfully', () => {
|
||||
wrapper = mountWithContexts(<Applications />);
|
||||
const pageSections = wrapper.find('PageSection');
|
||||
expect(wrapper.length).toBe(1);
|
||||
expect(pageSections.length).toBe(1);
|
||||
expect(pageSections.first().props().variant).toBe('light');
|
||||
});
|
||||
|
||||
test('shows Application information modal after successful creation', async () => {
|
||||
const history = createMemoryHistory({
|
||||
initialEntries: ['/applications/add'],
|
||||
});
|
||||
wrapper = mountWithContexts(<Applications />, {
|
||||
context: { router: { history } },
|
||||
});
|
||||
expect(wrapper.find('Modal[title="Application information"]').length).toBe(
|
||||
0
|
||||
);
|
||||
await act(async () => {
|
||||
wrapper
|
||||
.find('ApplicationAdd')
|
||||
.props()
|
||||
.onSuccessfulAdd({
|
||||
name: 'test',
|
||||
client_id: 'foobar',
|
||||
client_secret: 'aaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
});
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('Modal[title="Application information"]').length).toBe(
|
||||
1
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user