diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.tsx index a5356be72f5e4..91e0ae11a652e 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.tsx @@ -18,6 +18,7 @@ import { history } from '../../../../utils/history'; import { TransactionOverview } from '..'; import { IUrlParams } from '../../../../context/UrlParamsContext/types'; import * as useServiceTransactionTypesHook from '../../../../hooks/useServiceTransactionTypes'; +import * as useFetcherHook from '../../../../hooks/useFetcher'; import { fromQuery } from '../../../shared/Links/url_helpers'; import { Router } from 'react-router-dom'; import { UrlParamsProvider } from '../../../../context/UrlParamsContext'; @@ -51,6 +52,8 @@ function setup({ .spyOn(useServiceTransactionTypesHook, 'useServiceTransactionTypes') .mockReturnValue(serviceTransactionTypes); + jest.spyOn(useFetcherHook, 'useFetcher').mockReturnValue({} as any); + return render( diff --git a/x-pack/legacy/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx index 05094c59712a9..32379325c4020 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx @@ -10,13 +10,13 @@ import { UrlParamsContext, useUiFilters } from '../../../../context/UrlParamsContext'; -import { tick } from '../../../../utils/testHelpers'; import { DatePicker } from '../index'; import { IUrlParams } from '../../../../context/UrlParamsContext/types'; import { history } from '../../../../utils/history'; import { mount } from 'enzyme'; import { EuiSuperDatePicker } from '@elastic/eui'; import { MemoryRouter } from 'react-router-dom'; +import { wait } from '@testing-library/react'; const mockHistoryPush = jest.spyOn(history, 'push'); const mockRefreshTimeRange = jest.fn(); @@ -84,7 +84,7 @@ describe('DatePicker', () => { }); expect(mockRefreshTimeRange).not.toHaveBeenCalled(); jest.advanceTimersByTime(1000); - await tick(); + await wait(); expect(mockRefreshTimeRange).toHaveBeenCalled(); wrapper.unmount(); }); @@ -94,7 +94,7 @@ describe('DatePicker', () => { mountDatePicker({ refreshPaused: true, refreshInterval: 1000 }); expect(mockRefreshTimeRange).not.toHaveBeenCalled(); jest.advanceTimersByTime(1000); - await tick(); + await wait(); expect(mockRefreshTimeRange).not.toHaveBeenCalled(); }); }); diff --git a/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/Delayed/index.ts b/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/Delayed/index.ts index 798e872dbc472..9048afe57153d 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/Delayed/index.ts +++ b/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/Delayed/index.ts @@ -57,4 +57,10 @@ export class Delayed { public onChange(onChangeCallback: Callback) { this.onChangeCallback = onChangeCallback; } + + public destroy() { + if (this.timeoutId) { + window.clearTimeout(this.timeoutId); + } + } } diff --git a/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.test.tsx index 57e634df22837..c55c6ab351848 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.test.tsx @@ -4,11 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { + renderHook, + act, + RenderHookResult +} from '@testing-library/react-hooks'; import { useDelayedVisibility } from '.'; describe('useFetcher', () => { - let hook; + let hook: RenderHookResult; + beforeEach(() => { jest.useFakeTimers(); }); @@ -26,9 +31,15 @@ describe('useFetcher', () => { }); hook.rerender(true); - jest.advanceTimersByTime(10); + act(() => { + jest.advanceTimersByTime(10); + }); + expect(hook.result.current).toEqual(false); - jest.advanceTimersByTime(50); + act(() => { + jest.advanceTimersByTime(50); + }); + expect(hook.result.current).toEqual(true); }); @@ -38,8 +49,11 @@ describe('useFetcher', () => { }); hook.rerender(true); - jest.advanceTimersByTime(100); + act(() => { + jest.advanceTimersByTime(100); + }); hook.rerender(false); + expect(hook.result.current).toEqual(true); }); @@ -49,11 +63,22 @@ describe('useFetcher', () => { }); hook.rerender(true); - jest.advanceTimersByTime(100); + + act(() => { + jest.advanceTimersByTime(100); + }); + hook.rerender(false); - jest.advanceTimersByTime(900); + act(() => { + jest.advanceTimersByTime(900); + }); + expect(hook.result.current).toEqual(true); - jest.advanceTimersByTime(100); + + act(() => { + jest.advanceTimersByTime(100); + }); + expect(hook.result.current).toEqual(false); }); }); diff --git a/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.ts b/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.ts index 5acbbd1d45737..c4465c7b42339 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.ts +++ b/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.ts @@ -26,6 +26,10 @@ export function useDelayedVisibility( setIsVisible(visibility); }); delayedRef.current = delayed; + + return () => { + delayed.destroy(); + }; }, [hideDelayMs, showDelayMs, minimumVisibleDuration]); useEffect(() => { diff --git a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/__tests__/UrlParamsContext.test.tsx b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/__tests__/UrlParamsContext.test.tsx index 2604a3a122574..d2d8036e864ae 100644 --- a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/__tests__/UrlParamsContext.test.tsx +++ b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/__tests__/UrlParamsContext.test.tsx @@ -11,8 +11,8 @@ import { Location, History } from 'history'; import { MemoryRouter, Router } from 'react-router-dom'; import moment from 'moment-timezone'; import { IUrlParams } from '../types'; -import { tick } from '../../../utils/testHelpers'; import { getParsedDate } from '../helpers'; +import { wait } from '@testing-library/react'; function mountParams(location: Location) { return mount( @@ -143,13 +143,13 @@ describe('UrlParamsContext', () => { ); - await tick(); + await wait(); expect(calls.length).toBe(1); wrapper.find('button').simulate('click'); - await tick(); + await wait(); expect(calls.length).toBe(2); @@ -194,11 +194,11 @@ describe('UrlParamsContext', () => { ); - await tick(); + await wait(); wrapper.find('button').simulate('click'); - await tick(); + await wait(); const params = getDataFromOutput(wrapper); expect(params.start).toEqual('2000-06-14T00:00:00.000Z'); diff --git a/x-pack/legacy/plugins/apm/public/hooks/useFetcher.integration.test.tsx b/x-pack/legacy/plugins/apm/public/hooks/useFetcher.integration.test.tsx index 36a8377c02527..743cf4e01e555 100644 --- a/x-pack/legacy/plugins/apm/public/hooks/useFetcher.integration.test.tsx +++ b/x-pack/legacy/plugins/apm/public/hooks/useFetcher.integration.test.tsx @@ -5,8 +5,8 @@ */ import React from 'react'; -import { render } from '@testing-library/react'; -import { delay, tick } from '../utils/testHelpers'; +import { render, wait } from '@testing-library/react'; +import { delay } from '../utils/testHelpers'; import { useFetcher } from './useFetcher'; import { KibanaCoreContext } from '../../../observability/public/context/kibana_core'; import { LegacyCoreStart } from 'kibana/public'; @@ -76,7 +76,8 @@ describe('when simulating race condition', () => { it('should render "Hello from Peter" after 200ms', async () => { jest.advanceTimersByTime(200); - await tick(); + + await wait(); expect(renderSpy).lastCalledWith({ data: 'Hello from Peter', @@ -87,7 +88,7 @@ describe('when simulating race condition', () => { it('should render "Hello from Peter" after 600ms', async () => { jest.advanceTimersByTime(600); - await tick(); + await wait(); expect(renderSpy).lastCalledWith({ data: 'Hello from Peter', @@ -98,7 +99,7 @@ describe('when simulating race condition', () => { it('should should NOT have rendered "Hello from John" at any point', async () => { jest.advanceTimersByTime(600); - await tick(); + await wait(); expect(renderSpy).not.toHaveBeenCalledWith({ data: 'Hello from John', @@ -109,7 +110,7 @@ describe('when simulating race condition', () => { it('should send and receive calls in the right order', async () => { jest.advanceTimersByTime(600); - await tick(); + await wait(); expect(requestCallOrder).toEqual([ ['request', 'John', 500], diff --git a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx index b5cee4a78b01c..9e3c486715a1f 100644 --- a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx +++ b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx @@ -58,7 +58,6 @@ export async function getRenderedHref(Component: React.FC, location: Location) { ); - await tick(); await waitForElement(() => el.container.querySelector('a')); const a = el.container.querySelector('a'); @@ -74,9 +73,6 @@ export function delay(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } -// Await this when you need to "flush" promises to immediately resolve or throw in tests -export const tick = () => new Promise(resolve => setImmediate(resolve, 0)); - export function expectTextsNotInDocument(output: any, texts: string[]) { texts.forEach(text => { try {