theforeman/foreman

View on GitHub
webpack/assets/javascripts/react_app/components/PF4/TableIndexPage/Table/Table.test.js

Summary

Maintainability
D
2 days
Test Coverage
import React from 'react';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import configureMockStore from 'redux-mock-store';
import { fireEvent, screen, render, act } from '@testing-library/react';
import '@testing-library/jest-dom';

import { Table } from './Table';

const mockStore = configureMockStore([thunk]);
const store = mockStore({});
const columns = {
  name: { title: 'Name' },
  email: { title: 'Email' },
  role: { title: 'Role' },
};

const results = [
  { id: 1, name: 'John Doe', email: 'johndoe@example.com', role: 'Admin' },
  { id: 2, name: 'Jane Smith', email: 'janesmith@example.com', role: 'User' },
];

const setParams = jest.fn();
const refreshData = jest.fn();

describe('Table', () => {
  test('renders column names and result data', () => {
    render(
      <Provider store={store}>
        <Table
          columns={columns}
          params={{ page: 1, perPage: 10, order: '' }}
          setParams={setParams}
          refreshData={refreshData}
          results={results}
          url="/users"
          isPending={false}
        />
      </Provider>
    );

    // Check that column names are displayed
    expect(screen.getByText('Name')).toBeInTheDocument();
    expect(screen.getByText('Email')).toBeInTheDocument();
    expect(screen.getByText('Role')).toBeInTheDocument();

    // Check that result data is displayed
    expect(screen.getByText('John Doe')).toBeInTheDocument();
    expect(screen.getByText('johndoe@example.com')).toBeInTheDocument();
    expect(screen.getByText('Admin')).toBeInTheDocument();
    expect(screen.getByText('Jane Smith')).toBeInTheDocument();
    expect(screen.getByText('janesmith@example.com')).toBeInTheDocument();
    expect(screen.getByText('User')).toBeInTheDocument();
  });

  test('calls setParams with sort order when column header is clicked', async () => {
    render(
      <Provider store={store}>
        <Table
          columns={{ ...columns, name: { ...columns.name, isSorted: true } }}
          params={{ page: 1, perPage: 10, order: '' }}
          setParams={setParams}
          refreshData={refreshData}
          results={results}
          url="/users"
          isPending={false}
        />
      </Provider>
    );
    fireEvent.click(screen.getByRole('button', { name: 'Name' }));
    expect(setParams).toHaveBeenCalledWith({
      order: 'name desc',
      page: 1,
      perPage: 10,
    });
    fireEvent.click(screen.getByRole('button', { name: 'Name' }));
    expect(setParams).toHaveBeenCalledWith({
      order: 'name asc',
      page: 1,
      perPage: 10,
    });
  });

  test('shows delete modal when delete button is clicked', () => {
    const onDeleteClick = jest.fn();
    const resultWithDeleteButton = { ...results[0], can_delete: true };

    render(
      <Provider store={store}>
        <Table
          columns={columns}
          params={{ page: 1, perPage: 10, order: '' }}
          setParams={setParams}
          refreshData={refreshData}
          results={[resultWithDeleteButton]}
          isDeleteable={true}
          onDeleteClick={onDeleteClick}
          url="/users"
          isPending={false}
        />
      </Provider>
    );

    fireEvent.click(screen.getByLabelText('Actions'));
    fireEvent.click(screen.getByText('Delete'));
    expect(
      screen.getByText('You are about to delete John Doe. Are you sure?')
    ).toBeInTheDocument();
    fireEvent.click(screen.getByText('Delete'));
  });

  test('disables delete button when item cannot be deleted', () => {
    const resultWithDeleteButton = { ...results[0], can_delete: false };

    render(
      <Provider store={store}>
        <Table
          columns={columns}
          params={{ page: 1, perPage: 10, order: '' }}
          setParams={setParams}
          refreshData={refreshData}
          results={[resultWithDeleteButton]}
          isDeleteable={true}
          url="/users"
          isPending={false}
        />
      </Provider>
    );
    fireEvent.click(screen.getByLabelText('Actions'));
    expect(screen.getByText('Delete')).toHaveClass('pf-m-disabled');
  });

  test('no actions button when there are no actions', () => {
    const resultWithDeleteButton = { ...results[0], can_delete: true };

    render(
      <Provider store={store}>
        <Table
          columns={columns}
          params={{ page: 1, perPage: 10, order: '' }}
          setParams={setParams}
          refreshData={refreshData}
          results={[resultWithDeleteButton]}
          isDeleteable={true}
          url="/users"
          isPending={false}
        />
      </Provider>
    );
    expect(screen.queryAllByText('Actions')).toHaveLength(0);
  });

  test('show error and not the table on error', () => {
    render(
      <Provider store={store}>
        <Table
          columns={columns}
          params={{ page: 1, perPage: 10, order: '' }}
          setParams={setParams}
          refreshData={refreshData}
          results={results}
          errorMessage="Error test"
          isDeleteable={true}
          url="/users"
          isPending={false}
        />
      </Provider>
    );
    expect(screen.queryAllByText('John')).toHaveLength(0);
    expect(screen.queryAllByText('items')).toHaveLength(0);
    expect(screen.queryAllByText('Error test')).toHaveLength(1);
  });
  test('show empty state', () => {
    render(
      <Provider store={store}>
        <Table
          columns={columns}
          params={{ page: 1, perPage: 10, order: '' }}
          setParams={setParams}
          refreshData={refreshData}
          results={[]}
          isDeleteable={true}
          url="/users"
          isPending={false}
        />
      </Provider>
    );
    expect(screen.queryAllByText('items')).toHaveLength(0);
    expect(screen.queryAllByText('No Results')).toHaveLength(2);
    expect(screen.queryAllByText('Loading...')).toHaveLength(0);
  });
  test('show empty state while loading', () => {
    render(
      <Provider store={store}>
        <Table
          columns={columns}
          params={{ page: 1, perPage: 10, order: '' }}
          setParams={setParams}
          refreshData={refreshData}
          results={[]}
          isDeleteable={true}
          url="/users"
          isPending={true}
        />
      </Provider>
    );
    expect(screen.queryAllByText('items')).toHaveLength(0);
    expect(screen.queryAllByText('No Results')).toHaveLength(0);
    expect(screen.queryAllByText('Loading...')).toHaveLength(1);
  });
});