feat: override filter status component

fix: review modal test failure

chore: update unit test

chore: update hook and test

chore: add unit test for set all filter

chore: update use callback mock
This commit is contained in:
Leangseu Kim
2022-02-16 14:43:08 -05:00
committed by leangseu-edx
parent 59c57028a0
commit 278ac101a7
7 changed files with 189 additions and 1 deletions

View File

@@ -0,0 +1,65 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Button, DataTableContext } from '@edx/paragon';
import * as module from './FilterStatusComponent';
export const filterHooks = () => {
const { state, setAllFilters, headers } = React.useContext(DataTableContext);
if (!setAllFilters || !state.filters) {
return {};
}
const clearFilters = React.useCallback(() => setAllFilters([]), []);
const headerMap = headers.reduce(
(obj, cur) => ({ ...obj, [cur.id]: cur.Header }),
{},
);
const filterNames = state.filters.map((filter) => headerMap[filter.id]);
return { clearFilters, filterNames };
};
export const FilterStatusComponent = ({
className,
variant,
size,
clearFiltersText,
buttonClassName,
showFilteredFields,
}) => {
const { clearFilters, filterNames } = module.filterHooks();
if (!clearFilters) {
return null;
}
const filterTexts = <p>Filtered by {filterNames.join(', ')}</p>;
return (
<div className={className}>
{showFilteredFields && filterTexts}
<Button
className={buttonClassName}
variant={variant}
size={size}
onClick={clearFilters}
>
{clearFiltersText}
</Button>
</div>
);
};
FilterStatusComponent.defaultProps = {
className: '',
buttonClassName: 'pgn__smart-status-button',
variant: 'link',
size: 'inline',
clearFiltersText: 'Clear Filters',
showFilteredFields: true,
};
FilterStatusComponent.propTypes = {
className: PropTypes.string,
buttonClassName: PropTypes.string,
variant: PropTypes.string,
size: PropTypes.string,
clearFiltersText: PropTypes.string,
showFilteredFields: PropTypes.bool,
};

View File

@@ -0,0 +1,80 @@
import React from 'react';
import { shallow } from 'enzyme';
import * as module from './FilterStatusComponent';
const mockFilterHooks = {
clearFilters: jest.fn().mockName('clearFilters'),
filterNames: ['some abitary', 'column'],
};
const mockSetAllFilters = jest.fn().mockName('setAllFilters');
describe('FilterStatusComponent component', () => {
const props = {
className: 'css-class-name',
variant: 'button-variant',
size: 'button-size',
clearFiltersText: 'clear-filter-text',
buttonClassName: 'css-class-name-for-button',
showFilteredFields: true,
};
const contextProps = {
state: {
filters: [
{
id: 'filter-column',
value: 'abitary',
},
],
},
setAllFilters: () => mockSetAllFilters,
headers: [
{
id: 'filter-column',
Header: 'Formatted Filter Column',
},
{
id: 'dummy-column',
Header: 'Not showing column',
},
],
};
const { FilterStatusComponent } = module;
describe('snapshot', () => {
test('with filter', () => {
jest.spyOn(module, 'filterHooks').mockImplementationOnce(() => mockFilterHooks);
const el = shallow(<FilterStatusComponent {...props} />);
expect(el).toMatchSnapshot();
});
test('with filter but do not show filterd field', () => {
jest.spyOn(module, 'filterHooks').mockImplementationOnce(() => mockFilterHooks);
const el = shallow(<FilterStatusComponent {...props} showFilteredFields={false} />);
expect(el).toMatchSnapshot();
});
test('without filter', () => {
jest.spyOn(module, 'filterHooks').mockImplementationOnce(() => ({}));
const el = shallow(<FilterStatusComponent {...props} />);
expect(el).toMatchSnapshot();
});
});
describe('component', () => {
test('clear filter click', () => {
jest.spyOn(module, 'filterHooks').mockImplementationOnce(() => mockFilterHooks);
const el = shallow(<FilterStatusComponent {...props} />);
el.find('Button').simulate('click');
expect(mockFilterHooks.clearFilters).toHaveBeenCalledTimes(1);
});
test('on clear filter, set all filter get called with empty array', () => {
jest.spyOn(React, 'useContext').mockImplementationOnce(() => ({ ...contextProps }));
jest.spyOn(React, 'useCallback').mockImplementationOnce(cb => cb());
const el = shallow(<FilterStatusComponent {...props} />);
el.find('Button').simulate('click');
expect(mockSetAllFilters).toHaveBeenCalledTimes(1);
});
});
});

View File

@@ -15,6 +15,7 @@ import lmsMessages from 'data/services/lms/messages';
import { selectors, thunkActions } from 'data/redux';
import StatusBadge from 'components/StatusBadge';
import FilterStatusComponent from './FilterStatusComponent';
import messages from './messages';
@@ -89,6 +90,7 @@ export class SubmissionsTable extends React.Component {
return (
<DataTable
isFilterable
FilterStatusComponent={FilterStatusComponent}
numBreakoutFilters={2}
defaultColumnValues={{ Filter: TextFilter }}
isSelectable

View File

@@ -19,6 +19,8 @@ import {
mapDispatchToProps,
} from './SubmissionsTable';
jest.mock('./FilterStatusComponent', () => jest.fn().mockName('FilterStatusComponent'));
jest.mock('data/redux', () => ({
selectors: {
app: {

View File

@@ -0,0 +1,37 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FilterStatusComponent component snapshot with filter 1`] = `
<div
className="css-class-name"
>
<p>
Filtered by
some abitary, column
</p>
<Button
className="css-class-name-for-button"
onClick={[MockFunction clearFilters]}
size="button-size"
variant="button-variant"
>
clear-filter-text
</Button>
</div>
`;
exports[`FilterStatusComponent component snapshot with filter but do not show filterd field 1`] = `
<div
className="css-class-name"
>
<Button
className="css-class-name-for-button"
onClick={[MockFunction clearFilters]}
size="button-size"
variant="button-variant"
>
clear-filter-text
</Button>
</div>
`;
exports[`FilterStatusComponent component snapshot without filter 1`] = `""`;

View File

@@ -4,6 +4,7 @@ exports[`SubmissionsTable component component render tests snapshots snapshot: e
exports[`SubmissionsTable component component render tests snapshots snapshot: happy path 1`] = `
<DataTable
FilterStatusComponent={[MockFunction FilterStatusComponent]}
bulkActions={
Array [
[MockFunction this.selectedBulkAction],
@@ -124,6 +125,7 @@ exports[`SubmissionsTable component component render tests snapshots snapshot: h
exports[`SubmissionsTable component component render tests snapshots snapshot: team happy path 1`] = `
<DataTable
FilterStatusComponent={[MockFunction FilterStatusComponent]}
bulkActions={
Array [
[MockFunction this.selectedBulkAction],

View File

@@ -118,7 +118,7 @@ export const mapStateToProps = (state) => ({
export const mapDispatchToProps = {
setShowReview: actions.app.setShowReview,
stopGrading: thunkActions.grading.cancelGrading,
reloadSubmissions: thunkActions.app.reloadSubmissions,
reloadSubmissions: thunkActions.app.initialize,
};
export default connect(mapStateToProps, mapDispatchToProps)(ReviewModal);