Files
frontend-app-learning/src/courseware/course/sidebar/sidebars/course-outline/CourseOutlineTray.test.jsx
Javier Ontiveros d1dede568e feat: hide sidebar on screen resize (#1720)
Adds an event handler on the window resize to check if the sidebar isOpen and the size of the viewport is smaller than the sidebar display to hide the sidebar and prevent it from blocking the course view.
2025-06-04 16:22:01 -03:00

137 lines
5.6 KiB
JavaScript

import { MemoryRouter } from 'react-router-dom';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { AppProvider } from '@edx/frontend-platform/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { initializeTestStore } from '@src/setupTest';
import courseOutlineMessages from '@src/course-home/outline-tab/messages';
import SidebarContext from '../../SidebarContext';
import CourseOutlineTray from './CourseOutlineTray';
import { ID as outlineSidebarId } from './constants';
import messages from './messages';
describe('<CourseOutlineTray />', () => {
let store;
let section = {};
let sequence = {};
let unit;
let unitId;
let courseId;
let mockData;
const initTestStore = async (options) => {
store = await initializeTestStore(options);
const state = store.getState();
courseId = state.courseware.courseId;
[unitId] = Object.keys(state.models.units);
if (Object.keys(state.courseware.courseOutline).length) {
const [activeSequenceId] = Object.keys(state.courseware.courseOutline.sequences);
sequence = state.courseware.courseOutline.sequences[activeSequenceId];
const activeSectionId = Object.keys(state.courseware.courseOutline.sections)[0];
section = state.courseware.courseOutline.sections[activeSectionId];
[unitId] = sequence.unitIds;
unit = state.courseware.courseOutline.units[unitId];
}
mockData = {
courseId,
unitId,
currentSidebar: outlineSidebarId,
toggleSidebar: jest.fn(),
};
};
function renderWithProvider(testData = {}) {
const { container } = render(
<AppProvider store={store} wrapWithRouter={false}>
<IntlProvider locale="en">
<SidebarContext.Provider value={{ ...mockData, ...testData }}>
<MemoryRouter>
<CourseOutlineTray />
</MemoryRouter>
</SidebarContext.Provider>
</IntlProvider>
</AppProvider>,
);
return container;
}
it('renders correctly when course outline is loading', async () => {
await initTestStore({ excludeFetchOutlineSidebar: true });
renderWithProvider();
expect(screen.getByText(messages.loading.defaultMessage)).toBeInTheDocument();
expect(screen.getByText(messages.courseOutlineTitle.defaultMessage)).toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'Course outline' })).not.toBeInTheDocument();
});
it('doesn\'t render when outline sidebar is disabled', async () => {
await initTestStore({ enableNavigationSidebar: { enable_navigation_sidebar: false } });
renderWithProvider();
await expect(screen.queryByText(messages.loading.defaultMessage)).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: section.title })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: messages.toggleCourseOutlineTrigger.defaultMessage })).not.toBeInTheDocument();
});
it('renders correctly when course outline is loaded', async () => {
await initTestStore();
renderWithProvider();
await expect(screen.queryByText(messages.loading.defaultMessage)).not.toBeInTheDocument();
expect(screen.getByRole('button', { name: section.title })).toBeInTheDocument();
expect(screen.getByRole('button', { name: messages.toggleCourseOutlineTrigger.defaultMessage })).toBeInTheDocument();
expect(screen.getByRole('button', { name: `${sequence.title} , ${courseOutlineMessages.incompleteAssignment.defaultMessage}` })).toBeInTheDocument();
expect(screen.getByText(unit.title)).toBeInTheDocument();
});
it('collapses sidebar correctly when toggle button is clicked', async () => {
const user = userEvent.setup();
const mockToggleSidebar = jest.fn();
await initTestStore();
renderWithProvider({ toggleSidebar: mockToggleSidebar });
const collapseBtn = screen.getByRole('button', { name: messages.toggleCourseOutlineTrigger.defaultMessage });
const sidebarBackBtn = screen.queryByRole('button', { name: section.title });
expect(sidebarBackBtn).toBeInTheDocument();
expect(collapseBtn).toBeInTheDocument();
await user.click(collapseBtn);
expect(mockToggleSidebar).toHaveBeenCalledWith(null);
});
it('collapses sidebar correctly when screen is resized', async () => {
const mockToggleSidebar = jest.fn();
await initTestStore();
renderWithProvider({ toggleSidebar: mockToggleSidebar });
const collapseBtn = screen.getByRole('button', { name: messages.toggleCourseOutlineTrigger.defaultMessage });
expect(collapseBtn).toBeInTheDocument();
// Simulate screen resize
window.innerWidth = 500;
window.dispatchEvent(new Event('resize'));
expect(mockToggleSidebar).toHaveBeenCalledWith(null);
});
it('navigates to section or sequence level correctly on click by back/section button', async () => {
const user = userEvent.setup();
await initTestStore();
renderWithProvider();
const sidebarBackBtn = screen.queryByRole('button', { name: section.title });
expect(sidebarBackBtn).toBeInTheDocument();
expect(screen.getByRole('button', { name: `${sequence.title} , ${courseOutlineMessages.incompleteAssignment.defaultMessage}` })).toBeInTheDocument();
await user.click(sidebarBackBtn);
expect(sidebarBackBtn).not.toBeInTheDocument();
expect(screen.queryByText(messages.courseOutlineTitle.defaultMessage)).toBeInTheDocument();
await user.click(screen.getByRole('button', { name: `${section.title} , ${courseOutlineMessages.incompleteSection.defaultMessage}` }));
expect(screen.queryByRole('button', { name: section.title })).toBeInTheDocument();
});
});