-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Reactify visualize app * Fix typescript failures after merging master * Make sure refresh button works * Subscribe filter manager fetches * Use redirect to landing page * Update savedSearch type * Add check for TSVB is loaded * Add unit tests for useSavedVisInstance effect * Fix comments * Fix uiState persistence on vis load * Remove extra div around TableListView * Update DTS selectors * Add error handling for embeddable * Add unit tests for createVisualizeAppState * Add unit tests for useChromeVisibility * Add filter_manager.mock * Add unit tests for useVisualizeAppState * Use app state stub * Add unit tests for useLinkedSearchUpdates * Add unit tests for useEditorUpdates * Remove extra argument from useEditorUpdates effect * Update comments, fix typos * Remove extra div wrapper * Apply design suggestions * Revert accidental config changes * Add unit tests for useEditorUpdates * Use visualize services mock * Add unit tests for getVisualizationInstance * Fix eslint warnings Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
- Loading branch information
1 parent
0ebddcf
commit 1c91b1c
Showing
13 changed files
with
1,331 additions
and
4 deletions.
There are no files selected for viewing
42 changes: 42 additions & 0 deletions
42
src/plugins/data/public/query/filter_manager/filter_manager.mock.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import { Observable } from 'rxjs'; | ||
import { FilterManager } from './filter_manager'; | ||
|
||
export const createFilterManagerMock = () => { | ||
const filterManager = ({ | ||
mergeIncomingFilters: jest.fn(), | ||
handleStateUpdate: jest.fn(), | ||
getFilters: jest.fn(), | ||
getAppFilters: jest.fn(), | ||
getGlobalFilters: jest.fn(), | ||
getPartitionedFilters: jest.fn(), | ||
getUpdates$: jest.fn(() => new Observable()), | ||
getFetches$: jest.fn(() => new Observable()), | ||
addFilters: jest.fn(), | ||
setFilters: jest.fn(), | ||
setGlobalFilters: jest.fn(), | ||
setAppFilters: jest.fn(), | ||
removeFilter: jest.fn(), | ||
removeAll: jest.fn(), | ||
} as unknown) as jest.Mocked<FilterManager>; | ||
|
||
return filterManager; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
134 changes: 134 additions & 0 deletions
134
src/plugins/visualize/public/application/utils/create_visualize_app_state.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import { IKbnUrlStateStorage } from 'src/plugins/kibana_utils/public'; | ||
import { createVisualizeAppState } from './create_visualize_app_state'; | ||
import { migrateAppState } from './migrate_app_state'; | ||
import { visualizeAppStateStub } from './stubs'; | ||
|
||
const mockStartStateSync = jest.fn(); | ||
const mockStopStateSync = jest.fn(); | ||
|
||
jest.mock('../../../../kibana_utils/public', () => ({ | ||
createStateContainer: jest.fn(() => 'stateContainer'), | ||
syncState: jest.fn(() => ({ | ||
start: mockStartStateSync, | ||
stop: mockStopStateSync, | ||
})), | ||
})); | ||
jest.mock('./migrate_app_state', () => ({ | ||
migrateAppState: jest.fn(() => 'migratedAppState'), | ||
})); | ||
|
||
const { createStateContainer, syncState } = jest.requireMock('../../../../kibana_utils/public'); | ||
|
||
describe('createVisualizeAppState', () => { | ||
const kbnUrlStateStorage = ({ | ||
set: jest.fn(), | ||
get: jest.fn(() => ({ linked: false })), | ||
} as unknown) as IKbnUrlStateStorage; | ||
|
||
const { stateContainer, stopStateSync } = createVisualizeAppState({ | ||
stateDefaults: visualizeAppStateStub, | ||
kbnUrlStateStorage, | ||
}); | ||
const transitions = createStateContainer.mock.calls[0][1]; | ||
|
||
test('should initialize visualize app state', () => { | ||
expect(kbnUrlStateStorage.get).toHaveBeenCalledWith('_a'); | ||
expect(migrateAppState).toHaveBeenCalledWith({ | ||
...visualizeAppStateStub, | ||
linked: false, | ||
}); | ||
expect(kbnUrlStateStorage.set).toHaveBeenCalledWith('_a', 'migratedAppState', { | ||
replace: true, | ||
}); | ||
expect(createStateContainer).toHaveBeenCalled(); | ||
expect(syncState).toHaveBeenCalled(); | ||
expect(mockStartStateSync).toHaveBeenCalled(); | ||
}); | ||
|
||
test('should return the stateContainer and stopStateSync', () => { | ||
expect(stateContainer).toBe('stateContainer'); | ||
stopStateSync(); | ||
expect(stopStateSync).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
describe('stateContainer transitions', () => { | ||
test('set', () => { | ||
const newQuery = { query: '', language: '' }; | ||
expect(transitions.set(visualizeAppStateStub)('query', newQuery)).toEqual({ | ||
...visualizeAppStateStub, | ||
query: newQuery, | ||
}); | ||
}); | ||
|
||
test('setVis', () => { | ||
const newVis = { data: 'data' }; | ||
expect(transitions.setVis(visualizeAppStateStub)(newVis)).toEqual({ | ||
...visualizeAppStateStub, | ||
vis: { | ||
...visualizeAppStateStub.vis, | ||
...newVis, | ||
}, | ||
}); | ||
}); | ||
|
||
test('unlinkSavedSearch', () => { | ||
const params = { | ||
query: { query: '', language: '' }, | ||
parentFilters: [{ test: 'filter2' }], | ||
}; | ||
expect(transitions.unlinkSavedSearch(visualizeAppStateStub)(params)).toEqual({ | ||
...visualizeAppStateStub, | ||
query: params.query, | ||
filters: [...visualizeAppStateStub.filters, { test: 'filter2' }], | ||
linked: false, | ||
}); | ||
}); | ||
|
||
test('updateVisState: should not include resctricted param types', () => { | ||
const newVisState = { | ||
a: 1, | ||
_b: 2, | ||
$c: 3, | ||
d: () => {}, | ||
}; | ||
expect(transitions.updateVisState(visualizeAppStateStub)(newVisState)).toEqual({ | ||
...visualizeAppStateStub, | ||
vis: { a: 1 }, | ||
}); | ||
}); | ||
|
||
test('updateSavedQuery: add savedQuery', () => { | ||
const savedQueryId = '123test'; | ||
expect(transitions.updateSavedQuery(visualizeAppStateStub)(savedQueryId)).toEqual({ | ||
...visualizeAppStateStub, | ||
savedQuery: savedQueryId, | ||
}); | ||
}); | ||
|
||
test('updateSavedQuery: remove savedQuery from state', () => { | ||
const savedQueryId = '123test'; | ||
expect( | ||
transitions.updateSavedQuery({ ...visualizeAppStateStub, savedQuery: savedQueryId })() | ||
).toEqual(visualizeAppStateStub); | ||
}); | ||
}); | ||
}); |
124 changes: 124 additions & 0 deletions
124
src/plugins/visualize/public/application/utils/get_visualization_instance.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import { createSavedSearchesLoader } from '../../../../discover/public'; | ||
import { getVisualizationInstance } from './get_visualization_instance'; | ||
import { createVisualizeServicesMock } from './mocks'; | ||
import { VisualizeServices } from '../types'; | ||
import { BehaviorSubject } from 'rxjs'; | ||
|
||
const mockSavedSearchObj = {}; | ||
const mockGetSavedSearch = jest.fn(() => mockSavedSearchObj); | ||
|
||
jest.mock('../../../../discover/public', () => ({ | ||
createSavedSearchesLoader: jest.fn(() => ({ | ||
get: mockGetSavedSearch, | ||
})), | ||
})); | ||
|
||
describe('getVisualizationInstance', () => { | ||
const serializedVisMock = { | ||
type: 'area', | ||
}; | ||
let savedVisMock: any; | ||
let visMock: any; | ||
let mockServices: jest.Mocked<VisualizeServices>; | ||
let subj: BehaviorSubject<any>; | ||
|
||
beforeEach(() => { | ||
mockServices = createVisualizeServicesMock(); | ||
subj = new BehaviorSubject({}); | ||
visMock = { | ||
type: {}, | ||
data: {}, | ||
}; | ||
savedVisMock = {}; | ||
// @ts-expect-error | ||
mockServices.savedVisualizations.get.mockImplementation(() => savedVisMock); | ||
// @ts-expect-error | ||
mockServices.visualizations.convertToSerializedVis.mockImplementation(() => serializedVisMock); | ||
// @ts-expect-error | ||
mockServices.visualizations.createVis.mockImplementation(() => visMock); | ||
// @ts-expect-error | ||
mockServices.createVisEmbeddableFromObject.mockImplementation(() => ({ | ||
getOutput$: jest.fn(() => subj.asObservable()), | ||
})); | ||
}); | ||
|
||
test('should create new instances of savedVis, vis and embeddableHandler', async () => { | ||
const opts = { | ||
type: 'area', | ||
indexPattern: 'my_index_pattern', | ||
}; | ||
const { savedVis, savedSearch, vis, embeddableHandler } = await getVisualizationInstance( | ||
mockServices, | ||
opts | ||
); | ||
|
||
expect(mockServices.savedVisualizations.get).toHaveBeenCalledWith(opts); | ||
expect(savedVisMock.searchSourceFields).toEqual({ | ||
index: opts.indexPattern, | ||
}); | ||
expect(mockServices.visualizations.convertToSerializedVis).toHaveBeenCalledWith(savedVisMock); | ||
expect(mockServices.visualizations.createVis).toHaveBeenCalledWith( | ||
serializedVisMock.type, | ||
serializedVisMock | ||
); | ||
expect(mockServices.createVisEmbeddableFromObject).toHaveBeenCalledWith(visMock, { | ||
timeRange: undefined, | ||
filters: undefined, | ||
id: '', | ||
}); | ||
|
||
expect(vis).toBe(visMock); | ||
expect(savedVis).toBe(savedVisMock); | ||
expect(embeddableHandler).toBeDefined(); | ||
expect(savedSearch).toBeUndefined(); | ||
}); | ||
|
||
test('should load existing vis by id and call vis type setup if exists', async () => { | ||
const newVisObj = { data: {} }; | ||
visMock.type.setup = jest.fn(() => newVisObj); | ||
const { vis } = await getVisualizationInstance(mockServices, 'saved_vis_id'); | ||
|
||
expect(mockServices.savedVisualizations.get).toHaveBeenCalledWith('saved_vis_id'); | ||
expect(savedVisMock.searchSourceFields).toBeUndefined(); | ||
expect(visMock.type.setup).toHaveBeenCalledWith(visMock); | ||
expect(vis).toBe(newVisObj); | ||
}); | ||
|
||
test('should create saved search instance if vis based on saved search id', async () => { | ||
visMock.data.savedSearchId = 'saved_search_id'; | ||
const { savedSearch } = await getVisualizationInstance(mockServices, 'saved_vis_id'); | ||
|
||
expect(createSavedSearchesLoader).toHaveBeenCalled(); | ||
expect(mockGetSavedSearch).toHaveBeenCalledWith(visMock.data.savedSearchId); | ||
expect(savedSearch).toBe(mockSavedSearchObj); | ||
}); | ||
|
||
test('should subscribe on embeddable handler updates and send toasts on errors', async () => { | ||
await getVisualizationInstance(mockServices, 'saved_vis_id'); | ||
|
||
subj.next({ | ||
error: 'error', | ||
}); | ||
|
||
expect(mockServices.toastNotifications.addError).toHaveBeenCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import { coreMock } from '../../../../../core/public/mocks'; | ||
import { dataPluginMock } from '../../../../data/public/mocks'; | ||
import { visualizationsPluginMock } from '../../../../visualizations/public/mocks'; | ||
import { VisualizeServices } from '../types'; | ||
|
||
export const createVisualizeServicesMock = () => { | ||
const coreStartMock = coreMock.createStart(); | ||
const dataStartMock = dataPluginMock.createStartContract(); | ||
const toastNotifications = coreStartMock.notifications.toasts; | ||
const visualizations = visualizationsPluginMock.createStartContract(); | ||
|
||
return ({ | ||
...coreStartMock, | ||
data: dataStartMock, | ||
toastNotifications, | ||
history: { | ||
replace: jest.fn(), | ||
location: { pathname: '' }, | ||
}, | ||
visualizations, | ||
savedVisualizations: visualizations.savedVisualizationsLoader, | ||
createVisEmbeddableFromObject: visualizations.__LEGACY.createVisEmbeddableFromObject, | ||
} as unknown) as jest.Mocked<VisualizeServices>; | ||
}; |
Oops, something went wrong.