##// END OF EJS Templates
tests: re-use assert_session_flash to also test for negative cases....
marcink -
r1925:2c37cda7 default
parent child Browse files
Show More
@@ -1,264 +1,264 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 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 from paste.deploy import loadapp
31 from paste.deploy import loadapp
32 from paste.script.appinstall import SetupCommand
32 from paste.script.appinstall import SetupCommand
33
33
34 import pylons
34 import pylons
35 import pylons.test
35 import pylons.test
36 from pylons import config, url
36 from pylons import config, url
37 from pylons.i18n.translation import _get_translator
37 from pylons.i18n.translation import _get_translator
38 from pylons.util import ContextObj
38 from pylons.util import ContextObj
39
39
40 from routes.util import URLGenerator
40 from routes.util import URLGenerator
41 from nose.plugins.skip import SkipTest
41 from nose.plugins.skip import SkipTest
42 import pytest
42 import pytest
43
43
44 from rhodecode import is_windows
44 from rhodecode import is_windows
45 from rhodecode.config.routing import ADMIN_PREFIX
45 from rhodecode.config.routing import ADMIN_PREFIX
46 from rhodecode.model.meta import Session
46 from rhodecode.model.meta import Session
47 from rhodecode.model.db import User
47 from rhodecode.model.db import User
48 from rhodecode.lib import auth
48 from rhodecode.lib import auth
49 from rhodecode.lib.helpers import flash, link_to
49 from rhodecode.lib.helpers import flash, link_to
50 from rhodecode.lib.utils2 import safe_unicode, safe_str
50 from rhodecode.lib.utils2 import safe_unicode, safe_str
51
51
52
52
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
55 __all__ = [
55 __all__ = [
56 'get_new_dir', 'TestController', 'SkipTest',
56 'get_new_dir', 'TestController', 'SkipTest',
57 'url', 'link_to', 'ldap_lib_installed', 'clear_all_caches',
57 'url', 'link_to', 'ldap_lib_installed', 'clear_all_caches',
58 'assert_session_flash', 'login_user', 'no_newline_id_generator',
58 'assert_session_flash', 'login_user', 'no_newline_id_generator',
59 'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'SVN_REPO',
59 'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'SVN_REPO',
60 'NEW_HG_REPO', 'NEW_GIT_REPO',
60 'NEW_HG_REPO', 'NEW_GIT_REPO',
61 'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
61 'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
62 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
62 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
63 'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN',
63 'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN',
64 'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO',
64 'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO',
65 'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
65 'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
66 'TEST_GIT_REPO_CLONE', 'TEST_GIT_REPO_PULL', 'SCM_TESTS',
66 'TEST_GIT_REPO_CLONE', 'TEST_GIT_REPO_PULL', 'SCM_TESTS',
67 ]
67 ]
68
68
69 # Invoke websetup with the current config file
69 # Invoke websetup with the current config file
70 # SetupCommand('setup-app').run([config_file])
70 # SetupCommand('setup-app').run([config_file])
71
71
72 # SOME GLOBALS FOR TESTS
72 # SOME GLOBALS FOR TESTS
73 TEST_DIR = tempfile.gettempdir()
73 TEST_DIR = tempfile.gettempdir()
74
74
75 TESTS_TMP_PATH = jn(TEST_DIR, 'rc_test_%s' % _RandomNameSequence().next())
75 TESTS_TMP_PATH = jn(TEST_DIR, 'rc_test_%s' % _RandomNameSequence().next())
76 TEST_USER_ADMIN_LOGIN = 'test_admin'
76 TEST_USER_ADMIN_LOGIN = 'test_admin'
77 TEST_USER_ADMIN_PASS = 'test12'
77 TEST_USER_ADMIN_PASS = 'test12'
78 TEST_USER_ADMIN_EMAIL = 'test_admin@mail.com'
78 TEST_USER_ADMIN_EMAIL = 'test_admin@mail.com'
79
79
80 TEST_USER_REGULAR_LOGIN = 'test_regular'
80 TEST_USER_REGULAR_LOGIN = 'test_regular'
81 TEST_USER_REGULAR_PASS = 'test12'
81 TEST_USER_REGULAR_PASS = 'test12'
82 TEST_USER_REGULAR_EMAIL = 'test_regular@mail.com'
82 TEST_USER_REGULAR_EMAIL = 'test_regular@mail.com'
83
83
84 TEST_USER_REGULAR2_LOGIN = 'test_regular2'
84 TEST_USER_REGULAR2_LOGIN = 'test_regular2'
85 TEST_USER_REGULAR2_PASS = 'test12'
85 TEST_USER_REGULAR2_PASS = 'test12'
86 TEST_USER_REGULAR2_EMAIL = 'test_regular2@mail.com'
86 TEST_USER_REGULAR2_EMAIL = 'test_regular2@mail.com'
87
87
88 HG_REPO = 'vcs_test_hg'
88 HG_REPO = 'vcs_test_hg'
89 GIT_REPO = 'vcs_test_git'
89 GIT_REPO = 'vcs_test_git'
90 SVN_REPO = 'vcs_test_svn'
90 SVN_REPO = 'vcs_test_svn'
91
91
92 NEW_HG_REPO = 'vcs_test_hg_new'
92 NEW_HG_REPO = 'vcs_test_hg_new'
93 NEW_GIT_REPO = 'vcs_test_git_new'
93 NEW_GIT_REPO = 'vcs_test_git_new'
94
94
95 HG_FORK = 'vcs_test_hg_fork'
95 HG_FORK = 'vcs_test_hg_fork'
96 GIT_FORK = 'vcs_test_git_fork'
96 GIT_FORK = 'vcs_test_git_fork'
97
97
98 ## VCS
98 ## VCS
99 SCM_TESTS = ['hg', 'git']
99 SCM_TESTS = ['hg', 'git']
100 uniq_suffix = str(int(time.mktime(datetime.datetime.now().timetuple())))
100 uniq_suffix = str(int(time.mktime(datetime.datetime.now().timetuple())))
101
101
102 TEST_GIT_REPO = jn(TESTS_TMP_PATH, GIT_REPO)
102 TEST_GIT_REPO = jn(TESTS_TMP_PATH, GIT_REPO)
103 TEST_GIT_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcsgitclone%s' % uniq_suffix)
103 TEST_GIT_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcsgitclone%s' % uniq_suffix)
104 TEST_GIT_REPO_PULL = jn(TESTS_TMP_PATH, 'vcsgitpull%s' % uniq_suffix)
104 TEST_GIT_REPO_PULL = jn(TESTS_TMP_PATH, 'vcsgitpull%s' % uniq_suffix)
105
105
106 TEST_HG_REPO = jn(TESTS_TMP_PATH, HG_REPO)
106 TEST_HG_REPO = jn(TESTS_TMP_PATH, HG_REPO)
107 TEST_HG_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcshgclone%s' % uniq_suffix)
107 TEST_HG_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcshgclone%s' % uniq_suffix)
108 TEST_HG_REPO_PULL = jn(TESTS_TMP_PATH, 'vcshgpull%s' % uniq_suffix)
108 TEST_HG_REPO_PULL = jn(TESTS_TMP_PATH, 'vcshgpull%s' % uniq_suffix)
109
109
110 TEST_REPO_PREFIX = 'vcs-test'
110 TEST_REPO_PREFIX = 'vcs-test'
111
111
112
112
113 # skip ldap tests if LDAP lib is not installed
113 # skip ldap tests if LDAP lib is not installed
114 ldap_lib_installed = False
114 ldap_lib_installed = False
115 try:
115 try:
116 import ldap
116 import ldap
117 ldap_lib_installed = True
117 ldap_lib_installed = True
118 except ImportError:
118 except ImportError:
119 # means that python-ldap is not installed
119 # means that python-ldap is not installed
120 pass
120 pass
121
121
122
122
123 def clear_all_caches():
123 def clear_all_caches():
124 from beaker.cache import cache_managers
124 from beaker.cache import cache_managers
125 for _cache in cache_managers.values():
125 for _cache in cache_managers.values():
126 _cache.clear()
126 _cache.clear()
127
127
128
128
129 def get_new_dir(title):
129 def get_new_dir(title):
130 """
130 """
131 Returns always new directory path.
131 Returns always new directory path.
132 """
132 """
133 from rhodecode.tests.vcs.utils import get_normalized_path
133 from rhodecode.tests.vcs.utils import get_normalized_path
134 name_parts = [TEST_REPO_PREFIX]
134 name_parts = [TEST_REPO_PREFIX]
135 if title:
135 if title:
136 name_parts.append(title)
136 name_parts.append(title)
137 hex_str = hashlib.sha1('%s %s' % (os.getpid(), time.time())).hexdigest()
137 hex_str = hashlib.sha1('%s %s' % (os.getpid(), time.time())).hexdigest()
138 name_parts.append(hex_str)
138 name_parts.append(hex_str)
139 name = '-'.join(name_parts)
139 name = '-'.join(name_parts)
140 path = os.path.join(TEST_DIR, name)
140 path = os.path.join(TEST_DIR, name)
141 return get_normalized_path(path)
141 return get_normalized_path(path)
142
142
143
143
144 @pytest.mark.usefixtures('app', 'index_location')
144 @pytest.mark.usefixtures('app', 'index_location')
145 class TestController(object):
145 class TestController(object):
146
146
147 maxDiff = None
147 maxDiff = None
148
148
149 def log_user(self, username=TEST_USER_ADMIN_LOGIN,
149 def log_user(self, username=TEST_USER_ADMIN_LOGIN,
150 password=TEST_USER_ADMIN_PASS):
150 password=TEST_USER_ADMIN_PASS):
151 self._logged_username = username
151 self._logged_username = username
152 self._session = login_user_session(self.app, username, password)
152 self._session = login_user_session(self.app, username, password)
153 self.csrf_token = auth.get_csrf_token(self._session)
153 self.csrf_token = auth.get_csrf_token(self._session)
154
154
155 return self._session['rhodecode_user']
155 return self._session['rhodecode_user']
156
156
157 def logout_user(self):
157 def logout_user(self):
158 logout_user_session(self.app, auth.get_csrf_token(self._session))
158 logout_user_session(self.app, auth.get_csrf_token(self._session))
159 self.csrf_token = None
159 self.csrf_token = None
160 self._logged_username = None
160 self._logged_username = None
161 self._session = None
161 self._session = None
162
162
163 def _get_logged_user(self):
163 def _get_logged_user(self):
164 return User.get_by_username(self._logged_username)
164 return User.get_by_username(self._logged_username)
165
165
166
166
167 def login_user_session(
167 def login_user_session(
168 app, username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS):
168 app, username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS):
169 from rhodecode.tests.functional.test_login import login_url
169 from rhodecode.tests.functional.test_login import login_url
170 response = app.post(
170 response = app.post(
171 login_url,
171 login_url,
172 {'username': username, 'password': password})
172 {'username': username, 'password': password})
173 if 'invalid user name' in response.body:
173 if 'invalid user name' in response.body:
174 pytest.fail('could not login using %s %s' % (username, password))
174 pytest.fail('could not login using %s %s' % (username, password))
175
175
176 assert response.status == '302 Found'
176 assert response.status == '302 Found'
177 response = response.follow()
177 response = response.follow()
178 assert response.status == '200 OK'
178 assert response.status == '200 OK'
179
179
180 session = response.get_session_from_response()
180 session = response.get_session_from_response()
181 assert 'rhodecode_user' in session
181 assert 'rhodecode_user' in session
182 rc_user = session['rhodecode_user']
182 rc_user = session['rhodecode_user']
183 assert rc_user.get('username') == username
183 assert rc_user.get('username') == username
184 assert rc_user.get('is_authenticated')
184 assert rc_user.get('is_authenticated')
185
185
186 return session
186 return session
187
187
188
188
189 def logout_user_session(app, csrf_token):
189 def logout_user_session(app, csrf_token):
190 from rhodecode.tests.functional.test_login import logut_url
190 from rhodecode.tests.functional.test_login import logut_url
191 app.post(logut_url, {'csrf_token': csrf_token}, status=302)
191 app.post(logut_url, {'csrf_token': csrf_token}, status=302)
192
192
193
193
194 def login_user(app, username=TEST_USER_ADMIN_LOGIN,
194 def login_user(app, username=TEST_USER_ADMIN_LOGIN,
195 password=TEST_USER_ADMIN_PASS):
195 password=TEST_USER_ADMIN_PASS):
196 return login_user_session(app, username, password)['rhodecode_user']
196 return login_user_session(app, username, password)['rhodecode_user']
197
197
198
198
199 def assert_session_flash(response=None, msg=None, category=None):
199 def assert_session_flash(response=None, msg=None, category=None, no_=None):
200 """
200 """
201 Assert on a flash message in the current session.
201 Assert on a flash message in the current session.
202
202
203 :param msg: Required. The expected message. Will be evaluated if a
203 :param msg: Required. The expected message. Will be evaluated if a
204 :class:`LazyString` is passed in.
204 :class:`LazyString` is passed in.
205 :param response: Optional. For functional testing, pass in the response
205 :param response: Optional. For functional testing, pass in the response
206 object. Otherwise don't pass in any value.
206 object. Otherwise don't pass in any value.
207 :param category: Optional. If passed, the message category will be
207 :param category: Optional. If passed, the message category will be
208 checked as well.
208 checked as well.
209 :param no_: Optional. If passed, the message will be checked to NOT be in the
210 flash session
209 """
211 """
210 if msg is None:
212 if msg is None and no_ is None:
211 raise ValueError("Parameter msg is required.")
213 raise ValueError("Parameter msg or no_ is required.")
214
215 if msg and no_:
216 raise ValueError("Please specify either msg or no_, but not both")
212
217
213 messages = flash.pop_messages()
218 messages = flash.pop_messages()
214 msg = _eval_if_lazy(msg)
219 msg = _eval_if_lazy(msg)
215
220
216 assert messages, 'unable to find message `%s` in empty flash list' % msg
221 assert messages, 'unable to find message `%s` in empty flash list' % msg
217 message = messages[0]
222 message = messages[0]
218
223
219 message_text = _eval_if_lazy(message.message)
224 message_text = _eval_if_lazy(message.message) or ''
220
225
221 if msg not in message_text:
226 if no_:
222 fail_msg = u'msg `%s` not found in session ' \
227 if no_ in message_text:
223 u'flash: got `%s` (type:%s) instead' % (
228 msg = u'msg `%s` found in session flash.' % (no_,)
224 msg, message_text, type(message_text))
229 pytest.fail(safe_str(msg))
230 else:
231 if msg not in message_text:
232 fail_msg = u'msg `%s` not found in session ' \
233 u'flash: got `%s` (type:%s) instead' % (
234 msg, message_text, type(message_text))
225
235
226 pytest.fail(safe_str(fail_msg))
236 pytest.fail(safe_str(fail_msg))
227 if category:
237 if category:
228 assert category == message.category
238 assert category == message.category
229
239
230
240
231 def _eval_if_lazy(value):
241 def _eval_if_lazy(value):
232 return value.eval() if hasattr(value, 'eval') else value
242 return value.eval() if hasattr(value, 'eval') else value
233
243
234
244
235 def assert_not_in_session_flash(response, msg, category=None):
245 def assert_session_flash_is_empty(response):
236 assert 'flash' in response.session, 'Response session has no flash key'
246 assert 'flash' in response.session, 'Response session has no flash key'
237 message_category, message_text = response.session['flash'][0]
238 if msg in message_text:
239 msg = u'msg `%s` found in session flash: got `%s` instead' % (
240 msg, message_text)
241 pytest.fail(safe_str(msg))
242 if category:
243 assert category == message_category
244
247
245
248 msg = 'flash messages are present in session:%s' % \
246 def assert_session_flash_is_empty(response):
249 response.session['flash'][0]
247 if 'flash' in response.session:
250 pytest.fail(safe_str(msg))
248 msg = 'flash messages are present in session:%s' % \
249 response.session['flash'][0]
250 pytest.fail(safe_str(msg))
251
251
252
252
253 def no_newline_id_generator(test_name):
253 def no_newline_id_generator(test_name):
254 """
254 """
255 Generates a test name without spaces or newlines characters. Used for
255 Generates a test name without spaces or newlines characters. Used for
256 nicer output of progress of test
256 nicer output of progress of test
257 """
257 """
258 org_name = test_name
258 org_name = test_name
259 test_name = test_name\
259 test_name = test_name\
260 .replace('\n', '_N') \
260 .replace('\n', '_N') \
261 .replace('\t', '_T') \
261 .replace('\t', '_T') \
262 .replace(' ', '_S')
262 .replace(' ', '_S')
263
263
264 return test_name or 'test-with-empty-name'
264 return test_name or 'test-with-empty-name'
General Comments 0
You need to be logged in to leave comments. Login now