mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
* Hide auto interval when it is filtered * Add unit tests * Fix types
This commit is contained in:
parent
f041891336
commit
01135f6a4c
3 changed files with 228 additions and 11 deletions
60
src/plugins/vis_default_editor/public/components/controls/__snapshots__/time_interval.test.tsx.snap
generated
Normal file
60
src/plugins/vis_default_editor/public/components/controls/__snapshots__/time_interval.test.tsx.snap
generated
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TimeIntervalParamEditor should match snapshot 1`] = `
|
||||
<EuiFormRow
|
||||
describedByIds={Array []}
|
||||
display="rowCompressed"
|
||||
fullWidth={true}
|
||||
hasChildLabel={true}
|
||||
hasEmptyLabelSpace={false}
|
||||
helpText={
|
||||
<React.Fragment>
|
||||
<FormattedMessage
|
||||
defaultMessage="Select an option or create a custom value. Examples: 30s, 20m, 24h, 2d, 1w, 1M"
|
||||
id="visDefaultEditor.controls.timeInterval.selectOptionHelpText"
|
||||
values={Object {}}
|
||||
/>
|
||||
</React.Fragment>
|
||||
}
|
||||
isInvalid={true}
|
||||
label="Minimum interval"
|
||||
labelType="label"
|
||||
>
|
||||
<EuiComboBox
|
||||
async={false}
|
||||
compressed={true}
|
||||
data-test-subj="visEditorInterval"
|
||||
fullWidth={true}
|
||||
isClearable={true}
|
||||
isInvalid={true}
|
||||
noSuggestions={false}
|
||||
onBlur={[MockFunction]}
|
||||
onChange={[Function]}
|
||||
onCreateOption={[Function]}
|
||||
options={
|
||||
Array [
|
||||
Object {
|
||||
"key": "auto",
|
||||
"label": "Auto",
|
||||
},
|
||||
Object {
|
||||
"key": "ms",
|
||||
"label": "Millisecond",
|
||||
},
|
||||
Object {
|
||||
"key": "s",
|
||||
"label": "Second",
|
||||
},
|
||||
]
|
||||
}
|
||||
placeholder="Select an interval"
|
||||
selectedOptions={Array []}
|
||||
singleSelection={
|
||||
Object {
|
||||
"asPlainText": true,
|
||||
}
|
||||
}
|
||||
sortMatchesBy="none"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
`;
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { TimeIntervalParamEditor } from './time_interval';
|
||||
import { aggParamCommonPropsMock } from './test_utils';
|
||||
import { AggParamEditorProps } from '../agg_param_props';
|
||||
|
||||
jest.mock('../../../../data/public', () => ({
|
||||
search: {
|
||||
aggs: {
|
||||
isValidInterval: jest.fn().mockReturnValue(true),
|
||||
parseEsInterval: jest.fn(),
|
||||
InvalidEsCalendarIntervalError: class {},
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
import { search } from '../../../../data/public';
|
||||
|
||||
describe('TimeIntervalParamEditor', () => {
|
||||
let props: AggParamEditorProps<string>;
|
||||
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
...aggParamCommonPropsMock,
|
||||
showValidation: true,
|
||||
setTouched: jest.fn(),
|
||||
setValidity: jest.fn(),
|
||||
setValue: jest.fn(),
|
||||
};
|
||||
props.aggParam.options = [
|
||||
{
|
||||
display: 'Auto',
|
||||
enabled: jest.fn().mockReturnValue(true),
|
||||
val: 'auto',
|
||||
},
|
||||
{
|
||||
display: 'Millisecond',
|
||||
val: 'ms',
|
||||
},
|
||||
{
|
||||
display: 'Second',
|
||||
val: 's',
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
test('should match snapshot', () => {
|
||||
const comp = shallow(<TimeIntervalParamEditor {...props} />);
|
||||
expect(comp).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('interval "auto" value', () => {
|
||||
test('should convert interval options into combobox options', () => {
|
||||
props.value = 'auto';
|
||||
const comp = shallow(<TimeIntervalParamEditor {...props} />);
|
||||
|
||||
expect(comp.children().prop('selectedOptions')).toEqual([
|
||||
{
|
||||
key: 'auto',
|
||||
label: 'Auto',
|
||||
},
|
||||
]);
|
||||
expect(comp.children().prop('options')).toEqual([
|
||||
{
|
||||
key: 'auto',
|
||||
label: 'Auto',
|
||||
},
|
||||
{
|
||||
key: 'ms',
|
||||
label: 'Millisecond',
|
||||
},
|
||||
{
|
||||
key: 's',
|
||||
label: 'Second',
|
||||
},
|
||||
]);
|
||||
expect(comp.prop('isInvalid')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('should filter out "auto" interval value if it is disabled in options and mark as invalid', () => {
|
||||
props.aggParam.options[0].enabled = jest.fn().mockReturnValue(false);
|
||||
props.value = 'auto';
|
||||
const comp = shallow(<TimeIntervalParamEditor {...props} />);
|
||||
|
||||
expect(props.aggParam.options[0].enabled).toHaveBeenCalledWith(props.agg);
|
||||
expect(comp.prop('isInvalid')).toBeTruthy();
|
||||
expect(comp.children().prop('selectedOptions')).toEqual([]);
|
||||
expect(comp.children().prop('options')).toEqual([
|
||||
{
|
||||
key: 'ms',
|
||||
label: 'Millisecond',
|
||||
},
|
||||
{
|
||||
key: 's',
|
||||
label: 'Second',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('custom interval value', () => {
|
||||
test('should have valid "2h" interval selected', () => {
|
||||
props.value = '2h';
|
||||
// @ts-ignore
|
||||
props.agg.buckets = {
|
||||
getInterval: jest.fn().mockReturnValue({
|
||||
expression: '2h',
|
||||
}),
|
||||
};
|
||||
|
||||
const comp = shallow(<TimeIntervalParamEditor {...props} />);
|
||||
|
||||
expect(comp.prop('isInvalid')).toBeFalsy();
|
||||
expect(comp.prop('error')).toBeUndefined();
|
||||
expect(comp.children().prop('selectedOptions')).toEqual([{ label: '2h', key: 'custom' }]);
|
||||
});
|
||||
|
||||
test('should have invalid calendar interval "3w"', () => {
|
||||
props.value = '3w';
|
||||
// @ts-ignore
|
||||
props.agg.buckets = {
|
||||
getInterval: jest.fn().mockReturnValue({
|
||||
expression: '3w',
|
||||
}),
|
||||
};
|
||||
// @ts-expect-error
|
||||
search.aggs.isValidInterval.mockReturnValue(false);
|
||||
|
||||
const comp = shallow(<TimeIntervalParamEditor {...props} />);
|
||||
|
||||
expect(comp.prop('isInvalid')).toBeTruthy();
|
||||
expect(comp.prop('error')).toBeDefined();
|
||||
expect(comp.children().prop('selectedOptions')).toEqual([{ label: '3w', key: 'custom' }]);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -53,6 +53,7 @@ const errorMessage = i18n.translate(
|
|||
defaultMessage: 'Invalid interval format.',
|
||||
}
|
||||
);
|
||||
const autoInterval = 'auto';
|
||||
|
||||
function validateInterval(
|
||||
agg: any,
|
||||
|
@ -64,7 +65,7 @@ function validateInterval(
|
|||
return { isValid: true, interval: agg.buckets?.getInterval() };
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
if (!value || (value === autoInterval && !definedOption)) {
|
||||
return { isValid: false };
|
||||
}
|
||||
|
||||
|
@ -110,21 +111,22 @@ function TimeIntervalParamEditor({
|
|||
const timeBase: string = get(editorConfig, 'interval.timeBase') as string;
|
||||
const options = timeBase
|
||||
? []
|
||||
: ((aggParam as any).options || []).reduce(
|
||||
(filtered: ComboBoxOption[], option: AggParamOption) => {
|
||||
if (option.enabled ? option.enabled(agg) : true) {
|
||||
filtered.push({ label: option.display, key: option.val });
|
||||
}
|
||||
return filtered;
|
||||
},
|
||||
[] as ComboBoxOption[]
|
||||
);
|
||||
: (aggParam.options || []).reduce((filtered: ComboBoxOption[], option: AggParamOption) => {
|
||||
if (option.enabled ? option.enabled(agg) : true) {
|
||||
filtered.push({ label: option.display, key: option.val });
|
||||
}
|
||||
return filtered;
|
||||
}, []);
|
||||
|
||||
let selectedOptions: ComboBoxOption[] = [];
|
||||
let definedOption: ComboBoxOption | undefined;
|
||||
if (value) {
|
||||
definedOption = find(options, { key: value });
|
||||
selectedOptions = definedOption ? [definedOption] : [{ label: value, key: 'custom' }];
|
||||
selectedOptions = definedOption
|
||||
? [definedOption]
|
||||
: value === autoInterval
|
||||
? []
|
||||
: [{ label: value, key: 'custom' }];
|
||||
}
|
||||
|
||||
const { isValid, error, interval } = validateInterval(agg, value, definedOption, timeBase);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue