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