diff --git a/awx/ui/src/screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.test.js b/awx/ui/src/screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.test.js
index 792aabc8b..e10edc090 100644
--- a/awx/ui/src/screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.test.js
+++ b/awx/ui/src/screens/NotificationTemplate/NotificationTemplateDetail/NotificationTemplateDetail.test.js
@@ -1,9 +1,10 @@
import React from 'react';
-import { act } from 'react-dom/test-utils';
+import { screen } from '@testing-library/react';
+
import {
- mountWithContexts,
- waitForElement,
-} from '../../../../testUtils/enzymeHelpers';
+ renderWithContexts,
+ assertDetail,
+} from '../../../../testUtils/rtlContexts';
import NotificationTemplateDetail from './NotificationTemplateDetail';
import defaultMessages from '../shared/notification-template-default-messages.json';
@@ -23,28 +24,10 @@ const mockTemplate = {
organization: '/api/v2/organizations/1/',
},
summary_fields: {
- organization: {
- id: 1,
- name: 'Default',
- description: '',
- },
- created_by: {
- id: 2,
- username: 'test',
- first_name: '',
- last_name: '',
- },
- modified_by: {
- id: 2,
- username: 'test',
- first_name: '',
- last_name: '',
- },
- user_capabilities: {
- edit: true,
- delete: true,
- copy: true,
- },
+ organization: { id: 1, name: 'Default', description: '' },
+ created_by: { id: 2, username: 'test', first_name: '', last_name: '' },
+ modified_by: { id: 2, username: 'test', first_name: '', last_name: '' },
+ user_capabilities: { edit: true, delete: true, copy: true },
recent_notifications: [{ status: 'success' }],
},
created: '2021-06-16T18:52:23.811374Z',
@@ -68,61 +51,33 @@ const mockTemplate = {
};
describe('', () => {
- let wrapper;
-
afterEach(() => {
jest.clearAllMocks();
});
- test('should render Details', async () => {
- await act(async () => {
- wrapper = mountWithContexts(
-
- );
- });
- await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0);
- function assertDetail(label, value) {
- expect(wrapper.find(`Detail[label="${label}"] dt`).text()).toBe(label);
- expect(wrapper.find(`Detail[label="${label}"] dd`).text()).toBe(value);
- }
+ const assertCommonDetails = async () => {
+ expect(await screen.findByText('Name')).toBeInTheDocument();
assertDetail('Name', mockTemplate.name);
assertDetail('Description', mockTemplate.description);
- expect(
- wrapper
- .find('Detail[label="Email Options"]')
- .containsAllMatchingElements([
Use SSL, Use TLS])
- ).toEqual(true);
- expect(
- wrapper.find('Detail[label="Email Options"]').prop('helpText')
- ).toBeDefined();
+ // Email Options renders the SSL/TLS flags as list items
+ expect(screen.getByText('Use SSL')).toBeInTheDocument();
+ expect(screen.getByText('Use TLS')).toBeInTheDocument();
+ };
+
+ test('should render Details', async () => {
+ renderWithContexts(
+
+ );
+ await assertCommonDetails();
});
test('should render Details when defaultMessages is missing', async () => {
- await act(async () => {
- wrapper = mountWithContexts(
-
- );
- });
- await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0);
- function assertDetail(label, value) {
- expect(wrapper.find(`Detail[label="${label}"] dt`).text()).toBe(label);
- expect(wrapper.find(`Detail[label="${label}"] dd`).text()).toBe(value);
- }
- assertDetail('Name', mockTemplate.name);
- assertDetail('Description', mockTemplate.description);
- expect(
- wrapper
- .find('Detail[label="Email Options"]')
- .containsAllMatchingElements([Use SSL, Use TLS])
- ).toEqual(true);
- expect(
- wrapper.find('Detail[label="Email Options"]').prop('helpText')
- ).toBeDefined();
+ renderWithContexts(
+
+ );
+ await assertCommonDetails();
});
});
diff --git a/awx/ui/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.test.js b/awx/ui/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.test.js
index 98493f4b5..d8f30751a 100644
--- a/awx/ui/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.test.js
+++ b/awx/ui/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateList.test.js
@@ -1,11 +1,9 @@
import React from 'react';
-import { act } from 'react-dom/test-utils';
-import {
- NotificationsAPI,
- NotificationTemplatesAPI,
- OrganizationsAPI,
-} from 'api';
-import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
+import { screen, waitFor, fireEvent, act } from '@testing-library/react';
+
+import { NotificationsAPI, NotificationTemplatesAPI } from 'api';
+import { renderWithContexts } from '../../../../testUtils/rtlContexts';
+
import NotificationTemplateList from './NotificationTemplateList';
jest.mock('../../../api');
@@ -20,19 +18,9 @@ const mockTemplates = {
url: '/notification_templates/1',
type: 'slack',
summary_fields: {
- organization: {
- id: 1,
- name: 'Foo',
- },
- recent_notifications: [
- {
- status: 'success',
- },
- ],
- user_capabilities: {
- delete: true,
- edit: true,
- },
+ organization: { id: 1, name: 'Foo' },
+ recent_notifications: [{ status: 'success' }],
+ user_capabilities: { delete: true, edit: true },
},
},
{
@@ -40,15 +28,9 @@ const mockTemplates = {
id: 2,
url: '/notification_templates/2',
summary_fields: {
- organization: {
- id: 2,
- name: 'Bar',
- },
+ organization: { id: 2, name: 'Bar' },
recent_notifications: [],
- user_capabilities: {
- delete: true,
- edit: true,
- },
+ user_capabilities: { delete: true, edit: true },
},
},
{
@@ -56,22 +38,9 @@ const mockTemplates = {
id: 3,
url: '/notification_templates/3',
summary_fields: {
- organization: {
- id: 3,
- name: 'Test',
- },
- recent_notifications: [
- {
- status: 'failed',
- },
- {
- status: 'success',
- },
- ],
- user_capabilities: {
- delete: true,
- edit: true,
- },
+ organization: { id: 3, name: 'Test' },
+ recent_notifications: [{ status: 'failed' }, { status: 'success' }],
+ user_capabilities: { delete: true, edit: true },
},
},
],
@@ -79,180 +48,105 @@ const mockTemplates = {
};
describe('', () => {
- let wrapper;
beforeEach(() => {
- OrganizationsAPI.read.mockResolvedValue(mockTemplates);
- OrganizationsAPI.readOptions.mockResolvedValue({
- data: {
- actions: {
- GET: {},
- POST: {},
- },
- },
+ NotificationTemplatesAPI.read.mockResolvedValue(mockTemplates);
+ NotificationTemplatesAPI.readOptions.mockResolvedValue({
+ data: { actions: { GET: {}, POST: {} } },
});
});
+
afterEach(() => {
jest.resetAllMocks();
});
test('should load notifications', async () => {
- await act(async () => {
- wrapper = mountWithContexts();
- });
- wrapper.update();
- expect(OrganizationsAPI.read).toHaveBeenCalledTimes(1);
- expect(wrapper.find('NotificationTemplateListItem').length).toBe(3);
+ renderWithContexts();
+ expect(await screen.findByText('Boston')).toBeInTheDocument();
+ expect(screen.getByText('Minneapolis')).toBeInTheDocument();
+ expect(screen.getByText('Philidelphia')).toBeInTheDocument();
+ expect(NotificationTemplatesAPI.read).toHaveBeenCalledTimes(1);
});
- test('should select item', async () => {
- await act(async () => {
- wrapper = mountWithContexts();
- });
- wrapper.update();
- expect(
- wrapper.find('.pf-c-table__check').first().find('input').prop('checked')
- ).toEqual(false);
- await act(async () => {
- wrapper
- .find('.pf-c-table__check')
- .first()
- .find('input')
- .props()
- .onChange();
- });
- wrapper.update();
- expect(
- wrapper.find('.pf-c-table__check').first().find('input').prop('checked')
- ).toEqual(true);
+ test('should select a row', async () => {
+ const { user } = renderWithContexts();
+ await screen.findByText('Boston');
+ const checkboxes = screen.getAllByRole('checkbox');
+ expect(checkboxes[1]).not.toBeChecked();
+ await user.click(checkboxes[1]);
+ expect(checkboxes[1]).toBeChecked();
});
test('should delete notifications', async () => {
- await act(async () => {
- wrapper = mountWithContexts();
- });
- 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"]'
+ const { user } = renderWithContexts();
+ await screen.findByText('Boston');
+ await user.click(screen.getAllByRole('checkbox')[0]); // select all
+ await user.click(screen.getByRole('button', { name: 'Delete' }));
+ fireEvent.click(await screen.findByLabelText('confirm delete'));
+ await waitFor(() =>
+ expect(NotificationTemplatesAPI.destroy).toHaveBeenCalledTimes(3)
+ );
+ await waitFor(() =>
+ expect(NotificationTemplatesAPI.read).toHaveBeenCalledTimes(2)
);
- 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 () => {
- OrganizationsAPI.destroy.mockRejectedValue(
- new Error({
- response: {
- config: {
- method: 'delete',
- url: '/api/v2/organizations/1',
- },
- data: 'An error occurred',
- },
- })
- );
- await act(async () => {
- wrapper = mountWithContexts();
- });
- wrapper.update();
- await act(async () => {
- wrapper
- .find('.pf-c-table__check')
- .first()
- .find('input')
- .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();
+ test('should show an error dialog for a failed deletion', async () => {
+ NotificationTemplatesAPI.destroy.mockRejectedValue(new Error('nope'));
+ const { user } = renderWithContexts();
+ await screen.findByText('Boston');
+ await user.click(screen.getAllByRole('checkbox')[1]);
+ await user.click(screen.getByRole('button', { name: 'Delete' }));
+ fireEvent.click(await screen.findByLabelText('confirm delete'));
+ expect(await screen.findByText('Error!')).toBeInTheDocument();
+ });
- const modal = wrapper.find('Modal');
- expect(modal.prop('isOpen')).toEqual(true);
- expect(modal.prop('title')).toEqual('Error!');
+ test('should show the add button', async () => {
+ renderWithContexts();
+ await screen.findByText('Boston');
+ expect(screen.getByRole('link', { name: 'Add' })).toBeInTheDocument();
});
- test('should show add button', async () => {
- await act(async () => {
- wrapper = mountWithContexts();
+ test('should hide the add button without POST capability', async () => {
+ NotificationTemplatesAPI.readOptions.mockResolvedValue({
+ data: { actions: { GET: {} } },
});
- wrapper.update();
- expect(wrapper.find('ToolbarAddButton').length).toBe(1);
+ renderWithContexts();
+ await screen.findByText('Boston');
+ expect(screen.queryByRole('link', { name: 'Add' })).not.toBeInTheDocument();
});
- test('should show toast after test resolves', async () => {
+ test('should show a toast after a test notification resolves', async () => {
jest.useFakeTimers();
NotificationTemplatesAPI.test.mockResolvedValue({
- data: {
- notification: 9182,
- },
+ data: { notification: 9182 },
});
NotificationsAPI.readDetail.mockResolvedValue({
data: {
id: 9182,
status: 'failed',
error: 'There was an error with the notification',
- summary_fields: {
- notification_template: {
- name: 'foobar',
- },
- },
+ summary_fields: { notification_template: { name: 'foobar' } },
},
});
- await act(async () => {
- wrapper = mountWithContexts();
- });
- wrapper.update();
- expect(wrapper.find('Alert').length).toBe(0);
- await act(async () => {
- wrapper
- .find('button[aria-label="Test Notification"]')
- .at(0)
- .simulate('click');
- });
- wrapper.update();
- await act(async () => {
- jest.runAllTimers();
- });
- wrapper.update();
- expect(wrapper.find('Alert').length).toBe(1);
- });
+ renderWithContexts();
+ // wait for the list rows/actions to render before interacting
+ await screen.findByText('Boston');
- test('should hide add button (rbac)', async () => {
- OrganizationsAPI.readOptions.mockResolvedValue({
- data: {
- actions: {
- GET: {},
- },
- },
- });
+ expect(screen.queryByText('foobar')).not.toBeInTheDocument();
+ fireEvent.click(
+ screen.getAllByRole('button', { name: 'Test Notification' })[0]
+ );
+
+ // runAllTimersAsync flushes the microtask queue between timers, so the
+ // test() -> setTimeout(poll) -> readDetail() -> onAddToast chain resolves.
await act(async () => {
- wrapper = mountWithContexts();
+ await jest.runAllTimersAsync();
});
- wrapper.update();
- expect(wrapper.find('ToolbarAddButton').length).toBe(0);
+
+ // the toast carries the notification template name as its title
+ expect(NotificationsAPI.readDetail).toHaveBeenCalledWith(9182);
+ expect(screen.getByText('foobar')).toBeInTheDocument();
+ jest.useRealTimers();
});
});
diff --git a/awx/ui/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.test.js b/awx/ui/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.test.js
index bd3e07c46..b96b3d248 100644
--- a/awx/ui/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.test.js
+++ b/awx/ui/src/screens/NotificationTemplate/NotificationTemplateList/NotificationTemplateListItem.test.js
@@ -1,7 +1,9 @@
import React from 'react';
-import { act } from 'react-dom/test-utils';
+import { screen, waitFor } from '@testing-library/react';
+
import { NotificationTemplatesAPI } from 'api';
-import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
+import { renderWithContexts } from '../../../../testUtils/rtlContexts';
+
import NotificationTemplateListItem from './NotificationTemplateListItem';
jest.mock('../../../api/models/NotificationTemplates');
@@ -12,147 +14,81 @@ const template = {
notification_type: 'slack',
name: 'Test Notification',
summary_fields: {
- organization: {
- id: 1,
- name: 'Foo',
- },
- user_capabilities: {
- edit: true,
- copy: true,
- },
- recent_notifications: [
- {
- status: 'success',
- },
- ],
+ organization: { id: 1, name: 'Foo' },
+ user_capabilities: { edit: true, copy: true },
+ recent_notifications: [{ status: 'success' }],
},
};
+const renderItem = (props = {}) =>
+ renderWithContexts(
+
+ );
+
describe('', () => {
- test('should render template row', () => {
- const wrapper = mountWithContexts(
-
- );
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
- const cells = wrapper.find('Td');
- expect(cells).toHaveLength(6);
- expect(cells.at(1).text()).toEqual('Test Notification');
- expect(cells.at(2).text()).toEqual('Success');
- expect(cells.at(3).text()).toEqual('Slack');
+ test('should render template row', () => {
+ renderItem();
+ expect(screen.getByText('Test Notification')).toBeInTheDocument();
+ expect(screen.getByText('Success')).toBeInTheDocument();
+ expect(screen.getByText('Slack')).toBeInTheDocument();
});
test('should send test notification', async () => {
NotificationTemplatesAPI.test.mockResolvedValue({
data: { notification: 1 },
});
-
- const wrapper = mountWithContexts(
-
+ const { user } = renderItem();
+ await user.click(screen.getByRole('button', { name: 'Test Notification' }));
+ await waitFor(() =>
+ expect(NotificationTemplatesAPI.test).toHaveBeenCalledTimes(1)
);
- await act(async () => {
- wrapper.find('Button').at(0).invoke('onClick')();
- });
- expect(NotificationTemplatesAPI.test).toHaveBeenCalledTimes(1);
- expect(wrapper.find('Td').at(2).text()).toEqual('Running');
+ expect(screen.getByText('Running')).toBeInTheDocument();
});
- test('should call api to copy inventory', async () => {
+ test('should call api to copy template', async () => {
NotificationTemplatesAPI.copy.mockResolvedValue({ name: 'Foo' });
-
- const wrapper = mountWithContexts(
-
+ const { user } = renderItem();
+ await user.click(screen.getByRole('button', { name: 'Copy' }));
+ await waitFor(() =>
+ expect(NotificationTemplatesAPI.copy).toHaveBeenCalled()
);
-
- await act(async () =>
- wrapper.find('Button[aria-label="Copy"]').prop('onClick')()
- );
- expect(NotificationTemplatesAPI.copy).toHaveBeenCalled();
- jest.clearAllMocks();
});
- test('should render proper alert modal on copy error', async () => {
- NotificationTemplatesAPI.copy.mockRejectedValue(
- new Error({
- response: {
- config: {
- method: 'post',
- url: '/api/v2/notification_templates/3/copy',
- },
- data: 'An error ocurred',
- status: 403,
- },
- })
- );
-
- const wrapper = mountWithContexts(
-
- );
- expect(wrapper.find('Modal').length).toBe(0);
- await act(async () =>
- wrapper.find('Button[aria-label="Copy"]').prop('onClick')()
- );
- wrapper.update();
- expect(wrapper.find('Modal').length).toBe(1);
- expect(wrapper.find('Modal').prop('isOpen')).toBe(true);
- jest.clearAllMocks();
+ test('should render an error modal on copy failure', async () => {
+ NotificationTemplatesAPI.copy.mockRejectedValue(new Error('nope'));
+ const { user } = renderItem();
+ await user.click(screen.getByRole('button', { name: 'Copy' }));
+ expect(
+ await screen.findByText('Failed to copy template.')
+ ).toBeInTheDocument();
});
- test('should not render copy button', async () => {
- const wrapper = mountWithContexts(
-
- );
- expect(wrapper.find('CopyButton').length).toBe(0);
+ test('should not render copy button without copy capability', () => {
+ renderItem({
+ template: {
+ ...template,
+ summary_fields: {
+ organization: { id: 3, name: 'Test' },
+ user_capabilities: { copy: false, edit: false },
+ },
+ },
+ });
+ expect(
+ screen.queryByRole('button', { name: 'Copy' })
+ ).not.toBeInTheDocument();
});
});
diff --git a/awx/ui/src/screens/NotificationTemplate/shared/NotificationTemplateForm.test.js b/awx/ui/src/screens/NotificationTemplate/shared/NotificationTemplateForm.test.js
index 1fca957f2..d293d335c 100644
--- a/awx/ui/src/screens/NotificationTemplate/shared/NotificationTemplateForm.test.js
+++ b/awx/ui/src/screens/NotificationTemplate/shared/NotificationTemplateForm.test.js
@@ -1,11 +1,36 @@
import React from 'react';
-import { act } from 'react-dom/test-utils';
-import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
+import { screen, waitFor, act } from '@testing-library/react';
+
+import { renderWithContexts } from '../../../../testUtils/rtlContexts';
import NotificationTemplateForm from './NotificationTemplateForm';
jest.mock('../../../api/models/NotificationTemplates');
jest.mock('../../../api/models/Organizations');
+// react-ace (CodeEditor) does not expose its value as queryable text in jsdom,
+// so render the editor value as plain text to allow content assertions. The
+// custom-message fields use CodeEditorField, which is rendered from its formik
+// field value.
+jest.mock('components/CodeEditor', () => {
+ const ReactLib = require('react');
+ return {
+ __esModule: true,
+ ...jest.requireActual('components/CodeEditor'),
+ default: ({ value }) => ReactLib.createElement('div', null, value),
+ };
+});
+jest.mock('components/CodeEditor/CodeEditorField', () => {
+ const ReactLib = require('react');
+ const { useField } = require('formik');
+ return {
+ __esModule: true,
+ default: ({ name }) => {
+ const [field] = useField(name);
+ return ReactLib.createElement('div', null, field.value);
+ },
+ };
+});
+
const template = {
id: 3,
notification_type: 'slack',
@@ -14,18 +39,9 @@ const template = {
url: '/notification_templates/3',
organization: 1,
summary_fields: {
- user_capabilities: {
- edit: true,
- },
- recent_notifications: [
- {
- status: 'success',
- },
- ],
- organization: {
- id: 1,
- name: 'The Organization',
- },
+ user_capabilities: { edit: true },
+ recent_notifications: [{ status: 'success' }],
+ organization: { id: 1, name: 'The Organization' },
},
};
@@ -45,10 +61,7 @@ const emailTemplate = {
},
};
-const messageDef = {
- message: 'default message',
- body: 'default body',
-};
+const messageDef = { message: 'default message', body: 'default body' };
const defaults = {
started: messageDef,
success: messageDef,
@@ -60,12 +73,7 @@ const defaults = {
timed_out: messageDef,
},
};
-const defaultMessages = {
- email: defaults,
- slack: defaults,
- twilio: defaults,
-};
-
+const defaultMessages = { email: defaults, slack: defaults, twilio: defaults };
const allDefaultMessages = {
...defaultMessages,
grafana: defaults,
@@ -150,203 +158,135 @@ const secretTemplates = [
},
];
-describe('', () => {
- let wrapper;
- test('should render form fields', async () => {
- await act(async () => {
- wrapper = mountWithContexts(
-
- );
- });
+const renderForm = (props = {}) =>
+ renderWithContexts(
+
+ );
- expect(wrapper.find('input#notification-name').prop('value')).toEqual(
+describe('', () => {
+ test('should render fields and reveal email options on type change', async () => {
+ const { container, user } = renderForm();
+ expect(container.querySelector('#notification-name')).toHaveValue(
'Test Notification'
);
- expect(
- wrapper.find('input#notification-description').prop('value')
- ).toEqual('a sample notification');
- expect(wrapper.find('OrganizationLookup').prop('value')).toEqual({
- id: 1,
- name: 'The Organization',
- });
- expect(wrapper.find('AnsibleSelect').prop('value')).toEqual('slack');
- expect(wrapper.find('TypeInputsSubForm').prop('type')).toEqual('slack');
- expect(wrapper.find('CustomMessagesSubForm').prop('type')).toEqual('slack');
- expect(
- wrapper.find('CustomMessagesSubForm').prop('defaultMessages')
- ).toEqual(defaultMessages);
-
- expect(wrapper.find('input#option-use-ssl').length).toBe(0);
- expect(wrapper.find('input#option-use-tls').length).toBe(0);
-
- await act(async () => {
- wrapper.find('AnsibleSelect#notification-type').invoke('onChange')(
- {
- target: {
- name: 'notification_type',
- value: 'email',
- },
- },
- 'email'
- );
- });
+ expect(container.querySelector('#notification-description')).toHaveValue(
+ 'a sample notification'
+ );
+ expect(screen.getByDisplayValue('The Organization')).toBeInTheDocument();
+ expect(container.querySelector('#notification-type')).toHaveValue('slack');
+ expect(container.querySelector('#option-use-ssl')).toBeNull();
+ expect(container.querySelector('#option-use-tls')).toBeNull();
- wrapper.update();
+ await user.selectOptions(
+ container.querySelector('#notification-type'),
+ 'email'
+ );
- expect(wrapper.find('input#option-use-ssl').length).toBe(1);
- expect(wrapper.find('input#option-use-tls').length).toBe(1);
- expect(
- wrapper.find('FormGroup[label="Email Options"]').find('HelpIcon').length
- ).toBe(1);
+ await waitFor(() =>
+ expect(container.querySelector('#option-use-ssl')).toBeInTheDocument()
+ );
+ expect(container.querySelector('#option-use-tls')).toBeInTheDocument();
});
- test('should render custom messages fields', async () => {
+ test('should render existing custom messages', async () => {
await act(async () => {
- wrapper = mountWithContexts(
-
- );
+ renderForm({
+ template: {
+ ...template,
+ messages: { started: { message: 'Started', body: null } },
+ },
+ });
});
-
- expect(wrapper.find('CodeEditor').at(0).prop('value')).toEqual('Started');
+ expect(screen.getByText('Started')).toBeInTheDocument();
});
- test('should submit', async () => {
- const handleSubmit = jest.fn();
- await act(async () => {
- wrapper = mountWithContexts(
-
- );
+ test('should submit the assembled values', async () => {
+ const onSubmit = jest.fn();
+ const { user } = renderForm({
+ template: {
+ ...template,
+ notification_configuration: { channels: ['#foo'], token: 'abc123' },
+ },
+ onSubmit,
});
- await act(async () => {
- wrapper.find('FormActionGroup').invoke('onSubmit')();
- });
- wrapper.update();
+ await user.click(screen.getByRole('button', { name: 'Save' }));
- expect(handleSubmit).toHaveBeenCalledWith({
- name: 'Test Notification',
- description: 'a sample notification',
- organization: 1,
- notification_type: 'slack',
- notification_configuration: {
- channels: ['#foo'],
- hex_color: '',
- token: 'abc123',
- },
- messages: null,
- });
+ await waitFor(() =>
+ expect(onSubmit).toHaveBeenCalledWith({
+ name: 'Test Notification',
+ description: 'a sample notification',
+ organization: 1,
+ notification_type: 'slack',
+ notification_configuration: {
+ channels: ['#foo'],
+ hex_color: '',
+ token: 'abc123',
+ },
+ messages: null,
+ })
+ );
});
test('should clear the email password when reverted', async () => {
- const handleSubmit = jest.fn();
- await act(async () => {
- wrapper = mountWithContexts(
-
- );
- });
-
- await act(async () => {
- wrapper
- .find('Button')
- .filterWhere(
- (node) => node.prop('ouiaId') === 'notification_configuration.password-revert'
- )
- .simulate('click');
+ const onSubmit = jest.fn();
+ const { container, user } = renderForm({
+ template: emailTemplate,
+ onSubmit,
});
- wrapper.update();
- await act(async () => {
- wrapper.find('FormActionGroup').invoke('onSubmit')();
- });
- wrapper.update();
+ await user.click(
+ container.querySelector(
+ '[data-ouia-component-id="notification_configuration.password-revert"]'
+ )
+ );
+ await user.click(screen.getByRole('button', { name: 'Save' }));
- expect(handleSubmit).toHaveBeenCalledWith(
- expect.objectContaining({
- notification_configuration: expect.objectContaining({
- password: '',
- }),
- })
+ await waitFor(() =>
+ expect(onSubmit).toHaveBeenCalledWith(
+ expect.objectContaining({
+ notification_configuration: expect.objectContaining({
+ password: '',
+ }),
+ })
+ )
);
});
test.each(secretTemplates)(
'should clear the $type secret when reverted',
async ({ template: secretTemplate, fieldName }) => {
- const handleSubmit = jest.fn();
- await act(async () => {
- wrapper = mountWithContexts(
-
- );
+ const onSubmit = jest.fn();
+ const { container, user } = renderForm({
+ template: secretTemplate,
+ defaultMessages: allDefaultMessages,
+ onSubmit,
});
- const revertButton = wrapper
- .find('Button')
- .filterWhere(
- (node) => node.prop('ouiaId') === `${fieldName}-revert`
- );
-
- expect(revertButton.exists()).toBe(true);
-
- await act(async () => {
- revertButton.simulate('click');
- });
- wrapper.update();
+ const revertButton = container.querySelector(
+ `[data-ouia-component-id="${fieldName}-revert"]`
+ );
+ expect(revertButton).not.toBeNull();
- await act(async () => {
- wrapper.find('FormActionGroup').invoke('onSubmit')();
- });
- wrapper.update();
+ await user.click(revertButton);
+ await user.click(screen.getByRole('button', { name: 'Save' }));
- expect(handleSubmit).toHaveBeenCalledWith(
- expect.objectContaining({
- notification_configuration: expect.objectContaining({
- [fieldName.split('.').pop()]: '',
- }),
- })
+ const key = fieldName.split('.').pop();
+ await waitFor(() =>
+ expect(onSubmit).toHaveBeenCalledWith(
+ expect.objectContaining({
+ notification_configuration: expect.objectContaining({
+ [key]: '',
+ }),
+ })
+ )
);
}
);