mirror of
https://github.com/ansible/awx.git
synced 2026-01-12 18:40:01 -03:30
add notification list tests
This commit is contained in:
parent
8bb1c985c0
commit
4c555815b3
61
awx/ui_next/src/components/StatusLabel/StatusLabel.test.jsx
Normal file
61
awx/ui_next/src/components/StatusLabel/StatusLabel.test.jsx
Normal file
@ -0,0 +1,61 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import StatusLabel from './StatusLabel';
|
||||
|
||||
describe('StatusLabel', () => {
|
||||
test('should render success', () => {
|
||||
const wrapper = mount(<StatusLabel status="success" />);
|
||||
expect(wrapper).toHaveLength(1);
|
||||
expect(wrapper.find('CheckCircleIcon')).toHaveLength(1);
|
||||
expect(wrapper.find('Label').prop('color')).toEqual('green');
|
||||
expect(wrapper.text()).toEqual('Success');
|
||||
});
|
||||
|
||||
test('should render failed', () => {
|
||||
const wrapper = mount(<StatusLabel status="failed" />);
|
||||
expect(wrapper).toHaveLength(1);
|
||||
expect(wrapper.find('ExclamationCircleIcon')).toHaveLength(1);
|
||||
expect(wrapper.find('Label').prop('color')).toEqual('red');
|
||||
expect(wrapper.text()).toEqual('Failed');
|
||||
});
|
||||
|
||||
test('should render error', () => {
|
||||
const wrapper = mount(<StatusLabel status="error" />);
|
||||
expect(wrapper).toHaveLength(1);
|
||||
expect(wrapper.find('ExclamationCircleIcon')).toHaveLength(1);
|
||||
expect(wrapper.find('Label').prop('color')).toEqual('red');
|
||||
expect(wrapper.text()).toEqual('Error');
|
||||
});
|
||||
|
||||
test('should render running', () => {
|
||||
const wrapper = mount(<StatusLabel status="running" />);
|
||||
expect(wrapper).toHaveLength(1);
|
||||
expect(wrapper.find('SyncAltIcon')).toHaveLength(1);
|
||||
expect(wrapper.find('Label').prop('color')).toEqual('blue');
|
||||
expect(wrapper.text()).toEqual('Running');
|
||||
});
|
||||
|
||||
test('should render pending', () => {
|
||||
const wrapper = mount(<StatusLabel status="pending" />);
|
||||
expect(wrapper).toHaveLength(1);
|
||||
expect(wrapper.find('ClockIcon')).toHaveLength(1);
|
||||
expect(wrapper.find('Label').prop('color')).toEqual('blue');
|
||||
expect(wrapper.text()).toEqual('Pending');
|
||||
});
|
||||
|
||||
test('should render waiting', () => {
|
||||
const wrapper = mount(<StatusLabel status="waiting" />);
|
||||
expect(wrapper).toHaveLength(1);
|
||||
expect(wrapper.find('ClockIcon')).toHaveLength(1);
|
||||
expect(wrapper.find('Label').prop('color')).toEqual('grey');
|
||||
expect(wrapper.text()).toEqual('Waiting');
|
||||
});
|
||||
|
||||
test('should render canceled', () => {
|
||||
const wrapper = mount(<StatusLabel status="canceled" />);
|
||||
expect(wrapper).toHaveLength(1);
|
||||
expect(wrapper.find('ExclamationTriangleIcon')).toHaveLength(1);
|
||||
expect(wrapper.find('Label').prop('color')).toEqual('orange');
|
||||
expect(wrapper.text()).toEqual('Canceled');
|
||||
});
|
||||
});
|
||||
@ -1,33 +1,17 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import {
|
||||
Button,
|
||||
Chip,
|
||||
TextList,
|
||||
TextListItem,
|
||||
TextListItemVariants,
|
||||
TextListVariants,
|
||||
Label,
|
||||
} from '@patternfly/react-core';
|
||||
import { Button } from '@patternfly/react-core';
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
import AlertModal from '../../../components/AlertModal';
|
||||
import { CardBody, CardActionsRow } from '../../../components/Card';
|
||||
import ChipGroup from '../../../components/ChipGroup';
|
||||
import ContentError from '../../../components/ContentError';
|
||||
import ContentLoading from '../../../components/ContentLoading';
|
||||
import CredentialChip from '../../../components/CredentialChip';
|
||||
import {
|
||||
Detail,
|
||||
DetailList,
|
||||
DeletedDetail,
|
||||
UserDateDetail,
|
||||
} from '../../../components/DetailList';
|
||||
import DeleteButton from '../../../components/DeleteButton';
|
||||
import ErrorDetail from '../../../components/ErrorDetail';
|
||||
import LaunchButton from '../../../components/LaunchButton';
|
||||
import { VariablesDetail } from '../../../components/CodeMirrorInput';
|
||||
import { NotificationTemplatesAPI } from '../../../api';
|
||||
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||
import { NOTIFICATION_TYPES } from '../constants';
|
||||
|
||||
@ -0,0 +1,202 @@
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { OrganizationsAPI } from '../../../api';
|
||||
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
|
||||
import NotificationTemplateList from './NotificationTemplateList';
|
||||
|
||||
jest.mock('../../../api');
|
||||
|
||||
const mockTemplates = {
|
||||
data: {
|
||||
count: 3,
|
||||
results: [
|
||||
{
|
||||
name: 'Boston',
|
||||
id: 1,
|
||||
url: '/notification_templates/1',
|
||||
type: 'slack',
|
||||
summary_fields: {
|
||||
recent_notifications: [
|
||||
{
|
||||
status: 'success',
|
||||
},
|
||||
],
|
||||
user_capabilities: {
|
||||
delete: true,
|
||||
edit: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Minneapolis',
|
||||
id: 2,
|
||||
url: '/notification_templates/2',
|
||||
summary_fields: {
|
||||
recent_notifications: [],
|
||||
user_capabilities: {
|
||||
delete: true,
|
||||
edit: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Philidelphia',
|
||||
id: 3,
|
||||
url: '/notification_templates/3',
|
||||
summary_fields: {
|
||||
recent_notifications: [
|
||||
{
|
||||
status: 'failed',
|
||||
},
|
||||
{
|
||||
status: 'success',
|
||||
},
|
||||
],
|
||||
user_capabilities: {
|
||||
delete: true,
|
||||
edit: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
describe('<NotificationTemplateList />', () => {
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
OrganizationsAPI.read.mockResolvedValue(mockTemplates);
|
||||
OrganizationsAPI.readOptions.mockResolvedValue({
|
||||
data: {
|
||||
actions: {
|
||||
GET: {},
|
||||
POST: {},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('should load notifications', async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<NotificationTemplateList />);
|
||||
});
|
||||
wrapper.update();
|
||||
expect(OrganizationsAPI.read).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.find('NotificationTemplateListItem').length).toBe(3);
|
||||
});
|
||||
|
||||
test('should select item', async () => {
|
||||
const itemCheckboxInput = 'input#select-template-1';
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<NotificationTemplateList />);
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find(itemCheckboxInput).prop('checked')).toEqual(false);
|
||||
await act(async () => {
|
||||
wrapper
|
||||
.find(itemCheckboxInput)
|
||||
.closest('DataListCheck')
|
||||
.props()
|
||||
.onChange();
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find(itemCheckboxInput).prop('checked')).toEqual(true);
|
||||
});
|
||||
|
||||
test('should delete notifications', async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<NotificationTemplateList />);
|
||||
});
|
||||
wrapper.update();
|
||||
expect(OrganizationsAPI.read).toHaveBeenCalledTimes(1);
|
||||
await act(async () => {
|
||||
wrapper
|
||||
.find('Checkbox#select-all')
|
||||
.props()
|
||||
.onChange(true);
|
||||
});
|
||||
wrapper.update();
|
||||
await act(async () => {
|
||||
wrapper.find('button[aria-label="Delete"]').simulate('click');
|
||||
wrapper.update();
|
||||
});
|
||||
const deleteButton = global.document.querySelector(
|
||||
'body div[role="dialog"] button[aria-label="confirm delete"]'
|
||||
);
|
||||
expect(deleteButton).not.toEqual(null);
|
||||
await act(async () => {
|
||||
deleteButton.click();
|
||||
});
|
||||
expect(OrganizationsAPI.destroy).toHaveBeenCalledTimes(3);
|
||||
expect(OrganizationsAPI.read).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
test('should show error dialog shown for failed deletion', async () => {
|
||||
const itemCheckboxInput = 'input#select-template-1';
|
||||
OrganizationsAPI.destroy.mockRejectedValue(
|
||||
new Error({
|
||||
response: {
|
||||
config: {
|
||||
method: 'delete',
|
||||
url: '/api/v2/organizations/1',
|
||||
},
|
||||
data: 'An error occurred',
|
||||
},
|
||||
})
|
||||
);
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<NotificationTemplateList />);
|
||||
});
|
||||
wrapper.update();
|
||||
await act(async () => {
|
||||
wrapper
|
||||
.find(itemCheckboxInput)
|
||||
.closest('DataListCheck')
|
||||
.props()
|
||||
.onChange();
|
||||
});
|
||||
wrapper.update();
|
||||
await act(async () => {
|
||||
wrapper.find('button[aria-label="Delete"]').simulate('click');
|
||||
wrapper.update();
|
||||
});
|
||||
const deleteButton = global.document.querySelector(
|
||||
'body div[role="dialog"] button[aria-label="confirm delete"]'
|
||||
);
|
||||
expect(deleteButton).not.toEqual(null);
|
||||
await act(async () => {
|
||||
deleteButton.click();
|
||||
});
|
||||
wrapper.update();
|
||||
|
||||
const modal = wrapper.find('Modal');
|
||||
expect(modal.prop('isOpen')).toEqual(true);
|
||||
expect(modal.prop('title')).toEqual('Error!');
|
||||
});
|
||||
|
||||
test('should show add button', async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<NotificationTemplateList />);
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('ToolbarAddButton').length).toBe(1);
|
||||
});
|
||||
|
||||
test('should hide add button (rbac)', async () => {
|
||||
OrganizationsAPI.readOptions.mockResolvedValue({
|
||||
data: {
|
||||
actions: {
|
||||
GET: {},
|
||||
},
|
||||
},
|
||||
});
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<NotificationTemplateList />);
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('ToolbarAddButton').length).toBe(0);
|
||||
});
|
||||
});
|
||||
@ -34,7 +34,10 @@ function NotificationTemplateListItem({
|
||||
onSelect,
|
||||
i18n,
|
||||
}) {
|
||||
const latestStatus = template.summary_fields?.recent_notifications[0]?.status;
|
||||
const recentNotifications = template.summary_fields?.recent_notifications;
|
||||
const latestStatus = recentNotifications
|
||||
? recentNotifications[0]?.status
|
||||
: null;
|
||||
const [status, setStatus] = useState(latestStatus);
|
||||
|
||||
useEffect(() => {
|
||||
@ -44,7 +47,7 @@ function NotificationTemplateListItem({
|
||||
const { request: sendTestNotification, isLoading, error } = useRequest(
|
||||
useCallback(() => {
|
||||
NotificationTemplatesAPI.test(template.id);
|
||||
setStatus('pending');
|
||||
setStatus('running');
|
||||
}, [template.id])
|
||||
);
|
||||
|
||||
@ -72,11 +75,11 @@ function NotificationTemplateListItem({
|
||||
<b>{template.name}</b>
|
||||
</Link>
|
||||
</DataListCell>,
|
||||
<DataListCell>
|
||||
<DataListCell key="status">
|
||||
{status && <StatusLabel status={status} />}
|
||||
</DataListCell>,
|
||||
<DataListCell key="type">
|
||||
<strong css="margin-right: 24px">{i18n._(t`Type`)}</strong>
|
||||
<strong>{i18n._(t`Type:`)}</strong>{' '}
|
||||
{NOTIFICATION_TYPES[template.notification_type] ||
|
||||
template.notification_type}
|
||||
</DataListCell>,
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
|
||||
import { NotificationTemplatesAPI } from '../../../api';
|
||||
import NotificationTemplateListItem from './NotificationTemplateListItem';
|
||||
|
||||
jest.mock('../../../api/models/NotificationTemplates');
|
||||
|
||||
const template = {
|
||||
id: 3,
|
||||
notification_type: 'slack',
|
||||
name: 'Test Notification',
|
||||
summary_fields: {
|
||||
user_capabilities: {
|
||||
edit: true,
|
||||
},
|
||||
recent_notifications: [
|
||||
{
|
||||
status: 'success',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
describe('<NotificationTemplateListItem />', () => {
|
||||
test('should render template row', () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<NotificationTemplateListItem
|
||||
template={template}
|
||||
detailUrl="/notification_templates/3/detail"
|
||||
/>
|
||||
);
|
||||
|
||||
const cells = wrapper.find('DataListCell');
|
||||
expect(cells).toHaveLength(3);
|
||||
expect(cells.at(0).text()).toEqual('Test Notification');
|
||||
expect(cells.at(1).text()).toEqual('Success');
|
||||
expect(cells.at(2).text()).toEqual('Type: Slack');
|
||||
});
|
||||
|
||||
test('should send test notification', async () => {
|
||||
NotificationTemplatesAPI.test.mockResolvedValue({});
|
||||
|
||||
const wrapper = mountWithContexts(
|
||||
<NotificationTemplateListItem
|
||||
template={template}
|
||||
detailUrl="/notification_templates/3/detail"
|
||||
/>
|
||||
);
|
||||
await act(async () => {
|
||||
wrapper
|
||||
.find('Button')
|
||||
.at(0)
|
||||
.invoke('onClick')();
|
||||
});
|
||||
expect(NotificationTemplatesAPI.test).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
wrapper
|
||||
.find('DataListCell')
|
||||
.at(1)
|
||||
.text()
|
||||
).toEqual('Running');
|
||||
});
|
||||
});
|
||||
@ -1,18 +1,14 @@
|
||||
import React from 'react';
|
||||
|
||||
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
|
||||
|
||||
import NotificationTemplates from './NotificationTemplates';
|
||||
|
||||
describe('<NotificationTemplates />', () => {
|
||||
let pageWrapper;
|
||||
let pageSections;
|
||||
let title;
|
||||
|
||||
beforeEach(() => {
|
||||
pageWrapper = mountWithContexts(<NotificationTemplates />);
|
||||
pageSections = pageWrapper.find('PageSection');
|
||||
title = pageWrapper.find('Title');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -22,8 +18,6 @@ describe('<NotificationTemplates />', () => {
|
||||
test('initially renders without crashing', () => {
|
||||
expect(pageWrapper.length).toBe(1);
|
||||
expect(pageSections.length).toBe(2);
|
||||
expect(title.length).toBe(1);
|
||||
expect(title.props().size).toBe('2xl');
|
||||
expect(pageSections.first().props().variant).toBe('light');
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user