-
Notifications
You must be signed in to change notification settings - Fork 215
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into atelischak/courseware-search-tab-filters
- Loading branch information
Showing
8 changed files
with
817 additions
and
61 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
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
77 changes: 77 additions & 0 deletions
77
src/course-home/courseware-search/CoursewareSearchResults.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 |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import React from 'react'; | ||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; | ||
import { | ||
Folder, TextFields, VideoCamera, Article, | ||
} from '@edx/paragon/icons'; | ||
import { Icon } from '@edx/paragon'; | ||
import PropTypes from 'prop-types'; | ||
import messages from './messages'; | ||
|
||
const iconTypeMapping = { | ||
document: Folder, | ||
text: TextFields, | ||
video: VideoCamera, | ||
}; | ||
const defaultIcon = Article; | ||
|
||
const CoursewareSearchResults = ({ intl, results }) => { | ||
if (!results?.length) { | ||
return ( | ||
<div className="courseware-search-results"> | ||
<p className="courseware-search-results__empty" data-testid="no-results">{intl.formatMessage(messages.searchResultsNone)}</p> | ||
</div> | ||
); | ||
} | ||
|
||
return ( | ||
<div className="courseware-search-results" data-testid="search-results"> | ||
{results.map(({ | ||
title, href, type, breadcrumbs, contentMatches, isExternal, | ||
}) => { | ||
const key = type.toLowerCase(); | ||
const icon = iconTypeMapping[key] || defaultIcon; | ||
|
||
const linkProps = isExternal ? { | ||
href, | ||
target: '_blank', | ||
rel: 'nofollow', | ||
} : { href }; | ||
|
||
return ( | ||
<a className="courseware-search-results__item" {...linkProps}> | ||
<div className="courseware-search-results__icon"><Icon src={icon} /></div> | ||
<div className="courseware-search-results__info"> | ||
<div className="courseware-search-results__title"> | ||
<span>{title}</span> | ||
{contentMatches ? (<em>{contentMatches}</em>) : null } | ||
</div> | ||
{breadcrumbs?.length ? ( | ||
<ul className="courseware-search-results__breadcrumbs"> | ||
{breadcrumbs.map(bc => (<li><div>{bc}</div></li>))} | ||
</ul> | ||
) : null} | ||
</div> | ||
</a> | ||
); | ||
})} | ||
</div> | ||
); | ||
}; | ||
|
||
CoursewareSearchResults.propTypes = { | ||
intl: intlShape.isRequired, | ||
results: PropTypes.arrayOf(PropTypes.objectOf({ | ||
title: PropTypes.string.isRequired, | ||
href: PropTypes.string.isRequired, | ||
type: PropTypes.string, | ||
breadcrumbs: PropTypes.arrayOf(PropTypes.string), | ||
contentMatches: PropTypes.number, | ||
isExternal: PropTypes.bool, | ||
})), | ||
}; | ||
|
||
CoursewareSearchResults.defaultProps = { | ||
results: [], | ||
}; | ||
|
||
export default injectIntl(CoursewareSearchResults); |
38 changes: 38 additions & 0 deletions
38
src/course-home/courseware-search/CoursewareSearchResults.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 |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import React from 'react'; | ||
import { | ||
initializeMockApp, | ||
render, | ||
screen, | ||
} from '../../setupTest'; | ||
import CoursewareSearchResults from './CoursewareSearchResults'; | ||
import messages from './messages'; | ||
import mockedData from './test-data/mockedResults'; | ||
|
||
jest.mock('react-redux'); | ||
|
||
function renderComponent({ results }) { | ||
const { container } = render(<CoursewareSearchResults results={results} />); | ||
return container; | ||
} | ||
|
||
describe('CoursewareSearchResults', () => { | ||
beforeAll(async () => { | ||
initializeMockApp(); | ||
}); | ||
|
||
describe('when an empty array is provided', () => { | ||
beforeEach(() => { renderComponent({ results: [] }); }); | ||
|
||
it('should render a "no results found" message.', () => { | ||
expect(screen.getByTestId('no-results').textContent).toBe(messages.searchResultsNone.defaultMessage); | ||
}); | ||
}); | ||
|
||
describe('when list of results is provided', () => { | ||
beforeEach(() => { renderComponent({ results: mockedData }); }); | ||
|
||
it('should match the snapshot', () => { | ||
expect(screen.getByTestId('search-results')).toMatchSnapshot(); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.