diff --git a/package.json b/package.json index b7adde45..3e49a496 100644 --- a/package.json +++ b/package.json @@ -71,14 +71,6 @@ "webpack": "4.44.2", "webpack-cli": "3.3.12" }, - "jest": { - "collectCoverageFrom": [ - "src/**/*.{js,jsx}", - "!src/index.js", - "!**/node_modules/**", - "!**/tests/**" - ] - }, "peerDependencies": { "@edx/frontend-platform": "^1.5.2", "@edx/paragon": "^14.5.0", diff --git a/src/course-search/SearchBox.jsx b/src/course-search/SearchBox.jsx index 4121590f..947a4ab6 100644 --- a/src/course-search/SearchBox.jsx +++ b/src/course-search/SearchBox.jsx @@ -1,23 +1,22 @@ -import React from 'react'; +import React, { useContext } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import { useHistory } from 'react-router-dom'; -import qs from 'query-string'; import { SearchField } from '@edx/paragon'; import { connectSearchBox } from 'react-instantsearch-dom'; -import { updateRefinementsFromQueryParams } from './data/utils'; +import { deleteRefinementAction, setRefinementAction } from './data/actions'; import { STYLE_VARIANTS } from '../constants'; +import { SearchContext } from './SearchContext'; +import { QUERY_PARAM_FOR_PAGE, QUERY_PARAM_FOR_SEARCH_QUERY } from './data/constants'; export const searchText = 'Search courses'; export const SearchBoxBase = ({ className, defaultRefinement, - refinementsFromQueryParams, variant, }) => { - const history = useHistory(); + const { dispatch } = useContext(SearchContext); /** * Handles when a search is submitted by adding the user's search @@ -25,12 +24,8 @@ export const SearchBoxBase = ({ * existing query parameters must be preserved. */ const handleSubmit = (searchQuery) => { - const refinements = { ...refinementsFromQueryParams }; - refinements.q = searchQuery; - delete refinements.page; // reset to page 1 - - const updatedRefinements = updateRefinementsFromQueryParams(refinements); - history.push({ search: qs.stringify(updatedRefinements) }); + dispatch(setRefinementAction(QUERY_PARAM_FOR_SEARCH_QUERY, searchQuery)); + dispatch(deleteRefinementAction(QUERY_PARAM_FOR_PAGE)); }; /** @@ -38,12 +33,8 @@ export const SearchBoxBase = ({ * from the query parameters. */ const handleClear = () => { - const refinements = { ...refinementsFromQueryParams }; - delete refinements.q; - delete refinements.page; // reset to page 1 - - const updatedRefinements = updateRefinementsFromQueryParams(refinements); - history.push({ search: qs.stringify(updatedRefinements) }); + dispatch(deleteRefinementAction(QUERY_PARAM_FOR_SEARCH_QUERY)); + dispatch(deleteRefinementAction(QUERY_PARAM_FOR_PAGE)); }; return ( @@ -69,7 +60,6 @@ export const SearchBoxBase = ({ }; SearchBoxBase.propTypes = { - refinementsFromQueryParams: PropTypes.shape().isRequired, defaultRefinement: PropTypes.string, className: PropTypes.string, variant: PropTypes.oneOf([STYLE_VARIANTS.default, STYLE_VARIANTS.inverse]), diff --git a/src/course-search/SearchHeader.jsx b/src/course-search/SearchHeader.jsx index b04a81f4..20100f4a 100644 --- a/src/course-search/SearchHeader.jsx +++ b/src/course-search/SearchHeader.jsx @@ -30,7 +30,6 @@ const SearchHeader = ({ variant, containerSize }) => { diff --git a/src/course-search/tests/SearchBox.test.jsx b/src/course-search/tests/SearchBox.test.jsx index b34d34b0..9eab9234 100644 --- a/src/course-search/tests/SearchBox.test.jsx +++ b/src/course-search/tests/SearchBox.test.jsx @@ -3,15 +3,13 @@ import { screen, fireEvent } from '@testing-library/react'; import '@testing-library/jest-dom/extend-expect'; import { SearchBoxBase, searchText } from '../SearchBox'; - -import { renderWithRouter } from '../../utils/tests'; +import { renderWithSearchContext } from '../../utils/tests'; const TEST_QUERY = 'test query'; describe('', () => { test('renders with a label', () => { - const refinements = {}; - renderWithRouter(); + renderWithSearchContext(); // assert the Paragon component renders expect(screen.queryByRole('search')).toBeInTheDocument(); @@ -22,26 +20,14 @@ describe('', () => { }); test('renders with an initial value', () => { - const refinements = { - q: TEST_QUERY, - }; - const Component = () => ( - - ); - renderWithRouter(); + renderWithSearchContext(); // assert the Paragon component renders expect(screen.queryByRole('searchbox')).toHaveAttribute('value', TEST_QUERY); }); - test('handles submit', () => { - const refinements = {}; - const { history } = renderWithRouter(); + test('handles submit and clear', () => { + const { history } = renderWithSearchContext(); // fill in search input and submit the search fireEvent.change(screen.getByRole('searchbox'), { target: { value: TEST_QUERY } }); @@ -50,31 +36,12 @@ describe('', () => { // assert url is updated with the query expect(history).toHaveLength(2); expect(history.location.search).toEqual('?q=test%20query'); - }); - - test('handles clear', async () => { - const refinements = { - q: TEST_QUERY, - page: 2, - }; - const Component = () => ( - - ); - const { history } = renderWithRouter(, { - route: '/?q=test%20query&page=2', - }); - - // assert query initially exists in url - expect(history.location.search).toEqual('?q=test%20query&page=2'); // clear the input fireEvent.click(screen.getByText('clear search')); // assert query no longer exists in url - expect(history).toHaveLength(2); + expect(history).toHaveLength(3); expect(history.location.search).toEqual(''); }); }); diff --git a/src/index.js b/src/index.js index 92125011..2b9d137f 100644 --- a/src/index.js +++ b/src/index.js @@ -13,6 +13,7 @@ export { default as SearchHeader } from './course-search/SearchHeader'; export { default as SearchPagination } from './course-search/SearchPagination'; export { useNbHitsFromSearchResults, getCatalogString } from './course-search/data/hooks'; export { SEARCH_FACET_FILTERS, SHOW_ALL_NAME } from './course-search/data/constants'; +export { renderWithSearchContext } from './utils/tests'; export { addToRefinementArray, deleteRefinementAction, diff --git a/src/utils/tests.jsx b/src/utils/tests.jsx index 2c98b5cf..1dd0550a 100644 --- a/src/utils/tests.jsx +++ b/src/utils/tests.jsx @@ -2,9 +2,8 @@ import React from 'react'; import { Router } from 'react-router-dom'; import { createMemoryHistory } from 'history'; import { render } from '@testing-library/react'; -import { AppContext } from '@edx/frontend-platform/react'; +import SearchData from '../course-search/SearchContext'; -// eslint-disable import/prefer-default-export export function renderWithRouter( ui, { @@ -25,28 +24,8 @@ export function renderWithRouter( }; } -/* eslint-disable react/prop-types */ -export const FakeAppContext = ({ - initialAppState = {}, - children, -}) => ( - +export const renderWithSearchContext = (children) => renderWithRouter( + {children} - + , ); -/* eslint-enable react/prop-types */ - -/* warning, this store may not be complete, please add to it as needed */ -export const fakeReduxStore = { - courseEnrollments: { - courseRuns: [], - error: null, - isMarkCourseCompleteSuccess: false, - isMoveToInProgressSuccess: false, - }, - offers: { - loading: false, - offersCount: 0, - offers: [], - }, -};