##// END OF EJS Templates
tests: use common test route generator.
milka -
r4614:0e8f3a20 default
parent child Browse files
Show More
@@ -1,111 +1,111 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import pytest
21 import pytest
22
22
23 from rhodecode.apps._base import ADMIN_PREFIX
23 from rhodecode.apps._base import ADMIN_PREFIX
24 from rhodecode.model.db import User
24 from rhodecode.model.db import User
25 from rhodecode.tests import (
25 from rhodecode.tests import (
26 TestController, TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS,
26 TestController, route_path_generator, assert_session_flash)
27 TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, assert_session_flash)
28 from rhodecode.tests.fixture import Fixture
27 from rhodecode.tests.fixture import Fixture
29 from rhodecode.tests.utils import AssertResponse
28 from rhodecode.tests.utils import AssertResponse
30
29
31 fixture = Fixture()
30 fixture = Fixture()
32
31
33
32
34 def route_path(name, **kwargs):
33 def route_path(name, params=None, **kwargs):
35 return {
34 url_defs = {
36 'my_account_auth_tokens':
35 'my_account_auth_tokens':
37 ADMIN_PREFIX + '/my_account/auth_tokens',
36 ADMIN_PREFIX + '/my_account/auth_tokens',
38 'my_account_auth_tokens_add':
37 'my_account_auth_tokens_add':
39 ADMIN_PREFIX + '/my_account/auth_tokens/new',
38 ADMIN_PREFIX + '/my_account/auth_tokens/new',
40 'my_account_auth_tokens_delete':
39 'my_account_auth_tokens_delete':
41 ADMIN_PREFIX + '/my_account/auth_tokens/delete',
40 ADMIN_PREFIX + '/my_account/auth_tokens/delete',
42 }[name].format(**kwargs)
41 }
42 return route_path_generator(url_defs, name=name, params=params, **kwargs)
43
43
44
44
45 class TestMyAccountAuthTokens(TestController):
45 class TestMyAccountAuthTokens(TestController):
46
46
47 def test_my_account_auth_tokens(self):
47 def test_my_account_auth_tokens(self):
48 usr = self.log_user('test_regular2', 'test12')
48 usr = self.log_user('test_regular2', 'test12')
49 user = User.get(usr['user_id'])
49 user = User.get(usr['user_id'])
50 response = self.app.get(route_path('my_account_auth_tokens'))
50 response = self.app.get(route_path('my_account_auth_tokens'))
51 for token in user.auth_tokens:
51 for token in user.auth_tokens:
52 response.mustcontain(token[:4])
52 response.mustcontain(token[:4])
53 response.mustcontain('never')
53 response.mustcontain('never')
54
54
55 def test_my_account_add_auth_tokens_wrong_csrf(self, user_util):
55 def test_my_account_add_auth_tokens_wrong_csrf(self, user_util):
56 user = user_util.create_user(password='qweqwe')
56 user = user_util.create_user(password='qweqwe')
57 self.log_user(user.username, 'qweqwe')
57 self.log_user(user.username, 'qweqwe')
58
58
59 self.app.post(
59 self.app.post(
60 route_path('my_account_auth_tokens_add'),
60 route_path('my_account_auth_tokens_add'),
61 {'description': 'desc', 'lifetime': -1}, status=403)
61 {'description': 'desc', 'lifetime': -1}, status=403)
62
62
63 @pytest.mark.parametrize("desc, lifetime", [
63 @pytest.mark.parametrize("desc, lifetime", [
64 ('forever', -1),
64 ('forever', -1),
65 ('5mins', 60*5),
65 ('5mins', 60*5),
66 ('30days', 60*60*24*30),
66 ('30days', 60*60*24*30),
67 ])
67 ])
68 def test_my_account_add_auth_tokens(self, desc, lifetime, user_util):
68 def test_my_account_add_auth_tokens(self, desc, lifetime, user_util):
69 user = user_util.create_user(password='qweqwe')
69 user = user_util.create_user(password='qweqwe')
70 user_id = user.user_id
70 user_id = user.user_id
71 self.log_user(user.username, 'qweqwe')
71 self.log_user(user.username, 'qweqwe')
72
72
73 response = self.app.post(
73 response = self.app.post(
74 route_path('my_account_auth_tokens_add'),
74 route_path('my_account_auth_tokens_add'),
75 {'description': desc, 'lifetime': lifetime,
75 {'description': desc, 'lifetime': lifetime,
76 'csrf_token': self.csrf_token})
76 'csrf_token': self.csrf_token})
77 assert_session_flash(response, 'Auth token successfully created')
77 assert_session_flash(response, 'Auth token successfully created')
78
78
79 response = response.follow()
79 response = response.follow()
80 user = User.get(user_id)
80 user = User.get(user_id)
81 for auth_token in user.auth_tokens:
81 for auth_token in user.auth_tokens:
82 response.mustcontain(auth_token[:4])
82 response.mustcontain(auth_token[:4])
83
83
84 def test_my_account_delete_auth_token(self, user_util):
84 def test_my_account_delete_auth_token(self, user_util):
85 user = user_util.create_user(password='qweqwe')
85 user = user_util.create_user(password='qweqwe')
86 user_id = user.user_id
86 user_id = user.user_id
87 self.log_user(user.username, 'qweqwe')
87 self.log_user(user.username, 'qweqwe')
88
88
89 user = User.get(user_id)
89 user = User.get(user_id)
90 keys = user.get_auth_tokens()
90 keys = user.get_auth_tokens()
91 assert 2 == len(keys)
91 assert 2 == len(keys)
92
92
93 response = self.app.post(
93 response = self.app.post(
94 route_path('my_account_auth_tokens_add'),
94 route_path('my_account_auth_tokens_add'),
95 {'description': 'desc', 'lifetime': -1,
95 {'description': 'desc', 'lifetime': -1,
96 'csrf_token': self.csrf_token})
96 'csrf_token': self.csrf_token})
97 assert_session_flash(response, 'Auth token successfully created')
97 assert_session_flash(response, 'Auth token successfully created')
98 response.follow()
98 response.follow()
99
99
100 user = User.get(user_id)
100 user = User.get(user_id)
101 keys = user.get_auth_tokens()
101 keys = user.get_auth_tokens()
102 assert 3 == len(keys)
102 assert 3 == len(keys)
103
103
104 response = self.app.post(
104 response = self.app.post(
105 route_path('my_account_auth_tokens_delete'),
105 route_path('my_account_auth_tokens_delete'),
106 {'del_auth_token': keys[0].user_api_key_id, 'csrf_token': self.csrf_token})
106 {'del_auth_token': keys[0].user_api_key_id, 'csrf_token': self.csrf_token})
107 assert_session_flash(response, 'Auth token successfully deleted')
107 assert_session_flash(response, 'Auth token successfully deleted')
108
108
109 user = User.get(user_id)
109 user = User.get(user_id)
110 keys = user.auth_tokens
110 keys = user.auth_tokens
111 assert 2 == len(keys)
111 assert 2 == len(keys)
@@ -1,202 +1,202 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22
22
23 import mock
23 import mock
24 import pytest
24 import pytest
25 from whoosh import query
25 from whoosh import query
26
26
27 from rhodecode.tests import (
27 from rhodecode.tests import (
28 TestController, HG_REPO,
28 TestController, route_path_generator, HG_REPO,
29 TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
29 TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
30 from rhodecode.tests.utils import AssertResponse
30 from rhodecode.tests.utils import AssertResponse
31
31
32
32
33 def route_path(name, **kwargs):
33 def route_path(name, params=None, **kwargs):
34 from rhodecode.apps._base import ADMIN_PREFIX
34 from rhodecode.apps._base import ADMIN_PREFIX
35 return {
35 url_defs = {
36 'search':
36 'search':
37 ADMIN_PREFIX + '/search',
37 ADMIN_PREFIX + '/search',
38 'search_repo':
38 'search_repo':
39 '/{repo_name}/search',
39 '/{repo_name}/search',
40
40 }
41 }[name].format(**kwargs)
41 return route_path_generator(url_defs, name=name, params=params, **kwargs)
42
42
43
43
44 class TestSearchController(TestController):
44 class TestSearchController(TestController):
45
45
46 def test_index(self):
46 def test_index(self):
47 self.log_user()
47 self.log_user()
48 response = self.app.get(route_path('search'))
48 response = self.app.get(route_path('search'))
49 assert_response = response.assert_response()
49 assert_response = response.assert_response()
50 assert_response.one_element_exists('input#q')
50 assert_response.one_element_exists('input#q')
51
51
52 def test_search_files_empty_search(self):
52 def test_search_files_empty_search(self):
53 if os.path.isdir(self.index_location):
53 if os.path.isdir(self.index_location):
54 pytest.skip('skipped due to existing index')
54 pytest.skip('skipped due to existing index')
55 else:
55 else:
56 self.log_user()
56 self.log_user()
57 response = self.app.get(route_path('search'),
57 response = self.app.get(route_path('search'),
58 {'q': HG_REPO})
58 {'q': HG_REPO})
59 response.mustcontain('There is no index to search in. '
59 response.mustcontain('There is no index to search in. '
60 'Please run whoosh indexer')
60 'Please run whoosh indexer')
61
61
62 def test_search_validation(self):
62 def test_search_validation(self):
63 self.log_user()
63 self.log_user()
64 response = self.app.get(route_path('search'),
64 response = self.app.get(route_path('search'),
65 {'q': query, 'type': 'content', 'page_limit': 1000})
65 {'q': query, 'type': 'content', 'page_limit': 1000})
66
66
67 response.mustcontain(
67 response.mustcontain(
68 'page_limit - 1000 is greater than maximum value 500')
68 'page_limit - 1000 is greater than maximum value 500')
69
69
70 @pytest.mark.parametrize("query, expected_hits, expected_paths", [
70 @pytest.mark.parametrize("query, expected_hits, expected_paths", [
71 ('todo', 23, [
71 ('todo', 23, [
72 'vcs/backends/hg/inmemory.py',
72 'vcs/backends/hg/inmemory.py',
73 'vcs/tests/test_git.py']),
73 'vcs/tests/test_git.py']),
74 ('extension:rst installation', 6, [
74 ('extension:rst installation', 6, [
75 'docs/index.rst',
75 'docs/index.rst',
76 'docs/installation.rst']),
76 'docs/installation.rst']),
77 ('def repo', 87, [
77 ('def repo', 87, [
78 'vcs/tests/test_git.py',
78 'vcs/tests/test_git.py',
79 'vcs/tests/test_changesets.py']),
79 'vcs/tests/test_changesets.py']),
80 ('repository:%s def test' % HG_REPO, 18, [
80 ('repository:%s def test' % HG_REPO, 18, [
81 'vcs/tests/test_git.py',
81 'vcs/tests/test_git.py',
82 'vcs/tests/test_changesets.py']),
82 'vcs/tests/test_changesets.py']),
83 ('"def main"', 9, [
83 ('"def main"', 9, [
84 'vcs/__init__.py',
84 'vcs/__init__.py',
85 'vcs/tests/__init__.py',
85 'vcs/tests/__init__.py',
86 'vcs/utils/progressbar.py']),
86 'vcs/utils/progressbar.py']),
87 ('owner:test_admin', 358, [
87 ('owner:test_admin', 358, [
88 'vcs/tests/base.py',
88 'vcs/tests/base.py',
89 'MANIFEST.in',
89 'MANIFEST.in',
90 'vcs/utils/termcolors.py',
90 'vcs/utils/termcolors.py',
91 'docs/theme/ADC/static/documentation.png']),
91 'docs/theme/ADC/static/documentation.png']),
92 ('owner:test_admin def main', 72, [
92 ('owner:test_admin def main', 72, [
93 'vcs/__init__.py',
93 'vcs/__init__.py',
94 'vcs/tests/test_utils_filesize.py',
94 'vcs/tests/test_utils_filesize.py',
95 'vcs/tests/test_cli.py']),
95 'vcs/tests/test_cli.py']),
96 ('owner:michaΕ‚ test', 0, []),
96 ('owner:michaΕ‚ test', 0, []),
97 ])
97 ])
98 def test_search_files(self, query, expected_hits, expected_paths):
98 def test_search_files(self, query, expected_hits, expected_paths):
99 self.log_user()
99 self.log_user()
100 response = self.app.get(route_path('search'),
100 response = self.app.get(route_path('search'),
101 {'q': query, 'type': 'content', 'page_limit': 500})
101 {'q': query, 'type': 'content', 'page_limit': 500})
102
102
103 response.mustcontain('%s results' % expected_hits)
103 response.mustcontain('%s results' % expected_hits)
104 for path in expected_paths:
104 for path in expected_paths:
105 response.mustcontain(path)
105 response.mustcontain(path)
106
106
107 @pytest.mark.parametrize("query, expected_hits, expected_commits", [
107 @pytest.mark.parametrize("query, expected_hits, expected_commits", [
108 ('bother to ask where to fetch repo during tests', 3, [
108 ('bother to ask where to fetch repo during tests', 3, [
109 ('hg', 'a00c1b6f5d7a6ae678fd553a8b81d92367f7ecf1'),
109 ('hg', 'a00c1b6f5d7a6ae678fd553a8b81d92367f7ecf1'),
110 ('git', 'c6eb379775c578a95dad8ddab53f963b80894850'),
110 ('git', 'c6eb379775c578a95dad8ddab53f963b80894850'),
111 ('svn', '98')]),
111 ('svn', '98')]),
112 ('michaΕ‚', 0, []),
112 ('michaΕ‚', 0, []),
113 ('changed:tests/utils.py', 36, [
113 ('changed:tests/utils.py', 36, [
114 ('hg', 'a00c1b6f5d7a6ae678fd553a8b81d92367f7ecf1')]),
114 ('hg', 'a00c1b6f5d7a6ae678fd553a8b81d92367f7ecf1')]),
115 ('changed:vcs/utils/archivers.py', 11, [
115 ('changed:vcs/utils/archivers.py', 11, [
116 ('hg', '25213a5fbb048dff8ba65d21e466a835536e5b70'),
116 ('hg', '25213a5fbb048dff8ba65d21e466a835536e5b70'),
117 ('hg', '47aedd538bf616eedcb0e7d630ea476df0e159c7'),
117 ('hg', '47aedd538bf616eedcb0e7d630ea476df0e159c7'),
118 ('hg', 'f5d23247fad4856a1dabd5838afade1e0eed24fb'),
118 ('hg', 'f5d23247fad4856a1dabd5838afade1e0eed24fb'),
119 ('hg', '04ad456aefd6461aea24f90b63954b6b1ce07b3e'),
119 ('hg', '04ad456aefd6461aea24f90b63954b6b1ce07b3e'),
120 ('git', 'c994f0de03b2a0aa848a04fc2c0d7e737dba31fc'),
120 ('git', 'c994f0de03b2a0aa848a04fc2c0d7e737dba31fc'),
121 ('git', 'd1f898326327e20524fe22417c22d71064fe54a1'),
121 ('git', 'd1f898326327e20524fe22417c22d71064fe54a1'),
122 ('git', 'fe568b4081755c12abf6ba673ba777fc02a415f3'),
122 ('git', 'fe568b4081755c12abf6ba673ba777fc02a415f3'),
123 ('git', 'bafe786f0d8c2ff7da5c1dcfcfa577de0b5e92f1')]),
123 ('git', 'bafe786f0d8c2ff7da5c1dcfcfa577de0b5e92f1')]),
124 ('added:README.rst', 3, [
124 ('added:README.rst', 3, [
125 ('hg', '3803844fdbd3b711175fc3da9bdacfcd6d29a6fb'),
125 ('hg', '3803844fdbd3b711175fc3da9bdacfcd6d29a6fb'),
126 ('git', 'ff7ca51e58c505fec0dd2491de52c622bb7a806b'),
126 ('git', 'ff7ca51e58c505fec0dd2491de52c622bb7a806b'),
127 ('svn', '8')]),
127 ('svn', '8')]),
128 ('changed:lazy.py', 15, [
128 ('changed:lazy.py', 15, [
129 ('hg', 'eaa291c5e6ae6126a203059de9854ccf7b5baa12'),
129 ('hg', 'eaa291c5e6ae6126a203059de9854ccf7b5baa12'),
130 ('git', '17438a11f72b93f56d0e08e7d1fa79a378578a82'),
130 ('git', '17438a11f72b93f56d0e08e7d1fa79a378578a82'),
131 ('svn', '82'),
131 ('svn', '82'),
132 ('svn', '262'),
132 ('svn', '262'),
133 ('hg', 'f5d23247fad4856a1dabd5838afade1e0eed24fb'),
133 ('hg', 'f5d23247fad4856a1dabd5838afade1e0eed24fb'),
134 ('git', '33fa3223355104431402a888fa77a4e9956feb3e')
134 ('git', '33fa3223355104431402a888fa77a4e9956feb3e')
135 ]),
135 ]),
136 ('author:marcin@python-blog.com '
136 ('author:marcin@python-blog.com '
137 'commit_id:b986218ba1c9b0d6a259fac9b050b1724ed8e545', 1, [
137 'commit_id:b986218ba1c9b0d6a259fac9b050b1724ed8e545', 1, [
138 ('hg', 'b986218ba1c9b0d6a259fac9b050b1724ed8e545')]),
138 ('hg', 'b986218ba1c9b0d6a259fac9b050b1724ed8e545')]),
139 ('b986218ba1c9b0d6a259fac9b050b1724ed8e545', 1, [
139 ('b986218ba1c9b0d6a259fac9b050b1724ed8e545', 1, [
140 ('hg', 'b986218ba1c9b0d6a259fac9b050b1724ed8e545')]),
140 ('hg', 'b986218ba1c9b0d6a259fac9b050b1724ed8e545')]),
141 ('b986218b', 1, [
141 ('b986218b', 1, [
142 ('hg', 'b986218ba1c9b0d6a259fac9b050b1724ed8e545')]),
142 ('hg', 'b986218ba1c9b0d6a259fac9b050b1724ed8e545')]),
143 ])
143 ])
144 def test_search_commit_messages(
144 def test_search_commit_messages(
145 self, query, expected_hits, expected_commits, enabled_backends):
145 self, query, expected_hits, expected_commits, enabled_backends):
146 self.log_user()
146 self.log_user()
147 response = self.app.get(route_path('search'),
147 response = self.app.get(route_path('search'),
148 {'q': query, 'type': 'commit', 'page_limit': 500})
148 {'q': query, 'type': 'commit', 'page_limit': 500})
149
149
150 response.mustcontain('%s results' % expected_hits)
150 response.mustcontain('%s results' % expected_hits)
151 for backend, commit_id in expected_commits:
151 for backend, commit_id in expected_commits:
152 if backend in enabled_backends:
152 if backend in enabled_backends:
153 response.mustcontain(commit_id)
153 response.mustcontain(commit_id)
154
154
155 @pytest.mark.parametrize("query, expected_hits, expected_paths", [
155 @pytest.mark.parametrize("query, expected_hits, expected_paths", [
156 ('readme.rst', 3, []),
156 ('readme.rst', 3, []),
157 ('test*', 75, []),
157 ('test*', 75, []),
158 ('*model*', 1, []),
158 ('*model*', 1, []),
159 ('extension:rst', 48, []),
159 ('extension:rst', 48, []),
160 ('extension:rst api', 24, []),
160 ('extension:rst api', 24, []),
161 ])
161 ])
162 def test_search_file_paths(self, query, expected_hits, expected_paths):
162 def test_search_file_paths(self, query, expected_hits, expected_paths):
163 self.log_user()
163 self.log_user()
164 response = self.app.get(route_path('search'),
164 response = self.app.get(route_path('search'),
165 {'q': query, 'type': 'path', 'page_limit': 500})
165 {'q': query, 'type': 'path', 'page_limit': 500})
166
166
167 response.mustcontain('%s results' % expected_hits)
167 response.mustcontain('%s results' % expected_hits)
168 for path in expected_paths:
168 for path in expected_paths:
169 response.mustcontain(path)
169 response.mustcontain(path)
170
170
171 def test_search_commit_message_specific_repo(self, backend):
171 def test_search_commit_message_specific_repo(self, backend):
172 self.log_user()
172 self.log_user()
173 response = self.app.get(
173 response = self.app.get(
174 route_path('search_repo',repo_name=backend.repo_name),
174 route_path('search_repo',repo_name=backend.repo_name),
175 {'q': 'bother to ask where to fetch repo during tests',
175 {'q': 'bother to ask where to fetch repo during tests',
176 'type': 'commit'})
176 'type': 'commit'})
177
177
178 response.mustcontain('1 results')
178 response.mustcontain('1 results')
179
179
180 def test_filters_are_not_applied_for_admin_user(self):
180 def test_filters_are_not_applied_for_admin_user(self):
181 self.log_user()
181 self.log_user()
182 with mock.patch('whoosh.searching.Searcher.search') as search_mock:
182 with mock.patch('whoosh.searching.Searcher.search') as search_mock:
183 self.app.get(route_path('search'),
183 self.app.get(route_path('search'),
184 {'q': 'test query', 'type': 'commit'})
184 {'q': 'test query', 'type': 'commit'})
185 assert search_mock.call_count == 1
185 assert search_mock.call_count == 1
186 _, kwargs = search_mock.call_args
186 _, kwargs = search_mock.call_args
187 assert kwargs['filter'] is None
187 assert kwargs['filter'] is None
188
188
189 def test_filters_are_applied_for_normal_user(self, enabled_backends):
189 def test_filters_are_applied_for_normal_user(self, enabled_backends):
190 self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
190 self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
191 with mock.patch('whoosh.searching.Searcher.search') as search_mock:
191 with mock.patch('whoosh.searching.Searcher.search') as search_mock:
192 self.app.get(route_path('search'),
192 self.app.get(route_path('search'),
193 {'q': 'test query', 'type': 'commit'})
193 {'q': 'test query', 'type': 'commit'})
194 assert search_mock.call_count == 1
194 assert search_mock.call_count == 1
195 _, kwargs = search_mock.call_args
195 _, kwargs = search_mock.call_args
196 assert isinstance(kwargs['filter'], query.Or)
196 assert isinstance(kwargs['filter'], query.Or)
197 expected_repositories = [
197 expected_repositories = [
198 'vcs_test_{}'.format(b) for b in enabled_backends]
198 'vcs_test_{}'.format(b) for b in enabled_backends]
199 queried_repositories = [
199 queried_repositories = [
200 name for type_, name in kwargs['filter'].all_terms()]
200 name for type_, name in kwargs['filter'].all_terms()]
201 for repository in expected_repositories:
201 for repository in expected_repositories:
202 assert repository in queried_repositories
202 assert repository in queried_repositories
@@ -1,245 +1,255 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import time
22 import time
23 import logging
23 import logging
24 import datetime
24 import datetime
25 import hashlib
25 import hashlib
26 import tempfile
26 import tempfile
27 from os.path import join as jn
27 from os.path import join as jn
28
28
29 from tempfile import _RandomNameSequence
29 from tempfile import _RandomNameSequence
30
30
31 import pytest
31 import pytest
32
32
33 from rhodecode.model.db import User
33 from rhodecode.model.db import User
34 from rhodecode.lib import auth
34 from rhodecode.lib import auth
35 from rhodecode.lib import helpers as h
35 from rhodecode.lib import helpers as h
36 from rhodecode.lib.helpers import flash, link_to
36 from rhodecode.lib.helpers import flash
37 from rhodecode.lib.utils2 import safe_str
37 from rhodecode.lib.utils2 import safe_str
38
38
39
39
40 log = logging.getLogger(__name__)
40 log = logging.getLogger(__name__)
41
41
42 __all__ = [
42 __all__ = [
43 'get_new_dir', 'TestController',
43 'get_new_dir', 'TestController', 'route_path_generator',
44 'link_to', 'clear_cache_regions',
44 'clear_cache_regions',
45 'assert_session_flash', 'login_user', 'no_newline_id_generator',
45 'assert_session_flash', 'login_user', 'no_newline_id_generator',
46 'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'SVN_REPO',
46 'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'SVN_REPO',
47 'NEW_HG_REPO', 'NEW_GIT_REPO',
47 'NEW_HG_REPO', 'NEW_GIT_REPO',
48 'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
48 'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
49 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
49 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
50 'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN',
50 'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN',
51 'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO',
51 'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO',
52 'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
52 'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
53 'TEST_GIT_REPO_CLONE', 'TEST_GIT_REPO_PULL', 'SCM_TESTS',
53 'TEST_GIT_REPO_CLONE', 'TEST_GIT_REPO_PULL', 'SCM_TESTS',
54 ]
54 ]
55
55
56
56
57 # SOME GLOBALS FOR TESTS
57 # SOME GLOBALS FOR TESTS
58 TEST_DIR = tempfile.gettempdir()
58 TEST_DIR = tempfile.gettempdir()
59
59
60 TESTS_TMP_PATH = jn(TEST_DIR, 'rc_test_%s' % _RandomNameSequence().next())
60 TESTS_TMP_PATH = jn(TEST_DIR, 'rc_test_%s' % _RandomNameSequence().next())
61 TEST_USER_ADMIN_LOGIN = 'test_admin'
61 TEST_USER_ADMIN_LOGIN = 'test_admin'
62 TEST_USER_ADMIN_PASS = 'test12'
62 TEST_USER_ADMIN_PASS = 'test12'
63 TEST_USER_ADMIN_EMAIL = 'test_admin@mail.com'
63 TEST_USER_ADMIN_EMAIL = 'test_admin@mail.com'
64
64
65 TEST_USER_REGULAR_LOGIN = 'test_regular'
65 TEST_USER_REGULAR_LOGIN = 'test_regular'
66 TEST_USER_REGULAR_PASS = 'test12'
66 TEST_USER_REGULAR_PASS = 'test12'
67 TEST_USER_REGULAR_EMAIL = 'test_regular@mail.com'
67 TEST_USER_REGULAR_EMAIL = 'test_regular@mail.com'
68
68
69 TEST_USER_REGULAR2_LOGIN = 'test_regular2'
69 TEST_USER_REGULAR2_LOGIN = 'test_regular2'
70 TEST_USER_REGULAR2_PASS = 'test12'
70 TEST_USER_REGULAR2_PASS = 'test12'
71 TEST_USER_REGULAR2_EMAIL = 'test_regular2@mail.com'
71 TEST_USER_REGULAR2_EMAIL = 'test_regular2@mail.com'
72
72
73 HG_REPO = 'vcs_test_hg'
73 HG_REPO = 'vcs_test_hg'
74 GIT_REPO = 'vcs_test_git'
74 GIT_REPO = 'vcs_test_git'
75 SVN_REPO = 'vcs_test_svn'
75 SVN_REPO = 'vcs_test_svn'
76
76
77 NEW_HG_REPO = 'vcs_test_hg_new'
77 NEW_HG_REPO = 'vcs_test_hg_new'
78 NEW_GIT_REPO = 'vcs_test_git_new'
78 NEW_GIT_REPO = 'vcs_test_git_new'
79
79
80 HG_FORK = 'vcs_test_hg_fork'
80 HG_FORK = 'vcs_test_hg_fork'
81 GIT_FORK = 'vcs_test_git_fork'
81 GIT_FORK = 'vcs_test_git_fork'
82
82
83 ## VCS
83 ## VCS
84 SCM_TESTS = ['hg', 'git']
84 SCM_TESTS = ['hg', 'git']
85 uniq_suffix = str(int(time.mktime(datetime.datetime.now().timetuple())))
85 uniq_suffix = str(int(time.mktime(datetime.datetime.now().timetuple())))
86
86
87 TEST_GIT_REPO = jn(TESTS_TMP_PATH, GIT_REPO)
87 TEST_GIT_REPO = jn(TESTS_TMP_PATH, GIT_REPO)
88 TEST_GIT_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcsgitclone%s' % uniq_suffix)
88 TEST_GIT_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcsgitclone%s' % uniq_suffix)
89 TEST_GIT_REPO_PULL = jn(TESTS_TMP_PATH, 'vcsgitpull%s' % uniq_suffix)
89 TEST_GIT_REPO_PULL = jn(TESTS_TMP_PATH, 'vcsgitpull%s' % uniq_suffix)
90
90
91 TEST_HG_REPO = jn(TESTS_TMP_PATH, HG_REPO)
91 TEST_HG_REPO = jn(TESTS_TMP_PATH, HG_REPO)
92 TEST_HG_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcshgclone%s' % uniq_suffix)
92 TEST_HG_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcshgclone%s' % uniq_suffix)
93 TEST_HG_REPO_PULL = jn(TESTS_TMP_PATH, 'vcshgpull%s' % uniq_suffix)
93 TEST_HG_REPO_PULL = jn(TESTS_TMP_PATH, 'vcshgpull%s' % uniq_suffix)
94
94
95 TEST_REPO_PREFIX = 'vcs-test'
95 TEST_REPO_PREFIX = 'vcs-test'
96
96
97
97
98 def clear_cache_regions(regions=None):
98 def clear_cache_regions(regions=None):
99 # dogpile
99 # dogpile
100 from rhodecode.lib.rc_cache import region_meta
100 from rhodecode.lib.rc_cache import region_meta
101 for region_name, region in region_meta.dogpile_cache_regions.items():
101 for region_name, region in region_meta.dogpile_cache_regions.items():
102 if not regions or region_name in regions:
102 if not regions or region_name in regions:
103 region.invalidate()
103 region.invalidate()
104
104
105
105
106 def get_new_dir(title):
106 def get_new_dir(title):
107 """
107 """
108 Returns always new directory path.
108 Returns always new directory path.
109 """
109 """
110 from rhodecode.tests.vcs.utils import get_normalized_path
110 from rhodecode.tests.vcs.utils import get_normalized_path
111 name_parts = [TEST_REPO_PREFIX]
111 name_parts = [TEST_REPO_PREFIX]
112 if title:
112 if title:
113 name_parts.append(title)
113 name_parts.append(title)
114 hex_str = hashlib.sha1('%s %s' % (os.getpid(), time.time())).hexdigest()
114 hex_str = hashlib.sha1('%s %s' % (os.getpid(), time.time())).hexdigest()
115 name_parts.append(hex_str)
115 name_parts.append(hex_str)
116 name = '-'.join(name_parts)
116 name = '-'.join(name_parts)
117 path = os.path.join(TEST_DIR, name)
117 path = os.path.join(TEST_DIR, name)
118 return get_normalized_path(path)
118 return get_normalized_path(path)
119
119
120
120
121 def repo_id_generator(name):
121 def repo_id_generator(name):
122 numeric_hash = 0
122 numeric_hash = 0
123 for char in name:
123 for char in name:
124 numeric_hash += (ord(char))
124 numeric_hash += (ord(char))
125 return numeric_hash
125 return numeric_hash
126
126
127
127
128 @pytest.mark.usefixtures('app', 'index_location')
128 @pytest.mark.usefixtures('app', 'index_location')
129 class TestController(object):
129 class TestController(object):
130
130
131 maxDiff = None
131 maxDiff = None
132
132
133 def log_user(self, username=TEST_USER_ADMIN_LOGIN,
133 def log_user(self, username=TEST_USER_ADMIN_LOGIN,
134 password=TEST_USER_ADMIN_PASS):
134 password=TEST_USER_ADMIN_PASS):
135 self._logged_username = username
135 self._logged_username = username
136 self._session = login_user_session(self.app, username, password)
136 self._session = login_user_session(self.app, username, password)
137 self.csrf_token = auth.get_csrf_token(self._session)
137 self.csrf_token = auth.get_csrf_token(self._session)
138
138
139 return self._session['rhodecode_user']
139 return self._session['rhodecode_user']
140
140
141 def logout_user(self):
141 def logout_user(self):
142 logout_user_session(self.app, auth.get_csrf_token(self._session))
142 logout_user_session(self.app, auth.get_csrf_token(self._session))
143 self.csrf_token = None
143 self.csrf_token = None
144 self._logged_username = None
144 self._logged_username = None
145 self._session = None
145 self._session = None
146
146
147 def _get_logged_user(self):
147 def _get_logged_user(self):
148 return User.get_by_username(self._logged_username)
148 return User.get_by_username(self._logged_username)
149
149
150
150
151 def login_user_session(
151 def login_user_session(
152 app, username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS):
152 app, username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS):
153
153
154 response = app.post(
154 response = app.post(
155 h.route_path('login'),
155 h.route_path('login'),
156 {'username': username, 'password': password})
156 {'username': username, 'password': password})
157 if 'invalid user name' in response.body:
157 if 'invalid user name' in response.body:
158 pytest.fail('could not login using %s %s' % (username, password))
158 pytest.fail('could not login using %s %s' % (username, password))
159
159
160 assert response.status == '302 Found'
160 assert response.status == '302 Found'
161 response = response.follow()
161 response = response.follow()
162 assert response.status == '200 OK'
162 assert response.status == '200 OK'
163
163
164 session = response.get_session_from_response()
164 session = response.get_session_from_response()
165 assert 'rhodecode_user' in session
165 assert 'rhodecode_user' in session
166 rc_user = session['rhodecode_user']
166 rc_user = session['rhodecode_user']
167 assert rc_user.get('username') == username
167 assert rc_user.get('username') == username
168 assert rc_user.get('is_authenticated')
168 assert rc_user.get('is_authenticated')
169
169
170 return session
170 return session
171
171
172
172
173 def logout_user_session(app, csrf_token):
173 def logout_user_session(app, csrf_token):
174 app.post(h.route_path('logout'), {'csrf_token': csrf_token}, status=302)
174 app.post(h.route_path('logout'), {'csrf_token': csrf_token}, status=302)
175
175
176
176
177 def login_user(app, username=TEST_USER_ADMIN_LOGIN,
177 def login_user(app, username=TEST_USER_ADMIN_LOGIN,
178 password=TEST_USER_ADMIN_PASS):
178 password=TEST_USER_ADMIN_PASS):
179 return login_user_session(app, username, password)['rhodecode_user']
179 return login_user_session(app, username, password)['rhodecode_user']
180
180
181
181
182 def assert_session_flash(response, msg=None, category=None, no_=None):
182 def assert_session_flash(response, msg=None, category=None, no_=None):
183 """
183 """
184 Assert on a flash message in the current session.
184 Assert on a flash message in the current session.
185
185
186 :param response: Response from give calll, it will contain flash
186 :param response: Response from give calll, it will contain flash
187 messages or bound session with them.
187 messages or bound session with them.
188 :param msg: The expected message. Will be evaluated if a
188 :param msg: The expected message. Will be evaluated if a
189 :class:`LazyString` is passed in.
189 :class:`LazyString` is passed in.
190 :param category: Optional. If passed, the message category will be
190 :param category: Optional. If passed, the message category will be
191 checked as well.
191 checked as well.
192 :param no_: Optional. If passed, the message will be checked to NOT
192 :param no_: Optional. If passed, the message will be checked to NOT
193 be in the flash session
193 be in the flash session
194 """
194 """
195 if msg is None and no_ is None:
195 if msg is None and no_ is None:
196 raise ValueError("Parameter msg or no_ is required.")
196 raise ValueError("Parameter msg or no_ is required.")
197
197
198 if msg and no_:
198 if msg and no_:
199 raise ValueError("Please specify either msg or no_, but not both")
199 raise ValueError("Please specify either msg or no_, but not both")
200
200
201 session = response.get_session_from_response()
201 session = response.get_session_from_response()
202 messages = flash.pop_messages(session=session)
202 messages = flash.pop_messages(session=session)
203 msg = _eval_if_lazy(msg)
203 msg = _eval_if_lazy(msg)
204
204
205 if no_:
205 if no_:
206 error_msg = 'unable to detect no_ message `%s` in empty flash list' % no_
206 error_msg = 'unable to detect no_ message `%s` in empty flash list' % no_
207 else:
207 else:
208 error_msg = 'unable to find message `%s` in empty flash list' % msg
208 error_msg = 'unable to find message `%s` in empty flash list' % msg
209 assert messages, error_msg
209 assert messages, error_msg
210 message = messages[0]
210 message = messages[0]
211
211
212 message_text = _eval_if_lazy(message.message) or ''
212 message_text = _eval_if_lazy(message.message) or ''
213
213
214 if no_:
214 if no_:
215 if no_ in message_text:
215 if no_ in message_text:
216 msg = u'msg `%s` found in session flash.' % (no_,)
216 msg = u'msg `%s` found in session flash.' % (no_,)
217 pytest.fail(safe_str(msg))
217 pytest.fail(safe_str(msg))
218 else:
218 else:
219 if msg not in message_text:
219 if msg not in message_text:
220 fail_msg = u'msg `%s` not found in session ' \
220 fail_msg = u'msg `%s` not found in session ' \
221 u'flash: got `%s` (type:%s) instead' % (
221 u'flash: got `%s` (type:%s) instead' % (
222 msg, message_text, type(message_text))
222 msg, message_text, type(message_text))
223
223
224 pytest.fail(safe_str(fail_msg))
224 pytest.fail(safe_str(fail_msg))
225 if category:
225 if category:
226 assert category == message.category
226 assert category == message.category
227
227
228
228
229 def _eval_if_lazy(value):
229 def _eval_if_lazy(value):
230 return value.eval() if hasattr(value, 'eval') else value
230 return value.eval() if hasattr(value, 'eval') else value
231
231
232
232
233 def no_newline_id_generator(test_name):
233 def no_newline_id_generator(test_name):
234 """
234 """
235 Generates a test name without spaces or newlines characters. Used for
235 Generates a test name without spaces or newlines characters. Used for
236 nicer output of progress of test
236 nicer output of progress of test
237 """
237 """
238 org_name = test_name
238 org_name = test_name
239 test_name = safe_str(test_name)\
239 test_name = safe_str(test_name)\
240 .replace('\n', '_N') \
240 .replace('\n', '_N') \
241 .replace('\r', '_N') \
241 .replace('\r', '_N') \
242 .replace('\t', '_T') \
242 .replace('\t', '_T') \
243 .replace(' ', '_S')
243 .replace(' ', '_S')
244
244
245 return test_name or 'test-with-empty-name'
245 return test_name or 'test-with-empty-name'
246
247
248 def route_path_generator(url_defs, name, params=None, **kwargs):
249 import urllib
250
251 base_url = url_defs[name].format(**kwargs)
252
253 if params:
254 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
255 return base_url
General Comments 0
You need to be logged in to leave comments. Login now