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:
David Nuon
2023-10-24 13:32:26 -07:00
committed by GitHub
parent 040f1cb55b
commit 7c9211073f
4 changed files with 107 additions and 1 deletions

View File

@@ -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,

View 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;

View File

@@ -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();
});
});

View File

@@ -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;