chore(fe): migrate 6 Enzyme-based unit tests to RTL (#31819)
Signed-off-by: hainenber <dotronghai96@gmail.com> Co-authored-by: JUST.in DO IT <justin.park@airbnb.com>
This commit is contained in:
parent
7383e4348b
commit
b74da7963b
|
|
@ -19,12 +19,10 @@
|
|||
import { isValidElement } from 'react';
|
||||
import thunk from 'redux-thunk';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
import QueryTable from 'src/SqlLab/components/QueryTable';
|
||||
import TableView from 'src/components/TableView';
|
||||
import TableCollection from 'src/components/TableCollection';
|
||||
import { Provider } from 'react-redux';
|
||||
import { runningQuery, successfulQuery, user } from 'src/SqlLab/fixtures';
|
||||
import { render, screen } from 'spec/helpers/testing-library';
|
||||
|
||||
const mockedProps = {
|
||||
queries: [runningQuery, successfulQuery],
|
||||
|
|
@ -43,15 +41,15 @@ test('renders a proper table', () => {
|
|||
user,
|
||||
});
|
||||
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Provider store={store}>
|
||||
<QueryTable {...mockedProps} />
|
||||
</Provider>,
|
||||
);
|
||||
const tableWrapper = wrapper.find(TableView).find(TableCollection);
|
||||
|
||||
expect(wrapper.find(TableView)).toExist();
|
||||
expect(tableWrapper.find('table')).toExist();
|
||||
expect(tableWrapper.find('table').find('thead').find('tr')).toHaveLength(1);
|
||||
expect(tableWrapper.find('table').find('tbody').find('tr')).toHaveLength(2);
|
||||
expect(screen.getByTestId('listview-table')).toBeVisible(); // Presence of TableCollection
|
||||
expect(screen.getByRole('table')).toBeVisible();
|
||||
expect(container.querySelector('.table-condensed')).toBeVisible(); // Presence of TableView signature class
|
||||
expect(container.querySelectorAll('table > thead > tr')).toHaveLength(1);
|
||||
expect(container.querySelectorAll('table > tbody > tr')).toHaveLength(2);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,11 +16,12 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
import fetchMock from 'fetch-mock';
|
||||
|
||||
import ImageLoader from 'src/components/ListViewCard/ImageLoader';
|
||||
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
|
||||
import ImageLoader, {
|
||||
BackgroundPosition,
|
||||
} from 'src/components/ListViewCard/ImageLoader';
|
||||
import { render, screen } from 'spec/helpers/testing-library';
|
||||
|
||||
global.URL.createObjectURL = jest.fn(() => '/local_url');
|
||||
const blob = new Blob([], { type: 'image/png' });
|
||||
|
|
@ -37,36 +38,46 @@ describe('ImageLoader', () => {
|
|||
const defaultProps = {
|
||||
src: '/thumbnail',
|
||||
fallback: '/fallback',
|
||||
position: 'top' as BackgroundPosition,
|
||||
};
|
||||
|
||||
const factory = (extraProps = {}) => {
|
||||
const setup = (extraProps = {}) => {
|
||||
const props = { ...defaultProps, ...extraProps };
|
||||
return mount(<ImageLoader {...props} />);
|
||||
return render(<ImageLoader {...props} />);
|
||||
};
|
||||
|
||||
afterEach(fetchMock.resetHistory);
|
||||
afterEach(() => fetchMock.resetHistory());
|
||||
|
||||
it('is a valid element', async () => {
|
||||
const wrapper = factory();
|
||||
await waitForComponentToPaint(wrapper);
|
||||
expect(wrapper.find(ImageLoader)).toExist();
|
||||
setup();
|
||||
expect(await screen.findByTestId('image-loader')).toBeVisible();
|
||||
});
|
||||
|
||||
it('fetches loads the image in the background', async () => {
|
||||
const wrapper = factory();
|
||||
expect(wrapper.find('div').props().src).toBe('/fallback');
|
||||
await waitForComponentToPaint(wrapper);
|
||||
setup();
|
||||
expect(screen.getByTestId('image-loader')).toHaveAttribute(
|
||||
'src',
|
||||
'/fallback',
|
||||
);
|
||||
expect(fetchMock.calls(/thumbnail/)).toHaveLength(1);
|
||||
expect(global.URL.createObjectURL).toHaveBeenCalled();
|
||||
expect(wrapper.find('div').props().src).toBe('/local_url');
|
||||
expect(await screen.findByTestId('image-loader')).toHaveAttribute(
|
||||
'src',
|
||||
'/local_url',
|
||||
);
|
||||
});
|
||||
|
||||
it('displays fallback image when response is not an image', async () => {
|
||||
fetchMock.once('/thumbnail2', {});
|
||||
const wrapper = factory({ src: '/thumbnail2' });
|
||||
expect(wrapper.find('div').props().src).toBe('/fallback');
|
||||
await waitForComponentToPaint(wrapper);
|
||||
setup({ src: '/thumbnail2' });
|
||||
expect(screen.getByTestId('image-loader')).toHaveAttribute(
|
||||
'src',
|
||||
'/fallback',
|
||||
);
|
||||
expect(fetchMock.calls(/thumbnail2/)).toHaveLength(1);
|
||||
expect(wrapper.find('div').props().src).toBe('/fallback');
|
||||
expect(await screen.findByTestId('image-loader')).toHaveAttribute(
|
||||
'src',
|
||||
'/fallback',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -77,6 +77,7 @@ export default function ImageLoader({
|
|||
|
||||
return (
|
||||
<ImageContainer
|
||||
data-test="image-loader"
|
||||
src={isLoading ? fallback : imgSrc}
|
||||
{...rest}
|
||||
position={position}
|
||||
|
|
|
|||
|
|
@ -16,12 +16,10 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
import fetchMock from 'fetch-mock';
|
||||
|
||||
import ListViewCard from 'src/components/ListViewCard';
|
||||
import ImageLoader from 'src/components/ListViewCard/ImageLoader';
|
||||
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
|
||||
import { render, screen } from 'spec/helpers/testing-library';
|
||||
|
||||
global.URL.createObjectURL = jest.fn(() => '/local_url');
|
||||
fetchMock.get('/thumbnail', { body: new Blob(), sendAsJson: false });
|
||||
|
|
@ -44,25 +42,22 @@ describe('ListViewCard', () => {
|
|||
),
|
||||
};
|
||||
|
||||
let wrapper;
|
||||
const factory = (extraProps = {}) => {
|
||||
const props = { ...defaultProps, ...extraProps };
|
||||
return mount(<ListViewCard {...props} />);
|
||||
};
|
||||
beforeEach(async () => {
|
||||
wrapper = factory();
|
||||
await waitForComponentToPaint(wrapper);
|
||||
beforeEach(() => {
|
||||
const props = { ...defaultProps };
|
||||
render(<ListViewCard {...props} />);
|
||||
});
|
||||
|
||||
it('is a valid element', () => {
|
||||
expect(wrapper.find(ListViewCard)).toExist();
|
||||
expect(screen.getByTestId('styled-card')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders Actions', () => {
|
||||
expect(wrapper.find(ListViewCard.Actions)).toExist();
|
||||
expect(screen.getByTestId('card-actions')).toBeVisible();
|
||||
expect(screen.getByText('Action 1')).toBeVisible();
|
||||
expect(screen.getByText('Action 2')).toBeVisible();
|
||||
});
|
||||
|
||||
it('renders and ImageLoader', () => {
|
||||
expect(wrapper.find(ImageLoader)).toExist();
|
||||
it('renders an ImageLoader', () => {
|
||||
expect(screen.getByTestId('image-loader')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
|
@ -16,20 +16,18 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
import sinon from 'sinon';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
|
||||
import DeleteComponentButton from 'src/dashboard/components/DeleteComponentButton';
|
||||
import HoverMenu from 'src/dashboard/components/menu/HoverMenu';
|
||||
import { Draggable } from 'src/dashboard/components/dnd/DragDroppable';
|
||||
import Divider from 'src/dashboard/components/gridComponents/Divider';
|
||||
import newComponentFactory from 'src/dashboard/util/newComponentFactory';
|
||||
import {
|
||||
DIVIDER_TYPE,
|
||||
DASHBOARD_GRID_TYPE,
|
||||
} from 'src/dashboard/util/componentTypes';
|
||||
import { screen, render } from 'spec/helpers/testing-library';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
describe('Divider', () => {
|
||||
const props = {
|
||||
|
|
@ -44,42 +42,48 @@ describe('Divider', () => {
|
|||
deleteComponent() {},
|
||||
};
|
||||
|
||||
function setup(overrideProps) {
|
||||
const setup = overrideProps =>
|
||||
// We have to wrap provide DragDropContext for the underlying DragDroppable
|
||||
// otherwise we cannot assert on DragDroppable children
|
||||
const wrapper = mount(
|
||||
render(
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<Divider {...props} {...overrideProps} />
|
||||
</DndProvider>,
|
||||
{
|
||||
useDnd: true,
|
||||
},
|
||||
);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
it('should render a Draggable', () => {
|
||||
const wrapper = setup();
|
||||
expect(wrapper.find(Draggable)).toExist();
|
||||
setup();
|
||||
expect(screen.getByTestId('dragdroppable-object')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render a div with class "dashboard-component-divider"', () => {
|
||||
const wrapper = setup();
|
||||
expect(wrapper.find('.dashboard-component-divider')).toExist();
|
||||
const { container } = setup();
|
||||
expect(
|
||||
container.querySelector('.dashboard-component-divider'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render a HoverMenu with DeleteComponentButton in editMode', () => {
|
||||
let wrapper = setup();
|
||||
expect(wrapper.find(HoverMenu)).not.toExist();
|
||||
expect(wrapper.find(DeleteComponentButton)).not.toExist();
|
||||
setup();
|
||||
expect(screen.queryByTestId('hover-menu')).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole('button')).not.toBeInTheDocument();
|
||||
|
||||
// we cannot set props on the Divider because of the WithDragDropContext wrapper
|
||||
wrapper = setup({ editMode: true });
|
||||
expect(wrapper.find(HoverMenu)).toExist();
|
||||
expect(wrapper.find(DeleteComponentButton)).toExist();
|
||||
setup({ editMode: true });
|
||||
expect(screen.getByTestId('hover-menu')).toBeInTheDocument();
|
||||
expect(screen.getByRole('button').firstChild).toHaveAttribute(
|
||||
'aria-label',
|
||||
'trash',
|
||||
);
|
||||
});
|
||||
|
||||
it('should call deleteComponent when deleted', () => {
|
||||
const deleteComponent = sinon.spy();
|
||||
const wrapper = setup({ editMode: true, deleteComponent });
|
||||
wrapper.find(DeleteComponentButton).simulate('click');
|
||||
setup({ editMode: true, deleteComponent });
|
||||
userEvent.click(screen.getByRole('button'));
|
||||
expect(deleteComponent.callCount).toBe(1);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,13 +16,9 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
import Popover from 'src/components/Popover';
|
||||
|
||||
import Label from 'src/components/Label';
|
||||
import ViewportControl from 'src/explore/components/controls/ViewportControl';
|
||||
import TextControl from 'src/explore/components/controls/TextControl';
|
||||
import ControlHeader from 'src/explore/components/ControlHeader';
|
||||
import { render, screen } from 'spec/helpers/testing-library';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
const defaultProps = {
|
||||
value: {
|
||||
|
|
@ -33,29 +29,27 @@ const defaultProps = {
|
|||
pitch: 0,
|
||||
},
|
||||
name: 'foo',
|
||||
label: 'bar',
|
||||
};
|
||||
const renderedCoordinate = '6° 51\' 8.50" | 31° 13\' 21.56"';
|
||||
|
||||
describe('ViewportControl', () => {
|
||||
let wrapper;
|
||||
let inst;
|
||||
beforeEach(() => {
|
||||
wrapper = mount(<ViewportControl {...defaultProps} />);
|
||||
inst = wrapper.instance();
|
||||
render(<ViewportControl {...defaultProps} />);
|
||||
});
|
||||
|
||||
it('renders a OverlayTrigger', () => {
|
||||
const controlHeader = wrapper.find(ControlHeader);
|
||||
expect(controlHeader).toHaveLength(1);
|
||||
expect(wrapper.find(Popover)).toExist();
|
||||
it('renders a OverlayTrigger if clicked', () => {
|
||||
expect(screen.getByTestId('foo-header')).toBeInTheDocument(); // Presence of ControlHeader
|
||||
userEvent.click(screen.getByText(renderedCoordinate));
|
||||
expect(screen.getByText('Viewport')).toBeInTheDocument(); // Presence of Popover
|
||||
});
|
||||
|
||||
it('renders a Popover with 5 TextControl', () => {
|
||||
const popOver = mount(inst.renderPopover());
|
||||
expect(popOver.find(TextControl)).toHaveLength(5);
|
||||
it('renders a Popover with 5 TextControl if clicked', () => {
|
||||
userEvent.click(screen.getByText(renderedCoordinate));
|
||||
expect(screen.queryAllByTestId('inline-name')).toHaveLength(5);
|
||||
});
|
||||
|
||||
it('renders a summary in the label', () => {
|
||||
const label = wrapper.find(Label).first();
|
||||
expect(label.render().text()).toBe('6° 51\' 8.50" | 31° 13\' 21.56"');
|
||||
expect(screen.getByText(renderedCoordinate)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,12 +21,6 @@ import { render, screen, within } from 'spec/helpers/testing-library';
|
|||
import { act } from 'react-dom/test-utils';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { QueryParamProvider } from 'use-query-params';
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
import { Provider } from 'react-redux';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import thunk from 'redux-thunk';
|
||||
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
|
||||
import ListView from 'src/components/ListView/ListView';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import RowLevelSecurityList from '.';
|
||||
|
||||
|
|
@ -101,43 +95,6 @@ const mockUser = {
|
|||
userId: 1,
|
||||
};
|
||||
|
||||
const mockedProps = {};
|
||||
|
||||
const mockStore = configureStore([thunk]);
|
||||
const store = mockStore({});
|
||||
|
||||
describe('RulesList Enzyme', () => {
|
||||
let wrapper: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
fetchMock.resetHistory();
|
||||
wrapper = mount(
|
||||
<MemoryRouter>
|
||||
<Provider store={store}>
|
||||
<RowLevelSecurityList {...mockedProps} user={mockUser} />
|
||||
</Provider>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
await waitForComponentToPaint(wrapper);
|
||||
});
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.find(RowLevelSecurityList)).toExist();
|
||||
});
|
||||
it('renders a ListView', () => {
|
||||
expect(wrapper.find(ListView)).toExist();
|
||||
});
|
||||
it('fetched data', () => {
|
||||
// wrapper.update();
|
||||
const apiCalls = fetchMock.calls(/rowlevelsecurity\/\?q/);
|
||||
expect(apiCalls).toHaveLength(1);
|
||||
expect(apiCalls[0][0]).toMatchInlineSnapshot(
|
||||
`"http://localhost/api/v1/rowlevelsecurity/?q=(order_column:changed_on_delta_humanized,order_direction:desc,page:0,page_size:25)"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('RuleList RTL', () => {
|
||||
async function renderAndWait() {
|
||||
const mounted = act(async () => {
|
||||
|
|
@ -154,6 +111,27 @@ describe('RuleList RTL', () => {
|
|||
return mounted;
|
||||
}
|
||||
|
||||
it('renders', async () => {
|
||||
await renderAndWait();
|
||||
expect(screen.getByText('Row Level Security')).toBeVisible();
|
||||
});
|
||||
|
||||
it('renders a ListView', async () => {
|
||||
await renderAndWait();
|
||||
expect(screen.getByTestId('rls-list-view')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('fetched data', async () => {
|
||||
fetchMock.resetHistory();
|
||||
await renderAndWait();
|
||||
const apiCalls = fetchMock.calls(/rowlevelsecurity\/\?q/);
|
||||
expect(apiCalls).toHaveLength(1);
|
||||
expect(apiCalls[0][0]).toMatchInlineSnapshot(
|
||||
`"http://localhost/api/v1/rowlevelsecurity/?q=(order_column:changed_on_delta_humanized,order_direction:desc,page:0,page_size:25)"`,
|
||||
);
|
||||
fetchMock.resetHistory();
|
||||
});
|
||||
|
||||
it('renders add rule button on empty state', async () => {
|
||||
fetchMock.get(
|
||||
ruleListEndpoint,
|
||||
|
|
|
|||
Loading…
Reference in New Issue