import Action from './Action';
import DeprecatedBadge from './DeprecatedBadge';
import InternalBadge from './InternalBadge';
-import { getActionKey } from '../utils';
+import { getActionKey, actionsFilter } from '../utils';
import type { Domain as DomainType } from '../../../api/web-api';
type Props = {
render() {
const { domain, showInternal, showDeprecated, searchQuery } = this.props;
- const filteredActions = domain.actions
- .filter(action => showInternal || !action.internal)
- .filter(action => showDeprecated || !action.deprecatedSince)
- .filter(action => getActionKey(domain.path, action.key).indexOf(searchQuery) !== -1);
+ const filteredActions = domain.actions.filter(action =>
+ actionsFilter(showDeprecated, showInternal, searchQuery, domain, action)
+ );
return (
<div className="web-api-domain">
import DeprecatedBadge from './DeprecatedBadge';
import InternalBadge from './InternalBadge';
import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin';
-import { getActionKey, isDomainPathActive } from '../utils';
+import { isDomainPathActive, actionsFilter } from '../utils';
import type { Domain as DomainType } from '../../../api/web-api';
type Props = {
const { domains, showInternal, showDeprecated, searchQuery, splat } = this.props;
const filteredDomains = (domains || [])
.map(domain => {
- const filteredActions = domain.actions
- .filter(action => showInternal || !action.internal)
- .filter(action => showDeprecated || !action.deprecatedSince)
- .filter(action => getActionKey(domain.path, action.key).indexOf(searchQuery) !== -1);
+ const filteredActions = domain.actions.filter(action =>
+ actionsFilter(showDeprecated, showInternal, searchQuery, domain, action)
+ );
return { ...domain, filteredActions };
})
.filter(domain => domain.filteredActions.length);
constructor(props: Props) {
super(props);
this.state = { query: '' };
- this.actuallySearch = debounce(this.actuallySearch.bind(this), 250);
+ this.actuallySearch = debounce(this.actuallySearch, 250);
}
- handleSearch(e: SyntheticInputEvent) {
+ handleSearch = (e: SyntheticInputEvent) => {
const { value } = e.target;
this.setState({ query: value });
this.actuallySearch();
- }
+ };
- actuallySearch() {
+ actuallySearch = () => {
const { onSearch } = this.props;
onSearch(this.state.query);
- }
+ };
render() {
const { showInternal, showDeprecated, onToggleInternal, onToggleDeprecated } = this.props;
type="search"
value={this.state.query}
placeholder={translate('search_verb')}
- onChange={this.handleSearch.bind(this)}
+ onChange={this.handleSearch}
/>
</div>
<TooltipsContainer>
<div className="big-spacer-top">
- <Checkbox checked={showInternal} onCheck={onToggleInternal} />
- {' '}
+ <Checkbox
+ checked={showInternal}
+ className="little-spacer-right"
+ onCheck={onToggleInternal}
+ />
<span
style={{ cursor: 'pointer' }}
title={translate('api_documentation.internal_tooltip')}
<TooltipsContainer>
<div className="spacer-top">
- <Checkbox checked={showDeprecated} onCheck={onToggleDeprecated} />
- {' '}
+ <Checkbox
+ checked={showDeprecated}
+ className="little-spacer-right"
+ onCheck={onToggleDeprecated}
+ />
<span
style={{ cursor: 'pointer' }}
title={translate('api_documentation.deprecation_tooltip')}
componentDidMount() {
this.mounted = true;
- this.scrollToAction = this.scrollToAction.bind(this);
this.fetchList();
const footer = document.getElementById('footer');
if (footer) {
});
}
- scrollToAction() {
+ scrollToAction = () => {
const splat = this.props.params.splat || '';
this.scrollToElement(splat);
- }
+ };
scrollToElement(id: string) {
const element = document.getElementById(id);
}
}
- handleSearch(searchQuery: string) {
+ handleSearch = (searchQuery: string) => {
this.setState({ searchQuery });
- }
+ };
- handleToggleInternal() {
+ handleToggleInternal = () => {
const splat = this.props.params.splat || '';
const { router } = this.context;
const { domains } = this.state;
}
this.setState({ showInternal });
- }
+ };
- handleToggleDeprecated() {
+ handleToggleDeprecated = () => {
this.setState(state => ({ showDeprecated: !state.showDeprecated }));
- }
+ };
render() {
const splat = this.props.params.splat || '';
<Search
showDeprecated={showDeprecated}
showInternal={showInternal}
- onSearch={this.handleSearch.bind(this)}
- onToggleInternal={this.handleToggleInternal.bind(this)}
- onToggleDeprecated={this.handleToggleDeprecated.bind(this)}
+ onSearch={this.handleSearch}
+ onToggleInternal={this.handleToggleInternal}
+ onToggleDeprecated={this.handleToggleDeprecated}
/>
<Menu
import Domain from '../Domain';
it('should render deprecated actions', () => {
- const actions = [
- {
- key: 'foo',
- deprecatedSince: '5.0'
- }
- ];
+ const actions = [{ key: 'foo', deprecatedSince: '5.0' }];
const domain = { actions, path: 'api' };
expect(
shallow(<Domain domain={domain} searchQuery="" showDeprecated={true} />)
});
it('should not render deprecated actions', () => {
- const actions = [
- {
- key: 'foo',
- deprecatedSince: '5.0'
- }
- ];
+ const actions = [{ key: 'foo', deprecatedSince: '5.0' }];
const domain = { actions, path: 'api' };
expect(
shallow(<Domain domain={domain} searchQuery="" showDeprecated={false} />)
).toMatchSnapshot();
});
+
+it('should render internal actions', () => {
+ const actions = [{ key: 'foo', internal: true }];
+ const domain = { actions, path: 'api' };
+ expect(shallow(<Domain domain={domain} searchQuery="" showInternal={true} />)).toMatchSnapshot();
+});
+
+it('should not render internal actions', () => {
+ const actions = [{ key: 'foo', internal: true }];
+ const domain = { actions, path: 'api' };
+ expect(shallow(<Domain domain={domain} searchQuery="" showInternal={false} />)).toMatchSnapshot();
+});
+
+it('should render only actions matching the query', () => {
+ const actions = [{ key: 'foo' }, { key: 'bar' }];
+ const domain = { actions, path: 'api' };
+ expect(shallow(<Domain domain={domain} searchQuery="Foo" />)).toMatchSnapshot();
+});
+
+it('should also render actions with a description matching the query', () => {
+ const actions = [{ key: 'foo', description: 'foobar' }, { key: 'bar' }, { key: 'baz' }];
+ const domain = { actions, path: 'api' };
+ expect(
+ shallow(<Domain domain={domain} searchQuery="bar" showDeprecated={false} />)
+ ).toMatchSnapshot();
+});
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`should also render actions with a description matching the query 1`] = `
+<div
+ className="web-api-domain"
+>
+ <header
+ className="web-api-domain-header"
+ >
+ <h2
+ className="web-api-domain-title"
+ >
+ api
+ </h2>
+ </header>
+ <div
+ className="web-api-domain-actions"
+ >
+ <Action
+ action={
+ Object {
+ "description": "foobar",
+ "key": "foo",
+ }
+ }
+ domain={
+ Object {
+ "actions": Array [
+ Object {
+ "description": "foobar",
+ "key": "foo",
+ },
+ Object {
+ "key": "bar",
+ },
+ Object {
+ "key": "baz",
+ },
+ ],
+ "path": "api",
+ }
+ }
+ showDeprecated={false}
+ />
+ <Action
+ action={
+ Object {
+ "key": "bar",
+ }
+ }
+ domain={
+ Object {
+ "actions": Array [
+ Object {
+ "description": "foobar",
+ "key": "foo",
+ },
+ Object {
+ "key": "bar",
+ },
+ Object {
+ "key": "baz",
+ },
+ ],
+ "path": "api",
+ }
+ }
+ showDeprecated={false}
+ />
+ </div>
+</div>
+`;
+
exports[`should not render deprecated actions 1`] = `
<div
className="web-api-domain"
</div>
`;
+exports[`should not render internal actions 1`] = `
+<div
+ className="web-api-domain"
+>
+ <header
+ className="web-api-domain-header"
+ >
+ <h2
+ className="web-api-domain-title"
+ >
+ api
+ </h2>
+ </header>
+ <div
+ className="web-api-domain-actions"
+ />
+</div>
+`;
+
exports[`should render deprecated actions 1`] = `
<div
className="web-api-domain"
</div>
</div>
`;
+
+exports[`should render internal actions 1`] = `
+<div
+ className="web-api-domain"
+>
+ <header
+ className="web-api-domain-header"
+ >
+ <h2
+ className="web-api-domain-title"
+ >
+ api
+ </h2>
+ </header>
+ <div
+ className="web-api-domain-actions"
+ >
+ <Action
+ action={
+ Object {
+ "internal": true,
+ "key": "foo",
+ }
+ }
+ domain={
+ Object {
+ "actions": Array [
+ Object {
+ "internal": true,
+ "key": "foo",
+ },
+ ],
+ "path": "api",
+ }
+ }
+ showInternal={true}
+ />
+ </div>
+</div>
+`;
+
+exports[`should render only actions matching the query 1`] = `
+<div
+ className="web-api-domain"
+>
+ <header
+ className="web-api-domain-header"
+ >
+ <h2
+ className="web-api-domain-title"
+ >
+ api
+ </h2>
+ </header>
+ <div
+ className="web-api-domain-actions"
+ >
+ <Action
+ action={
+ Object {
+ "key": "foo",
+ }
+ }
+ domain={
+ Object {
+ "actions": Array [
+ Object {
+ "key": "foo",
+ },
+ Object {
+ "key": "bar",
+ },
+ ],
+ "path": "api",
+ }
+ }
+ />
+ </div>
+</div>
+`;
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-export function getActionKey(domain, action) {
- return domain + '/' + action;
+//@flow
+import type { Domain, Action } from '../../api/web-api';
+
+export function actionsFilter(
+ showDeprecated: boolean,
+ showInternal: boolean,
+ searchQuery: string,
+ domain: Domain,
+ action: Action
+) {
+ const lowSearchQuery = searchQuery.toLowerCase();
+ return (
+ (showInternal || !action.internal) &&
+ (showDeprecated || !action.deprecatedSince) &&
+ (getActionKey(domain.path, action.key).includes(lowSearchQuery) ||
+ (action.description || '').toLowerCase().includes(lowSearchQuery))
+ );
+}
+
+export function getActionKey(domainPath: string, actionKey: string) {
+ return domainPath + '/' + actionKey;
}
-export const isDomainPathActive = (path, splat) => {
+export const isDomainPathActive = (path: string, splat: string) => {
const pathTokens = path.split('/');
const splatTokens = splat.split('/');