[SIEM] Uses faster wait from testing-library and removes duplicate older wait idiom (#72509)

## Summary

* Removes the older wait pattern that does a block no matter what
* Utilizes the improved and better pattern for test-library's waitFor which will test immediately and then poll for results
* Changes everything to put their expect statement within the waitFor
* Once the waitFor is in TypeScript/JS we can change the import statement to use that

If you get a timeout or error this is what it looks like now which improves the developer experience in some ways but does degrade things in others as it suggests that everything is timeout related. However, developers should inspect the values and remove the waitFor() and re-run their tests if they think that they have a real problem during development.

<img width="990" alt="Screen Shot 2020-07-20 at 12 40 39 PM" src="https://user-images.githubusercontent.com/1151048/87975739-4084d980-ca89-11ea-83c9-ba3fb932a175.png">


See the API for more information:
https://testing-library.com/docs/dom-testing-library/api-async#waitfor

But in short we should be using:

```ts
await waitFor(() => expect(...));
```

throughout our code at this point and the waitFor will loop quickly and efficiently until it either times out or gets the condition expected.

### Checklist

Delete any items that are not applicable to this PR.

- [x] [Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios
This commit is contained in:
Frank Hassanabad 2020-07-20 16:23:38 -06:00 committed by GitHub
parent 709e0a0a11
commit 03fe8c3e89
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 577 additions and 490 deletions

View file

@ -15,7 +15,9 @@ import { Router, routeData, mockHistory, mockLocation } from '../__mock__/router
import { useInsertTimeline } from '../../../timelines/components/timeline/insert_timeline_popover/use_insert_timeline';
import { usePostComment } from '../../containers/use_post_comment';
import { useForm } from '../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form';
import { wait } from '../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
jest.mock(
'../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form'
@ -84,10 +86,11 @@ describe('AddComment ', () => {
expect(wrapper.find(`[data-test-subj="loading-spinner"]`).exists()).toBeFalsy();
wrapper.find(`[data-test-subj="submit-comment"]`).first().simulate('click');
await wait();
expect(onCommentSaving).toBeCalled();
expect(postComment).toBeCalledWith(sampleData, onCommentPosted);
expect(formHookMock.reset).toBeCalled();
await waitFor(() => {
expect(onCommentSaving).toBeCalled();
expect(postComment).toBeCalledWith(sampleData, onCommentPosted);
expect(formHookMock.reset).toBeCalled();
});
});
it('should render spinner and disable submit when loading', () => {

View file

@ -15,7 +15,9 @@ import { TestProviders } from '../../../common/mock';
import { useUpdateCase } from '../../containers/use_update_case';
import { useGetCase } from '../../containers/use_get_case';
import { useGetCaseUserActions } from '../../containers/use_get_case_user_actions';
import { wait } from '../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { useConnectors } from '../../containers/configure/use_connectors';
import { connectorsMock } from '../../containers/configure/mock';
@ -108,30 +110,33 @@ describe('CaseView ', () => {
</Router>
</TestProviders>
);
await wait();
expect(wrapper.find(`[data-test-subj="case-view-title"]`).first().prop('title')).toEqual(
data.title
);
expect(wrapper.find(`[data-test-subj="case-view-status"]`).first().text()).toEqual(data.status);
expect(
wrapper
.find(`[data-test-subj="case-view-tag-list"] [data-test-subj="case-tag"]`)
.first()
.text()
).toEqual(data.tags[0]);
expect(wrapper.find(`[data-test-subj="case-view-username"]`).first().text()).toEqual(
data.createdBy.username
);
expect(wrapper.contains(`[data-test-subj="case-view-closedAt"]`)).toBe(false);
expect(wrapper.find(`[data-test-subj="case-view-createdAt"]`).first().prop('value')).toEqual(
data.createdAt
);
expect(
wrapper
.find(`[data-test-subj="description-action"] [data-test-subj="user-action-markdown"]`)
.first()
.prop('raw')
).toEqual(data.description);
await waitFor(() => {
expect(wrapper.find(`[data-test-subj="case-view-title"]`).first().prop('title')).toEqual(
data.title
);
expect(wrapper.find(`[data-test-subj="case-view-status"]`).first().text()).toEqual(
data.status
);
expect(
wrapper
.find(`[data-test-subj="case-view-tag-list"] [data-test-subj="case-tag"]`)
.first()
.text()
).toEqual(data.tags[0]);
expect(wrapper.find(`[data-test-subj="case-view-username"]`).first().text()).toEqual(
data.createdBy.username
);
expect(wrapper.contains(`[data-test-subj="case-view-closedAt"]`)).toBe(false);
expect(wrapper.find(`[data-test-subj="case-view-createdAt"]`).first().prop('value')).toEqual(
data.createdAt
);
expect(
wrapper
.find(`[data-test-subj="description-action"] [data-test-subj="user-action-markdown"]`)
.first()
.prop('raw')
).toEqual(data.description);
});
});
it('should show closed indicators in header when case is closed', async () => {
@ -146,14 +151,15 @@ describe('CaseView ', () => {
</Router>
</TestProviders>
);
await wait();
expect(wrapper.contains(`[data-test-subj="case-view-createdAt"]`)).toBe(false);
expect(wrapper.find(`[data-test-subj="case-view-closedAt"]`).first().prop('value')).toEqual(
basicCaseClosed.closedAt
);
expect(wrapper.find(`[data-test-subj="case-view-status"]`).first().text()).toEqual(
basicCaseClosed.status
);
await waitFor(() => {
expect(wrapper.contains(`[data-test-subj="case-view-createdAt"]`)).toBe(false);
expect(wrapper.find(`[data-test-subj="case-view-closedAt"]`).first().prop('value')).toEqual(
basicCaseClosed.closedAt
);
expect(wrapper.find(`[data-test-subj="case-view-status"]`).first().text()).toEqual(
basicCaseClosed.status
);
});
});
it('should dispatch update state when button is toggled', async () => {
@ -164,11 +170,12 @@ describe('CaseView ', () => {
</Router>
</TestProviders>
);
await wait();
wrapper
.find('input[data-test-subj="toggle-case-status"]')
.simulate('change', { target: { checked: true } });
expect(updateCaseProperty).toHaveBeenCalled();
await waitFor(() => {
wrapper
.find('input[data-test-subj="toggle-case-status"]')
.simulate('change', { target: { checked: true } });
expect(updateCaseProperty).toHaveBeenCalled();
});
});
it('should display EditableTitle isLoading', () => {
@ -296,17 +303,17 @@ describe('CaseView ', () => {
</TestProviders>
);
await wait();
await waitFor(() => {
expect(
wrapper.find('[data-test-subj="has-data-to-push-button"]').first().exists()
).toBeTruthy();
expect(
wrapper.find('[data-test-subj="has-data-to-push-button"]').first().exists()
).toBeTruthy();
wrapper.find('[data-test-subj="push-to-external-service"]').first().simulate('click');
wrapper.find('[data-test-subj="push-to-external-service"]').first().simulate('click');
wrapper.update();
wrapper.update();
expect(postPushToService).toHaveBeenCalled();
expect(postPushToService).toHaveBeenCalled();
});
});
it('should return null if error', () => {
@ -424,17 +431,19 @@ describe('CaseView ', () => {
</Router>
</TestProviders>
);
await wait();
wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click');
wrapper.update();
wrapper.find('button[data-test-subj="dropdown-connector-servicenow-2"]').simulate('click');
wrapper.update();
wrapper.find(`[data-test-subj="edit-connectors-submit"]`).last().simulate('click');
wrapper.update();
await wait();
wrapper.update();
expect(
wrapper.find('[data-test-subj="dropdown-connectors"]').at(0).prop('valueOfSelected')
).toBe('servicenow-1');
await waitFor(() => {
wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click');
wrapper.update();
wrapper.find('button[data-test-subj="dropdown-connector-servicenow-2"]').simulate('click');
wrapper.update();
wrapper.find(`[data-test-subj="edit-connectors-submit"]`).last().simulate('click');
wrapper.update();
});
await waitFor(() => {
wrapper.update();
expect(
wrapper.find('[data-test-subj="dropdown-connectors"]').at(0).prop('valueOfSelected')
).toBe('servicenow-1');
});
});
});

View file

@ -19,7 +19,9 @@ import { useGetTags } from '../../containers/use_get_tags';
jest.mock('../../../timelines/components/timeline/insert_timeline_popover/use_insert_timeline');
jest.mock('../../containers/use_post_case');
import { useForm } from '../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form';
import { wait } from '../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
jest.mock(
'../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form'
@ -97,8 +99,7 @@ describe('Create case', () => {
</TestProviders>
);
wrapper.find(`[data-test-subj="create-case-submit"]`).first().simulate('click');
await wait();
expect(postCase).toBeCalledWith(sampleData);
await waitFor(() => expect(postCase).toBeCalledWith(sampleData));
});
it('should redirect to all cases on cancel click', () => {

View file

@ -11,7 +11,8 @@ import { EditConnector } from './index';
import { getFormMock, useFormMock } from '../__mock__/form';
import { TestProviders } from '../../../common/mock';
import { connectorsMock } from '../../containers/configure/mock';
import { wait } from '../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
jest.mock(
'../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form'
@ -68,8 +69,7 @@ describe('EditConnector ', () => {
await act(async () => {
wrapper.find(`[data-test-subj="edit-connectors-submit"]`).last().simulate('click');
await wait();
expect(onSubmit.mock.calls[0][0]).toBe(sampleConnector);
await waitFor(() => expect(onSubmit.mock.calls[0][0]).toBe(sampleConnector));
});
});
@ -92,10 +92,11 @@ describe('EditConnector ', () => {
await act(async () => {
wrapper.find(`[data-test-subj="edit-connectors-submit"]`).last().simulate('click');
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
expect(formHookMock.setFieldValue).toHaveBeenCalledWith('connector', 'none');
});
});
expect(formHookMock.setFieldValue).toHaveBeenCalledWith('connector', 'none');
});
it('Resets selector on cancel', async () => {
@ -115,12 +116,13 @@ describe('EditConnector ', () => {
await act(async () => {
wrapper.find(`[data-test-subj="edit-connectors-cancel"]`).last().simulate('click');
await wait();
wrapper.update();
expect(formHookMock.setFieldValue).toBeCalledWith(
'connector',
defaultProps.selectedConnector
);
await waitFor(() => {
wrapper.update();
expect(formHookMock.setFieldValue).toBeCalledWith(
'connector',
defaultProps.selectedConnector
);
});
});
});

View file

@ -11,7 +11,8 @@ import { act } from 'react-dom/test-utils';
import { TagList } from '.';
import { getFormMock } from '../__mock__/form';
import { TestProviders } from '../../../common/mock';
import { wait } from '../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { useForm } from '../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form';
import { useGetTags } from '../../containers/use_get_tags';
@ -77,8 +78,7 @@ describe('TagList ', () => {
wrapper.find(`[data-test-subj="tag-list-edit-button"]`).last().simulate('click');
await act(async () => {
wrapper.find(`[data-test-subj="edit-tags-submit"]`).last().simulate('click');
await wait();
expect(onSubmit).toBeCalledWith(sampleTags);
await waitFor(() => expect(onSubmit).toBeCalledWith(sampleTags));
});
});
it('Tag options render with new tags added', () => {
@ -107,9 +107,10 @@ describe('TagList ', () => {
await act(async () => {
expect(wrapper.find(`[data-test-subj="case-tag"]`).last().exists()).toBeFalsy();
wrapper.find(`[data-test-subj="edit-tags-cancel"]`).last().simulate('click');
await wait();
wrapper.update();
expect(wrapper.find(`[data-test-subj="case-tag"]`).last().exists()).toBeTruthy();
await waitFor(() => {
wrapper.update();
expect(wrapper.find(`[data-test-subj="case-tag"]`).last().exists()).toBeTruthy();
});
});
});
it('Renders disabled button', () => {

View file

@ -13,7 +13,8 @@ import { useUpdateComment } from '../../containers/use_update_comment';
import { basicCase, basicPush, getUserAction } from '../../containers/mock';
import { UserActionTree } from '.';
import { TestProviders } from '../../../common/mock';
import { wait } from '../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
const fetchUserActions = jest.fn();
@ -225,22 +226,23 @@ describe('UserActionTree ', () => {
.first()
.simulate('click');
await act(async () => {
await wait();
wrapper.update();
expect(
wrapper
.find(
`[data-test-subj="user-action-${props.data.comments[0].id}"] [data-test-subj="user-action-markdown-form"]`
)
.exists()
).toEqual(false);
expect(patchComment).toBeCalledWith({
commentUpdate: sampleData.content,
caseId: props.data.id,
commentId: props.data.comments[0].id,
fetchUserActions,
updateCase,
version: props.data.comments[0].version,
await waitFor(() => {
wrapper.update();
expect(
wrapper
.find(
`[data-test-subj="user-action-${props.data.comments[0].id}"] [data-test-subj="user-action-markdown-form"]`
)
.exists()
).toEqual(false);
expect(patchComment).toBeCalledWith({
commentUpdate: sampleData.content,
caseId: props.data.id,
commentId: props.data.comments[0].id,
fetchUserActions,
updateCase,
version: props.data.comments[0].version,
});
});
});
});
@ -269,15 +271,16 @@ describe('UserActionTree ', () => {
.first()
.simulate('click');
await act(async () => {
await wait();
expect(
wrapper
.find(
`[data-test-subj="user-action-${props.data.id}"] [data-test-subj="user-action-markdown-form"]`
)
.exists()
).toEqual(false);
expect(onUpdateField).toBeCalledWith({ key: 'description', value: sampleData.content });
await waitFor(() => {
expect(
wrapper
.find(
`[data-test-subj="user-action-${props.data.id}"] [data-test-subj="user-action-markdown-form"]`
)
.exists()
).toEqual(false);
expect(onUpdateField).toBeCalledWith({ key: 'description', value: sampleData.content });
});
});
});

View file

@ -10,7 +10,8 @@ import useResizeObserver from 'use-resize-observer/polyfilled';
import '../../mock/match_media';
import { mockIndexPattern, TestProviders } from '../../mock';
import { wait } from '../../lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { mockEventViewerResponse } from './mock';
import { StatefulEventsViewer } from '.';
@ -60,12 +61,13 @@ describe('EventsViewer', () => {
</TestProviders>
);
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
expect(wrapper.find(`[data-test-subj="header-section-subtitle"]`).first().text()).toEqual(
'Showing: 12 events'
);
expect(wrapper.find(`[data-test-subj="header-section-subtitle"]`).first().text()).toEqual(
'Showing: 12 events'
);
});
});
test('it does NOT render fetch index pattern is loading', async () => {
@ -84,10 +86,13 @@ describe('EventsViewer', () => {
</TestProviders>
);
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
expect(wrapper.find(`[data-test-subj="header-section-subtitle"]`).first().exists()).toBe(false);
expect(wrapper.find(`[data-test-subj="header-section-subtitle"]`).first().exists()).toBe(
false
);
});
});
test('it does NOT render when start is empty', async () => {
@ -106,10 +111,13 @@ describe('EventsViewer', () => {
</TestProviders>
);
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
expect(wrapper.find(`[data-test-subj="header-section-subtitle"]`).first().exists()).toBe(false);
expect(wrapper.find(`[data-test-subj="header-section-subtitle"]`).first().exists()).toBe(
false
);
});
});
test('it does NOT render when end is empty', async () => {
@ -128,10 +136,13 @@ describe('EventsViewer', () => {
</TestProviders>
);
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
expect(wrapper.find(`[data-test-subj="header-section-subtitle"]`).first().exists()).toBe(false);
expect(wrapper.find(`[data-test-subj="header-section-subtitle"]`).first().exists()).toBe(
false
);
});
});
test('it renders the Fields Browser as a settings gear', async () => {
@ -148,10 +159,11 @@ describe('EventsViewer', () => {
</TestProviders>
);
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
expect(wrapper.find(`[data-test-subj="show-field-browser"]`).first().exists()).toBe(true);
expect(wrapper.find(`[data-test-subj="show-field-browser"]`).first().exists()).toBe(true);
});
});
test('it renders the footer containing the Load More button', async () => {
@ -168,10 +180,11 @@ describe('EventsViewer', () => {
</TestProviders>
);
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
expect(wrapper.find(`[data-test-subj="TimelineMoreButton"]`).first().exists()).toBe(true);
expect(wrapper.find(`[data-test-subj="TimelineMoreButton"]`).first().exists()).toBe(true);
});
});
defaultHeaders.forEach((header) => {
@ -189,14 +202,15 @@ describe('EventsViewer', () => {
</TestProviders>
);
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
defaultHeaders.forEach((h) =>
expect(wrapper.find(`[data-test-subj="header-text-${header.id}"]`).first().exists()).toBe(
true
)
);
defaultHeaders.forEach((h) =>
expect(wrapper.find(`[data-test-subj="header-text-${header.id}"]`).first().exists()).toBe(
true
)
);
});
});
});
});

View file

@ -9,7 +9,8 @@ import { MockedProvider } from 'react-apollo/test-utils';
import useResizeObserver from 'use-resize-observer/polyfilled';
import '../../mock/match_media';
import { wait } from '../../lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { mockIndexPattern, TestProviders } from '../../mock';
import { useMountAppended } from '../../utils/use_mount_appended';
@ -54,10 +55,11 @@ describe('StatefulEventsViewer', () => {
</TestProviders>
);
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
expect(wrapper.find('[data-test-subj="events-viewer-panel"]').first().exists()).toBe(true);
expect(wrapper.find('[data-test-subj="events-viewer-panel"]').first().exists()).toBe(true);
});
});
// InspectButtonContainer controls displaying InspectButton components
@ -75,9 +77,10 @@ describe('StatefulEventsViewer', () => {
</TestProviders>
);
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
expect(wrapper.find(`InspectButtonContainer`).exists()).toBe(true);
expect(wrapper.find(`InspectButtonContainer`).exists()).toBe(true);
});
});
});

View file

@ -21,7 +21,8 @@ import {
} from './test_dependencies';
import { UrlStateContainerPropTypes } from './types';
import { useUrlStateHooks } from './use_url_state';
import { wait } from '../../lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
let mockProps: UrlStateContainerPropTypes;
@ -194,29 +195,32 @@ describe('UrlStateContainer', () => {
}).relativeTimeSearch.undefinedQuery,
});
wrapper.update();
await wait();
if (CONSTANTS.detectionsPage === page) {
expect(mockSetRelativeRangeDatePicker.mock.calls[3][0]).toEqual({
from: '2020-01-01T00:00:00.000Z',
fromStr: 'now-1d/d',
kind: 'relative',
to: '2020-01-01T00:00:00.000Z',
toStr: 'now-1d/d',
id: 'global',
});
await waitFor(() => {
expect(mockSetRelativeRangeDatePicker.mock.calls[3][0]).toEqual({
from: '2020-01-01T00:00:00.000Z',
fromStr: 'now-1d/d',
kind: 'relative',
to: '2020-01-01T00:00:00.000Z',
toStr: 'now-1d/d',
id: 'global',
});
expect(mockSetRelativeRangeDatePicker.mock.calls[2][0]).toEqual({
from: 1558732849370,
fromStr: 'now-15m',
kind: 'relative',
to: 1558733749370,
toStr: 'now',
id: 'timeline',
expect(mockSetRelativeRangeDatePicker.mock.calls[2][0]).toEqual({
from: 1558732849370,
fromStr: 'now-15m',
kind: 'relative',
to: 1558733749370,
toStr: 'now',
id: 'timeline',
});
});
} else {
// There is no change in url state, so that's expected we only have two actions
expect(mockSetRelativeRangeDatePicker.mock.calls.length).toEqual(2);
await waitFor(() => {
// There is no change in url state, so that's expected we only have two actions
expect(mockSetRelativeRangeDatePicker.mock.calls.length).toEqual(2);
});
}
}
);

View file

@ -19,12 +19,6 @@ export type WrapArrayIfExitts = <T>(value: Many<T>) => T[] | undefined;
export const asArrayIfExists: WrapArrayIfExitts = (value) =>
!isUndefined(value) ? castArray(value) : undefined;
export const wait = (delay = 0): Promise<void> => {
return new Promise((resolve) => {
return setTimeout(resolve, delay);
});
};
/**
* Creates a Union Type for all the values of an object
*/

View file

@ -13,7 +13,8 @@ import { StepAboutRule } from '.';
import { mockAboutStepRule } from '../../../pages/detection_engine/rules/all/__mocks__/mock';
import { StepRuleDescription } from '../description_step';
import { stepAboutDefaultValue } from './default_value';
import { wait } from '@testing-library/react';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { AboutStepRule } from '../../../pages/detection_engine/rules/types';
const theme = () => ({ eui: euiDarkVars, darkMode: true });
@ -162,31 +163,32 @@ describe('StepAboutRuleComponent', () => {
.simulate('change', { target: { value: 'Test name text' } });
wrapper.find('button[data-test-subj="about-continue"]').first().simulate('click').update();
await wait();
const expected: Omit<AboutStepRule, 'isNew'> = {
author: [],
isAssociatedToEndpointList: false,
isBuildingBlock: false,
license: '',
ruleNameOverride: '',
timestampOverride: '',
description: 'Test description text',
falsePositives: [''],
name: 'Test name text',
note: '',
references: [''],
riskScore: { value: 50, mapping: [] },
severity: { value: 'low', mapping: [] },
tags: [],
threat: [
{
framework: 'MITRE ATT&CK',
tactic: { id: 'none', name: 'none', reference: 'none' },
technique: [],
},
],
};
expect(stepDataMock.mock.calls[1][1]).toEqual(expected);
await waitFor(() => {
const expected: Omit<AboutStepRule, 'isNew'> = {
author: [],
isAssociatedToEndpointList: false,
isBuildingBlock: false,
license: '',
ruleNameOverride: '',
timestampOverride: '',
description: 'Test description text',
falsePositives: [''],
name: 'Test name text',
note: '',
references: [''],
riskScore: { value: 50, mapping: [] },
severity: { value: 'low', mapping: [] },
tags: [],
threat: [
{
framework: 'MITRE ATT&CK',
tactic: { id: 'none', name: 'none', reference: 'none' },
technique: [],
},
],
};
expect(stepDataMock.mock.calls[1][1]).toEqual(expected);
});
});
test('it allows user to set the risk score as a number (and not a string)', async () => {
@ -221,30 +223,31 @@ describe('StepAboutRuleComponent', () => {
.simulate('change', { target: { value: '80' } });
wrapper.find('[data-test-subj="about-continue"]').first().simulate('click').update();
await wait();
const expected: Omit<AboutStepRule, 'isNew'> = {
author: [],
isAssociatedToEndpointList: false,
isBuildingBlock: false,
license: '',
ruleNameOverride: '',
timestampOverride: '',
description: 'Test description text',
falsePositives: [''],
name: 'Test name text',
note: '',
references: [''],
riskScore: { value: 80, mapping: [] },
severity: { value: 'low', mapping: [] },
tags: [],
threat: [
{
framework: 'MITRE ATT&CK',
tactic: { id: 'none', name: 'none', reference: 'none' },
technique: [],
},
],
};
expect(stepDataMock.mock.calls[1][1]).toEqual(expected);
await waitFor(() => {
const expected: Omit<AboutStepRule, 'isNew'> = {
author: [],
isAssociatedToEndpointList: false,
isBuildingBlock: false,
license: '',
ruleNameOverride: '',
timestampOverride: '',
description: 'Test description text',
falsePositives: [''],
name: 'Test name text',
note: '',
references: [''],
riskScore: { value: 80, mapping: [] },
severity: { value: 'low', mapping: [] },
tags: [],
threat: [
{
framework: 'MITRE ATT&CK',
tactic: { id: 'none', name: 'none', reference: 'none' },
technique: [],
},
],
};
expect(stepDataMock.mock.calls[1][1]).toEqual(expected);
});
});
});

View file

@ -11,7 +11,8 @@ import { act } from 'react-dom/test-utils';
import '../../../../../common/mock/match_media';
import { createKibanaContextProviderMock } from '../../../../../common/mock/kibana_react';
import { TestProviders } from '../../../../../common/mock';
import { wait } from '../../../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { AllRules } from './index';
jest.mock('react-router-dom', () => {
@ -202,10 +203,10 @@ describe('AllRules', () => {
);
await act(async () => {
await wait();
expect(wrapper.exists('[data-test-subj="monitoring-table"]')).toBeFalsy();
expect(wrapper.exists('[data-test-subj="rules-table"]')).toBeTruthy();
await waitFor(() => {
expect(wrapper.exists('[data-test-subj="monitoring-table"]')).toBeFalsy();
expect(wrapper.exists('[data-test-subj="rules-table"]')).toBeTruthy();
});
});
});
@ -234,11 +235,11 @@ describe('AllRules', () => {
monitoringTab.simulate('click');
await act(async () => {
wrapper.update();
await wait();
expect(wrapper.exists('[data-test-subj="monitoring-table"]')).toBeTruthy();
expect(wrapper.exists('[data-test-subj="rules-table"]')).toBeFalsy();
await waitFor(() => {
wrapper.update();
expect(wrapper.exists('[data-test-subj="monitoring-table"]')).toBeTruthy();
expect(wrapper.exists('[data-test-subj="rules-table"]')).toBeFalsy();
});
});
});
});

View file

