Files
frontend-app-learning/src/courseware/course/sequence/sequence-navigation/SequenceNavigation.test.jsx
2020-07-31 16:02:38 -04:00

105 lines
3.6 KiB
JavaScript

import React from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies
import { cloneDeep } from 'lodash';
import { fireEvent } from '@testing-library/dom';
import {
initialState, render, screen, testUnits,
} from '../../../../setupTest';
import SequenceNavigation from './SequenceNavigation';
import useIndexOfLastVisibleChild from '../../../../generic/tabs/useIndexOfLastVisibleChild';
// Mock the hook to avoid relying on its implementation and mocking `getBoundingClientRect`.
jest.mock('../../../../generic/tabs/useIndexOfLastVisibleChild');
useIndexOfLastVisibleChild.mockReturnValue([0, null, null]);
describe('Sequence Navigation', () => {
const mockData = {
previousSequenceHandler: () => {},
onNavigate: () => {},
nextSequenceHandler: () => {},
sequenceId: '1',
unitId: '3',
};
it('is empty while loading', () => {
// Clone initialState.
const testState = cloneDeep(initialState);
testState.courseware.sequenceStatus = 'loading';
const { asFragment } = render(
<SequenceNavigation {...mockData} />,
{ initialState: testState },
);
expect(asFragment()).toMatchSnapshot();
});
it('renders empty div without unitId', () => {
const { asFragment } = render(<SequenceNavigation {...mockData} unitId={undefined} />, { initialState });
expect(asFragment()).toMatchSnapshot();
});
it('renders locked button for gated content', () => {
// TODO: Not sure if this is working as expected, because the `contentType="lock"` will be overridden by the value
// from Redux. To make this provide a `fa-icon` lock we could introduce something like `overriddenContentType`.
const testState = cloneDeep(initialState);
testState.models.sequences['1'].gatedContent = { gated: true };
const { asFragment } = render(
<SequenceNavigation {...mockData} />,
{ initialState: testState },
);
expect(asFragment()).toMatchSnapshot();
});
it('renders correctly', () => {
const { asFragment } = render(<SequenceNavigation {...mockData} />, { initialState });
expect(asFragment()).toMatchSnapshot();
});
it('has both navigation buttons enabled for a non-corner unit of the sequence', () => {
render(<SequenceNavigation
{...mockData}
/>, { initialState });
screen.getAllByRole('button', { name: /previous|next/i }).forEach(button => {
expect(button).toBeEnabled();
});
});
it('has the "Previous" button disabled for the first unit of the sequence', () => {
render(<SequenceNavigation
{...mockData}
unitId="1"
/>, { initialState });
expect(screen.getByRole('button', { name: /previous/i })).toBeDisabled();
expect(screen.getByRole('button', { name: /next/i })).toBeEnabled();
});
it('has the "Next" button disabled for the last unit of the sequence', () => {
render(<SequenceNavigation
{...mockData}
sequenceId="2"
unitId={testUnits.length.toString()}
/>, { initialState });
expect(screen.getByRole('button', { name: /previous/i })).toBeEnabled();
expect(screen.getByRole('button', { name: /next/i })).toBeDisabled();
});
it('handles "Previous" and "Next" click', () => {
const previousSequenceHandler = jest.fn();
const nextSequenceHandler = jest.fn();
render(<SequenceNavigation
{...mockData}
{...{ previousSequenceHandler, nextSequenceHandler }}
/>, { initialState });
fireEvent.click(screen.getByRole('button', { name: /previous/i }));
expect(previousSequenceHandler).toHaveBeenCalledTimes(1);
fireEvent.click(screen.getByRole('button', { name: /next/i }));
expect(nextSequenceHandler).toHaveBeenCalledTimes(1);
});
});