Skip to content

Commit

Permalink
Fixes the unHandledPromise rejections happening from unit tests (#104017
Browse files Browse the repository at this point in the history
) (#104034)

## 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>
  • Loading branch information
kibanamachine and FrankHassanabad authored Jul 1, 2021
1 parent 7f0410b commit 9b9473f
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import React from 'react';
import { mount, shallow } from 'enzyme';
import { mount } from 'enzyme';

import { QueryBarDefineRule } from './index';
import {
Expand All @@ -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');
Expand Down Expand Up @@ -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', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 9b9473f

Please sign in to comment.