Add CoursewareSearchForm component (#1214)
* feat: Add CoursewareSearchBar component * fix: lint * fix: Clarified component names and i18n description * test: Add more tests * fix: lint * fix: Made props in CoursewareSearchForm optional
This commit is contained in:
@@ -9,6 +9,8 @@ import { setShowSearch } from '../data/slice';
|
||||
import { useElementBoundingBox, useLockScroll } from './hooks';
|
||||
import messages from './messages';
|
||||
|
||||
import CoursewareSearchForm from './CoursewareSearchForm';
|
||||
|
||||
const CoursewareSearch = ({ intl, ...sectionProps }) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
@@ -31,7 +33,9 @@ const CoursewareSearch = ({ intl, ...sectionProps }) => {
|
||||
</div>
|
||||
<div className="courseware-search__outer-content">
|
||||
<div className="courseware-search__content" style={{ height: '999px' }}>
|
||||
<h2>{intl.formatMessage(messages.searchModuleTitle)}</h2>
|
||||
<CoursewareSearchForm
|
||||
placeholder={intl.formatMessage(messages.searchBarPlaceholderText)}
|
||||
/>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis semper rutrum odio quis congue.
|
||||
Duis sodales nibh et sapien elementum fermentum. Quisque magna urna, gravida at gravida et,
|
||||
|
||||
37
src/course-home/courseware-search/CoursewareSearchForm.jsx
Normal file
37
src/course-home/courseware-search/CoursewareSearchForm.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { SearchField } from '@edx/paragon';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const CoursewareSearchForm = ({
|
||||
onSubmit,
|
||||
onChange,
|
||||
placeholder,
|
||||
}) => (
|
||||
<SearchField.Advanced
|
||||
onSubmit={onSubmit}
|
||||
onChange={onChange}
|
||||
submitButtonLocation="external"
|
||||
className="courseware-search-form"
|
||||
>
|
||||
<div className="pgn__searchfield_wrapper" data-testid="courseware-search-form">
|
||||
<SearchField.Label />
|
||||
<SearchField.Input placeholder={placeholder} />
|
||||
<SearchField.ClearButton />
|
||||
</div>
|
||||
<SearchField.SubmitButton submitButtonLocation="external" />
|
||||
</SearchField.Advanced>
|
||||
);
|
||||
|
||||
CoursewareSearchForm.propTypes = {
|
||||
onSubmit: PropTypes.func,
|
||||
onChange: PropTypes.func,
|
||||
placeholder: PropTypes.string,
|
||||
};
|
||||
|
||||
CoursewareSearchForm.defaultProps = {
|
||||
onSubmit: undefined,
|
||||
onChange: undefined,
|
||||
placeholder: undefined,
|
||||
};
|
||||
|
||||
export default CoursewareSearchForm;
|
||||
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
act,
|
||||
initializeMockApp,
|
||||
render,
|
||||
screen,
|
||||
waitFor,
|
||||
fireEvent,
|
||||
} from '../../setupTest';
|
||||
import CoursewareSearchForm from './CoursewareSearchForm';
|
||||
|
||||
function renderComponent(placeholder, onSubmit, onChange) {
|
||||
const { container } = render(<CoursewareSearchForm
|
||||
placeholder={placeholder}
|
||||
onSubmit={onSubmit}
|
||||
onChange={onChange}
|
||||
/>);
|
||||
return container;
|
||||
}
|
||||
|
||||
describe('CoursewareSearchToggle', () => {
|
||||
const placeholderText = 'Search for courseware';
|
||||
let onSubmitHandlerMock;
|
||||
let onChangeHandlerMock;
|
||||
|
||||
beforeAll(async () => {
|
||||
onChangeHandlerMock = jest.fn();
|
||||
onSubmitHandlerMock = jest.fn();
|
||||
initializeMockApp();
|
||||
});
|
||||
|
||||
it('should render', async () => {
|
||||
await act(async () => renderComponent(placeholderText, onSubmitHandlerMock, onChangeHandlerMock));
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId('courseware-search-form')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should call onChange handler when input changes', async () => {
|
||||
await act(async () => renderComponent(placeholderText, onSubmitHandlerMock, onChangeHandlerMock));
|
||||
await waitFor(() => {
|
||||
const element = screen.queryByPlaceholderText(placeholderText);
|
||||
fireEvent.change(element, { target: { value: 'test' } });
|
||||
expect(onChangeHandlerMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should call onSubmit handler when submit is clicked', async () => {
|
||||
await act(async () => renderComponent(placeholderText, onSubmitHandlerMock, onChangeHandlerMock));
|
||||
await waitFor(() => {
|
||||
const element = screen.queryAllByText('Search')[0];
|
||||
fireEvent.click(element);
|
||||
expect(onSubmitHandlerMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
});
|
||||
@@ -16,6 +16,11 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Search this course',
|
||||
description: 'Title for the Courseware Search module.',
|
||||
},
|
||||
searchBarPlaceholderText: {
|
||||
id: 'learn.coursewareSerch.searchBarPlaceholderText',
|
||||
defaultMessage: 'Search',
|
||||
description: 'Placeholder text for the Courseware Search input control',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
|
||||
Reference in New Issue
Block a user