chore: Moves spec files to the src folder - iteration 10 (#17902)

* chore: Moves spec files to the src folder - iteration 10

* Fixes test

* Fixes lint problem

* Uses styledMount in test
This commit is contained in:
Michael S. Molina
2022-01-07 15:24:15 -03:00
committed by GitHub
parent bb7e979142
commit 647bbf1ea1
37 changed files with 11 additions and 9 deletions

View File

@@ -0,0 +1,219 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { AGGREGATES } from 'src/explore/constants';
import AdhocMetric, {
EXPRESSION_TYPES,
} from 'src/explore/components/controls/MetricControl/AdhocMetric';
const valueColumn = { type: 'DOUBLE', column_name: 'value' };
describe('AdhocMetric', () => {
it('sets label, hasCustomLabel and optionName in constructor', () => {
const adhocMetric = new AdhocMetric({
column: valueColumn,
aggregate: AGGREGATES.SUM,
});
expect(adhocMetric.optionName.length).toBeGreaterThan(10);
expect(adhocMetric).toEqual({
expressionType: EXPRESSION_TYPES.SIMPLE,
column: valueColumn,
aggregate: AGGREGATES.SUM,
label: 'SUM(value)',
hasCustomLabel: false,
optionName: adhocMetric.optionName,
sqlExpression: null,
isNew: false,
});
});
it('can create altered duplicates', () => {
const adhocMetric1 = new AdhocMetric({
column: valueColumn,
aggregate: AGGREGATES.SUM,
isNew: true,
});
const adhocMetric2 = adhocMetric1.duplicateWith({
aggregate: AGGREGATES.AVG,
});
expect(adhocMetric1.column).toBe(adhocMetric2.column);
expect(adhocMetric1.column).toBe(valueColumn);
expect(adhocMetric1.aggregate).toBe(AGGREGATES.SUM);
expect(adhocMetric2.aggregate).toBe(AGGREGATES.AVG);
// duplicated clone should not be new
expect(adhocMetric1.isNew).toBe(true);
expect(adhocMetric2.isNew).toStrictEqual(false);
});
it('can verify equality', () => {
const adhocMetric1 = new AdhocMetric({
column: valueColumn,
aggregate: AGGREGATES.SUM,
});
const adhocMetric2 = adhocMetric1.duplicateWith({});
// eslint-disable-next-line no-unused-expressions
expect(adhocMetric1.equals(adhocMetric2)).toBe(true);
});
it('can verify inequality', () => {
const adhocMetric1 = new AdhocMetric({
column: valueColumn,
aggregate: AGGREGATES.SUM,
label: 'old label',
hasCustomLabel: true,
});
const adhocMetric2 = adhocMetric1.duplicateWith({ label: 'new label' });
// eslint-disable-next-line no-unused-expressions
expect(adhocMetric1.equals(adhocMetric2)).toBe(false);
const adhocMetric3 = new AdhocMetric({
expressionType: EXPRESSION_TYPES.SQL,
sqlExpression: 'COUNT(*)',
label: 'old label',
hasCustomLabel: true,
});
const adhocMetric4 = adhocMetric3.duplicateWith({
sqlExpression: 'COUNT(1)',
});
// eslint-disable-next-line no-unused-expressions
expect(adhocMetric3.equals(adhocMetric4)).toBe(false);
});
it('updates label if hasCustomLabel is false', () => {
const adhocMetric1 = new AdhocMetric({
column: valueColumn,
aggregate: AGGREGATES.SUM,
});
const adhocMetric2 = adhocMetric1.duplicateWith({
aggregate: AGGREGATES.AVG,
});
expect(adhocMetric2.label).toBe('AVG(value)');
});
it('keeps label if hasCustomLabel is true', () => {
const adhocMetric1 = new AdhocMetric({
column: valueColumn,
aggregate: AGGREGATES.SUM,
hasCustomLabel: true,
label: 'label1',
});
const adhocMetric2 = adhocMetric1.duplicateWith({
aggregate: AGGREGATES.AVG,
});
expect(adhocMetric2.label).toBe('label1');
});
it('can determine if it is valid', () => {
const adhocMetric1 = new AdhocMetric({
expressionType: EXPRESSION_TYPES.SIMPLE,
column: valueColumn,
aggregate: AGGREGATES.SUM,
hasCustomLabel: true,
label: 'label1',
});
// eslint-disable-next-line no-unused-expressions
expect(adhocMetric1.isValid()).toBe(true);
const adhocMetric2 = new AdhocMetric({
expressionType: EXPRESSION_TYPES.SIMPLE,
column: valueColumn,
aggregate: null,
hasCustomLabel: true,
label: 'label1',
});
// eslint-disable-next-line no-unused-expressions
expect(adhocMetric2.isValid()).toBe(false);
const adhocMetric3 = new AdhocMetric({
expressionType: EXPRESSION_TYPES.SQL,
sqlExpression: 'COUNT(*)',
hasCustomLabel: true,
label: 'label1',
});
// eslint-disable-next-line no-unused-expressions
expect(adhocMetric3.isValid()).toBe(true);
const adhocMetric4 = new AdhocMetric({
expressionType: EXPRESSION_TYPES.SQL,
column: valueColumn,
aggregate: AGGREGATES.SUM,
hasCustomLabel: true,
label: 'label1',
});
// eslint-disable-next-line no-unused-expressions
expect(adhocMetric4.isValid()).toBe(false);
const adhocMetric5 = new AdhocMetric({
expressionType: EXPRESSION_TYPES.SQL,
hasCustomLabel: true,
label: 'label1',
});
// eslint-disable-next-line no-unused-expressions
expect(adhocMetric5.isValid()).toBe(false);
});
it('can translate back from sql expressions to simple expressions when possible', () => {
const adhocMetric = new AdhocMetric({
expressionType: EXPRESSION_TYPES.SQL,
sqlExpression: 'AVG(my_column)',
hasCustomLabel: true,
label: 'label1',
});
expect(adhocMetric.inferSqlExpressionColumn()).toBe('my_column');
expect(adhocMetric.inferSqlExpressionAggregate()).toBe('AVG');
const adhocMetric2 = new AdhocMetric({
expressionType: EXPRESSION_TYPES.SQL,
sqlExpression: 'AVG(SUM(my_column)) / MAX(other_column)',
hasCustomLabel: true,
label: 'label1',
});
expect(adhocMetric2.inferSqlExpressionColumn()).toBeNull();
expect(adhocMetric2.inferSqlExpressionAggregate()).toBeNull();
});
it('will infer columns and aggregates when converting to a simple expression', () => {
const adhocMetric = new AdhocMetric({
expressionType: EXPRESSION_TYPES.SQL,
sqlExpression: 'AVG(my_column)',
hasCustomLabel: true,
label: 'label1',
});
const adhocMetric2 = adhocMetric.duplicateWith({
expressionType: EXPRESSION_TYPES.SIMPLE,
aggregate: AGGREGATES.SUM,
});
expect(adhocMetric2.aggregate).toBe(AGGREGATES.SUM);
expect(adhocMetric2.column.column_name).toBe('my_column');
const adhocMetric3 = adhocMetric.duplicateWith({
expressionType: EXPRESSION_TYPES.SIMPLE,
column: valueColumn,
});
expect(adhocMetric3.aggregate).toBe(AGGREGATES.AVG);
expect(adhocMetric3.column.column_name).toBe('value');
});
});

View File

@@ -0,0 +1,126 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.
*/
/* eslint-disable no-unused-expressions */
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import { FormItem } from 'src/components/Form';
import Button from 'src/components/Button';
import { AGGREGATES } from 'src/explore/constants';
import AdhocMetricEditPopover from 'src/explore/components/controls/MetricControl/AdhocMetricEditPopover';
import AdhocMetric, {
EXPRESSION_TYPES,
} from 'src/explore/components/controls/MetricControl/AdhocMetric';
const columns = [
{ type: 'VARCHAR(255)', column_name: 'source', id: 1 },
{ type: 'VARCHAR(255)', column_name: 'target', id: 2 },
{ type: 'DOUBLE', column_name: 'value', id: 3 },
];
const sumValueAdhocMetric = new AdhocMetric({
expressionType: EXPRESSION_TYPES.SIMPLE,
column: columns[2],
aggregate: AGGREGATES.SUM,
});
const sqlExpressionAdhocMetric = new AdhocMetric({
expressionType: EXPRESSION_TYPES.SQL,
sqlExpression: 'COUNT(*)',
});
function setup(overrides) {
const onChange = sinon.spy();
const onClose = sinon.spy();
const props = {
adhocMetric: sumValueAdhocMetric,
savedMetric: { metric_name: 'foo', expression: 'COUNT(*)' },
savedMetrics: [],
onChange,
onClose,
onResize: () => {},
getCurrentLabel: () => {},
columns,
...overrides,
};
const wrapper = shallow(<AdhocMetricEditPopover {...props} />);
return { wrapper, onChange, onClose };
}
describe('AdhocMetricEditPopover', () => {
it('renders a popover with edit metric form contents', () => {
const { wrapper } = setup();
expect(wrapper.find(FormItem)).toHaveLength(3);
expect(wrapper.find(Button)).toHaveLength(2);
});
it('overwrites the adhocMetric in state with onColumnChange', () => {
const { wrapper } = setup();
wrapper.instance().onColumnChange(columns[0].column_name);
expect(wrapper.state('adhocMetric')).toEqual(
sumValueAdhocMetric.duplicateWith({ column: columns[0] }),
);
});
it('overwrites the adhocMetric in state with onAggregateChange', () => {
const { wrapper } = setup();
wrapper.instance().onAggregateChange(AGGREGATES.AVG);
expect(wrapper.state('adhocMetric')).toEqual(
sumValueAdhocMetric.duplicateWith({ aggregate: AGGREGATES.AVG }),
);
});
it('overwrites the adhocMetric in state with onSqlExpressionChange', () => {
const { wrapper } = setup({ adhocMetric: sqlExpressionAdhocMetric });
wrapper.instance().onSqlExpressionChange('COUNT(1)');
expect(wrapper.state('adhocMetric')).toEqual(
sqlExpressionAdhocMetric.duplicateWith({ sqlExpression: 'COUNT(1)' }),
);
});
it('prevents saving if no column or aggregate is chosen', () => {
const { wrapper } = setup();
expect(wrapper.find(Button).find({ disabled: true })).not.toExist();
wrapper.instance().onColumnChange(null);
expect(wrapper.find(Button).find({ disabled: true })).toExist();
wrapper.instance().onColumnChange(columns[0].column_name);
expect(wrapper.find(Button).find({ disabled: true })).not.toExist();
wrapper.instance().onAggregateChange(null);
expect(wrapper.find(Button).find({ disabled: true })).toExist();
});
it('highlights save if changes are present', () => {
const { wrapper } = setup();
expect(wrapper.find(Button).find({ buttonStyle: 'primary' })).not.toExist();
wrapper.instance().onColumnChange(columns[1].column_name);
expect(wrapper.find(Button).find({ buttonStyle: 'primary' })).toExist();
});
it('will initiate a drag when clicked', () => {
const { wrapper } = setup();
wrapper.instance().onDragDown = sinon.spy();
wrapper.instance().forceUpdate();
expect(wrapper.find('.fa-expand')).toExist();
expect(wrapper.instance().onDragDown.calledOnce).toBe(false);
wrapper.find('.fa-expand').simulate('mouseDown');
expect(wrapper.instance().onDragDown.calledOnce).toBe(true);
});
});

View File

@@ -0,0 +1,70 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.
*/
/* eslint-disable no-unused-expressions */
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import { Tooltip } from 'src/components/Tooltip';
import AdhocMetricEditPopoverTitle from 'src/explore/components/controls/MetricControl/AdhocMetricEditPopoverTitle';
const title = {
label: 'Title',
hasCustomLabel: false,
};
function setup(overrides) {
const onChange = sinon.spy();
const props = {
title,
onChange,
...overrides,
};
const wrapper = shallow(<AdhocMetricEditPopoverTitle {...props} />);
return { wrapper, onChange };
}
describe('AdhocMetricEditPopoverTitle', () => {
it('renders an OverlayTrigger wrapper with the title', () => {
const { wrapper } = setup();
expect(wrapper.find(Tooltip)).toExist();
expect(
wrapper.find('[data-test="AdhocMetricEditTitle#trigger"]').text(),
).toBe(`${title.label}\xa0`);
});
it('transfers to edit mode when clicked', () => {
const { wrapper } = setup();
expect(wrapper.state('isEditMode')).toBe(false);
wrapper
.find('[data-test="AdhocMetricEditTitle#trigger"]')
.simulate('click');
expect(wrapper.state('isEditMode')).toBe(true);
});
it('Render non-interactive span with title when edit is disabled', () => {
const { wrapper } = setup({ isEditDisabled: true });
expect(
wrapper.find('[data-test="AdhocMetricTitle"]').exists(),
).toBeTruthy();
expect(
wrapper.find('[data-test="AdhocMetricEditTitle#trigger"]').exists(),
).toBeFalsy();
});
});

View File

@@ -0,0 +1,85 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.
*/
/* eslint-disable no-unused-expressions */
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import Popover from 'src/components/Popover';
import { AGGREGATES } from 'src/explore/constants';
import AdhocMetricOption from 'src/explore/components/controls/MetricControl/AdhocMetricOption';
import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric';
const columns = [
{ type: 'VARCHAR(255)', column_name: 'source' },
{ type: 'VARCHAR(255)', column_name: 'target' },
{ type: 'DOUBLE', column_name: 'value' },
];
const sumValueAdhocMetric = new AdhocMetric({
column: columns[2],
aggregate: AGGREGATES.SUM,
});
function setup(overrides) {
const onMetricEdit = sinon.spy();
const props = {
adhocMetric: sumValueAdhocMetric,
savedMetric: {},
savedMetrics: [],
onMetricEdit,
columns,
onMoveLabel: () => {},
onDropLabel: () => {},
index: 0,
...overrides,
};
const wrapper = shallow(<AdhocMetricOption {...props} />)
.find('AdhocMetricPopoverTrigger')
.shallow();
return { wrapper, onMetricEdit };
}
describe('AdhocMetricOption', () => {
it('renders an overlay trigger wrapper for the label', () => {
const { wrapper } = setup();
expect(wrapper.find(Popover)).toExist();
expect(wrapper.find('OptionControlLabel')).toExist();
});
it('overwrites the adhocMetric in state with onLabelChange', () => {
const { wrapper } = setup();
wrapper.instance().onLabelChange({ target: { value: 'new label' } });
expect(wrapper.state('title').label).toBe('new label');
expect(wrapper.state('title').hasCustomLabel).toBe(true);
});
it('returns to default labels when the custom label is cleared', () => {
const { wrapper } = setup();
expect(wrapper.state('title').label).toBe('SUM(value)');
wrapper.instance().onLabelChange({ target: { value: 'new label' } });
expect(wrapper.state('title').label).toBe('new label');
wrapper.instance().onLabelChange({ target: { value: '' } });
expect(wrapper.state('title').label).toBe('SUM(value)');
expect(wrapper.state('title').hasCustomLabel).toBe(false);
});
});

View File

@@ -0,0 +1,31 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { render, screen } from 'spec/helpers/testing-library';
import AggregateOption from 'src/explore/components/controls/MetricControl/AggregateOption';
describe('AggregateOption', () => {
it('renders the aggregate', () => {
render(<AggregateOption aggregate={{ aggregate_name: 'SUM' }} />);
const aggregateOption = screen.getByText(/sum/i);
expect(aggregateOption).toBeVisible();
});
});

View File

@@ -0,0 +1,59 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.
*/
/* eslint-disable no-unused-expressions */
import React from 'react';
import { shallow } from 'enzyme';
import { styledMount as mount } from 'spec/helpers/theming';
import FilterDefinitionOption from 'src/explore/components/controls/MetricControl/FilterDefinitionOption';
import { AGGREGATES } from 'src/explore/constants';
import AdhocMetric, {
EXPRESSION_TYPES,
} from 'src/explore/components/controls/MetricControl/AdhocMetric';
import { StyledColumnOption } from 'src/explore/components/optionRenderers';
const sumValueAdhocMetric = new AdhocMetric({
expressionType: EXPRESSION_TYPES.SIMPLE,
column: { type: 'VARCHAR(255)', column_name: 'source' },
aggregate: AGGREGATES.SUM,
});
describe('FilterDefinitionOption', () => {
it('renders a StyledColumnOption given a column', () => {
const wrapper = shallow(
<FilterDefinitionOption option={{ column_name: 'a_column' }} />,
);
expect(wrapper.find(StyledColumnOption)).toExist();
});
it('renders a StyledColumnOption given an adhoc metric', () => {
const wrapper = shallow(
<FilterDefinitionOption option={sumValueAdhocMetric} />,
);
expect(wrapper.find(StyledColumnOption)).toExist();
});
it('renders the metric name given a saved metric', () => {
const wrapper = mount(
<FilterDefinitionOption
option={{ saved_metric_name: 'my_custom_metric' }}
/>,
);
expect(wrapper.find('.option-label').text()).toBe('my_custom_metric');
});
});

View File

@@ -0,0 +1,54 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 configureStore from 'redux-mock-store';
import { shallow } from 'enzyme';
import MetricDefinitionOption from 'src/explore/components/controls/MetricControl/MetricDefinitionOption';
import AggregateOption from 'src/explore/components/controls/MetricControl/AggregateOption';
import {
StyledMetricOption,
StyledColumnOption,
} from 'src/explore/components/optionRenderers';
describe('MetricDefinitionOption', () => {
const mockStore = configureStore([]);
const store = mockStore({});
function setup(props) {
return shallow(<MetricDefinitionOption store={store} {...props} />).dive();
}
it('renders a StyledMetricOption given a saved metric', () => {
const wrapper = setup({
option: { metric_name: 'a_saved_metric', expression: 'COUNT(*)' },
});
expect(wrapper.find(StyledMetricOption)).toExist();
});
it('renders a StyledColumnOption given a column', () => {
const wrapper = setup({ option: { column_name: 'a_column' } });
expect(wrapper.find(StyledColumnOption)).toExist();
});
it('renders an AggregateOption given an aggregate metric', () => {
const wrapper = setup({ option: { aggregate_name: 'an_aggregate' } });
expect(wrapper.find(AggregateOption)).toExist();
});
});

View File

@@ -0,0 +1,55 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.
*/
/* eslint-disable no-unused-expressions */
import React from 'react';
import { shallow } from 'enzyme';
import { AGGREGATES } from 'src/explore/constants';
import MetricDefinitionValue from 'src/explore/components/controls/MetricControl/MetricDefinitionValue';
import AdhocMetricOption from 'src/explore/components/controls/MetricControl/AdhocMetricOption';
import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric';
const sumValueAdhocMetric = new AdhocMetric({
column: { type: 'DOUBLE', column_name: 'value' },
aggregate: AGGREGATES.SUM,
});
describe('MetricDefinitionValue', () => {
it('renders a MetricOption given a saved metric', () => {
const wrapper = shallow(
<MetricDefinitionValue
onMetricEdit={() => {}}
option={{ metric_name: 'a_saved_metric', expression: 'COUNT(*)' }}
index={1}
/>,
);
expect(wrapper.find('AdhocMetricOption')).toExist();
});
it('renders an AdhocMetricOption given an adhoc metric', () => {
const wrapper = shallow(
<MetricDefinitionValue
onMetricEdit={() => {}}
option={sumValueAdhocMetric}
index={1}
/>,
);
expect(wrapper.find(AdhocMetricOption)).toExist();
});
});

View File

@@ -0,0 +1,178 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.
*/
/* eslint-disable no-unused-expressions */
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import { AGGREGATES } from 'src/explore/constants';
import { LabelsContainer } from 'src/explore/components/controls/OptionControls';
import { supersetTheme } from '@superset-ui/core';
import MetricsControl from 'src/explore/components/controls/MetricControl/MetricsControl';
import AdhocMetric, {
EXPRESSION_TYPES,
} from 'src/explore/components/controls/MetricControl/AdhocMetric';
const defaultProps = {
name: 'metrics',
label: 'Metrics',
value: undefined,
multi: true,
columns: [
{ type: 'VARCHAR(255)', column_name: 'source' },
{ type: 'VARCHAR(255)', column_name: 'target' },
{ type: 'DOUBLE', column_name: 'value' },
],
savedMetrics: [
{ metric_name: 'sum__value', expression: 'SUM(energy_usage.value)' },
{ metric_name: 'avg__value', expression: 'AVG(energy_usage.value)' },
],
datasourceType: 'sqla',
};
function setup(overrides) {
const onChange = sinon.spy();
const props = {
onChange,
theme: supersetTheme,
...defaultProps,
...overrides,
};
const wrapper = shallow(<MetricsControl {...props} />);
const component = wrapper.shallow();
return { wrapper, component, onChange };
}
const valueColumn = { type: 'DOUBLE', column_name: 'value' };
const sumValueAdhocMetric = new AdhocMetric({
column: valueColumn,
aggregate: AGGREGATES.SUM,
label: 'SUM(value)',
});
// TODO: rewrite the tests to RTL
describe.skip('MetricsControl', () => {
it('renders Select', () => {
const { component } = setup();
expect(component.find(LabelsContainer)).toExist();
});
describe('constructor', () => {
it('coerces Adhoc Metrics from form data into instances of the AdhocMetric class and leaves saved metrics', () => {
const { component } = setup({
value: [
{
expressionType: EXPRESSION_TYPES.SIMPLE,
column: { type: 'double', column_name: 'value' },
aggregate: AGGREGATES.SUM,
label: 'SUM(value)',
optionName: 'blahblahblah',
},
],
});
const adhocMetric = component.state('value')[0];
expect(adhocMetric instanceof AdhocMetric).toBe(true);
expect(adhocMetric.optionName.length).toBeGreaterThan(10);
expect(component.state('value')).toEqual([
{
expressionType: EXPRESSION_TYPES.SIMPLE,
column: { type: 'double', column_name: 'value' },
aggregate: AGGREGATES.SUM,
label: 'SUM(value)',
hasCustomLabel: false,
optionName: 'blahblahblah',
sqlExpression: null,
isNew: false,
},
]);
});
});
describe('onChange', () => {
it('handles creating a new metric', () => {
const { component, onChange } = setup();
component.instance().onNewMetric({
metric_name: 'sum__value',
expression: 'SUM(energy_usage.value)',
});
expect(onChange.lastCall.args).toEqual([['sum__value']]);
});
});
describe('onMetricEdit', () => {
it('accepts an edited metric from an AdhocMetricEditPopover', () => {
const { component, onChange } = setup({
value: [sumValueAdhocMetric],
});
const editedMetric = sumValueAdhocMetric.duplicateWith({
aggregate: AGGREGATES.AVG,
});
component.instance().onMetricEdit(editedMetric, sumValueAdhocMetric);
expect(onChange.lastCall.args).toEqual([[editedMetric]]);
});
});
describe('option filter', () => {
it('Removes metrics if savedMetrics changes', () => {
const { props, component, onChange } = setup({
value: [
{
expressionType: EXPRESSION_TYPES.SIMPLE,
column: { type: 'double', column_name: 'value' },
aggregate: AGGREGATES.SUM,
label: 'SUM(value)',
optionName: 'blahblahblah',
},
],
});
expect(component.state('value')).toHaveLength(1);
component.setProps({ ...props, columns: [] });
expect(onChange.lastCall.args).toEqual([[]]);
});
it('Does not remove custom sql metric if savedMetrics changes', () => {
const { props, component, onChange } = setup({
value: [
{
expressionType: EXPRESSION_TYPES.SQL,
sqlExpression: 'COUNT(*)',
label: 'old label',
hasCustomLabel: true,
},
],
});
expect(component.state('value')).toHaveLength(1);
component.setProps({ ...props, columns: [] });
expect(onChange.calledOnce).toEqual(false);
});
it('Does not fail if no columns or savedMetrics are passed', () => {
const { component } = setup({
savedMetrics: null,
columns: null,
});
expect(component.exists('.metrics-select')).toEqual(true);
});
});
});