diff options
author | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-07-27 12:18:59 +0200 |
---|---|---|
committer | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-08-14 11:44:44 +0200 |
commit | a0ea568244db7b77b165c7ecf7dca83620f8edbd (patch) | |
tree | 02c361c952478ae4ab28f9d0a2a6c6f9ff9ef4c5 /server/sonar-web/src/main/js/components | |
parent | f2c95a685a3b950a68122af1e5673978a07df773 (diff) | |
download | sonarqube-a0ea568244db7b77b165c7ecf7dca83620f8edbd.tar.gz sonarqube-a0ea568244db7b77b165c7ecf7dca83620f8edbd.zip |
Generalize facet components for both issues and measures
Diffstat (limited to 'server/sonar-web/src/main/js/components')
18 files changed, 1048 insertions, 0 deletions
diff --git a/server/sonar-web/src/main/js/components/controls/SearchSelect.js b/server/sonar-web/src/main/js/components/controls/SearchSelect.js new file mode 100644 index 00000000000..38515273b6c --- /dev/null +++ b/server/sonar-web/src/main/js/components/controls/SearchSelect.js @@ -0,0 +1,124 @@ +/* + * 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 Select from 'react-select'; +import { debounce } from 'lodash'; +import { translate, translateWithParameters } from '../../helpers/l10n'; + +type Option = { label: string, value: string }; + +type Props = {| + autofocus: boolean, + minimumQueryLength: number, + onSearch: (query: string) => Promise<Array<Option>>, + onSelect: (value: string) => void, + renderOption?: (option: Object) => React.Element<*>, + resetOnBlur: boolean, + value?: string +|}; + +type State = { + loading: boolean, + options: Array<Option>, + query: string +}; + +export default class SearchSelect extends React.PureComponent { + mounted: boolean; + props: Props; + state: State; + + static defaultProps = { + autofocus: true, + minimumQueryLength: 2, + resetOnBlur: true + }; + + constructor(props: Props) { + super(props); + this.state = { loading: false, options: [], query: '' }; + this.search = debounce(this.search, 250); + } + + componentDidMount() { + this.mounted = true; + } + + componentWillUnmount() { + this.mounted = false; + } + + search = (query: string) => { + this.props.onSearch(query).then(options => { + if (this.mounted) { + this.setState({ loading: false, options }); + } + }); + }; + + handleBlur = () => { + this.setState({ options: [], query: '' }); + }; + + handleChange = (option: Option) => { + this.props.onSelect(option.value); + }; + + handleInputChange = (query: string = '') => { + if (query.length >= this.props.minimumQueryLength) { + this.setState({ loading: true, query }); + this.search(query); + } else { + this.setState({ options: [], query }); + } + }; + + // disable internal filtering + handleFilterOption = () => true; + + render() { + return ( + <Select + autofocus={this.props.autofocus} + cache={false} + className="input-super-large" + clearable={false} + filterOption={this.handleFilterOption} + isLoading={this.state.loading} + noResultsText={ + this.state.query.length < this.props.minimumQueryLength + ? translateWithParameters('select2.tooShort', this.props.minimumQueryLength) + : translate('select2.noMatches') + } + onBlur={this.props.resetOnBlur ? this.handleBlur : undefined} + onChange={this.handleChange} + onInputChange={this.handleInputChange} + onOpen={this.props.minimumQueryLength === 0 ? this.handleInputChange : undefined} + optionRenderer={this.props.renderOption} + options={this.state.options} + placeholder={translate('search_verb')} + searchable={true} + value={this.props.value} + valueRenderer={this.props.renderOption} + /> + ); + } +} diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/SearchSelect-test.js b/server/sonar-web/src/main/js/components/controls/__tests__/SearchSelect-test.js new file mode 100644 index 00000000000..f4d46d4f8a8 --- /dev/null +++ b/server/sonar-web/src/main/js/components/controls/__tests__/SearchSelect-test.js @@ -0,0 +1,49 @@ +/* + * 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 { shallow } from 'enzyme'; +import SearchSelect from '../SearchSelect'; + +jest.mock('lodash', () => ({ + debounce: fn => fn +})); + +it('should render Select', () => { + expect(shallow(<SearchSelect onSearch={jest.fn()} onSelect={jest.fn()} />)).toMatchSnapshot(); +}); + +it('should call onSelect', () => { + const onSelect = jest.fn(); + const wrapper = shallow(<SearchSelect onSearch={jest.fn()} onSelect={onSelect} />); + wrapper.prop('onChange')({ value: 'foo' }); + expect(onSelect).lastCalledWith('foo'); +}); + +it('should call onSearch', () => { + const onSearch = jest.fn().mockReturnValue(Promise.resolve([])); + const wrapper = shallow( + <SearchSelect minimumQueryLength={2} onSearch={onSearch} onSelect={jest.fn()} /> + ); + wrapper.prop('onInputChange')('f'); + expect(onSearch).not.toHaveBeenCalled(); + wrapper.prop('onInputChange')('foo'); + expect(onSearch).lastCalledWith('foo'); +}); diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchSelect-test.js.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchSelect-test.js.snap new file mode 100644 index 00000000000..d3ea2edb7b0 --- /dev/null +++ b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchSelect-test.js.snap @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render Select 1`] = ` +<Select + addLabelText="Add \\"{label}\\"?" + arrowRenderer={[Function]} + autofocus={true} + autosize={true} + backspaceRemoves={true} + backspaceToRemoveMessage="Press backspace to remove {label}" + cache={false} + className="input-super-large" + clearAllText="Clear all" + clearRenderer={[Function]} + clearValueText="Clear value" + clearable={false} + deleteRemoves={true} + delimiter="," + disabled={false} + escapeClearsValue={true} + filterOption={[Function]} + filterOptions={[Function]} + ignoreAccents={true} + ignoreCase={true} + inputProps={Object {}} + isLoading={false} + joinValues={false} + labelKey="label" + matchPos="any" + matchProp="any" + menuBuffer={0} + menuRenderer={[Function]} + multi={false} + noResultsText="select2.tooShort.2" + onBlur={[Function]} + onBlurResetsInput={true} + onChange={[Function]} + onCloseResetsInput={true} + onInputChange={[Function]} + optionComponent={[Function]} + options={Array []} + pageSize={5} + placeholder="search_verb" + required={false} + scrollMenuIntoView={true} + searchable={true} + simpleValue={false} + tabSelectsValue={true} + valueComponent={[Function]} + valueKey="value" +/> +`; diff --git a/server/sonar-web/src/main/js/components/facet/FacetBox.js b/server/sonar-web/src/main/js/components/facet/FacetBox.js new file mode 100644 index 00000000000..92b7afb58db --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/FacetBox.js @@ -0,0 +1,33 @@ +/* + * 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'; + +type Props = {| + children?: React.Element<*> +|}; + +export default function FacetBox(props: Props) { + return ( + <div className="search-navigator-facet-box"> + {props.children} + </div> + ); +} diff --git a/server/sonar-web/src/main/js/components/facet/FacetFooter.js b/server/sonar-web/src/main/js/components/facet/FacetFooter.js new file mode 100644 index 00000000000..d11af837202 --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/FacetFooter.js @@ -0,0 +1,43 @@ +/* + * 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 SearchSelect from '../controls/SearchSelect'; + +type Option = { label: string, value: string }; + +type Props = {| + minimumQueryLength?: number, + onSearch: (query: string) => Promise<Array<Option>>, + onSelect: (value: string) => void, + renderOption?: (option: Object) => React.Element<*> +|}; + +export default class FacetFooter extends React.PureComponent { + props: Props; + + render() { + return ( + <div className="search-navigator-facet-footer"> + <SearchSelect autofocus={false} {...this.props} /> + </div> + ); + } +} diff --git a/server/sonar-web/src/main/js/components/facet/FacetHeader.js b/server/sonar-web/src/main/js/components/facet/FacetHeader.js new file mode 100644 index 00000000000..42c7b274f89 --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/FacetHeader.js @@ -0,0 +1,105 @@ +/* + * 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 +/* eslint-disable max-len */ +import React from 'react'; +import { translate } from '../../helpers/l10n'; + +type Props = {| + name: string, + onClear?: () => void, + onClick?: () => void, + open: boolean, + values?: number +|}; + +export default class FacetHeader extends React.PureComponent { + props: Props; + + static defaultProps = { + open: true + }; + + handleClearClick = (event: Event & { currentTarget: HTMLElement }) => { + event.preventDefault(); + event.currentTarget.blur(); + if (this.props.onClear) { + this.props.onClear(); + } + }; + + handleClick = (event: Event & { currentTarget: HTMLElement }) => { + event.preventDefault(); + event.currentTarget.blur(); + if (this.props.onClick) { + this.props.onClick(); + } + }; + + renderCheckbox() { + return ( + <svg viewBox="0 0 1792 1792" width="10" height="10" style={{ paddingTop: 3 }}> + {this.props.open + ? <path + style={{ fill: 'currentColor ' }} + d="M1683 808l-742 741q-19 19-45 19t-45-19l-742-741q-19-19-19-45.5t19-45.5l166-165q19-19 45-19t45 19l531 531 531-531q19-19 45-19t45 19l166 165q19 19 19 45.5t-19 45.5z" + /> + : <path + style={{ fill: 'currentColor ' }} + d="M1363 877l-742 742q-19 19-45 19t-45-19l-166-166q-19-19-19-45t19-45l531-531-531-531q-19-19-19-45t19-45l166-166q19-19 45-19t45 19l742 742q19 19 19 45t-19 45z" + />} + </svg> + ); + } + + renderValueIndicator() { + if (this.props.open || !this.props.values) { + return null; + } + return ( + <span className="spacer-left badge is-rounded"> + {this.props.values} + </span> + ); + } + + render() { + const showClearButton: boolean = !!this.props.values && this.props.onClear != null; + + return ( + <div> + {showClearButton && + <button + className="search-navigator-facet-header-button button-small button-red" + onClick={this.handleClearClick}> + {translate('clear')} + </button>} + + {this.props.onClick + ? <a className="search-navigator-facet-header" href="#" onClick={this.handleClick}> + {this.renderCheckbox()} {this.props.name} {this.renderValueIndicator()} + </a> + : <span className="search-navigator-facet-header"> + {this.props.name} + </span>} + </div> + ); + } +} diff --git a/server/sonar-web/src/main/js/components/facet/FacetItem.js b/server/sonar-web/src/main/js/components/facet/FacetItem.js new file mode 100644 index 00000000000..4ecaf7650d4 --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/FacetItem.js @@ -0,0 +1,73 @@ +/* + * 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 classNames from 'classnames'; + +type Props = {| + active: boolean, + disabled: boolean, + halfWidth: boolean, + name: string | React.Element<*>, + onClick: string => void, + stat?: ?(string | React.Element<*>), + value: string +|}; + +export default class FacetItem extends React.PureComponent { + props: Props; + + static defaultProps = { + disabled: false, + halfWidth: false + }; + + handleClick = (event: Event & { currentTarget: HTMLElement }) => { + event.preventDefault(); + this.props.onClick(this.props.value); + }; + + render() { + const className = classNames('facet', 'search-navigator-facet', { + active: this.props.active, + 'search-navigator-facet-half': this.props.halfWidth + }); + + return this.props.disabled + ? <span className={className}> + <span className="facet-name"> + {this.props.name} + </span> + {this.props.stat != null && + <span className="facet-stat"> + {this.props.stat} + </span>} + </span> + : <a className={className} href="#" onClick={this.handleClick}> + <span className="facet-name"> + {this.props.name} + </span> + {this.props.stat != null && + <span className="facet-stat"> + {this.props.stat} + </span>} + </a>; + } +} diff --git a/server/sonar-web/src/main/js/components/facet/FacetItemsList.js b/server/sonar-web/src/main/js/components/facet/FacetItemsList.js new file mode 100644 index 00000000000..5d36d9934e3 --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/FacetItemsList.js @@ -0,0 +1,33 @@ +/* + * 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'; + +type Props = {| + children?: Array<React.Element<*>> +|}; + +export default function FacetItemsList(props: Props) { + return ( + <div className="search-navigator-facet-list"> + {props.children} + </div> + ); +} diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/FacetBox-test.js b/server/sonar-web/src/main/js/components/facet/__tests__/FacetBox-test.js new file mode 100644 index 00000000000..2fb313d3f85 --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/__tests__/FacetBox-test.js @@ -0,0 +1,33 @@ +/* + * 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 { shallow } from 'enzyme'; +import FacetBox from '../FacetBox'; + +it('should render', () => { + expect( + shallow( + <FacetBox> + <div /> + </FacetBox> + ) + ).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/FacetFooter-test.js b/server/sonar-web/src/main/js/components/facet/__tests__/FacetFooter-test.js new file mode 100644 index 00000000000..4dbf1cc3ece --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/__tests__/FacetFooter-test.js @@ -0,0 +1,27 @@ +/* + * 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 { shallow } from 'enzyme'; +import FacetFooter from '../FacetFooter'; + +it('should render', () => { + expect(shallow(<FacetFooter onSearch={jest.fn()} onSelect={jest.fn()} />)).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/FacetHeader-test.js b/server/sonar-web/src/main/js/components/facet/__tests__/FacetHeader-test.js new file mode 100644 index 00000000000..aaa674c1926 --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/__tests__/FacetHeader-test.js @@ -0,0 +1,65 @@ +/* + * 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 { shallow } from 'enzyme'; +import { click } from '../../../helpers/testUtils'; +import FacetHeader from '../FacetHeader'; + +it('should render open facet with value', () => { + expect( + shallow(<FacetHeader name="foo" onClick={jest.fn()} open={true} values={1} />) + ).toMatchSnapshot(); +}); + +it('should render open facet without value', () => { + expect(shallow(<FacetHeader name="foo" onClick={jest.fn()} open={true} />)).toMatchSnapshot(); +}); + +it('should render closed facet with value', () => { + expect( + shallow(<FacetHeader name="foo" onClick={jest.fn()} open={false} values={1} />) + ).toMatchSnapshot(); +}); + +it('should render closed facet without value', () => { + expect(shallow(<FacetHeader name="foo" onClick={jest.fn()} open={false} />)).toMatchSnapshot(); +}); + +it('should render without link', () => { + expect(shallow(<FacetHeader name="foo" open={false} />)).toMatchSnapshot(); +}); + +it('should call onClick', () => { + const onClick = jest.fn(); + const wrapper = shallow(<FacetHeader name="foo" onClick={onClick} open={false} />); + click(wrapper.find('a')); + expect(onClick).toHaveBeenCalled(); +}); + +it('should clear', () => { + const onClear = jest.fn(); + const wrapper = shallow( + <FacetHeader name="foo" onClear={onClear} onClick={jest.fn()} open={false} values={3} /> + ); + expect(wrapper).toMatchSnapshot(); + click(wrapper.find('.button-red')); + expect(onClear).toHaveBeenCalled(); +}); diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/FacetItem-test.js b/server/sonar-web/src/main/js/components/facet/__tests__/FacetItem-test.js new file mode 100644 index 00000000000..2b602b29357 --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/__tests__/FacetItem-test.js @@ -0,0 +1,60 @@ +/* + * 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 { shallow } from 'enzyme'; +import { click } from '../../../helpers/testUtils'; +import FacetItem from '../FacetItem'; + +const renderFacetItem = (props: {}) => + shallow( + <FacetItem active={false} name="foo" onClick={jest.fn()} stat={null} value="bar" {...props} /> + ); + +it('should render active', () => { + expect(renderFacetItem({ active: true })).toMatchSnapshot(); +}); + +it('should render inactive', () => { + expect(renderFacetItem({ active: false })).toMatchSnapshot(); +}); + +it('should render stat', () => { + expect(renderFacetItem({ stat: '13' })).toMatchSnapshot(); +}); + +it('should render disabled', () => { + expect(renderFacetItem({ disabled: true })).toMatchSnapshot(); +}); + +it('should render half width', () => { + expect(renderFacetItem({ halfWidth: true })).toMatchSnapshot(); +}); + +it('should render effort stat', () => { + expect(renderFacetItem({ facetMode: 'effort', stat: '1234' })).toMatchSnapshot(); +}); + +it('should call onClick', () => { + const onClick = jest.fn(); + const wrapper = renderFacetItem({ onClick }); + click(wrapper, { currentTarget: { dataset: { value: 'bar' } } }); + expect(onClick).toHaveBeenCalled(); +}); diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/FacetItemsList-test.js b/server/sonar-web/src/main/js/components/facet/__tests__/FacetItemsList-test.js new file mode 100644 index 00000000000..39fc1fb4eef --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/__tests__/FacetItemsList-test.js @@ -0,0 +1,33 @@ +/* + * 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 { shallow } from 'enzyme'; +import FacetItemsList from '../FacetItemsList'; + +it('should render', () => { + expect( + shallow( + <FacetItemsList> + <div /> + </FacetItemsList> + ) + ).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetBox-test.js.snap b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetBox-test.js.snap new file mode 100644 index 00000000000..e28d4538d46 --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetBox-test.js.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render 1`] = ` +<div + className="search-navigator-facet-box" +> + <div /> +</div> +`; diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetFooter-test.js.snap b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetFooter-test.js.snap new file mode 100644 index 00000000000..e2475bdc5dd --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetFooter-test.js.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render 1`] = ` +<div + className="search-navigator-facet-footer" +> + <SearchSelect + autofocus={false} + minimumQueryLength={2} + onSearch={[Function]} + onSelect={[Function]} + resetOnBlur={true} + /> +</div> +`; diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetHeader-test.js.snap b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetHeader-test.js.snap new file mode 100644 index 00000000000..8c92ac2d4ba --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetHeader-test.js.snap @@ -0,0 +1,192 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should clear 1`] = ` +<div> + <button + className="search-navigator-facet-header-button button-small button-red" + onClick={[Function]} + > + clear + </button> + <a + className="search-navigator-facet-header" + href="#" + onClick={[Function]} + > + <svg + height="10" + style={ + Object { + "paddingTop": 3, + } + } + viewBox="0 0 1792 1792" + width="10" + > + <path + d="M1363 877l-742 742q-19 19-45 19t-45-19l-166-166q-19-19-19-45t19-45l531-531-531-531q-19-19-19-45t19-45l166-166q19-19 45-19t45 19l742 742q19 19 19 45t-19 45z" + style={ + Object { + "fill": "currentColor ", + } + } + /> + </svg> + + foo + + <span + className="spacer-left badge is-rounded" + > + 3 + </span> + </a> +</div> +`; + +exports[`should render closed facet with value 1`] = ` +<div> + <a + className="search-navigator-facet-header" + href="#" + onClick={[Function]} + > + <svg + height="10" + style={ + Object { + "paddingTop": 3, + } + } + viewBox="0 0 1792 1792" + width="10" + > + <path + d="M1363 877l-742 742q-19 19-45 19t-45-19l-166-166q-19-19-19-45t19-45l531-531-531-531q-19-19-19-45t19-45l166-166q19-19 45-19t45 19l742 742q19 19 19 45t-19 45z" + style={ + Object { + "fill": "currentColor ", + } + } + /> + </svg> + + foo + + <span + className="spacer-left badge is-rounded" + > + 1 + </span> + </a> +</div> +`; + +exports[`should render closed facet without value 1`] = ` +<div> + <a + className="search-navigator-facet-header" + href="#" + onClick={[Function]} + > + <svg + height="10" + style={ + Object { + "paddingTop": 3, + } + } + viewBox="0 0 1792 1792" + width="10" + > + <path + d="M1363 877l-742 742q-19 19-45 19t-45-19l-166-166q-19-19-19-45t19-45l531-531-531-531q-19-19-19-45t19-45l166-166q19-19 45-19t45 19l742 742q19 19 19 45t-19 45z" + style={ + Object { + "fill": "currentColor ", + } + } + /> + </svg> + + foo + + </a> +</div> +`; + +exports[`should render open facet with value 1`] = ` +<div> + <a + className="search-navigator-facet-header" + href="#" + onClick={[Function]} + > + <svg + height="10" + style={ + Object { + "paddingTop": 3, + } + } + viewBox="0 0 1792 1792" + width="10" + > + <path + d="M1683 808l-742 741q-19 19-45 19t-45-19l-742-741q-19-19-19-45.5t19-45.5l166-165q19-19 45-19t45 19l531 531 531-531q19-19 45-19t45 19l166 165q19 19 19 45.5t-19 45.5z" + style={ + Object { + "fill": "currentColor ", + } + } + /> + </svg> + + foo + + </a> +</div> +`; + +exports[`should render open facet without value 1`] = ` +<div> + <a + className="search-navigator-facet-header" + href="#" + onClick={[Function]} + > + <svg + height="10" + style={ + Object { + "paddingTop": 3, + } + } + viewBox="0 0 1792 1792" + width="10" + > + <path + d="M1683 808l-742 741q-19 19-45 19t-45-19l-742-741q-19-19-19-45.5t19-45.5l166-165q19-19 45-19t45 19l531 531 531-531q19-19 45-19t45 19l166 165q19 19 19 45.5t-19 45.5z" + style={ + Object { + "fill": "currentColor ", + } + } + /> + </svg> + + foo + + </a> +</div> +`; + +exports[`should render without link 1`] = ` +<div> + <span + className="search-navigator-facet-header" + > + foo + </span> +</div> +`; diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetItem-test.js.snap b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetItem-test.js.snap new file mode 100644 index 00000000000..6aff532c59f --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetItem-test.js.snap @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render active 1`] = ` +<a + className="facet search-navigator-facet active" + href="#" + onClick={[Function]} +> + <span + className="facet-name" + > + foo + </span> +</a> +`; + +exports[`should render disabled 1`] = ` +<span + className="facet search-navigator-facet" +> + <span + className="facet-name" + > + foo + </span> +</span> +`; + +exports[`should render effort stat 1`] = ` +<a + className="facet search-navigator-facet" + href="#" + onClick={[Function]} +> + <span + className="facet-name" + > + foo + </span> + <span + className="facet-stat" + > + 1234 + </span> +</a> +`; + +exports[`should render half width 1`] = ` +<a + className="facet search-navigator-facet search-navigator-facet-half" + href="#" + onClick={[Function]} +> + <span + className="facet-name" + > + foo + </span> +</a> +`; + +exports[`should render inactive 1`] = ` +<a + className="facet search-navigator-facet" + href="#" + onClick={[Function]} +> + <span + className="facet-name" + > + foo + </span> +</a> +`; + +exports[`should render stat 1`] = ` +<a + className="facet search-navigator-facet" + href="#" + onClick={[Function]} +> + <span + className="facet-name" + > + foo + </span> + <span + className="facet-stat" + > + 13 + </span> +</a> +`; diff --git a/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetItemsList-test.js.snap b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetItemsList-test.js.snap new file mode 100644 index 00000000000..9962cfc364e --- /dev/null +++ b/server/sonar-web/src/main/js/components/facet/__tests__/__snapshots__/FacetItemsList-test.js.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render 1`] = ` +<div + className="search-navigator-facet-list" +> + <div /> +</div> +`; |