/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Any modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
/*
* 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 { IndexPattern, IAggType, AggGroupNames } from 'src/plugins/data/public';
import { DefaultEditorAgg, DefaultEditorAggProps } from './agg';
import { DefaultEditorAggParams } from './agg_params';
import { AGGS_ACTION_KEYS } from './agg_group_state';
import { Schema } from '../schemas';
import { EditorVisState } from './sidebar/state/reducers';
jest.mock('./agg_params', () => ({
DefaultEditorAggParams: () => null,
}));
describe('DefaultEditorAgg component', () => {
let defaultProps: DefaultEditorAggProps;
let setAggParamValue: jest.Mock;
let setStateParamValue: jest.Mock;
let onToggleEnableAgg: jest.Mock;
let removeAgg: jest.Mock;
let setAggsState: jest.Mock;
beforeEach(() => {
setAggParamValue = jest.fn();
setStateParamValue = jest.fn();
onToggleEnableAgg = jest.fn();
removeAgg = jest.fn();
setAggsState = jest.fn();
defaultProps = {
agg: {
id: '1',
brandNew: true,
getIndexPattern: () => ({} as IndexPattern),
schema: 'metric',
title: 'Metrics',
params: {},
} as any,
aggIndex: 0,
aggIsTooLow: false,
dragHandleProps: null,
formIsTouched: false,
groupName: AggGroupNames.Metrics,
isDisabled: false,
isDraggable: false,
isLastBucket: false,
isRemovable: false,
metricAggs: [],
state: { params: {} } as EditorVisState,
setAggParamValue,
setStateParamValue,
onAggTypeChange: () => {},
setAggsState,
onToggleEnableAgg,
removeAgg,
schemas: [
{
name: 'metric',
} as Schema,
],
};
});
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 as any).brandNew = false;
const comp = mount();
act(() => {
comp.find(DefaultEditorAggParams).props().setValidity(false);
});
comp.update();
expect(setAggsState).toBeCalledWith({
type: AGGS_ACTION_KEYS.VALID,
payload: false,
aggId: defaultProps.agg.id,
});
expect(
comp.find('.visEditorSidebar__aggGroupAccordionButtonContent span').exists()
).toBeFalsy();
});
it('should show description when agg is valid', () => {
(defaultProps.agg as any).brandNew = false;
defaultProps.agg.type = {
makeLabel: () => 'Agg description',
} as IAggType;
const comp = mount();
act(() => {
comp.find(DefaultEditorAggParams).props().setValidity(true);
});
comp.update();
expect(setAggsState).toBeCalledWith({
type: AGGS_ACTION_KEYS.VALID,
payload: true,
aggId: defaultProps.agg.id,
});
expect(comp.find('.visEditorSidebar__aggGroupAccordionButtonContent span').text()).toBe(
'Agg description'
);
});
it('should call setTouched when accordion is collapsed', () => {
const comp = mount();
expect(defaultProps.setAggsState).toBeCalledTimes(0);
comp.find('.euiAccordion__button').simulate('click');
// make sure that the accordion is collapsed
expect(comp.find('.euiAccordion-isOpen').exists()).toBeFalsy();
expect(defaultProps.setAggsState).toBeCalledWith({
type: AGGS_ACTION_KEYS.TOUCHED,
payload: true,
aggId: defaultProps.agg.id,
});
});
it('should call setAggsState inside setValidity', () => {
const comp = mount();
act(() => {
comp.find(DefaultEditorAggParams).props().setValidity(false);
});
expect(setAggsState).toBeCalledWith({
type: AGGS_ACTION_KEYS.VALID,
payload: false,
aggId: defaultProps.agg.id,
});
expect(
comp.find('.visEditorSidebar__aggGroupAccordionButtonContent span').exists()
).toBeFalsy();
});
it('should add schema component', () => {
defaultProps.agg.schema = 'split';
const comp = mount();
expect(comp.find('RowsOrColumnsControl').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.id, false);
});
it('should disable the disableAggregation button', () => {
defaultProps.isDisabled = true;
defaultProps.isRemovable = true;
const comp = mount();
expect(
comp
.find('EuiButtonIcon[data-test-subj="toggleDisableAggregationBtn disable"]')
.prop('disabled')
).toBeTruthy();
});
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.id, 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.id);
});
});
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',
} as IAggType;
const compHistogram = shallow();
defaultProps.agg.type = {
name: 'date_histogram',
} as IAggType;
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',
} as IAggType;
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',
} as IAggType;
const comp = mount();
comp.setProps({ agg: { ...defaultProps.agg, type: { name: 'histogram' } } });
expect(defaultProps.setAggParamValue).toHaveBeenCalledWith(
defaultProps.agg.id,
'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',
} as IAggType;
const comp = mount();
comp.setProps({ agg: { ...defaultProps.agg, type: { name: 'date_histogram' } } });
expect(defaultProps.setAggParamValue).toHaveBeenCalledWith(
defaultProps.agg.id,
'min_doc_count',
0
);
});
});
});