aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/components
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2018-08-08 18:46:50 +0200
committerSonarTech <sonartech@sonarsource.com>2018-08-21 20:21:02 +0200
commit15f3d9c2584cca304590ad68dea4d025ac356813 (patch)
tree8c04843ea598da97f54f26c118a3a046db78edad /server/sonar-web/src/main/js/components
parentd0fd02dac9cc7ef5db1343073f4a1b6dfca79bea (diff)
downloadsonarqube-15f3d9c2584cca304590ad68dea4d025ac356813.tar.gz
sonarqube-15f3d9c2584cca304590ad68dea4d025ac356813.zip
SONAR-6400 allow to show more items in a facet (#597)
Diffstat (limited to 'server/sonar-web/src/main/js/components')
-rw-r--r--server/sonar-web/src/main/js/components/facet/FacetItem.tsx2
-rw-r--r--server/sonar-web/src/main/js/components/facet/ListStyleFacet.tsx112
-rw-r--r--server/sonar-web/src/main/js/components/facet/ListStyleFacetFooter.tsx71
-rw-r--r--server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacet-test.tsx44
-rw-r--r--server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacetFooter-test.tsx56
-rw-r--r--server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetItem-test.tsx.snap1
-rw-r--r--server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/ListStyleFacet-test.tsx.snap179
-rw-r--r--server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/ListStyleFacetFooter-test.tsx.snap47
8 files changed, 409 insertions, 103 deletions
diff --git a/server/sonar-web/src/main/js/components/facet/FacetItem.tsx b/server/sonar-web/src/main/js/components/facet/FacetItem.tsx
index 0f86901fffb..70beec9c901 100644
--- a/server/sonar-web/src/main/js/components/facet/FacetItem.tsx
+++ b/server/sonar-web/src/main/js/components/facet/FacetItem.tsx
@@ -55,7 +55,7 @@ export default class FacetItem extends React.PureComponent<Props> {
});
return this.props.disabled ? (
- <span className={className} data-facet={this.props.value}>
+ <span className={className} data-facet={this.props.value} title={this.props.tooltip}>
<span className="facet-name">{name}</span>
{this.props.stat != null && <span className="facet-stat">{this.props.stat}</span>}
</span>
diff --git a/server/sonar-web/src/main/js/components/facet/ListStyleFacet.tsx b/server/sonar-web/src/main/js/components/facet/ListStyleFacet.tsx
index ae2222ea4cb..4b0bc9c93ac 100644
--- a/server/sonar-web/src/main/js/components/facet/ListStyleFacet.tsx
+++ b/server/sonar-web/src/main/js/components/facet/ListStyleFacet.tsx
@@ -23,6 +23,7 @@ import FacetBox from './FacetBox';
import FacetHeader from './FacetHeader';
import FacetItem from './FacetItem';
import FacetItemsList from './FacetItemsList';
+import ListStyleFacetFooter from './ListStyleFacetFooter';
import MultipleSelectionHint from './MultipleSelectionHint';
import { translate } from '../../helpers/l10n';
import DeferredSpinner from '../common/DeferredSpinner';
@@ -38,6 +39,8 @@ export interface Props<S> {
getSearchResultKey: (result: S) => string;
getSearchResultText: (result: S) => string;
loading?: boolean;
+ maxInitialItems?: number;
+ maxItems?: number;
onChange: (changes: { [x: string]: string | string[] }) => void;
onSearch: (query: string, page?: number) => Promise<{ results: S[]; paging: Paging }>;
onToggle: (property: string) => void;
@@ -46,25 +49,32 @@ export interface Props<S> {
renderFacetItem: (item: string) => React.ReactNode;
renderSearchResult: (result: S, query: string) => React.ReactNode;
searchPlaceholder: string;
- values: string[];
stats: { [x: string]: number } | undefined;
+ values: string[];
}
interface State<S> {
autoFocus: boolean;
query: string;
searching: boolean;
- searchResults?: S[];
searchPaging?: Paging;
+ searchResults?: S[];
+ showFullList: boolean;
}
export default class ListStyleFacet<S> extends React.Component<Props<S>, State<S>> {
mounted = false;
+ static defaultProps = {
+ maxInitialItems: 15,
+ maxItems: 100
+ };
+
state: State<S> = {
autoFocus: false,
query: '',
- searching: false
+ searching: false,
+ showFullList: false
};
componentDidMount() {
@@ -72,9 +82,18 @@ export default class ListStyleFacet<S> extends React.Component<Props<S>, State<S
}
componentDidUpdate(prevProps: Props<S>) {
- // focus search field *only* if it was manually open
if (!prevProps.open && this.props.open) {
+ // focus search field *only* if it was manually open
this.setState({ autoFocus: true });
+ } else if (prevProps.open && !this.props.open) {
+ // reset state when closing the facet
+ this.setState({ query: '', searchResults: undefined, searching: false, showFullList: false });
+ } else if (
+ prevProps.stats !== this.props.stats &&
+ Object.keys(this.props.stats || {}).length < this.props.maxInitialItems!
+ ) {
+ // show limited list if `stats` changed and there are less than 15 items
+ this.setState({ showFullList: false });
}
}
@@ -139,11 +158,29 @@ export default class ListStyleFacet<S> extends React.Component<Props<S>, State<S
}
};
- getStat(item: string) {
+ getStat(item: string, zeroIfAbsent = false) {
const { stats } = this.props;
- return stats ? stats[item] : undefined;
+ const defaultValue = zeroIfAbsent ? 0 : undefined;
+ return stats && stats[item] !== undefined ? stats && stats[item] : defaultValue;
}
+ showFullList = () => {
+ this.setState({ showFullList: true });
+ };
+
+ hideFullList = () => {
+ this.setState({ showFullList: false });
+ };
+
+ getLastActiveIndex = (list: string[]) => {
+ for (let i = list.length - 1; i >= 0; i--) {
+ if (this.props.values.includes(list[i])) {
+ return i;
+ }
+ }
+ return 0;
+ };
+
renderList() {
const { stats } = this.props;
@@ -151,27 +188,51 @@ export default class ListStyleFacet<S> extends React.Component<Props<S>, State<S
return null;
}
- const items = sortBy(
+ const sortedItems = sortBy(
Object.keys(stats),
key => -stats[key],
key => this.props.getFacetItemText(key)
);
+ // limit the number of items to this.props.maxInitialItems,
+ // but make sure all (in other words, the last) selected items are displayed
+ const lastSelectedIndex = this.getLastActiveIndex(sortedItems);
+ const countToDisplay = Math.max(this.props.maxInitialItems!, lastSelectedIndex + 1);
+ const limitedList = this.state.showFullList
+ ? sortedItems
+ : sortedItems.slice(0, countToDisplay);
+
+ const mightHaveMoreResults = sortedItems.length >= this.props.maxItems!;
+
return (
- <FacetItemsList>
- {items.map(item => (
- <FacetItem
- active={this.props.values.includes(item)}
- key={item}
- loading={this.props.loading}
- name={this.props.renderFacetItem(item)}
- onClick={this.handleItemClick}
- stat={formatFacetStat(this.getStat(item))}
- tooltip={this.props.getFacetItemText(item)}
- value={item}
- />
- ))}
- </FacetItemsList>
+ <>
+ <FacetItemsList>
+ {limitedList.map(item => (
+ <FacetItem
+ active={this.props.values.includes(item)}
+ key={item}
+ loading={this.props.loading}
+ name={this.props.renderFacetItem(item)}
+ onClick={this.handleItemClick}
+ stat={formatFacetStat(this.getStat(item))}
+ tooltip={this.props.getFacetItemText(item)}
+ value={item}
+ />
+ ))}
+ </FacetItemsList>
+ <ListStyleFacetFooter
+ count={limitedList.length}
+ showLess={this.state.showFullList ? this.hideFullList : undefined}
+ showMore={this.showFullList}
+ total={sortedItems.length}
+ />
+ {mightHaveMoreResults &&
+ this.state.showFullList && (
+ <div className="alert alert-warning spacer-top">
+ {translate('facet_might_have_more_results')}
+ </div>
+ )}
+ </>
);
}
@@ -211,6 +272,7 @@ export default class ListStyleFacet<S> extends React.Component<Props<S>, State<S
{searchResults.map(result => this.renderSearchResult(result))}
</FacetItemsList>
<ListFooter
+ className="spacer-bottom"
count={searchResults.length}
loadMore={this.searchMore}
ready={!searching}
@@ -223,7 +285,11 @@ export default class ListStyleFacet<S> extends React.Component<Props<S>, State<S
renderSearchResult(result: S) {
const key = this.props.getSearchResultKey(result);
const active = this.props.values.includes(key);
- const stat = this.getStat(key);
+
+ // default to 0 if we're sure there are not more results
+ const isFacetExhaustive = Object.keys(this.props.stats || {}).length < this.props.maxItems!;
+ const stat = this.getStat(key, isFacetExhaustive);
+
return (
<FacetItem
active={active}
@@ -232,7 +298,7 @@ export default class ListStyleFacet<S> extends React.Component<Props<S>, State<S
loading={this.props.loading}
name={this.props.renderSearchResult(result, this.state.query)}
onClick={this.handleItemClick}
- stat={stat && formatFacetStat(stat)}
+ stat={formatFacetStat(stat)}
tooltip={this.props.getSearchResultText(result)}
value={key}
/>
diff --git a/server/sonar-web/src/main/js/components/facet/ListStyleFacetFooter.tsx b/server/sonar-web/src/main/js/components/facet/ListStyleFacetFooter.tsx
new file mode 100644
index 00000000000..b4fe7eb4d83
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/facet/ListStyleFacetFooter.tsx
@@ -0,0 +1,71 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { translate, translateWithParameters } from '../../helpers/l10n';
+import { formatMeasure } from '../../helpers/measures';
+
+interface Props {
+ className?: string;
+ count: number;
+ showMore: () => void;
+ showLess: (() => void) | undefined;
+ total: number;
+}
+
+export default class ListStyleFacetFooter extends React.PureComponent<Props> {
+ handleShowMoreClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
+ event.preventDefault();
+ event.currentTarget.blur();
+ this.props.showMore();
+ };
+
+ handleShowLessClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
+ event.preventDefault();
+ event.currentTarget.blur();
+ if (this.props.showLess) {
+ this.props.showLess();
+ }
+ };
+
+ render() {
+ const { count, total } = this.props;
+ const hasMore = total > count;
+ const allShown = Boolean(total && total === count);
+
+ return (
+ <footer className="note spacer-top spacer-bottom text-center">
+ {translateWithParameters('x_show', formatMeasure(count, 'INT', null))}
+
+ {hasMore && (
+ <a className="spacer-left text-muted" href="#" onClick={this.handleShowMoreClick}>
+ {translate('show_more')}
+ </a>
+ )}
+
+ {this.props.showLess &&
+ allShown && (
+ <a className="spacer-left text-muted" href="#" onClick={this.handleShowLessClick}>
+ {translate('show_less')}
+ </a>
+ )}
+ </footer>
+ );
+ }
+}
diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacet-test.tsx b/server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacet-test.tsx
index 7cb3f16a0a0..c9c4180d1ea 100644
--- a/server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacet-test.tsx
+++ b/server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacet-test.tsx
@@ -116,6 +116,50 @@ it('should search', async () => {
expect(onSearch).lastCalledWith('blabla');
});
+it('should limit the number of items', () => {
+ const wrapper = shallowRender({ maxInitialItems: 2, maxItems: 5 });
+ expect(wrapper.find('FacetItem').length).toBe(2);
+
+ wrapper.find('ListStyleFacetFooter').prop<Function>('showMore')();
+ wrapper.update();
+ expect(wrapper.find('FacetItem').length).toBe(3);
+
+ wrapper.find('ListStyleFacetFooter').prop<Function>('showLess')();
+ wrapper.update();
+ expect(wrapper.find('FacetItem').length).toBe(2);
+});
+
+it('should show warning that there might be more results', () => {
+ const wrapper = shallowRender({ maxInitialItems: 2, maxItems: 3 });
+ wrapper.find('ListStyleFacetFooter').prop<Function>('showMore')();
+ wrapper.update();
+ expect(wrapper.find('.alert-warning').exists()).toBe(true);
+});
+
+it('should reset state when closes', () => {
+ const wrapper = shallowRender();
+ wrapper.setState({
+ query: 'foobar',
+ searchResults: ['foo', 'bar'],
+ searching: true,
+ showFullList: true
+ });
+
+ wrapper.setProps({ open: false });
+ expect(wrapper.state('query')).toBe('');
+ expect(wrapper.state('searchResults')).toBe(undefined);
+ expect(wrapper.state('searching')).toBe(false);
+ expect(wrapper.state('showFullList')).toBe(false);
+});
+
+it('should collapse list when new stats have few results', () => {
+ const wrapper = shallowRender({ maxInitialItems: 2, maxItems: 3 });
+ wrapper.setState({ showFullList: true });
+
+ wrapper.setProps({ stats: { d: 1 } });
+ expect(wrapper.state('showFullList')).toBe(false);
+});
+
function shallowRender(props: Partial<Props<string>> = {}) {
return shallow(
<ListStyleFacet
diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacetFooter-test.tsx b/server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacetFooter-test.tsx
new file mode 100644
index 00000000000..5c9ec734b43
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/facet/__tests__/ListStyleFacetFooter-test.tsx
@@ -0,0 +1,56 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import ListStyleFacetFooter from '../ListStyleFacetFooter';
+import { click } from '../../../helpers/testUtils';
+
+it('should not render "show more"', () => {
+ expect(
+ shallow(<ListStyleFacetFooter count={3} showLess={undefined} showMore={jest.fn()} total={3} />)
+ ).toMatchSnapshot();
+});
+
+it('should show more', () => {
+ const showMore = jest.fn();
+ const wrapper = shallow(
+ <ListStyleFacetFooter count={3} showLess={undefined} showMore={showMore} total={15} />
+ );
+ expect(wrapper).toMatchSnapshot();
+ click(wrapper.find('a'));
+ expect(showMore).toBeCalled();
+});
+
+it('should show less', () => {
+ const showLess = jest.fn();
+ const wrapper = shallow(
+ <ListStyleFacetFooter count={15} showLess={showLess} showMore={jest.fn()} total={15} />
+ );
+ expect(wrapper).toMatchSnapshot();
+ click(wrapper.find('a'));
+ expect(showLess).toBeCalled();
+});
+
+it('should not render "show less"', () => {
+ const wrapper = shallow(
+ <ListStyleFacetFooter count={15} showLess={undefined} showMore={jest.fn()} total={15} />
+ );
+ expect(wrapper).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetItem-test.tsx.snap b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetItem-test.tsx.snap
index 725eb2a401f..eaa0c2cf53c 100644
--- a/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetItem-test.tsx.snap
+++ b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetItem-test.tsx.snap
@@ -36,6 +36,7 @@ exports[`should render disabled 1`] = `
<span
className="search-navigator-facet"
data-facet="bar"
+ title="foo"
>
<span
className="facet-name"
diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/ListStyleFacet-test.tsx.snap b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/ListStyleFacet-test.tsx.snap
index 7b05d4a28f0..82fab9ce2f4 100644
--- a/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/ListStyleFacet-test.tsx.snap
+++ b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/ListStyleFacet-test.tsx.snap
@@ -25,44 +25,51 @@ exports[`should render 1`] = `
placeholder="search for foo..."
value=""
/>
- <FacetItemsList>
- <FacetItem
- active={false}
- disabled={false}
- halfWidth={false}
- key="a"
- loading={false}
- name="a"
- onClick={[Function]}
- stat="10"
- tooltip="a"
- value="a"
- />
- <FacetItem
- active={false}
- disabled={false}
- halfWidth={false}
- key="b"
- loading={false}
- name="b"
- onClick={[Function]}
- stat="8"
- tooltip="b"
- value="b"
- />
- <FacetItem
- active={false}
- disabled={false}
- halfWidth={false}
- key="c"
- loading={false}
- name="c"
- onClick={[Function]}
- stat="1"
- tooltip="c"
- value="c"
+ <React.Fragment>
+ <FacetItemsList>
+ <FacetItem
+ active={false}
+ disabled={false}
+ halfWidth={false}
+ key="a"
+ loading={false}
+ name="a"
+ onClick={[Function]}
+ stat="10"
+ tooltip="a"
+ value="a"
+ />
+ <FacetItem
+ active={false}
+ disabled={false}
+ halfWidth={false}
+ key="b"
+ loading={false}
+ name="b"
+ onClick={[Function]}
+ stat="8"
+ tooltip="b"
+ value="b"
+ />
+ <FacetItem
+ active={false}
+ disabled={false}
+ halfWidth={false}
+ key="c"
+ loading={false}
+ name="c"
+ onClick={[Function]}
+ stat="1"
+ tooltip="c"
+ value="c"
+ />
+ </FacetItemsList>
+ <ListStyleFacetFooter
+ count={3}
+ showMore={[Function]}
+ total={3}
/>
- </FacetItemsList>
+ </React.Fragment>
<MultipleSelectionHint
options={3}
values={0}
@@ -100,28 +107,31 @@ exports[`should search 1`] = `
<FacetItemsList>
<FacetItem
active={false}
- disabled={false}
+ disabled={true}
halfWidth={false}
key="d"
loading={false}
name="d"
onClick={[Function]}
+ stat={0}
tooltip="d"
value="d"
/>
<FacetItem
active={false}
- disabled={false}
+ disabled={true}
halfWidth={false}
key="e"
loading={false}
name="e"
onClick={[Function]}
+ stat={0}
tooltip="e"
value="e"
/>
</FacetItemsList>
<ListFooter
+ className="spacer-bottom"
count={2}
loadMore={[Function]}
ready={true}
@@ -165,39 +175,43 @@ exports[`should search 2`] = `
<FacetItemsList>
<FacetItem
active={false}
- disabled={false}
+ disabled={true}
halfWidth={false}
key="d"
loading={false}
name="d"
onClick={[Function]}
+ stat={0}
tooltip="d"
value="d"
/>
<FacetItem
active={false}
- disabled={false}
+ disabled={true}
halfWidth={false}
key="e"
loading={false}
name="e"
onClick={[Function]}
+ stat={0}
tooltip="e"
value="e"
/>
<FacetItem
active={false}
- disabled={false}
+ disabled={true}
halfWidth={false}
key="f"
loading={false}
name="f"
onClick={[Function]}
+ stat={0}
tooltip="f"
value="f"
/>
</FacetItemsList>
<ListFooter
+ className="spacer-bottom"
count={3}
loadMore={[Function]}
ready={true}
@@ -237,44 +251,51 @@ exports[`should search 3`] = `
placeholder="search for foo..."
value=""
/>
- <FacetItemsList>
- <FacetItem
- active={false}
- disabled={false}
- halfWidth={false}
- key="a"
- loading={false}
- name="a"
- onClick={[Function]}
- stat="10"
- tooltip="a"
- value="a"
- />
- <FacetItem
- active={false}
- disabled={false}
- halfWidth={false}
- key="b"
- loading={false}
- name="b"
- onClick={[Function]}
- stat="8"
- tooltip="b"
- value="b"
- />
- <FacetItem
- active={false}
- disabled={false}
- halfWidth={false}
- key="c"
- loading={false}
- name="c"
- onClick={[Function]}
- stat="1"
- tooltip="c"
- value="c"
+ <React.Fragment>
+ <FacetItemsList>
+ <FacetItem
+ active={false}
+ disabled={false}
+ halfWidth={false}
+ key="a"
+ loading={false}
+ name="a"
+ onClick={[Function]}
+ stat="10"
+ tooltip="a"
+ value="a"
+ />
+ <FacetItem
+ active={false}
+ disabled={false}
+ halfWidth={false}
+ key="b"
+ loading={false}
+ name="b"
+ onClick={[Function]}
+ stat="8"
+ tooltip="b"
+ value="b"
+ />
+ <FacetItem
+ active={false}
+ disabled={false}
+ halfWidth={false}
+ key="c"
+ loading={false}
+ name="c"
+ onClick={[Function]}
+ stat="1"
+ tooltip="c"
+ value="c"
+ />
+ </FacetItemsList>
+ <ListStyleFacetFooter
+ count={3}
+ showMore={[Function]}
+ total={3}
/>
- </FacetItemsList>
+ </React.Fragment>
<MultipleSelectionHint
options={3}
values={0}
diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/ListStyleFacetFooter-test.tsx.snap b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/ListStyleFacetFooter-test.tsx.snap
new file mode 100644
index 00000000000..85a2744871c
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/ListStyleFacetFooter-test.tsx.snap
@@ -0,0 +1,47 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should not render "show less" 1`] = `
+<footer
+ className="note spacer-top spacer-bottom text-center"
+>
+ x_show.15
+</footer>
+`;
+
+exports[`should not render "show more" 1`] = `
+<footer
+ className="note spacer-top spacer-bottom text-center"
+>
+ x_show.3
+</footer>
+`;
+
+exports[`should show less 1`] = `
+<footer
+ className="note spacer-top spacer-bottom text-center"
+>
+ x_show.15
+ <a
+ className="spacer-left text-muted"
+ href="#"
+ onClick={[Function]}
+ >
+ show_less
+ </a>
+</footer>
+`;
+
+exports[`should show more 1`] = `
+<footer
+ className="note spacer-top spacer-bottom text-center"
+>
+ x_show.3
+ <a
+ className="spacer-left text-muted"
+ href="#"
+ onClick={[Function]}
+ >
+ show_more
+ </a>
+</footer>
+`;