##// END OF EJS Templates
tests: fixed clone url tests.
marcink -
r2499:7c7f631d default
parent child Browse files
Show More
@@ -1,523 +1,522 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import re
22 22
23 23 import mock
24 24 import pytest
25 25
26 26 from rhodecode.apps.repository.views.repo_summary import RepoSummaryView
27 27 from rhodecode.lib import helpers as h
28 28 from rhodecode.lib.compat import OrderedDict
29 29 from rhodecode.lib.utils2 import AttributeDict, safe_str
30 30 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
31 31 from rhodecode.model.db import Repository
32 32 from rhodecode.model.meta import Session
33 33 from rhodecode.model.repo import RepoModel
34 34 from rhodecode.model.scm import ScmModel
35 35 from rhodecode.tests import assert_session_flash
36 36 from rhodecode.tests.fixture import Fixture
37 37 from rhodecode.tests.utils import AssertResponse, repo_on_filesystem
38 38
39 39
40 40 fixture = Fixture()
41 41
42 42
43 43 def route_path(name, params=None, **kwargs):
44 44 import urllib
45 45
46 46 base_url = {
47 47 'repo_summary': '/{repo_name}',
48 48 'repo_stats': '/{repo_name}/repo_stats/{commit_id}',
49 49 'repo_refs_data': '/{repo_name}/refs-data',
50 50 'repo_refs_changelog_data': '/{repo_name}/refs-data-changelog',
51 51 'repo_creating_check': '/{repo_name}/repo_creating_check',
52 52 }[name].format(**kwargs)
53 53
54 54 if params:
55 55 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
56 56 return base_url
57 57
58 58
59 def assert_clone_url(response, server, repo, disabled=False):
60
61 response.mustcontain(
62 '<input type="text" class="input-monospace clone_url_input" '
63 '{disabled}readonly="readonly" '
64 'value="http://test_admin@{server}/{repo}"/>'.format(
65 server=server, repo=repo, disabled='disabled ' if disabled else ' ')
66 )
67
68
59 69 @pytest.mark.usefixtures('app')
60 70 class TestSummaryView(object):
61 71 def test_index(self, autologin_user, backend, http_host_only_stub):
62 72 repo_id = backend.repo.repo_id
63 73 repo_name = backend.repo_name
64 74 with mock.patch('rhodecode.lib.helpers.is_svn_without_proxy',
65 75 return_value=False):
66 76 response = self.app.get(
67 77 route_path('repo_summary', repo_name=repo_name))
68 78
69 79 # repo type
70 80 response.mustcontain(
71 81 '<i class="icon-%s">' % (backend.alias, )
72 82 )
73 83 # public/private
74 84 response.mustcontain(
75 85 """<i class="icon-unlock-alt">"""
76 86 )
77 87
78 88 # clone url...
79 response.mustcontain(
80 'id="clone_url" readonly="readonly"'
81 ' value="http://test_admin@%s/%s"' % (http_host_only_stub, repo_name, ))
82 response.mustcontain(
83 'id="clone_url_id" readonly="readonly"'
84 ' value="http://test_admin@%s/_%s"' % (http_host_only_stub, repo_id, ))
89 assert_clone_url(response, http_host_only_stub, repo_name)
90 assert_clone_url(response, http_host_only_stub, '_{}'.format(repo_id))
85 91
86 92 def test_index_svn_without_proxy(
87 93 self, autologin_user, backend_svn, http_host_only_stub):
88 94 repo_id = backend_svn.repo.repo_id
89 95 repo_name = backend_svn.repo_name
90 96 response = self.app.get(route_path('repo_summary', repo_name=repo_name))
91 97 # clone url...
92 response.mustcontain(
93 'id="clone_url" disabled'
94 ' value="http://test_admin@%s/%s"' % (http_host_only_stub, repo_name, ))
95 response.mustcontain(
96 'id="clone_url_id" disabled'
97 ' value="http://test_admin@%s/_%s"' % (http_host_only_stub, repo_id, ))
98
99 assert_clone_url(response, http_host_only_stub, repo_name, disabled=True)
100 assert_clone_url(response, http_host_only_stub, '_{}'.format(repo_id), disabled=True)
98 101
99 102 def test_index_with_trailing_slash(
100 103 self, autologin_user, backend, http_host_only_stub):
101 104
102 105 repo_id = backend.repo.repo_id
103 106 repo_name = backend.repo_name
104 107 with mock.patch('rhodecode.lib.helpers.is_svn_without_proxy',
105 108 return_value=False):
106 109 response = self.app.get(
107 110 route_path('repo_summary', repo_name=repo_name) + '/',
108 111 status=200)
109 112
110 113 # clone url...
111 response.mustcontain(
112 'id="clone_url" readonly="readonly"'
113 ' value="http://test_admin@%s/%s"' % (http_host_only_stub, repo_name, ))
114 response.mustcontain(
115 'id="clone_url_id" readonly="readonly"'
116 ' value="http://test_admin@%s/_%s"' % (http_host_only_stub, repo_id, ))
114 assert_clone_url(response, http_host_only_stub, repo_name)
115 assert_clone_url(response, http_host_only_stub, '_{}'.format(repo_id))
117 116
118 117 def test_index_by_id(self, autologin_user, backend):
119 118 repo_id = backend.repo.repo_id
120 119 response = self.app.get(
121 120 route_path('repo_summary', repo_name='_%s' % (repo_id,)))
122 121
123 122 # repo type
124 123 response.mustcontain(
125 124 '<i class="icon-%s">' % (backend.alias, )
126 125 )
127 126 # public/private
128 127 response.mustcontain(
129 128 """<i class="icon-unlock-alt">"""
130 129 )
131 130
132 131 def test_index_by_repo_having_id_path_in_name_hg(self, autologin_user):
133 132 fixture.create_repo(name='repo_1')
134 133 response = self.app.get(route_path('repo_summary', repo_name='repo_1'))
135 134
136 135 try:
137 136 response.mustcontain("repo_1")
138 137 finally:
139 138 RepoModel().delete(Repository.get_by_repo_name('repo_1'))
140 139 Session().commit()
141 140
142 141 def test_index_with_anonymous_access_disabled(
143 142 self, backend, disable_anonymous_user):
144 143 response = self.app.get(
145 144 route_path('repo_summary', repo_name=backend.repo_name), status=302)
146 145 assert 'login' in response.location
147 146
148 147 def _enable_stats(self, repo):
149 148 r = Repository.get_by_repo_name(repo)
150 149 r.enable_statistics = True
151 150 Session().add(r)
152 151 Session().commit()
153 152
154 153 expected_trending = {
155 154 'hg': {
156 155 "py": {"count": 68, "desc": ["Python"]},
157 156 "rst": {"count": 16, "desc": ["Rst"]},
158 157 "css": {"count": 2, "desc": ["Css"]},
159 158 "sh": {"count": 2, "desc": ["Bash"]},
160 159 "bat": {"count": 1, "desc": ["Batch"]},
161 160 "cfg": {"count": 1, "desc": ["Ini"]},
162 161 "html": {"count": 1, "desc": ["EvoqueHtml", "Html"]},
163 162 "ini": {"count": 1, "desc": ["Ini"]},
164 163 "js": {"count": 1, "desc": ["Javascript"]},
165 164 "makefile": {"count": 1, "desc": ["Makefile", "Makefile"]}
166 165 },
167 166 'git': {
168 167 "py": {"count": 68, "desc": ["Python"]},
169 168 "rst": {"count": 16, "desc": ["Rst"]},
170 169 "css": {"count": 2, "desc": ["Css"]},
171 170 "sh": {"count": 2, "desc": ["Bash"]},
172 171 "bat": {"count": 1, "desc": ["Batch"]},
173 172 "cfg": {"count": 1, "desc": ["Ini"]},
174 173 "html": {"count": 1, "desc": ["EvoqueHtml", "Html"]},
175 174 "ini": {"count": 1, "desc": ["Ini"]},
176 175 "js": {"count": 1, "desc": ["Javascript"]},
177 176 "makefile": {"count": 1, "desc": ["Makefile", "Makefile"]}
178 177 },
179 178 'svn': {
180 179 "py": {"count": 75, "desc": ["Python"]},
181 180 "rst": {"count": 16, "desc": ["Rst"]},
182 181 "html": {"count": 11, "desc": ["EvoqueHtml", "Html"]},
183 182 "css": {"count": 2, "desc": ["Css"]},
184 183 "bat": {"count": 1, "desc": ["Batch"]},
185 184 "cfg": {"count": 1, "desc": ["Ini"]},
186 185 "ini": {"count": 1, "desc": ["Ini"]},
187 186 "js": {"count": 1, "desc": ["Javascript"]},
188 187 "makefile": {"count": 1, "desc": ["Makefile", "Makefile"]},
189 188 "sh": {"count": 1, "desc": ["Bash"]}
190 189 },
191 190 }
192 191
193 192 def test_repo_stats(self, autologin_user, backend, xhr_header):
194 193 response = self.app.get(
195 194 route_path(
196 195 'repo_stats', repo_name=backend.repo_name, commit_id='tip'),
197 196 extra_environ=xhr_header,
198 197 status=200)
199 198 assert re.match(r'6[\d\.]+ KiB', response.json['size'])
200 199
201 200 def test_repo_stats_code_stats_enabled(self, autologin_user, backend, xhr_header):
202 201 repo_name = backend.repo_name
203 202
204 203 # codes stats
205 204 self._enable_stats(repo_name)
206 205 ScmModel().mark_for_invalidation(repo_name)
207 206
208 207 response = self.app.get(
209 208 route_path(
210 209 'repo_stats', repo_name=backend.repo_name, commit_id='tip'),
211 210 extra_environ=xhr_header,
212 211 status=200)
213 212
214 213 expected_data = self.expected_trending[backend.alias]
215 214 returned_stats = response.json['code_stats']
216 215 for k, v in expected_data.items():
217 216 assert v == returned_stats[k]
218 217
219 218 def test_repo_refs_data(self, backend):
220 219 response = self.app.get(
221 220 route_path('repo_refs_data', repo_name=backend.repo_name),
222 221 status=200)
223 222
224 223 # Ensure that there is the correct amount of items in the result
225 224 repo = backend.repo.scm_instance()
226 225 data = response.json['results']
227 226 items = sum(len(section['children']) for section in data)
228 227 repo_refs = len(repo.branches) + len(repo.tags) + len(repo.bookmarks)
229 228 assert items == repo_refs
230 229
231 230 def test_index_shows_missing_requirements_message(
232 231 self, backend, autologin_user):
233 232 repo_name = backend.repo_name
234 233 scm_patcher = mock.patch.object(
235 234 Repository, 'scm_instance', side_effect=RepositoryRequirementError)
236 235
237 236 with scm_patcher:
238 237 response = self.app.get(route_path('repo_summary', repo_name=repo_name))
239 238 assert_response = AssertResponse(response)
240 239 assert_response.element_contains(
241 240 '.main .alert-warning strong', 'Missing requirements')
242 241 assert_response.element_contains(
243 242 '.main .alert-warning',
244 243 'Commits cannot be displayed, because this repository '
245 244 'uses one or more extensions, which was not enabled.')
246 245
247 246 def test_missing_requirements_page_does_not_contains_switch_to(
248 247 self, autologin_user, backend):
249 248 repo_name = backend.repo_name
250 249 scm_patcher = mock.patch.object(
251 250 Repository, 'scm_instance', side_effect=RepositoryRequirementError)
252 251
253 252 with scm_patcher:
254 253 response = self.app.get(route_path('repo_summary', repo_name=repo_name))
255 254 response.mustcontain(no='Switch To')
256 255
257 256
258 257 @pytest.mark.usefixtures('app')
259 258 class TestRepoLocation(object):
260 259
261 260 @pytest.mark.parametrize("suffix", [u'', u'Δ…Δ™Ε‚'], ids=['', 'non-ascii'])
262 261 def test_missing_filesystem_repo(
263 262 self, autologin_user, backend, suffix, csrf_token):
264 263 repo = backend.create_repo(name_suffix=suffix)
265 264 repo_name = repo.repo_name
266 265
267 266 # delete from file system
268 267 RepoModel()._delete_filesystem_repo(repo)
269 268
270 269 # test if the repo is still in the database
271 270 new_repo = RepoModel().get_by_repo_name(repo_name)
272 271 assert new_repo.repo_name == repo_name
273 272
274 273 # check if repo is not in the filesystem
275 274 assert not repo_on_filesystem(repo_name)
276 275
277 276 response = self.app.get(
278 277 route_path('repo_summary', repo_name=safe_str(repo_name)), status=302)
279 278
280 279 msg = 'The repository `%s` cannot be loaded in filesystem. ' \
281 280 'Please check if it exist, or is not damaged.' % repo_name
282 281 assert_session_flash(response, msg)
283 282
284 283 @pytest.mark.parametrize("suffix", [u'', u'Δ…Δ™Ε‚'], ids=['', 'non-ascii'])
285 284 def test_missing_filesystem_repo_on_repo_check(
286 285 self, autologin_user, backend, suffix, csrf_token):
287 286 repo = backend.create_repo(name_suffix=suffix)
288 287 repo_name = repo.repo_name
289 288
290 289 # delete from file system
291 290 RepoModel()._delete_filesystem_repo(repo)
292 291
293 292 # test if the repo is still in the database
294 293 new_repo = RepoModel().get_by_repo_name(repo_name)
295 294 assert new_repo.repo_name == repo_name
296 295
297 296 # check if repo is not in the filesystem
298 297 assert not repo_on_filesystem(repo_name)
299 298
300 299 # flush the session
301 300 self.app.get(
302 301 route_path('repo_summary', repo_name=safe_str(repo_name)),
303 302 status=302)
304 303
305 304 response = self.app.get(
306 305 route_path('repo_creating_check', repo_name=safe_str(repo_name)),
307 306 status=200)
308 307 msg = 'The repository `%s` cannot be loaded in filesystem. ' \
309 308 'Please check if it exist, or is not damaged.' % repo_name
310 309 assert_session_flash(response, msg )
311 310
312 311
313 312 @pytest.fixture()
314 313 def summary_view(context_stub, request_stub, user_util):
315 314 """
316 315 Bootstrap view to test the view functions
317 316 """
318 317 request_stub.matched_route = AttributeDict(name='test_view')
319 318
320 319 request_stub.user = user_util.create_user().AuthUser()
321 320 request_stub.db_repo = user_util.create_repo()
322 321
323 322 view = RepoSummaryView(context=context_stub, request=request_stub)
324 323 return view
325 324
326 325
327 326 @pytest.mark.usefixtures('app')
328 327 class TestCreateReferenceData(object):
329 328
330 329 @pytest.fixture
331 330 def example_refs(self):
332 331 section_1_refs = OrderedDict((('a', 'a_id'), ('b', 'b_id')))
333 332 example_refs = [
334 333 ('section_1', section_1_refs, 't1'),
335 334 ('section_2', {'c': 'c_id'}, 't2'),
336 335 ]
337 336 return example_refs
338 337
339 338 def test_generates_refs_based_on_commit_ids(self, example_refs, summary_view):
340 339 repo = mock.Mock()
341 340 repo.name = 'test-repo'
342 341 repo.alias = 'git'
343 342 full_repo_name = 'pytest-repo-group/' + repo.name
344 343
345 344 result = summary_view._create_reference_data(
346 345 repo, full_repo_name, example_refs)
347 346
348 347 expected_files_url = '/{}/files/'.format(full_repo_name)
349 348 expected_result = [
350 349 {
351 350 'children': [
352 351 {
353 352 'id': 'a', 'raw_id': 'a_id', 'text': 'a', 'type': 't1',
354 353 'files_url': expected_files_url + 'a/?at=a',
355 354 },
356 355 {
357 356 'id': 'b', 'raw_id': 'b_id', 'text': 'b', 'type': 't1',
358 357 'files_url': expected_files_url + 'b/?at=b',
359 358 }
360 359 ],
361 360 'text': 'section_1'
362 361 },
363 362 {
364 363 'children': [
365 364 {
366 365 'id': 'c', 'raw_id': 'c_id', 'text': 'c', 'type': 't2',
367 366 'files_url': expected_files_url + 'c/?at=c',
368 367 }
369 368 ],
370 369 'text': 'section_2'
371 370 }]
372 371 assert result == expected_result
373 372
374 373 def test_generates_refs_with_path_for_svn(self, example_refs, summary_view):
375 374 repo = mock.Mock()
376 375 repo.name = 'test-repo'
377 376 repo.alias = 'svn'
378 377 full_repo_name = 'pytest-repo-group/' + repo.name
379 378
380 379 result = summary_view._create_reference_data(
381 380 repo, full_repo_name, example_refs)
382 381
383 382 expected_files_url = '/{}/files/'.format(full_repo_name)
384 383 expected_result = [
385 384 {
386 385 'children': [
387 386 {
388 387 'id': 'a@a_id', 'raw_id': 'a_id',
389 388 'text': 'a', 'type': 't1',
390 389 'files_url': expected_files_url + 'a_id/a?at=a',
391 390 },
392 391 {
393 392 'id': 'b@b_id', 'raw_id': 'b_id',
394 393 'text': 'b', 'type': 't1',
395 394 'files_url': expected_files_url + 'b_id/b?at=b',
396 395 }
397 396 ],
398 397 'text': 'section_1'
399 398 },
400 399 {
401 400 'children': [
402 401 {
403 402 'id': 'c@c_id', 'raw_id': 'c_id',
404 403 'text': 'c', 'type': 't2',
405 404 'files_url': expected_files_url + 'c_id/c?at=c',
406 405 }
407 406 ],
408 407 'text': 'section_2'
409 408 }
410 409 ]
411 410 assert result == expected_result
412 411
413 412
414 413 class TestCreateFilesUrl(object):
415 414
416 415 def test_creates_non_svn_url(self, app, summary_view):
417 416 repo = mock.Mock()
418 417 repo.name = 'abcde'
419 418 full_repo_name = 'test-repo-group/' + repo.name
420 419 ref_name = 'branch1'
421 420 raw_id = 'deadbeef0123456789'
422 421 is_svn = False
423 422
424 423 with mock.patch('rhodecode.lib.helpers.route_path') as url_mock:
425 424 result = summary_view._create_files_url(
426 425 repo, full_repo_name, ref_name, raw_id, is_svn)
427 426 url_mock.assert_called_once_with(
428 427 'repo_files', repo_name=full_repo_name, commit_id=ref_name,
429 428 f_path='', _query=dict(at=ref_name))
430 429 assert result == url_mock.return_value
431 430
432 431 def test_creates_svn_url(self, app, summary_view):
433 432 repo = mock.Mock()
434 433 repo.name = 'abcde'
435 434 full_repo_name = 'test-repo-group/' + repo.name
436 435 ref_name = 'branch1'
437 436 raw_id = 'deadbeef0123456789'
438 437 is_svn = True
439 438
440 439 with mock.patch('rhodecode.lib.helpers.route_path') as url_mock:
441 440 result = summary_view._create_files_url(
442 441 repo, full_repo_name, ref_name, raw_id, is_svn)
443 442 url_mock.assert_called_once_with(
444 443 'repo_files', repo_name=full_repo_name, f_path=ref_name,
445 444 commit_id=raw_id, _query=dict(at=ref_name))
446 445 assert result == url_mock.return_value
447 446
448 447 def test_name_has_slashes(self, app, summary_view):
449 448 repo = mock.Mock()
450 449 repo.name = 'abcde'
451 450 full_repo_name = 'test-repo-group/' + repo.name
452 451 ref_name = 'branch1/branch2'
453 452 raw_id = 'deadbeef0123456789'
454 453 is_svn = False
455 454
456 455 with mock.patch('rhodecode.lib.helpers.route_path') as url_mock:
457 456 result = summary_view._create_files_url(
458 457 repo, full_repo_name, ref_name, raw_id, is_svn)
459 458 url_mock.assert_called_once_with(
460 459 'repo_files', repo_name=full_repo_name, commit_id=raw_id,
461 460 f_path='', _query=dict(at=ref_name))
462 461 assert result == url_mock.return_value
463 462
464 463
465 464 class TestReferenceItems(object):
466 465 repo = mock.Mock()
467 466 repo.name = 'pytest-repo'
468 467 repo_full_name = 'pytest-repo-group/' + repo.name
469 468 ref_type = 'branch'
470 469 fake_url = '/abcde/'
471 470
472 471 @staticmethod
473 472 def _format_function(name, id_):
474 473 return 'format_function_{}_{}'.format(name, id_)
475 474
476 475 def test_creates_required_amount_of_items(self, summary_view):
477 476 amount = 100
478 477 refs = {
479 478 'ref{}'.format(i): '{0:040d}'.format(i)
480 479 for i in range(amount)
481 480 }
482 481
483 482 url_patcher = mock.patch.object(summary_view, '_create_files_url')
484 483 svn_patcher = mock.patch('rhodecode.lib.helpers.is_svn',
485 484 return_value=False)
486 485
487 486 with url_patcher as url_mock, svn_patcher:
488 487 result = summary_view._create_reference_items(
489 488 self.repo, self.repo_full_name, refs, self.ref_type,
490 489 self._format_function)
491 490 assert len(result) == amount
492 491 assert url_mock.call_count == amount
493 492
494 493 def test_single_item_details(self, summary_view):
495 494 ref_name = 'ref1'
496 495 ref_id = 'deadbeef'
497 496 refs = {
498 497 ref_name: ref_id
499 498 }
500 499
501 500 svn_patcher = mock.patch('rhodecode.lib.helpers.is_svn',
502 501 return_value=False)
503 502
504 503 url_patcher = mock.patch.object(
505 504 summary_view, '_create_files_url', return_value=self.fake_url)
506 505
507 506 with url_patcher as url_mock, svn_patcher:
508 507 result = summary_view._create_reference_items(
509 508 self.repo, self.repo_full_name, refs, self.ref_type,
510 509 self._format_function)
511 510
512 511 url_mock.assert_called_once_with(
513 512 self.repo, self.repo_full_name, ref_name, ref_id, False)
514 513 expected_result = [
515 514 {
516 515 'text': ref_name,
517 516 'id': self._format_function(ref_name, ref_id),
518 517 'raw_id': ref_id,
519 518 'type': self.ref_type,
520 519 'files_url': self.fake_url
521 520 }
522 521 ]
523 522 assert result == expected_result
General Comments 0
You need to be logged in to leave comments. Login now