Skip to content

Commit

Permalink
[Security Solution] [Cases] Improve jest tests on connector switcher …
Browse files Browse the repository at this point in the history
  • Loading branch information
stephmilovic authored Oct 12, 2020
1 parent 296ced8 commit d8070bd
Show file tree
Hide file tree
Showing 10 changed files with 362 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const ConnectorCardDisplay: React.FC<ConnectorCardProps> = ({
<StyledText>
{listItems.length > 0 &&
listItems.map((item, i) => (
<span key={`${item.title}-${i}`}>
<span data-test-subj="card-list-item" key={`${item.title}-${i}`}>
<strong>{`${item.title}: `}</strong>
{item.description}
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { GetIssueTypesProps, GetFieldsByIssueTypeProps } from '../api';
import { IssueTypes, Fields } from '../types';
import { GetIssueTypesProps, GetFieldsByIssueTypeProps, GetIssueTypeProps } from '../api';
import { IssueTypes, Fields, Issues, Issue } from '../types';
import { issues } from '../../mock';

const issueTypes = [
{
Expand All @@ -31,6 +32,10 @@ const fieldsByIssueType = {
},
};

export const getIssue = async (props: GetIssueTypeProps): Promise<{ data: Issue }> =>
Promise.resolve({ data: issues[0] });
export const getIssues = async (props: GetIssueTypesProps): Promise<{ data: Issues }> =>
Promise.resolve({ data: issues });
export const getIssueTypes = async (props: GetIssueTypesProps): Promise<{ data: IssueTypes }> =>
Promise.resolve({ data: issueTypes });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,27 @@ import React from 'react';
import { mount } from 'enzyme';
import { omit } from 'lodash/fp';

import { connector } from '../mock';
import { connector, issues } from '../mock';
import { useGetIssueTypes } from './use_get_issue_types';
import { useGetFieldsByIssueType } from './use_get_fields_by_issue_type';
import Fields from './fields';
import { waitFor } from '@testing-library/dom';
import { useGetSingleIssue } from './use_get_single_issue';
import { useGetIssues } from './use_get_issues';
import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui';

jest.mock('../../../../common/lib/kibana');
jest.mock('./use_get_issue_types');
jest.mock('./use_get_fields_by_issue_type');
jest.mock('./use_get_single_issue');
jest.mock('./use_get_issues');

const useGetIssueTypesMock = useGetIssueTypes as jest.Mock;
const useGetFieldsByIssueTypeMock = useGetFieldsByIssueType as jest.Mock;
const useGetSingleIssueMock = useGetSingleIssue as jest.Mock;
const useGetIssuesMock = useGetIssues as jest.Mock;

describe('JiraParamsFields renders', () => {
describe('Jira Fields', () => {
const useGetIssueTypesResponse = {
isLoading: false,
issueTypes: [
Expand Down Expand Up @@ -57,28 +65,104 @@ describe('JiraParamsFields renders', () => {
},
};

const useGetSingleIssueResponse = {
isLoading: false,
issue: { title: 'Parent Task', key: 'parentId' },
};

const fields = {
issueType: '10006',
priority: 'High',
parent: null,
};

const useGetIssuesResponse = {
isLoading: false,
issues,
};

const onChange = jest.fn();

beforeEach(() => {
useGetIssueTypesMock.mockReturnValue(useGetIssueTypesResponse);
useGetFieldsByIssueTypeMock.mockReturnValue(useGetFieldsByIssueTypeResponse);
useGetSingleIssueMock.mockReturnValue(useGetSingleIssueResponse);
jest.clearAllMocks();
});

test('all params fields are rendered', () => {
test('all params fields are rendered - isEdit: true', () => {
const wrapper = mount(<Fields fields={fields} onChange={onChange} connector={connector} />);
expect(wrapper.find('[data-test-subj="issueTypeSelect"]').first().prop('value')).toStrictEqual(
'10006'
);
expect(wrapper.find('[data-test-subj="prioritySelect"]').first().prop('value')).toStrictEqual(
'High'
);
expect(wrapper.find('[data-test-subj="search-parent-issues"]').first().exists()).toBeFalsy();
});

test('all params fields are rendered - isEdit: false', () => {
const wrapper = mount(
<Fields
isEdit={false}
fields={{ ...fields, parent: 'Parent Task' }}
onChange={onChange}
connector={connector}
/>
);
expect(wrapper.find('[data-test-subj="card-list-item"]').at(0).text()).toEqual(
'Issue type: Task'
);
expect(wrapper.find('[data-test-subj="card-list-item"]').at(1).text()).toEqual(
'Parent issue: Parent Task'
);
expect(wrapper.find('[data-test-subj="card-list-item"]').at(2).text()).toEqual(
'Priority: High'
);
});

test('it sets parent correctly', async () => {
useGetFieldsByIssueTypeMock.mockReturnValue({
...useGetFieldsByIssueTypeResponse,
fields: {
...useGetFieldsByIssueTypeResponse.fields,
parent: {},
},
});
useGetIssuesMock.mockReturnValue(useGetIssuesResponse);
const wrapper = mount(<Fields fields={fields} onChange={onChange} connector={connector} />);

await waitFor(() =>
((wrapper.find(EuiComboBox).props() as unknown) as {
onChange: (a: EuiComboBoxOptionOption[]) => void;
}).onChange([{ label: 'parentId', value: 'parentId' }])
);
wrapper.update();
expect(onChange).toHaveBeenCalledWith({
issueType: '10006',
parent: 'parentId',
priority: 'High',
});
});
test('it searches parent correctly', async () => {
useGetFieldsByIssueTypeMock.mockReturnValue({
...useGetFieldsByIssueTypeResponse,
fields: {
...useGetFieldsByIssueTypeResponse.fields,
parent: {},
},
});
useGetSingleIssueMock.mockReturnValue({ useGetSingleIssueResponse, issue: null });
useGetIssuesMock.mockReturnValue(useGetIssuesResponse);
const wrapper = mount(<Fields fields={fields} onChange={onChange} connector={connector} />);

await waitFor(() =>
((wrapper.find(EuiComboBox).props() as unknown) as {
onSearchChange: (a: string) => void;
}).onSearchChange('womanId')
);
wrapper.update();
expect(useGetIssuesMock.mock.calls[2][0].query).toEqual('womanId');
});

test('it disabled the fields when loading issue types', () => {
Expand Down Expand Up @@ -116,7 +200,7 @@ describe('JiraParamsFields renders', () => {
expect(wrapper.find('[data-test-subj="prioritySelect"]').first().exists()).toBeFalsy();
});

test('it sets issue type correctly', async () => {
test('it sets issue type correctly', () => {
const wrapper = mount(<Fields fields={fields} onChange={onChange} connector={connector} />);

wrapper
Expand All @@ -129,7 +213,29 @@ describe('JiraParamsFields renders', () => {
expect(onChange).toHaveBeenCalledWith({ issueType: '10007', parent: null, priority: null });
});

test('it sets priority correctly', async () => {
test('it sets issue type when it comes as null', () => {
const wrapper = mount(
<Fields fields={{ ...fields, issueType: null }} onChange={onChange} connector={connector} />
);
expect(wrapper.find('select[data-test-subj="issueTypeSelect"]').first().props().value).toEqual(
'10006'
);
});

test('it sets issue type when it comes as unknown value', () => {
const wrapper = mount(
<Fields
fields={{ ...fields, issueType: '99999' }}
onChange={onChange}
connector={connector}
/>
);
expect(wrapper.find('select[data-test-subj="issueTypeSelect"]').first().props().value).toEqual(
'10006'
);
});

test('it sets priority correctly', () => {
const wrapper = mount(<Fields fields={fields} onChange={onChange} connector={connector} />);

wrapper
Expand All @@ -142,7 +248,7 @@ describe('JiraParamsFields renders', () => {
expect(onChange).toHaveBeenCalledWith({ issueType: '10006', parent: null, priority: '2' });
});

test('it resets priority when changing issue type', async () => {
test('it resets priority when changing issue type', () => {
const wrapper = mount(<Fields fields={fields} onChange={onChange} connector={connector} />);
wrapper
.find('select[data-test-subj="issueTypeSelect"]')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ const JiraSettingFieldsComponent: React.FunctionComponent<SettingFieldsProps<Jir
},
[currentIssueType, fields, onChange, parent, priority]
);

return isEdit ? (
<span data-test-subj={'connector-settings-jira'}>
<EuiFormRow fullWidth label={i18n.ISSUE_TYPE}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const SearchIssuesComponent: React.FC<Props> = ({ selectedValue, actionConnector
singleSelection
fullWidth
placeholder={inputPlaceholder}
data-test-sub={'search-parent-issues'}
data-test-subj={'search-parent-issues'}
aria-label={i18n.SEARCH_ISSUES_COMBO_BOX_ARIA_LABEL}
options={options}
isLoading={isLoadingIssues || isLoadingSingleIssue}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { renderHook, act } from '@testing-library/react-hooks';

import { useKibana } from '../../../../common/lib/kibana';
import { connector as actionConnector, issues } from '../mock';
import { useGetIssues, UseGetIssues } from './use_get_issues';
import * as api from './api';

jest.mock('../../../../common/lib/kibana');
jest.mock('./api');

const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>;

describe('useGetIssues', () => {
const { http, notifications } = useKibanaMock().services;
beforeEach(() => jest.clearAllMocks());

test('init', async () => {
await act(async () => {
const { result, waitForNextUpdate } = renderHook<string, UseGetIssues>(() =>
useGetIssues({
http,
toastNotifications: notifications.toasts,
actionConnector,
query: null,
})
);
await waitForNextUpdate();
expect(result.current).toEqual({ isLoading: false, issues: [] });
});
});

test('fetch issues', async () => {
await act(async () => {
const { result, waitForNextUpdate } = renderHook<string, UseGetIssues>(() =>
useGetIssues({
http,
toastNotifications: notifications.toasts,
actionConnector,
query: 'Task',
})
);
await waitForNextUpdate();
await waitForNextUpdate();
expect(result.current).toEqual({
isLoading: false,
issues,
});
});
});

test('unhappy path', async () => {
const spyOnGetCaseConfigure = jest.spyOn(api, 'getIssues');
spyOnGetCaseConfigure.mockImplementation(() => {
throw new Error('Something went wrong');
});

await act(async () => {
const { result, waitForNextUpdate } = renderHook<string, UseGetIssues>(() =>
useGetIssues({
http,
toastNotifications: notifications.toasts,
actionConnector,
query: 'oh no',
})
);

await waitForNextUpdate();
await waitForNextUpdate();

expect(result.current).toEqual({ isLoading: false, issues: [] });
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { renderHook, act } from '@testing-library/react-hooks';

import { useKibana } from '../../../../common/lib/kibana';
import { connector as actionConnector, issues } from '../mock';
import { useGetSingleIssue, UseGetSingleIssue } from './use_get_single_issue';
import * as api from './api';

jest.mock('../../../../common/lib/kibana');
jest.mock('./api');

const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>;

describe('useGetSingleIssue', () => {
const { http, notifications } = useKibanaMock().services;
beforeEach(() => jest.clearAllMocks());

test('init', async () => {
await act(async () => {
const { result, waitForNextUpdate } = renderHook<string, UseGetSingleIssue>(() =>
useGetSingleIssue({
http,
toastNotifications: notifications.toasts,
actionConnector,
id: null,
})
);
await waitForNextUpdate();
expect(result.current).toEqual({ isLoading: false, issue: null });
});
});

test('fetch issues', async () => {
await act(async () => {
const { result, waitForNextUpdate } = renderHook<string, UseGetSingleIssue>(() =>
useGetSingleIssue({
http,
toastNotifications: notifications.toasts,
actionConnector,
id: '123',
})
);
await waitForNextUpdate();
await waitForNextUpdate();
expect(result.current).toEqual({
isLoading: false,
issue: issues[0],
});
});
});

test('unhappy path', async () => {
const spyOnGetCaseConfigure = jest.spyOn(api, 'getIssue');
spyOnGetCaseConfigure.mockImplementation(() => {
throw new Error('Something went wrong');
});

await act(async () => {
const { result, waitForNextUpdate } = renderHook<string, UseGetSingleIssue>(() =>
useGetSingleIssue({
http,
toastNotifications: notifications.toasts,
actionConnector,
id: '123',
})
);

await waitForNextUpdate();
await waitForNextUpdate();

expect(result.current).toEqual({ isLoading: false, issue: null });
});
});
});
Loading

0 comments on commit d8070bd

Please sign in to comment.