mirror of
https://github.com/ansible/awx.git
synced 2026-01-12 10:30:03 -03:30
Converts NotificationList to functional component and now uses useRequest
This commit is contained in:
parent
d36999acc7
commit
d8af8baae3
@ -1,15 +1,14 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { number, shape, string, bool } from 'prop-types';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import React, { useEffect, useCallback, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { number, shape, bool } from 'prop-types';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
import AlertModal from '../AlertModal';
|
||||
import ErrorDetail from '../ErrorDetail';
|
||||
import NotificationListItem from './NotificationListItem';
|
||||
import PaginatedDataList from '../PaginatedDataList';
|
||||
import { getQSConfig, parseQueryString } from '../../util/qs';
|
||||
|
||||
import useRequest from '../../util/useRequest';
|
||||
import { NotificationTemplatesAPI } from '../../api';
|
||||
|
||||
const QS_CONFIG = getQSConfig('notification', {
|
||||
@ -18,64 +17,49 @@ const QS_CONFIG = getQSConfig('notification', {
|
||||
order_by: 'name',
|
||||
});
|
||||
|
||||
class NotificationList extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
contentError: null,
|
||||
hasContentLoading: true,
|
||||
toggleError: false,
|
||||
loadingToggleIds: [],
|
||||
itemCount: 0,
|
||||
notifications: [],
|
||||
startedTemplateIds: [],
|
||||
successTemplateIds: [],
|
||||
errorTemplateIds: [],
|
||||
typeLabels: null,
|
||||
};
|
||||
this.handleNotificationToggle = this.handleNotificationToggle.bind(this);
|
||||
this.handleNotificationErrorClose = this.handleNotificationErrorClose.bind(
|
||||
this
|
||||
);
|
||||
this.loadNotifications = this.loadNotifications.bind(this);
|
||||
}
|
||||
function NotificationList({ apiModel, canToggleNotifications, id, i18n }) {
|
||||
const location = useLocation();
|
||||
const [isToggleLoading, setIsToggleLoading] = useState(false);
|
||||
const [toggleError, setToggleError] = useState(null);
|
||||
|
||||
componentDidMount() {
|
||||
this.loadNotifications();
|
||||
}
|
||||
const {
|
||||
result: fetchNotificationsResult,
|
||||
result: {
|
||||
notifications,
|
||||
itemCount,
|
||||
startedTemplateIds,
|
||||
successTemplateIds,
|
||||
errorTemplateIds,
|
||||
typeLabels,
|
||||
},
|
||||
error: contentError,
|
||||
isLoading,
|
||||
request: fetchNotifications,
|
||||
setValue,
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
const params = parseQueryString(QS_CONFIG, location.search);
|
||||
const [
|
||||
{
|
||||
data: { results: notificationsResults, count: notificationsCount },
|
||||
},
|
||||
{
|
||||
data: { actions },
|
||||
},
|
||||
] = await Promise.all([
|
||||
NotificationTemplatesAPI.read(params),
|
||||
NotificationTemplatesAPI.readOptions(),
|
||||
]);
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { location } = this.props;
|
||||
if (location !== prevProps.location) {
|
||||
this.loadNotifications();
|
||||
}
|
||||
}
|
||||
const labels = actions.GET.notification_type.choices.reduce(
|
||||
(map, notifType) => ({ ...map, [notifType[0]]: notifType[1] }),
|
||||
{}
|
||||
);
|
||||
|
||||
async loadNotifications() {
|
||||
const { id, location, apiModel } = this.props;
|
||||
const { typeLabels } = this.state;
|
||||
const params = parseQueryString(QS_CONFIG, location.search);
|
||||
|
||||
const promises = [NotificationTemplatesAPI.read(params)];
|
||||
|
||||
if (!typeLabels) {
|
||||
promises.push(NotificationTemplatesAPI.readOptions());
|
||||
}
|
||||
|
||||
this.setState({ contentError: null, hasContentLoading: true });
|
||||
try {
|
||||
const {
|
||||
data: { count: itemCount = 0, results: notifications = [] },
|
||||
} = await NotificationTemplatesAPI.read(params);
|
||||
|
||||
const optionsResponse = await NotificationTemplatesAPI.readOptions();
|
||||
|
||||
let idMatchParams;
|
||||
if (notifications.length > 0) {
|
||||
idMatchParams = { id__in: notifications.map(n => n.id).join(',') };
|
||||
} else {
|
||||
idMatchParams = {};
|
||||
}
|
||||
const idMatchParams =
|
||||
notificationsResults.length > 0
|
||||
? { id__in: notificationsResults.map(n => n.id).join(',') }
|
||||
: {};
|
||||
|
||||
const [
|
||||
{ data: startedTemplates },
|
||||
@ -87,69 +71,35 @@ class NotificationList extends Component {
|
||||
apiModel.readNotificationTemplatesError(id, idMatchParams),
|
||||
]);
|
||||
|
||||
const stateToUpdate = {
|
||||
itemCount,
|
||||
notifications,
|
||||
return {
|
||||
notifications: notificationsResults,
|
||||
itemCount: notificationsCount,
|
||||
startedTemplateIds: startedTemplates.results.map(st => st.id),
|
||||
successTemplateIds: successTemplates.results.map(su => su.id),
|
||||
errorTemplateIds: errorTemplates.results.map(e => e.id),
|
||||
typeLabels: labels,
|
||||
};
|
||||
|
||||
if (!typeLabels) {
|
||||
const {
|
||||
data: {
|
||||
actions: {
|
||||
GET: {
|
||||
notification_type: { choices },
|
||||
},
|
||||
},
|
||||
},
|
||||
} = optionsResponse;
|
||||
// The structure of choices looks like [['slack', 'Slack'], ['email', 'Email'], ...]
|
||||
stateToUpdate.typeLabels = choices.reduce(
|
||||
(map, notifType) => ({ ...map, [notifType[0]]: notifType[1] }),
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
this.setState(stateToUpdate);
|
||||
} catch (err) {
|
||||
this.setState({ contentError: err });
|
||||
} finally {
|
||||
this.setState({ hasContentLoading: false });
|
||||
}, [apiModel, id, location]),
|
||||
{
|
||||
notifications: [],
|
||||
itemCount: 0,
|
||||
startedTemplateIds: [],
|
||||
successTemplateIds: [],
|
||||
errorTemplateIds: [],
|
||||
typeLabels: {},
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
async handleNotificationToggle(notificationId, isCurrentlyOn, status) {
|
||||
const { id, apiModel } = this.props;
|
||||
useEffect(() => {
|
||||
fetchNotifications();
|
||||
}, [fetchNotifications]);
|
||||
|
||||
let stateArrayName;
|
||||
if (status === 'success') {
|
||||
stateArrayName = 'successTemplateIds';
|
||||
} else if (status === 'error') {
|
||||
stateArrayName = 'errorTemplateIds';
|
||||
} else if (status === 'started') {
|
||||
stateArrayName = 'startedTemplateIds';
|
||||
}
|
||||
|
||||
let stateUpdateFunction;
|
||||
if (isCurrentlyOn) {
|
||||
// when switching off, remove the toggled notification id from the array
|
||||
stateUpdateFunction = prevState => ({
|
||||
[stateArrayName]: prevState[stateArrayName].filter(
|
||||
i => i !== notificationId
|
||||
),
|
||||
});
|
||||
} else {
|
||||
// when switching on, add the toggled notification id to the array
|
||||
stateUpdateFunction = prevState => ({
|
||||
[stateArrayName]: prevState[stateArrayName].concat(notificationId),
|
||||
});
|
||||
}
|
||||
|
||||
this.setState(({ loadingToggleIds }) => ({
|
||||
loadingToggleIds: loadingToggleIds.concat([notificationId]),
|
||||
}));
|
||||
const handleNotificationToggle = async (
|
||||
notificationId,
|
||||
isCurrentlyOn,
|
||||
status
|
||||
) => {
|
||||
setIsToggleLoading(true);
|
||||
try {
|
||||
if (isCurrentlyOn) {
|
||||
await apiModel.disassociateNotificationTemplate(
|
||||
@ -157,128 +107,111 @@ class NotificationList extends Component {
|
||||
notificationId,
|
||||
status
|
||||
);
|
||||
setValue({
|
||||
...fetchNotificationsResult,
|
||||
[`${status}TemplateIds`]: fetchNotificationsResult[
|
||||
`${status}TemplateIds`
|
||||
].filter(i => i !== notificationId),
|
||||
});
|
||||
} else {
|
||||
await apiModel.associateNotificationTemplate(
|
||||
id,
|
||||
notificationId,
|
||||
status
|
||||
);
|
||||
setValue({
|
||||
...fetchNotificationsResult,
|
||||
[`${status}TemplateIds`]: fetchNotificationsResult[
|
||||
`${status}TemplateIds`
|
||||
].concat(notificationId),
|
||||
});
|
||||
}
|
||||
this.setState(stateUpdateFunction);
|
||||
} catch (err) {
|
||||
this.setState({ toggleError: err });
|
||||
setToggleError(err);
|
||||
} finally {
|
||||
this.setState(({ loadingToggleIds }) => ({
|
||||
loadingToggleIds: loadingToggleIds.filter(
|
||||
item => item !== notificationId
|
||||
),
|
||||
}));
|
||||
setIsToggleLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleNotificationErrorClose() {
|
||||
this.setState({ toggleError: false });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { canToggleNotifications, i18n } = this.props;
|
||||
const {
|
||||
contentError,
|
||||
hasContentLoading,
|
||||
toggleError,
|
||||
loadingToggleIds,
|
||||
itemCount,
|
||||
notifications,
|
||||
startedTemplateIds,
|
||||
successTemplateIds,
|
||||
errorTemplateIds,
|
||||
typeLabels,
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<PaginatedDataList
|
||||
contentError={contentError}
|
||||
hasContentLoading={hasContentLoading}
|
||||
items={notifications}
|
||||
itemCount={itemCount}
|
||||
pluralizedItemName={i18n._(t`Notifications`)}
|
||||
qsConfig={QS_CONFIG}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: i18n._(t`Name`),
|
||||
key: 'name',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Type`),
|
||||
key: 'type',
|
||||
options: [
|
||||
['email', i18n._(t`Email`)],
|
||||
['grafana', i18n._(t`Grafana`)],
|
||||
['hipchat', i18n._(t`Hipchat`)],
|
||||
['irc', i18n._(t`IRC`)],
|
||||
['mattermost', i18n._(t`Mattermost`)],
|
||||
['pagerduty', i18n._(t`Pagerduty`)],
|
||||
['rocketchat', i18n._(t`Rocket.Chat`)],
|
||||
['slack', i18n._(t`Slack`)],
|
||||
['twilio', i18n._(t`Twilio`)],
|
||||
['webhook', i18n._(t`Webhook`)],
|
||||
],
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Created By (Username)`),
|
||||
key: 'created_by__username',
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Modified By (Username)`),
|
||||
key: 'modified_by__username',
|
||||
},
|
||||
]}
|
||||
toolbarSortColumns={[
|
||||
{
|
||||
name: i18n._(t`Name`),
|
||||
key: 'name',
|
||||
},
|
||||
]}
|
||||
renderItem={notification => (
|
||||
<NotificationListItem
|
||||
key={notification.id}
|
||||
notification={notification}
|
||||
detailUrl={`/notifications/${notification.id}`}
|
||||
canToggleNotifications={
|
||||
canToggleNotifications &&
|
||||
!loadingToggleIds.includes(notification.id)
|
||||
}
|
||||
toggleNotification={this.handleNotificationToggle}
|
||||
errorTurnedOn={errorTemplateIds.includes(notification.id)}
|
||||
startedTurnedOn={startedTemplateIds.includes(notification.id)}
|
||||
successTurnedOn={successTemplateIds.includes(notification.id)}
|
||||
typeLabels={typeLabels}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
return (
|
||||
<>
|
||||
<PaginatedDataList
|
||||
contentError={contentError}
|
||||
hasContentLoading={isLoading}
|
||||
items={notifications}
|
||||
itemCount={itemCount}
|
||||
pluralizedItemName={i18n._(t`Notifications`)}
|
||||
qsConfig={QS_CONFIG}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: i18n._(t`Name`),
|
||||
key: 'name',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Type`),
|
||||
key: 'type',
|
||||
options: [
|
||||
['email', i18n._(t`Email`)],
|
||||
['grafana', i18n._(t`Grafana`)],
|
||||
['hipchat', i18n._(t`Hipchat`)],
|
||||
['irc', i18n._(t`IRC`)],
|
||||
['mattermost', i18n._(t`Mattermost`)],
|
||||
['pagerduty', i18n._(t`Pagerduty`)],
|
||||
['rocketchat', i18n._(t`Rocket.Chat`)],
|
||||
['slack', i18n._(t`Slack`)],
|
||||
['twilio', i18n._(t`Twilio`)],
|
||||
['webhook', i18n._(t`Webhook`)],
|
||||
],
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Created by (username)`),
|
||||
key: 'created_by__username',
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Modified by (username)`),
|
||||
key: 'modified_by__username',
|
||||
},
|
||||
]}
|
||||
toolbarSortColumns={[
|
||||
{
|
||||
name: i18n._(t`Name`),
|
||||
key: 'name',
|
||||
},
|
||||
]}
|
||||
renderItem={notification => (
|
||||
<NotificationListItem
|
||||
key={notification.id}
|
||||
notification={notification}
|
||||
detailUrl={`/notifications/${notification.id}`}
|
||||
canToggleNotifications={canToggleNotifications && !isToggleLoading}
|
||||
toggleNotification={handleNotificationToggle}
|
||||
errorTurnedOn={errorTemplateIds.includes(notification.id)}
|
||||
startedTurnedOn={startedTemplateIds.includes(notification.id)}
|
||||
successTurnedOn={successTemplateIds.includes(notification.id)}
|
||||
typeLabels={typeLabels}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{toggleError && (
|
||||
<AlertModal
|
||||
variant="error"
|
||||
title={i18n._(t`Error!`)}
|
||||
isOpen={toggleError && loadingToggleIds.length === 0}
|
||||
onClose={this.handleNotificationErrorClose}
|
||||
isOpen={!isToggleLoading}
|
||||
onClose={() => setToggleError(null)}
|
||||
>
|
||||
{i18n._(t`Failed to toggle notification.`)}
|
||||
<ErrorDetail error={toggleError} />
|
||||
</AlertModal>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
NotificationList.propTypes = {
|
||||
apiModel: shape({}).isRequired,
|
||||
id: number.isRequired,
|
||||
canToggleNotifications: bool.isRequired,
|
||||
location: shape({
|
||||
search: string.isRequired,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
export { NotificationList as _NotificationList };
|
||||
export default withI18n()(withRouter(NotificationList));
|
||||
export default withI18n()(NotificationList);
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
import React from 'react';
|
||||
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
|
||||
import { sleep } from '../../../testUtils/testUtils';
|
||||
|
||||
import { NotificationTemplatesAPI } from '../../api';
|
||||
|
||||
import NotificationList from './NotificationList';
|
||||
|
||||
jest.mock('../../api');
|
||||
|
||||
describe('<NotificationList />', () => {
|
||||
let wrapper;
|
||||
const data = {
|
||||
count: 2,
|
||||
results: [
|
||||
@ -58,220 +56,185 @@ describe('<NotificationList />', () => {
|
||||
},
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
NotificationTemplatesAPI.read.mockReturnValue({ data });
|
||||
MockModelAPI.readNotificationTemplatesSuccess.mockReturnValue({
|
||||
data: { results: [{ id: 1 }] },
|
||||
});
|
||||
MockModelAPI.readNotificationTemplatesError.mockReturnValue({
|
||||
data: { results: [{ id: 2 }] },
|
||||
});
|
||||
MockModelAPI.readNotificationTemplatesStarted.mockReturnValue({
|
||||
data: { results: [{ id: 3 }] },
|
||||
NotificationTemplatesAPI.read.mockReturnValue({ data });
|
||||
|
||||
MockModelAPI.readNotificationTemplatesSuccess.mockReturnValue({
|
||||
data: { results: [{ id: 1 }] },
|
||||
});
|
||||
|
||||
MockModelAPI.readNotificationTemplatesError.mockReturnValue({
|
||||
data: { results: [{ id: 2 }] },
|
||||
});
|
||||
|
||||
MockModelAPI.readNotificationTemplatesStarted.mockReturnValue({
|
||||
data: { results: [{ id: 3 }] },
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<NotificationList
|
||||
id={1}
|
||||
canToggleNotifications
|
||||
apiModel={MockModelAPI}
|
||||
/>
|
||||
);
|
||||
});
|
||||
wrapper.update();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('initially renders succesfully', async () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<NotificationList id={1} canToggleNotifications apiModel={MockModelAPI} />
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
const dataList = wrapper.find('PaginatedDataList');
|
||||
expect(dataList).toHaveLength(1);
|
||||
expect(dataList.prop('items')).toEqual(data.results);
|
||||
test('initially renders succesfully', () => {
|
||||
expect(wrapper.find('PaginatedDataList')).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('should render list fetched of items', async () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<NotificationList id={1} canToggleNotifications apiModel={MockModelAPI} />
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
|
||||
test('should render list fetched of items', () => {
|
||||
expect(NotificationTemplatesAPI.read).toHaveBeenCalled();
|
||||
expect(wrapper.find('NotificationList').state('notifications')).toEqual(
|
||||
data.results
|
||||
);
|
||||
const items = wrapper.find('NotificationListItem');
|
||||
expect(items).toHaveLength(3);
|
||||
expect(items.at(0).prop('successTurnedOn')).toEqual(true);
|
||||
expect(items.at(0).prop('errorTurnedOn')).toEqual(false);
|
||||
expect(items.at(0).prop('startedTurnedOn')).toEqual(false);
|
||||
expect(items.at(1).prop('successTurnedOn')).toEqual(false);
|
||||
expect(items.at(1).prop('errorTurnedOn')).toEqual(true);
|
||||
expect(items.at(1).prop('startedTurnedOn')).toEqual(false);
|
||||
expect(items.at(2).prop('successTurnedOn')).toEqual(false);
|
||||
expect(items.at(2).prop('errorTurnedOn')).toEqual(false);
|
||||
expect(items.at(2).prop('startedTurnedOn')).toEqual(true);
|
||||
expect(NotificationTemplatesAPI.readOptions).toHaveBeenCalled();
|
||||
expect(MockModelAPI.readNotificationTemplatesSuccess).toHaveBeenCalled();
|
||||
expect(MockModelAPI.readNotificationTemplatesError).toHaveBeenCalled();
|
||||
expect(MockModelAPI.readNotificationTemplatesStarted).toHaveBeenCalled();
|
||||
expect(wrapper.find('NotificationListItem').length).toBe(3);
|
||||
expect(
|
||||
wrapper.find('input#notification-1-success-toggle').props().checked
|
||||
).toBe(true);
|
||||
expect(
|
||||
wrapper.find('input#notification-1-error-toggle').props().checked
|
||||
).toBe(false);
|
||||
expect(
|
||||
wrapper.find('input#notification-1-started-toggle').props().checked
|
||||
).toBe(false);
|
||||
expect(
|
||||
wrapper.find('input#notification-2-success-toggle').props().checked
|
||||
).toBe(false);
|
||||
expect(
|
||||
wrapper.find('input#notification-2-error-toggle').props().checked
|
||||
).toBe(true);
|
||||
expect(
|
||||
wrapper.find('input#notification-2-started-toggle').props().checked
|
||||
).toBe(false);
|
||||
expect(
|
||||
wrapper.find('input#notification-3-success-toggle').props().checked
|
||||
).toBe(false);
|
||||
expect(
|
||||
wrapper.find('input#notification-3-error-toggle').props().checked
|
||||
).toBe(false);
|
||||
expect(
|
||||
wrapper.find('input#notification-3-started-toggle').props().checked
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should enable success notification', async () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<NotificationList id={1} canToggleNotifications apiModel={MockModelAPI} />
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
wrapper.find('NotificationList').state('successTemplateIds')
|
||||
).toEqual([1]);
|
||||
const items = wrapper.find('NotificationListItem');
|
||||
items
|
||||
.at(1)
|
||||
.find('Switch[aria-label="Toggle notification success"]')
|
||||
.prop('onChange')();
|
||||
wrapper.find('input#notification-2-success-toggle').props().checked
|
||||
).toBe(false);
|
||||
await act(async () => {
|
||||
wrapper.find('Switch#notification-2-success-toggle').prop('onChange')();
|
||||
});
|
||||
wrapper.update();
|
||||
expect(MockModelAPI.associateNotificationTemplate).toHaveBeenCalledWith(
|
||||
1,
|
||||
2,
|
||||
'success'
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
expect(
|
||||
wrapper.find('NotificationList').state('successTemplateIds')
|
||||
).toEqual([1, 2]);
|
||||
wrapper.find('input#notification-2-success-toggle').props().checked
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should enable error notification', async () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<NotificationList id={1} canToggleNotifications apiModel={MockModelAPI} />
|
||||
);
|
||||
await sleep(0);
|
||||
expect(
|
||||
wrapper.find('input#notification-1-error-toggle').props().checked
|
||||
).toBe(false);
|
||||
await act(async () => {
|
||||
wrapper.find('Switch#notification-1-error-toggle').prop('onChange')();
|
||||
});
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find('NotificationList').state('errorTemplateIds')).toEqual([
|
||||
2,
|
||||
]);
|
||||
const items = wrapper.find('NotificationListItem');
|
||||
items
|
||||
.at(0)
|
||||
.find('Switch[aria-label="Toggle notification failure"]')
|
||||
.prop('onChange')();
|
||||
expect(MockModelAPI.associateNotificationTemplate).toHaveBeenCalledWith(
|
||||
1,
|
||||
1,
|
||||
'error'
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('NotificationList').state('errorTemplateIds')).toEqual([
|
||||
2,
|
||||
1,
|
||||
]);
|
||||
expect(
|
||||
wrapper.find('input#notification-1-error-toggle').props().checked
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should enable start notification', async () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<NotificationList id={1} canToggleNotifications apiModel={MockModelAPI} />
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
wrapper.find('NotificationList').state('startedTemplateIds')
|
||||
).toEqual([3]);
|
||||
const items = wrapper.find('NotificationListItem');
|
||||
items
|
||||
.at(0)
|
||||
.find('Switch[aria-label="Toggle notification start"]')
|
||||
.prop('onChange')();
|
||||
wrapper.find('input#notification-1-started-toggle').props().checked
|
||||
).toBe(false);
|
||||
await act(async () => {
|
||||
wrapper.find('Switch#notification-1-started-toggle').prop('onChange')();
|
||||
});
|
||||
wrapper.update();
|
||||
expect(MockModelAPI.associateNotificationTemplate).toHaveBeenCalledWith(
|
||||
1,
|
||||
1,
|
||||
'started'
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
expect(
|
||||
wrapper.find('NotificationList').state('startedTemplateIds')
|
||||
).toEqual([3, 1]);
|
||||
wrapper.find('input#notification-1-started-toggle').props().checked
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should disable success notification', async () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<NotificationList id={1} canToggleNotifications apiModel={MockModelAPI} />
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
wrapper.find('NotificationList').state('successTemplateIds')
|
||||
).toEqual([1]);
|
||||
const items = wrapper.find('NotificationListItem');
|
||||
items
|
||||
.at(0)
|
||||
.find('Switch[aria-label="Toggle notification success"]')
|
||||
.prop('onChange')();
|
||||
wrapper.find('input#notification-1-success-toggle').props().checked
|
||||
).toBe(true);
|
||||
await act(async () => {
|
||||
wrapper.find('Switch#notification-1-success-toggle').prop('onChange')();
|
||||
});
|
||||
wrapper.update();
|
||||
expect(MockModelAPI.disassociateNotificationTemplate).toHaveBeenCalledWith(
|
||||
1,
|
||||
1,
|
||||
'success'
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
expect(
|
||||
wrapper.find('NotificationList').state('successTemplateIds')
|
||||
).toEqual([]);
|
||||
wrapper.find('input#notification-1-success-toggle').props().checked
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test('should disable error notification', async () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<NotificationList id={1} canToggleNotifications apiModel={MockModelAPI} />
|
||||
);
|
||||
await sleep(0);
|
||||
expect(
|
||||
wrapper.find('input#notification-2-error-toggle').props().checked
|
||||
).toBe(true);
|
||||
await act(async () => {
|
||||
wrapper.find('Switch#notification-2-error-toggle').prop('onChange')();
|
||||
});
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find('NotificationList').state('errorTemplateIds')).toEqual([
|
||||
2,
|
||||
]);
|
||||
const items = wrapper.find('NotificationListItem');
|
||||
items
|
||||
.at(1)
|
||||
.find('Switch[aria-label="Toggle notification failure"]')
|
||||
.prop('onChange')();
|
||||
expect(MockModelAPI.disassociateNotificationTemplate).toHaveBeenCalledWith(
|
||||
1,
|
||||
2,
|
||||
'error'
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('NotificationList').state('errorTemplateIds')).toEqual(
|
||||
[]
|
||||
);
|
||||
expect(
|
||||
wrapper.find('input#notification-2-error-toggle').props().checked
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test('should disable start notification', async () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<NotificationList id={1} canToggleNotifications apiModel={MockModelAPI} />
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
wrapper.find('NotificationList').state('startedTemplateIds')
|
||||
).toEqual([3]);
|
||||
const items = wrapper.find('NotificationListItem');
|
||||
items
|
||||
.at(2)
|
||||
.find('Switch[aria-label="Toggle notification start"]')
|
||||
.prop('onChange')();
|
||||
wrapper.find('input#notification-3-started-toggle').props().checked
|
||||
).toBe(true);
|
||||
await act(async () => {
|
||||
wrapper.find('Switch#notification-3-started-toggle').prop('onChange')();
|
||||
});
|
||||
wrapper.update();
|
||||
expect(MockModelAPI.disassociateNotificationTemplate).toHaveBeenCalledWith(
|
||||
1,
|
||||
3,
|
||||
'started'
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
expect(
|
||||
wrapper.find('NotificationList').state('startedTemplateIds')
|
||||
).toEqual([]);
|
||||
wrapper.find('input#notification-3-started-toggle').props().checked
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test('should throw toggle error', async () => {
|
||||
MockModelAPI.associateNotificationTemplate.mockRejectedValue(
|
||||
new Error({
|
||||
@ -284,27 +247,16 @@ describe('<NotificationList />', () => {
|
||||
},
|
||||
})
|
||||
);
|
||||
const wrapper = mountWithContexts(
|
||||
<NotificationList id={1} canToggleNotifications apiModel={MockModelAPI} />
|
||||
);
|
||||
await sleep(0);
|
||||
expect(wrapper.find('ErrorDetail').length).toBe(0);
|
||||
await act(async () => {
|
||||
wrapper.find('Switch#notification-1-started-toggle').prop('onChange')();
|
||||
});
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
wrapper.find('NotificationList').state('startedTemplateIds')
|
||||
).toEqual([3]);
|
||||
const items = wrapper.find('NotificationListItem');
|
||||
items
|
||||
.at(0)
|
||||
.find('Switch[aria-label="Toggle notification start"]')
|
||||
.prop('onChange')();
|
||||
expect(MockModelAPI.associateNotificationTemplate).toHaveBeenCalledWith(
|
||||
1,
|
||||
1,
|
||||
'started'
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('ErrorDetail').length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user