diff --git a/awx/ui_next/src/screens/Application/ApplicationAdd/ApplicationAdd.jsx b/awx/ui_next/src/screens/Application/ApplicationAdd/ApplicationAdd.jsx
index 0537fa813c..34f40645d7 100644
--- a/awx/ui_next/src/screens/Application/ApplicationAdd/ApplicationAdd.jsx
+++ b/awx/ui_next/src/screens/Application/ApplicationAdd/ApplicationAdd.jsx
@@ -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);
}
diff --git a/awx/ui_next/src/screens/Application/ApplicationAdd/ApplicationAdd.test.jsx b/awx/ui_next/src/screens/Application/ApplicationAdd/ApplicationAdd.test.jsx
index 2bc0eba47e..dd480e8ab9 100644
--- a/awx/ui_next/src/screens/Application/ApplicationAdd/ApplicationAdd.test.jsx
+++ b/awx/ui_next/src/screens/Application/ApplicationAdd/ApplicationAdd.test.jsx
@@ -39,12 +39,16 @@ const options = {
},
};
+const onSuccessfulAdd = jest.fn();
+
describe('', () => {
let wrapper;
test('should render properly', async () => {
ApplicationsAPI.readOptions.mockResolvedValue(options);
await act(async () => {
- wrapper = mountWithContexts();
+ wrapper = mountWithContexts(
+
+ );
});
expect(wrapper.find('ApplicationAdd').length).toBe(1);
expect(wrapper.find('ApplicationForm').length).toBe(1);
@@ -59,9 +63,12 @@ describe('', () => {
ApplicationsAPI.create.mockResolvedValue({ data: { id: 8 } });
await act(async () => {
- wrapper = mountWithContexts(, {
- context: { router: { history } },
- });
+ wrapper = mountWithContexts(
+ ,
+ {
+ context: { router: { history } },
+ }
+ );
});
await act(async () => {
@@ -124,6 +131,7 @@ describe('', () => {
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('', () => {
ApplicationsAPI.create.mockResolvedValue({ data: { id: 8 } });
await act(async () => {
- wrapper = mountWithContexts(, {
- context: { router: { history } },
- });
+ wrapper = mountWithContexts(
+ ,
+ {
+ context: { router: { history } },
+ }
+ );
});
await act(async () => {
wrapper.find('Button[aria-label="Cancel"]').prop('onClick')();
@@ -157,7 +168,9 @@ describe('', () => {
ApplicationsAPI.create.mockRejectedValue(error);
ApplicationsAPI.readOptions.mockResolvedValue(options);
await act(async () => {
- wrapper = mountWithContexts();
+ wrapper = mountWithContexts(
+
+ );
});
await act(async () => {
wrapper.find('Formik').prop('onSubmit')({
@@ -181,7 +194,9 @@ describe('', () => {
})
);
await act(async () => {
- wrapper = mountWithContexts();
+ wrapper = mountWithContexts(
+
+ );
});
wrapper.update();
diff --git a/awx/ui_next/src/screens/Application/ApplicationDetails/ApplicationDetails.jsx b/awx/ui_next/src/screens/Application/ApplicationDetails/ApplicationDetails.jsx
index e6874b65a5..54ab2bdf24 100644
--- a/awx/ui_next/src/screens/Application/ApplicationDetails/ApplicationDetails.jsx
+++ b/awx/ui_next/src/screens/Application/ApplicationDetails/ApplicationDetails.jsx
@@ -80,6 +80,7 @@ function ApplicationDetails({
application.authorization_grant_type
)}
/>
+
', () => {
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'
);
diff --git a/awx/ui_next/src/screens/Application/ApplicationEdit/ApplicationEdit.jsx b/awx/ui_next/src/screens/Application/ApplicationEdit/ApplicationEdit.jsx
index 18268ba63a..13558bd2a0 100644
--- a/awx/ui_next/src/screens/Application/ApplicationEdit/ApplicationEdit.jsx
+++ b/awx/ui_next/src/screens/Application/ApplicationEdit/ApplicationEdit.jsx
@@ -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 (
- <>
-
-
-
-
-
-
-
- >
+
+
+
+
+
);
}
export default ApplicationEdit;
diff --git a/awx/ui_next/src/screens/Application/Applications.jsx b/awx/ui_next/src/screens/Application/Applications.jsx
index 1842e5bd89..91b5c9a024 100644
--- a/awx/ui_next/src/screens/Application/Applications.jsx
+++ b/awx/ui_next/src/screens/Application/Applications.jsx
@@ -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 }) {
-
+ setApplicationModalSource(app)}
+ />
@@ -45,6 +53,48 @@ function Applications({ i18n }) {
+ {applicationModalSource && (
+ setApplicationModalSource(null)}
+ >
+
+
+ {applicationModalSource.client_id && (
+
+ {applicationModalSource.client_id}
+
+ }
+ />
+ )}
+ {applicationModalSource.client_secret && (
+
+ {applicationModalSource.client_secret}
+
+ }
+ />
+ )}
+
+
+ )}
>
);
}
diff --git a/awx/ui_next/src/screens/Application/Applications.test.jsx b/awx/ui_next/src/screens/Application/Applications.test.jsx
index f309a2b60a..bb75e55deb 100644
--- a/awx/ui_next/src/screens/Application/Applications.test.jsx
+++ b/awx/ui_next/src/screens/Application/Applications.test.jsx
@@ -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('', () => {
- let pageWrapper;
- let pageSections;
-
- beforeEach(() => {
- pageWrapper = mountWithContexts();
- 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();
+ 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(, {
+ 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
+ );
+ });
});