chore(shared components): Migrate enzyme to RTL (#26258)
This commit is contained in:
parent
8e2f81816f
commit
1a1548da3b
|
|
@ -16,10 +16,7 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
import { fireEvent, render } from 'spec/helpers/testing-library';
|
||||||
import { isValidElement } from 'react';
|
|
||||||
import { ReactWrapper } from 'enzyme';
|
|
||||||
import { styledMount as mount } from 'spec/helpers/theming';
|
|
||||||
import Button from '.';
|
import Button from '.';
|
||||||
import {
|
import {
|
||||||
ButtonGallery,
|
ButtonGallery,
|
||||||
|
|
@ -27,36 +24,27 @@ import {
|
||||||
STYLES as buttonStyles,
|
STYLES as buttonStyles,
|
||||||
} from './Button.stories';
|
} from './Button.stories';
|
||||||
|
|
||||||
describe('Button', () => {
|
test('works with an onClick handler', () => {
|
||||||
let wrapper: ReactWrapper;
|
const mockAction = jest.fn();
|
||||||
|
const { getByRole } = render(<Button onClick={mockAction} />);
|
||||||
// test the basic component
|
fireEvent.click(getByRole('button'));
|
||||||
it('renders the base component', () => {
|
expect(mockAction).toHaveBeenCalled();
|
||||||
expect(isValidElement(<Button />)).toBe(true);
|
});
|
||||||
});
|
|
||||||
|
test('does not handle onClicks when disabled', () => {
|
||||||
it('works with an onClick handler', () => {
|
const mockAction = jest.fn();
|
||||||
const mockAction = jest.fn();
|
const { getByRole } = render(<Button onClick={mockAction} disabled />);
|
||||||
wrapper = mount(<Button onClick={mockAction} />);
|
fireEvent.click(getByRole('button'));
|
||||||
wrapper.find('Button').first().simulate('click');
|
expect(mockAction).toHaveBeenCalledTimes(0);
|
||||||
expect(mockAction).toHaveBeenCalled();
|
});
|
||||||
});
|
|
||||||
|
// test stories from the storybook!
|
||||||
it('does not handle onClicks when disabled', () => {
|
test('All the sorybook gallery variants mount', () => {
|
||||||
const mockAction = jest.fn();
|
const { getAllByRole } = render(<ButtonGallery />);
|
||||||
wrapper = mount(<Button onClick={mockAction} disabled />);
|
|
||||||
wrapper.find('Button').first().simulate('click');
|
const permutationCount =
|
||||||
expect(mockAction).toHaveBeenCalledTimes(0);
|
Object.values(buttonStyles.options).filter(o => o).length *
|
||||||
});
|
Object.values(buttonSizes.options).length;
|
||||||
|
|
||||||
// test stories from the storybook!
|
expect(getAllByRole('button')).toHaveLength(permutationCount);
|
||||||
it('All the sorybook gallery variants mount', () => {
|
|
||||||
wrapper = mount(<ButtonGallery />);
|
|
||||||
|
|
||||||
const permutationCount =
|
|
||||||
Object.values(buttonStyles.options).filter(o => o).length *
|
|
||||||
Object.values(buttonSizes.options).length;
|
|
||||||
|
|
||||||
expect(wrapper.find(Button).length).toEqual(permutationCount);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,22 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { shallow } from 'enzyme';
|
import { render } from 'spec/helpers/testing-library';
|
||||||
import { SuperChart } from '@superset-ui/core';
|
|
||||||
|
|
||||||
import ChartRenderer from 'src/components/Chart/ChartRenderer';
|
import ChartRenderer from 'src/components/Chart/ChartRenderer';
|
||||||
|
|
||||||
|
jest.mock('@superset-ui/core', () => ({
|
||||||
|
...jest.requireActual('@superset-ui/core'),
|
||||||
|
SuperChart: ({ formData }) => (
|
||||||
|
<div data-test="mock-super-chart">{JSON.stringify(formData)}</div>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock(
|
||||||
|
'src/components/Chart/ChartContextMenu/ChartContextMenu',
|
||||||
|
() => () => <div data-test="mock-chart-context-menu" />,
|
||||||
|
);
|
||||||
|
|
||||||
const requiredProps = {
|
const requiredProps = {
|
||||||
chartId: 1,
|
chartId: 1,
|
||||||
datasource: {},
|
datasource: {},
|
||||||
|
|
@ -31,18 +42,18 @@ const requiredProps = {
|
||||||
vizType: 'table',
|
vizType: 'table',
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('ChartRenderer', () => {
|
test('should render SuperChart', () => {
|
||||||
it('should render SuperChart', () => {
|
const { getByTestId } = render(
|
||||||
const wrapper = shallow(
|
<ChartRenderer {...requiredProps} chartIsStale={false} />,
|
||||||
<ChartRenderer {...requiredProps} chartIsStale={false} />,
|
);
|
||||||
);
|
expect(getByTestId('mock-super-chart')).toBeInTheDocument();
|
||||||
expect(wrapper.find(SuperChart)).toExist();
|
});
|
||||||
});
|
|
||||||
|
test('should use latestQueryFormData instead of formData when chartIsStale is true', () => {
|
||||||
it('should use latestQueryFormData instead of formData when chartIsStale is true', () => {
|
const { getByTestId } = render(
|
||||||
const wrapper = shallow(<ChartRenderer {...requiredProps} chartIsStale />);
|
<ChartRenderer {...requiredProps} chartIsStale />,
|
||||||
expect(wrapper.find(SuperChart).prop('formData')).toEqual({
|
);
|
||||||
testControl: 'bar',
|
expect(getByTestId('mock-super-chart')).toHaveTextContent(
|
||||||
});
|
JSON.stringify({ testControl: 'bar' }),
|
||||||
});
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,62 +16,46 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
import { fireEvent, render } from 'spec/helpers/testing-library';
|
||||||
|
|
||||||
import { isValidElement } from 'react';
|
import Checkbox from 'src/components/Checkbox';
|
||||||
import { ReactWrapper } from 'enzyme';
|
|
||||||
import {
|
|
||||||
styledMount as mount,
|
|
||||||
styledShallow as shallow,
|
|
||||||
} from 'spec/helpers/theming';
|
|
||||||
|
|
||||||
import Checkbox, {
|
jest.mock('src/components/Checkbox/CheckboxIcons', () => ({
|
||||||
CheckboxChecked,
|
CheckboxChecked: () => <div data-test="mock-CheckboxChecked" />,
|
||||||
CheckboxUnchecked,
|
CheckboxUnchecked: () => <div data-test="mock-CheckboxUnchecked" />,
|
||||||
} from 'src/components/Checkbox';
|
}));
|
||||||
|
|
||||||
describe('Checkbox', () => {
|
describe('when unchecked', () => {
|
||||||
let wrapper: ReactWrapper;
|
test('renders the unchecked component', () => {
|
||||||
|
const { getByTestId } = render(
|
||||||
it('renders the base component', () => {
|
<Checkbox style={{}} checked={false} onChange={() => true} />,
|
||||||
expect(
|
|
||||||
isValidElement(
|
|
||||||
<Checkbox style={{}} checked={false} onChange={() => true} />,
|
|
||||||
),
|
|
||||||
).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when unchecked', () => {
|
|
||||||
it('renders the unchecked component', () => {
|
|
||||||
const shallowWrapper = shallow(
|
|
||||||
<Checkbox style={{}} checked={false} onChange={() => true} />,
|
|
||||||
);
|
|
||||||
expect(shallowWrapper.dive().find(CheckboxUnchecked)).toExist();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when checked', () => {
|
|
||||||
it('renders the checked component', () => {
|
|
||||||
const shallowWrapper = shallow(
|
|
||||||
<Checkbox style={{}} checked onChange={() => true} />,
|
|
||||||
);
|
|
||||||
expect(shallowWrapper.dive().find(CheckboxChecked)).toExist();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('works with an onChange handler', () => {
|
|
||||||
const mockAction = jest.fn();
|
|
||||||
wrapper = mount(
|
|
||||||
<Checkbox style={{}} checked={false} onChange={mockAction} />,
|
|
||||||
);
|
);
|
||||||
wrapper.find('Checkbox').first().simulate('click');
|
expect(getByTestId('mock-CheckboxUnchecked')).toBeInTheDocument();
|
||||||
expect(mockAction).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders custom Checkbox styles without melting', () => {
|
|
||||||
wrapper = mount(
|
|
||||||
<Checkbox onChange={() => true} checked={false} style={{ opacity: 1 }} />,
|
|
||||||
);
|
|
||||||
expect(wrapper.find('Checkbox')).toExist();
|
|
||||||
expect(wrapper.find('Checkbox')).toHaveStyle({ opacity: 1 });
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when checked', () => {
|
||||||
|
test('renders the checked component', () => {
|
||||||
|
const { getByTestId } = render(
|
||||||
|
<Checkbox style={{}} checked onChange={() => true} />,
|
||||||
|
);
|
||||||
|
expect(getByTestId('mock-CheckboxChecked')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('works with an onChange handler', () => {
|
||||||
|
const mockAction = jest.fn();
|
||||||
|
const { getByRole } = render(
|
||||||
|
<Checkbox style={{}} checked={false} onChange={mockAction} />,
|
||||||
|
);
|
||||||
|
fireEvent.click(getByRole('checkbox'));
|
||||||
|
expect(mockAction).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('renders custom Checkbox styles without melting', () => {
|
||||||
|
const { getByRole } = render(
|
||||||
|
<Checkbox onChange={() => true} checked={false} style={{ opacity: 1 }} />,
|
||||||
|
);
|
||||||
|
expect(getByRole('checkbox')).toBeInTheDocument();
|
||||||
|
expect(getByRole('checkbox')).toHaveStyle({ opacity: 1 });
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,48 +16,51 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { mount } from 'enzyme';
|
import { fireEvent, render, waitFor } from 'spec/helpers/testing-library';
|
||||||
import Button from 'src/components/Button';
|
import Button from 'src/components/Button';
|
||||||
import { act } from 'react-dom/test-utils';
|
|
||||||
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
|
||||||
import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
|
import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
|
||||||
import Modal from 'src/components/Modal';
|
|
||||||
|
|
||||||
describe('ConfirmStatusChange', () => {
|
const mockedProps = {
|
||||||
const mockedProps = {
|
title: 'please confirm',
|
||||||
title: 'please confirm',
|
description: 'are you sure?',
|
||||||
description: 'are you sure?',
|
onConfirm: jest.fn(),
|
||||||
onConfirm: jest.fn(),
|
};
|
||||||
};
|
|
||||||
const wrapper = mount(
|
test('opens a confirm modal', () => {
|
||||||
|
const { getByTestId } = render(
|
||||||
<ConfirmStatusChange {...mockedProps}>
|
<ConfirmStatusChange {...mockedProps}>
|
||||||
{confirm => (
|
{confirm => (
|
||||||
<>
|
<>
|
||||||
<Button id="btn1" onClick={confirm} />
|
<Button data-test="btn1" onClick={confirm} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</ConfirmStatusChange>,
|
</ConfirmStatusChange>,
|
||||||
{
|
|
||||||
wrappingComponent: ThemeProvider,
|
|
||||||
wrappingComponentProps: { theme: supersetTheme },
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
it('opens a confirm modal', () => {
|
fireEvent.click(getByTestId('btn1'));
|
||||||
act(() => {
|
|
||||||
wrapper.find('#btn1').first().props().onClick('foo');
|
|
||||||
});
|
|
||||||
|
|
||||||
wrapper.update();
|
expect(getByTestId(`${mockedProps.title}-modal`)).toBeInTheDocument();
|
||||||
|
});
|
||||||
expect(wrapper.find(Modal)).toExist();
|
|
||||||
});
|
test('calls the function on confirm', async () => {
|
||||||
|
const { getByTestId, getByRole } = render(
|
||||||
it('calls the function on confirm', () => {
|
<ConfirmStatusChange {...mockedProps}>
|
||||||
act(() => {
|
{confirm => (
|
||||||
wrapper.find(Button).last().props().onClick();
|
<>
|
||||||
});
|
<Button data-test="btn1" onClick={() => confirm('foo')} />
|
||||||
|
</>
|
||||||
expect(mockedProps.onConfirm).toHaveBeenCalledWith('foo');
|
)}
|
||||||
});
|
</ConfirmStatusChange>,
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.click(getByTestId('btn1'));
|
||||||
|
|
||||||
|
const confirmInput = getByTestId('delete-modal-input');
|
||||||
|
fireEvent.change(confirmInput, { target: { value: 'DELETE' } });
|
||||||
|
|
||||||
|
const confirmButton = getByRole('button', { name: 'delete' });
|
||||||
|
fireEvent.click(confirmButton);
|
||||||
|
|
||||||
|
await waitFor(() => expect(mockedProps.onConfirm).toHaveBeenCalledTimes(1));
|
||||||
|
expect(mockedProps.onConfirm).toHaveBeenCalledWith('foo');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,12 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { mount } from 'enzyme';
|
import { waitFor, render, fireEvent } from 'spec/helpers/testing-library';
|
||||||
import configureStore from 'redux-mock-store';
|
import configureStore from 'redux-mock-store';
|
||||||
import fetchMock from 'fetch-mock';
|
import fetchMock from 'fetch-mock';
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
import { act } from 'react-dom/test-utils';
|
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
|
||||||
import Modal from 'src/components/Modal';
|
|
||||||
import { ChangeDatasourceModal } from 'src/components/Datasource';
|
import { ChangeDatasourceModal } from 'src/components/Datasource';
|
||||||
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
|
|
||||||
import mockDatasource from 'spec/fixtures/mockDatasource';
|
import mockDatasource from 'spec/fixtures/mockDatasource';
|
||||||
|
|
||||||
const mockStore = configureStore([thunk]);
|
const mockStore = configureStore([thunk]);
|
||||||
|
|
@ -57,60 +53,40 @@ fetchMock.get(DATASOURCES_ENDPOINT, { result: [mockDatasource['7__table']] });
|
||||||
fetchMock.get(DATASOURCE_ENDPOINT, DATASOURCE_PAYLOAD);
|
fetchMock.get(DATASOURCE_ENDPOINT, DATASOURCE_PAYLOAD);
|
||||||
fetchMock.get(INFO_ENDPOINT, {});
|
fetchMock.get(INFO_ENDPOINT, {});
|
||||||
|
|
||||||
async function mountAndWait(props = mockedProps) {
|
afterEach(() => {
|
||||||
const mounted = mount(<ChangeDatasourceModal store={store} {...props} />, {
|
fetchMock.resetHistory();
|
||||||
wrappingComponent: ThemeProvider,
|
});
|
||||||
wrappingComponentProps: { theme: supersetTheme },
|
|
||||||
});
|
const setup = (props = mockedProps) =>
|
||||||
await waitForComponentToPaint(mounted);
|
render(<ChangeDatasourceModal {...props} />, {
|
||||||
|
useRedux: true,
|
||||||
return mounted;
|
store,
|
||||||
}
|
});
|
||||||
|
|
||||||
describe('ChangeDatasourceModal', () => {
|
test('renders', () => {
|
||||||
let wrapper;
|
const { getByTestId } = setup();
|
||||||
|
expect(getByTestId('Swap dataset-modal')).toBeInTheDocument();
|
||||||
beforeEach(async () => {
|
});
|
||||||
wrapper = await mountAndWait();
|
|
||||||
});
|
test('fetches datasources', async () => {
|
||||||
|
setup();
|
||||||
it('renders', () => {
|
await waitFor(() => expect(fetchMock.calls(INFO_ENDPOINT)).toHaveLength(1));
|
||||||
expect(wrapper.find(ChangeDatasourceModal)).toHaveLength(1);
|
});
|
||||||
});
|
|
||||||
|
test('renders confirmation message', async () => {
|
||||||
it('renders a Modal', () => {
|
const { findByTestId, getByRole } = setup();
|
||||||
expect(wrapper.find(Modal)).toExist();
|
const confirmLink = await findByTestId('datasource-link');
|
||||||
});
|
fireEvent.click(confirmLink);
|
||||||
|
expect(getByRole('button', { name: 'Proceed' })).toBeInTheDocument();
|
||||||
it('fetches datasources', async () => {
|
});
|
||||||
expect(fetchMock.calls(INFO_ENDPOINT)).toHaveLength(3);
|
|
||||||
});
|
test('changes the datasource', async () => {
|
||||||
|
const { findByTestId, getByRole } = setup();
|
||||||
it('renders confirmation message', async () => {
|
const confirmLink = await findByTestId('datasource-link');
|
||||||
await waitForComponentToPaint(wrapper, 1000);
|
fireEvent.click(confirmLink);
|
||||||
|
const proceedButton = getByRole('button', { name: 'Proceed' });
|
||||||
act(() => {
|
fireEvent.click(proceedButton);
|
||||||
wrapper.find('[data-test="datasource-link"]').at(0).props().onClick();
|
await waitFor(() =>
|
||||||
});
|
expect(fetchMock.calls(/api\/v1\/dataset\/7/)).toHaveLength(1),
|
||||||
|
);
|
||||||
await waitForComponentToPaint(wrapper);
|
|
||||||
|
|
||||||
expect(wrapper.find('.proceed-btn')).toExist();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('changes the datasource', async () => {
|
|
||||||
await waitForComponentToPaint(wrapper, 1000);
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
wrapper.find('[data-test="datasource-link"]').at(0).props().onClick();
|
|
||||||
});
|
|
||||||
await waitForComponentToPaint(wrapper);
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
wrapper.find('.proceed-btn').at(0).props().onClick(datasourceData);
|
|
||||||
});
|
|
||||||
await waitForComponentToPaint(wrapper);
|
|
||||||
|
|
||||||
expect(fetchMock.calls(/api\/v1\/dataset\/7/)).toHaveLength(1);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { isValidElement } from 'react';
|
import { render } from 'spec/helpers/testing-library';
|
||||||
import { shallow } from 'enzyme';
|
|
||||||
|
|
||||||
import mockDatasource from 'spec/fixtures/mockDatasource';
|
import mockDatasource from 'spec/fixtures/mockDatasource';
|
||||||
import CollectionTable from './CollectionTable';
|
import CollectionTable from './CollectionTable';
|
||||||
|
|
@ -27,22 +26,13 @@ const props = {
|
||||||
tableColumns: ['column_name', 'type', 'groupby'],
|
tableColumns: ['column_name', 'type', 'groupby'],
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('CollectionTable', () => {
|
test('renders a table', () => {
|
||||||
let wrapper;
|
const { length } = mockDatasource['7__table'].columns;
|
||||||
let el;
|
const { getByRole } = render(<CollectionTable {...props} />);
|
||||||
|
expect(getByRole('table')).toBeInTheDocument();
|
||||||
beforeEach(() => {
|
expect(
|
||||||
el = <CollectionTable {...props} />;
|
getByRole('table')
|
||||||
wrapper = shallow(el);
|
.getElementsByTagName('tbody')[0]
|
||||||
});
|
.getElementsByClassName('row'),
|
||||||
|
).toHaveLength(length);
|
||||||
it('is valid', () => {
|
|
||||||
expect(isValidElement(el)).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders a table', () => {
|
|
||||||
const { length } = mockDatasource['7__table'].columns;
|
|
||||||
expect(wrapper.find('table')).toExist();
|
|
||||||
expect(wrapper.find('tbody tr.row')).toHaveLength(length);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,40 +16,34 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
import { fireEvent, render, screen } from 'spec/helpers/testing-library';
|
||||||
|
|
||||||
import { render, screen } from 'spec/helpers/testing-library';
|
|
||||||
import { shallow } from 'enzyme';
|
|
||||||
import TextAreaControl from 'src/explore/components/controls/TextAreaControl';
|
|
||||||
import Field from './Field';
|
import Field from './Field';
|
||||||
|
|
||||||
describe('Field', () => {
|
const defaultProps = {
|
||||||
const defaultProps = {
|
fieldKey: 'mock',
|
||||||
fieldKey: 'mock',
|
value: '',
|
||||||
value: '',
|
label: 'mock',
|
||||||
label: 'mock',
|
description: 'description',
|
||||||
description: 'description',
|
control: <input type="text" data-test="mock-text-control" />,
|
||||||
control: <TextAreaControl />,
|
onChange: jest.fn(),
|
||||||
onChange: jest.fn(),
|
compact: false,
|
||||||
compact: false,
|
inline: false,
|
||||||
inline: false,
|
};
|
||||||
};
|
|
||||||
|
|
||||||
it('should render', () => {
|
test('should render', () => {
|
||||||
const { container } = render(<Field {...defaultProps} />);
|
const { container } = render(<Field {...defaultProps} />);
|
||||||
expect(container).toBeInTheDocument();
|
expect(container).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call onChange', () => {
|
test('should call onChange', () => {
|
||||||
const wrapper = shallow(<Field {...defaultProps} />);
|
const { getByTestId } = render(<Field {...defaultProps} />);
|
||||||
const textArea = wrapper.find(TextAreaControl);
|
const textArea = getByTestId('mock-text-control');
|
||||||
textArea.simulate('change', { target: { value: 'x' } });
|
fireEvent.change(textArea, { target: { value: 'x' } });
|
||||||
expect(defaultProps.onChange).toHaveBeenCalled();
|
expect(defaultProps.onChange).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render compact', () => {
|
test('should render compact', () => {
|
||||||
render(<Field {...defaultProps} compact />);
|
render(<Field {...defaultProps} compact />);
|
||||||
expect(
|
expect(screen.queryByText(defaultProps.description)).not.toBeInTheDocument();
|
||||||
screen.queryByText(defaultProps.description),
|
|
||||||
).not.toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,88 +16,98 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { isValidElement } from 'react';
|
import { fireEvent, getByRole, render } from 'spec/helpers/testing-library';
|
||||||
import { shallow } from 'enzyme';
|
|
||||||
import sinon from 'sinon';
|
|
||||||
|
|
||||||
import EditableTable from 'src/components/EditableTitle';
|
import EditableTable from 'src/components/EditableTitle';
|
||||||
|
|
||||||
describe('EditableTitle', () => {
|
const mockEvent = {
|
||||||
const callback = sinon.spy();
|
target: {
|
||||||
const mockProps = {
|
value: 'new title',
|
||||||
title: 'my title',
|
},
|
||||||
canEdit: true,
|
};
|
||||||
onSaveTitle: callback,
|
const mockProps = {
|
||||||
};
|
title: 'my title',
|
||||||
const mockEvent = {
|
canEdit: true,
|
||||||
target: {
|
onSaveTitle: jest.fn(),
|
||||||
value: 'new title',
|
};
|
||||||
},
|
|
||||||
};
|
test('should render title', () => {
|
||||||
let editableWrapper = shallow(<EditableTable {...mockProps} />);
|
const { getByRole } = render(<EditableTable {...mockProps} />);
|
||||||
const notEditableWrapper = shallow(
|
expect(getByRole('button')).toBeInTheDocument();
|
||||||
<EditableTable title="my title" onSaveTitle={callback} />,
|
expect(getByRole('button')).toHaveValue(mockProps.title);
|
||||||
|
});
|
||||||
|
test('should not render an input if it is not editable', () => {
|
||||||
|
const { queryByRole } = render(
|
||||||
|
<EditableTable title="my title" onSaveTitle={jest.fn()} />,
|
||||||
);
|
);
|
||||||
it('is valid', () => {
|
expect(queryByRole('button')).not.toBeInTheDocument();
|
||||||
expect(isValidElement(<EditableTable {...mockProps} />)).toBe(true);
|
});
|
||||||
});
|
|
||||||
it('should render title', () => {
|
|
||||||
const titleElement = editableWrapper.find('input');
|
|
||||||
expect(titleElement.props().value).toBe('my title');
|
|
||||||
expect(titleElement.props().type).toBe('button');
|
|
||||||
});
|
|
||||||
it('should not render an input if it is not editable', () => {
|
|
||||||
expect(notEditableWrapper.find('input')).not.toExist();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('should handle click', () => {
|
describe('should handle click', () => {
|
||||||
it('should change title', () => {
|
test('should change title', () => {
|
||||||
editableWrapper.find('input').simulate('click');
|
const { getByRole, container } = render(<EditableTable {...mockProps} />);
|
||||||
expect(editableWrapper.find('input').props().type).toBe('text');
|
fireEvent.click(getByRole('button'));
|
||||||
});
|
expect(container.querySelector('input')?.getAttribute('type')).toEqual(
|
||||||
});
|
'text',
|
||||||
|
);
|
||||||
describe('should handle change', () => {
|
});
|
||||||
afterEach(() => {
|
});
|
||||||
editableWrapper = shallow(<EditableTable {...mockProps} />);
|
|
||||||
});
|
describe('should handle change', () => {
|
||||||
it('should change title', () => {
|
test('should change title', () => {
|
||||||
editableWrapper.find('input').simulate('change', mockEvent);
|
const { getByTestId, container } = render(
|
||||||
expect(editableWrapper.find('input').props().value).toBe('new title');
|
<EditableTable {...mockProps} editing />,
|
||||||
});
|
);
|
||||||
});
|
fireEvent.change(getByTestId('editable-title-input'), mockEvent);
|
||||||
|
expect(container.querySelector('input')).toHaveValue('new title');
|
||||||
describe('should handle blur', () => {
|
});
|
||||||
beforeEach(() => {
|
});
|
||||||
editableWrapper.find('input').simulate('click');
|
|
||||||
});
|
describe('should handle blur', () => {
|
||||||
afterEach(() => {
|
const setup = (overrides: Partial<typeof mockProps> = {}) => {
|
||||||
callback.resetHistory();
|
const selectors = render(<EditableTable {...mockProps} {...overrides} />);
|
||||||
editableWrapper = shallow(<EditableTable {...mockProps} />);
|
fireEvent.click(selectors.getByRole('button'));
|
||||||
});
|
return selectors;
|
||||||
|
};
|
||||||
it('default input type should be text', () => {
|
|
||||||
expect(editableWrapper.find('input').props().type).toBe('text');
|
test('default input type should be text', () => {
|
||||||
});
|
const { container } = setup();
|
||||||
|
expect(container.querySelector('input')?.getAttribute('type')).toEqual(
|
||||||
it('should trigger callback', () => {
|
'text',
|
||||||
editableWrapper.find('input').simulate('change', mockEvent);
|
);
|
||||||
editableWrapper.find('input').simulate('blur');
|
});
|
||||||
expect(editableWrapper.find('input').props().type).toBe('button');
|
|
||||||
expect(callback.callCount).toBe(1);
|
test('should trigger callback', () => {
|
||||||
expect(callback.getCall(0).args[0]).toBe('new title');
|
const callback = jest.fn();
|
||||||
});
|
const { getByTestId, container } = setup({ onSaveTitle: callback });
|
||||||
it('should not trigger callback', () => {
|
fireEvent.change(getByTestId('editable-title-input'), mockEvent);
|
||||||
editableWrapper.find('input').simulate('blur');
|
fireEvent.blur(getByTestId('editable-title-input'));
|
||||||
expect(editableWrapper.find('input').props().type).toBe('button');
|
expect(callback).toHaveBeenCalledTimes(1);
|
||||||
// no change
|
expect(callback).toHaveBeenCalledWith('new title');
|
||||||
expect(callback.callCount).toBe(0);
|
expect(container.querySelector('input')?.getAttribute('type')).toEqual(
|
||||||
});
|
'button',
|
||||||
it('should not save empty title', () => {
|
);
|
||||||
editableWrapper.find('input').simulate('blur');
|
});
|
||||||
expect(editableWrapper.find('input').props().type).toBe('button');
|
|
||||||
expect(editableWrapper.find('input').props().value).toBe('my title');
|
test('should not trigger callback', () => {
|
||||||
expect(callback.callCount).toBe(0);
|
const callback = jest.fn();
|
||||||
});
|
const { getByTestId, container } = setup({ onSaveTitle: callback });
|
||||||
|
fireEvent.blur(getByTestId('editable-title-input'));
|
||||||
|
expect(container.querySelector('input')?.getAttribute('type')).toEqual(
|
||||||
|
'button',
|
||||||
|
);
|
||||||
|
// no change
|
||||||
|
expect(callback).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not save empty title', () => {
|
||||||
|
const callback = jest.fn();
|
||||||
|
const { getByTestId, container } = setup({ onSaveTitle: callback });
|
||||||
|
fireEvent.blur(getByTestId('editable-title-input'));
|
||||||
|
expect(container.querySelector('input')?.getAttribute('type')).toEqual(
|
||||||
|
'button',
|
||||||
|
);
|
||||||
|
expect(getByRole(container, 'button')).toHaveValue(mockProps.title);
|
||||||
|
expect(callback).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,42 +16,44 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { shallow } from 'enzyme';
|
import { render } from 'spec/helpers/testing-library';
|
||||||
|
|
||||||
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
|
|
||||||
import { Row, Col } from 'src/components';
|
|
||||||
import TextControl from 'src/explore/components/controls/TextControl';
|
import TextControl from 'src/explore/components/controls/TextControl';
|
||||||
import FormRow from 'src/components/FormRow';
|
import FormRow from 'src/components/FormRow';
|
||||||
|
|
||||||
|
jest.mock('@superset-ui/chart-controls', () => ({
|
||||||
|
...jest.requireActual('@superset-ui/chart-controls'),
|
||||||
|
InfoTooltipWithTrigger: () => <div data-test="mock-info-tooltip" />,
|
||||||
|
}));
|
||||||
|
jest.mock('src/components', () => ({
|
||||||
|
...jest.requireActual('src/components'),
|
||||||
|
Row: ({ children }) => <div data-test="mock-row">{children}</div>,
|
||||||
|
Col: ({ children }) => <div data-test="mock-col">{children}</div>,
|
||||||
|
}));
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
label: 'Hello',
|
label: 'Hello',
|
||||||
tooltip: 'A tooltip',
|
tooltip: 'A tooltip',
|
||||||
control: <TextControl label="test_cbox" />,
|
control: <TextControl label="test_cbox" />,
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('FormRow', () => {
|
const setup = (overrideProps = {}) => {
|
||||||
let wrapper;
|
const props = {
|
||||||
|
...defaultProps,
|
||||||
const getWrapper = (overrideProps = {}) => {
|
...overrideProps,
|
||||||
const props = {
|
|
||||||
...defaultProps,
|
|
||||||
...overrideProps,
|
|
||||||
};
|
|
||||||
return shallow(<FormRow {...props} />);
|
|
||||||
};
|
};
|
||||||
|
return render(<FormRow {...props} />);
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
test('renders an InfoTooltipWithTrigger only if needed', () => {
|
||||||
wrapper = getWrapper();
|
const { getByTestId, queryByTestId, rerender } = setup();
|
||||||
});
|
expect(getByTestId('mock-info-tooltip')).toBeInTheDocument();
|
||||||
|
rerender(<FormRow {...defaultProps} tooltip={null} />);
|
||||||
it('renders an InfoTooltipWithTrigger only if needed', () => {
|
expect(queryByTestId('mock-info-tooltip')).not.toBeInTheDocument();
|
||||||
expect(wrapper.find(InfoTooltipWithTrigger)).toExist();
|
});
|
||||||
wrapper = getWrapper({ tooltip: null });
|
|
||||||
expect(wrapper.find(InfoTooltipWithTrigger)).not.toExist();
|
test('renders a Row and 2 Cols', () => {
|
||||||
});
|
const { getByTestId, getAllByTestId } = setup();
|
||||||
|
expect(getByTestId('mock-row')).toBeInTheDocument();
|
||||||
it('renders a Row and 2 Cols', () => {
|
expect(getAllByTestId('mock-col')).toHaveLength(2);
|
||||||
expect(wrapper.find(Row)).toExist();
|
|
||||||
expect(wrapper.find(Col)).toHaveLength(2);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,25 +16,29 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { isValidElement } from 'react';
|
import { render } from 'spec/helpers/testing-library';
|
||||||
import { shallow } from 'enzyme';
|
|
||||||
import { Tooltip } from 'src/components/Tooltip';
|
|
||||||
import { IconTooltip } from 'src/components/IconTooltip';
|
import { IconTooltip } from 'src/components/IconTooltip';
|
||||||
|
|
||||||
describe('IconTooltip', () => {
|
jest.mock('src/components/Tooltip', () => ({
|
||||||
const mockedProps = {
|
Tooltip: () => <div data-test="mock-tooltip" />,
|
||||||
tooltip: 'This is a tooltip',
|
}));
|
||||||
};
|
|
||||||
it('renders', () => {
|
const mockedProps = {
|
||||||
expect(isValidElement(<IconTooltip>TEST</IconTooltip>)).toBe(true);
|
tooltip: 'This is a tooltip',
|
||||||
});
|
};
|
||||||
it('renders with props', () => {
|
test('renders', () => {
|
||||||
expect(
|
const { container } = render(<IconTooltip>TEST</IconTooltip>);
|
||||||
isValidElement(<IconTooltip {...mockedProps}>TEST</IconTooltip>),
|
expect(container).toBeInTheDocument();
|
||||||
).toBe(true);
|
});
|
||||||
});
|
test('renders with props', () => {
|
||||||
it('renders a tooltip', () => {
|
const { container } = render(
|
||||||
const wrapper = shallow(<IconTooltip {...mockedProps}>TEST</IconTooltip>);
|
<IconTooltip {...mockedProps}>TEST</IconTooltip>,
|
||||||
expect(wrapper.find(Tooltip)).toExist();
|
);
|
||||||
});
|
expect(container).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
test('renders a tooltip', () => {
|
||||||
|
const { getByTestId } = render(
|
||||||
|
<IconTooltip {...mockedProps}>TEST</IconTooltip>,
|
||||||
|
);
|
||||||
|
expect(getByTestId('mock-tooltip')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,18 +16,14 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { act } from 'react-dom/test-utils';
|
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
import configureStore from 'redux-mock-store';
|
import configureStore from 'redux-mock-store';
|
||||||
import { styledMount as mount } from 'spec/helpers/theming';
|
import { fireEvent, render, waitFor } from 'spec/helpers/testing-library';
|
||||||
import { ReactWrapper } from 'enzyme';
|
|
||||||
import fetchMock from 'fetch-mock';
|
import fetchMock from 'fetch-mock';
|
||||||
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
|
|
||||||
import { Upload } from 'src/components';
|
|
||||||
import Button from 'src/components/Button';
|
|
||||||
import { ImportResourceName } from 'src/views/CRUD/types';
|
import { ImportResourceName } from 'src/views/CRUD/types';
|
||||||
import ImportModelsModal from 'src/components/ImportModal';
|
import ImportModelsModal, {
|
||||||
import Modal from 'src/components/Modal';
|
ImportModelsModalProps,
|
||||||
|
} from 'src/components/ImportModal';
|
||||||
|
|
||||||
const mockStore = configureStore([thunk]);
|
const mockStore = configureStore([thunk]);
|
||||||
const store = mockStore({});
|
const store = mockStore({});
|
||||||
|
|
@ -48,148 +44,98 @@ const requiredProps = {
|
||||||
onHide: () => {},
|
onHide: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('ImportModelsModal', () => {
|
afterEach(() => {
|
||||||
let wrapper: ReactWrapper;
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
const setup = (overrides: Partial<ImportModelsModalProps> = {}) =>
|
||||||
wrapper = mount(<ImportModelsModal {...requiredProps} />, {
|
render(<ImportModelsModal {...requiredProps} {...overrides} />, { store });
|
||||||
context: { store },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
test('renders', () => {
|
||||||
jest.clearAllMocks();
|
const { container } = setup();
|
||||||
});
|
expect(container).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it('renders', () => {
|
test('renders a Modal', () => {
|
||||||
expect(wrapper.find(ImportModelsModal)).toExist();
|
const { getByTestId } = setup();
|
||||||
});
|
expect(getByTestId('model-modal')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it('renders a Modal', () => {
|
test('renders "Import database" header', () => {
|
||||||
expect(wrapper.find(Modal)).toExist();
|
const { getByText } = setup();
|
||||||
});
|
expect(getByText('Import database')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it('renders "Import database" header', () => {
|
test('renders a file input field', () => {
|
||||||
expect(wrapper.find('h4').text()).toEqual('Import database');
|
setup();
|
||||||
});
|
expect(document.querySelector('input[type="file"]')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it('renders a file input field', () => {
|
test('should render the close, file, import and cancel buttons', () => {
|
||||||
expect(wrapper.find('input[type="file"]')).toExist();
|
setup();
|
||||||
});
|
expect(document.querySelectorAll('button')).toHaveLength(4);
|
||||||
|
});
|
||||||
|
|
||||||
it('should render the close, file, import and cancel buttons', () => {
|
test('should render the import button initially disabled', () => {
|
||||||
expect(wrapper.find('button')).toHaveLength(4);
|
const { getByRole } = setup();
|
||||||
});
|
expect(getByRole('button', { name: 'Import' })).toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
it('should render the import button initially disabled', () => {
|
test('should render the import button enabled when a file is selected', async () => {
|
||||||
expect(wrapper.find(Button).at(2).prop('disabled')).toBe(true);
|
const file = new File([new ArrayBuffer(1)], 'model_export.zip');
|
||||||
});
|
const { getByTestId, getByRole } = setup();
|
||||||
|
await waitFor(() =>
|
||||||
it('should render the import button enabled when a file is selected', () => {
|
fireEvent.change(getByTestId('model-file-input'), {
|
||||||
const file = new File([new ArrayBuffer(1)], 'model_export.zip');
|
target: {
|
||||||
act(() => {
|
files: [file],
|
||||||
const handler = wrapper.find(Upload).prop('onChange');
|
|
||||||
if (handler) {
|
|
||||||
handler({
|
|
||||||
fileList: [],
|
|
||||||
file: {
|
|
||||||
name: 'model_export.zip',
|
|
||||||
originFileObj: file,
|
|
||||||
uid: '-1',
|
|
||||||
size: 0,
|
|
||||||
type: 'zip',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
wrapper.update();
|
|
||||||
expect(wrapper.find(Button).at(2).prop('disabled')).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should POST with request header `Accept: application/json`', async () => {
|
|
||||||
const file = new File([new ArrayBuffer(1)], 'model_export.zip');
|
|
||||||
act(() => {
|
|
||||||
const handler = wrapper.find(Upload).prop('onChange');
|
|
||||||
if (handler) {
|
|
||||||
handler({
|
|
||||||
fileList: [],
|
|
||||||
file: {
|
|
||||||
name: 'model_export.zip',
|
|
||||||
originFileObj: file,
|
|
||||||
uid: '-1',
|
|
||||||
size: 0,
|
|
||||||
type: 'zip',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
wrapper.update();
|
|
||||||
|
|
||||||
wrapper.find(Button).at(2).simulate('click');
|
|
||||||
await waitForComponentToPaint(wrapper);
|
|
||||||
expect(fetchMock.calls(DATABASE_IMPORT_URL)[0][1]?.headers).toStrictEqual({
|
|
||||||
Accept: 'application/json',
|
|
||||||
'X-CSRFToken': '1234',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render password fields when needed for import', () => {
|
|
||||||
const wrapperWithPasswords = mount(
|
|
||||||
<ImportModelsModal
|
|
||||||
{...requiredProps}
|
|
||||||
passwordFields={['databases/examples.yaml']}
|
|
||||||
/>,
|
|
||||||
{
|
|
||||||
context: { store },
|
|
||||||
},
|
},
|
||||||
);
|
}),
|
||||||
expect(wrapperWithPasswords.find('input[type="password"]')).toExist();
|
);
|
||||||
});
|
expect(getByRole('button', { name: 'Import' })).toBeEnabled();
|
||||||
|
});
|
||||||
|
|
||||||
it('should render ssh_tunnel password fields when needed for import', () => {
|
test('should POST with request header `Accept: application/json`', async () => {
|
||||||
const wrapperWithPasswords = mount(
|
const file = new File([new ArrayBuffer(1)], 'model_export.zip');
|
||||||
<ImportModelsModal
|
const { getByTestId, getByRole } = setup();
|
||||||
{...requiredProps}
|
await waitFor(() =>
|
||||||
sshTunnelPasswordFields={['databases/examples.yaml']}
|
fireEvent.change(getByTestId('model-file-input'), {
|
||||||
/>,
|
target: {
|
||||||
{
|
files: [file],
|
||||||
context: { store },
|
|
||||||
},
|
},
|
||||||
);
|
}),
|
||||||
expect(
|
);
|
||||||
wrapperWithPasswords.find('[data-test="ssh_tunnel_password"]'),
|
fireEvent.click(getByRole('button', { name: 'Import' }));
|
||||||
).toExist();
|
await waitFor(() =>
|
||||||
});
|
expect(fetchMock.calls(DATABASE_IMPORT_URL)).toHaveLength(1),
|
||||||
|
);
|
||||||
it('should render ssh_tunnel private_key fields when needed for import', () => {
|
expect(fetchMock.calls(DATABASE_IMPORT_URL)[0][1]?.headers).toStrictEqual({
|
||||||
const wrapperWithPasswords = mount(
|
Accept: 'application/json',
|
||||||
<ImportModelsModal
|
'X-CSRFToken': '1234',
|
||||||
{...requiredProps}
|
|
||||||
sshTunnelPrivateKeyFields={['databases/examples.yaml']}
|
|
||||||
/>,
|
|
||||||
{
|
|
||||||
context: { store },
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
wrapperWithPasswords.find('[data-test="ssh_tunnel_private_key"]'),
|
|
||||||
).toExist();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render ssh_tunnel private_key_password fields when needed for import', () => {
|
|
||||||
const wrapperWithPasswords = mount(
|
|
||||||
<ImportModelsModal
|
|
||||||
{...requiredProps}
|
|
||||||
sshTunnelPrivateKeyPasswordFields={['databases/examples.yaml']}
|
|
||||||
/>,
|
|
||||||
{
|
|
||||||
context: { store },
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
wrapperWithPasswords.find(
|
|
||||||
'[data-test="ssh_tunnel_private_key_password"]',
|
|
||||||
),
|
|
||||||
).toExist();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should render password fields when needed for import', () => {
|
||||||
|
setup({ passwordFields: ['databases/examples.yaml'] });
|
||||||
|
expect(document.querySelector('input[type="password"]')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render ssh_tunnel password fields when needed for import', () => {
|
||||||
|
const { getByTestId } = setup({
|
||||||
|
sshTunnelPasswordFields: ['databases/examples.yaml'],
|
||||||
|
});
|
||||||
|
expect(getByTestId('ssh_tunnel_password')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render ssh_tunnel private_key fields when needed for import', () => {
|
||||||
|
const { getByTestId } = setup({
|
||||||
|
sshTunnelPrivateKeyFields: ['databases/examples.yaml'],
|
||||||
|
});
|
||||||
|
expect(getByTestId('ssh_tunnel_private_key')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render ssh_tunnel private_key_password fields when needed for import', () => {
|
||||||
|
const { getByTestId } = setup({
|
||||||
|
sshTunnelPrivateKeyPasswordFields: ['databases/examples.yaml'],
|
||||||
|
});
|
||||||
|
expect(getByTestId('ssh_tunnel_private_key_password')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,42 +16,28 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
import { fireEvent, render } from 'spec/helpers/testing-library';
|
||||||
|
|
||||||
import { isValidElement } from 'react';
|
|
||||||
import { ReactWrapper } from 'enzyme';
|
|
||||||
import { styledMount as mount } from 'spec/helpers/theming';
|
|
||||||
import Label from '.';
|
import Label from '.';
|
||||||
import { LabelGallery, options } from './Label.stories';
|
import { LabelGallery, options } from './Label.stories';
|
||||||
|
|
||||||
describe('Label', () => {
|
// test the basic component
|
||||||
let wrapper: ReactWrapper;
|
test('renders the base component (no onClick)', () => {
|
||||||
|
const { container } = render(<Label />);
|
||||||
// test the basic component
|
expect(container).toBeInTheDocument();
|
||||||
it('renders the base component (no onClick)', () => {
|
});
|
||||||
expect(isValidElement(<Label />)).toBe(true);
|
|
||||||
});
|
test('works with an onClick handler', () => {
|
||||||
|
const mockAction = jest.fn();
|
||||||
it('renders with role=undefined when onClick is not present', () => {
|
const { getByText } = render(<Label onClick={mockAction}>test</Label>);
|
||||||
wrapper = mount(<Label />);
|
fireEvent.click(getByText('test'));
|
||||||
expect(wrapper.find('span').prop('role')).toBeUndefined();
|
expect(mockAction).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders with role="button" when onClick is present', () => {
|
// test stories from the storybook!
|
||||||
const mockAction = jest.fn();
|
test('renders all the storybook gallery variants', () => {
|
||||||
wrapper = mount(<Label onClick={mockAction} />);
|
const { container } = render(<LabelGallery />);
|
||||||
expect(wrapper.find('span').prop('role')).toBe('button');
|
expect(container.querySelectorAll('.ant-tag')).toHaveLength(
|
||||||
});
|
options.length * 2,
|
||||||
|
);
|
||||||
it('works with an onClick handler', () => {
|
|
||||||
const mockAction = jest.fn();
|
|
||||||
wrapper = mount(<Label onClick={mockAction} />);
|
|
||||||
wrapper.find(Label).simulate('click');
|
|
||||||
expect(mockAction).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
// test stories from the storybook!
|
|
||||||
it('renders all the storybook gallery variants', () => {
|
|
||||||
wrapper = mount(<LabelGallery />);
|
|
||||||
expect(wrapper.find(Label).length).toEqual(options.length * 2);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,30 +16,22 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
import { fireEvent, render } from 'spec/helpers/testing-library';
|
||||||
|
|
||||||
import { MouseEvent } from 'react';
|
|
||||||
import { ReactWrapper } from 'enzyme';
|
|
||||||
import { styledMount as mount } from 'spec/helpers/theming';
|
|
||||||
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
|
|
||||||
import LastUpdated from '.';
|
import LastUpdated from '.';
|
||||||
|
|
||||||
describe('LastUpdated', () => {
|
const updatedAt = new Date('Sat Dec 12 2020 00:00:00 GMT-0800');
|
||||||
let wrapper: ReactWrapper;
|
|
||||||
const updatedAt = new Date('Sat Dec 12 2020 00:00:00 GMT-0800');
|
|
||||||
|
|
||||||
it('renders the base component (no refresh)', () => {
|
test('renders the base component (no refresh)', () => {
|
||||||
const wrapper = mount(<LastUpdated updatedAt={updatedAt} />);
|
const { getByText } = render(<LastUpdated updatedAt={updatedAt} />);
|
||||||
expect(/^Last Updated .+$/.test(wrapper.text())).toBe(true);
|
expect(getByText(/^Last Updated .+$/)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders a refresh action', async () => {
|
test('renders a refresh action', async () => {
|
||||||
const mockAction = jest.fn();
|
const mockAction = jest.fn();
|
||||||
wrapper = mount(<LastUpdated updatedAt={updatedAt} update={mockAction} />);
|
const { getByLabelText } = render(
|
||||||
await waitForComponentToPaint(wrapper);
|
<LastUpdated updatedAt={updatedAt} update={mockAction} />,
|
||||||
const props = wrapper.find('[aria-label="refresh"]').first().props();
|
);
|
||||||
if (props.onClick) {
|
fireEvent.click(getByLabelText('refresh'));
|
||||||
props.onClick({} as MouseEvent);
|
expect(mockAction).toHaveBeenCalled();
|
||||||
}
|
|
||||||
expect(mockAction).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,8 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { mount } from 'enzyme';
|
import { fireEvent, render, waitFor } from 'spec/helpers/testing-library';
|
||||||
import { ThemeProvider, supersetTheme } from '@superset-ui/core';
|
|
||||||
import Toast from 'src/components/MessageToasts/Toast';
|
import Toast from 'src/components/MessageToasts/Toast';
|
||||||
import { act } from 'react-dom/test-utils';
|
|
||||||
import mockMessageToasts from './mockMessageToasts';
|
import mockMessageToasts from './mockMessageToasts';
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
|
|
@ -27,35 +25,22 @@ const props = {
|
||||||
onCloseToast() {},
|
onCloseToast() {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const setup = overrideProps =>
|
const setup = overrideProps => render(<Toast {...props} {...overrideProps} />);
|
||||||
mount(<Toast {...props} {...overrideProps} />, {
|
|
||||||
wrappingComponent: ThemeProvider,
|
|
||||||
wrappingComponentProps: { theme: supersetTheme },
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Toast', () => {
|
test('should render', () => {
|
||||||
it('should render', () => {
|
const { getByTestId } = setup();
|
||||||
const wrapper = setup();
|
expect(getByTestId('toast-container')).toBeInTheDocument();
|
||||||
expect(wrapper.find('[data-test="toast-container"]')).toExist();
|
});
|
||||||
});
|
|
||||||
|
test('should render toastText within the div', () => {
|
||||||
it('should render toastText within the div', () => {
|
const { getByTestId } = setup();
|
||||||
const wrapper = setup();
|
expect(getByTestId('toast-container')).toHaveTextContent(props.toast.text);
|
||||||
const container = wrapper.find('[data-test="toast-container"]');
|
});
|
||||||
expect(container.hostNodes().childAt(1).text()).toBe(props.toast.text);
|
|
||||||
});
|
test('should call onCloseToast upon toast dismissal', async () => {
|
||||||
|
const onCloseToast = jest.fn();
|
||||||
it('should call onCloseToast upon toast dismissal', async () =>
|
const { getByTestId } = setup({ onCloseToast });
|
||||||
act(
|
fireEvent.click(getByTestId('close-button'));
|
||||||
() =>
|
await waitFor(() => expect(onCloseToast).toHaveBeenCalledTimes(1));
|
||||||
new Promise(done => {
|
expect(onCloseToast).toHaveBeenCalledWith(props.toast.id);
|
||||||
const onCloseToast = id => {
|
|
||||||
expect(id).toBe(props.toast.id);
|
|
||||||
done();
|
|
||||||
};
|
|
||||||
|
|
||||||
const wrapper = setup({ onCloseToast });
|
|
||||||
wrapper.find('[data-test="close-button"]').props().onClick();
|
|
||||||
}),
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,35 +16,33 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { shallow } from 'enzyme';
|
import { fireEvent, render, waitFor } from 'spec/helpers/testing-library';
|
||||||
import Toast from 'src/components/MessageToasts/Toast';
|
|
||||||
import ToastPresenter from 'src/components/MessageToasts/ToastPresenter';
|
import ToastPresenter from 'src/components/MessageToasts/ToastPresenter';
|
||||||
import mockMessageToasts from './mockMessageToasts';
|
import mockMessageToasts from './mockMessageToasts';
|
||||||
|
|
||||||
describe('ToastPresenter', () => {
|
const props = {
|
||||||
const props = {
|
toasts: mockMessageToasts,
|
||||||
toasts: mockMessageToasts,
|
removeToast() {},
|
||||||
removeToast() {},
|
};
|
||||||
};
|
|
||||||
|
|
||||||
function setup(overrideProps) {
|
function setup(overrideProps) {
|
||||||
const wrapper = shallow(<ToastPresenter {...props} {...overrideProps} />);
|
return render(<ToastPresenter {...props} {...overrideProps} />);
|
||||||
return wrapper;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
it('should render a div with id toast-presenter', () => {
|
test('should render a div with id toast-presenter', () => {
|
||||||
const wrapper = setup();
|
const { container } = setup();
|
||||||
expect(wrapper.find('#toast-presenter')).toExist();
|
expect(container.querySelector('#toast-presenter')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render a Toast for each toast object', () => {
|
test('should render a Toast for each toast object', () => {
|
||||||
const wrapper = setup();
|
const { getAllByRole } = setup();
|
||||||
expect(wrapper.find(Toast)).toHaveLength(props.toasts.length);
|
expect(getAllByRole('alert')).toHaveLength(props.toasts.length);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should pass removeToast to the Toast component', () => {
|
test('should pass removeToast to the Toast component', async () => {
|
||||||
const removeToast = () => {};
|
const removeToast = jest.fn();
|
||||||
const wrapper = setup({ removeToast });
|
const { getAllByTestId } = setup({ removeToast });
|
||||||
expect(wrapper.find(Toast).first().prop('onCloseToast')).toBe(removeToast);
|
fireEvent.click(getAllByTestId('close-button')[0]);
|
||||||
});
|
await waitFor(() => expect(removeToast).toHaveBeenCalledTimes(1));
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue