-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8c6c0db
commit 106fc03
Showing
7 changed files
with
446 additions
and
224 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
300 changes: 81 additions & 219 deletions
300
src/course-checklist/ChecklistSection/ChecklistSection.test.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,255 +1,117 @@ | ||
/* eslint-disable */ | ||
import { | ||
render, | ||
within, | ||
screen, | ||
} from '@testing-library/react'; | ||
import '@testing-library/jest-dom'; | ||
import { camelCaseObject, initializeMockApp } from '@edx/frontend-platform'; | ||
import { AppProvider } from '@edx/frontend-platform/react'; | ||
import { render, screen, fireEvent } from '@testing-library/react'; | ||
import '@testing-library/jest-dom/extend-expect'; | ||
import { IntlProvider } from '@edx/frontend-platform/i18n'; | ||
|
||
import initializeStore from '../../store'; | ||
import { initialState,generateCourseLaunchData } from '../factories/mockApiResponses'; | ||
import { useNavigate } from 'react-router'; | ||
import { useSelector } from 'react-redux'; | ||
import ChecklistItemBody from './ChecklistItemBody'; | ||
import messages from './messages'; | ||
import ChecklistSection from './index'; | ||
import { checklistItems } from './utils/courseChecklistData'; | ||
import getUpdateLinks from '../utils'; | ||
|
||
const testData = camelCaseObject(generateCourseLaunchData()); | ||
jest.mock('react-redux', () => ({ | ||
useSelector: jest.fn(), | ||
})); | ||
|
||
jest.mock('react-router', () => ({ | ||
useNavigate: jest.fn(), | ||
})); | ||
|
||
const mockNavigate = jest.fn(); | ||
useNavigate.mockReturnValue(mockNavigate); | ||
|
||
const defaultProps = { | ||
data: testData, | ||
dataHeading: 'Test checklist', | ||
idPrefix: 'launchChecklist', | ||
updateLinks: getUpdateLinks('courseId'), | ||
isLoading: false, | ||
courseId: 'course-v1:edX+DemoX+2024', | ||
checkId: 'welcomeMessage', | ||
isCompleted: false, | ||
updateLink: 'https://example.com/update', | ||
intl: { | ||
formatMessage: jest.fn(({ defaultMessage }) => defaultMessage), | ||
}, | ||
}; | ||
|
||
const testChecklistData = checklistItems[defaultProps.idPrefix]; | ||
|
||
const completedItemIds = ['welcomeMessage', 'courseDates'] | ||
|
||
const renderComponent = (props) => { | ||
render( | ||
<IntlProvider locale="en"> | ||
<AppProvider store={store}> | ||
<ChecklistSection {...props} /> | ||
</AppProvider> | ||
</IntlProvider>, | ||
); | ||
const waffleFlags = { | ||
ENABLE_NEW_COURSE_UPDATES_PAGE: false, | ||
}; | ||
|
||
let store; | ||
|
||
describe('ChecklistSection', () => { | ||
describe('ChecklistItemBody', () => { | ||
beforeEach(() => { | ||
initializeMockApp({ | ||
authenticatedUser: { | ||
userId: 3, | ||
username: 'abc123', | ||
administrator: false, | ||
roles: [], | ||
}, | ||
}); | ||
store = initializeStore(initialState); | ||
}); | ||
|
||
it('a heading using the dataHeading prop', () => { | ||
renderComponent(defaultProps); | ||
|
||
expect(screen.getByText(defaultProps.dataHeading)).toBeVisible(); | ||
}); | ||
|
||
it('completion count text', () => { | ||
renderComponent(defaultProps); | ||
const completionText = `${completedItemIds.length}/6 completed`; | ||
expect(screen.getByTestId('completion-subheader').textContent).toEqual(completionText); | ||
useSelector.mockReturnValue({ waffleFlags }); | ||
}); | ||
|
||
it('a loading spinner when isLoading prop is true', () => { | ||
renderComponent({ ...defaultProps, isLoading: true }); | ||
|
||
const completionSubheader = screen.queryByTestId('completion-subheader'); | ||
expect(completionSubheader).toBeNull(); | ||
|
||
const loadingSpinner = screen.getByTestId('loading-spinner'); | ||
expect(loadingSpinner).toBeVisible(); | ||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('the correct number of checks', () => { | ||
renderComponent(defaultProps); | ||
it('renders uncompleted icon when isCompleted is false', () => { | ||
render( | ||
<IntlProvider locale="en"> | ||
<ChecklistItemBody {...defaultProps} /> | ||
</IntlProvider>, | ||
); | ||
|
||
const listItems = screen.getAllByTestId('checklist-item', { exact: false }); | ||
expect(listItems).toHaveLength(6); | ||
const uncompletedIcon = screen.getByTestId('uncompleted-icon'); | ||
expect(uncompletedIcon).toBeInTheDocument(); | ||
}); | ||
|
||
it('welcomeMessage comment section should be null', () => { | ||
renderComponent(defaultProps); | ||
it('renders completed icon when isCompleted is true', () => { | ||
render( | ||
<IntlProvider locale="en"> | ||
<ChecklistItemBody {...defaultProps} isCompleted /> | ||
</IntlProvider>, | ||
); | ||
|
||
const comment = screen.getByTestId('comment-section-welcomeMessage'); | ||
expect(comment.children).toHaveLength(0); | ||
const completedIcon = screen.getByTestId('completed-icon'); | ||
expect(completedIcon).toBeInTheDocument(); | ||
}); | ||
|
||
it('certificate comment section should be null', () => { | ||
renderComponent(defaultProps); | ||
it('renders short and long descriptions based on checkId', () => { | ||
render( | ||
<IntlProvider locale="en"> | ||
<ChecklistItemBody {...defaultProps} /> | ||
</IntlProvider>, | ||
); | ||
|
||
const comment = screen.getByTestId('comment-section-certificate'); | ||
expect(comment.children).toHaveLength(0); | ||
}); | ||
const shortDescription = screen.getByText(messages.welcomeMessageShortDescription.defaultMessage); | ||
const longDescription = screen.getByText(messages.welcomeMessageLongDescription.defaultMessage); | ||
|
||
it('courseDates comment section should be null', () => { | ||
renderComponent(defaultProps); | ||
|
||
const comment = screen.getByTestId('comment-section-courseDates'); | ||
expect(comment.children).toHaveLength(0); | ||
expect(shortDescription).toBeInTheDocument(); | ||
expect(longDescription).toBeInTheDocument(); | ||
}); | ||
|
||
it('proctoringEmail comment section should be null', () => { | ||
renderComponent(defaultProps); | ||
|
||
const comment = screen.getByTestId('comment-section-proctoringEmail'); | ||
expect(comment.children).toHaveLength(0); | ||
}); | ||
it('renders update hyperlink when updateLink is provided', () => { | ||
render( | ||
<IntlProvider locale="en"> | ||
<ChecklistItemBody {...defaultProps} /> | ||
</IntlProvider>, | ||
); | ||
|
||
describe('gradingPolicy comment section', () => { | ||
it('should be null if sum of weights is equal to 1', () => { | ||
const props = { | ||
...defaultProps, | ||
data: { | ||
...defaultProps.data, | ||
grades: { | ||
...defaultProps.data.grades, | ||
sumOfWeights: 1, | ||
} | ||
}, | ||
}; | ||
renderComponent(props); | ||
|
||
const comment = screen.getByTestId('comment-section-gradingPolicy'); | ||
expect(comment.children).toHaveLength(0); | ||
}); | ||
|
||
it('should have comment section', () => { | ||
renderComponent(defaultProps); | ||
|
||
const comment = screen.getByTestId('comment-section-gradingPolicy'); | ||
expect(comment.children).toHaveLength(1); | ||
|
||
expect(screen.getByText( | ||
'Your current grading policy adds up to', | ||
{ exact: false }, | ||
)).toBeVisible(); | ||
}); | ||
const updateLink = screen.getByTestId('update-hyperlink'); | ||
expect(updateLink).toBeInTheDocument(); | ||
}); | ||
|
||
describe('assignmentDeadlines comment section', () => { | ||
it('should be null if assignments with dates before start and after end are empty', () => { | ||
const props = { | ||
...defaultProps, | ||
data: { | ||
...defaultProps.data, | ||
assignments: { | ||
...defaultProps.data.assignments, | ||
assignmentsWithDatesAfterEnd: [], | ||
assignmentsWithOraDatesBeforeStart: [], | ||
} | ||
}, | ||
}; | ||
renderComponent(props); | ||
|
||
const comment = screen.getByTestId('comment-section-assignmentDeadlines'); | ||
expect(comment.children).toHaveLength(0); | ||
}); | ||
|
||
it('should have comment section', () => { | ||
renderComponent(defaultProps); | ||
it('navigates to internal course page if ENABLE_NEW_COURSE_UPDATES_PAGE flag is enabled', () => { | ||
useSelector.mockReturnValue({ waffleFlags: { ENABLE_NEW_COURSE_UPDATES_PAGE: true } }); | ||
|
||
const comment = screen.getByTestId('comment-section-assignmentDeadlines'); | ||
const assigmentLinks = within(comment).getAllByRole('link'); | ||
render( | ||
<IntlProvider locale="en"> | ||
<ChecklistItemBody {...defaultProps} /> | ||
</IntlProvider>, | ||
); | ||
|
||
expect(comment.children).toHaveLength(1); | ||
const updateLink = screen.getByTestId('update-hyperlink'); | ||
fireEvent.click(updateLink); | ||
|
||
expect(screen.getByText( | ||
messages.assignmentDeadlinesComment.defaultMessage, | ||
{ exact: false }, | ||
)).toBeVisible(); | ||
expect(mockNavigate).toHaveBeenCalledWith(`/course/${defaultProps.courseId}/course_info`); | ||
}); | ||
|
||
expect(assigmentLinks).toHaveLength(2); | ||
it('redirects to external link if ENABLE_NEW_COURSE_UPDATES_PAGE flag is disabled', () => { | ||
render( | ||
<IntlProvider locale="en"> | ||
<ChecklistItemBody {...defaultProps} /> | ||
</IntlProvider>, | ||
); | ||
|
||
expect(assigmentLinks[0].textContent).toEqual('Subsection'); | ||
const updateLink = screen.getByTestId('update-hyperlink'); | ||
fireEvent.click(updateLink); | ||
|
||
expect(assigmentLinks[1].textContent).toEqual('ORA subsection'); | ||
}); | ||
}); | ||
}); | ||
|
||
testChecklistData.forEach((check) => { | ||
describe(`check with id '${check.id}'`, () => { | ||
let checkItem; | ||
beforeEach(() => { | ||
initializeMockApp({ | ||
authenticatedUser: { | ||
userId: 3, | ||
username: 'abc123', | ||
administrator: false, | ||
roles: [], | ||
}, | ||
}); | ||
store = initializeStore(initialState); | ||
renderComponent(defaultProps); | ||
checkItem = screen.getAllByTestId(`checklist-item-${check.id}`); | ||
}); | ||
|
||
it('renders', () => { | ||
expect(checkItem).toHaveLength(1); | ||
}); | ||
|
||
it('has correct icon', () => { | ||
const icon = screen.getAllByTestId(`icon-${check.id}`) | ||
|
||
expect(icon).toHaveLength(1); | ||
|
||
const { queryByTestId } = within(icon[0]); | ||
if (completedItemIds.includes(check.id)) { | ||
expect(queryByTestId('completed-icon')).not.toBeNull(); | ||
} else { | ||
expect(queryByTestId('uncompleted-icon')).not.toBeNull(); | ||
} | ||
}); | ||
|
||
it('has correct short description', () => { | ||
const { getByText } = within(checkItem[0]); | ||
const shortDescription = messages[`${check.id}ShortDescription`].defaultMessage; | ||
expect(getByText(shortDescription)).toBeVisible(); | ||
}); | ||
|
||
it('has correct long description', () => { | ||
const { getByText } = within(checkItem[0]); | ||
const longDescription = messages[`${check.id}LongDescription`].defaultMessage; | ||
expect(getByText(longDescription)).toBeVisible(); | ||
}); | ||
|
||
describe('has correct link', () => { | ||
const links = getUpdateLinks('courseId') | ||
const shouldShowLink = Object.keys(links).includes(check.id); | ||
|
||
if (shouldShowLink) { | ||
it('with a Hyperlink', () => { | ||
const { getByRole, getByText } = within(checkItem[0]); | ||
|
||
expect(getByText('Update')).toBeVisible(); | ||
|
||
expect(getByRole('link').href).toMatch(links[check.id]); | ||
}); | ||
} else { | ||
it('without a Hyperlink', () => { | ||
const { queryByText } = within(checkItem[0]); | ||
|
||
expect(queryByText('Update')).toBeNull(); | ||
}); | ||
} | ||
}); | ||
expect(window.location.href).toBe('http://localhost/'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { render } from '@testing-library/react'; | ||
import '@testing-library/jest-dom/extend-expect'; | ||
import { BrowserRouter as Router } from 'react-router-dom'; | ||
|
||
import HelpSidebarLink from './HelpSidebarLink'; | ||
|
||
describe('HelpSidebarLink Component', () => { | ||
const defaultProps = { | ||
isNewPage: true, | ||
pathToPage: '/test-page', | ||
title: 'Test Title', | ||
as: 'li', | ||
}; | ||
|
||
it('renders a React Router Link when isNewPage is true', () => { | ||
const { getByText } = render( | ||
<Router> | ||
<HelpSidebarLink {...defaultProps} /> | ||
</Router>, | ||
); | ||
|
||
const linkElement = getByText('Test Title'); | ||
expect(linkElement.closest('a')).toHaveAttribute('href', '/test-page'); | ||
}); | ||
|
||
it('renders a Hyperlink when isNewPage is false', () => { | ||
const props = { ...defaultProps, isNewPage: false, pathToPage: 'https://example.com' }; | ||
const { getByText } = render(<HelpSidebarLink {...props} />); | ||
|
||
const hyperlinkElement = getByText('Test Title'); | ||
expect(hyperlinkElement.closest('a')).toHaveAttribute('href', 'https://example.com'); | ||
expect(hyperlinkElement.closest('a')).toHaveAttribute('target', '_blank'); | ||
}); | ||
|
||
it('renders the correct tag element specified by "as" prop', () => { | ||
const props = { ...defaultProps, as: 'div' }; | ||
const { container } = render( | ||
<Router> | ||
<HelpSidebarLink {...props} /> | ||
</Router>, | ||
); | ||
|
||
const tagElement = container.querySelector('div.sidebar-link'); | ||
expect(tagElement).toBeInTheDocument(); | ||
}); | ||
}); |
Oops, something went wrong.