diff options
author | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-08-24 15:08:35 +0200 |
---|---|---|
committer | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-08-25 16:01:06 +0200 |
commit | 6103fc329f77399dab5fffc8c9688d6285cf67d3 (patch) | |
tree | 2dd1c06ce22406178344337be4fa109a6f137758 /server/sonar-web/src/main/js/apps/web-api/components | |
parent | 4f49fdb5b4596540bd15e4a3cebe533911e0e6db (diff) | |
download | sonarqube-6103fc329f77399dab5fffc8c9688d6285cf67d3.tar.gz sonarqube-6103fc329f77399dab5fffc8c9688d6285cf67d3.zip |
SONAR-9521 Add sparator between ws descriptions (hum and rewrite to ts)
Diffstat (limited to 'server/sonar-web/src/main/js/apps/web-api/components')
30 files changed, 1882 insertions, 927 deletions
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Action.js b/server/sonar-web/src/main/js/apps/web-api/components/Action.js deleted file mode 100644 index 6e84e8a8a5b..00000000000 --- a/server/sonar-web/src/main/js/apps/web-api/components/Action.js +++ /dev/null @@ -1,178 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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. - */ -// @flow -import React from 'react'; -import { Link } from 'react-router'; -import classNames from 'classnames'; -import { getActionKey } from '../utils'; -import Params from './Params'; -import ResponseExample from './ResponseExample'; -import ActionChangelog from './ActionChangelog'; -import DeprecatedBadge from './DeprecatedBadge'; -import InternalBadge from './InternalBadge'; -import LinkIcon from '../../../components/icons-components/LinkIcon'; -import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; -/*:: import type { Action as ActionType, Domain as DomainType } from '../../../api/web-api'; */ - -/*:: -type Props = { - action: ActionType, - domain: DomainType, - showDeprecated: boolean, - showInternal: boolean -}; -*/ - -/*:: -type State = { - showChangelog: boolean, - showParams: boolean, - showResponse: boolean -}; -*/ - -export default class Action extends React.PureComponent { - /*:: props: Props; */ - - state /*: State */ = { - showChangelog: false, - showParams: false, - showResponse: false - }; - - handleShowParamsClick = (e /*: SyntheticInputEvent */) => { - e.preventDefault(); - this.setState({ - showChangelog: false, - showResponse: false, - showParams: !this.state.showParams - }); - }; - - handleShowResponseClick = (e /*: SyntheticInputEvent */) => { - e.preventDefault(); - this.setState({ - showChangelog: false, - showParams: false, - showResponse: !this.state.showResponse - }); - }; - - handleChangelogClick = (e /*: SyntheticInputEvent */) => { - e.preventDefault(); - this.setState({ - showChangelog: !this.state.showChangelog, - showParams: false, - showResponse: false - }); - }; - - render() { - const { action, domain } = this.props; - const { showChangelog, showParams, showResponse } = this.state; - const verb = action.post ? 'POST' : 'GET'; - const actionKey = getActionKey(domain.path, action.key); - - return ( - <div id={actionKey} className="web-api-action"> - <TooltipsContainer> - <header className="web-api-action-header"> - <Link - to={{ pathname: '/web_api/' + actionKey }} - className="spacer-right link-no-underline"> - <LinkIcon /> - </Link> - - <h3 className="web-api-action-title"> - {verb} {actionKey} - </h3> - - {action.internal && - <span className="spacer-left"> - <InternalBadge /> - </span>} - - {action.since && - <span className="spacer-left badge"> - since {action.since} - </span>} - - {action.deprecatedSince && - <span className="spacer-left"> - <DeprecatedBadge since={action.deprecatedSince} /> - </span>} - </header> - </TooltipsContainer> - - <div - className="web-api-action-description markdown" - dangerouslySetInnerHTML={{ __html: action.description }} - /> - - {(action.params || action.hasResponseExample) && - <ul className="web-api-action-actions tabs"> - {action.params && - <li> - <a - className={classNames({ selected: showParams })} - href="#" - onClick={this.handleShowParamsClick}> - Parameters - </a> - </li>} - - {action.hasResponseExample && - <li> - <a - className={classNames({ selected: showResponse })} - href="#" - onClick={this.handleShowResponseClick}> - Response Example - </a> - </li>} - - {action.changelog.length > 0 && - <li> - <a - className={classNames({ selected: showChangelog })} - href="#" - onClick={this.handleChangelogClick}> - Changelog - </a> - </li>} - </ul>} - - {showParams && - action.params && - <Params - params={action.params} - showDeprecated={this.props.showDeprecated} - showInternal={this.props.showInternal} - />} - - {showResponse && - action.hasResponseExample && - <ResponseExample domain={domain} action={action} />} - - {showChangelog && <ActionChangelog changelog={action.changelog} />} - </div> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Action.tsx b/server/sonar-web/src/main/js/apps/web-api/components/Action.tsx new file mode 100644 index 00000000000..92cea769d0a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/Action.tsx @@ -0,0 +1,181 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 { Link } from 'react-router'; +import * as classNames from 'classnames'; +import { getActionKey } from '../utils'; +import Params from './Params'; +import ResponseExample from './ResponseExample'; +import ActionChangelog from './ActionChangelog'; +import DeprecatedBadge from './DeprecatedBadge'; +import InternalBadge from './InternalBadge'; +import LinkIcon from '../../../components/icons-components/LinkIcon'; +import { Action as ActionType, Domain as DomainType } from '../../../api/web-api'; +import { translate, translateWithParameters } from '../../../helpers/l10n'; + +interface Props { + action: ActionType; + domain: DomainType; + showDeprecated: boolean; + showInternal: boolean; +} + +interface State { + showChangelog: boolean; + showParams: boolean; + showResponse: boolean; +} + +export default class Action extends React.PureComponent<Props, State> { + state: State = { + showChangelog: false, + showParams: false, + showResponse: false + }; + + handleShowParamsClick = (e: React.SyntheticEvent<HTMLElement>) => { + e.preventDefault(); + this.setState({ + showChangelog: false, + showResponse: false, + showParams: !this.state.showParams + }); + }; + + handleShowResponseClick = (e: React.SyntheticEvent<HTMLElement>) => { + e.preventDefault(); + this.setState({ + showChangelog: false, + showParams: false, + showResponse: !this.state.showResponse + }); + }; + + handleChangelogClick = (e: React.SyntheticEvent<HTMLElement>) => { + e.preventDefault(); + this.setState({ + showChangelog: !this.state.showChangelog, + showParams: false, + showResponse: false + }); + }; + + renderTabs() { + const { action } = this.props; + const { showChangelog, showParams, showResponse } = this.state; + + if (action.params || action.hasResponseExample || action.changelog.length > 0) { + return ( + <ul className="web-api-action-actions tabs"> + {action.params && + <li> + <a + className={classNames({ selected: showParams })} + href="#" + onClick={this.handleShowParamsClick}> + {translate('api_documentation.parameters')} + </a> + </li>} + + {action.hasResponseExample && + <li> + <a + className={classNames({ selected: showResponse })} + href="#" + onClick={this.handleShowResponseClick}> + {translate('api_documentation.response_example')} + </a> + </li>} + + {action.changelog.length > 0 && + <li> + <a + className={classNames({ selected: showChangelog })} + href="#" + onClick={this.handleChangelogClick}> + {translate('api_documentation.changelog')} + </a> + </li>} + </ul> + ); + } + + return <hr />; + } + + render() { + const { action, domain } = this.props; + const { showChangelog, showParams, showResponse } = this.state; + const verb = action.post ? 'POST' : 'GET'; + const actionKey = getActionKey(domain.path, action.key); + + return ( + <div id={actionKey} className="web-api-action"> + <header className="web-api-action-header"> + <Link + to={{ pathname: '/web_api/' + actionKey }} + className="spacer-right link-no-underline"> + <LinkIcon /> + </Link> + + <h3 className="web-api-action-title"> + {verb} {actionKey} + </h3> + + {action.internal && + <span className="spacer-left"> + <InternalBadge /> + </span>} + + {action.since && + <span className="spacer-left badge"> + {translateWithParameters('since_x', action.since)} + </span>} + + {action.deprecatedSince && + <span className="spacer-left"> + <DeprecatedBadge since={action.deprecatedSince} /> + </span>} + </header> + + <div + className="web-api-action-description markdown" + dangerouslySetInnerHTML={{ __html: action.description }} + /> + + {this.renderTabs()} + + {showParams && + action.params && + <Params + params={action.params} + showDeprecated={this.props.showDeprecated} + showInternal={this.props.showInternal} + />} + + {showResponse && + action.hasResponseExample && + <ResponseExample domain={domain} action={action} />} + + {showChangelog && <ActionChangelog changelog={action.changelog} />} + </div> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.js b/server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.tsx index ff5b42b5213..7e33e9719ae 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.tsx @@ -17,33 +17,24 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// @flow -import React from 'react'; +import * as React from 'react'; +import { Changelog } from '../../../api/web-api'; -/*:: -type Props = { - changelog: Array<{ - description: string, - version: string - }> -}; -*/ - -export default class ActionChangelog extends React.PureComponent { - /*:: props: Props; */ +interface Props { + changelog: Changelog[]; +} - render() { - return ( - <ul className="big-spacer-top"> - {this.props.changelog.map((item, index) => - <li key={index} className="spacer-top"> - <span className="spacer-right badge"> - {item.version} - </span> - {item.description} - </li> - )} - </ul> - ); - } +export default function ActionChangelog({ changelog }: Props) { + return ( + <ul className="big-spacer-top"> + {changelog.map((item, index) => + <li key={index} className="spacer-top"> + <span className="spacer-right badge"> + {item.version} + </span> + {item.description} + </li> + )} + </ul> + ); } diff --git a/server/sonar-web/src/main/js/apps/web-api/components/DeprecatedBadge.tsx b/server/sonar-web/src/main/js/apps/web-api/components/DeprecatedBadge.tsx new file mode 100644 index 00000000000..504d0553823 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/DeprecatedBadge.tsx @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 Tooltip from '../../../components/controls/Tooltip'; +import { translate, translateWithParameters } from '../../../helpers/l10n'; + +export default function DeprecatedBadge({ since }: { since?: string }) { + const label = since + ? translateWithParameters('api_documentation.depracated_since_x', since) + : translate('api_documentation.depracated'); + return ( + <Tooltip overlay={translate('api_documentation.deprecation_tooltip')}> + <span className="badge badge-warning"> + {label} + </span> + </Tooltip> + ); +} diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Domain.js b/server/sonar-web/src/main/js/apps/web-api/components/Domain.js deleted file mode 100644 index e7240504008..00000000000 --- a/server/sonar-web/src/main/js/apps/web-api/components/Domain.js +++ /dev/null @@ -1,84 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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. - */ -// @flow -import React from 'react'; -import Action from './Action'; -import DeprecatedBadge from './DeprecatedBadge'; -import InternalBadge from './InternalBadge'; -import { getActionKey, actionsFilter } from '../utils'; -/*:: import type { Domain as DomainType } from '../../../api/web-api'; */ - -/*:: -type Props = { - domain: DomainType, - showDeprecated: boolean, - showInternal: boolean, - searchQuery: string -}; -*/ - -export default class Domain extends React.PureComponent { - /*:: props: Props; */ - - render() { - const { domain, showInternal, showDeprecated, searchQuery } = this.props; - const filteredActions = domain.actions.filter(action => - actionsFilter(showDeprecated, showInternal, searchQuery, domain, action) - ); - - return ( - <div className="web-api-domain"> - <header className="web-api-domain-header"> - <h2 className="web-api-domain-title"> - {domain.path} - </h2> - - {domain.deprecated && - <span className="spacer-left"> - <DeprecatedBadge /> - </span>} - - {domain.internal && - <span className="spacer-left"> - <InternalBadge /> - </span>} - </header> - - {domain.description && - <div - className="web-api-domain-description markdown" - dangerouslySetInnerHTML={{ __html: domain.description }} - />} - - <div className="web-api-domain-actions"> - {filteredActions.map(action => - <Action - key={getActionKey(domain.path, action.key)} - action={action} - domain={domain} - showDeprecated={showDeprecated} - showInternal={showInternal} - /> - )} - </div> - </div> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Domain.tsx b/server/sonar-web/src/main/js/apps/web-api/components/Domain.tsx new file mode 100644 index 00000000000..8e70e2ed767 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/Domain.tsx @@ -0,0 +1,76 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 Action from './Action'; +import DeprecatedBadge from './DeprecatedBadge'; +import InternalBadge from './InternalBadge'; +import { getActionKey, actionsFilter } from '../utils'; +import { Domain as DomainType } from '../../../api/web-api'; + +interface Props { + domain: DomainType; + showDeprecated: boolean; + showInternal: boolean; + searchQuery: string; +} + +export default function Domain({ domain, showInternal, showDeprecated, searchQuery }: Props) { + const filteredActions = domain.actions.filter(action => + actionsFilter(showDeprecated, showInternal, searchQuery, domain, action) + ); + + return ( + <div className="web-api-domain"> + <header className="web-api-domain-header"> + <h2 className="web-api-domain-title"> + {domain.path} + </h2> + + {domain.deprecated && + <span className="spacer-left"> + <DeprecatedBadge /> + </span>} + + {domain.internal && + <span className="spacer-left"> + <InternalBadge /> + </span>} + </header> + + {domain.description && + <div + className="web-api-domain-description markdown" + dangerouslySetInnerHTML={{ __html: domain.description }} + />} + + <div className="web-api-domain-actions"> + {filteredActions.map(action => + <Action + key={getActionKey(domain.path, action.key)} + action={action} + domain={domain} + showDeprecated={showDeprecated} + showInternal={showInternal} + /> + )} + </div> + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/web-api/components/InternalBadge.js b/server/sonar-web/src/main/js/apps/web-api/components/InternalBadge.tsx index 210d30b9a2c..4b7ed15fede 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/InternalBadge.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/InternalBadge.tsx @@ -17,16 +17,16 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; +import Tooltip from '../../../components/controls/Tooltip'; import { translate } from '../../../helpers/l10n'; export default function InternalBadge() { return ( - <span - className="badge badge-danger" - title={translate('api_documentation.internal_tooltip')} - data-toggle="tooltip"> - internal - </span> + <Tooltip overlay={translate('api_documentation.internal_tooltip')}> + <span className="badge badge-danger"> + {translate('internal')} + </span> + </Tooltip> ); } diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Menu.js b/server/sonar-web/src/main/js/apps/web-api/components/Menu.js deleted file mode 100644 index 521817badff..00000000000 --- a/server/sonar-web/src/main/js/apps/web-api/components/Menu.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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. - */ -// @flow -import React from 'react'; -import { Link } from 'react-router'; -import classNames from 'classnames'; -import DeprecatedBadge from './DeprecatedBadge'; -import InternalBadge from './InternalBadge'; -import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; -import { isDomainPathActive, actionsFilter } from '../utils'; -/*:: import type { Domain as DomainType } from '../../../api/web-api'; */ - -/*:: -type Props = { - domains: Array<DomainType>, - showDeprecated: boolean, - showInternal: boolean, - searchQuery: string, - splat: string -}; -*/ - -export default class Menu extends React.PureComponent { - /*:: props: Props; */ - - render() { - const { domains, showInternal, showDeprecated, searchQuery, splat } = this.props; - const filteredDomains = (domains || []) - .map(domain => { - const filteredActions = domain.actions.filter(action => - actionsFilter(showDeprecated, showInternal, searchQuery, domain, action) - ); - return { ...domain, filteredActions }; - }) - .filter(domain => domain.filteredActions.length); - - return ( - <div className="api-documentation-results panel"> - <TooltipsContainer> - <div className="list-group"> - {filteredDomains.map(domain => - <Link - key={domain.path} - className={classNames('list-group-item', { - active: isDomainPathActive(domain.path, splat) - })} - to={'/web_api/' + domain.path}> - <h3 className="list-group-item-heading"> - {domain.path} - {domain.deprecated && <DeprecatedBadge />} - {domain.internal && <InternalBadge />} - </h3> - {domain.description && - <div - className="list-group-item-text markdown" - dangerouslySetInnerHTML={{ __html: domain.description }} - />} - </Link> - )} - </div> - </TooltipsContainer> - </div> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Menu.tsx b/server/sonar-web/src/main/js/apps/web-api/components/Menu.tsx new file mode 100644 index 00000000000..d33ddade68b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/Menu.tsx @@ -0,0 +1,72 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 { Link } from 'react-router'; +import * as classNames from 'classnames'; +import DeprecatedBadge from './DeprecatedBadge'; +import InternalBadge from './InternalBadge'; +import { isDomainPathActive, actionsFilter } from '../utils'; +import { Domain } from '../../../api/web-api'; + +interface Props { + domains: Domain[]; + showDeprecated: boolean; + showInternal: boolean; + searchQuery: string; + splat: string; +} + +export default function Menu(props: Props) { + const { domains, showInternal, showDeprecated, searchQuery, splat } = props; + const filteredDomains = (domains || []) + .map(domain => { + const filteredActions = domain.actions.filter(action => + actionsFilter(showDeprecated, showInternal, searchQuery, domain, action) + ); + return { ...domain, filteredActions }; + }) + .filter(domain => domain.filteredActions.length); + + return ( + <div className="api-documentation-results panel"> + <div className="list-group"> + {filteredDomains.map(domain => + <Link + key={domain.path} + className={classNames('list-group-item', { + active: isDomainPathActive(domain.path, splat) + })} + to={'/web_api/' + domain.path}> + <h3 className="list-group-item-heading"> + {domain.path} + {domain.deprecated && <DeprecatedBadge />} + {domain.internal && <InternalBadge />} + </h3> + {domain.description && + <div + className="list-group-item-text markdown" + dangerouslySetInnerHTML={{ __html: domain.description }} + />} + </Link> + )} + </div> + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Params.js b/server/sonar-web/src/main/js/apps/web-api/components/Params.js deleted file mode 100644 index f2e7751c3c0..00000000000 --- a/server/sonar-web/src/main/js/apps/web-api/components/Params.js +++ /dev/null @@ -1,138 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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. - */ -// @flow -import React from 'react'; -import InternalBadge from './InternalBadge'; -import DeprecatedBadge from './DeprecatedBadge'; -/*:: import type { Param } from '../../../api/web-api'; */ - -export default class Params extends React.PureComponent { - /*:: props: { - showDeprecated: boolean, - showInternal: boolean, - params: Array<Param> - }; -*/ - - render() { - const { showDeprecated, showInternal, params } = this.props; - const displayedParameters = params - .filter(p => showDeprecated || !p.deprecatedSince) - .filter(p => showInternal || !p.internal); - return ( - <div className="web-api-params"> - <table> - <tbody> - {displayedParameters.map(param => - <tr key={param.key}> - <td className="markdown" style={{ width: 180 }}> - <code> - {param.key} - </code> - - {param.internal && - <div className="little-spacer-top"> - <InternalBadge /> - </div>} - - {param.deprecatedSince && - <div className="little-spacer-top"> - <DeprecatedBadge since={param.deprecatedSince} /> - </div>} - - {showDeprecated && - param.deprecatedKey && - <div className="little-spacer-top"> - <code> - {param.deprecatedKey} - </code> - </div>} - - {showDeprecated && - param.deprecatedKey && - param.deprecatedKeySince && - <div className="little-spacer-top"> - <DeprecatedBadge since={param.deprecatedKeySince} /> - </div>} - - <div className="note little-spacer-top"> - {param.required ? 'required' : 'optional'} - </div> - - {param.since && - <div className="note little-spacer-top"> - since {param.since} - </div>} - </td> - - <td> - <div - className="markdown" - dangerouslySetInnerHTML={{ __html: param.description }} - /> - </td> - - <td style={{ width: 250 }}> - {param.possibleValues && - <div> - <h4>Possible values</h4> - <ul className="list-styled"> - {param.possibleValues.map(value => - <li key={value} className="little-spacer-top"> - <code> - {value} - </code> - </li> - )} - </ul> - </div>} - - {param.defaultValue && - <div className="little-spacer-top"> - <h4>Default value</h4> - <code> - {param.defaultValue} - </code> - </div>} - - {param.exampleValue && - <div className="little-spacer-top"> - <h4>Example value</h4> - <code> - {param.exampleValue} - </code> - </div>} - - {param.maxValuesAllowed != null && - <div className="little-spacer-top"> - <h4>Maximum allowed values</h4> - <code> - {param.maxValuesAllowed} - </code> - </div>} - </td> - </tr> - )} - </tbody> - </table> - </div> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Params.tsx b/server/sonar-web/src/main/js/apps/web-api/components/Params.tsx new file mode 100644 index 00000000000..e0691804e7d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/Params.tsx @@ -0,0 +1,139 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 InternalBadge from './InternalBadge'; +import DeprecatedBadge from './DeprecatedBadge'; +import { Param } from '../../../api/web-api'; +import { translate, translateWithParameters } from '../../../helpers/l10n'; + +interface Props { + params: Param[]; + showDeprecated: boolean; + showInternal: boolean; +} + +export default function Params({ params, showDeprecated, showInternal }: Props) { + const displayedParameters = params + .filter(p => showDeprecated || !p.deprecatedSince) + .filter(p => showInternal || !p.internal); + return ( + <div className="web-api-params"> + <table> + <tbody> + {displayedParameters.map(param => + <tr key={param.key}> + <td className="markdown" style={{ width: 180 }}> + <code> + {param.key} + </code> + + {param.internal && + <div className="little-spacer-top"> + <InternalBadge /> + </div>} + + {param.deprecatedSince && + <div className="little-spacer-top"> + <DeprecatedBadge since={param.deprecatedSince} /> + </div>} + + {showDeprecated && + param.deprecatedKey && + <div className="little-spacer-top"> + <code> + {param.deprecatedKey} + </code> + </div>} + + {showDeprecated && + param.deprecatedKey && + param.deprecatedKeySince && + <div className="little-spacer-top"> + <DeprecatedBadge since={param.deprecatedKeySince} /> + </div>} + + <div className="note little-spacer-top"> + {param.required ? 'required' : 'optional'} + </div> + + {param.since && + <div className="note little-spacer-top"> + {translateWithParameters('since_x', param.since)} + </div>} + </td> + + <td> + <div className="markdown" dangerouslySetInnerHTML={{ __html: param.description }} /> + </td> + + <td style={{ width: 250 }}> + {param.possibleValues && + <div> + <h4> + {translate('api_documentation.possible_values')} + </h4> + <ul className="list-styled"> + {param.possibleValues.map(value => + <li key={value} className="little-spacer-top"> + <code> + {value} + </code> + </li> + )} + </ul> + </div>} + + {param.defaultValue && + <div className="little-spacer-top"> + <h4> + {translate('api_documentation.default_values')} + </h4> + <code> + {param.defaultValue} + </code> + </div>} + + {param.exampleValue && + <div className="little-spacer-top"> + <h4> + {translate('api_documentation.example_values')} + </h4> + <code> + {param.exampleValue} + </code> + </div>} + + {param.maxValuesAllowed != null && + <div className="little-spacer-top"> + <h4> + {translate('api_documentation.max_values')} + </h4> + <code> + {param.maxValuesAllowed} + </code> + </div>} + </td> + </tr> + )} + </tbody> + </table> + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.js b/server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.tsx index 88bf4973bec..746fb398e11 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.tsx @@ -17,18 +17,33 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; -import { fetchResponseExample as fetchResponseExampleApi } from '../../../api/web-api'; +import * as React from 'react'; +import { + Action, + Domain, + Example, + fetchResponseExample as fetchResponseExampleApi +} from '../../../api/web-api'; -export default class ResponseExample extends React.PureComponent { - state = {}; +interface Props { + action: Action; + domain: Domain; +} + +interface State { + responseExample?: Example; +} + +export default class ResponseExample extends React.PureComponent<Props, State> { + mounted: boolean; + state: State = {}; componentDidMount() { this.mounted = true; this.fetchResponseExample(); } - componentDidUpdate(nextProps) { + componentDidUpdate(nextProps: Props) { if (nextProps.action !== this.props.action) { this.fetchResponseExample(); } diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Search.js b/server/sonar-web/src/main/js/apps/web-api/components/Search.tsx index c08bbb8bb2e..ab64ad6167e 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/Search.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/Search.tsx @@ -17,51 +17,38 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// @flow -import React from 'react'; +import * as React from 'react'; import { debounce } from 'lodash'; import Checkbox from '../../../components/controls/Checkbox'; import HelpIcon from '../../../components/icons-components/HelpIcon'; import Tooltip from '../../../components/controls/Tooltip'; import { translate } from '../../../helpers/l10n'; -/*:: -type Props = { - showDeprecated: boolean, - showInternal: boolean, - onSearch: string => void, - onToggleInternal: () => void, - onToggleDeprecated: () => void -}; -*/ - -/*:: -type State = { - query: string -}; -*/ +interface Props { + showDeprecated: boolean; + showInternal: boolean; + onSearch: (search: string) => void; + onToggleInternal: () => void; + onToggleDeprecated: () => void; +} -export default class Search extends React.PureComponent { - /*:: actuallySearch: () => void; */ - /*:: props: Props; */ - /*:: state: State; */ +interface State { + query: string; +} - constructor(props /*: Props */) { +export default class Search extends React.PureComponent<Props, State> { + constructor(props: Props) { super(props); this.state = { query: '' }; this.actuallySearch = debounce(this.actuallySearch, 250); } - handleSearch = (e /*: SyntheticInputEvent */) => { - const { value } = e.target; - this.setState({ query: value }); + handleSearch = (e: React.SyntheticEvent<HTMLInputElement>) => { + this.setState({ query: e.currentTarget.value }); this.actuallySearch(); }; - actuallySearch = () => { - const { onSearch } = this.props; - onSearch(this.state.query); - }; + actuallySearch = () => this.props.onSearch(this.state.query); render() { const { showInternal, showDeprecated, onToggleInternal, onToggleDeprecated } = this.props; @@ -82,7 +69,7 @@ export default class Search extends React.PureComponent { <div className="big-spacer-top"> <Checkbox checked={showInternal} onCheck={onToggleInternal}> <span className="little-spacer-left"> - {translate('api_documentation.show_deprecated')} + {translate('api_documentation.show_internal')} </span> </Checkbox> <Tooltip overlay={translate('api_documentation.internal_tooltip')} placement="right"> @@ -95,7 +82,7 @@ export default class Search extends React.PureComponent { <div className="spacer-top"> <Checkbox checked={showDeprecated} onCheck={onToggleDeprecated}> <span className="little-spacer-left"> - {translate('api_documentation.show_internal')} + {translate('api_documentation.show_deprecated')} </span> </Checkbox> <Tooltip overlay={translate('api_documentation.deprecation_tooltip')} placement="right"> diff --git a/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.js b/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.tsx index a8e8eadb27e..9a346b3f921 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.tsx @@ -17,39 +17,43 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// @flow -import React from 'react'; -import PropTypes from 'prop-types'; +import * as React from 'react'; +import * as PropTypes from 'prop-types'; import Helmet from 'react-helmet'; import { Link } from 'react-router'; -import { fetchWebApi } from '../../../api/web-api'; +import { Domain as DomainType, fetchWebApi } from '../../../api/web-api'; import Menu from './Menu'; import Search from './Search'; import Domain from './Domain'; import { getActionKey, isDomainPathActive } from '../utils'; +import { scrollToElement } from '../../../helpers/scrolling'; import { translate } from '../../../helpers/l10n'; -/*:: import type { Domain as DomainType } from '../../../api/web-api'; */ import '../styles/web-api.css'; -/*:: -type State = { - domains: Array<DomainType>, - searchQuery: string, - showDeprecated: boolean, - showInternal: boolean -}; -*/ - -export default class WebApiApp extends React.PureComponent { - /*:: mounted: boolean; */ - /*:: scrollToAction: () => void; */ - state /*: State */ = { +interface Props { + params: { splat?: string }; +} + +interface State { + domains: DomainType[]; + searchQuery: string; + showDeprecated: boolean; + showInternal: boolean; +} + +export default class WebApiApp extends React.PureComponent<Props, State> { + mounted: boolean; + state: State = { domains: [], searchQuery: '', showDeprecated: false, showInternal: false }; + static contextTypes = { + router: PropTypes.object.isRequired + }; + componentDidMount() { this.mounted = true; this.fetchList(); @@ -72,7 +76,7 @@ export default class WebApiApp extends React.PureComponent { } } - fetchList(cb /*: void | () => void */) { + fetchList(cb?: () => void) { fetchWebApi().then(domains => { if (this.mounted) { this.setState({ domains }, cb); @@ -82,21 +86,13 @@ export default class WebApiApp extends React.PureComponent { scrollToAction = () => { const splat = this.props.params.splat || ''; - this.scrollToElement(splat); - }; - - scrollToElement(id /*: string */) { - const element = document.getElementById(id); - - if (element) { - const rect = element.getBoundingClientRect(); - const top = rect.top + window.pageYOffset - 20; - - window.scrollTo(0, top); + const action = document.getElementById(splat); + if (action) { + scrollToElement(action, { topOffset: 20, bottomOffset: 20 }); } else { window.scrollTo(0, 0); } - } + }; toggleInternalInitially() { const splat = this.props.params.splat || ''; @@ -117,9 +113,7 @@ export default class WebApiApp extends React.PureComponent { } } - handleSearch = (searchQuery /*: string */) => { - this.setState({ searchQuery }); - }; + handleSearch = (searchQuery: string) => this.setState({ searchQuery }); handleToggleInternal = () => { const splat = this.props.params.splat || ''; @@ -135,9 +129,8 @@ export default class WebApiApp extends React.PureComponent { this.setState({ showInternal }); }; - handleToggleDeprecated = () => { + handleToggleDeprecated = () => this.setState(state => ({ showDeprecated: !state.showDeprecated })); - }; render() { const splat = this.props.params.splat || ''; @@ -196,7 +189,3 @@ export default class WebApiApp extends React.PureComponent { ); } } - -WebApiApp.contextTypes = { - router: PropTypes.object.isRequired -}; diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Action-test.tsx b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Action-test.tsx new file mode 100644 index 00000000000..98c97e6134b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Action-test.tsx @@ -0,0 +1,75 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 Action from '../Action'; + +const ACTION = { + key: 'foo', + changelog: [{ description: 'Changelog desc', version: '5.0' }], + description: 'Foo Desc', + hasResponseExample: true, + internal: false, + params: [ + { + key: 'param', + description: 'Param desc', + internal: true, + required: true + } + ], + post: false +}; +const DOMAIN = { + actions: [ACTION], + path: 'foo', + description: 'API Foo', + deprecated: false, + internal: false +}; + +const PROPS = { + action: ACTION, + domain: DOMAIN, + showDeprecated: false, + showInternal: false +}; + +it('should render correctly', () => { + expect(shallow(<Action {...PROPS} />)).toMatchSnapshot(); +}); + +it('should display the params', () => { + const wrapper = shallow(<Action {...PROPS} />); + wrapper.setState({ showParams: true }); + expect(wrapper.find('Params')).toMatchSnapshot(); +}); + +it('should display the response example', () => { + const wrapper = shallow(<Action {...PROPS} />); + wrapper.setState({ showResponse: true }); + expect(wrapper.find('ResponseExample')).toMatchSnapshot(); +}); + +it('should display the changelog', () => { + const wrapper = shallow(<Action {...PROPS} />); + wrapper.setState({ showChangelog: true }); + expect(wrapper.find('ActionChangelog')).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ActionChangelog-test.js b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ActionChangelog-test.tsx index 380213bf33a..d05d9ec184f 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ActionChangelog-test.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ActionChangelog-test.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import { shallow } from 'enzyme'; import ActionChangelog from '../ActionChangelog'; diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Domain-test.js b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Domain-test.js deleted file mode 100644 index 5608b8c5987..00000000000 --- a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Domain-test.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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 React from 'react'; -import { shallow } from 'enzyme'; -import Domain from '../Domain'; - -it('should render deprecated actions', () => { - const actions = [{ key: 'foo', deprecatedSince: '5.0' }]; - const domain = { actions, path: 'api' }; - expect( - shallow(<Domain domain={domain} searchQuery="" showDeprecated={true} />) - ).toMatchSnapshot(); -}); - -it('should not render deprecated actions', () => { - 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(); -}); diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Domain-test.tsx b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Domain-test.tsx new file mode 100644 index 00000000000..4114f4944e0 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Domain-test.tsx @@ -0,0 +1,96 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 Domain from '../Domain'; + +const ACTION = { + key: 'foo', + changelog: [], + description: 'Foo Desc', + hasResponseExample: false, + internal: false, + post: false +}; +const DOMAIN = { + actions: [ACTION], + path: 'api', + description: 'API Desc', + deprecated: false, + internal: false +}; +const DEFAULT_PROPS = { + domain: DOMAIN, + showDeprecated: false, + showInternal: false, + searchQuery: '' +}; + +it('should render deprecated actions', () => { + const action = { ...ACTION, deprecatedSince: '5.0' }; + const domain = { ...DOMAIN, actions: [action] }; + expect( + shallow(<Domain {...DEFAULT_PROPS} domain={domain} showDeprecated={true} />) + ).toMatchSnapshot(); +}); + +it('should not render deprecated actions', () => { + const action = { ...ACTION, deprecatedSince: '5.0' }; + const domain = { ...DOMAIN, actions: [action] }; + expect( + shallow(<Domain {...DEFAULT_PROPS} domain={domain} showDeprecated={false} />) + ).toMatchSnapshot(); +}); + +it('should render internal actions', () => { + const action = { ...ACTION, internal: true }; + const domain = { ...DOMAIN, actions: [action] }; + expect( + shallow(<Domain {...DEFAULT_PROPS} domain={domain} showInternal={true} />) + ).toMatchSnapshot(); +}); + +it('should not render internal actions', () => { + const action = { ...ACTION, internal: true }; + const domain = { ...DOMAIN, actions: [action] }; + expect( + shallow(<Domain {...DEFAULT_PROPS} domain={domain} showInternal={false} />) + ).toMatchSnapshot(); +}); + +it('should render only actions matching the query', () => { + const actions = [ACTION, { ...ACTION, key: 'bar', description: 'Bar desc' }]; + const domain = { ...DOMAIN, actions: actions }; + expect( + shallow(<Domain {...DEFAULT_PROPS} domain={domain} searchQuery="Foo" />) + ).toMatchSnapshot(); +}); + +it('should also render actions with a description matching the query', () => { + const actions = [ + ACTION, + { ...ACTION, key: 'bar', description: 'Bar desc' }, + { ...ACTION, key: 'baz', description: 'foobar' } + ]; + const domain = { ...DOMAIN, actions: actions }; + expect( + shallow(<Domain {...DEFAULT_PROPS} domain={domain} searchQuery="Foo" />) + ).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Menu-test.tsx b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Menu-test.tsx new file mode 100644 index 00000000000..198f04ac895 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Menu-test.tsx @@ -0,0 +1,104 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 Menu from '../Menu'; + +const ACTION = { + key: 'foo', + changelog: [], + description: 'Foo Desc', + hasResponseExample: false, + internal: false, + post: false +}; +const DOMAIN1 = { + actions: [ACTION], + path: 'foo', + description: 'API Foo', + deprecated: false, + internal: false +}; +const DOMAIN2 = { + actions: [ACTION], + path: 'bar', + description: 'API Bar', + deprecated: false, + internal: false +}; +const PROPS = { + domains: [DOMAIN1, DOMAIN2], + showDeprecated: false, + showInternal: false, + searchQuery: '', + splat: '' +}; + +it('should render deprecated domains', () => { + const domain = { + ...DOMAIN2, + deprecatedSince: '5.0', + actions: [{ ...ACTION, deprecatedSince: '5.0' }] + }; + const domains = [DOMAIN1, domain]; + expect(shallow(<Menu {...PROPS} domains={domains} showDeprecated={true} />)).toMatchSnapshot(); +}); + +it('should not render deprecated domains', () => { + const domain = { + ...DOMAIN2, + deprecatedSince: '5.0', + actions: [{ ...ACTION, deprecatedSince: '5.0' }] + }; + const domains = [DOMAIN1, domain]; + expect(shallow(<Menu {...PROPS} domains={domains} showDeprecated={false} />)).toMatchSnapshot(); +}); + +it('should render internal domains', () => { + const domain = { ...DOMAIN2, internal: true, actions: [{ ...ACTION, internal: true }] }; + const domains = [DOMAIN1, domain]; + expect(shallow(<Menu {...PROPS} domains={domains} showInternal={true} />)).toMatchSnapshot(); +}); + +it('should not render internal domains', () => { + const domain = { ...DOMAIN2, internal: true, actions: [{ ...ACTION, internal: true }] }; + const domains = [DOMAIN1, domain]; + expect(shallow(<Menu {...PROPS} domains={domains} showInternal={false} />)).toMatchSnapshot(); +}); + +it('should render only domains with an action matching the query', () => { + const domain = { + ...DOMAIN2, + actions: [{ ...ACTION, key: 'bar', path: 'bar', description: 'Bar Desc' }] + }; + const domains = [DOMAIN1, domain]; + expect(shallow(<Menu {...PROPS} domains={domains} searchQuery="Foo" />)).toMatchSnapshot(); +}); + +it('should also render domains with an actions description matching the query', () => { + const domain = { + ...DOMAIN1, + path: 'baz', + description: 'API Baz', + actions: [{ ...ACTION, key: 'baz', path: 'baz', description: 'barbaz' }] + }; + const domains = [DOMAIN1, DOMAIN2, domain]; + expect(shallow(<Menu {...PROPS} domains={domains} searchQuery="Bar" />)).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Params-test.js b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Params-test.tsx index e8ca685eaea..480b56f26f0 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Params-test.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Params-test.tsx @@ -17,37 +17,40 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import { shallow } from 'enzyme'; import Params from '../Params'; -it('should render deprecated parameters', () => { +const DEFAULT_PARAM = { + key: 'foo', + description: 'Foo desc', + internal: false, + required: false +}; + +it('should render deprecated and internal parameters', () => { const params = [ - { - key: 'foo', - deprecatedSince: '5.0' - } + { ...DEFAULT_PARAM, deprecatedSince: '5.0' }, + { ...DEFAULT_PARAM, deprecatedSince: '5.0', internal: true } ]; - expect(shallow(<Params params={params} showDeprecated={true} />)).toMatchSnapshot(); + expect( + shallow(<Params params={params} showDeprecated={true} showInternal={true} />) + ).toMatchSnapshot(); }); it('should not render deprecated parameters', () => { - const params = [ - { - key: 'foo', - deprecatedSince: '5.0' - } - ]; - expect(shallow(<Params params={params} showDeprecated={false} />)).toMatchSnapshot(); + const params = [{ ...DEFAULT_PARAM, deprecatedSince: '5.0' }]; + expect( + shallow(<Params params={params} showDeprecated={false} showInternal={false} />) + ).toMatchSnapshot(); }); it('should render deprecated key', () => { const params = [ - { - key: 'foo', - deprecatedKey: 'foo-deprecated', - deprecatedKeySince: '5.0' - } + { ...DEFAULT_PARAM, deprecatedKey: 'foo-deprecated', deprecatedSince: '5.0' }, + { ...DEFAULT_PARAM, deprecatedSince: '5.0', internal: true } ]; - expect(shallow(<Params params={params} showDeprecated={true} />)).toMatchSnapshot(); + expect( + shallow(<Params params={params} showDeprecated={true} showInternal={false} />) + ).toMatchSnapshot(); }); diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ResponseExample-test.tsx b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ResponseExample-test.tsx new file mode 100644 index 00000000000..5e90e29d23f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ResponseExample-test.tsx @@ -0,0 +1,50 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 ResponseExample from '../ResponseExample'; + +const ACTION = { + key: 'foo', + changelog: [], + description: 'Foo Desc', + hasResponseExample: false, + internal: false, + post: false +}; +const DOMAIN = { + actions: [ACTION], + path: 'foo', + description: 'API Foo', + deprecated: false, + internal: false +}; + +const PROPS = { + action: ACTION, + domain: DOMAIN +}; + +it('should render correctly after fetching an example', () => { + const wrapper = shallow(<ResponseExample {...PROPS} />); + expect(wrapper).toMatchSnapshot(); + wrapper.setState({ responseExample: { format: 'json', example: 'my example' } }); + expect(wrapper).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/web-api/components/DeprecatedBadge.js b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Search-test.tsx index 988daab5efc..a7f6a81210a 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/DeprecatedBadge.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Search-test.tsx @@ -17,18 +17,18 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; -import { translate } from '../../../helpers/l10n'; +import * as React from 'react'; +import { shallow } from 'enzyme'; +import Search from '../Search'; -export default function DeprecatedBadge({ since }) { - const label = since ? `deprecated since ${since}` : 'deprecated'; +const PROPS = { + showDeprecated: false, + showInternal: false, + onSearch: () => {}, + onToggleInternal: () => {}, + onToggleDeprecated: () => {} +}; - return ( - <span - className="badge badge-warning" - title={translate('api_documentation.deprecation_tooltip')} - data-toggle="tooltip"> - {label} - </span> - ); -} +it('should render correctly', () => { + expect(shallow(<Search {...PROPS} />)).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Action-test.tsx.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Action-test.tsx.snap new file mode 100644 index 00000000000..02cc7f1b708 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Action-test.tsx.snap @@ -0,0 +1,160 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should display the changelog 1`] = ` +<ActionChangelog + changelog={ + Array [ + Object { + "description": "Changelog desc", + "version": "5.0", + }, + ] + } +/> +`; + +exports[`should display the params 1`] = ` +<Params + params={ + Array [ + Object { + "description": "Param desc", + "internal": true, + "key": "param", + "required": true, + }, + ] + } + showDeprecated={false} + showInternal={false} +/> +`; + +exports[`should display the response example 1`] = ` +<ResponseExample + action={ + Object { + "changelog": Array [ + Object { + "description": "Changelog desc", + "version": "5.0", + }, + ], + "description": "Foo Desc", + "hasResponseExample": true, + "internal": false, + "key": "foo", + "params": Array [ + Object { + "description": "Param desc", + "internal": true, + "key": "param", + "required": true, + }, + ], + "post": false, + } + } + domain={ + Object { + "actions": Array [ + Object { + "changelog": Array [ + Object { + "description": "Changelog desc", + "version": "5.0", + }, + ], + "description": "Foo Desc", + "hasResponseExample": true, + "internal": false, + "key": "foo", + "params": Array [ + Object { + "description": "Param desc", + "internal": true, + "key": "param", + "required": true, + }, + ], + "post": false, + }, + ], + "deprecated": false, + "description": "API Foo", + "internal": false, + "path": "foo", + } + } +/> +`; + +exports[`should render correctly 1`] = ` +<div + className="web-api-action" + id="foo/foo" +> + <header + className="web-api-action-header" + > + <Link + className="spacer-right link-no-underline" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/web_api/foo/foo", + } + } + > + <LinkIcon /> + </Link> + <h3 + className="web-api-action-title" + > + GET + + foo/foo + </h3> + </header> + <div + className="web-api-action-description markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "Foo Desc", + } + } + /> + <ul + className="web-api-action-actions tabs" + > + <li> + <a + className="" + href="#" + onClick={[Function]} + > + api_documentation.parameters + </a> + </li> + <li> + <a + className="" + href="#" + onClick={[Function]} + > + api_documentation.response_example + </a> + </li> + <li> + <a + className="" + href="#" + onClick={[Function]} + > + api_documentation.changelog + </a> + </li> + </ul> +</div> +`; diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ActionChangelog-test.js.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ActionChangelog-test.tsx.snap index 8c3eb7ace6d..8c3eb7ace6d 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ActionChangelog-test.js.snap +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ActionChangelog-test.tsx.snap diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Domain-test.js.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Domain-test.js.snap deleted file mode 100644 index 8a1c7fd8843..00000000000 --- a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Domain-test.js.snap +++ /dev/null @@ -1,230 +0,0 @@ -// 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" -> - <header - className="web-api-domain-header" - > - <h2 - className="web-api-domain-title" - > - api - </h2> - </header> - <div - className="web-api-domain-actions" - /> -</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" -> - <header - className="web-api-domain-header" - > - <h2 - className="web-api-domain-title" - > - api - </h2> - </header> - <div - className="web-api-domain-actions" - > - <Action - action={ - Object { - "deprecatedSince": "5.0", - "key": "foo", - } - } - domain={ - Object { - "actions": Array [ - Object { - "deprecatedSince": "5.0", - "key": "foo", - }, - ], - "path": "api", - } - } - showDeprecated={true} - /> - </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> -`; diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Domain-test.tsx.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Domain-test.tsx.snap new file mode 100644 index 00000000000..e1c93d26f4a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Domain-test.tsx.snap @@ -0,0 +1,369 @@ +// 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-description markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Desc", + } + } + /> + <div + className="web-api-domain-actions" + > + <Action + action={ + Object { + "changelog": Array [], + "description": "Foo Desc", + "hasResponseExample": false, + "internal": false, + "key": "foo", + "post": false, + } + } + domain={ + Object { + "actions": Array [ + Object { + "changelog": Array [], + "description": "Foo Desc", + "hasResponseExample": false, + "internal": false, + "key": "foo", + "post": false, + }, + Object { + "changelog": Array [], + "description": "Bar desc", + "hasResponseExample": false, + "internal": false, + "key": "bar", + "post": false, + }, + Object { + "changelog": Array [], + "description": "foobar", + "hasResponseExample": false, + "internal": false, + "key": "baz", + "post": false, + }, + ], + "deprecated": false, + "description": "API Desc", + "internal": false, + "path": "api", + } + } + showDeprecated={false} + showInternal={false} + /> + <Action + action={ + Object { + "changelog": Array [], + "description": "foobar", + "hasResponseExample": false, + "internal": false, + "key": "baz", + "post": false, + } + } + domain={ + Object { + "actions": Array [ + Object { + "changelog": Array [], + "description": "Foo Desc", + "hasResponseExample": false, + "internal": false, + "key": "foo", + "post": false, + }, + Object { + "changelog": Array [], + "description": "Bar desc", + "hasResponseExample": false, + "internal": false, + "key": "bar", + "post": false, + }, + Object { + "changelog": Array [], + "description": "foobar", + "hasResponseExample": false, + "internal": false, + "key": "baz", + "post": false, + }, + ], + "deprecated": false, + "description": "API Desc", + "internal": false, + "path": "api", + } + } + showDeprecated={false} + showInternal={false} + /> + </div> +</div> +`; + +exports[`should not render deprecated 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-description markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Desc", + } + } + /> + <div + className="web-api-domain-actions" + /> +</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-description markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Desc", + } + } + /> + <div + className="web-api-domain-actions" + /> +</div> +`; + +exports[`should render deprecated 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-description markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Desc", + } + } + /> + <div + className="web-api-domain-actions" + > + <Action + action={ + Object { + "changelog": Array [], + "deprecatedSince": "5.0", + "description": "Foo Desc", + "hasResponseExample": false, + "internal": false, + "key": "foo", + "post": false, + } + } + domain={ + Object { + "actions": Array [ + Object { + "changelog": Array [], + "deprecatedSince": "5.0", + "description": "Foo Desc", + "hasResponseExample": false, + "internal": false, + "key": "foo", + "post": false, + }, + ], + "deprecated": false, + "description": "API Desc", + "internal": false, + "path": "api", + } + } + showDeprecated={true} + showInternal={false} + /> + </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-description markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Desc", + } + } + /> + <div + className="web-api-domain-actions" + > + <Action + action={ + Object { + "changelog": Array [], + "description": "Foo Desc", + "hasResponseExample": false, + "internal": true, + "key": "foo", + "post": false, + } + } + domain={ + Object { + "actions": Array [ + Object { + "changelog": Array [], + "description": "Foo Desc", + "hasResponseExample": false, + "internal": true, + "key": "foo", + "post": false, + }, + ], + "deprecated": false, + "description": "API Desc", + "internal": false, + "path": "api", + } + } + showDeprecated={false} + 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-description markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Desc", + } + } + /> + <div + className="web-api-domain-actions" + > + <Action + action={ + Object { + "changelog": Array [], + "description": "Foo Desc", + "hasResponseExample": false, + "internal": false, + "key": "foo", + "post": false, + } + } + domain={ + Object { + "actions": Array [ + Object { + "changelog": Array [], + "description": "Foo Desc", + "hasResponseExample": false, + "internal": false, + "key": "foo", + "post": false, + }, + Object { + "changelog": Array [], + "description": "Bar desc", + "hasResponseExample": false, + "internal": false, + "key": "bar", + "post": false, + }, + ], + "deprecated": false, + "description": "API Desc", + "internal": false, + "path": "api", + } + } + showDeprecated={false} + showInternal={false} + /> + </div> +</div> +`; diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Menu-test.tsx.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Menu-test.tsx.snap new file mode 100644 index 00000000000..34329aa2fbf --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Menu-test.tsx.snap @@ -0,0 +1,248 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should also render domains with an actions description matching the query 1`] = ` +<div + className="api-documentation-results panel" +> + <div + className="list-group" + > + <Link + className="list-group-item" + onlyActiveOnIndex={false} + style={Object {}} + to="/web_api/bar" + > + <h3 + className="list-group-item-heading" + > + bar + </h3> + <div + className="list-group-item-text markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Bar", + } + } + /> + </Link> + <Link + className="list-group-item" + onlyActiveOnIndex={false} + style={Object {}} + to="/web_api/baz" + > + <h3 + className="list-group-item-heading" + > + baz + </h3> + <div + className="list-group-item-text markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Baz", + } + } + /> + </Link> + </div> +</div> +`; + +exports[`should not render deprecated domains 1`] = ` +<div + className="api-documentation-results panel" +> + <div + className="list-group" + > + <Link + className="list-group-item" + onlyActiveOnIndex={false} + style={Object {}} + to="/web_api/foo" + > + <h3 + className="list-group-item-heading" + > + foo + </h3> + <div + className="list-group-item-text markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Foo", + } + } + /> + </Link> + </div> +</div> +`; + +exports[`should not render internal domains 1`] = ` +<div + className="api-documentation-results panel" +> + <div + className="list-group" + > + <Link + className="list-group-item" + onlyActiveOnIndex={false} + style={Object {}} + to="/web_api/foo" + > + <h3 + className="list-group-item-heading" + > + foo + </h3> + <div + className="list-group-item-text markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Foo", + } + } + /> + </Link> + </div> +</div> +`; + +exports[`should render deprecated domains 1`] = ` +<div + className="api-documentation-results panel" +> + <div + className="list-group" + > + <Link + className="list-group-item" + onlyActiveOnIndex={false} + style={Object {}} + to="/web_api/foo" + > + <h3 + className="list-group-item-heading" + > + foo + </h3> + <div + className="list-group-item-text markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Foo", + } + } + /> + </Link> + <Link + className="list-group-item" + onlyActiveOnIndex={false} + style={Object {}} + to="/web_api/bar" + > + <h3 + className="list-group-item-heading" + > + bar + </h3> + <div + className="list-group-item-text markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Bar", + } + } + /> + </Link> + </div> +</div> +`; + +exports[`should render internal domains 1`] = ` +<div + className="api-documentation-results panel" +> + <div + className="list-group" + > + <Link + className="list-group-item" + onlyActiveOnIndex={false} + style={Object {}} + to="/web_api/foo" + > + <h3 + className="list-group-item-heading" + > + foo + </h3> + <div + className="list-group-item-text markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Foo", + } + } + /> + </Link> + <Link + className="list-group-item" + onlyActiveOnIndex={false} + style={Object {}} + to="/web_api/bar" + > + <h3 + className="list-group-item-heading" + > + bar + <InternalBadge /> + </h3> + <div + className="list-group-item-text markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Bar", + } + } + /> + </Link> + </div> +</div> +`; + +exports[`should render only domains with an action matching the query 1`] = ` +<div + className="api-documentation-results panel" +> + <div + className="list-group" + > + <Link + className="list-group-item" + onlyActiveOnIndex={false} + style={Object {}} + to="/web_api/foo" + > + <h3 + className="list-group-item-heading" + > + foo + </h3> + <div + className="list-group-item-text markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "API Foo", + } + } + /> + </Link> + </div> +</div> +`; diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Params-test.js.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Params-test.tsx.snap index 294cc61c75a..c6a75522309 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Params-test.js.snap +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Params-test.tsx.snap @@ -10,7 +10,7 @@ exports[`should not render deprecated parameters 1`] = ` </div> `; -exports[`should render deprecated key 1`] = ` +exports[`should render deprecated and internal parameters 1`] = ` <div className="web-api-params" > @@ -31,9 +31,50 @@ exports[`should render deprecated key 1`] = ` <div className="little-spacer-top" > - <code> - foo-deprecated - </code> + <DeprecatedBadge + since="5.0" + /> + </div> + <div + className="note little-spacer-top" + > + optional + </div> + </td> + <td> + <div + className="markdown" + dangerouslySetInnerHTML={ + Object { + "__html": "Foo desc", + } + } + /> + </td> + <td + style={ + Object { + "width": 250, + } + } + /> + </tr> + <tr> + <td + className="markdown" + style={ + Object { + "width": 180, + } + } + > + <code> + foo + </code> + <div + className="little-spacer-top" + > + <InternalBadge /> </div> <div className="little-spacer-top" @@ -53,7 +94,7 @@ exports[`should render deprecated key 1`] = ` className="markdown" dangerouslySetInnerHTML={ Object { - "__html": undefined, + "__html": "Foo desc", } } /> @@ -71,7 +112,7 @@ exports[`should render deprecated key 1`] = ` </div> `; -exports[`should render deprecated parameters 1`] = ` +exports[`should render deprecated key 1`] = ` <div className="web-api-params" > @@ -97,6 +138,13 @@ exports[`should render deprecated parameters 1`] = ` /> </div> <div + className="little-spacer-top" + > + <code> + foo-deprecated + </code> + </div> + <div className="note little-spacer-top" > optional @@ -107,7 +155,7 @@ exports[`should render deprecated parameters 1`] = ` className="markdown" dangerouslySetInnerHTML={ Object { - "__html": undefined, + "__html": "Foo desc", } } /> diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ResponseExample-test.tsx.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ResponseExample-test.tsx.snap new file mode 100644 index 00000000000..fd3c8003bda --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ResponseExample-test.tsx.snap @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly after fetching an example 1`] = ` +<div + className="web-api-response" +/> +`; + +exports[`should render correctly after fetching an example 2`] = ` +<div + className="web-api-response" +> + <pre + style={ + Object { + "whiteSpace": "pre-wrap", + } + } + > + my example + </pre> +</div> +`; diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Search-test.tsx.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Search-test.tsx.snap new file mode 100644 index 00000000000..2e4b787f7fe --- /dev/null +++ b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Search-test.tsx.snap @@ -0,0 +1,70 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` +<div + className="web-api-search" +> + <div> + <i + className="icon-search" + /> + <input + className="spacer-left input-large" + onChange={[Function]} + placeholder="search_verb" + type="search" + value="" + /> + </div> + <div + className="big-spacer-top" + > + <Checkbox + checked={false} + onCheck={[Function]} + thirdState={false} + > + <span + className="little-spacer-left" + > + api_documentation.show_internal + </span> + </Checkbox> + <Tooltip + overlay="api_documentation.internal_tooltip" + placement="right" + > + <span> + <HelpIcon + className="spacer-left text-info" + /> + </span> + </Tooltip> + </div> + <div + className="spacer-top" + > + <Checkbox + checked={false} + onCheck={[Function]} + thirdState={false} + > + <span + className="little-spacer-left" + > + api_documentation.show_deprecated + </span> + </Checkbox> + <Tooltip + overlay="api_documentation.deprecation_tooltip" + placement="right" + > + <span> + <HelpIcon + className="spacer-left text-info" + /> + </span> + </Tooltip> + </div> +</div> +`; |