aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/users
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2017-03-28 11:58:01 +0200
committerGrégoire Aubert <gregaubert@users.noreply.github.com>2017-03-31 10:29:27 +0200
commit4b2cf358d38ad0e1931246530d3ff6ada7467079 (patch)
tree6cc4745b769dc225cf26cbf76801ad0b303d17f7 /server/sonar-web/src/main/js/apps/users
parente4af315006ebfb8e6a606d2a29d1aff5706b7452 (diff)
downloadsonarqube-4b2cf358d38ad0e1931246530d3ff6ada7467079.tar.gz
sonarqube-4b2cf358d38ad0e1931246530d3ff6ada7467079.zip
SONAR-8992 Add a member to an organization
Diffstat (limited to 'server/sonar-web/src/main/js/apps/users')
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/UsersSearch.js2
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.css13
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.js102
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchOption.js74
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchValue.js48
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/__tests__/UsersSelectSearch-test.js54
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/__tests__/UsersSelectSearchOption-test.js48
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/__tests__/UsersSelectSearchValue-test.js53
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearch-test.js.snap131
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearchOption-test.js.snap45
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearchValue-test.js.snap47
11 files changed, 616 insertions, 1 deletions
diff --git a/server/sonar-web/src/main/js/apps/users/components/UsersSearch.js b/server/sonar-web/src/main/js/apps/users/components/UsersSearch.js
index 5c17f90f8cf..1b8290cd35d 100644
--- a/server/sonar-web/src/main/js/apps/users/components/UsersSearch.js
+++ b/server/sonar-web/src/main/js/apps/users/components/UsersSearch.js
@@ -56,7 +56,7 @@ export default class UsersSearch extends React.PureComponent {
render() {
const { query } = this.state;
const inputClassName = classNames('search-box-input', {
- touched: query != null && query !== '' && query.length < 2
+ touched: query != null && query.length === 1
});
return (
<div className="panel panel-vertical bordered-bottom spacer-bottom">
diff --git a/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.css b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.css
new file mode 100644
index 00000000000..c8780833809
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.css
@@ -0,0 +1,13 @@
+.Select-big .Select-control {
+ padding-top: 4px;
+ padding-bottom: 4px;
+}
+
+.Select-big .Select-placeholder {
+ margin-top: 4px;
+ margin-bottom: 4px;
+}
+
+.Select-big .Select-value-label {
+ margin-top: 5px;
+}
diff --git a/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.js b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.js
new file mode 100644
index 00000000000..5026720f2b2
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearch.js
@@ -0,0 +1,102 @@
+/*
+ * 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 UsersSelectSearchOption from './UsersSelectSearchOption';
+import UsersSelectSearchValue from './UsersSelectSearchValue';
+import './UsersSelectSearch.css';
+
+export type Option = {
+ login: string,
+ name: string,
+ email?: string,
+ avatar?: string,
+ groupCount?: number
+};
+
+type Props = {
+ selectedUser?: Option,
+ excludedUsers: Array<string>,
+ searchUsers: (string, number) => Promise<*>,
+ handleValueChange: (Option) => void
+};
+
+type State = {
+ searchResult: Array<Option>,
+ isLoading: boolean,
+ search: string
+};
+
+const LIST_SIZE = 10;
+
+export default class UsersSelectSearch extends React.PureComponent {
+ props: Props;
+ state: State;
+
+ constructor(props: Props) {
+ super(props);
+ this.handleSearch = debounce(this.handleSearch);
+ this.state = { searchResult: [], isLoading: false, search: '' };
+ }
+
+ componentDidMount() {
+ this.handleSearch(this.state.search);
+ }
+
+ componentWillReceiveProps(nextProps: Props) {
+ if (this.props.excludedUsers !== nextProps.excludedUsers) {
+ this.handleSearch(this.state.search);
+ }
+ }
+
+ filterSearchResult = ({ users }: { users: Array<Option> }) =>
+ users.filter(user => !this.props.excludedUsers.includes(user.login)).slice(0, LIST_SIZE);
+
+ handleSearch = (search: string) => {
+ this.setState({ isLoading: true, search });
+ this.props.searchUsers(search, Math.min(this.props.excludedUsers.length + LIST_SIZE, 500))
+ .then(this.filterSearchResult)
+ .then(searchResult => {
+ this.setState({ isLoading: false, searchResult });
+ });
+ };
+
+ render() {
+ return (
+ <Select
+ className="Select-big"
+ options={this.state.searchResult}
+ isLoading={this.state.isLoading}
+ optionComponent={UsersSelectSearchOption}
+ valueComponent={UsersSelectSearchValue}
+ onChange={this.props.handleValueChange}
+ onInputChange={this.handleSearch}
+ value={this.props.selectedUser}
+ placeholder=""
+ labelKey="name"
+ valueKey="login"
+ clearable={false}
+ searchable={true}
+ />
+ );
+ }
+}
diff --git a/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchOption.js b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchOption.js
new file mode 100644
index 00000000000..1861cb83d0c
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchOption.js
@@ -0,0 +1,74 @@
+/*
+ * 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 Avatar from '../../../components/ui/Avatar';
+import type { Option } from './UsersSelectSearch';
+
+type Props = {
+ option: Option,
+ children?: Element | Text,
+ className?: string,
+ isFocused?: boolean,
+ onFocus: (Option, MouseEvent) => void,
+ onSelect: (Option, MouseEvent) => void
+};
+
+const AVATAR_SIZE: number = 20;
+
+export default class UsersSelectSearchOption extends React.PureComponent {
+ props: Props;
+
+ handleMouseDown = (event: MouseEvent) => {
+ event.preventDefault();
+ event.stopPropagation();
+ this.props.onSelect(this.props.option, event);
+ };
+
+ handleMouseEnter = (event: MouseEvent) => {
+ this.props.onFocus(this.props.option, event);
+ };
+
+ handleMouseMove = (event: MouseEvent) => {
+ if (this.props.isFocused) {
+ return;
+ }
+ this.props.onFocus(this.props.option, event);
+ };
+
+ render() {
+ const user = this.props.option;
+ return (
+ <div
+ className={this.props.className}
+ onMouseDown={this.handleMouseDown}
+ onMouseEnter={this.handleMouseEnter}
+ onMouseMove={this.handleMouseMove}
+ title={user.name}
+ >
+ <div className="little-spacer-bottom little-spacer-top">
+ <Avatar hash={user.avatar} email={user.email} size={AVATAR_SIZE} />
+ <strong className="spacer-left">{user.login}</strong>
+ <span className="note little-spacer-left">{this.props.children}</span>
+ </div>
+ </div>
+ );
+ }
+}
diff --git a/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchValue.js b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchValue.js
new file mode 100644
index 00000000000..b0939f127a9
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/users/components/UsersSelectSearchValue.js
@@ -0,0 +1,48 @@
+/*
+ * 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 Avatar from '../../../components/ui/Avatar';
+import type { Option } from './UsersSelectSearch';
+
+type Props = {
+ value: Option,
+ children?: Element | Text
+};
+
+const AVATAR_SIZE: number = 20;
+
+export default class UsersSelectSearchValue extends React.PureComponent {
+ props: Props;
+
+ render() {
+ const user = this.props.value;
+ return (
+ <div className="Select-value" title={user ? user.name : ''}>
+ {user && user.login &&
+ <div className="Select-value-label">
+ <Avatar hash={user.avatar} email={user.email} size={AVATAR_SIZE} />
+ <strong className="spacer-left">{user.login}</strong>
+ <span className="note little-spacer-left">{this.props.children}</span>
+ </div>}
+ </div>
+ );
+ }
+}
diff --git a/server/sonar-web/src/main/js/apps/users/components/__tests__/UsersSelectSearch-test.js b/server/sonar-web/src/main/js/apps/users/components/__tests__/UsersSelectSearch-test.js
new file mode 100644
index 00000000000..cfc0481145c
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/users/components/__tests__/UsersSelectSearch-test.js
@@ -0,0 +1,54 @@
+/*
+ * 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 UsersSelectSearch from '../UsersSelectSearch';
+
+const selectedUser = {
+ login: 'admin',
+ name: 'Administrator',
+ avatar: '7daf6c79d4802916d83f6266e24850af'
+};
+const users = [
+ { login: 'admin', name: 'Administrator', email: 'admin@admin.ch' },
+ { login: 'test', name: 'Tester', email: 'tester@testing.ch' },
+ { login: 'foo', name: 'Foo Bar', email: 'foo@bar.ch' }
+];
+const excludedUsers = ['admin'];
+const onSearch = jest.fn(() => {
+ return Promise.resolve(users);
+});
+const onChange = jest.fn();
+
+it('should render correctly', () => {
+ const wrapper = shallow(
+ <UsersSelectSearch
+ selectedUser={selectedUser}
+ excludedUsers={excludedUsers}
+ isLoading={false}
+ handleValueChange={onChange}
+ searchUsers={onSearch}
+ />
+ );
+ expect(wrapper).toMatchSnapshot();
+ const searchResult = wrapper.instance().filterSearchResult({ users });
+ expect(searchResult).toMatchSnapshot();
+ expect(wrapper.setState({ searchResult })).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/users/components/__tests__/UsersSelectSearchOption-test.js b/server/sonar-web/src/main/js/apps/users/components/__tests__/UsersSelectSearchOption-test.js
new file mode 100644
index 00000000000..3023f73918c
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/users/components/__tests__/UsersSelectSearchOption-test.js
@@ -0,0 +1,48 @@
+/*
+ * 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 UsersSelectSearchOption from '../UsersSelectSearchOption';
+
+const user = {
+ login: 'admin',
+ name: 'Administrator',
+ avatar: '7daf6c79d4802916d83f6266e24850af'
+};
+
+const user2 = {
+ login: 'admin',
+ name: 'Administrator',
+ email: 'admin@admin.ch'
+};
+
+it('should render correctly without all parameters', () => {
+ const wrapper = shallow(
+ <UsersSelectSearchOption option={user}>{user.name}</UsersSelectSearchOption>
+ );
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('should render correctly with email instead of hash', () => {
+ const wrapper = shallow(
+ <UsersSelectSearchOption option={user2}>{user.name}</UsersSelectSearchOption>
+ );
+ expect(wrapper).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/users/components/__tests__/UsersSelectSearchValue-test.js b/server/sonar-web/src/main/js/apps/users/components/__tests__/UsersSelectSearchValue-test.js
new file mode 100644
index 00000000000..357365a0826
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/users/components/__tests__/UsersSelectSearchValue-test.js
@@ -0,0 +1,53 @@
+/*
+ * 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 UsersSelectSearchValue from '../UsersSelectSearchValue';
+
+const user = {
+ login: 'admin',
+ name: 'Administrator',
+ avatar: '7daf6c79d4802916d83f6266e24850af'
+};
+
+const user2 = {
+ login: 'admin',
+ name: 'Administrator',
+ email: 'admin@admin.ch'
+};
+
+it('should render correctly with a user', () => {
+ const wrapper = shallow(
+ <UsersSelectSearchValue value={user}>{user.name}</UsersSelectSearchValue>
+ );
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('should render correctly with email instead of hash', () => {
+ const wrapper = shallow(
+ <UsersSelectSearchValue value={user2}>{user2.name}</UsersSelectSearchValue>
+ );
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('should render correctly without value', () => {
+ const wrapper = shallow(<UsersSelectSearchValue />);
+ expect(wrapper).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearch-test.js.snap b/server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearch-test.js.snap
new file mode 100644
index 00000000000..e4f6d80595e
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearch-test.js.snap
@@ -0,0 +1,131 @@
+exports[`test should render correctly 1`] = `
+<Select
+ addLabelText="Add \"{label}\"?"
+ arrowRenderer={[Function]}
+ autosize={true}
+ backspaceRemoves={true}
+ backspaceToRemoveMessage="Press backspace to remove {label}"
+ className="Select-big"
+ clearAllText="Clear all"
+ clearValueText="Clear value"
+ clearable={false}
+ delimiter=","
+ disabled={false}
+ escapeClearsValue={true}
+ filterOptions={[Function]}
+ ignoreAccents={true}
+ ignoreCase={true}
+ inputProps={Object {}}
+ isLoading={false}
+ joinValues={false}
+ labelKey="name"
+ matchPos="any"
+ matchProp="any"
+ menuBuffer={0}
+ menuRenderer={[Function]}
+ multi={false}
+ noResultsText="No results found"
+ onBlurResetsInput={true}
+ onChange={[Function]}
+ onCloseResetsInput={true}
+ onInputChange={[Function]}
+ openAfterFocus={false}
+ optionComponent={[Function]}
+ options={Array []}
+ pageSize={5}
+ placeholder=""
+ required={false}
+ scrollMenuIntoView={true}
+ searchable={true}
+ simpleValue={false}
+ tabSelectsValue={true}
+ value={
+ Object {
+ "avatar": "7daf6c79d4802916d83f6266e24850af",
+ "login": "admin",
+ "name": "Administrator",
+ }
+ }
+ valueComponent={[Function]}
+ valueKey="login" />
+`;
+
+exports[`test should render correctly 2`] = `
+Array [
+ Object {
+ "email": "tester@testing.ch",
+ "login": "test",
+ "name": "Tester",
+ },
+ Object {
+ "email": "foo@bar.ch",
+ "login": "foo",
+ "name": "Foo Bar",
+ },
+]
+`;
+
+exports[`test should render correctly 3`] = `
+<Select
+ addLabelText="Add \"{label}\"?"
+ arrowRenderer={[Function]}
+ autosize={true}
+ backspaceRemoves={true}
+ backspaceToRemoveMessage="Press backspace to remove {label}"
+ className="Select-big"
+ clearAllText="Clear all"
+ clearValueText="Clear value"
+ clearable={false}
+ delimiter=","
+ disabled={false}
+ escapeClearsValue={true}
+ filterOptions={[Function]}
+ ignoreAccents={true}
+ ignoreCase={true}
+ inputProps={Object {}}
+ isLoading={false}
+ joinValues={false}
+ labelKey="name"
+ matchPos="any"
+ matchProp="any"
+ menuBuffer={0}
+ menuRenderer={[Function]}
+ multi={false}
+ noResultsText="No results found"
+ onBlurResetsInput={true}
+ onChange={[Function]}
+ onCloseResetsInput={true}
+ onInputChange={[Function]}
+ openAfterFocus={false}
+ optionComponent={[Function]}
+ options={
+ Array [
+ Object {
+ "email": "tester@testing.ch",
+ "login": "test",
+ "name": "Tester",
+ },
+ Object {
+ "email": "foo@bar.ch",
+ "login": "foo",
+ "name": "Foo Bar",
+ },
+ ]
+ }
+ pageSize={5}
+ placeholder=""
+ required={false}
+ scrollMenuIntoView={true}
+ searchable={true}
+ simpleValue={false}
+ tabSelectsValue={true}
+ value={
+ Object {
+ "avatar": "7daf6c79d4802916d83f6266e24850af",
+ "login": "admin",
+ "name": "Administrator",
+ }
+ }
+ valueComponent={[Function]}
+ valueKey="login" />
+`;
diff --git a/server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearchOption-test.js.snap b/server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearchOption-test.js.snap
new file mode 100644
index 00000000000..92c64c9030f
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearchOption-test.js.snap
@@ -0,0 +1,45 @@
+exports[`test should render correctly with email instead of hash 1`] = `
+<div
+ onMouseDown={[Function]}
+ onMouseEnter={[Function]}
+ onMouseMove={[Function]}
+ title="Administrator">
+ <div
+ className="little-spacer-bottom little-spacer-top">
+ <Connect(Avatar)
+ email="admin@admin.ch"
+ size={20} />
+ <strong
+ className="spacer-left">
+ admin
+ </strong>
+ <span
+ className="note little-spacer-left">
+ Administrator
+ </span>
+ </div>
+</div>
+`;
+
+exports[`test should render correctly without all parameters 1`] = `
+<div
+ onMouseDown={[Function]}
+ onMouseEnter={[Function]}
+ onMouseMove={[Function]}
+ title="Administrator">
+ <div
+ className="little-spacer-bottom little-spacer-top">
+ <Connect(Avatar)
+ hash="7daf6c79d4802916d83f6266e24850af"
+ size={20} />
+ <strong
+ className="spacer-left">
+ admin
+ </strong>
+ <span
+ className="note little-spacer-left">
+ Administrator
+ </span>
+ </div>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearchValue-test.js.snap b/server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearchValue-test.js.snap
new file mode 100644
index 00000000000..2e5a2ab9cd6
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UsersSelectSearchValue-test.js.snap
@@ -0,0 +1,47 @@
+exports[`test should render correctly with a user 1`] = `
+<div
+ className="Select-value"
+ title="Administrator">
+ <div
+ className="Select-value-label">
+ <Connect(Avatar)
+ hash="7daf6c79d4802916d83f6266e24850af"
+ size={20} />
+ <strong
+ className="spacer-left">
+ admin
+ </strong>
+ <span
+ className="note little-spacer-left">
+ Administrator
+ </span>
+ </div>
+</div>
+`;
+
+exports[`test should render correctly with email instead of hash 1`] = `
+<div
+ className="Select-value"
+ title="Administrator">
+ <div
+ className="Select-value-label">
+ <Connect(Avatar)
+ email="admin@admin.ch"
+ size={20} />
+ <strong
+ className="spacer-left">
+ admin
+ </strong>
+ <span
+ className="note little-spacer-left">
+ Administrator
+ </span>
+ </div>
+</div>
+`;
+
+exports[`test should render correctly without value 1`] = `
+<div
+ className="Select-value"
+ title="" />
+`;