Fixes the unHandledPromise rejections happening from unit tests (#104017) (#104035)

## Summary

We had `unHandledPromise` rejections within some of our unit tests which still pass on CI but technically those tests are not running correctly and will not catch bugs.

We were seeing them showing up like so:

```ts
PASS  x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts (10.502 s)
(node:21059) UnhandledPromiseRejectionWarning: [object Object]
    at emitUnhandledRejectionWarning (internal/process/promises.js:170:15)
    at processPromiseRejections (internal/process/promises.js:247:11)
    at processTicksAndRejections (internal/process/task_queues.js:96:32)
(node:21059) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)
(node:21059) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    at emitDeprecationWarning (internal/process/promises.js:180:11)
    at processPromiseRejections (internal/process/promises.js:249:13)
    at processTicksAndRejections (internal/process/task_queues.js:96:32)
 PASS  x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts
 PASS  x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts
 PASS  x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts
(node:21059) UnhandledPromiseRejectionWarning: Error: bulk failed
    at emitUnhandledRejectionWarning (internal/process/promises.js:170:15)
    at processPromiseRejections (internal/process/promises.js:247:11)
    at processTicksAndRejections (internal/process/task_queues.js:96:32)
(node:21059) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 7)
````

You can narrow down `unHandledPromise` rejections and fix tests one by one by running the following command:
```ts
node --trace-warnings --unhandled-rejections=strict scripts/jest.js --runInBand x-pack/plugins/security_solution
```

You can manually test if I fixed them by running that command and ensuring all tests run without errors and that the process exits with a 0 for detections only by running:

```ts
node --trace-warnings --unhandled-rejections=strict scripts/jest.js --runInBand x-pack/plugins/security_solution/public/detections
```

and

```ts
node --trace-warnings --unhandled-rejections=strict scripts/jest.js --runInBand x-pack/plugins/security_solution/server/lib/detection_engine
```

### Checklist
- [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or

Co-authored-by: Frank Hassanabad <frank.hassanabad@elastic.co>
This commit is contained in:
Kibana Machine 2021-06-30 21:42:03 -04:00 committed by GitHub
parent bc02990c46
commit 062777ca90
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 14 deletions

View file

@ -6,7 +6,7 @@
*/
import React from 'react';
import { mount, shallow } from 'enzyme';
import { mount } from 'enzyme';
import { QueryBarDefineRule } from './index';
import {
@ -17,7 +17,26 @@ import {
import { useGetAllTimeline, getAllTimeline } from '../../../../timelines/containers/all';
import { mockHistory, Router } from '../../../../common/mock/router';
jest.mock('../../../../common/lib/kibana');
jest.mock('../../../../common/lib/kibana', () => {
const actual = jest.requireActual('../../../../common/lib/kibana');
return {
...actual,
KibanaServices: {
get: jest.fn(() => ({
http: {
post: jest.fn().mockReturnValue({
success: true,
success_count: 0,
timelines_installed: 0,
timelines_updated: 0,
errors: [],
}),
fetch: jest.fn(),
},
})),
},
};
});
jest.mock('../../../../timelines/containers/all', () => {
const originalModule = jest.requireActual('../../../../timelines/containers/all');
@ -55,8 +74,14 @@ describe('QueryBarDefineRule', () => {
/>
);
};
const wrapper = shallow(<Component />);
expect(wrapper.dive().find('[data-test-subj="query-bar-define-rule"]')).toHaveLength(1);
const wrapper = mount(
<TestProviders>
<Router history={mockHistory}>
<Component />
</Router>
</TestProviders>
);
expect(wrapper.find('[data-test-subj="query-bar-define-rule"]').exists()).toBeTruthy();
});
it('renders import query from saved timeline modal actions hidden correctly', () => {

View file

@ -36,11 +36,16 @@ jest.mock('react-router-dom', () => ({
}),
}));
jest.mock('../../../pages/detection_engine/rules/all/actions', () => ({
deleteRulesAction: jest.fn(),
duplicateRulesAction: jest.fn(),
editRuleAction: jest.fn(),
}));
jest.mock('../../../pages/detection_engine/rules/all/actions', () => {
const actual = jest.requireActual('../../../../common/lib/kibana');
return {
...actual,
exportRulesAction: jest.fn(),
deleteRulesAction: jest.fn(),
duplicateRulesAction: jest.fn(),
editRuleAction: jest.fn(),
};
});
const duplicateRulesActionMock = duplicateRulesAction as jest.Mock;
const flushPromises = () => new Promise(setImmediate);

View file

@ -31,6 +31,7 @@ import { getQueryRuleParams } from '../schemas/rule_schemas.mock';
import { bulkCreateFactory } from './bulk_create_factory';
import { wrapHitsFactory } from './wrap_hits_factory';
import { mockBuildRuleMessage } from './__mocks__/build_rule_message.mock';
import { ResponseError } from '@elastic/elasticsearch/lib/errors';
const buildRuleMessage = mockBuildRuleMessage;
@ -739,9 +740,16 @@ describe('searchAfterAndBulkCreate', () => {
repeatedSearchResultsWithSortId(4, 1, someGuids.slice(0, 3))
)
);
mockService.scopedClusterClient.asCurrentUser.bulk.mockRejectedValue(
elasticsearchClientMock.createErrorTransportRequestPromise(new Error('bulk failed'))
); // Added this recently
mockService.scopedClusterClient.asCurrentUser.bulk.mockReturnValue(
elasticsearchClientMock.createErrorTransportRequestPromise(
new ResponseError(
elasticsearchClientMock.createApiResponse({
statusCode: 400,
body: { error: { type: 'bulk_error_type' } },
})
)
)
);
const { success, createdSignalsCount, lastLookBackDate } = await searchAfterAndBulkCreate({
listClient,
exceptionsList: [exceptionItem],

View file

@ -32,6 +32,7 @@ import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mo
import { queryExecutor } from './executors/query';
import { mlExecutor } from './executors/ml';
import { getMlRuleParams, getQueryRuleParams } from '../schemas/rule_schemas.mock';
import { ResponseError } from '@elastic/elasticsearch/lib/errors';
jest.mock('./rule_status_saved_objects_client');
jest.mock('./rule_status_service');
@ -455,8 +456,15 @@ describe('signal_rule_alert_type', () => {
});
it('and call ruleStatusService with the default message', async () => {
(queryExecutor as jest.Mock).mockRejectedValue(
elasticsearchClientMock.createErrorTransportRequestPromise({})
(queryExecutor as jest.Mock).mockReturnValue(
elasticsearchClientMock.createErrorTransportRequestPromise(
new ResponseError(
elasticsearchClientMock.createApiResponse({
statusCode: 400,
body: { error: { type: 'some_error_type' } },
})
)
)
);
await alert.executor(payload);
expect(logger.error).toHaveBeenCalled();