blob: 320e4f528037d6c83cffee6d066deb5c6e1e503b [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 configureStore from 'redux-mock-store';
import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import sinon from 'sinon';
import fetchMock from 'fetch-mock';
import thunk from 'redux-thunk';
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
import DatabaseSelector from 'src/components/DatabaseSelector';
import TableSelector from 'src/components/TableSelector';
import { initialState, tables } from '../sqllab/fixtures';
const mockStore = configureStore([thunk]);
const store = mockStore(initialState);
const FETCH_SCHEMAS_ENDPOINT = 'glob:*/api/v1/database/*/schemas/*';
const GET_TABLE_ENDPOINT = 'glob:*/superset/tables/1/*/*';
const GET_TABLE_NAMES_ENDPOINT = 'glob:*/superset/tables/1/main/*';
const mockedProps = {
clearable: false,
database: { id: 1, database_name: 'main' },
dbId: 1,
formMode: false,
getDbList: sinon.stub(),
handleError: sinon.stub(),
horizontal: false,
onChange: sinon.stub(),
onDbChange: sinon.stub(),
onSchemaChange: sinon.stub(),
onTableChange: sinon.stub(),
sqlLabMode: true,
tableName: '',
tableNameSticky: true,
};
const schemaOptions = {
result: ['main', 'erf', 'superset'],
};
const selectedSchema = { label: 'main', title: 'main', value: 'main' };
const selectedTable = {
extra: null,
label: 'birth_names',
schema: 'main',
title: 'birth_names',
type: undefined,
value: 'birth_names',
};
async function mountAndWait(props = mockedProps) {
const mounted = mount(<TableSelector {...props} />, {
context: { store },
wrappingComponent: ThemeProvider,
wrappingComponentProps: { theme: supersetTheme },
});
await waitForComponentToPaint(mounted);
return mounted;
}
describe('TableSelector', () => {
let wrapper;
beforeEach(async () => {
fetchMock.reset();
wrapper = await mountAndWait();
});
it('renders', () => {
expect(wrapper.find(TableSelector)).toExist();
expect(wrapper.find(DatabaseSelector)).toExist();
});
describe('change database', () => {
afterEach(fetchMock.resetHistory);
afterAll(fetchMock.reset);
it('should fetch schemas', async () => {
fetchMock.get(FETCH_SCHEMAS_ENDPOINT, { overwriteRoutes: true });
act(() => {
wrapper.find('[data-test="select-database"]').first().props().onChange({
id: 1,
database_name: 'main',
});
});
await waitForComponentToPaint(wrapper);
expect(fetchMock.calls(FETCH_SCHEMAS_ENDPOINT)).toHaveLength(1);
});
it('should fetch schema options', async () => {
fetchMock.get(FETCH_SCHEMAS_ENDPOINT, schemaOptions, {
overwriteRoutes: true,
});
act(() => {
wrapper.find('[data-test="select-database"]').first().props().onChange({
id: 1,
database_name: 'main',
});
});
await waitForComponentToPaint(wrapper);
wrapper.update();
expect(fetchMock.calls(FETCH_SCHEMAS_ENDPOINT)).toHaveLength(1);
expect(
wrapper.find('[name="select-schema"]').first().props().options,
).toEqual([
{ value: 'main', label: 'main', title: 'main' },
{ value: 'erf', label: 'erf', title: 'erf' },
{ value: 'superset', label: 'superset', title: 'superset' },
]);
});
it('should clear table options', async () => {
act(() => {
wrapper.find('[data-test="select-database"]').first().props().onChange({
id: 1,
database_name: 'main',
});
});
await waitForComponentToPaint(wrapper);
const props = wrapper.find('[name="async-select-table"]').first().props();
expect(props.isDisabled).toBe(true);
expect(props.value).toEqual(undefined);
});
});
describe('change schema', () => {
beforeEach(async () => {
fetchMock.get(FETCH_SCHEMAS_ENDPOINT, schemaOptions, {
overwriteRoutes: true,
});
});
afterEach(fetchMock.resetHistory);
afterAll(fetchMock.reset);
it('should fetch table', async () => {
fetchMock.get(GET_TABLE_NAMES_ENDPOINT, { overwriteRoutes: true });
act(() => {
wrapper.find('[data-test="select-database"]').first().props().onChange({
id: 1,
database_name: 'main',
});
});
await waitForComponentToPaint(wrapper);
act(() => {
wrapper
.find('[name="select-schema"]')
.first()
.props()
.onChange(selectedSchema);
});
await waitForComponentToPaint(wrapper);
expect(fetchMock.calls(GET_TABLE_NAMES_ENDPOINT)).toHaveLength(1);
});
it('should fetch table options', async () => {
fetchMock.get(GET_TABLE_NAMES_ENDPOINT, tables, {
overwriteRoutes: true,
});
act(() => {
wrapper.find('[data-test="select-database"]').first().props().onChange({
id: 1,
database_name: 'main',
});
});
await waitForComponentToPaint(wrapper);
act(() => {
wrapper
.find('[name="select-schema"]')
.first()
.props()
.onChange(selectedSchema);
});
await waitForComponentToPaint(wrapper);
expect(
wrapper.find('[name="select-schema"]').first().props().value[0],
).toEqual(selectedSchema);
expect(fetchMock.calls(GET_TABLE_NAMES_ENDPOINT)).toHaveLength(1);
const { options } = wrapper.find('[name="select-table"]').first().props();
expect({ options }).toEqual(tables);
});
});
describe('change table', () => {
beforeEach(async () => {
fetchMock.get(GET_TABLE_NAMES_ENDPOINT, tables, {
overwriteRoutes: true,
});
});
it('should change table value', async () => {
act(() => {
wrapper
.find('[name="select-schema"]')
.first()
.props()
.onChange(selectedSchema);
});
await waitForComponentToPaint(wrapper);
act(() => {
wrapper
.find('[name="select-table"]')
.first()
.props()
.onChange(selectedTable);
});
await waitForComponentToPaint(wrapper);
expect(
wrapper.find('[name="select-table"]').first().props().value,
).toEqual('birth_names');
});
it('should call onTableChange with schema from table object', async () => {
act(() => {
wrapper
.find('[name="select-schema"]')
.first()
.props()
.onChange(selectedSchema);
});
await waitForComponentToPaint(wrapper);
act(() => {
wrapper
.find('[name="select-table"]')
.first()
.props()
.onChange(selectedTable);
});
await waitForComponentToPaint(wrapper);
expect(mockedProps.onTableChange.getCall(0).args[0]).toBe('birth_names');
expect(mockedProps.onTableChange.getCall(0).args[1]).toBe('main');
});
});
describe('getTableNamesBySubStr', () => {
afterEach(fetchMock.resetHistory);
afterAll(fetchMock.reset);
it('should handle empty', async () => {
act(() => {
wrapper
.find('[name="async-select-table"]')
.first()
.props()
.loadOptions();
});
await waitForComponentToPaint(wrapper);
const props = wrapper.find('[name="async-select-table"]').first().props();
expect(props.isDisabled).toBe(true);
expect(props.value).toEqual('');
});
it('should handle table name', async () => {
wrapper.setProps({ schema: 'main' });
fetchMock.get(GET_TABLE_ENDPOINT, tables, {
overwriteRoutes: true,
});
act(() => {
wrapper
.find('[name="async-select-table"]')
.first()
.props()
.loadOptions();
});
await waitForComponentToPaint(wrapper);
expect(fetchMock.calls(GET_TABLE_ENDPOINT)).toHaveLength(1);
});
});
});