Skip to content

Commit 1330b6b

Browse files
authored
[Discover] Improve buildEsqlFetchSubscribe tests (elastic#262350)
- Addresses elastic#258030 ### Summary Some smaller optimizations to check before going into full rewrite. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) - [x] Review the [backport guidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing) and apply applicable `backport:*` labels.
1 parent 2a1da0d commit 1330b6b

1 file changed

Lines changed: 72 additions & 85 deletions

File tree

src/platform/plugins/shared/discover/public/application/main/state_management/utils/build_esql_fetch_subscribe.test.ts

Lines changed: 72 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,24 @@
77
* License v3.0 only", or the "Server Side Public License, v 1".
88
*/
99

10-
import { waitFor } from '@testing-library/react';
1110
import type { DataTableRecord } from '@kbn/discover-utils/types';
1211
import type { AggregateQuery, Query } from '@kbn/es-query';
1312
import { dataViewMock } from '@kbn/discover-utils/src/__mocks__';
1413
import { VIEW_MODE } from '@kbn/saved-search-plugin/public';
1514
import type { EsHitRecord } from '@kbn/discover-utils';
1615
import { buildDataTableRecord } from '@kbn/discover-utils';
1716
import { FetchStatus } from '../../../types';
17+
import type { InternalStateMockToolkit } from '../../../../__mocks__/discover_state.mock';
1818
import { getDiscoverInternalStateMock } from '../../../../__mocks__/discover_state.mock';
1919
import { savedSearchMock } from '../../../../__mocks__/saved_search';
2020
import { internalStateActions } from '../redux';
2121
import type { DiscoverAppState } from '../redux';
2222
import { dataViewAdHoc } from '../../../../__mocks__/data_view_complex';
23+
import type { DiscoverDataStateContainer } from '../discover_data_state_container';
24+
25+
// Track resources from the last test for cleanup in afterEach
26+
let lastTestToolkit: InternalStateMockToolkit | undefined;
27+
let lastTestDataState: DiscoverDataStateContainer | undefined;
2328

2429
async function getTestProps({
2530
query,
@@ -43,6 +48,10 @@ async function getTestProps({
4348
skipWaitForDataFetching: true,
4449
});
4550

51+
// Track for cleanup in afterEach
52+
lastTestToolkit = toolkit;
53+
lastTestDataState = dataState;
54+
4655
toolkit.internalState.dispatch(
4756
toolkit.injectCurrentTab(internalStateActions.updateAppState)({
4857
appState: { columns: [], ...appState },
@@ -116,13 +125,23 @@ const setupTest = async ({
116125
// Testing buildEsqlFetchSubscribe through the state container
117126
// since the logic is pretty intertwined with the state management
118127
describe('buildEsqlFetchSubscribe', () => {
128+
afterEach(() => {
129+
// Cancel pending URL state storage updates (uses Promise.resolve().then(flush) batching)
130+
// and stop leaked throttled middleware timers (lodash.throttle with 300ms trailing setTimeout)
131+
lastTestToolkit?.stateStorageContainer.cancel();
132+
// Cancel running queries and abort controllers in the data state container
133+
lastTestDataState?.cancel();
134+
lastTestToolkit = undefined;
135+
lastTestDataState = undefined;
136+
jest.restoreAllMocks();
137+
});
119138
test('an ES|QL query should change state when loading and finished', async () => {
120139
const { replaceUrlState, dataState, tabId } = await setupTest();
121140

122141
replaceUrlState.mockClear();
123142

124143
dataState.data$.documents$.next(msgComplete);
125-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
144+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
126145
expect(replaceUrlState).toHaveBeenCalledWith({
127146
tabId,
128147
appState: { columns: ['field1', 'field2'] },
@@ -136,7 +155,7 @@ describe('buildEsqlFetchSubscribe', () => {
136155
},
137156
});
138157

139-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(0));
158+
expect(replaceUrlState).toHaveBeenCalledTimes(0);
140159
});
141160

142161
test('should change viewMode to undefined (default) if it was PATTERN_LEVEL', async () => {
@@ -146,7 +165,7 @@ describe('buildEsqlFetchSubscribe', () => {
146165
},
147166
});
148167

149-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
168+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
150169
expect(replaceUrlState).toHaveBeenCalledWith({
151170
tabId,
152171
appState: { viewMode: undefined },
@@ -171,13 +190,10 @@ describe('buildEsqlFetchSubscribe', () => {
171190
// transformational command
172191
query: { esql: 'from the-data-view-title | keep field1' },
173192
});
174-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
175-
176-
await waitFor(() => {
177-
expect(replaceUrlState).toHaveBeenCalledWith({
178-
tabId,
179-
appState: { columns: ['field1'] },
180-
});
193+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
194+
expect(replaceUrlState).toHaveBeenCalledWith({
195+
tabId,
196+
appState: { columns: ['field1'] },
181197
});
182198
});
183199

@@ -198,21 +214,18 @@ describe('buildEsqlFetchSubscribe', () => {
198214
],
199215
query: { esql: 'from the-data-view-2' },
200216
});
201-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
202-
203-
await waitFor(() => {
204-
expect(replaceUrlState).toHaveBeenCalledWith({
205-
tabId,
206-
appState: { columns: ['field1'] },
207-
});
217+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
218+
expect(replaceUrlState).toHaveBeenCalledWith({
219+
tabId,
220+
appState: { columns: ['field1'] },
208221
});
209222
});
210223

211224
test('changing a ES|QL query with no transformational commands should not change state when loading and finished if index pattern and columns are the same', async () => {
212225
const { replaceUrlState, dataState, tabId } = await setupTest({});
213226
const documents$ = dataState.data$.documents$;
214227
documents$.next(msgComplete);
215-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
228+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
216229
replaceUrlState.mockClear();
217230

218231
documents$.next({
@@ -227,7 +240,7 @@ describe('buildEsqlFetchSubscribe', () => {
227240
// non transformational command, same columns as msgComplete
228241
query: { esql: 'from the-data-view-title | where field1 > 0' },
229242
});
230-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(0));
243+
expect(replaceUrlState).toHaveBeenCalledTimes(0);
231244
replaceUrlState.mockClear();
232245

233246
documents$.next({
@@ -242,23 +255,18 @@ describe('buildEsqlFetchSubscribe', () => {
242255
// non transformational command, different index
243256
query: { esql: 'from the-data-view-title2 | where field1 > 0' },
244257
});
245-
await waitFor(
246-
() => {
247-
expect(replaceUrlState).toHaveBeenCalledWith({
248-
tabId,
249-
appState: { columns: ['field1', 'field2'] },
250-
});
251-
},
252-
{ timeout: 5000 }
253-
);
258+
expect(replaceUrlState).toHaveBeenCalledWith({
259+
tabId,
260+
appState: { columns: ['field1', 'field2'] },
261+
});
254262
});
255263

256264
test('only changing an ES|QL query with same result columns should not change columns', async () => {
257265
const { replaceUrlState, dataState, tabId } = await setupTest({});
258266
const documents$ = dataState.data$.documents$;
259267

260268
documents$.next(msgComplete);
261-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
269+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
262270
replaceUrlState.mockClear();
263271

264272
documents$.next({
@@ -272,12 +280,10 @@ describe('buildEsqlFetchSubscribe', () => {
272280
],
273281
query: { esql: 'from the-data-view-title | keep field1' },
274282
});
275-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
276-
await waitFor(() => {
277-
expect(replaceUrlState).toHaveBeenCalledWith({
278-
tabId,
279-
appState: { columns: ['field1'] },
280-
});
283+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
284+
expect(replaceUrlState).toHaveBeenCalledWith({
285+
tabId,
286+
appState: { columns: ['field1'] },
281287
});
282288
replaceUrlState.mockClear();
283289

@@ -293,15 +299,15 @@ describe('buildEsqlFetchSubscribe', () => {
293299
query: { esql: 'from the-data-view-title | keep field 1 | WHERE field1=1' },
294300
});
295301

296-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(0));
302+
expect(replaceUrlState).toHaveBeenCalledTimes(0);
297303
});
298304

299305
test('if its not an ES|QL query coming along, it should be ignored', async () => {
300306
const { replaceUrlState, dataState, tabId } = await setupTest({});
301307
const documents$ = dataState.data$.documents$;
302308

303309
documents$.next(msgComplete);
304-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
310+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
305311
replaceUrlState.mockClear();
306312

307313
documents$.next({
@@ -327,11 +333,9 @@ describe('buildEsqlFetchSubscribe', () => {
327333
query: { esql: 'from the-data-view-title | keep field 1 | WHERE field1=1' },
328334
});
329335

330-
await waitFor(() => {
331-
expect(replaceUrlState).toHaveBeenCalledWith({
332-
tabId,
333-
appState: { columns: ['field1'] },
334-
});
336+
expect(replaceUrlState).toHaveBeenCalledWith({
337+
tabId,
338+
appState: { columns: ['field1'] },
335339
});
336340
});
337341

@@ -356,12 +360,10 @@ describe('buildEsqlFetchSubscribe', () => {
356360
query: { esql: 'from the-data-view-title | keep field 1 | WHERE field1=1' },
357361
});
358362

359-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
360-
await waitFor(() => {
361-
expect(replaceUrlState).toHaveBeenCalledWith({
362-
tabId,
363-
appState: { columns: ['field1', 'field2'] },
364-
});
363+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
364+
expect(replaceUrlState).toHaveBeenCalledWith({
365+
tabId,
366+
appState: { columns: ['field1', 'field2'] },
365367
});
366368
replaceUrlState.mockClear();
367369

@@ -376,7 +378,7 @@ describe('buildEsqlFetchSubscribe', () => {
376378
],
377379
query: { esql: 'from the-data-view-title | keep field1' },
378380
});
379-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
381+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
380382
expect(replaceUrlState).toHaveBeenCalledWith({
381383
tabId,
382384
appState: { columns: ['field1'] },
@@ -405,12 +407,10 @@ describe('buildEsqlFetchSubscribe', () => {
405407
query: { esql: 'from the-data-view-title | keep field 1' },
406408
});
407409

408-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
409-
await waitFor(() => {
410-
expect(replaceUrlState).toHaveBeenCalledWith({
411-
tabId,
412-
appState: { columns: ['field1'] },
413-
});
410+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
411+
expect(replaceUrlState).toHaveBeenCalledWith({
412+
tabId,
413+
appState: { columns: ['field1'] },
414414
});
415415
});
416416

@@ -457,7 +457,7 @@ describe('buildEsqlFetchSubscribe', () => {
457457
],
458458
query: { esql: 'from the-data-view-title | WHERE field2=1' },
459459
});
460-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
460+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
461461
expect(replaceUrlState).toHaveBeenCalledWith({
462462
tabId,
463463
appState: { columns: ['field1', 'field2'] },
@@ -479,7 +479,7 @@ describe('buildEsqlFetchSubscribe', () => {
479479
],
480480
query: { esql: 'from the-data-view-title | WHERE field2=1' },
481481
});
482-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
482+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
483483
expect(replaceUrlState).toHaveBeenCalledWith({
484484
tabId,
485485
appState: { columns: ['field1', 'field2'] },
@@ -496,7 +496,7 @@ describe('buildEsqlFetchSubscribe', () => {
496496
],
497497
query: { esql: 'from the-data-view-title | keep field1' },
498498
});
499-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
499+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
500500
expect(replaceUrlState).toHaveBeenCalledWith({
501501
tabId,
502502
appState: { columns: ['field1'] },
@@ -527,7 +527,7 @@ describe('buildEsqlFetchSubscribe', () => {
527527
],
528528
query: { esql: 'from the-data-view-title | WHERE field1=2' },
529529
});
530-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
530+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
531531
toolkit.internalState.dispatch(
532532
toolkit.injectCurrentTab(internalStateActions.updateAppState)({
533533
appState: { columns: ['field1', 'field2'] },
@@ -561,7 +561,7 @@ describe('buildEsqlFetchSubscribe', () => {
561561
query: { esql: 'from the-data-view-title | keep field1' },
562562
});
563563

564-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
564+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
565565
expect(replaceUrlState).toHaveBeenCalledWith({
566566
tabId,
567567
appState: { columns: ['field1'] },
@@ -573,7 +573,7 @@ describe('buildEsqlFetchSubscribe', () => {
573573
const documents$ = dataState.data$.documents$;
574574

575575
documents$.next(msgComplete);
576-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
576+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
577577
replaceUrlState.mockClear();
578578

579579
documents$.next({
@@ -592,13 +592,10 @@ describe('buildEsqlFetchSubscribe', () => {
592592
dataView: dataViewAdHoc,
593593
})
594594
);
595-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
596-
597-
await waitFor(() => {
598-
expect(replaceUrlState).toHaveBeenCalledWith({
599-
tabId,
600-
appState: { columns: ['field1'] },
601-
});
595+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
596+
expect(replaceUrlState).toHaveBeenCalledWith({
597+
tabId,
598+
appState: { columns: ['field1'] },
602599
});
603600
});
604601

@@ -622,9 +619,7 @@ describe('buildEsqlFetchSubscribe', () => {
622619
fetchStatus: FetchStatus.LOADING,
623620
query: { esql: 'from pattern1' },
624621
});
625-
await waitFor(() =>
626-
expect(toolkit.getCurrentTab().defaultProfileState.fieldsToReset).toEqual('all')
627-
);
622+
expect(toolkit.getCurrentTab().defaultProfileState.fieldsToReset).toEqual('all');
628623
documents$.next({
629624
fetchStatus: FetchStatus.PARTIAL,
630625
query: { esql: 'from pattern1' },
@@ -643,9 +638,7 @@ describe('buildEsqlFetchSubscribe', () => {
643638
fetchStatus: FetchStatus.LOADING,
644639
query: { esql: 'from pattern1' },
645640
});
646-
await waitFor(() =>
647-
expect(toolkit.getCurrentTab().defaultProfileState.fieldsToReset).toEqual('none')
648-
);
641+
expect(toolkit.getCurrentTab().defaultProfileState.fieldsToReset).toEqual('none');
649642
documents$.next({
650643
fetchStatus: FetchStatus.PARTIAL,
651644
query: { esql: 'from pattern1' },
@@ -659,9 +652,7 @@ describe('buildEsqlFetchSubscribe', () => {
659652
fetchStatus: FetchStatus.LOADING,
660653
query: { esql: 'from pattern2' },
661654
});
662-
await waitFor(() =>
663-
expect(toolkit.getCurrentTab().defaultProfileState.fieldsToReset).toEqual('all')
664-
);
655+
expect(toolkit.getCurrentTab().defaultProfileState.fieldsToReset).toEqual('all');
665656
documents$.next({
666657
fetchStatus: FetchStatus.PARTIAL,
667658
query: { esql: 'from pattern2' },
@@ -714,7 +705,7 @@ describe('buildEsqlFetchSubscribe', () => {
714705
query: { esql: 'from the-data-view-title' },
715706
});
716707

717-
await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1));
708+
expect(replaceUrlState).toHaveBeenCalledTimes(1);
718709
expect(replaceUrlState).toHaveBeenCalledWith({
719710
tabId,
720711
appState: { columns: expectedColumns },
@@ -732,16 +723,12 @@ describe('buildEsqlFetchSubscribe', () => {
732723
query: { esql: 'from pattern' },
733724
result: result1,
734725
});
735-
await waitFor(() =>
736-
expect(toolkit.getCurrentTab().defaultProfileState.fieldsToReset).toEqual('none')
737-
);
726+
expect(toolkit.getCurrentTab().defaultProfileState.fieldsToReset).toEqual('none');
738727
documents$.next({
739728
fetchStatus: FetchStatus.PARTIAL,
740729
query: { esql: 'from pattern' },
741730
result: result2,
742731
});
743-
await waitFor(() =>
744-
expect(toolkit.getCurrentTab().defaultProfileState.fieldsToReset).toEqual(['columns'])
745-
);
732+
expect(toolkit.getCurrentTab().defaultProfileState.fieldsToReset).toEqual(['columns']);
746733
});
747734
});

0 commit comments

Comments
 (0)