airbnb/caravel

View on GitHub
superset-frontend/src/dashboard/components/gridComponents/Row.test.jsx

Summary

Maintainability
D
2 days
Test Coverage
/**
 * 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 { fireEvent, render } from 'spec/helpers/testing-library';

import BackgroundStyleDropdown from 'src/dashboard/components/menu/BackgroundStyleDropdown';
import IconButton from 'src/dashboard/components/IconButton';
import Row from 'src/dashboard/components/gridComponents/Row';
import { DASHBOARD_GRID_ID } from 'src/dashboard/util/constants';

import { getMockStore } from 'spec/fixtures/mockStore';
import { dashboardLayout as mockLayout } from 'spec/fixtures/mockDashboardLayout';
import { initialState } from 'src/SqlLab/fixtures';

jest.mock('src/dashboard/components/dnd/DragDroppable', () => ({
  Draggable: ({ children }) => (
    <div data-test="mock-draggable">{children({})}</div>
  ),
  Droppable: ({ children, depth }) => (
    <div data-test="mock-droppable" depth={depth}>
      {children({})}
    </div>
  ),
}));
jest.mock(
  'src/dashboard/containers/DashboardComponent',
  () =>
    ({ availableColumnCount, depth }) => (
      <div data-test="mock-dashboard-component" depth={depth}>
        {availableColumnCount}
      </div>
    ),
);

jest.mock(
  'src/dashboard/components/menu/WithPopoverMenu',
  () =>
    ({ children }) => <div data-test="mock-with-popover-menu">{children}</div>,
);

jest.mock(
  'src/dashboard/components/DeleteComponentButton',
  () =>
    ({ onDelete }) => (
      <button
        type="button"
        data-test="mock-delete-component-button"
        onClick={onDelete}
      >
        Delete
      </button>
    ),
);

const rowWithoutChildren = { ...mockLayout.present.ROW_ID, children: [] };
const props = {
  id: 'ROW_ID',
  parentId: DASHBOARD_GRID_ID,
  component: mockLayout.present.ROW_ID,
  parentComponent: mockLayout.present[DASHBOARD_GRID_ID],
  index: 0,
  depth: 2,
  editMode: false,
  availableColumnCount: 12,
  columnWidth: 50,
  occupiedColumnCount: 6,
  onResizeStart() {},
  onResize() {},
  onResizeStop() {},
  handleComponentDrop() {},
  deleteComponent() {},
  updateComponents() {},
};

function setup(overrideProps) {
  // We have to wrap provide DragDropContext for the underlying DragDroppable
  // otherwise we cannot assert on DragDroppable children
  const mockStore = getMockStore({
    ...initialState,
  });

  return render(<Row {...props} {...overrideProps} />, {
    store: mockStore,
    useDnd: true,
    useRouter: true,
  });
}

test('should render a Draggable', () => {
  // don't count child DragDroppables
  const { getByTestId, queryByTestId } = setup({
    component: rowWithoutChildren,
  });

  expect(getByTestId('mock-draggable')).toBeInTheDocument();
  expect(queryByTestId('mock-droppable')).not.toBeInTheDocument();
});

test('should skip rendering HoverMenu and DeleteComponentButton when not in editMode', () => {
  const { container, queryByTestId } = setup({
    component: rowWithoutChildren,
  });
  expect(container.querySelector('.hover-menu')).not.toBeInTheDocument();
  expect(queryByTestId('mock-delete-component-button')).not.toBeInTheDocument();
});

test('should render a WithPopoverMenu', () => {
  // don't count child DragDroppables
  const { getByTestId } = setup({ component: rowWithoutChildren });
  expect(getByTestId('mock-with-popover-menu')).toBeInTheDocument();
});

test('should render a HoverMenu in editMode', () => {
  const { container, getAllByTestId, getByTestId } = setup({
    component: rowWithoutChildren,
    editMode: true,
  });
  expect(container.querySelector('.hover-menu')).toBeInTheDocument();

  // Droppable area enabled in editMode
  expect(getAllByTestId('mock-droppable').length).toBe(1);

  // pass the same depth of its droppable area
  expect(getByTestId('mock-droppable')).toHaveAttribute(
    'depth',
    `${props.depth}`,
  );
});

test('should render a DeleteComponentButton in editMode', () => {
  const { getByTestId } = setup({
    component: rowWithoutChildren,
    editMode: true,
  });
  expect(getByTestId('mock-delete-component-button')).toBeInTheDocument();
});

test.skip('should render a BackgroundStyleDropdown when focused', () => {
  let wrapper = setup({ component: rowWithoutChildren });
  expect(wrapper.find(BackgroundStyleDropdown)).not.toExist();

  // we cannot set props on the Row because of the WithDragDropContext wrapper
  wrapper = setup({ component: rowWithoutChildren, editMode: true });
  wrapper
    .find(IconButton)
    .at(1) // first one is delete button
    .simulate('click');

  expect(wrapper.find(BackgroundStyleDropdown)).toExist();
});

test('should call deleteComponent when deleted', () => {
  const deleteComponent = jest.fn();
  const { getByTestId } = setup({ editMode: true, deleteComponent });
  fireEvent.click(getByTestId('mock-delete-component-button'));
  expect(deleteComponent).toHaveBeenCalledTimes(1);
});

test('should pass appropriate availableColumnCount to children', () => {
  const { getByTestId } = setup();
  expect(getByTestId('mock-dashboard-component')).toHaveTextContent(
    props.availableColumnCount - props.occupiedColumnCount,
  );
});

test('should increment the depth of its children', () => {
  const { getByTestId } = setup();
  expect(getByTestId('mock-dashboard-component')).toHaveAttribute(
    'depth',
    `${props.depth + 1}`,
  );
});