Skip to content

Commit

Permalink
[Lens] Filter out pinned filters from saved object of Lens (#57197)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbondyra committed Feb 13, 2020
1 parent 4437858 commit c333576
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 38 deletions.
131 changes: 94 additions & 37 deletions x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx
Expand Up @@ -38,7 +38,10 @@ jest

const { TopNavMenu } = npStart.plugins.navigation.ui;

const waitForPromises = () => new Promise(resolve => setTimeout(resolve));
const waitForPromises = async () =>
act(async () => {
await new Promise(resolve => setTimeout(resolve));
});

function createMockFrame(): jest.Mocked<EditorFrameInstance> {
return {
Expand Down Expand Up @@ -220,6 +223,7 @@ describe('Lens App', () => {
});

instance.setProps({ docId: '1234' });

await waitForPromises();

expect(defaultArgs.core.chrome.setBreadcrumbs).toHaveBeenCalledWith([
Expand Down Expand Up @@ -373,8 +377,10 @@ describe('Lens App', () => {
async function save({
initialDocId,
addToDashboardMode,
lastKnownDoc = { expression: 'kibana 3' },
...saveProps
}: SaveProps & {
lastKnownDoc?: object;
initialDocId?: string;
addToDashboardMode?: boolean;
}) {
Expand All @@ -392,6 +398,7 @@ describe('Lens App', () => {
state: {
query: 'fake query',
datasourceMetaData: { filterableIndexPatterns: [{ id: '1', title: 'saved' }] },
filters: [],
},
});
(args.docStorage.save as jest.Mock).mockImplementation(async ({ id }) => ({
Expand All @@ -410,10 +417,12 @@ describe('Lens App', () => {
}

const onChange = frame.mount.mock.calls[0][1].onChange;
onChange({
filterableIndexPatterns: [],
doc: ({ id: initialDocId, expression: 'kibana 3' } as unknown) as Document,
});
act(() =>
onChange({
filterableIndexPatterns: [],
doc: { id: initialDocId, ...lastKnownDoc } as Document,
})
);

instance.update();

Expand Down Expand Up @@ -441,10 +450,12 @@ describe('Lens App', () => {
expect(getButton(instance).disableButton).toEqual(true);

const onChange = frame.mount.mock.calls[0][1].onChange;
onChange({
filterableIndexPatterns: [],
doc: ({ id: 'will save this', expression: 'valid expression' } as unknown) as Document,
});
act(() =>
onChange({
filterableIndexPatterns: [],
doc: ({ id: 'will save this', expression: 'valid expression' } as unknown) as Document,
})
);
instance.update();
expect(getButton(instance).disableButton).toEqual(true);
});
Expand Down Expand Up @@ -482,10 +493,12 @@ describe('Lens App', () => {
expect(getButton(instance).disableButton).toEqual(true);

const onChange = frame.mount.mock.calls[0][1].onChange;
onChange({
filterableIndexPatterns: [],
doc: ({ id: 'will save this', expression: 'valid expression' } as unknown) as Document,
});
act(() =>
onChange({
filterableIndexPatterns: [],
doc: ({ id: 'will save this', expression: 'valid expression' } as unknown) as Document,
})
);
instance.update();

expect(getButton(instance).disableButton).toEqual(false);
Expand Down Expand Up @@ -559,10 +572,12 @@ describe('Lens App', () => {
const instance = mount(<App {...args} />);

const onChange = frame.mount.mock.calls[0][1].onChange;
onChange({
filterableIndexPatterns: [],
doc: ({ id: undefined, expression: 'new expression' } as unknown) as Document,
});
act(() =>
onChange({
filterableIndexPatterns: [],
doc: ({ id: undefined, expression: 'new expression' } as unknown) as Document,
})
);

instance.update();

Expand Down Expand Up @@ -593,6 +608,38 @@ describe('Lens App', () => {

expect(args.redirectTo).toHaveBeenCalledWith('aaa');
});

it('saves app filters and does not save pinned filters', async () => {
const indexPattern = ({ id: 'index1' } as unknown) as IIndexPattern;
const field = ({ name: 'myfield' } as unknown) as IFieldType;
const pinnedField = ({ name: 'pinnedField' } as unknown) as IFieldType;

const unpinned = esFilters.buildExistsFilter(field, indexPattern);
const pinned = esFilters.buildExistsFilter(pinnedField, indexPattern);
FilterManager.setFiltersStore([pinned], esFilters.FilterStateStore.GLOBAL_STATE);
await waitForPromises();

const { args } = await save({
initialDocId: '1234',
newCopyOnSave: false,
newTitle: 'hello there2',
lastKnownDoc: {
expression: 'kibana 3',
state: {
filters: [pinned, unpinned],
},
},
});

expect(args.docStorage.save).toHaveBeenCalledWith({
id: '1234',
title: 'hello there2',
expression: 'kibana 3',
state: {
filters: [unpinned],
},
});
});
});
});

Expand Down Expand Up @@ -658,10 +705,12 @@ describe('Lens App', () => {
);

const onChange = frame.mount.mock.calls[0][1].onChange;
onChange({
filterableIndexPatterns: [{ id: '1', title: 'newIndex' }],
doc: ({ id: undefined, expression: 'valid expression' } as unknown) as Document,
});
act(() =>
onChange({
filterableIndexPatterns: [{ id: '1', title: 'newIndex' }],
doc: ({ id: undefined, expression: 'valid expression' } as unknown) as Document,
})
);

await waitForPromises();
instance.update();
Expand All @@ -674,12 +723,15 @@ describe('Lens App', () => {
);

// Do it again to verify that the dirty checking is done right
onChange({
filterableIndexPatterns: [{ id: '2', title: 'second index' }],
doc: ({ id: undefined, expression: 'valid expression' } as unknown) as Document,
});
act(() =>
onChange({
filterableIndexPatterns: [{ id: '2', title: 'second index' }],
doc: ({ id: undefined, expression: 'valid expression' } as unknown) as Document,
})
);

await waitForPromises();

instance.update();

expect(TopNavMenu).toHaveBeenLastCalledWith(
Expand All @@ -689,17 +741,18 @@ describe('Lens App', () => {
{}
);
});

it('updates the editor frame when the user changes query or time in the search bar', () => {
const args = defaultArgs;
args.editorFrame = frame;

const instance = mount(<App {...args} />);

instance.find(TopNavMenu).prop('onQuerySubmit')!({
dateRange: { from: 'now-14d', to: 'now-7d' },
query: { query: 'new', language: 'lucene' },
});
act(() =>
instance.find(TopNavMenu).prop('onQuerySubmit')!({
dateRange: { from: 'now-14d', to: 'now-7d' },
query: { query: 'new', language: 'lucene' },
})
);

instance.update();

Expand Down Expand Up @@ -728,7 +781,9 @@ describe('Lens App', () => {
const indexPattern = ({ id: 'index1' } as unknown) as IIndexPattern;
const field = ({ name: 'myfield' } as unknown) as IFieldType;

args.data.query.filterManager.setFilters([esFilters.buildExistsFilter(field, indexPattern)]);
act(() =>
args.data.query.filterManager.setFilters([esFilters.buildExistsFilter(field, indexPattern)])
);

instance.update();

Expand Down Expand Up @@ -852,10 +907,12 @@ describe('Lens App', () => {

const instance = mount(<App {...args} />);

instance.find(TopNavMenu).prop('onQuerySubmit')!({
dateRange: { from: 'now-14d', to: 'now-7d' },
query: { query: 'new', language: 'lucene' },
});
act(() =>
instance.find(TopNavMenu).prop('onQuerySubmit')!({
dateRange: { from: 'now-14d', to: 'now-7d' },
query: { query: 'new', language: 'lucene' },
})
);

const indexPattern = ({ id: 'index1' } as unknown) as IIndexPattern;
const field = ({ name: 'myfield' } as unknown) as IFieldType;
Expand All @@ -865,10 +922,10 @@ describe('Lens App', () => {
const pinned = esFilters.buildExistsFilter(pinnedField, indexPattern);
FilterManager.setFiltersStore([pinned], esFilters.FilterStateStore.GLOBAL_STATE);

args.data.query.filterManager.setFilters([pinned, unpinned]);
act(() => args.data.query.filterManager.setFilters([pinned, unpinned]));
instance.update();

instance.find(TopNavMenu).prop('onClearSavedQuery')!();
act(() => instance.find(TopNavMenu).prop('onClearSavedQuery')!());
instance.update();

expect(frame.mount).toHaveBeenLastCalledWith(
Expand Down
17 changes: 16 additions & 1 deletion x-pack/legacy/plugins/lens/public/app_plugin/app.tsx
Expand Up @@ -20,6 +20,7 @@ import { EditorFrameInstance } from '../types';
import { NativeRenderer } from '../native_renderer';
import { trackUiEvent } from '../lens_ui_telemetry';
import {
esFilters,
Filter,
IndexPattern as IndexPatternInstance,
IndexPatternsContract,
Expand Down Expand Up @@ -320,8 +321,22 @@ export function App({
{lastKnownDoc && state.isSaveModalVisible && (
<SavedObjectSaveModal
onSave={props => {
const [pinnedFilters, appFilters] = _.partition(
lastKnownDoc.state?.filters,
esFilters.isFilterPinned
);
const lastDocWithoutPinned = pinnedFilters?.length
? {
...lastKnownDoc,
state: {
...lastKnownDoc.state,
filters: appFilters,
},
}
: lastKnownDoc;

const doc = {
...lastKnownDoc,
...lastDocWithoutPinned,
id: props.newCopyOnSave ? undefined : lastKnownDoc.id,
title: props.newTitle,
};
Expand Down

0 comments on commit c333576

Please sign in to comment.