@ -7,10 +7,11 @@
import { cloneDeep } from 'lodash/fp';
import React from 'react';
import { MockedProvider } from 'react-apollo/test-utils';
import { render, act } from '@testing-library/react';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { render, act, wait as waitFor } from '@testing-library/react';
import { mockFirstLastSeenHostQuery } from '../../containers/hosts/first_last_seen/mock';
import { wait } from '../../../common/lib/helpers';
import { TestProviders } from '../../../common/mock';
import { FirstLastSeenHost, FirstLastSeenHostType } from '.';
@ -51,10 +52,12 @@ describe('FirstLastSeen Component', () => {
</TestProviders>
);
await act(() => wait());
expect(container.innerHTML).toBe(
`<div class="euiText euiText--small"><span class="euiToolTipAnchor">${firstSeen}</span></div>`
await act(() =>
waitFor(() => {
expect(container.innerHTML).toBe(
`<div class="euiText euiText--small"><span class="euiToolTipAnchor">${firstSeen}</span></div>`
);
})
);
});
@ -66,9 +69,12 @@ describe('FirstLastSeen Component', () => {
</MockedProvider>
</TestProviders>
);
await act(() => wait());
expect(container.innerHTML).toBe(
`<div class="euiText euiText--small"><span class="euiToolTipAnchor">${lastSeen}</span></div>`
await act(() =>
waitFor(() => {
expect(container.innerHTML).toBe(
`<div class="euiText euiText--small"><span class="euiToolTipAnchor">${lastSeen}</span></div>`
);
})
);
});
@ -83,10 +89,12 @@ describe('FirstLastSeen Component', () => {
</TestProviders>
);
await act(() => wait());
expect(container.innerHTML).toBe(
`<div class="euiText euiText--small"><span class="euiToolTipAnchor">${lastSeen}</span></div>`
await act(() =>
waitFor(() => {
expect(container.innerHTML).toBe(
`<div class="euiText euiText--small"><span class="euiToolTipAnchor">${lastSeen}</span></div>`
);
})
);
});
@ -101,10 +109,12 @@ describe('FirstLastSeen Component', () => {
</TestProviders>
);
await act(() => wait());
expect(container.innerHTML).toBe(
`<div class="euiText euiText--small"><span class="euiToolTipAnchor">${firstSeen}</span></div>`
await act(() =>
waitFor(() => {
expect(container.innerHTML).toBe(
`<div class="euiText euiText--small"><span class="euiToolTipAnchor">${firstSeen}</span></div>`
);
})
);
});
@ -118,8 +128,11 @@ describe('FirstLastSeen Component', () => {
</MockedProvider>
</TestProviders>
);
await act(() => wait());
expect(container.textContent).toBe('something-invalid');
await act(() =>
waitFor(() => {
expect(container.textContent).toBe('something-invalid');
})
);
});
test('Last Seen With a bad date time string', async () => {
@ -132,7 +145,10 @@ describe('FirstLastSeen Component', () => {
</MockedProvider>
</TestProviders>
);
await act(() => wait());
expect(container.textContent).toBe('something-invalid');
await act(() =>
waitFor(() => {
expect(container.textContent).toBe('something-invalid');
})
);
});
});

View file

@ -13,7 +13,8 @@ import { ThemeProvider } from 'styled-components';
import '../../../common/mock/match_media';
import { useQuery } from '../../../common/containers/matrix_histogram';
import { wait } from '../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { mockIndexPattern, TestProviders } from '../../../common/mock';
import { AlertsByCategory } from '.';
@ -57,34 +58,45 @@ describe('Alerts by category', () => {
</ThemeProvider>
);
await wait();
wrapper.update();
});
test('it renders the expected title', () => {
expect(wrapper.find('[data-test-subj="header-section-title"]').text()).toEqual(
'External alert trend'
);
});
test('it renders the subtitle (to prevent layout thrashing)', () => {
expect(wrapper.find('[data-test-subj="header-panel-subtitle"]').exists()).toBe(true);
});
test('it renders the expected filter fields', () => {
const expectedOptions = ['event.category', 'event.module'];
expectedOptions.forEach((option) => {
expect(wrapper.find(`option[value="${option}"]`).text()).toEqual(option);
await waitFor(() => {
wrapper.update();
});
});
test('it renders the `View alerts` button', () => {
expect(wrapper.find('[data-test-subj="view-alerts"]').exists()).toBe(true);
test('it renders the expected title', async () => {
await waitFor(() => {
expect(wrapper.find('[data-test-subj="header-section-title"]').text()).toEqual(
'External alert trend'
);
});
});
test('it does NOT render the bar chart when data is not available', () => {
expect(wrapper.find(`.echChart`).exists()).toBe(false);
test('it renders the subtitle (to prevent layout thrashing)', async () => {
await waitFor(() => {
expect(wrapper.find('[data-test-subj="header-panel-subtitle"]').exists()).toBe(true);
});
});
test('it renders the expected filter fields', async () => {
await waitFor(() => {
const expectedOptions = ['event.category', 'event.module'];
expectedOptions.forEach((option) => {
expect(wrapper.find(`option[value="${option}"]`).text()).toEqual(option);
});
});
});
test('it renders the `View alerts` button', async () => {
await waitFor(() => {
expect(wrapper.find('[data-test-subj="view-alerts"]').exists()).toBe(true);
});
});
test('it does NOT render the bar chart when data is not available', async () => {
await waitFor(() => {
expect(wrapper.find(`.echChart`).exists()).toBe(false);
});
});
});
@ -119,18 +131,21 @@ describe('Alerts by category', () => {
</ThemeProvider>
);
await wait();
wrapper.update();
});
test('it renders the expected subtitle', () => {
expect(wrapper.find('[data-test-subj="header-panel-subtitle"]').text()).toEqual(
'Showing: 6 external alerts'
);
test('it renders the expected subtitle', async () => {
await waitFor(() => {
expect(wrapper.find('[data-test-subj="header-panel-subtitle"]').text()).toEqual(
'Showing: 6 external alerts'
);
});
});
test('it renders the bar chart when data is available', () => {
expect(wrapper.find(`.echChart`).exists()).toBe(true);
test('it renders the bar chart when data is available', async () => {
await waitFor(() => {
expect(wrapper.find(`.echChart`).exists()).toBe(true);
});
});
});
});

View file

@ -24,7 +24,8 @@ import { createStore, State } from '../../../common/store';
import { overviewHostQuery } from '../../containers/overview_host/index.gql_query';
import { GetOverviewHostQuery } from '../../../graphql/types';
import { wait } from '../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
jest.mock('../../../common/lib/kibana');
jest.mock('../../../common/components/link_to');
@ -147,11 +148,12 @@ describe('OverviewHost', () => {
</MockedProvider>
</TestProviders>
);
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
expect(wrapper.find('[data-test-subj="header-panel-subtitle"]').first().text()).toEqual(
'Showing: 16 events'
);
expect(wrapper.find('[data-test-subj="header-panel-subtitle"]').first().text()).toEqual(
'Showing: 16 events'
);
});
});
});

View file

