diff --git a/src/legacy/ui/public/vis/editors/default/components/__snapshots__/default_editor_agg.test.tsx.snap b/src/legacy/ui/public/vis/editors/default/components/__snapshots__/default_editor_agg.test.tsx.snap
new file mode 100644
index 00000000000000..5790e0d4e872f5
--- /dev/null
+++ b/src/legacy/ui/public/vis/editors/default/components/__snapshots__/default_editor_agg.test.tsx.snap
@@ -0,0 +1,69 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`DefaultEditorAgg component should init with the default set of props 1`] = `
+
+ Schema name
+
+
+ }
+ buttonContentClassName="visEditorSidebar__aggGroupAccordionButtonContent eui-textTruncate"
+ className="visEditorSidebar__section visEditorSidebar__collapsible visEditorSidebar__collapsible--marginBottom"
+ data-test-subj="visEditorAggAccordion1"
+ extraAction={
+
+
+
+
+
+ }
+ id="visEditorAggAccordion1"
+ initialIsOpen={true}
+ onToggle={[Function]}
+ paddingSize="none"
+>
+
+
+
+`;
diff --git a/src/legacy/ui/public/vis/editors/default/components/__snapshots__/default_editor_agg_group.test.tsx.snap b/src/legacy/ui/public/vis/editors/default/components/__snapshots__/default_editor_agg_group.test.tsx.snap
new file mode 100644
index 00000000000000..813b7978d26671
--- /dev/null
+++ b/src/legacy/ui/public/vis/editors/default/components/__snapshots__/default_editor_agg_group.test.tsx.snap
@@ -0,0 +1,42 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`DefaultEditorAgg component should init with the default set of props 1`] = `
+
+
+
+
+ Metrics
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/src/legacy/ui/public/vis/editors/default/components/default_editor_agg.test.tsx b/src/legacy/ui/public/vis/editors/default/components/default_editor_agg.test.tsx
new file mode 100644
index 00000000000000..ce12b18cf777af
--- /dev/null
+++ b/src/legacy/ui/public/vis/editors/default/components/default_editor_agg.test.tsx
@@ -0,0 +1,279 @@
+/*
+ * 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 { mount, shallow } from 'enzyme';
+import { VisState } from 'ui/vis';
+import { AggGroupNames } from '../agg_groups';
+import { DefaultEditorAgg, DefaultEditorAggProps } from './default_editor_agg';
+import { act } from 'react-dom/test-utils';
+import { DefaultEditorAggParams } from './default_editor_agg_params';
+
+jest.mock('./default_editor_agg_params', () => ({
+ DefaultEditorAggParams: () => null,
+}));
+
+describe('DefaultEditorAgg component', () => {
+ let defaultProps: DefaultEditorAggProps;
+ let onAggParamsChange: jest.Mock;
+ let setTouched: jest.Mock;
+ let onToggleEnableAgg: jest.Mock;
+ let removeAgg: jest.Mock;
+ let setValidity: jest.Mock;
+
+ beforeEach(() => {
+ onAggParamsChange = jest.fn();
+ setTouched = jest.fn();
+ onToggleEnableAgg = jest.fn();
+ removeAgg = jest.fn();
+ setValidity = jest.fn();
+
+ defaultProps = {
+ agg: {
+ id: 1,
+ brandNew: true,
+ getIndexPattern: () => ({}),
+ schema: { title: 'Schema name' },
+ title: 'Metrics',
+ params: {},
+ },
+ aggIndex: 0,
+ aggIsTooLow: false,
+ dragHandleProps: null,
+ formIsTouched: false,
+ groupName: AggGroupNames.Metrics,
+ isDraggable: false,
+ isLastBucket: false,
+ isRemovable: false,
+ metricAggs: [],
+ state: {} as VisState,
+ onAggParamsChange,
+ onAggTypeChange: () => {},
+ setValidity,
+ setTouched,
+ onToggleEnableAgg,
+ removeAgg,
+ };
+ });
+
+ it('should init with the default set of props', () => {
+ const comp = shallow();
+
+ expect(comp).toMatchSnapshot();
+ });
+
+ it('should open accordion initially', () => {
+ const comp = shallow();
+
+ expect(comp.props()).toHaveProperty('initialIsOpen', true);
+ });
+
+ it('should not show description when agg is invalid', () => {
+ defaultProps.agg.brandNew = false;
+ const comp = mount();
+
+ act(() => {
+ comp
+ .find(DefaultEditorAggParams)
+ .props()
+ .setValidity(false);
+ });
+ comp.update();
+ expect(setValidity).toBeCalledWith(false);
+
+ expect(
+ comp.find('.visEditorSidebar__aggGroupAccordionButtonContent span').exists()
+ ).toBeFalsy();
+ });
+
+ it('should show description when agg is valid', () => {
+ defaultProps.agg.brandNew = false;
+ defaultProps.agg.type = {
+ makeLabel: () => 'Agg description',
+ };
+ const comp = mount();
+
+ act(() => {
+ comp
+ .find(DefaultEditorAggParams)
+ .props()
+ .setValidity(true);
+ });
+ comp.update();
+ expect(setValidity).toBeCalledWith(true);
+
+ expect(comp.find('.visEditorSidebar__aggGroupAccordionButtonContent span').text()).toBe(
+ 'Agg description'
+ );
+ });
+
+ it('should call setTouched when accordion is collapsed', () => {
+ const comp = mount();
+ expect(defaultProps.setTouched).toBeCalledTimes(0);
+
+ comp.find('.euiAccordion__button').simulate('click');
+ // make sure that the accordion is collapsed
+ expect(comp.find('.euiAccordion-isOpen').exists()).toBeFalsy();
+
+ expect(defaultProps.setTouched).toBeCalledWith(true);
+ });
+
+ it('should call setValidity inside onSetValidity', () => {
+ const comp = mount();
+
+ act(() => {
+ comp
+ .find(DefaultEditorAggParams)
+ .props()
+ .setValidity(false);
+ });
+
+ expect(setValidity).toBeCalledWith(false);
+
+ expect(
+ comp.find('.visEditorSidebar__aggGroupAccordionButtonContent span').exists()
+ ).toBeFalsy();
+ });
+
+ it('should add schema component', () => {
+ defaultProps.agg.schema = {
+ editorComponent: () =>
,
+ };
+ const comp = mount();
+
+ expect(comp.find('.schemaComponent').exists()).toBeTruthy();
+ });
+
+ describe('agg actions', () => {
+ beforeEach(() => {
+ defaultProps.agg.enabled = true;
+ });
+
+ it('should not have actions', () => {
+ const comp = shallow();
+ const actions = shallow(comp.prop('extraAction'));
+
+ expect(actions.children().exists()).toBeFalsy();
+ });
+
+ it('should have disable and remove actions', () => {
+ defaultProps.isRemovable = true;
+ const comp = mount();
+
+ expect(
+ comp.find('[data-test-subj="toggleDisableAggregationBtn disable"] button').exists()
+ ).toBeTruthy();
+ expect(comp.find('[data-test-subj="removeDimensionBtn"] button').exists()).toBeTruthy();
+ });
+
+ it('should have draggable action', () => {
+ defaultProps.isDraggable = true;
+ const comp = mount();
+
+ expect(comp.find('[data-test-subj="dragHandleBtn"]').exists()).toBeTruthy();
+ });
+
+ it('should disable agg', () => {
+ defaultProps.isRemovable = true;
+ const comp = mount();
+ comp.find('[data-test-subj="toggleDisableAggregationBtn disable"] button').simulate('click');
+
+ expect(defaultProps.onToggleEnableAgg).toBeCalledWith(defaultProps.agg, false);
+ });
+
+ it('should enable agg', () => {
+ defaultProps.agg.enabled = false;
+ const comp = mount();
+ comp.find('[data-test-subj="toggleDisableAggregationBtn enable"] button').simulate('click');
+
+ expect(defaultProps.onToggleEnableAgg).toBeCalledWith(defaultProps.agg, true);
+ });
+
+ it('should call removeAgg', () => {
+ defaultProps.isRemovable = true;
+ const comp = mount();
+ comp.find('[data-test-subj="removeDimensionBtn"] button').simulate('click');
+
+ expect(defaultProps.removeAgg).toBeCalledWith(defaultProps.agg);
+ });
+ });
+
+ describe('last bucket', () => {
+ beforeEach(() => {
+ defaultProps.isLastBucket = true;
+ defaultProps.lastParentPipelineAggTitle = 'ParentPipelineAgg';
+ });
+
+ it('should disable min_doc_count when agg is histogram or date_histogram', () => {
+ defaultProps.agg.type = {
+ name: 'histogram',
+ };
+ const compHistogram = shallow();
+ defaultProps.agg.type = {
+ name: 'date_histogram',
+ };
+ const compDateHistogram = shallow();
+
+ expect(compHistogram.find(DefaultEditorAggParams).props()).toHaveProperty('disabledParams', [
+ 'min_doc_count',
+ ]);
+ expect(compDateHistogram.find(DefaultEditorAggParams).props()).toHaveProperty(
+ 'disabledParams',
+ ['min_doc_count']
+ );
+ });
+
+ it('should set error when agg is not histogram or date_histogram', () => {
+ defaultProps.agg.type = {
+ name: 'aggType',
+ };
+ const comp = shallow();
+
+ expect(comp.find(DefaultEditorAggParams).prop('aggError')).toBeDefined();
+ });
+
+ it('should set min_doc_count to true when agg type was changed to histogram', () => {
+ defaultProps.agg.type = {
+ name: 'aggType',
+ };
+ const comp = mount();
+ comp.setProps({ agg: { ...defaultProps.agg, type: { name: 'histogram' } } });
+
+ expect(defaultProps.onAggParamsChange).toHaveBeenCalledWith(
+ defaultProps.agg.params,
+ 'min_doc_count',
+ true
+ );
+ });
+
+ it('should set min_doc_count to 0 when agg type was changed to date_histogram', () => {
+ defaultProps.agg.type = {
+ name: 'aggType',
+ };
+ const comp = mount();
+ comp.setProps({ agg: { ...defaultProps.agg, type: { name: 'date_histogram' } } });
+
+ expect(defaultProps.onAggParamsChange).toHaveBeenCalledWith(
+ defaultProps.agg.params,
+ 'min_doc_count',
+ 0
+ );
+ });
+ });
+});
diff --git a/src/legacy/ui/public/vis/editors/default/components/default_editor_agg.tsx b/src/legacy/ui/public/vis/editors/default/components/default_editor_agg.tsx
index 7d6bc34ac06c9b..40fb8a7b63a297 100644
--- a/src/legacy/ui/public/vis/editors/default/components/default_editor_agg.tsx
+++ b/src/legacy/ui/public/vis/editors/default/components/default_editor_agg.tsx
@@ -32,7 +32,7 @@ import { AggConfig } from '../../../';
import { DefaultEditorAggParams } from './default_editor_agg_params';
import { DefaultEditorAggCommonProps } from './default_editor_agg_common_props';
-interface DefaultEditorAggProps extends DefaultEditorAggCommonProps {
+export interface DefaultEditorAggProps extends DefaultEditorAggCommonProps {
agg: AggConfig;
aggIndex: number;
aggIsTooLow: boolean;
@@ -137,7 +137,7 @@ function DefaultEditorAgg({
tooltip: i18n.translate('common.ui.vis.editors.agg.disableAggButtonTooltip', {
defaultMessage: 'Disable aggregation',
}),
- dataTestSubj: 'toggleDisableAggregationBtn',
+ dataTestSubj: 'toggleDisableAggregationBtn disable',
});
}
if (!agg.enabled) {
@@ -149,7 +149,7 @@ function DefaultEditorAgg({
tooltip: i18n.translate('common.ui.vis.editors.agg.enableAggButtonTooltip', {
defaultMessage: 'Enable aggregation',
}),
- dataTestSubj: 'toggleDisableAggregationBtn',
+ dataTestSubj: 'toggleDisableAggregationBtn enable',
});
}
if (isDraggable) {
diff --git a/src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group.test.tsx b/src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group.test.tsx
new file mode 100644
index 00000000000000..17be226e32db61
--- /dev/null
+++ b/src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group.test.tsx
@@ -0,0 +1,221 @@
+/*
+ * 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 { mount, shallow } from 'enzyme';
+import { act } from 'react-dom/test-utils';
+import { VisState } from '../../../';
+import { Schema } from '../schemas';
+import { AggGroupNames } from '../agg_groups';
+import { AggConfig } from '../../../agg_config';
+import { AggConfigs } from '../../../agg_configs';
+import { DefaultEditorAggGroup, DefaultEditorAggGroupProps } from './default_editor_agg_group';
+import { DefaultEditorAgg } from './default_editor_agg';
+import { DefaultEditorAggAdd } from './default_editor_agg_add';
+
+jest.mock('@elastic/eui', () => ({
+ EuiTitle: 'eui-title',
+ EuiDragDropContext: 'eui-drag-drop-context',
+ EuiDroppable: 'eui-droppable',
+ EuiDraggable: (props: any) => props.children({ dragHandleProps: {} }),
+ EuiSpacer: 'eui-spacer',
+ EuiPanel: 'eui-panel',
+}));
+
+jest.mock('./default_editor_agg', () => ({
+ DefaultEditorAgg: () => ,
+}));
+
+jest.mock('./default_editor_agg_add', () => ({
+ DefaultEditorAggAdd: () => ,
+}));
+
+describe('DefaultEditorAgg component', () => {
+ let defaultProps: DefaultEditorAggGroupProps;
+ let aggs: AggConfigs;
+ let setTouched: jest.Mock;
+ let setValidity: jest.Mock;
+ let reorderAggs: jest.Mock;
+
+ beforeEach(() => {
+ setTouched = jest.fn();
+ setValidity = jest.fn();
+ reorderAggs = jest.fn();
+
+ aggs = [
+ {
+ id: 1,
+ title: 'Metrics',
+ params: {
+ field: {
+ type: 'number',
+ },
+ },
+ group: 'metrics',
+ schema: {},
+ },
+ {
+ id: 3,
+ title: 'Agg',
+ params: {
+ field: {
+ type: 'string',
+ },
+ },
+ group: 'metrics',
+ schema: {},
+ },
+ {
+ id: 2,
+ title: 'Buckets',
+ params: {
+ field: {
+ type: 'number',
+ },
+ },
+ group: 'buckets',
+ schema: {},
+ },
+ ] as AggConfigs;
+
+ Object.defineProperty(aggs, 'bySchemaGroup', {
+ get: () =>
+ aggs.reduce((acc: { [key: string]: AggConfig }, option: AggConfig) => {
+ if (acc[option.group]) {
+ acc[option.group].push(option);
+ } else {
+ acc[option.group] = [option];
+ }
+
+ return acc;
+ }, {}),
+ });
+
+ defaultProps = {
+ formIsTouched: false,
+ metricAggs: [],
+ groupName: AggGroupNames.Metrics,
+ state: {
+ aggs,
+ } as VisState,
+ schemas: [
+ {
+ max: 1,
+ } as Schema,
+ {
+ max: 1,
+ } as Schema,
+ ],
+ setTouched,
+ setValidity,
+ reorderAggs,
+ addSchema: () => {},
+ removeAgg: () => {},
+ onAggParamsChange: () => {},
+ onAggTypeChange: () => {},
+ onToggleEnableAgg: () => {},
+ };
+ });
+
+ it('should init with the default set of props', () => {
+ const comp = shallow();
+
+ expect(comp).toMatchSnapshot();
+ });
+
+ it('should call setTouched with false', () => {
+ mount();
+
+ expect(setTouched).toBeCalledWith(false);
+ });
+
+ it('should mark group as touched when all invalid aggs are touched', () => {
+ defaultProps.groupName = AggGroupNames.Buckets;
+ const comp = mount();
+ act(() => {
+ const aggProps = comp.find(DefaultEditorAgg).props();
+ aggProps.setValidity(false);
+ aggProps.setTouched(true);
+ });
+
+ expect(setTouched).toBeCalledWith(true);
+ });
+
+ it('should mark group as touched when the form applied', () => {
+ const comp = mount();
+ act(() => {
+ comp
+ .find(DefaultEditorAgg)
+ .first()
+ .props()
+ .setValidity(false);
+ });
+ expect(setTouched).toBeCalledWith(false);
+ comp.setProps({ formIsTouched: true });
+
+ expect(setTouched).toBeCalledWith(true);
+ });
+
+ it('should mark group as invalid when at least one agg is invalid', () => {
+ const comp = mount();
+ act(() => {
+ comp
+ .find(DefaultEditorAgg)
+ .first()
+ .props()
+ .setValidity(false);
+ });
+
+ expect(setValidity).toBeCalledWith(false);
+ });
+
+ it('should last bucket has truthy isLastBucket prop', () => {
+ defaultProps.groupName = AggGroupNames.Buckets;
+ const comp = mount();
+ const lastAgg = comp.find(DefaultEditorAgg).last();
+
+ expect(lastAgg.props()).toHaveProperty('isLastBucket', true);
+ });
+
+ it('should call reorderAggs when dragging ended', () => {
+ const comp = shallow();
+ act(() => {
+ // simulate dragging ending
+ comp.props().onDragEnd({ source: { index: 0 }, destination: { index: 1 } });
+ });
+
+ expect(reorderAggs).toHaveBeenCalledWith([
+ defaultProps.state.aggs[1],
+ defaultProps.state.aggs[0],
+ ]);
+ });
+
+ it('should show add button when schemas count is less than max', () => {
+ defaultProps.groupName = AggGroupNames.Buckets;
+ const comp = shallow();
+
+ expect(comp.find(DefaultEditorAggAdd).exists()).toBeTruthy();
+ });
+
+ it('should not show add button when schemas count is not less than max', () => {
+ const comp = shallow();
+
+ expect(comp.find(DefaultEditorAggAdd).exists()).toBeFalsy();
+ });
+});
diff --git a/src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group.tsx b/src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group.tsx
index 4a5f012f8783c9..d645efa818c141 100644
--- a/src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group.tsx
+++ b/src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group.tsx
@@ -40,7 +40,7 @@ import {
import { aggGroupReducer, initAggsState, AGGS_ACTION_KEYS } from './default_editor_agg_group_state';
import { Schema } from '../schemas';
-interface DefaultEditorAggGroupProps extends DefaultEditorAggCommonProps {
+export interface DefaultEditorAggGroupProps extends DefaultEditorAggCommonProps {
schemas: Schema[];
addSchema: (schems: Schema) => void;
reorderAggs: (group: AggConfig[]) => void;
diff --git a/src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group_helper.test.ts b/src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group_helper.test.ts
new file mode 100644
index 00000000000000..36b5ad82ae29fd
--- /dev/null
+++ b/src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group_helper.test.ts
@@ -0,0 +1,139 @@
+/*
+ * 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 { AggConfig } from '../../../agg_config';
+import {
+ isAggRemovable,
+ calcAggIsTooLow,
+ isInvalidAggsTouched,
+} from './default_editor_agg_group_helper';
+import { AggsState } from './default_editor_agg_group_state';
+
+describe('DefaultEditorGroup helpers', () => {
+ let group: AggConfig;
+
+ beforeEach(() => {
+ group = [
+ {
+ id: 1,
+ title: 'Test1',
+ params: {
+ field: {
+ type: 'number',
+ },
+ },
+ group: 'metrics',
+ schema: { name: 'metric', min: 1, mustBeFirst: true },
+ },
+ {
+ id: 2,
+ title: 'Test2',
+ params: {
+ field: {
+ type: 'string',
+ },
+ },
+ group: 'metrics',
+ schema: { name: 'metric', min: 2 },
+ },
+ ];
+ });
+ describe('isAggRemovable', () => {
+ it('should return true when the number of aggs with the same schema is above the min', () => {
+ const isRemovable = isAggRemovable(group[0], group);
+
+ expect(isRemovable).toBeTruthy();
+ });
+
+ it('should return false when the number of aggs with the same schema is not above the min', () => {
+ const isRemovable = isAggRemovable(group[1], group);
+
+ expect(isRemovable).toBeFalsy();
+ });
+ });
+
+ describe('calcAggIsTooLow', () => {
+ it('should return false when agg.schema.mustBeFirst has falsy value', () => {
+ const isRemovable = calcAggIsTooLow(group[1], 0, group);
+
+ expect(isRemovable).toBeFalsy();
+ });
+
+ it('should return false when there is no different schema', () => {
+ group[1].schema = group[0].schema;
+ const isRemovable = calcAggIsTooLow(group[0], 0, group);
+
+ expect(isRemovable).toBeFalsy();
+ });
+
+ it('should return false when different schema is not less than agg index', () => {
+ const isRemovable = calcAggIsTooLow(group[0], 0, group);
+
+ expect(isRemovable).toBeFalsy();
+ });
+
+ it('should return true when agg index is greater than different schema index', () => {
+ const isRemovable = calcAggIsTooLow(group[0], 2, group);
+
+ expect(isRemovable).toBeTruthy();
+ });
+ });
+
+ describe('isInvalidAggsTouched', () => {
+ let aggsState: AggsState;
+
+ beforeEach(() => {
+ aggsState = {
+ 1: {
+ valid: true,
+ touched: false,
+ },
+ 2: {
+ valid: true,
+ touched: false,
+ },
+ 3: {
+ valid: true,
+ touched: false,
+ },
+ };
+ });
+
+ it('should return false when there are no invalid aggs', () => {
+ const isAllInvalidAggsTouched = isInvalidAggsTouched(aggsState);
+
+ expect(isAllInvalidAggsTouched).toBeFalsy();
+ });
+
+ it('should return false when not all invalid aggs are touched', () => {
+ aggsState[1].valid = false;
+ const isAllInvalidAggsTouched = isInvalidAggsTouched(aggsState);
+
+ expect(isAllInvalidAggsTouched).toBeFalsy();
+ });
+
+ it('should return true when all invalid aggs are touched', () => {
+ aggsState[1].valid = false;
+ aggsState[1].touched = true;
+ const isAllInvalidAggsTouched = isInvalidAggsTouched(aggsState);
+
+ expect(isAllInvalidAggsTouched).toBeTruthy();
+ });
+ });
+});
diff --git a/src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group_helper.tsx b/src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group_helper.ts
similarity index 100%
rename from src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group_helper.tsx
rename to src/legacy/ui/public/vis/editors/default/components/default_editor_agg_group_helper.ts