Unverified Commit 71383b15 authored by Ryan Lieu's avatar Ryan Lieu Committed by GitHub

Moved PopularTables out into separate component (#183)

* moved PopularTables out into separate component

* added tests

* fixed linting issues

* removed bookmarklist from populartables

* fixed tests

* addressed comments

* move populartables component to common

* removed unecessary boiler plate, improved tests
parent 90bb34a5
...@@ -6,10 +6,6 @@ export const DOCUMENT_TITLE_SUFFIX = ' - Amundsen Search'; ...@@ -6,10 +6,6 @@ export const DOCUMENT_TITLE_SUFFIX = ' - Amundsen Search';
export const PAGE_INDEX_ERROR_MESSAGE = 'Page index out of bounds for available matches'; export const PAGE_INDEX_ERROR_MESSAGE = 'Page index out of bounds for available matches';
export const POPULAR_TABLES_INFO_TEXT = 'These are some of the most commonly accessed tables within your organization.';
export const POPULAR_TABLES_LABEL = 'Popular Tables';
export const POPULAR_TABLES_SOURCE_NAME = 'popular_tables';
export const SEARCH_INFO_TEXT = `Ordered by the relevance of matches within a resource's metadata, as well as overall usage.`; export const SEARCH_INFO_TEXT = `Ordered by the relevance of matches within a resource's metadata, as well as overall usage.`;
export const SEARCH_SOURCE_NAME = 'search_results'; export const SEARCH_SOURCE_NAME = 'search_results';
export const SEARCH_ERROR_MESSAGE_INFIX = ' - did not match any '; export const SEARCH_ERROR_MESSAGE_INFIX = ' - did not match any ';
......
...@@ -9,6 +9,7 @@ import { RouteComponentProps } from 'react-router'; ...@@ -9,6 +9,7 @@ import { RouteComponentProps } from 'react-router';
import SearchBar from './SearchBar'; import SearchBar from './SearchBar';
import SearchList from './SearchList'; import SearchList from './SearchList';
import LoadingSpinner from 'components/common/LoadingSpinner'; import LoadingSpinner from 'components/common/LoadingSpinner';
import PopularTables from 'components/common/PopularTables';
import BookmarkList from 'components/common/Bookmark/BookmarkList' import BookmarkList from 'components/common/Bookmark/BookmarkList'
import InfoButton from 'components/common/InfoButton'; import InfoButton from 'components/common/InfoButton';
...@@ -25,8 +26,6 @@ import { ...@@ -25,8 +26,6 @@ import {
TableSearchResults, TableSearchResults,
UserSearchResults UserSearchResults
} from 'ducks/search/types'; } from 'ducks/search/types';
import { getPopularTables } from 'ducks/popularTables/reducer';
import { GetPopularTablesRequest } from 'ducks/popularTables/types';
// TODO: Use css-modules instead of 'import' // TODO: Use css-modules instead of 'import'
import './styles.scss'; import './styles.scss';
...@@ -35,9 +34,6 @@ import { ...@@ -35,9 +34,6 @@ import {
DOCUMENT_TITLE_SUFFIX, DOCUMENT_TITLE_SUFFIX,
PAGE_INDEX_ERROR_MESSAGE, PAGE_INDEX_ERROR_MESSAGE,
PAGINATION_PAGE_RANGE, PAGINATION_PAGE_RANGE,
POPULAR_TABLES_INFO_TEXT,
POPULAR_TABLES_LABEL,
POPULAR_TABLES_SOURCE_NAME,
RESULTS_PER_PAGE, RESULTS_PER_PAGE,
SEARCH_ERROR_MESSAGE_INFIX, SEARCH_ERROR_MESSAGE_INFIX,
SEARCH_ERROR_MESSAGE_PREFIX, SEARCH_ERROR_MESSAGE_PREFIX,
...@@ -50,7 +46,6 @@ import { ...@@ -50,7 +46,6 @@ import {
export interface StateFromProps { export interface StateFromProps {
searchTerm: string; searchTerm: string;
isLoading: boolean; isLoading: boolean;
popularTables: TableResource[];
tables: TableSearchResults; tables: TableSearchResults;
dashboards: DashboardSearchResults; dashboards: DashboardSearchResults;
users: UserSearchResults; users: UserSearchResults;
...@@ -59,7 +54,6 @@ export interface StateFromProps { ...@@ -59,7 +54,6 @@ export interface StateFromProps {
export interface DispatchFromProps { export interface DispatchFromProps {
searchAll: (term: string, options?: SearchAllOptions) => SearchAllRequest; searchAll: (term: string, options?: SearchAllOptions) => SearchAllRequest;
searchResource: (resource: ResourceType, term: string, pageIndex: number) => SearchResourceRequest; searchResource: (resource: ResourceType, term: string, pageIndex: number) => SearchResourceRequest;
getPopularTables: () => GetPopularTablesRequest;
} }
export type SearchPageProps = StateFromProps & DispatchFromProps & RouteComponentProps<any>; export type SearchPageProps = StateFromProps & DispatchFromProps & RouteComponentProps<any>;
...@@ -80,7 +74,6 @@ export class SearchPage extends React.Component<SearchPageProps, SearchPageState ...@@ -80,7 +74,6 @@ export class SearchPage extends React.Component<SearchPageProps, SearchPageState
} }
componentDidMount() { componentDidMount() {
this.props.getPopularTables();
const params = qs.parse(this.props.location.search); const params = qs.parse(this.props.location.search);
const { searchTerm, pageIndex, selectedTab } = params; const { searchTerm, pageIndex, selectedTab } = params;
const { term, index, currentTab } = this.getSanitizedUrlParams(searchTerm, pageIndex, selectedTab); const { term, index, currentTab } = this.getSanitizedUrlParams(searchTerm, pageIndex, selectedTab);
...@@ -166,20 +159,12 @@ export class SearchPage extends React.Component<SearchPageProps, SearchPageState ...@@ -166,20 +159,12 @@ export class SearchPage extends React.Component<SearchPageProps, SearchPageState
}; };
renderPopularTables = () => { renderPopularTables = () => {
const searchListParams = {
source: POPULAR_TABLES_SOURCE_NAME,
paginationStartIndex: 0,
};
return ( return (
<div className="search-list-container"> <div className="search-list-container">
<BookmarkList /> <BookmarkList />
<div className="popular-tables-header"> <PopularTables />
<label className="title-1">{POPULAR_TABLES_LABEL}</label> </div>
<InfoButton infoText={POPULAR_TABLES_INFO_TEXT}/> )
</div>
<SearchList results={ this.props.popularTables } params={ searchListParams }/>
</div>
)
}; };
renderSearchResults = () => { renderSearchResults = () => {
...@@ -294,7 +279,6 @@ export const mapStateToProps = (state: GlobalState) => { ...@@ -294,7 +279,6 @@ export const mapStateToProps = (state: GlobalState) => {
return { return {
searchTerm: state.search.search_term, searchTerm: state.search.search_term,
isLoading: state.search.isLoading, isLoading: state.search.isLoading,
popularTables: state.popularTables,
tables: state.search.tables, tables: state.search.tables,
users: state.search.users, users: state.search.users,
dashboards: state.search.dashboards, dashboards: state.search.dashboards,
...@@ -302,7 +286,7 @@ export const mapStateToProps = (state: GlobalState) => { ...@@ -302,7 +286,7 @@ export const mapStateToProps = (state: GlobalState) => {
}; };
export const mapDispatchToProps = (dispatch: any) => { export const mapDispatchToProps = (dispatch: any) => {
return bindActionCreators({ searchAll, searchResource, getPopularTables } , dispatch); return bindActionCreators({ searchAll, searchResource } , dispatch);
}; };
export default connect<StateFromProps, DispatchFromProps>(mapStateToProps, mapDispatchToProps)(SearchPage); export default connect<StateFromProps, DispatchFromProps>(mapStateToProps, mapDispatchToProps)(SearchPage);
...@@ -14,14 +14,6 @@ ...@@ -14,14 +14,6 @@
} }
} }
.popular-tables-header {
display: flex;
flex-direction: row;
margin-bottom: 32px;
}
.tab-content { .tab-content {
.search-list-header { .search-list-header {
display: flex; display: flex;
......
...@@ -10,9 +10,6 @@ import { ...@@ -10,9 +10,6 @@ import {
DOCUMENT_TITLE_SUFFIX, DOCUMENT_TITLE_SUFFIX,
PAGINATION_PAGE_RANGE, PAGINATION_PAGE_RANGE,
PAGE_INDEX_ERROR_MESSAGE, PAGE_INDEX_ERROR_MESSAGE,
POPULAR_TABLES_INFO_TEXT,
POPULAR_TABLES_LABEL,
POPULAR_TABLES_SOURCE_NAME,
RESULTS_PER_PAGE, RESULTS_PER_PAGE,
SEARCH_ERROR_MESSAGE_INFIX, SEARCH_ERROR_MESSAGE_INFIX,
SEARCH_ERROR_MESSAGE_PREFIX, SEARCH_ERROR_MESSAGE_PREFIX,
...@@ -30,6 +27,8 @@ import SearchList from '../SearchList'; ...@@ -30,6 +27,8 @@ import SearchList from '../SearchList';
import globalState from 'fixtures/globalState'; import globalState from 'fixtures/globalState';
import LoadingSpinner from 'components/common/LoadingSpinner'; import LoadingSpinner from 'components/common/LoadingSpinner';
import BookmarkList from 'components/common/Bookmark/BookmarkList';
import PopularTables from 'components/common/PopularTables';
describe('SearchPage', () => { describe('SearchPage', () => {
const setStateSpy = jest.spyOn(SearchPage.prototype, 'setState'); const setStateSpy = jest.spyOn(SearchPage.prototype, 'setState');
...@@ -37,13 +36,11 @@ describe('SearchPage', () => { ...@@ -37,13 +36,11 @@ describe('SearchPage', () => {
const props: SearchPageProps = { const props: SearchPageProps = {
searchTerm: globalState.search.search_term, searchTerm: globalState.search.search_term,
isLoading: false, isLoading: false,
popularTables: globalState.popularTables,
dashboards: globalState.search.dashboards, dashboards: globalState.search.dashboards,
tables: globalState.search.tables, tables: globalState.search.tables,
users: globalState.search.users, users: globalState.search.users,
searchAll: jest.fn(), searchAll: jest.fn(),
searchResource: jest.fn(), searchResource: jest.fn(),
getPopularTables: jest.fn(),
history: { history: {
length: 2, length: 2,
action: "POP", action: "POP",
...@@ -116,10 +113,6 @@ describe('SearchPage', () => { ...@@ -116,10 +113,6 @@ describe('SearchPage', () => {
wrapper.instance().componentDidMount(); wrapper.instance().componentDidMount();
}); });
it('calls props.getPopularTables', () => {
expect(props.getPopularTables).toHaveBeenCalled();
});
it('calls setState', () => { it('calls setState', () => {
expect(setStateSpy).toHaveBeenCalledWith({ selectedTab: mockSanitizedUrlParams.currentTab }); expect(setStateSpy).toHaveBeenCalledWith({ selectedTab: mockSanitizedUrlParams.currentTab });
}); });
...@@ -642,33 +635,11 @@ describe('SearchPage', () => { ...@@ -642,33 +635,11 @@ describe('SearchPage', () => {
}); });
describe('renderPopularTables', () => { describe('renderPopularTables', () => {
let content; it('renders bookmark list and popular tables', () => {
let props; const {props, wrapper} = setup();
let wrapper; wrapper.instance().renderPopularTables();
beforeAll(() => { expect(wrapper.contains(<BookmarkList />));
const setupResult = setup({ searchTerm: '' }); expect(wrapper.contains(<PopularTables />));
props = setupResult.props;
wrapper = setupResult.wrapper;
content = shallow(wrapper.instance().renderPopularTables());
});
it('renders correct label for content', () => {
expect(content.children().at(1).find('label').text()).toEqual(POPULAR_TABLES_LABEL);
});
it('renders InfoButton with correct props', () => {
expect(content.children().at(1).find(InfoButton).props()).toMatchObject({
infoText: POPULAR_TABLES_INFO_TEXT,
});
});
it('renders SearchList with correct props', () => {
expect(content.children().find(SearchList).props()).toMatchObject({
results: props.popularTables,
params: {
source: POPULAR_TABLES_SOURCE_NAME,
paginationStartIndex: 0,
},
});
}); });
}); });
...@@ -746,10 +717,6 @@ describe('mapDispatchToProps', () => { ...@@ -746,10 +717,6 @@ describe('mapDispatchToProps', () => {
it('sets searchResource on the props', () => { it('sets searchResource on the props', () => {
expect(result.searchResource).toBeInstanceOf(Function); expect(result.searchResource).toBeInstanceOf(Function);
}); });
it('sets getPopularTables on the props', () => {
expect(result.getPopularTables).toBeInstanceOf(Function);
});
}); });
describe('mapStateToProps', () => { describe('mapStateToProps', () => {
...@@ -766,10 +733,6 @@ describe('mapStateToProps', () => { ...@@ -766,10 +733,6 @@ describe('mapStateToProps', () => {
expect(result.isLoading).toEqual(globalState.search.isLoading); expect(result.isLoading).toEqual(globalState.search.isLoading);
}); });
it('sets popularTables on the props', () => {
expect(result.popularTables).toEqual(globalState.popularTables);
});
it('sets tables on the props', () => { it('sets tables on the props', () => {
expect(result.tables).toEqual(globalState.search.tables); expect(result.tables).toEqual(globalState.search.tables);
}); });
......
// TODO: Hard-coded text strings should be translatable/customizable
export const POPULAR_TABLES_INFO_TEXT = 'These are some of the most commonly accessed tables within your organization.';
export const POPULAR_TABLES_LABEL = 'Popular Tables';
export const POPULAR_TABLES_SOURCE_NAME = 'popular_tables';
import * as React from 'react';
// TODO: Use css-modules instead of 'import'
import './styles.scss';
import { POPULAR_TABLES_LABEL, POPULAR_TABLES_INFO_TEXT, POPULAR_TABLES_SOURCE_NAME } from './constants';
import InfoButton from 'components/common/InfoButton';
import SearchList from 'components/SearchPage/SearchList';
import { getPopularTables } from 'ducks/popularTables/reducer';
import { GetPopularTablesRequest, TableResource } from 'ducks/popularTables/types';
import { GlobalState } from 'ducks/rootReducer';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
export interface StateFromProps {
popularTables: TableResource[];
}
export interface DispatchFromProps {
getPopularTables: () => GetPopularTablesRequest;
}
export type PopularTablesProps = StateFromProps & DispatchFromProps;
export class PopularTables extends React.Component<PopularTablesProps> {
constructor(props) {
super(props);
}
componentDidMount() {
this.props.getPopularTables();
}
render() {
return (
<>
<div className="popular-tables-header">
<label className="title-1">{POPULAR_TABLES_LABEL}</label>
<InfoButton infoText={POPULAR_TABLES_INFO_TEXT} />
</div>
<SearchList
results={this.props.popularTables}
params={{
source: POPULAR_TABLES_SOURCE_NAME,
paginationStartIndex: 0,
}}
/>
</>
);
}
}
export const mapStateToProps = (state: GlobalState) => {
return {
popularTables: state.popularTables,
};
};
export const mapDispatchToProps = (dispatch: any) => {
return bindActionCreators({ getPopularTables }, dispatch);
};
export default connect<StateFromProps, DispatchFromProps>(mapStateToProps, mapDispatchToProps)(PopularTables);
@import 'variables';
.popular-tables-header {
display: flex;
flex-direction: row;
margin-bottom: 32px;
}
import * as React from 'react';
import { shallow } from 'enzyme';
import {
POPULAR_TABLES_INFO_TEXT,
POPULAR_TABLES_LABEL,
POPULAR_TABLES_SOURCE_NAME,
} from '../constants';
import InfoButton from 'components/common/InfoButton';
import SearchList from 'components/SearchPage/SearchList';
import globalState from 'fixtures/globalState';
import { PopularTables, PopularTablesProps, mapStateToProps, mapDispatchToProps } from '..';
describe('PopularTables', () => {
const setup = (propOverrides?: Partial<PopularTablesProps>) => {
const props: PopularTablesProps = {
popularTables: jest.fn() as any,
getPopularTables: jest.fn(),
...propOverrides
};
const wrapper = shallow<PopularTables>(<PopularTables {...props} />)
return { props, wrapper };
};
let wrapper;
let props;
describe('componentDidMount', () => {
let getPopularTablesSpy;
beforeAll(() => {
const setupResult = setup();
wrapper = setupResult.wrapper;
props = setupResult.props;
getPopularTablesSpy = jest.spyOn(props, 'getPopularTables');
});
it('calls getPopularTables', () => {
expect(getPopularTablesSpy).toHaveBeenCalled();
});
});
describe('mapStateToProps', () => {
let result;
beforeAll(() => {
result = mapStateToProps(globalState);
});
it('sets popularTables on the props', () => {
expect(result.popularTables).toEqual(globalState.popularTables);
});
});
describe('mapDispatchToProps', () => {
let result;
beforeAll(() => {
const dispatch = jest.fn(() => Promise.resolve());
result = mapDispatchToProps(dispatch);
});
it('sets getPopularTables on the props', () => {
expect(result.getPopularTables).toBeInstanceOf(Function);
});
});
describe('render', () => {
beforeAll(() => {
const setupResult = setup();
wrapper = setupResult.wrapper;
props = setupResult.props;
});
it('renders correct label for content', () => {
expect(wrapper.children().find('label').text()).toEqual(POPULAR_TABLES_LABEL);
});
it('renders InfoButton with correct props', () => {
expect(wrapper.children().find(InfoButton).props()).toMatchObject({
infoText: POPULAR_TABLES_INFO_TEXT,
});
});
it('renders SearchList with correct props', () => {
expect(wrapper.children().find(SearchList).props()).toMatchObject({
results: props.popularTables,
params: {
source: POPULAR_TABLES_SOURCE_NAME,
paginationStartIndex: 0,
},
});
});
});
});
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment