mirror of
https://github.com/ansible/awx.git
synced 2026-03-18 09:27:31 -02:30
Merge pull request #6335 from AlexSCorey/6316-TemplateUsesFunction
Moves template.jsx over to a functional component. Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
@@ -1,8 +1,18 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { useEffect, useCallback } from 'react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { Card, CardActions, PageSection } from '@patternfly/react-core';
|
import { Card, CardActions, PageSection } from '@patternfly/react-core';
|
||||||
import { Switch, Route, Redirect, withRouter, Link } from 'react-router-dom';
|
import {
|
||||||
|
Switch,
|
||||||
|
Route,
|
||||||
|
Redirect,
|
||||||
|
withRouter,
|
||||||
|
Link,
|
||||||
|
useLocation,
|
||||||
|
useParams,
|
||||||
|
useRouteMatch,
|
||||||
|
} from 'react-router-dom';
|
||||||
|
import useRequest from '@util/useRequest';
|
||||||
|
|
||||||
import { TabbedCardHeader } from '@components/Card';
|
import { TabbedCardHeader } from '@components/Card';
|
||||||
import CardCloseButton from '@components/CardCloseButton';
|
import CardCloseButton from '@components/CardCloseButton';
|
||||||
@@ -17,261 +27,195 @@ import JobTemplateEdit from './JobTemplateEdit';
|
|||||||
import { JobTemplatesAPI, OrganizationsAPI } from '@api';
|
import { JobTemplatesAPI, OrganizationsAPI } from '@api';
|
||||||
import TemplateSurvey from './TemplateSurvey';
|
import TemplateSurvey from './TemplateSurvey';
|
||||||
|
|
||||||
class Template extends Component {
|
function Template({ i18n, me, setBreadcrumb }) {
|
||||||
constructor(props) {
|
const location = useLocation();
|
||||||
super(props);
|
const { id: templateId } = useParams();
|
||||||
|
const match = useRouteMatch();
|
||||||
|
|
||||||
this.state = {
|
const {
|
||||||
contentError: null,
|
result: { isNotifAdmin, template },
|
||||||
hasContentLoading: true,
|
isLoading: hasRolesandTemplateLoading,
|
||||||
template: null,
|
error: rolesAndTemplateError,
|
||||||
isNotifAdmin: false,
|
request: loadTemplateAndRoles,
|
||||||
};
|
} = useRequest(
|
||||||
this.loadTemplate = this.loadTemplate.bind(this);
|
useCallback(async () => {
|
||||||
this.loadTemplateAndRoles = this.loadTemplateAndRoles.bind(this);
|
|
||||||
this.loadSchedules = this.loadSchedules.bind(this);
|
|
||||||
this.loadScheduleOptions = this.loadScheduleOptions.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
async componentDidMount() {
|
|
||||||
await this.loadTemplateAndRoles();
|
|
||||||
}
|
|
||||||
|
|
||||||
async componentDidUpdate(prevProps) {
|
|
||||||
const { location } = this.props;
|
|
||||||
if (location !== prevProps.location) {
|
|
||||||
await this.loadTemplate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadTemplateAndRoles() {
|
|
||||||
const { match, setBreadcrumb } = this.props;
|
|
||||||
const id = parseInt(match.params.id, 10);
|
|
||||||
|
|
||||||
this.setState({ contentError: null, hasContentLoading: true });
|
|
||||||
try {
|
|
||||||
const [{ data }, notifAdminRes] = await Promise.all([
|
const [{ data }, notifAdminRes] = await Promise.all([
|
||||||
JobTemplatesAPI.readDetail(id),
|
JobTemplatesAPI.readDetail(templateId),
|
||||||
OrganizationsAPI.read({
|
OrganizationsAPI.read({
|
||||||
page_size: 1,
|
page_size: 1,
|
||||||
role_level: 'notification_admin_role',
|
role_level: 'notification_admin_role',
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
setBreadcrumb(data);
|
setBreadcrumb(data);
|
||||||
this.setState({
|
|
||||||
|
return {
|
||||||
template: data,
|
template: data,
|
||||||
isNotifAdmin: notifAdminRes.data.results.length > 0,
|
isNotifAdmin: notifAdminRes.data.results.length > 0,
|
||||||
});
|
};
|
||||||
} catch (err) {
|
}, [setBreadcrumb, templateId]),
|
||||||
this.setState({ contentError: err });
|
{ isNotifAdmin: false, template: null }
|
||||||
} finally {
|
);
|
||||||
this.setState({ hasContentLoading: false });
|
useEffect(() => {
|
||||||
}
|
loadTemplateAndRoles();
|
||||||
}
|
}, [loadTemplateAndRoles]);
|
||||||
|
|
||||||
async loadTemplate() {
|
const loadScheduleOptions = () => {
|
||||||
const { setBreadcrumb, match } = this.props;
|
return JobTemplatesAPI.readScheduleOptions(templateId);
|
||||||
const { id } = match.params;
|
};
|
||||||
|
|
||||||
this.setState({ contentError: null, hasContentLoading: true });
|
const loadSchedules = params => {
|
||||||
try {
|
return JobTemplatesAPI.readSchedules(templateId, params);
|
||||||
const { data } = await JobTemplatesAPI.readDetail(id);
|
};
|
||||||
setBreadcrumb(data);
|
|
||||||
this.setState({ template: data });
|
|
||||||
} catch (err) {
|
|
||||||
this.setState({ contentError: err });
|
|
||||||
} finally {
|
|
||||||
this.setState({ hasContentLoading: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loadScheduleOptions() {
|
const canSeeNotificationsTab = me.is_system_auditor || isNotifAdmin;
|
||||||
const { template } = this.state;
|
|
||||||
return JobTemplatesAPI.readScheduleOptions(template.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
loadSchedules(params) {
|
const tabsArray = [
|
||||||
const { template } = this.state;
|
{ name: i18n._(t`Details`), link: `${match.url}/details` },
|
||||||
return JobTemplatesAPI.readSchedules(template.id, params);
|
{ name: i18n._(t`Access`), link: `${match.url}/access` },
|
||||||
}
|
];
|
||||||
|
|
||||||
render() {
|
if (canSeeNotificationsTab) {
|
||||||
const { i18n, location, match, me, setBreadcrumb } = this.props;
|
tabsArray.push({
|
||||||
const {
|
name: i18n._(t`Notifications`),
|
||||||
contentError,
|
link: `${match.url}/notifications`,
|
||||||
hasContentLoading,
|
|
||||||
isNotifAdmin,
|
|
||||||
template,
|
|
||||||
} = this.state;
|
|
||||||
|
|
||||||
const canSeeNotificationsTab = me.is_system_auditor || isNotifAdmin;
|
|
||||||
|
|
||||||
const tabsArray = [
|
|
||||||
{ name: i18n._(t`Details`), link: `${match.url}/details` },
|
|
||||||
{ name: i18n._(t`Access`), link: `${match.url}/access` },
|
|
||||||
];
|
|
||||||
|
|
||||||
if (canSeeNotificationsTab) {
|
|
||||||
tabsArray.push({
|
|
||||||
name: i18n._(t`Notifications`),
|
|
||||||
link: `${match.url}/notifications`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (template) {
|
|
||||||
tabsArray.push({
|
|
||||||
name: i18n._(t`Schedules`),
|
|
||||||
link: `${match.url}/schedules`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
tabsArray.push(
|
|
||||||
{
|
|
||||||
name: i18n._(t`Completed Jobs`),
|
|
||||||
link: `${match.url}/completed_jobs`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: i18n._(t`Survey`),
|
|
||||||
link: `${match.url}/survey`,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
tabsArray.forEach((tab, n) => {
|
|
||||||
tab.id = n;
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let cardHeader = (
|
if (template) {
|
||||||
<TabbedCardHeader>
|
tabsArray.push({
|
||||||
<RoutedTabs tabsArray={tabsArray} />
|
name: i18n._(t`Schedules`),
|
||||||
<CardActions>
|
link: `${match.url}/schedules`,
|
||||||
<CardCloseButton linkTo="/templates" />
|
});
|
||||||
</CardActions>
|
}
|
||||||
</TabbedCardHeader>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
tabsArray.push(
|
||||||
location.pathname.endsWith('edit') ||
|
{
|
||||||
location.pathname.includes('schedules/')
|
name: i18n._(t`Completed Jobs`),
|
||||||
) {
|
link: `${match.url}/completed_jobs`,
|
||||||
cardHeader = null;
|
},
|
||||||
|
{
|
||||||
|
name: i18n._(t`Survey`),
|
||||||
|
link: `${match.url}/survey`,
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (!hasContentLoading && contentError) {
|
tabsArray.forEach((tab, n) => {
|
||||||
return (
|
tab.id = n;
|
||||||
<PageSection>
|
});
|
||||||
<Card>
|
|
||||||
<ContentError error={contentError}>
|
|
||||||
{contentError.response.status === 404 && (
|
|
||||||
<span>
|
|
||||||
{i18n._(`Template not found.`)}{' '}
|
|
||||||
<Link to="/templates">{i18n._(`View all Templates.`)}</Link>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</ContentError>
|
|
||||||
</Card>
|
|
||||||
</PageSection>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let cardHeader = (
|
||||||
|
<TabbedCardHeader>
|
||||||
|
<RoutedTabs tabsArray={tabsArray} />
|
||||||
|
<CardActions>
|
||||||
|
<CardCloseButton linkTo="/templates" />
|
||||||
|
</CardActions>
|
||||||
|
</TabbedCardHeader>
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
location.pathname.endsWith('edit') ||
|
||||||
|
location.pathname.includes('schedules/')
|
||||||
|
) {
|
||||||
|
cardHeader = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentError = rolesAndTemplateError;
|
||||||
|
if (!hasRolesandTemplateLoading && contentError) {
|
||||||
return (
|
return (
|
||||||
<PageSection>
|
<PageSection>
|
||||||
<Card>
|
<Card>
|
||||||
{cardHeader}
|
<ContentError error={contentError}>
|
||||||
<Switch>
|
{contentError.response.status === 404 && (
|
||||||
<Redirect
|
<span>
|
||||||
from="/templates/:templateType/:id"
|
{i18n._(`Template not found.`)}{' '}
|
||||||
to="/templates/:templateType/:id/details"
|
<Link to="/templates">{i18n._(`View all Templates.`)}</Link>
|
||||||
exact
|
</span>
|
||||||
/>
|
|
||||||
{template && (
|
|
||||||
<Route
|
|
||||||
key="details"
|
|
||||||
path="/templates/:templateType/:id/details"
|
|
||||||
render={() => (
|
|
||||||
<JobTemplateDetail
|
|
||||||
hasTemplateLoading={hasContentLoading}
|
|
||||||
template={template}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
{template && (
|
</ContentError>
|
||||||
<Route
|
|
||||||
key="edit"
|
|
||||||
path="/templates/:templateType/:id/edit"
|
|
||||||
render={() => <JobTemplateEdit template={template} />}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{template && (
|
|
||||||
<Route
|
|
||||||
key="access"
|
|
||||||
path="/templates/:templateType/:id/access"
|
|
||||||
render={() => (
|
|
||||||
<ResourceAccessList
|
|
||||||
resource={template}
|
|
||||||
apiModel={JobTemplatesAPI}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{template && (
|
|
||||||
<Route
|
|
||||||
key="schedules"
|
|
||||||
path="/templates/:templateType/:id/schedules"
|
|
||||||
render={() => (
|
|
||||||
<Schedules
|
|
||||||
setBreadcrumb={setBreadcrumb}
|
|
||||||
unifiedJobTemplate={template}
|
|
||||||
loadSchedules={this.loadSchedules}
|
|
||||||
loadScheduleOptions={this.loadScheduleOptions}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{canSeeNotificationsTab && (
|
|
||||||
<Route
|
|
||||||
path="/templates/:templateType/:id/notifications"
|
|
||||||
render={() => (
|
|
||||||
<NotificationList
|
|
||||||
id={Number(match.params.id)}
|
|
||||||
canToggleNotifications={isNotifAdmin}
|
|
||||||
apiModel={JobTemplatesAPI}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{template?.id && (
|
|
||||||
<Route path="/templates/:templateType/:id/completed_jobs">
|
|
||||||
<JobList defaultParams={{ job__job_template: template.id }} />
|
|
||||||
</Route>
|
|
||||||
)}
|
|
||||||
{template && (
|
|
||||||
<Route path="/templates/:templateType/:id/survey">
|
|
||||||
<TemplateSurvey template={template} />
|
|
||||||
</Route>
|
|
||||||
)}
|
|
||||||
<Route
|
|
||||||
key="not-found"
|
|
||||||
path="*"
|
|
||||||
render={() =>
|
|
||||||
!hasContentLoading && (
|
|
||||||
<ContentError isNotFound>
|
|
||||||
{match.params.id && (
|
|
||||||
<Link
|
|
||||||
to={`/templates/${match.params.templateType}/${match.params.id}/details`}
|
|
||||||
>
|
|
||||||
{i18n._(`View Template Details`)}
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</ContentError>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Switch>
|
|
||||||
</Card>
|
</Card>
|
||||||
</PageSection>
|
</PageSection>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageSection>
|
||||||
|
<Card>
|
||||||
|
{cardHeader}
|
||||||
|
<Switch>
|
||||||
|
<Redirect
|
||||||
|
from="/templates/:templateType/:id"
|
||||||
|
to="/templates/:templateType/:id/details"
|
||||||
|
exact
|
||||||
|
/>
|
||||||
|
{template && (
|
||||||
|
<Route key="details" path="/templates/:templateType/:id/details">
|
||||||
|
<JobTemplateDetail
|
||||||
|
hasTemplateLoading={hasRolesandTemplateLoading}
|
||||||
|
template={template}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
)}
|
||||||
|
{template && (
|
||||||
|
<Route key="edit" path="/templates/:templateType/:id/edit">
|
||||||
|
<JobTemplateEdit template={template} />
|
||||||
|
</Route>
|
||||||
|
)}
|
||||||
|
{template && (
|
||||||
|
<Route key="access" path="/templates/:templateType/:id/access">
|
||||||
|
<ResourceAccessList
|
||||||
|
resource={template}
|
||||||
|
apiModel={JobTemplatesAPI}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
)}
|
||||||
|
{template && (
|
||||||
|
<Route
|
||||||
|
key="schedules"
|
||||||
|
path="/templates/:templateType/:id/schedules"
|
||||||
|
>
|
||||||
|
<Schedules
|
||||||
|
setBreadcrumb={setBreadcrumb}
|
||||||
|
unifiedJobTemplate={template}
|
||||||
|
loadSchedules={loadSchedules}
|
||||||
|
loadScheduleOptions={loadScheduleOptions}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
)}
|
||||||
|
{canSeeNotificationsTab && (
|
||||||
|
<Route path="/templates/:templateType/:id/notifications">
|
||||||
|
<NotificationList
|
||||||
|
id={Number(templateId)}
|
||||||
|
canToggleNotifications={isNotifAdmin}
|
||||||
|
apiModel={JobTemplatesAPI}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
)}
|
||||||
|
{template?.id && (
|
||||||
|
<Route path="/templates/:templateType/:id/completed_jobs">
|
||||||
|
<JobList defaultParams={{ job__job_template: template.id }} />
|
||||||
|
</Route>
|
||||||
|
)}
|
||||||
|
{template && (
|
||||||
|
<Route path="/templates/:templateType/:id/survey">
|
||||||
|
<TemplateSurvey template={template} />
|
||||||
|
</Route>
|
||||||
|
)}
|
||||||
|
{!hasRolesandTemplateLoading && (
|
||||||
|
<Route key="not-found" path="*">
|
||||||
|
<ContentError isNotFound>
|
||||||
|
{match.params.id && (
|
||||||
|
<Link
|
||||||
|
to={`/templates/${match.params.templateType}/${match.params.id}/details`}
|
||||||
|
>
|
||||||
|
{i18n._(`View Template Details`)}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</ContentError>
|
||||||
|
</Route>
|
||||||
|
)}
|
||||||
|
</Switch>
|
||||||
|
</Card>
|
||||||
|
</PageSection>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Template as _Template };
|
export { Template as _Template };
|
||||||
|
|||||||
@@ -1,63 +1,57 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createMemoryHistory } from 'history';
|
import { createMemoryHistory } from 'history';
|
||||||
import { JobTemplatesAPI, OrganizationsAPI } from '@api';
|
import { JobTemplatesAPI, OrganizationsAPI } from '@api';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
|
|
||||||
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
||||||
import Template, { _Template } from './Template';
|
import Template from './Template';
|
||||||
import mockJobTemplateData from './shared/data.job_template.json';
|
import mockJobTemplateData from './shared/data.job_template.json';
|
||||||
|
|
||||||
jest.mock('@api');
|
jest.mock('@api/models/JobTemplates');
|
||||||
|
jest.mock('@api/models/Organizations');
|
||||||
JobTemplatesAPI.readDetail.mockResolvedValue({
|
|
||||||
data: mockJobTemplateData,
|
|
||||||
});
|
|
||||||
|
|
||||||
OrganizationsAPI.read.mockResolvedValue({
|
|
||||||
data: {
|
|
||||||
count: 1,
|
|
||||||
next: null,
|
|
||||||
previous: null,
|
|
||||||
results: [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const mockMe = {
|
const mockMe = {
|
||||||
is_super_user: true,
|
is_super_user: true,
|
||||||
is_system_auditor: false,
|
is_system_auditor: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('<Template />', () => {
|
describe('<Template />', () => {
|
||||||
test('initially renders succesfully', () => {
|
beforeEach(() => {
|
||||||
mountWithContexts(<Template setBreadcrumb={() => {}} me={mockMe} />);
|
JobTemplatesAPI.readDetail.mockResolvedValue({
|
||||||
|
data: mockJobTemplateData,
|
||||||
|
});
|
||||||
|
|
||||||
|
OrganizationsAPI.read.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
count: 1,
|
||||||
|
next: null,
|
||||||
|
previous: null,
|
||||||
|
results: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
test('When component mounts API is called and the response is put in state', async done => {
|
test('initially renders succesfully', async () => {
|
||||||
const loadTemplateAndRoles = jest.spyOn(
|
await act(async () => {
|
||||||
_Template.prototype,
|
mountWithContexts(<Template setBreadcrumb={() => {}} me={mockMe} />);
|
||||||
'loadTemplateAndRoles'
|
});
|
||||||
);
|
});
|
||||||
const wrapper = mountWithContexts(
|
test('When component mounts API is called and the response is put in state', async () => {
|
||||||
<Template setBreadcrumb={() => {}} me={mockMe} />
|
await act(async () => {
|
||||||
);
|
mountWithContexts(<Template setBreadcrumb={() => {}} me={mockMe} />);
|
||||||
await waitForElement(
|
});
|
||||||
wrapper,
|
expect(JobTemplatesAPI.readDetail).toBeCalled();
|
||||||
'Template',
|
expect(OrganizationsAPI.read).toBeCalled();
|
||||||
el => el.state('hasContentLoading') === true
|
|
||||||
);
|
|
||||||
expect(loadTemplateAndRoles).toHaveBeenCalled();
|
|
||||||
await waitForElement(
|
|
||||||
wrapper,
|
|
||||||
'Template',
|
|
||||||
el => el.state('hasContentLoading') === true
|
|
||||||
);
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
test('notifications tab shown for admins', async done => {
|
test('notifications tab shown for admins', async done => {
|
||||||
const wrapper = mountWithContexts(
|
let wrapper;
|
||||||
<Template setBreadcrumb={() => {}} me={mockMe} />
|
await act(async () => {
|
||||||
);
|
wrapper = mountWithContexts(
|
||||||
|
<Template setBreadcrumb={() => {}} me={mockMe} />
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const tabs = await waitForElement(
|
const tabs = await waitForElement(
|
||||||
wrapper,
|
wrapper,
|
||||||
@@ -77,9 +71,12 @@ describe('<Template />', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const wrapper = mountWithContexts(
|
let wrapper;
|
||||||
<Template setBreadcrumb={() => {}} me={mockMe} />
|
await act(async () => {
|
||||||
);
|
wrapper = mountWithContexts(
|
||||||
|
<Template setBreadcrumb={() => {}} me={mockMe} />
|
||||||
|
);
|
||||||
|
});
|
||||||
const tabs = await waitForElement(
|
const tabs = await waitForElement(
|
||||||
wrapper,
|
wrapper,
|
||||||
'.pf-c-tabs__item',
|
'.pf-c-tabs__item',
|
||||||
@@ -93,24 +90,28 @@ describe('<Template />', () => {
|
|||||||
const history = createMemoryHistory({
|
const history = createMemoryHistory({
|
||||||
initialEntries: ['/templates/job_template/1/foobar'],
|
initialEntries: ['/templates/job_template/1/foobar'],
|
||||||
});
|
});
|
||||||
const wrapper = mountWithContexts(
|
let wrapper;
|
||||||
<Template setBreadcrumb={() => {}} me={mockMe} />,
|
await act(async () => {
|
||||||
{
|
wrapper = mountWithContexts(
|
||||||
context: {
|
<Template setBreadcrumb={() => {}} me={mockMe} />,
|
||||||
router: {
|
{
|
||||||
history,
|
context: {
|
||||||
route: {
|
router: {
|
||||||
location: history.location,
|
history,
|
||||||
match: {
|
route: {
|
||||||
params: { id: 1 },
|
location: history.location,
|
||||||
url: '/templates/job_template/1/foobar',
|
match: {
|
||||||
path: '/templates/job_template/1/foobar',
|
params: { id: 1 },
|
||||||
|
url: '/templates/job_template/1/foobar',
|
||||||
|
path: '/templates/job_template/1/foobar',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
}
|
);
|
||||||
);
|
});
|
||||||
|
|
||||||
await waitForElement(wrapper, 'ContentError', el => el.length === 1);
|
await waitForElement(wrapper, 'ContentError', el => el.length === 1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user