blob: 39b2d86a9bc1fb9dc0447c348c6bfa1c6a3e4b78 [file] [log] [blame]
/**
* 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 { ReactWrapper } from 'enzyme';
import { styledMount as mount } from 'spec/helpers/theming';
import { act } from 'react-dom/test-utils';
import withAsyncVerification, {
ControlPropsWithExtras,
WithAsyncVerificationOptions,
} from 'src/explore/components/controls/withAsyncVerification';
import { ExtraControlProps } from '@superset-ui/chart-controls';
import MetricsControl from 'src/explore/components/controls/MetricControl/MetricsControl';
const VALID_METRIC = {
metric_name: 'sum__value',
expression: 'SUM(energy_usage.value)',
};
const mockSetControlValue = jest.fn();
const defaultProps = {
name: 'metrics',
label: 'Metrics',
value: undefined,
multi: true,
needAsyncVerification: true,
actions: { setControlValue: mockSetControlValue },
onChange: () => {},
columns: [
{ type: 'VARCHAR(255)', column_name: 'source' },
{ type: 'VARCHAR(255)', column_name: 'target' },
{ type: 'DOUBLE', column_name: 'value' },
],
savedMetrics: [
VALID_METRIC,
{ metric_name: 'avg__value', expression: 'AVG(energy_usage.value)' },
],
datasourceType: 'sqla',
};
function verify(sourceProp: string) {
const mock = jest.fn();
mock.mockImplementation(async (props: ControlPropsWithExtras) => ({
[sourceProp]: props.validMetrics || [VALID_METRIC],
}));
return mock;
}
async function setup({
extraProps,
baseControl = MetricsControl,
onChange,
}: Partial<WithAsyncVerificationOptions> & {
extraProps?: ExtraControlProps;
} = {}) {
const props = {
...defaultProps,
...extraProps,
};
const verifier = verify('savedMetrics');
const VerifiedControl = withAsyncVerification({
baseControl,
verify: verifier,
onChange,
});
type Wrapper = ReactWrapper<typeof props & ExtraControlProps>;
let wrapper: Wrapper | undefined;
await act(async () => {
wrapper = mount(<VerifiedControl {...props} />);
});
return { props, wrapper: wrapper as Wrapper, onChange, verifier };
}
describe('VerifiedMetricsControl', () => {
it('should calls verify correctly', async () => {
expect.assertions(5);
const { wrapper, verifier, props } = await setup();
expect(wrapper.find(MetricsControl).length).toBe(1);
expect(verifier).toBeCalledTimes(1);
expect(verifier).toBeCalledWith(
expect.objectContaining({ savedMetrics: props.savedMetrics }),
);
// should call verifier with new props when props are updated.
await act(async () => {
wrapper.setProps({ validMetric: ['abc'] });
});
expect(verifier).toBeCalledTimes(2);
expect(verifier).toBeCalledWith(
expect.objectContaining({ validMetric: ['abc'] }),
);
});
it('should trigger onChange event', async () => {
expect.assertions(3);
const mockOnChange = jest.fn();
const { wrapper } = await setup({
// should allow specify baseControl with control component name
baseControl: 'MetricsControl',
onChange: mockOnChange,
});
const child = wrapper.find(MetricsControl);
child.props().onChange(['abc']);
expect(child.length).toBe(1);
expect(mockOnChange).toBeCalledTimes(1);
expect(mockOnChange).toBeCalledWith(['abc'], {
actions: defaultProps.actions,
columns: defaultProps.columns,
datasourceType: defaultProps.datasourceType,
label: defaultProps.label,
multi: defaultProps.multi,
name: defaultProps.name,
// in real life, `onChange` should have been called with the updated
// props (both savedMetrics and value should have beend updated), but
// because of the limitation of enzyme (it cannot get props updated from
// useEffect hooks), we are not able to check that here.
savedMetrics: defaultProps.savedMetrics,
value: undefined,
});
});
});