##// END OF EJS Templates
tests: lazy load the JSON history for tests....
marcink -
r1932:6605b41c default
parent child Browse files
Show More
@@ -1,1062 +1,1064 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
22
23 import mock
23 import mock
24 import pytest
24 import pytest
25
25
26 from rhodecode.apps.repository.views.repo_files import RepoFilesView
26 from rhodecode.apps.repository.views.repo_files import RepoFilesView
27 from rhodecode.lib import helpers as h
27 from rhodecode.lib import helpers as h
28 from rhodecode.lib.compat import OrderedDict
28 from rhodecode.lib.compat import OrderedDict
29 from rhodecode.lib.ext_json import json
29 from rhodecode.lib.ext_json import json
30 from rhodecode.lib.vcs import nodes
30 from rhodecode.lib.vcs import nodes
31
31
32 from rhodecode.lib.vcs.conf import settings
32 from rhodecode.lib.vcs.conf import settings
33 from rhodecode.tests import assert_session_flash
33 from rhodecode.tests import assert_session_flash
34 from rhodecode.tests.fixture import Fixture
34 from rhodecode.tests.fixture import Fixture
35
35
36 fixture = Fixture()
36 fixture = Fixture()
37
37
38 NODE_HISTORY = {
38
39 'hg': json.loads(fixture.load_resource('hg_node_history_response.json')),
39 def get_node_history(backend_type):
40 'git': json.loads(fixture.load_resource('git_node_history_response.json')),
40 return {
41 'svn': json.loads(fixture.load_resource('svn_node_history_response.json')),
41 'hg': json.loads(fixture.load_resource('hg_node_history_response.json')),
42 }
42 'git': json.loads(fixture.load_resource('git_node_history_response.json')),
43 'svn': json.loads(fixture.load_resource('svn_node_history_response.json')),
44 }[backend_type]
43
45
44
46
45 def route_path(name, params=None, **kwargs):
47 def route_path(name, params=None, **kwargs):
46 import urllib
48 import urllib
47
49
48 base_url = {
50 base_url = {
49 'repo_archivefile': '/{repo_name}/archive/{fname}',
51 'repo_archivefile': '/{repo_name}/archive/{fname}',
50 'repo_files_diff': '/{repo_name}/diff/{f_path}',
52 'repo_files_diff': '/{repo_name}/diff/{f_path}',
51 'repo_files_diff_2way_redirect': '/{repo_name}/diff-2way/{f_path}',
53 'repo_files_diff_2way_redirect': '/{repo_name}/diff-2way/{f_path}',
52 'repo_files': '/{repo_name}/files/{commit_id}/{f_path}',
54 'repo_files': '/{repo_name}/files/{commit_id}/{f_path}',
53 'repo_files:default_path': '/{repo_name}/files/{commit_id}/',
55 'repo_files:default_path': '/{repo_name}/files/{commit_id}/',
54 'repo_files:default_commit': '/{repo_name}/files',
56 'repo_files:default_commit': '/{repo_name}/files',
55 'repo_files:rendered': '/{repo_name}/render/{commit_id}/{f_path}',
57 'repo_files:rendered': '/{repo_name}/render/{commit_id}/{f_path}',
56 'repo_files:annotated': '/{repo_name}/annotate/{commit_id}/{f_path}',
58 'repo_files:annotated': '/{repo_name}/annotate/{commit_id}/{f_path}',
57 'repo_files:annotated_previous': '/{repo_name}/annotate-previous/{commit_id}/{f_path}',
59 'repo_files:annotated_previous': '/{repo_name}/annotate-previous/{commit_id}/{f_path}',
58 'repo_files_nodelist': '/{repo_name}/nodelist/{commit_id}/{f_path}',
60 'repo_files_nodelist': '/{repo_name}/nodelist/{commit_id}/{f_path}',
59 'repo_file_raw': '/{repo_name}/raw/{commit_id}/{f_path}',
61 'repo_file_raw': '/{repo_name}/raw/{commit_id}/{f_path}',
60 'repo_file_download': '/{repo_name}/download/{commit_id}/{f_path}',
62 'repo_file_download': '/{repo_name}/download/{commit_id}/{f_path}',
61 'repo_file_history': '/{repo_name}/history/{commit_id}/{f_path}',
63 'repo_file_history': '/{repo_name}/history/{commit_id}/{f_path}',
62 'repo_file_authors': '/{repo_name}/authors/{commit_id}/{f_path}',
64 'repo_file_authors': '/{repo_name}/authors/{commit_id}/{f_path}',
63 'repo_files_remove_file': '/{repo_name}/remove_file/{commit_id}/{f_path}',
65 'repo_files_remove_file': '/{repo_name}/remove_file/{commit_id}/{f_path}',
64 'repo_files_delete_file': '/{repo_name}/delete_file/{commit_id}/{f_path}',
66 'repo_files_delete_file': '/{repo_name}/delete_file/{commit_id}/{f_path}',
65 'repo_files_edit_file': '/{repo_name}/edit_file/{commit_id}/{f_path}',
67 'repo_files_edit_file': '/{repo_name}/edit_file/{commit_id}/{f_path}',
66 'repo_files_update_file': '/{repo_name}/update_file/{commit_id}/{f_path}',
68 'repo_files_update_file': '/{repo_name}/update_file/{commit_id}/{f_path}',
67 'repo_files_add_file': '/{repo_name}/add_file/{commit_id}/{f_path}',
69 'repo_files_add_file': '/{repo_name}/add_file/{commit_id}/{f_path}',
68 'repo_files_create_file': '/{repo_name}/create_file/{commit_id}/{f_path}',
70 'repo_files_create_file': '/{repo_name}/create_file/{commit_id}/{f_path}',
69 'repo_nodetree_full': '/{repo_name}/nodetree_full/{commit_id}/{f_path}',
71 'repo_nodetree_full': '/{repo_name}/nodetree_full/{commit_id}/{f_path}',
70 'repo_nodetree_full:default_path': '/{repo_name}/nodetree_full/{commit_id}/',
72 'repo_nodetree_full:default_path': '/{repo_name}/nodetree_full/{commit_id}/',
71 }[name].format(**kwargs)
73 }[name].format(**kwargs)
72
74
73 if params:
75 if params:
74 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
76 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
75 return base_url
77 return base_url
76
78
77
79
78 def assert_files_in_response(response, files, params):
80 def assert_files_in_response(response, files, params):
79 template = (
81 template = (
80 'href="/%(repo_name)s/files/%(commit_id)s/%(name)s"')
82 'href="/%(repo_name)s/files/%(commit_id)s/%(name)s"')
81 _assert_items_in_response(response, files, template, params)
83 _assert_items_in_response(response, files, template, params)
82
84
83
85
84 def assert_dirs_in_response(response, dirs, params):
86 def assert_dirs_in_response(response, dirs, params):
85 template = (
87 template = (
86 'href="/%(repo_name)s/files/%(commit_id)s/%(name)s"')
88 'href="/%(repo_name)s/files/%(commit_id)s/%(name)s"')
87 _assert_items_in_response(response, dirs, template, params)
89 _assert_items_in_response(response, dirs, template, params)
88
90
89
91
90 def _assert_items_in_response(response, items, template, params):
92 def _assert_items_in_response(response, items, template, params):
91 for item in items:
93 for item in items:
92 item_params = {'name': item}
94 item_params = {'name': item}
93 item_params.update(params)
95 item_params.update(params)
94 response.mustcontain(template % item_params)
96 response.mustcontain(template % item_params)
95
97
96
98
97 def assert_timeago_in_response(response, items, params):
99 def assert_timeago_in_response(response, items, params):
98 for item in items:
100 for item in items:
99 response.mustcontain(h.age_component(params['date']))
101 response.mustcontain(h.age_component(params['date']))
100
102
101
103
102 @pytest.mark.usefixtures("app")
104 @pytest.mark.usefixtures("app")
103 class TestFilesViews(object):
105 class TestFilesViews(object):
104
106
105 def test_show_files(self, backend):
107 def test_show_files(self, backend):
106 response = self.app.get(
108 response = self.app.get(
107 route_path('repo_files',
109 route_path('repo_files',
108 repo_name=backend.repo_name,
110 repo_name=backend.repo_name,
109 commit_id='tip', f_path='/'))
111 commit_id='tip', f_path='/'))
110 commit = backend.repo.get_commit()
112 commit = backend.repo.get_commit()
111
113
112 params = {
114 params = {
113 'repo_name': backend.repo_name,
115 'repo_name': backend.repo_name,
114 'commit_id': commit.raw_id,
116 'commit_id': commit.raw_id,
115 'date': commit.date
117 'date': commit.date
116 }
118 }
117 assert_dirs_in_response(response, ['docs', 'vcs'], params)
119 assert_dirs_in_response(response, ['docs', 'vcs'], params)
118 files = [
120 files = [
119 '.gitignore',
121 '.gitignore',
120 '.hgignore',
122 '.hgignore',
121 '.hgtags',
123 '.hgtags',
122 # TODO: missing in Git
124 # TODO: missing in Git
123 # '.travis.yml',
125 # '.travis.yml',
124 'MANIFEST.in',
126 'MANIFEST.in',
125 'README.rst',
127 'README.rst',
126 # TODO: File is missing in svn repository
128 # TODO: File is missing in svn repository
127 # 'run_test_and_report.sh',
129 # 'run_test_and_report.sh',
128 'setup.cfg',
130 'setup.cfg',
129 'setup.py',
131 'setup.py',
130 'test_and_report.sh',
132 'test_and_report.sh',
131 'tox.ini',
133 'tox.ini',
132 ]
134 ]
133 assert_files_in_response(response, files, params)
135 assert_files_in_response(response, files, params)
134 assert_timeago_in_response(response, files, params)
136 assert_timeago_in_response(response, files, params)
135
137
136 def test_show_files_links_submodules_with_absolute_url(self, backend_hg):
138 def test_show_files_links_submodules_with_absolute_url(self, backend_hg):
137 repo = backend_hg['subrepos']
139 repo = backend_hg['subrepos']
138 response = self.app.get(
140 response = self.app.get(
139 route_path('repo_files',
141 route_path('repo_files',
140 repo_name=repo.repo_name,
142 repo_name=repo.repo_name,
141 commit_id='tip', f_path='/'))
143 commit_id='tip', f_path='/'))
142 assert_response = response.assert_response()
144 assert_response = response.assert_response()
143 assert_response.contains_one_link(
145 assert_response.contains_one_link(
144 'absolute-path @ 000000000000', 'http://example.com/absolute-path')
146 'absolute-path @ 000000000000', 'http://example.com/absolute-path')
145
147
146 def test_show_files_links_submodules_with_absolute_url_subpaths(
148 def test_show_files_links_submodules_with_absolute_url_subpaths(
147 self, backend_hg):
149 self, backend_hg):
148 repo = backend_hg['subrepos']
150 repo = backend_hg['subrepos']
149 response = self.app.get(
151 response = self.app.get(
150 route_path('repo_files',
152 route_path('repo_files',
151 repo_name=repo.repo_name,
153 repo_name=repo.repo_name,
152 commit_id='tip', f_path='/'))
154 commit_id='tip', f_path='/'))
153 assert_response = response.assert_response()
155 assert_response = response.assert_response()
154 assert_response.contains_one_link(
156 assert_response.contains_one_link(
155 'subpaths-path @ 000000000000',
157 'subpaths-path @ 000000000000',
156 'http://sub-base.example.com/subpaths-path')
158 'http://sub-base.example.com/subpaths-path')
157
159
158 @pytest.mark.xfail_backends("svn", reason="Depends on branch support")
160 @pytest.mark.xfail_backends("svn", reason="Depends on branch support")
159 def test_files_menu(self, backend):
161 def test_files_menu(self, backend):
160 new_branch = "temp_branch_name"
162 new_branch = "temp_branch_name"
161 commits = [
163 commits = [
162 {'message': 'a'},
164 {'message': 'a'},
163 {'message': 'b', 'branch': new_branch}
165 {'message': 'b', 'branch': new_branch}
164 ]
166 ]
165 backend.create_repo(commits)
167 backend.create_repo(commits)
166
168
167 backend.repo.landing_rev = "branch:%s" % new_branch
169 backend.repo.landing_rev = "branch:%s" % new_branch
168
170
169 # get response based on tip and not new commit
171 # get response based on tip and not new commit
170 response = self.app.get(
172 response = self.app.get(
171 route_path('repo_files',
173 route_path('repo_files',
172 repo_name=backend.repo_name,
174 repo_name=backend.repo_name,
173 commit_id='tip', f_path='/'))
175 commit_id='tip', f_path='/'))
174
176
175 # make sure Files menu url is not tip but new commit
177 # make sure Files menu url is not tip but new commit
176 landing_rev = backend.repo.landing_rev[1]
178 landing_rev = backend.repo.landing_rev[1]
177 files_url = route_path('repo_files:default_path',
179 files_url = route_path('repo_files:default_path',
178 repo_name=backend.repo_name,
180 repo_name=backend.repo_name,
179 commit_id=landing_rev)
181 commit_id=landing_rev)
180
182
181 assert landing_rev != 'tip'
183 assert landing_rev != 'tip'
182 response.mustcontain(
184 response.mustcontain(
183 '<li class="active"><a class="menulink" href="%s">' % files_url)
185 '<li class="active"><a class="menulink" href="%s">' % files_url)
184
186
185 def test_show_files_commit(self, backend):
187 def test_show_files_commit(self, backend):
186 commit = backend.repo.get_commit(commit_idx=32)
188 commit = backend.repo.get_commit(commit_idx=32)
187
189
188 response = self.app.get(
190 response = self.app.get(
189 route_path('repo_files',
191 route_path('repo_files',
190 repo_name=backend.repo_name,
192 repo_name=backend.repo_name,
191 commit_id=commit.raw_id, f_path='/'))
193 commit_id=commit.raw_id, f_path='/'))
192
194
193 dirs = ['docs', 'tests']
195 dirs = ['docs', 'tests']
194 files = ['README.rst']
196 files = ['README.rst']
195 params = {
197 params = {
196 'repo_name': backend.repo_name,
198 'repo_name': backend.repo_name,
197 'commit_id': commit.raw_id,
199 'commit_id': commit.raw_id,
198 }
200 }
199 assert_dirs_in_response(response, dirs, params)
201 assert_dirs_in_response(response, dirs, params)
200 assert_files_in_response(response, files, params)
202 assert_files_in_response(response, files, params)
201
203
202 def test_show_files_different_branch(self, backend):
204 def test_show_files_different_branch(self, backend):
203 branches = dict(
205 branches = dict(
204 hg=(150, ['git']),
206 hg=(150, ['git']),
205 # TODO: Git test repository does not contain other branches
207 # TODO: Git test repository does not contain other branches
206 git=(633, ['master']),
208 git=(633, ['master']),
207 # TODO: Branch support in Subversion
209 # TODO: Branch support in Subversion
208 svn=(150, [])
210 svn=(150, [])
209 )
211 )
210 idx, branches = branches[backend.alias]
212 idx, branches = branches[backend.alias]
211 commit = backend.repo.get_commit(commit_idx=idx)
213 commit = backend.repo.get_commit(commit_idx=idx)
212 response = self.app.get(
214 response = self.app.get(
213 route_path('repo_files',
215 route_path('repo_files',
214 repo_name=backend.repo_name,
216 repo_name=backend.repo_name,
215 commit_id=commit.raw_id, f_path='/'))
217 commit_id=commit.raw_id, f_path='/'))
216
218
217 assert_response = response.assert_response()
219 assert_response = response.assert_response()
218 for branch in branches:
220 for branch in branches:
219 assert_response.element_contains('.tags .branchtag', branch)
221 assert_response.element_contains('.tags .branchtag', branch)
220
222
221 def test_show_files_paging(self, backend):
223 def test_show_files_paging(self, backend):
222 repo = backend.repo
224 repo = backend.repo
223 indexes = [73, 92, 109, 1, 0]
225 indexes = [73, 92, 109, 1, 0]
224 idx_map = [(rev, repo.get_commit(commit_idx=rev).raw_id)
226 idx_map = [(rev, repo.get_commit(commit_idx=rev).raw_id)
225 for rev in indexes]
227 for rev in indexes]
226
228
227 for idx in idx_map:
229 for idx in idx_map:
228 response = self.app.get(
230 response = self.app.get(
229 route_path('repo_files',
231 route_path('repo_files',
230 repo_name=backend.repo_name,
232 repo_name=backend.repo_name,
231 commit_id=idx[1], f_path='/'))
233 commit_id=idx[1], f_path='/'))
232
234
233 response.mustcontain("""r%s:%s""" % (idx[0], idx[1][:8]))
235 response.mustcontain("""r%s:%s""" % (idx[0], idx[1][:8]))
234
236
235 def test_file_source(self, backend):
237 def test_file_source(self, backend):
236 commit = backend.repo.get_commit(commit_idx=167)
238 commit = backend.repo.get_commit(commit_idx=167)
237 response = self.app.get(
239 response = self.app.get(
238 route_path('repo_files',
240 route_path('repo_files',
239 repo_name=backend.repo_name,
241 repo_name=backend.repo_name,
240 commit_id=commit.raw_id, f_path='vcs/nodes.py'))
242 commit_id=commit.raw_id, f_path='vcs/nodes.py'))
241
243
242 msgbox = """<div class="commit right-content">%s</div>"""
244 msgbox = """<div class="commit right-content">%s</div>"""
243 response.mustcontain(msgbox % (commit.message, ))
245 response.mustcontain(msgbox % (commit.message, ))
244
246
245 assert_response = response.assert_response()
247 assert_response = response.assert_response()
246 if commit.branch:
248 if commit.branch:
247 assert_response.element_contains(
249 assert_response.element_contains(
248 '.tags.tags-main .branchtag', commit.branch)
250 '.tags.tags-main .branchtag', commit.branch)
249 if commit.tags:
251 if commit.tags:
250 for tag in commit.tags:
252 for tag in commit.tags:
251 assert_response.element_contains('.tags.tags-main .tagtag', tag)
253 assert_response.element_contains('.tags.tags-main .tagtag', tag)
252
254
253 def test_file_source_annotated(self, backend):
255 def test_file_source_annotated(self, backend):
254 response = self.app.get(
256 response = self.app.get(
255 route_path('repo_files:annotated',
257 route_path('repo_files:annotated',
256 repo_name=backend.repo_name,
258 repo_name=backend.repo_name,
257 commit_id='tip', f_path='vcs/nodes.py'))
259 commit_id='tip', f_path='vcs/nodes.py'))
258 expected_commits = {
260 expected_commits = {
259 'hg': 'r356',
261 'hg': 'r356',
260 'git': 'r345',
262 'git': 'r345',
261 'svn': 'r208',
263 'svn': 'r208',
262 }
264 }
263 response.mustcontain(expected_commits[backend.alias])
265 response.mustcontain(expected_commits[backend.alias])
264
266
265 def test_file_source_authors(self, backend):
267 def test_file_source_authors(self, backend):
266 response = self.app.get(
268 response = self.app.get(
267 route_path('repo_file_authors',
269 route_path('repo_file_authors',
268 repo_name=backend.repo_name,
270 repo_name=backend.repo_name,
269 commit_id='tip', f_path='vcs/nodes.py'))
271 commit_id='tip', f_path='vcs/nodes.py'))
270 expected_authors = {
272 expected_authors = {
271 'hg': ('Marcin Kuzminski', 'Lukasz Balcerzak'),
273 'hg': ('Marcin Kuzminski', 'Lukasz Balcerzak'),
272 'git': ('Marcin Kuzminski', 'Lukasz Balcerzak'),
274 'git': ('Marcin Kuzminski', 'Lukasz Balcerzak'),
273 'svn': ('marcin', 'lukasz'),
275 'svn': ('marcin', 'lukasz'),
274 }
276 }
275
277
276 for author in expected_authors[backend.alias]:
278 for author in expected_authors[backend.alias]:
277 response.mustcontain(author)
279 response.mustcontain(author)
278
280
279 def test_file_source_authors_with_annotation(self, backend):
281 def test_file_source_authors_with_annotation(self, backend):
280 response = self.app.get(
282 response = self.app.get(
281 route_path('repo_file_authors',
283 route_path('repo_file_authors',
282 repo_name=backend.repo_name,
284 repo_name=backend.repo_name,
283 commit_id='tip', f_path='vcs/nodes.py',
285 commit_id='tip', f_path='vcs/nodes.py',
284 params=dict(annotate=1)))
286 params=dict(annotate=1)))
285 expected_authors = {
287 expected_authors = {
286 'hg': ('Marcin Kuzminski', 'Lukasz Balcerzak'),
288 'hg': ('Marcin Kuzminski', 'Lukasz Balcerzak'),
287 'git': ('Marcin Kuzminski', 'Lukasz Balcerzak'),
289 'git': ('Marcin Kuzminski', 'Lukasz Balcerzak'),
288 'svn': ('marcin', 'lukasz'),
290 'svn': ('marcin', 'lukasz'),
289 }
291 }
290
292
291 for author in expected_authors[backend.alias]:
293 for author in expected_authors[backend.alias]:
292 response.mustcontain(author)
294 response.mustcontain(author)
293
295
294 def test_file_source_history(self, backend, xhr_header):
296 def test_file_source_history(self, backend, xhr_header):
295 response = self.app.get(
297 response = self.app.get(
296 route_path('repo_file_history',
298 route_path('repo_file_history',
297 repo_name=backend.repo_name,
299 repo_name=backend.repo_name,
298 commit_id='tip', f_path='vcs/nodes.py'),
300 commit_id='tip', f_path='vcs/nodes.py'),
299 extra_environ=xhr_header)
301 extra_environ=xhr_header)
300 assert NODE_HISTORY[backend.alias] == json.loads(response.body)
302 assert get_node_history(backend.alias) == json.loads(response.body)
301
303
302 def test_file_source_history_svn(self, backend_svn, xhr_header):
304 def test_file_source_history_svn(self, backend_svn, xhr_header):
303 simple_repo = backend_svn['svn-simple-layout']
305 simple_repo = backend_svn['svn-simple-layout']
304 response = self.app.get(
306 response = self.app.get(
305 route_path('repo_file_history',
307 route_path('repo_file_history',
306 repo_name=simple_repo.repo_name,
308 repo_name=simple_repo.repo_name,
307 commit_id='tip', f_path='trunk/example.py'),
309 commit_id='tip', f_path='trunk/example.py'),
308 extra_environ=xhr_header)
310 extra_environ=xhr_header)
309
311
310 expected_data = json.loads(
312 expected_data = json.loads(
311 fixture.load_resource('svn_node_history_branches.json'))
313 fixture.load_resource('svn_node_history_branches.json'))
312 assert expected_data == response.json
314 assert expected_data == response.json
313
315
314 def test_file_source_history_with_annotation(self, backend, xhr_header):
316 def test_file_source_history_with_annotation(self, backend, xhr_header):
315 response = self.app.get(
317 response = self.app.get(
316 route_path('repo_file_history',
318 route_path('repo_file_history',
317 repo_name=backend.repo_name,
319 repo_name=backend.repo_name,
318 commit_id='tip', f_path='vcs/nodes.py',
320 commit_id='tip', f_path='vcs/nodes.py',
319 params=dict(annotate=1)),
321 params=dict(annotate=1)),
320
322
321 extra_environ=xhr_header)
323 extra_environ=xhr_header)
322 assert NODE_HISTORY[backend.alias] == json.loads(response.body)
324 assert get_node_history(backend.alias) == json.loads(response.body)
323
325
324 def test_tree_search_top_level(self, backend, xhr_header):
326 def test_tree_search_top_level(self, backend, xhr_header):
325 commit = backend.repo.get_commit(commit_idx=173)
327 commit = backend.repo.get_commit(commit_idx=173)
326 response = self.app.get(
328 response = self.app.get(
327 route_path('repo_files_nodelist',
329 route_path('repo_files_nodelist',
328 repo_name=backend.repo_name,
330 repo_name=backend.repo_name,
329 commit_id=commit.raw_id, f_path='/'),
331 commit_id=commit.raw_id, f_path='/'),
330 extra_environ=xhr_header)
332 extra_environ=xhr_header)
331 assert 'nodes' in response.json
333 assert 'nodes' in response.json
332 assert {'name': 'docs', 'type': 'dir'} in response.json['nodes']
334 assert {'name': 'docs', 'type': 'dir'} in response.json['nodes']
333
335
334 def test_tree_search_missing_xhr(self, backend):
336 def test_tree_search_missing_xhr(self, backend):
335 self.app.get(
337 self.app.get(
336 route_path('repo_files_nodelist',
338 route_path('repo_files_nodelist',
337 repo_name=backend.repo_name,
339 repo_name=backend.repo_name,
338 commit_id='tip', f_path='/'),
340 commit_id='tip', f_path='/'),
339 status=404)
341 status=404)
340
342
341 def test_tree_search_at_path(self, backend, xhr_header):
343 def test_tree_search_at_path(self, backend, xhr_header):
342 commit = backend.repo.get_commit(commit_idx=173)
344 commit = backend.repo.get_commit(commit_idx=173)
343 response = self.app.get(
345 response = self.app.get(
344 route_path('repo_files_nodelist',
346 route_path('repo_files_nodelist',
345 repo_name=backend.repo_name,
347 repo_name=backend.repo_name,
346 commit_id=commit.raw_id, f_path='/docs'),
348 commit_id=commit.raw_id, f_path='/docs'),
347 extra_environ=xhr_header)
349 extra_environ=xhr_header)
348 assert 'nodes' in response.json
350 assert 'nodes' in response.json
349 nodes = response.json['nodes']
351 nodes = response.json['nodes']
350 assert {'name': 'docs/api', 'type': 'dir'} in nodes
352 assert {'name': 'docs/api', 'type': 'dir'} in nodes
351 assert {'name': 'docs/index.rst', 'type': 'file'} in nodes
353 assert {'name': 'docs/index.rst', 'type': 'file'} in nodes
352
354
353 def test_tree_search_at_path_2nd_level(self, backend, xhr_header):
355 def test_tree_search_at_path_2nd_level(self, backend, xhr_header):
354 commit = backend.repo.get_commit(commit_idx=173)
356 commit = backend.repo.get_commit(commit_idx=173)
355 response = self.app.get(
357 response = self.app.get(
356 route_path('repo_files_nodelist',
358 route_path('repo_files_nodelist',
357 repo_name=backend.repo_name,
359 repo_name=backend.repo_name,
358 commit_id=commit.raw_id, f_path='/docs/api'),
360 commit_id=commit.raw_id, f_path='/docs/api'),
359 extra_environ=xhr_header)
361 extra_environ=xhr_header)
360 assert 'nodes' in response.json
362 assert 'nodes' in response.json
361 nodes = response.json['nodes']
363 nodes = response.json['nodes']
362 assert {'name': 'docs/api/index.rst', 'type': 'file'} in nodes
364 assert {'name': 'docs/api/index.rst', 'type': 'file'} in nodes
363
365
364 def test_tree_search_at_path_missing_xhr(self, backend):
366 def test_tree_search_at_path_missing_xhr(self, backend):
365 self.app.get(
367 self.app.get(
366 route_path('repo_files_nodelist',
368 route_path('repo_files_nodelist',
367 repo_name=backend.repo_name,
369 repo_name=backend.repo_name,
368 commit_id='tip', f_path='/docs'),
370 commit_id='tip', f_path='/docs'),
369 status=404)
371 status=404)
370
372
371 def test_nodetree(self, backend, xhr_header):
373 def test_nodetree(self, backend, xhr_header):
372 commit = backend.repo.get_commit(commit_idx=173)
374 commit = backend.repo.get_commit(commit_idx=173)
373 response = self.app.get(
375 response = self.app.get(
374 route_path('repo_nodetree_full',
376 route_path('repo_nodetree_full',
375 repo_name=backend.repo_name,
377 repo_name=backend.repo_name,
376 commit_id=commit.raw_id, f_path='/'),
378 commit_id=commit.raw_id, f_path='/'),
377 extra_environ=xhr_header)
379 extra_environ=xhr_header)
378
380
379 assert_response = response.assert_response()
381 assert_response = response.assert_response()
380
382
381 for attr in ['data-commit-id', 'data-date', 'data-author']:
383 for attr in ['data-commit-id', 'data-date', 'data-author']:
382 elements = assert_response.get_elements('[{}]'.format(attr))
384 elements = assert_response.get_elements('[{}]'.format(attr))
383 assert len(elements) > 1
385 assert len(elements) > 1
384
386
385 for element in elements:
387 for element in elements:
386 assert element.get(attr)
388 assert element.get(attr)
387
389
388 def test_nodetree_if_file(self, backend, xhr_header):
390 def test_nodetree_if_file(self, backend, xhr_header):
389 commit = backend.repo.get_commit(commit_idx=173)
391 commit = backend.repo.get_commit(commit_idx=173)
390 response = self.app.get(
392 response = self.app.get(
391 route_path('repo_nodetree_full',
393 route_path('repo_nodetree_full',
392 repo_name=backend.repo_name,
394 repo_name=backend.repo_name,
393 commit_id=commit.raw_id, f_path='README.rst'),
395 commit_id=commit.raw_id, f_path='README.rst'),
394 extra_environ=xhr_header)
396 extra_environ=xhr_header)
395 assert response.body == ''
397 assert response.body == ''
396
398
397 def test_nodetree_wrong_path(self, backend, xhr_header):
399 def test_nodetree_wrong_path(self, backend, xhr_header):
398 commit = backend.repo.get_commit(commit_idx=173)
400 commit = backend.repo.get_commit(commit_idx=173)
399 response = self.app.get(
401 response = self.app.get(
400 route_path('repo_nodetree_full',
402 route_path('repo_nodetree_full',
401 repo_name=backend.repo_name,
403 repo_name=backend.repo_name,
402 commit_id=commit.raw_id, f_path='/dont-exist'),
404 commit_id=commit.raw_id, f_path='/dont-exist'),
403 extra_environ=xhr_header)
405 extra_environ=xhr_header)
404
406
405 err = 'error: There is no file nor ' \
407 err = 'error: There is no file nor ' \
406 'directory at the given path'
408 'directory at the given path'
407 assert err in response.body
409 assert err in response.body
408
410
409 def test_nodetree_missing_xhr(self, backend):
411 def test_nodetree_missing_xhr(self, backend):
410 self.app.get(
412 self.app.get(
411 route_path('repo_nodetree_full',
413 route_path('repo_nodetree_full',
412 repo_name=backend.repo_name,
414 repo_name=backend.repo_name,
413 commit_id='tip', f_path='/'),
415 commit_id='tip', f_path='/'),
414 status=404)
416 status=404)
415
417
416
418
417 @pytest.mark.usefixtures("app", "autologin_user")
419 @pytest.mark.usefixtures("app", "autologin_user")
418 class TestRawFileHandling(object):
420 class TestRawFileHandling(object):
419
421
420 def test_download_file(self, backend):
422 def test_download_file(self, backend):
421 commit = backend.repo.get_commit(commit_idx=173)
423 commit = backend.repo.get_commit(commit_idx=173)
422 response = self.app.get(
424 response = self.app.get(
423 route_path('repo_file_download',
425 route_path('repo_file_download',
424 repo_name=backend.repo_name,
426 repo_name=backend.repo_name,
425 commit_id=commit.raw_id, f_path='vcs/nodes.py'),)
427 commit_id=commit.raw_id, f_path='vcs/nodes.py'),)
426
428
427 assert response.content_disposition == "attachment; filename=nodes.py"
429 assert response.content_disposition == "attachment; filename=nodes.py"
428 assert response.content_type == "text/x-python"
430 assert response.content_type == "text/x-python"
429
431
430 def test_download_file_wrong_cs(self, backend):
432 def test_download_file_wrong_cs(self, backend):
431 raw_id = u'ERRORce30c96924232dffcd24178a07ffeb5dfc'
433 raw_id = u'ERRORce30c96924232dffcd24178a07ffeb5dfc'
432
434
433 response = self.app.get(
435 response = self.app.get(
434 route_path('repo_file_download',
436 route_path('repo_file_download',
435 repo_name=backend.repo_name,
437 repo_name=backend.repo_name,
436 commit_id=raw_id, f_path='vcs/nodes.svg'),
438 commit_id=raw_id, f_path='vcs/nodes.svg'),
437 status=404)
439 status=404)
438
440
439 msg = """No such commit exists for this repository"""
441 msg = """No such commit exists for this repository"""
440 response.mustcontain(msg)
442 response.mustcontain(msg)
441
443
442 def test_download_file_wrong_f_path(self, backend):
444 def test_download_file_wrong_f_path(self, backend):
443 commit = backend.repo.get_commit(commit_idx=173)
445 commit = backend.repo.get_commit(commit_idx=173)
444 f_path = 'vcs/ERRORnodes.py'
446 f_path = 'vcs/ERRORnodes.py'
445
447
446 response = self.app.get(
448 response = self.app.get(
447 route_path('repo_file_download',
449 route_path('repo_file_download',
448 repo_name=backend.repo_name,
450 repo_name=backend.repo_name,
449 commit_id=commit.raw_id, f_path=f_path),
451 commit_id=commit.raw_id, f_path=f_path),
450 status=404)
452 status=404)
451
453
452 msg = (
454 msg = (
453 "There is no file nor directory at the given path: "
455 "There is no file nor directory at the given path: "
454 "`%s` at commit %s" % (f_path, commit.short_id))
456 "`%s` at commit %s" % (f_path, commit.short_id))
455 response.mustcontain(msg)
457 response.mustcontain(msg)
456
458
457 def test_file_raw(self, backend):
459 def test_file_raw(self, backend):
458 commit = backend.repo.get_commit(commit_idx=173)
460 commit = backend.repo.get_commit(commit_idx=173)
459 response = self.app.get(
461 response = self.app.get(
460 route_path('repo_file_raw',
462 route_path('repo_file_raw',
461 repo_name=backend.repo_name,
463 repo_name=backend.repo_name,
462 commit_id=commit.raw_id, f_path='vcs/nodes.py'),)
464 commit_id=commit.raw_id, f_path='vcs/nodes.py'),)
463
465
464 assert response.content_type == "text/plain"
466 assert response.content_type == "text/plain"
465
467
466 def test_file_raw_binary(self, backend):
468 def test_file_raw_binary(self, backend):
467 commit = backend.repo.get_commit()
469 commit = backend.repo.get_commit()
468 response = self.app.get(
470 response = self.app.get(
469 route_path('repo_file_raw',
471 route_path('repo_file_raw',
470 repo_name=backend.repo_name,
472 repo_name=backend.repo_name,
471 commit_id=commit.raw_id,
473 commit_id=commit.raw_id,
472 f_path='docs/theme/ADC/static/breadcrumb_background.png'),)
474 f_path='docs/theme/ADC/static/breadcrumb_background.png'),)
473
475
474 assert response.content_disposition == 'inline'
476 assert response.content_disposition == 'inline'
475
477
476 def test_raw_file_wrong_cs(self, backend):
478 def test_raw_file_wrong_cs(self, backend):
477 raw_id = u'ERRORcce30c96924232dffcd24178a07ffeb5dfc'
479 raw_id = u'ERRORcce30c96924232dffcd24178a07ffeb5dfc'
478
480
479 response = self.app.get(
481 response = self.app.get(
480 route_path('repo_file_raw',
482 route_path('repo_file_raw',
481 repo_name=backend.repo_name,
483 repo_name=backend.repo_name,
482 commit_id=raw_id, f_path='vcs/nodes.svg'),
484 commit_id=raw_id, f_path='vcs/nodes.svg'),
483 status=404)
485 status=404)
484
486
485 msg = """No such commit exists for this repository"""
487 msg = """No such commit exists for this repository"""
486 response.mustcontain(msg)
488 response.mustcontain(msg)
487
489
488 def test_raw_wrong_f_path(self, backend):
490 def test_raw_wrong_f_path(self, backend):
489 commit = backend.repo.get_commit(commit_idx=173)
491 commit = backend.repo.get_commit(commit_idx=173)
490 f_path = 'vcs/ERRORnodes.py'
492 f_path = 'vcs/ERRORnodes.py'
491 response = self.app.get(
493 response = self.app.get(
492 route_path('repo_file_raw',
494 route_path('repo_file_raw',
493 repo_name=backend.repo_name,
495 repo_name=backend.repo_name,
494 commit_id=commit.raw_id, f_path=f_path),
496 commit_id=commit.raw_id, f_path=f_path),
495 status=404)
497 status=404)
496
498
497 msg = (
499 msg = (
498 "There is no file nor directory at the given path: "
500 "There is no file nor directory at the given path: "
499 "`%s` at commit %s" % (f_path, commit.short_id))
501 "`%s` at commit %s" % (f_path, commit.short_id))
500 response.mustcontain(msg)
502 response.mustcontain(msg)
501
503
502 def test_raw_svg_should_not_be_rendered(self, backend):
504 def test_raw_svg_should_not_be_rendered(self, backend):
503 backend.create_repo()
505 backend.create_repo()
504 backend.ensure_file("xss.svg")
506 backend.ensure_file("xss.svg")
505 response = self.app.get(
507 response = self.app.get(
506 route_path('repo_file_raw',
508 route_path('repo_file_raw',
507 repo_name=backend.repo_name,
509 repo_name=backend.repo_name,
508 commit_id='tip', f_path='xss.svg'),)
510 commit_id='tip', f_path='xss.svg'),)
509 # If the content type is image/svg+xml then it allows to render HTML
511 # If the content type is image/svg+xml then it allows to render HTML
510 # and malicious SVG.
512 # and malicious SVG.
511 assert response.content_type == "text/plain"
513 assert response.content_type == "text/plain"
512
514
513
515
514 @pytest.mark.usefixtures("app")
516 @pytest.mark.usefixtures("app")
515 class TestRepositoryArchival(object):
517 class TestRepositoryArchival(object):
516
518
517 def test_archival(self, backend):
519 def test_archival(self, backend):
518 backend.enable_downloads()
520 backend.enable_downloads()
519 commit = backend.repo.get_commit(commit_idx=173)
521 commit = backend.repo.get_commit(commit_idx=173)
520 for archive, info in settings.ARCHIVE_SPECS.items():
522 for archive, info in settings.ARCHIVE_SPECS.items():
521 mime_type, arch_ext = info
523 mime_type, arch_ext = info
522 short = commit.short_id + arch_ext
524 short = commit.short_id + arch_ext
523 fname = commit.raw_id + arch_ext
525 fname = commit.raw_id + arch_ext
524 filename = '%s-%s' % (backend.repo_name, short)
526 filename = '%s-%s' % (backend.repo_name, short)
525 response = self.app.get(
527 response = self.app.get(
526 route_path('repo_archivefile',
528 route_path('repo_archivefile',
527 repo_name=backend.repo_name,
529 repo_name=backend.repo_name,
528 fname=fname))
530 fname=fname))
529
531
530 assert response.status == '200 OK'
532 assert response.status == '200 OK'
531 headers = [
533 headers = [
532 ('Content-Disposition', 'attachment; filename=%s' % filename),
534 ('Content-Disposition', 'attachment; filename=%s' % filename),
533 ('Content-Type', '%s' % mime_type),
535 ('Content-Type', '%s' % mime_type),
534 ]
536 ]
535
537
536 for header in headers:
538 for header in headers:
537 assert header in response.headers.items()
539 assert header in response.headers.items()
538
540
539 @pytest.mark.parametrize('arch_ext',[
541 @pytest.mark.parametrize('arch_ext',[
540 'tar', 'rar', 'x', '..ax', '.zipz', 'tar.gz.tar'])
542 'tar', 'rar', 'x', '..ax', '.zipz', 'tar.gz.tar'])
541 def test_archival_wrong_ext(self, backend, arch_ext):
543 def test_archival_wrong_ext(self, backend, arch_ext):
542 backend.enable_downloads()
544 backend.enable_downloads()
543 commit = backend.repo.get_commit(commit_idx=173)
545 commit = backend.repo.get_commit(commit_idx=173)
544
546
545 fname = commit.raw_id + '.' + arch_ext
547 fname = commit.raw_id + '.' + arch_ext
546
548
547 response = self.app.get(
549 response = self.app.get(
548 route_path('repo_archivefile',
550 route_path('repo_archivefile',
549 repo_name=backend.repo_name,
551 repo_name=backend.repo_name,
550 fname=fname))
552 fname=fname))
551 response.mustcontain(
553 response.mustcontain(
552 'Unknown archive type for: `{}`'.format(fname))
554 'Unknown archive type for: `{}`'.format(fname))
553
555
554 @pytest.mark.parametrize('commit_id', [
556 @pytest.mark.parametrize('commit_id', [
555 '00x000000', 'tar', 'wrong', '@$@$42413232', '232dffcd'])
557 '00x000000', 'tar', 'wrong', '@$@$42413232', '232dffcd'])
556 def test_archival_wrong_commit_id(self, backend, commit_id):
558 def test_archival_wrong_commit_id(self, backend, commit_id):
557 backend.enable_downloads()
559 backend.enable_downloads()
558 fname = '%s.zip' % commit_id
560 fname = '%s.zip' % commit_id
559
561
560 response = self.app.get(
562 response = self.app.get(
561 route_path('repo_archivefile',
563 route_path('repo_archivefile',
562 repo_name=backend.repo_name,
564 repo_name=backend.repo_name,
563 fname=fname))
565 fname=fname))
564 response.mustcontain('Unknown commit_id')
566 response.mustcontain('Unknown commit_id')
565
567
566
568
567 @pytest.mark.usefixtures("app")
569 @pytest.mark.usefixtures("app")
568 class TestFilesDiff(object):
570 class TestFilesDiff(object):
569
571
570 @pytest.mark.parametrize("diff", ['diff', 'download', 'raw'])
572 @pytest.mark.parametrize("diff", ['diff', 'download', 'raw'])
571 def test_file_full_diff(self, backend, diff):
573 def test_file_full_diff(self, backend, diff):
572 commit1 = backend.repo.get_commit(commit_idx=-1)
574 commit1 = backend.repo.get_commit(commit_idx=-1)
573 commit2 = backend.repo.get_commit(commit_idx=-2)
575 commit2 = backend.repo.get_commit(commit_idx=-2)
574
576
575 response = self.app.get(
577 response = self.app.get(
576 route_path('repo_files_diff',
578 route_path('repo_files_diff',
577 repo_name=backend.repo_name,
579 repo_name=backend.repo_name,
578 f_path='README'),
580 f_path='README'),
579 params={
581 params={
580 'diff1': commit2.raw_id,
582 'diff1': commit2.raw_id,
581 'diff2': commit1.raw_id,
583 'diff2': commit1.raw_id,
582 'fulldiff': '1',
584 'fulldiff': '1',
583 'diff': diff,
585 'diff': diff,
584 })
586 })
585
587
586 if diff == 'diff':
588 if diff == 'diff':
587 # use redirect since this is OLD view redirecting to compare page
589 # use redirect since this is OLD view redirecting to compare page
588 response = response.follow()
590 response = response.follow()
589
591
590 # It's a symlink to README.rst
592 # It's a symlink to README.rst
591 response.mustcontain('README.rst')
593 response.mustcontain('README.rst')
592 response.mustcontain('No newline at end of file')
594 response.mustcontain('No newline at end of file')
593
595
594 def test_file_binary_diff(self, backend):
596 def test_file_binary_diff(self, backend):
595 commits = [
597 commits = [
596 {'message': 'First commit'},
598 {'message': 'First commit'},
597 {'message': 'Commit with binary',
599 {'message': 'Commit with binary',
598 'added': [nodes.FileNode('file.bin', content='\0BINARY\0')]},
600 'added': [nodes.FileNode('file.bin', content='\0BINARY\0')]},
599 ]
601 ]
600 repo = backend.create_repo(commits=commits)
602 repo = backend.create_repo(commits=commits)
601
603
602 response = self.app.get(
604 response = self.app.get(
603 route_path('repo_files_diff',
605 route_path('repo_files_diff',
604 repo_name=backend.repo_name,
606 repo_name=backend.repo_name,
605 f_path='file.bin'),
607 f_path='file.bin'),
606 params={
608 params={
607 'diff1': repo.get_commit(commit_idx=0).raw_id,
609 'diff1': repo.get_commit(commit_idx=0).raw_id,
608 'diff2': repo.get_commit(commit_idx=1).raw_id,
610 'diff2': repo.get_commit(commit_idx=1).raw_id,
609 'fulldiff': '1',
611 'fulldiff': '1',
610 'diff': 'diff',
612 'diff': 'diff',
611 })
613 })
612 # use redirect since this is OLD view redirecting to compare page
614 # use redirect since this is OLD view redirecting to compare page
613 response = response.follow()
615 response = response.follow()
614 response.mustcontain('Expand 1 commit')
616 response.mustcontain('Expand 1 commit')
615 response.mustcontain('1 file changed: 0 inserted, 0 deleted')
617 response.mustcontain('1 file changed: 0 inserted, 0 deleted')
616
618
617 if backend.alias == 'svn':
619 if backend.alias == 'svn':
618 response.mustcontain('new file 10644')
620 response.mustcontain('new file 10644')
619 # TODO(marcink): SVN doesn't yet detect binary changes
621 # TODO(marcink): SVN doesn't yet detect binary changes
620 else:
622 else:
621 response.mustcontain('new file 100644')
623 response.mustcontain('new file 100644')
622 response.mustcontain('binary diff hidden')
624 response.mustcontain('binary diff hidden')
623
625
624 def test_diff_2way(self, backend):
626 def test_diff_2way(self, backend):
625 commit1 = backend.repo.get_commit(commit_idx=-1)
627 commit1 = backend.repo.get_commit(commit_idx=-1)
626 commit2 = backend.repo.get_commit(commit_idx=-2)
628 commit2 = backend.repo.get_commit(commit_idx=-2)
627 response = self.app.get(
629 response = self.app.get(
628 route_path('repo_files_diff_2way_redirect',
630 route_path('repo_files_diff_2way_redirect',
629 repo_name=backend.repo_name,
631 repo_name=backend.repo_name,
630 f_path='README'),
632 f_path='README'),
631 params={
633 params={
632 'diff1': commit2.raw_id,
634 'diff1': commit2.raw_id,
633 'diff2': commit1.raw_id,
635 'diff2': commit1.raw_id,
634 })
636 })
635 # use redirect since this is OLD view redirecting to compare page
637 # use redirect since this is OLD view redirecting to compare page
636 response = response.follow()
638 response = response.follow()
637
639
638 # It's a symlink to README.rst
640 # It's a symlink to README.rst
639 response.mustcontain('README.rst')
641 response.mustcontain('README.rst')
640 response.mustcontain('No newline at end of file')
642 response.mustcontain('No newline at end of file')
641
643
642 def test_requires_one_commit_id(self, backend, autologin_user):
644 def test_requires_one_commit_id(self, backend, autologin_user):
643 response = self.app.get(
645 response = self.app.get(
644 route_path('repo_files_diff',
646 route_path('repo_files_diff',
645 repo_name=backend.repo_name,
647 repo_name=backend.repo_name,
646 f_path='README.rst'),
648 f_path='README.rst'),
647 status=400)
649 status=400)
648 response.mustcontain(
650 response.mustcontain(
649 'Need query parameter', 'diff1', 'diff2', 'to generate a diff.')
651 'Need query parameter', 'diff1', 'diff2', 'to generate a diff.')
650
652
651 def test_returns_no_files_if_file_does_not_exist(self, vcsbackend):
653 def test_returns_no_files_if_file_does_not_exist(self, vcsbackend):
652 repo = vcsbackend.repo
654 repo = vcsbackend.repo
653 response = self.app.get(
655 response = self.app.get(
654 route_path('repo_files_diff',
656 route_path('repo_files_diff',
655 repo_name=repo.name,
657 repo_name=repo.name,
656 f_path='does-not-exist-in-any-commit'),
658 f_path='does-not-exist-in-any-commit'),
657 params={
659 params={
658 'diff1': repo[0].raw_id,
660 'diff1': repo[0].raw_id,
659 'diff2': repo[1].raw_id
661 'diff2': repo[1].raw_id
660 })
662 })
661
663
662 response = response.follow()
664 response = response.follow()
663 response.mustcontain('No files')
665 response.mustcontain('No files')
664
666
665 def test_returns_redirect_if_file_not_changed(self, backend):
667 def test_returns_redirect_if_file_not_changed(self, backend):
666 commit = backend.repo.get_commit(commit_idx=-1)
668 commit = backend.repo.get_commit(commit_idx=-1)
667 response = self.app.get(
669 response = self.app.get(
668 route_path('repo_files_diff_2way_redirect',
670 route_path('repo_files_diff_2way_redirect',
669 repo_name=backend.repo_name,
671 repo_name=backend.repo_name,
670 f_path='README'),
672 f_path='README'),
671 params={
673 params={
672 'diff1': commit.raw_id,
674 'diff1': commit.raw_id,
673 'diff2': commit.raw_id,
675 'diff2': commit.raw_id,
674 })
676 })
675
677
676 response = response.follow()
678 response = response.follow()
677 response.mustcontain('No files')
679 response.mustcontain('No files')
678 response.mustcontain('No commits in this compare')
680 response.mustcontain('No commits in this compare')
679
681
680 def test_supports_diff_to_different_path_svn(self, backend_svn):
682 def test_supports_diff_to_different_path_svn(self, backend_svn):
681 #TODO: check this case
683 #TODO: check this case
682 return
684 return
683
685
684 repo = backend_svn['svn-simple-layout'].scm_instance()
686 repo = backend_svn['svn-simple-layout'].scm_instance()
685 commit_id_1 = '24'
687 commit_id_1 = '24'
686 commit_id_2 = '26'
688 commit_id_2 = '26'
687
689
688 response = self.app.get(
690 response = self.app.get(
689 route_path('repo_files_diff',
691 route_path('repo_files_diff',
690 repo_name=backend_svn.repo_name,
692 repo_name=backend_svn.repo_name,
691 f_path='trunk/example.py'),
693 f_path='trunk/example.py'),
692 params={
694 params={
693 'diff1': 'tags/v0.2/example.py@' + commit_id_1,
695 'diff1': 'tags/v0.2/example.py@' + commit_id_1,
694 'diff2': commit_id_2,
696 'diff2': commit_id_2,
695 })
697 })
696
698
697 response = response.follow()
699 response = response.follow()
698 response.mustcontain(
700 response.mustcontain(
699 # diff contains this
701 # diff contains this
700 "Will print out a useful message on invocation.")
702 "Will print out a useful message on invocation.")
701
703
702 # Note: Expecting that we indicate the user what's being compared
704 # Note: Expecting that we indicate the user what's being compared
703 response.mustcontain("trunk/example.py")
705 response.mustcontain("trunk/example.py")
704 response.mustcontain("tags/v0.2/example.py")
706 response.mustcontain("tags/v0.2/example.py")
705
707
706 def test_show_rev_redirects_to_svn_path(self, backend_svn):
708 def test_show_rev_redirects_to_svn_path(self, backend_svn):
707 #TODO: check this case
709 #TODO: check this case
708 return
710 return
709
711
710 repo = backend_svn['svn-simple-layout'].scm_instance()
712 repo = backend_svn['svn-simple-layout'].scm_instance()
711 commit_id = repo[-1].raw_id
713 commit_id = repo[-1].raw_id
712
714
713 response = self.app.get(
715 response = self.app.get(
714 route_path('repo_files_diff',
716 route_path('repo_files_diff',
715 repo_name=backend_svn.repo_name,
717 repo_name=backend_svn.repo_name,
716 f_path='trunk/example.py'),
718 f_path='trunk/example.py'),
717 params={
719 params={
718 'diff1': 'branches/argparse/example.py@' + commit_id,
720 'diff1': 'branches/argparse/example.py@' + commit_id,
719 'diff2': commit_id,
721 'diff2': commit_id,
720 },
722 },
721 status=302)
723 status=302)
722 response = response.follow()
724 response = response.follow()
723 assert response.headers['Location'].endswith(
725 assert response.headers['Location'].endswith(
724 'svn-svn-simple-layout/files/26/branches/argparse/example.py')
726 'svn-svn-simple-layout/files/26/branches/argparse/example.py')
725
727
726 def test_show_rev_and_annotate_redirects_to_svn_path(self, backend_svn):
728 def test_show_rev_and_annotate_redirects_to_svn_path(self, backend_svn):
727 #TODO: check this case
729 #TODO: check this case
728 return
730 return
729
731
730 repo = backend_svn['svn-simple-layout'].scm_instance()
732 repo = backend_svn['svn-simple-layout'].scm_instance()
731 commit_id = repo[-1].raw_id
733 commit_id = repo[-1].raw_id
732 response = self.app.get(
734 response = self.app.get(
733 route_path('repo_files_diff',
735 route_path('repo_files_diff',
734 repo_name=backend_svn.repo_name,
736 repo_name=backend_svn.repo_name,
735 f_path='trunk/example.py'),
737 f_path='trunk/example.py'),
736 params={
738 params={
737 'diff1': 'branches/argparse/example.py@' + commit_id,
739 'diff1': 'branches/argparse/example.py@' + commit_id,
738 'diff2': commit_id,
740 'diff2': commit_id,
739 'show_rev': 'Show at Revision',
741 'show_rev': 'Show at Revision',
740 'annotate': 'true',
742 'annotate': 'true',
741 },
743 },
742 status=302)
744 status=302)
743 response = response.follow()
745 response = response.follow()
744 assert response.headers['Location'].endswith(
746 assert response.headers['Location'].endswith(
745 'svn-svn-simple-layout/annotate/26/branches/argparse/example.py')
747 'svn-svn-simple-layout/annotate/26/branches/argparse/example.py')
746
748
747
749
748 @pytest.mark.usefixtures("app", "autologin_user")
750 @pytest.mark.usefixtures("app", "autologin_user")
749 class TestModifyFilesWithWebInterface(object):
751 class TestModifyFilesWithWebInterface(object):
750
752
751 def test_add_file_view(self, backend):
753 def test_add_file_view(self, backend):
752 self.app.get(
754 self.app.get(
753 route_path('repo_files_add_file',
755 route_path('repo_files_add_file',
754 repo_name=backend.repo_name,
756 repo_name=backend.repo_name,
755 commit_id='tip', f_path='/')
757 commit_id='tip', f_path='/')
756 )
758 )
757
759
758 @pytest.mark.xfail_backends("svn", reason="Depends on online editing")
760 @pytest.mark.xfail_backends("svn", reason="Depends on online editing")
759 def test_add_file_into_repo_missing_content(self, backend, csrf_token):
761 def test_add_file_into_repo_missing_content(self, backend, csrf_token):
760 repo = backend.create_repo()
762 repo = backend.create_repo()
761 filename = 'init.py'
763 filename = 'init.py'
762 response = self.app.post(
764 response = self.app.post(
763 route_path('repo_files_create_file',
765 route_path('repo_files_create_file',
764 repo_name=backend.repo_name,
766 repo_name=backend.repo_name,
765 commit_id='tip', f_path='/'),
767 commit_id='tip', f_path='/'),
766 params={
768 params={
767 'content': "",
769 'content': "",
768 'filename': filename,
770 'filename': filename,
769 'location': "",
771 'location': "",
770 'csrf_token': csrf_token,
772 'csrf_token': csrf_token,
771 },
773 },
772 status=302)
774 status=302)
773 assert_session_flash(response,
775 assert_session_flash(response,
774 'Successfully committed new file `{}`'.format(
776 'Successfully committed new file `{}`'.format(
775 os.path.join(filename)))
777 os.path.join(filename)))
776
778
777 def test_add_file_into_repo_missing_filename(self, backend, csrf_token):
779 def test_add_file_into_repo_missing_filename(self, backend, csrf_token):
778 response = self.app.post(
780 response = self.app.post(
779 route_path('repo_files_create_file',
781 route_path('repo_files_create_file',
780 repo_name=backend.repo_name,
782 repo_name=backend.repo_name,
781 commit_id='tip', f_path='/'),
783 commit_id='tip', f_path='/'),
782 params={
784 params={
783 'content': "foo",
785 'content': "foo",
784 'csrf_token': csrf_token,
786 'csrf_token': csrf_token,
785 },
787 },
786 status=302)
788 status=302)
787
789
788 assert_session_flash(response, 'No filename')
790 assert_session_flash(response, 'No filename')
789
791
790 def test_add_file_into_repo_errors_and_no_commits(
792 def test_add_file_into_repo_errors_and_no_commits(
791 self, backend, csrf_token):
793 self, backend, csrf_token):
792 repo = backend.create_repo()
794 repo = backend.create_repo()
793 # Create a file with no filename, it will display an error but
795 # Create a file with no filename, it will display an error but
794 # the repo has no commits yet
796 # the repo has no commits yet
795 response = self.app.post(
797 response = self.app.post(
796 route_path('repo_files_create_file',
798 route_path('repo_files_create_file',
797 repo_name=repo.repo_name,
799 repo_name=repo.repo_name,
798 commit_id='tip', f_path='/'),
800 commit_id='tip', f_path='/'),
799 params={
801 params={
800 'content': "foo",
802 'content': "foo",
801 'csrf_token': csrf_token,
803 'csrf_token': csrf_token,
802 },
804 },
803 status=302)
805 status=302)
804
806
805 assert_session_flash(response, 'No filename')
807 assert_session_flash(response, 'No filename')
806
808
807 # Not allowed, redirect to the summary
809 # Not allowed, redirect to the summary
808 redirected = response.follow()
810 redirected = response.follow()
809 summary_url = h.route_path('repo_summary', repo_name=repo.repo_name)
811 summary_url = h.route_path('repo_summary', repo_name=repo.repo_name)
810
812
811 # As there are no commits, displays the summary page with the error of
813 # As there are no commits, displays the summary page with the error of
812 # creating a file with no filename
814 # creating a file with no filename
813
815
814 assert redirected.request.path == summary_url
816 assert redirected.request.path == summary_url
815
817
816 @pytest.mark.parametrize("location, filename", [
818 @pytest.mark.parametrize("location, filename", [
817 ('/abs', 'foo'),
819 ('/abs', 'foo'),
818 ('../rel', 'foo'),
820 ('../rel', 'foo'),
819 ('file/../foo', 'foo'),
821 ('file/../foo', 'foo'),
820 ])
822 ])
821 def test_add_file_into_repo_bad_filenames(
823 def test_add_file_into_repo_bad_filenames(
822 self, location, filename, backend, csrf_token):
824 self, location, filename, backend, csrf_token):
823 response = self.app.post(
825 response = self.app.post(
824 route_path('repo_files_create_file',
826 route_path('repo_files_create_file',
825 repo_name=backend.repo_name,
827 repo_name=backend.repo_name,
826 commit_id='tip', f_path='/'),
828 commit_id='tip', f_path='/'),
827 params={
829 params={
828 'content': "foo",
830 'content': "foo",
829 'filename': filename,
831 'filename': filename,
830 'location': location,
832 'location': location,
831 'csrf_token': csrf_token,
833 'csrf_token': csrf_token,
832 },
834 },
833 status=302)
835 status=302)
834
836
835 assert_session_flash(
837 assert_session_flash(
836 response,
838 response,
837 'The location specified must be a relative path and must not '
839 'The location specified must be a relative path and must not '
838 'contain .. in the path')
840 'contain .. in the path')
839
841
840 @pytest.mark.parametrize("cnt, location, filename", [
842 @pytest.mark.parametrize("cnt, location, filename", [
841 (1, '', 'foo.txt'),
843 (1, '', 'foo.txt'),
842 (2, 'dir', 'foo.rst'),
844 (2, 'dir', 'foo.rst'),
843 (3, 'rel/dir', 'foo.bar'),
845 (3, 'rel/dir', 'foo.bar'),
844 ])
846 ])
845 def test_add_file_into_repo(self, cnt, location, filename, backend,
847 def test_add_file_into_repo(self, cnt, location, filename, backend,
846 csrf_token):
848 csrf_token):
847 repo = backend.create_repo()
849 repo = backend.create_repo()
848 response = self.app.post(
850 response = self.app.post(
849 route_path('repo_files_create_file',
851 route_path('repo_files_create_file',
850 repo_name=repo.repo_name,
852 repo_name=repo.repo_name,
851 commit_id='tip', f_path='/'),
853 commit_id='tip', f_path='/'),
852 params={
854 params={
853 'content': "foo",
855 'content': "foo",
854 'filename': filename,
856 'filename': filename,
855 'location': location,
857 'location': location,
856 'csrf_token': csrf_token,
858 'csrf_token': csrf_token,
857 },
859 },
858 status=302)
860 status=302)
859 assert_session_flash(response,
861 assert_session_flash(response,
860 'Successfully committed new file `{}`'.format(
862 'Successfully committed new file `{}`'.format(
861 os.path.join(location, filename)))
863 os.path.join(location, filename)))
862
864
863 def test_edit_file_view(self, backend):
865 def test_edit_file_view(self, backend):
864 response = self.app.get(
866 response = self.app.get(
865 route_path('repo_files_edit_file',
867 route_path('repo_files_edit_file',
866 repo_name=backend.repo_name,
868 repo_name=backend.repo_name,
867 commit_id=backend.default_head_id,
869 commit_id=backend.default_head_id,
868 f_path='vcs/nodes.py'),
870 f_path='vcs/nodes.py'),
869 status=200)
871 status=200)
870 response.mustcontain("Module holding everything related to vcs nodes.")
872 response.mustcontain("Module holding everything related to vcs nodes.")
871
873
872 def test_edit_file_view_not_on_branch(self, backend):
874 def test_edit_file_view_not_on_branch(self, backend):
873 repo = backend.create_repo()
875 repo = backend.create_repo()
874 backend.ensure_file("vcs/nodes.py")
876 backend.ensure_file("vcs/nodes.py")
875
877
876 response = self.app.get(
878 response = self.app.get(
877 route_path('repo_files_edit_file',
879 route_path('repo_files_edit_file',
878 repo_name=repo.repo_name,
880 repo_name=repo.repo_name,
879 commit_id='tip',
881 commit_id='tip',
880 f_path='vcs/nodes.py'),
882 f_path='vcs/nodes.py'),
881 status=302)
883 status=302)
882 assert_session_flash(
884 assert_session_flash(
883 response,
885 response,
884 'You can only edit files with commit being a valid branch')
886 'You can only edit files with commit being a valid branch')
885
887
886 def test_edit_file_view_commit_changes(self, backend, csrf_token):
888 def test_edit_file_view_commit_changes(self, backend, csrf_token):
887 repo = backend.create_repo()
889 repo = backend.create_repo()
888 backend.ensure_file("vcs/nodes.py", content="print 'hello'")
890 backend.ensure_file("vcs/nodes.py", content="print 'hello'")
889
891
890 response = self.app.post(
892 response = self.app.post(
891 route_path('repo_files_update_file',
893 route_path('repo_files_update_file',
892 repo_name=repo.repo_name,
894 repo_name=repo.repo_name,
893 commit_id=backend.default_head_id,
895 commit_id=backend.default_head_id,
894 f_path='vcs/nodes.py'),
896 f_path='vcs/nodes.py'),
895 params={
897 params={
896 'content': "print 'hello world'",
898 'content': "print 'hello world'",
897 'message': 'I committed',
899 'message': 'I committed',
898 'filename': "vcs/nodes.py",
900 'filename': "vcs/nodes.py",
899 'csrf_token': csrf_token,
901 'csrf_token': csrf_token,
900 },
902 },
901 status=302)
903 status=302)
902 assert_session_flash(
904 assert_session_flash(
903 response, 'Successfully committed changes to file `vcs/nodes.py`')
905 response, 'Successfully committed changes to file `vcs/nodes.py`')
904 tip = repo.get_commit(commit_idx=-1)
906 tip = repo.get_commit(commit_idx=-1)
905 assert tip.message == 'I committed'
907 assert tip.message == 'I committed'
906
908
907 def test_edit_file_view_commit_changes_default_message(self, backend,
909 def test_edit_file_view_commit_changes_default_message(self, backend,
908 csrf_token):
910 csrf_token):
909 repo = backend.create_repo()
911 repo = backend.create_repo()
910 backend.ensure_file("vcs/nodes.py", content="print 'hello'")
912 backend.ensure_file("vcs/nodes.py", content="print 'hello'")
911
913
912 commit_id = (
914 commit_id = (
913 backend.default_branch_name or
915 backend.default_branch_name or
914 backend.repo.scm_instance().commit_ids[-1])
916 backend.repo.scm_instance().commit_ids[-1])
915
917
916 response = self.app.post(
918 response = self.app.post(
917 route_path('repo_files_update_file',
919 route_path('repo_files_update_file',
918 repo_name=repo.repo_name,
920 repo_name=repo.repo_name,
919 commit_id=commit_id,
921 commit_id=commit_id,
920 f_path='vcs/nodes.py'),
922 f_path='vcs/nodes.py'),
921 params={
923 params={
922 'content': "print 'hello world'",
924 'content': "print 'hello world'",
923 'message': '',
925 'message': '',
924 'filename': "vcs/nodes.py",
926 'filename': "vcs/nodes.py",
925 'csrf_token': csrf_token,
927 'csrf_token': csrf_token,
926 },
928 },
927 status=302)
929 status=302)
928 assert_session_flash(
930 assert_session_flash(
929 response, 'Successfully committed changes to file `vcs/nodes.py`')
931 response, 'Successfully committed changes to file `vcs/nodes.py`')
930 tip = repo.get_commit(commit_idx=-1)
932 tip = repo.get_commit(commit_idx=-1)
931 assert tip.message == 'Edited file vcs/nodes.py via RhodeCode Enterprise'
933 assert tip.message == 'Edited file vcs/nodes.py via RhodeCode Enterprise'
932
934
933 def test_delete_file_view(self, backend):
935 def test_delete_file_view(self, backend):
934 self.app.get(
936 self.app.get(
935 route_path('repo_files_remove_file',
937 route_path('repo_files_remove_file',
936 repo_name=backend.repo_name,
938 repo_name=backend.repo_name,
937 commit_id=backend.default_head_id,
939 commit_id=backend.default_head_id,
938 f_path='vcs/nodes.py'),
940 f_path='vcs/nodes.py'),
939 status=200)
941 status=200)
940
942
941 def test_delete_file_view_not_on_branch(self, backend):
943 def test_delete_file_view_not_on_branch(self, backend):
942 repo = backend.create_repo()
944 repo = backend.create_repo()
943 backend.ensure_file('vcs/nodes.py')
945 backend.ensure_file('vcs/nodes.py')
944
946
945 response = self.app.get(
947 response = self.app.get(
946 route_path('repo_files_remove_file',
948 route_path('repo_files_remove_file',
947 repo_name=repo.repo_name,
949 repo_name=repo.repo_name,
948 commit_id='tip',
950 commit_id='tip',
949 f_path='vcs/nodes.py'),
951 f_path='vcs/nodes.py'),
950 status=302)
952 status=302)
951 assert_session_flash(
953 assert_session_flash(
952 response,
954 response,
953 'You can only delete files with commit being a valid branch')
955 'You can only delete files with commit being a valid branch')
954
956
955 def test_delete_file_view_commit_changes(self, backend, csrf_token):
957 def test_delete_file_view_commit_changes(self, backend, csrf_token):
956 repo = backend.create_repo()
958 repo = backend.create_repo()
957 backend.ensure_file("vcs/nodes.py")
959 backend.ensure_file("vcs/nodes.py")
958
960
959 response = self.app.post(
961 response = self.app.post(
960 route_path('repo_files_delete_file',
962 route_path('repo_files_delete_file',
961 repo_name=repo.repo_name,
963 repo_name=repo.repo_name,
962 commit_id=backend.default_head_id,
964 commit_id=backend.default_head_id,
963 f_path='vcs/nodes.py'),
965 f_path='vcs/nodes.py'),
964 params={
966 params={
965 'message': 'i commited',
967 'message': 'i commited',
966 'csrf_token': csrf_token,
968 'csrf_token': csrf_token,
967 },
969 },
968 status=302)
970 status=302)
969 assert_session_flash(
971 assert_session_flash(
970 response, 'Successfully deleted file `vcs/nodes.py`')
972 response, 'Successfully deleted file `vcs/nodes.py`')
971
973
972
974
973 @pytest.mark.usefixtures("app")
975 @pytest.mark.usefixtures("app")
974 class TestFilesViewOtherCases(object):
976 class TestFilesViewOtherCases(object):
975
977
976 def test_access_empty_repo_redirect_to_summary_with_alert_write_perms(
978 def test_access_empty_repo_redirect_to_summary_with_alert_write_perms(
977 self, backend_stub, autologin_regular_user, user_regular,
979 self, backend_stub, autologin_regular_user, user_regular,
978 user_util):
980 user_util):
979
981
980 repo = backend_stub.create_repo()
982 repo = backend_stub.create_repo()
981 user_util.grant_user_permission_to_repo(
983 user_util.grant_user_permission_to_repo(
982 repo, user_regular, 'repository.write')
984 repo, user_regular, 'repository.write')
983 response = self.app.get(
985 response = self.app.get(
984 route_path('repo_files',
986 route_path('repo_files',
985 repo_name=repo.repo_name,
987 repo_name=repo.repo_name,
986 commit_id='tip', f_path='/'))
988 commit_id='tip', f_path='/'))
987
989
988 repo_file_add_url = route_path(
990 repo_file_add_url = route_path(
989 'repo_files_add_file',
991 'repo_files_add_file',
990 repo_name=repo.repo_name,
992 repo_name=repo.repo_name,
991 commit_id=0, f_path='') + '#edit'
993 commit_id=0, f_path='') + '#edit'
992
994
993 assert_session_flash(
995 assert_session_flash(
994 response,
996 response,
995 'There are no files yet. <a class="alert-link" '
997 'There are no files yet. <a class="alert-link" '
996 'href="{}">Click here to add a new file.</a>'
998 'href="{}">Click here to add a new file.</a>'
997 .format(repo_file_add_url))
999 .format(repo_file_add_url))
998
1000
999 def test_access_empty_repo_redirect_to_summary_with_alert_no_write_perms(
1001 def test_access_empty_repo_redirect_to_summary_with_alert_no_write_perms(
1000 self, backend_stub, user_util):
1002 self, backend_stub, user_util):
1001 repo = backend_stub.create_repo()
1003 repo = backend_stub.create_repo()
1002 repo_file_add_url = route_path(
1004 repo_file_add_url = route_path(
1003 'repo_files_add_file',
1005 'repo_files_add_file',
1004 repo_name=repo.repo_name,
1006 repo_name=repo.repo_name,
1005 commit_id=0, f_path='') + '#edit'
1007 commit_id=0, f_path='') + '#edit'
1006
1008
1007 response = self.app.get(
1009 response = self.app.get(
1008 route_path('repo_files',
1010 route_path('repo_files',
1009 repo_name=repo.repo_name,
1011 repo_name=repo.repo_name,
1010 commit_id='tip', f_path='/'))
1012 commit_id='tip', f_path='/'))
1011
1013
1012 assert_session_flash(response, no_=repo_file_add_url)
1014 assert_session_flash(response, no_=repo_file_add_url)
1013
1015
1014 @pytest.mark.parametrize('file_node', [
1016 @pytest.mark.parametrize('file_node', [
1015 'archive/file.zip',
1017 'archive/file.zip',
1016 'diff/my-file.txt',
1018 'diff/my-file.txt',
1017 'render.py',
1019 'render.py',
1018 'render',
1020 'render',
1019 'remove_file',
1021 'remove_file',
1020 'remove_file/to-delete.txt',
1022 'remove_file/to-delete.txt',
1021 ])
1023 ])
1022 def test_file_names_equal_to_routes_parts(self, backend, file_node):
1024 def test_file_names_equal_to_routes_parts(self, backend, file_node):
1023 backend.create_repo()
1025 backend.create_repo()
1024 backend.ensure_file(file_node)
1026 backend.ensure_file(file_node)
1025
1027
1026 self.app.get(
1028 self.app.get(
1027 route_path('repo_files',
1029 route_path('repo_files',
1028 repo_name=backend.repo_name,
1030 repo_name=backend.repo_name,
1029 commit_id='tip', f_path=file_node),
1031 commit_id='tip', f_path=file_node),
1030 status=200)
1032 status=200)
1031
1033
1032
1034
1033 class TestAdjustFilePathForSvn(object):
1035 class TestAdjustFilePathForSvn(object):
1034 """
1036 """
1035 SVN specific adjustments of node history in RepoFilesView.
1037 SVN specific adjustments of node history in RepoFilesView.
1036 """
1038 """
1037
1039
1038 def test_returns_path_relative_to_matched_reference(self):
1040 def test_returns_path_relative_to_matched_reference(self):
1039 repo = self._repo(branches=['trunk'])
1041 repo = self._repo(branches=['trunk'])
1040 self.assert_file_adjustment('trunk/file', 'file', repo)
1042 self.assert_file_adjustment('trunk/file', 'file', repo)
1041
1043
1042 def test_does_not_modify_file_if_no_reference_matches(self):
1044 def test_does_not_modify_file_if_no_reference_matches(self):
1043 repo = self._repo(branches=['trunk'])
1045 repo = self._repo(branches=['trunk'])
1044 self.assert_file_adjustment('notes/file', 'notes/file', repo)
1046 self.assert_file_adjustment('notes/file', 'notes/file', repo)
1045
1047
1046 def test_does_not_adjust_partial_directory_names(self):
1048 def test_does_not_adjust_partial_directory_names(self):
1047 repo = self._repo(branches=['trun'])
1049 repo = self._repo(branches=['trun'])
1048 self.assert_file_adjustment('trunk/file', 'trunk/file', repo)
1050 self.assert_file_adjustment('trunk/file', 'trunk/file', repo)
1049
1051
1050 def test_is_robust_to_patterns_which_prefix_other_patterns(self):
1052 def test_is_robust_to_patterns_which_prefix_other_patterns(self):
1051 repo = self._repo(branches=['trunk', 'trunk/new', 'trunk/old'])
1053 repo = self._repo(branches=['trunk', 'trunk/new', 'trunk/old'])
1052 self.assert_file_adjustment('trunk/new/file', 'file', repo)
1054 self.assert_file_adjustment('trunk/new/file', 'file', repo)
1053
1055
1054 def assert_file_adjustment(self, f_path, expected, repo):
1056 def assert_file_adjustment(self, f_path, expected, repo):
1055 result = RepoFilesView.adjust_file_path_for_svn(f_path, repo)
1057 result = RepoFilesView.adjust_file_path_for_svn(f_path, repo)
1056 assert result == expected
1058 assert result == expected
1057
1059
1058 def _repo(self, branches=None):
1060 def _repo(self, branches=None):
1059 repo = mock.Mock()
1061 repo = mock.Mock()
1060 repo.branches = OrderedDict((name, '0') for name in branches or [])
1062 repo.branches = OrderedDict((name, '0') for name in branches or [])
1061 repo.tags = {}
1063 repo.tags = {}
1062 return repo
1064 return repo
General Comments 0
You need to be logged in to leave comments. Login now