From bb3a5319e1752e3b020bb5b0f1f8a4b69a1ad7c1 Mon Sep 17 00:00:00 2001 From: nreese Date: Wed, 22 Feb 2023 15:17:40 -0700 Subject: [PATCH] map_embeddable unit tests --- .../filterable_embeddable/should_fetch.tsx | 7 +- .../lens/public/embeddable/embeddable.tsx | 1 - .../public/embeddable/map_embeddable.test.tsx | 159 ++++++++++++++++++ 3 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/maps/public/embeddable/map_embeddable.test.tsx diff --git a/src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx b/src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx index 253734e3fbb0a..f162e22d56ec5 100644 --- a/src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx +++ b/src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx @@ -8,7 +8,7 @@ import fastIsEqual from 'fast-deep-equal'; import { Observable } from 'rxjs'; -import { map, distinctUntilChanged } from 'rxjs/operators'; +import { map, distinctUntilChanged, skip, startWith } from 'rxjs/operators'; import type { Filter, Query, TimeRange } from '@kbn/es-query'; import { COMPARE_ALL_OPTIONS, onlyDisabledFiltersChanged } from '@kbn/es-query'; import { EmbeddableInput } from '../embeddables'; @@ -33,6 +33,8 @@ export function shouldFetch$< getInput: () => TFilterableEmbeddableInput ): Observable { return updated$.pipe(map(() => getInput())).pipe( + // wrapping distinctUntilChanged with startWith and skip to prime distinctUntilChanged with an initial input value. + startWith(getInput()), distinctUntilChanged((a: TFilterableEmbeddableInput, b: TFilterableEmbeddableInput) => { if ( !fastIsEqual( @@ -44,6 +46,7 @@ export function shouldFetch$< } return onlyDisabledFiltersChanged(a.filters, b.filters, shouldRefreshFilterCompareOptions); - }) + }), + skip(1) ); } diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.tsx index 225b31d04136e..4586f37451898 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.tsx @@ -503,7 +503,6 @@ export class Embeddable // Update search context and reload on changes related to search this.inputReloadSubscriptions.push( shouldFetch$(this.getUpdated$(), () => this.getInput()) - .pipe(skip(1)) .subscribe((input) => { this.onContainerStateChanged(input); }) diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.test.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.test.tsx new file mode 100644 index 0000000000000..3af244c74becd --- /dev/null +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.test.tsx @@ -0,0 +1,159 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { v4 as uuidv4 } from 'uuid'; +import { map, distinctUntilChanged } from 'rxjs/operators'; +import { MapEmbeddable } from './map_embeddable'; + +jest.mock('../kibana_services', () => { + return { + getHttp() { + return { + basePath: { + prepend: (url) => url, + }, + }; + }, + getMapsCapabilities() { + return { save: true }; + }, + getSearchService() { + return { + session: { + getSearchOptions() { + return undefined; + } + } + }; + }, + getShowMapsInspectorAdapter() { + return false; + }, + getTimeFilter() { + return { + getTime() { + return { from: 'now-7d', to: 'now' }; + } + } + } + }; +}); + +jest.mock('../connected_components/map_container', () => { + return { + MapContainer: () => { + return
mockLayerTOC
; + }, + }; +}); + +import { MapContainer } from '../connected_components/map_container'; + +jest.mock('../routes/map_page', () => { + class MockSavedMap { + // eslint-disable-next-line @typescript-eslint/no-var-requires + private _store = require('../reducers/store').createMapStore(); + private _attributes = { + title: 'myMap' + }; + + whenReady = async function() {} + + getStore = function() { + return this._store; + } + getAttributes = function() { + return this._attributes; + } + getAutoFitToBounds = function() { + return true; + } + getSharingSavedObjectProps = function() { + return null; + } + } + return { SavedMap: MockSavedMap }; +}); + +function untilInitialized(mapEmbeddable: MapEmbeddable) { + return new Promise((resolve) => { + mapEmbeddable.setInitializationFinished = () => { + resolve(); + } + }); +} + +function onNextTick() { + // wait one tick to give observables time to fire + return new Promise((resolve) => setTimeout(resolve, 0)); +} + +describe('shouldFetch$', () => { + test('should not fetch when search context does not change', async () => { + const mapEmbeddable = new MapEmbeddable( + {}, + { + id: 'map1', + } + ); + await untilInitialized(mapEmbeddable); + + const fetchSpy = jest.spyOn(mapEmbeddable, '_dispatchSetQuery'); + + mapEmbeddable.updateInput({ + title: 'updated map title' + }); + + await onNextTick(); + + expect(fetchSpy).not.toHaveBeenCalled(); + }); + + describe('on searchSessionId change', () => { + test('should fetch when filterByMapExtent is false', async () => { + const mapEmbeddable = new MapEmbeddable( + {}, + { + id: 'map1', + filterByMapExtent: false, + } + ); + await untilInitialized(mapEmbeddable); + + const fetchSpy = jest.spyOn(mapEmbeddable, '_dispatchSetQuery'); + + mapEmbeddable.updateInput({ + searchSessionId: uuidv4() + }); + + await onNextTick(); + + expect(fetchSpy).toHaveBeenCalled(); + }); + + test('should not fetch when filterByMapExtent is true', async () => { + const mapEmbeddable = new MapEmbeddable( + {}, + { + id: 'map1', + filterByMapExtent: true, + } + ); + await untilInitialized(mapEmbeddable); + + const fetchSpy = jest.spyOn(mapEmbeddable, '_dispatchSetQuery'); + + mapEmbeddable.updateInput({ + searchSessionId: uuidv4() + }); + + await onNextTick(); + + expect(fetchSpy).not.toHaveBeenCalled(); + }); + }); +}); \ No newline at end of file