@ -22,7 +22,8 @@ import { OverviewNetwork } from '.';
import { createStore, State } from '../../../common/store';
import { overviewNetworkQuery } from '../../containers/overview_network/index.gql_query';
import { GetOverviewHostQuery } from '../../../graphql/types';
import { wait } from '../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
jest.mock('../../../common/components/link_to');
const mockNavigateToApp = jest.fn();
@ -155,12 +156,13 @@ describe('OverviewNetwork', () => {
</MockedProvider>
</TestProviders>
);
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
expect(wrapper.find('[data-test-subj="header-panel-subtitle"]').first().text()).toEqual(
'Showing: 9 events'
);
expect(wrapper.find('[data-test-subj="header-panel-subtitle"]').first().text()).toEqual(
'Showing: 9 events'
);
});
});
it('it renders View Network', () => {

View file

@ -8,7 +8,8 @@ import { mount } from 'enzyme';
import { MockedProvider } from 'react-apollo/test-utils';
import React from 'react';
import { wait } from '../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import '../../../common/mock/match_media';
import { TestProviders, apolloClient } from '../../../common/mock/test_providers';
import { mockOpenTimelineQueryResults } from '../../../common/mock/timeline_results';
@ -119,15 +120,15 @@ describe('StatefulOpenTimeline', () => {
</TestProviders>
);
await wait();
await waitFor(() => {
wrapper
.find('[data-test-subj="search-bar"] input')
.simulate('keyup', { key: 'Enter', target: { value: ' abcd ' } });
wrapper
.find('[data-test-subj="search-bar"] input')
.simulate('keyup', { key: 'Enter', target: { value: ' abcd ' } });
expect(wrapper.find('[data-test-subj="query-message"]').first().text()).toContain(
'Showing: 11 timelines with'
);
expect(wrapper.find('[data-test-subj="query-message"]').first().text()).toContain(
'Showing: 11 timelines with'
);
});
});
test('echos (renders) the query when the user enters a query', async () => {
@ -144,15 +145,15 @@ describe('StatefulOpenTimeline', () => {
</TestProviders>
);
await wait();
await waitFor(() => {
wrapper
.find('[data-test-subj="search-bar"] input')
.simulate('keyup', { key: 'Enter', target: { value: ' abcd ' } });
wrapper
.find('[data-test-subj="search-bar"] input')
.simulate('keyup', { key: 'Enter', target: { value: ' abcd ' } });
expect(wrapper.find('[data-test-subj="selectable-query-text"]').first().text()).toEqual(
'with "abcd"'
);
expect(wrapper.find('[data-test-subj="selectable-query-text"]').first().text()).toEqual(
'with "abcd"'
);
});
});
});
@ -171,12 +172,12 @@ describe('StatefulOpenTimeline', () => {
</TestProviders>
);
await wait();
expect(
wrapper.find(`.${OPEN_TIMELINE_CLASS_NAME} input`).first().getDOMNode().id ===
document.activeElement!.id
).toBe(true);
await waitFor(() => {
expect(
wrapper.find(`.${OPEN_TIMELINE_CLASS_NAME} input`).first().getDOMNode().id ===
document.activeElement!.id
).toBe(true);
});
});
});
@ -198,26 +199,26 @@ describe('StatefulOpenTimeline', () => {
</TestProviders>
);
await wait();
await waitFor(() => {
wrapper
.find('.euiCheckbox__input')
.first()
.simulate('change', { target: { checked: true } });
wrapper
.find('.euiCheckbox__input')
.first()
.simulate('change', { target: { checked: true } });
wrapper.find('[data-test-subj="favorite-selected"]').first().simulate('click');
wrapper.find('[data-test-subj="favorite-selected"]').first().simulate('click');
expect(addTimelinesToFavorites).toHaveBeenCalledWith([
'saved-timeline-11',
'saved-timeline-10',
'saved-timeline-9',
'saved-timeline-8',
'saved-timeline-6',
'saved-timeline-5',
'saved-timeline-4',
'saved-timeline-3',
'saved-timeline-2',
]);
expect(addTimelinesToFavorites).toHaveBeenCalledWith([
'saved-timeline-11',
'saved-timeline-10',
'saved-timeline-9',
'saved-timeline-8',
'saved-timeline-6',
'saved-timeline-5',
'saved-timeline-4',
'saved-timeline-3',
'saved-timeline-2',
]);
});
});
});
@ -239,26 +240,26 @@ describe('StatefulOpenTimeline', () => {
</TestProviders>
);
await wait();
await waitFor(() => {
wrapper
.find('.euiCheckbox__input')
.first()
.simulate('change', { target: { checked: true } });
wrapper
.find('.euiCheckbox__input')
.first()
.simulate('change', { target: { checked: true } });
wrapper.find('[data-test-subj="delete-selected"]').first().simulate('click');
wrapper.find('[data-test-subj="delete-selected"]').first().simulate('click');
expect(deleteTimelines).toHaveBeenCalledWith([
'saved-timeline-11',
'saved-timeline-10',
'saved-timeline-9',
'saved-timeline-8',
'saved-timeline-6',
'saved-timeline-5',
'saved-timeline-4',
'saved-timeline-3',
'saved-timeline-2',
]);
expect(deleteTimelines).toHaveBeenCalledWith([
'saved-timeline-11',
'saved-timeline-10',
'saved-timeline-9',
'saved-timeline-8',
'saved-timeline-6',
'saved-timeline-5',
'saved-timeline-4',
'saved-timeline-3',
'saved-timeline-2',
]);
});
});
});
@ -278,19 +279,19 @@ describe('StatefulOpenTimeline', () => {
</TestProviders>
);
await wait();
await waitFor(() => {
wrapper
.find('.euiCheckbox__input')
.first()
.simulate('change', { target: { checked: true } });
wrapper
.find('.euiCheckbox__input')
.first()
.simulate('change', { target: { checked: true } });
const selectedItems: [] = wrapper
.find('[data-test-subj="open-timeline"]')
.last()
.prop('selectedItems');
const selectedItems: [] = wrapper
.find('[data-test-subj="open-timeline"]')
.last()
.prop('selectedItems');
expect(selectedItems.length).toEqual(13); // 13 because we did mock 13 timelines in the query
expect(selectedItems.length).toEqual(13); // 13 because we did mock 13 timelines in the query
});
});
});
@ -366,29 +367,37 @@ describe('StatefulOpenTimeline', () => {
</TestProviders>
);
await wait();
wrapper.update();
await waitFor(() => {
wrapper.update();
expect(
wrapper.find('[data-test-subj="open-timeline"]').last().prop('itemIdToExpandedNotesRowMap')
).toEqual({});
expect(
wrapper
.find('[data-test-subj="open-timeline"]')
.last()
.prop('itemIdToExpandedNotesRowMap')
).toEqual({});
wrapper.find('[data-test-subj="expand-notes"]').first().simulate('click');
wrapper.find('[data-test-subj="expand-notes"]').first().simulate('click');
expect(
wrapper.find('[data-test-subj="open-timeline"]').last().prop('itemIdToExpandedNotesRowMap')
).toEqual({
'10849df0-7b44-11e9-a608-ab3d811609': (
<NotePreviews
notes={
mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0].notes != null
? mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0].notes.map(
(note) => ({ ...note, savedObjectId: note.noteId })
)
: []
}
/>
),
expect(
wrapper
.find('[data-test-subj="open-timeline"]')
.last()
.prop('itemIdToExpandedNotesRowMap')
).toEqual({
'10849df0-7b44-11e9-a608-ab3d811609': (
<NotePreviews
notes={
mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0].notes !=
null
? mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0].notes.map(
(note) => ({ ...note, savedObjectId: note.noteId })
)
: []
}
/>
),
});
});
});
@ -407,21 +416,21 @@ describe('StatefulOpenTimeline', () => {
</TestProviders>
);
await wait();
await waitFor(() => {
wrapper.update();
wrapper.update();
wrapper.find('[data-test-subj="expand-notes"]').first().simulate('click');
expect(wrapper.find('[data-test-subj="note-previews-container"]').exists()).toEqual(true);
expect(wrapper.find('[data-test-subj="updated-by"]').exists()).toEqual(true);
wrapper.find('[data-test-subj="expand-notes"]').first().simulate('click');
expect(wrapper.find('[data-test-subj="note-previews-container"]').exists()).toEqual(true);
expect(wrapper.find('[data-test-subj="updated-by"]').exists()).toEqual(true);
expect(
wrapper
.find('[data-test-subj="note-previews-container"]')
.find('[data-test-subj="updated-by"]')
.first()
.text()
).toEqual('elastic');
expect(
wrapper
.find('[data-test-subj="note-previews-container"]')
.find('[data-test-subj="updated-by"]')
.first()
.text()
).toEqual('elastic');
});
});
/**
@ -442,11 +451,11 @@ describe('StatefulOpenTimeline', () => {
</TestProviders>
);
await wait();
expect(wrapper.find(`[data-test-subj="timeline-${TimelineTabsStyle.tab}"]`).exists()).toEqual(
true
);
await waitFor(() => {
expect(
wrapper.find(`[data-test-subj="timeline-${TimelineTabsStyle.tab}"]`).exists()
).toEqual(true);
});
});
});
@ -467,13 +476,14 @@ describe('StatefulOpenTimeline', () => {
);
const getSelectedItem = (): [] =>
wrapper.find('[data-test-subj="open-timeline"]').last().prop('selectedItems');
await wait();
expect(getSelectedItem().length).toEqual(0);
wrapper
.find('.euiCheckbox__input')
.first()
.simulate('change', { target: { checked: true } });
expect(getSelectedItem().length).toEqual(13);
await waitFor(() => {
expect(getSelectedItem().length).toEqual(0);
wrapper
.find('.euiCheckbox__input')
.first()
.simulate('change', { target: { checked: true } });
expect(getSelectedItem().length).toEqual(13);
});
});
});
@ -492,13 +502,13 @@ describe('StatefulOpenTimeline', () => {
</TestProviders>
);
await wait();
await waitFor(() => {
wrapper.update();
wrapper.update();
expect(wrapper.find('[data-test-subj="query-message"]').first().text()).toContain(
'Showing: 11 timelines '
);
expect(wrapper.find('[data-test-subj="query-message"]').first().text()).toContain(
'Showing: 11 timelines '
);
});
});
// TODO - Have been skip because we need to re-implement the test as the component changed
@ -519,21 +529,21 @@ describe('StatefulOpenTimeline', () => {
</TestProviders>
);
await wait();
await waitFor(() => {
wrapper
.find(
`[data-test-subj="title-${
mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0].savedObjectId
}"]`
)
.first()
.simulate('click');
wrapper
.find(
`[data-test-subj="title-${
mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0].savedObjectId
}"]`
)
.first()
.simulate('click');
expect(onOpenTimeline).toHaveBeenCalledWith({
duplicate: false,
timelineId: mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0]
.savedObjectId,
expect(onOpenTimeline).toHaveBeenCalledWith({
duplicate: false,
timelineId: mockOpenTimelineQueryResults[0].result.data!.getAllTimeline.timeline[0]
.savedObjectId,
});
});
});
@ -555,10 +565,10 @@ describe('StatefulOpenTimeline', () => {
</TestProviders>
);
await wait();
await waitFor(() => {
wrapper.find('[data-test-subj="open-duplicate"]').first().simulate('click');
wrapper.find('[data-test-subj="open-duplicate"]').first().simulate('click');
expect(onOpenTimeline).toBeCalledWith({ duplicate: true, timelineId: 'saved-timeline-11' });
expect(onOpenTimeline).toBeCalledWith({ duplicate: true, timelineId: 'saved-timeline-11' });
});
});
});

View file

@ -10,7 +10,8 @@ import React from 'react';
import { MockedProvider } from 'react-apollo/test-utils';
import { ThemeProvider } from 'styled-components';
import { wait } from '../../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { TestProviderWithoutDragAndDrop } from '../../../../common/mock/test_providers';
import { mockOpenTimelineQueryResults } from '../../../../common/mock/timeline_results';
import { useGetAllTimeline, getAllTimeline } from '../../../containers/all';
@ -64,10 +65,15 @@ describe('OpenTimelineModal', () => {
</ThemeProvider>
);
await wait();
await waitFor(
() => {
wrapper.update();
wrapper.update();
expect(wrapper.find('div[data-test-subj="open-timeline-modal"].euiModal').length).toEqual(1);
});
expect(wrapper.find('div[data-test-subj="open-timeline-modal"].euiModal').length).toEqual(
1
);
},
{ timeout: 10000 }
);
}, 20000);
});

View file

@ -10,7 +10,8 @@ import React from 'react';
import { MockedProvider } from 'react-apollo/test-utils';
import { ThemeProvider } from 'styled-components';
import { wait } from '../../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { TestProviderWithoutDragAndDrop } from '../../../../common/mock/test_providers';
import { mockOpenTimelineQueryResults } from '../../../../common/mock/timeline_results';
import * as i18n from '../translations';
@ -29,13 +30,13 @@ describe('OpenTimelineModalButton', () => {
</TestProviderWithoutDragAndDrop>
);
await wait();
await waitFor(() => {
wrapper.update();
wrapper.update();
expect(wrapper.find('[data-test-subj="open-timeline-button"]').first().text()).toEqual(
i18n.OPEN_TIMELINE
);
expect(wrapper.find('[data-test-subj="open-timeline-button"]').first().text()).toEqual(
i18n.OPEN_TIMELINE
);
});
});
describe('onClick prop', () => {
@ -51,13 +52,13 @@ describe('OpenTimelineModalButton', () => {
</ThemeProvider>
);
await wait();
await waitFor(() => {
wrapper.find('[data-test-subj="open-timeline-button"]').first().simulate('click');
wrapper.find('[data-test-subj="open-timeline-button"]').first().simulate('click');
wrapper.update();
wrapper.update();
expect(onClick).toBeCalled();
expect(onClick).toBeCalled();
});
});
});
});

View file

@ -16,7 +16,8 @@ import { TestProviders } from '../../../../common/mock/test_providers';
import { Body, BodyProps } from '.';
import { columnRenderers, rowRenderers } from './renderers';
import { Sort } from './sort';
import { wait } from '../../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { useMountAppended } from '../../../../common/utils/use_mount_appended';
import { SELECTOR_TIMELINE_BODY_CLASS_NAME, TimelineBody } from '../styles';
import { TimelineType } from '../../../../../common/types/timeline';
@ -130,16 +131,17 @@ describe('Body', () => {
</TestProviders>
);
wrapper.update();
await wait();
wrapper.update();
headersJustTimestamp.forEach(() => {
expect(
wrapper
.find('[data-test-subj="data-driven-columns"]')
.first()
.find('[data-test-subj="localized-date-tool-tip"]')
.exists()
).toEqual(true);
await waitFor(() => {
wrapper.update();
headersJustTimestamp.forEach(() => {
expect(
wrapper
.find('[data-test-subj="data-driven-columns"]')
.first()
.find('[data-test-subj="localized-date-tool-tip"]')
.exists()
).toEqual(true);
});
});
}, 20000);

View file

@ -16,7 +16,8 @@ import {
ReturnSignalIndex,
} from '../../../detections/containers/detection_engine/alerts/use_signal_index';
import { mocksSource } from '../../../common/containers/source/mock';
import { wait } from '../../../common/lib/helpers';
// we don't have the types for waitFor just yet, so using "as waitFor" until when we do
import { wait as waitFor } from '@testing-library/react';
import { defaultHeaders, mockTimelineData, TestProviders } from '../../../common/mock';
import { Direction } from '../../../graphql/types';
import { timelineQuery } from '../../containers/index.gql_query';
@ -124,12 +125,13 @@ describe('StatefulTimeline', () => {
</TestProviders>
);
await act(async () => {
await wait();
wrapper.update();
const timeline = wrapper.find(Timeline);
expect(timeline.props().indexToAdd).toEqual([
'no-alert-index-049FC71A-4C2C-446F-9901-37XMC5024C51',
]);
await waitFor(() => {
wrapper.update();
const timeline = wrapper.find(Timeline);
expect(timeline.props().indexToAdd).toEqual([
'no-alert-index-049FC71A-4C2C-446F-9901-37XMC5024C51',
]);
});
});
});
@ -147,10 +149,11 @@ describe('StatefulTimeline', () => {
</TestProviders>
);
await act(async () => {
await wait();
wrapper.update();
const timeline = wrapper.find(Timeline);
expect(timeline.props().indexToAdd).toEqual(['mock-siem-signals-index']);
await waitFor(() => {
wrapper.update();
const timeline = wrapper.find(Timeline);
expect(timeline.props().indexToAdd).toEqual(['mock-siem-signals-index']);
});
});
});
});

View file

@ -7,6 +7,8 @@
import React from 'react';
import { shallow } from 'enzyme';
// we don't have the types for waitFor just yet, so using "as waitFor" for when we do
import { wait as waitFor } from '@testing-library/react';
import '../../../common/mock/match_media';
import {
mockGlobalState,
@ -44,10 +46,6 @@ import { TimelineStatus, TimelineType } from '../../../../common/types/timeline'
jest.mock('../../containers/local_storage');
const wait = (ms: number = 500): Promise<void> => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
const addTimelineInStorageMock = addTimelineInStorage as jest.Mock;
describe('epicLocalStorage', () => {
@ -128,8 +126,7 @@ describe('epicLocalStorage', () => {
</TestProviders>
);
store.dispatch(upsertColumn({ id: 'test', index: 1, column: defaultHeaders[0] }));
await wait();
expect(addTimelineInStorageMock).toHaveBeenCalled();
await waitFor(() => expect(addTimelineInStorageMock).toHaveBeenCalled());
});
it('persist timeline when removing a column ', async () => {
@ -139,8 +136,7 @@ describe('epicLocalStorage', () => {
</TestProviders>
);
store.dispatch(removeColumn({ id: 'test', columnId: '@timestamp' }));
await wait();
expect(addTimelineInStorageMock).toHaveBeenCalled();
await waitFor(() => expect(addTimelineInStorageMock).toHaveBeenCalled());
});
it('persists resizing of a column', async () => {
@ -150,8 +146,7 @@ describe('epicLocalStorage', () => {
</TestProviders>
);
store.dispatch(applyDeltaToColumnWidth({ id: 'test', columnId: '@timestamp', delta: 80 }));
await wait();
expect(addTimelineInStorageMock).toHaveBeenCalled();
await waitFor(() => expect(addTimelineInStorageMock).toHaveBeenCalled());
});
it('persist the resetting of the fields', async () => {
@ -161,8 +156,7 @@ describe('epicLocalStorage', () => {
</TestProviders>
);
store.dispatch(updateColumns({ id: 'test', columns: defaultHeaders }));
await wait();
expect(addTimelineInStorageMock).toHaveBeenCalled();
await waitFor(() => expect(addTimelineInStorageMock).toHaveBeenCalled());
});
it('persist items per page', async () => {
@ -172,8 +166,7 @@ describe('epicLocalStorage', () => {
</TestProviders>
);
store.dispatch(updateItemsPerPage({ id: 'test', itemsPerPage: 50 }));
await wait();
expect(addTimelineInStorageMock).toHaveBeenCalled();
await waitFor(() => expect(addTimelineInStorageMock).toHaveBeenCalled());
});
it('persist the sorting of a column', async () => {
@ -191,7 +184,6 @@ describe('epicLocalStorage', () => {
},
})
);
await wait();
expect(addTimelineInStorageMock).toHaveBeenCalled();
await waitFor(() => expect(addTimelineInStorageMock).toHaveBeenCalled());
});
});