diff --git a/swh/web/assets/src/bundles/browse/browse.css b/swh/web/assets/src/bundles/browse/browse.css index 7210eb91..b4976594 100644 --- a/swh/web/assets/src/bundles/browse/browse.css +++ b/swh/web/assets/src/bundles/browse/browse.css @@ -1,119 +1,149 @@ /** * Copyright (C) 2018 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ .swh-browse-nav li a { border-radius: 4px; } .scrollable-menu { max-height: 180px; overflow-x: hidden; } .swh-corner-ribbon { width: 200px; background: #fecd1b; color: #e20026; position: absolute; text-align: center; line-height: 50px; letter-spacing: 1px; box-shadow: 0 0 3px rgba(0, 0, 0, 0.3); top: 55px; right: -50px; left: auto; transform: rotate(45deg); z-index: 2000; } .swh-loading { display: none; text-align: center; margin-top: 10px; } .swh-loading.show { display: block; } .swh-metadata-table-row { border-top: 1px solid #ddd !important; } .swh-metadata-table-key { min-width: 200px; max-width: 200px; width: 200px; } .swh-metadata-table-value pre { white-space: pre-wrap; } .swh-table-cell-text-overflow { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .swh-directory-table { margin-bottom: 0; } .swh-directory-table td { border-top: 1px solid #ddd !important; } .swh-title-color { color: #e20026; } .swh-log-entry-message { min-width: 440px; max-width: 440px; width: 440px; } .swh-popover { max-height: 50vh; max-width: 80vw; overflow-y: auto; overflow-x: auto; padding: 0; padding-right: 1.4em; } .swh-search-pagination { margin-top: 5px; } .ui-slideouttab-panel { z-index: 30000; } #swh-identifiers { width: 70vw; top: 0; border: 1px solid #e20026; } #swh-identifiers .handle { background-color: #e20026; border: 1px solid #e20026; color: white; padding-top: 0.1em; padding-bottom: 0.1em; } #swh-identifiers-content { height: 100%; overflow: auto; } .swh-empty-snapshot { white-space: pre-line; } + +td.swh-branch-name { + max-width: 300px; +} + +td.swh-branch-message { + min-width: 500px; + max-width: 500px; +} + +td.swh-branch-date { + min-width: 250px; +} + +td.swh-branch-name a, +td.swh-branch-message a, +td.swh-branch-date a { + text-decoration: none; +} + +td.swh-release-name a, +td.swh-release-message a, +td.swh-release-date a { + text-decoration: none; +} + +tr.swh-directory-entry a, +tr.swh-search-result-entry a { + text-decoration: none; +} diff --git a/swh/web/assets/src/bundles/browse/origin-search.js b/swh/web/assets/src/bundles/browse/origin-search.js index c822f6fb..3297030d 100644 --- a/swh/web/assets/src/bundles/browse/origin-search.js +++ b/swh/web/assets/src/bundles/browse/origin-search.js @@ -1,248 +1,249 @@ /** * Copyright (C) 2018 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ import {heapsPermute} from 'utils/heaps-permute'; import {handleFetchError} from 'utils/functions'; let originPatterns; let perPage = 100; let limit = perPage * 2; let offset = 0; let currentData = null; let inSearch = false; function fixTableRowsStyle() { setTimeout(() => { $('#origin-search-results tbody tr').removeAttr('style'); }); } function clearOriginSearchResultsTable() { $('#origin-search-results tbody tr').remove(); } function populateOriginSearchResultsTable(data, offset) { let localOffset = offset % limit; if (data.length > 0) { $('#swh-origin-search-results').show(); $('#swh-no-result').hide(); clearOriginSearchResultsTable(); let table = $('#origin-search-results tbody'); for (let i = localOffset; i < localOffset + perPage && i < data.length; ++i) { let elem = data[i]; - let tableRow = '
Below you can find a list of the available endpoints for version 1 of the Software Heritage API. For a more general introduction please refer to the API overview.
Endpoints marked "available" are considered stable for the current version of the API; endpoints marked "upcoming" are work in progress that will be stabilized in the near future.
Endpoint | Status | Description | {% for route, doc in doc_routes %} -|||||||
---|---|---|---|---|---|---|---|---|---|
{% url doc.route_view_name %} | -{{ doc.tags|join:', ' }} | ++ {% url doc.route_view_name %} + | ++ {{ doc.tags|join:', ' }} + | {% else %} -{% url doc.route_view_name %} | -available | ++ + {% url doc.route_view_name %} + + | ++ + available + + | {% endif %} -{{ doc.doc_intro | safe_docstring_display | safe }} | ++ + {{ doc.doc_intro | safe_docstring_display | safe }} + + |
Name | Revision | Message | Date |
---|---|---|---|
{{ branch.name }} | -{{ branch.revision|slice:":7" }} | - -{{ branch.date }} | +|
+ + {{ branch.name }} + + | ++ + {{ branch.revision|slice:":7" }} + + | + ++ + {{ branch.date }} + + |
Name | Target | Message | Date |
---|---|---|---|
{{ release.name }} | -{{ release.target|slice:":7" }} | - -{{ release.date }} | +|
+ + {{ release.name }} + + | ++ + {{ release.target|slice:":7" }} + + | + ++ + {{ release.date }} + + |
Revision | Author | Date | Message | Commit Date |
---|---|---|---|---|
{{ rev.id }} | {{ rev.author }} | {{ rev.date }} | {{ rev.commit_date }} |
Searching origins ...
File | Mode | Size | ||
---|---|---|---|---|
- - {{ d.name }} + + + {{ d.name }} + + | ++ + {{ d.perms }} + + | ++ + | -{{ d.perms }} | -|
- - {{ f.name }} + + + {{ f.name }} + + | ++ + {{ f.perms }} + + | ++ + {{ f.length }} + | -{{ f.perms }} | -{{ f.length }} |
' % content_language)
self.assertContains(resp, escape(content_data))
split_path = content_path.split('/')
filename = split_path[-1]
path = content_path.replace(filename, '')[:-1]
path_info = gen_path_info(path)
del url_args['path']
if timestamp:
url_args['timestamp'] = \
format_utc_iso_date(parse_timestamp(timestamp).isoformat(),
'%Y-%m-%dT%H:%M:%S')
root_dir_url = reverse('browse-origin-directory',
url_args=url_args,
query_params=query_params)
self.assertContains(resp, '',
count=len(path_info)+1)
self.assertContains(resp, '%s' %
(root_dir_url, root_dir_sha1[:7]))
for p in path_info:
url_args['path'] = p['path']
dir_url = reverse('browse-origin-directory',
url_args=url_args,
query_params=query_params)
self.assertContains(resp, '%s' %
(dir_url, p['name']))
self.assertContains(resp, ' %s ' % filename)
query_string = 'sha1_git:' + content_sha1
url_raw = reverse('browse-content-raw',
url_args={'query_string': query_string},
query_params={'filename': filename})
self.assertContains(resp, url_raw)
del url_args['path']
origin_branches_url = \
reverse('browse-origin-branches',
url_args=url_args,
query_params=query_params)
self.assertContains(resp, 'Branches (%s)' %
(origin_branches_url, len(origin_branches)))
origin_releases_url = \
reverse('browse-origin-releases',
url_args=url_args,
query_params=query_params)
self.assertContains(resp, 'Releases (%s)' %
(origin_releases_url, len(origin_releases)))
self.assertContains(resp, '',
count=len(origin_branches))
url_args['path'] = content_path
for branch in origin_branches:
query_params['branch'] = branch['name']
root_dir_branch_url = \
reverse('browse-origin-content',
url_args=url_args,
query_params=query_params)
self.assertContains(resp, '' % root_dir_branch_url)
self.assertContains(resp, '',
count=len(origin_releases))
query_params['branch'] = None
for release in origin_releases:
query_params['release'] = release['name']
root_dir_release_url = \
reverse('browse-origin-content',
url_args=url_args,
query_params=query_params)
self.assertContains(resp, '' % root_dir_release_url)
del url_args['origin_type']
url = reverse('browse-origin-content',
url_args=url_args,
query_params=query_params)
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertTemplateUsed('content.html')
swh_cnt_id = get_swh_persistent_id('content', content_sha1_git)
swh_cnt_id_url = reverse('browse-swh-id',
url_args={'swh_id': swh_cnt_id})
self.assertContains(resp, swh_cnt_id)
self.assertContains(resp, swh_cnt_id_url)
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.views.utils.snapshot_context.service')
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.utils.snapshot_context.request_content')
def test_origin_content_view(self, mock_request_content, mock_utils_service,
mock_service, mock_get_origin_visit_snapshot,
mock_get_origin_visits):
stub_content_text_sha1 = stub_content_text_data['checksums']['sha1']
stub_content_text_sha1_git = stub_content_text_data['checksums']['sha1_git']
mock_get_origin_visits.return_value = stub_content_origin_visits
mock_get_origin_visit_snapshot.return_value = stub_content_origin_snapshot
mock_service.lookup_directory_with_path.return_value = \
{'target': stub_content_text_sha1}
mock_request_content.return_value = stub_content_text_data
mock_utils_service.lookup_origin.return_value = stub_content_origin_info
mock_utils_service.lookup_snapshot_size.return_value = {
'revision': len(stub_content_origin_snapshot[0]),
'release': len(stub_content_origin_snapshot[1])
}
self.origin_content_view_helper(stub_content_origin_info,
stub_content_origin_visits,
stub_content_origin_snapshot[0],
stub_content_origin_snapshot[1],
stub_content_origin_branch,
stub_content_root_dir,
stub_content_text_sha1,
stub_content_text_sha1_git,
stub_content_text_path,
stub_content_text_data['raw_data'],
'cpp')
self.origin_content_view_helper(stub_content_origin_info,
stub_content_origin_visits,
stub_content_origin_snapshot[0],
stub_content_origin_snapshot[1],
stub_content_origin_branch,
stub_content_root_dir,
stub_content_text_sha1,
stub_content_text_sha1_git,
stub_content_text_path,
stub_content_text_data['raw_data'],
'cpp',
visit_id=stub_content_origin_visit_id)
self.origin_content_view_helper(stub_content_origin_info,
stub_content_origin_visits,
stub_content_origin_snapshot[0],
stub_content_origin_snapshot[1],
stub_content_origin_branch,
stub_content_root_dir,
stub_content_text_sha1,
stub_content_text_sha1_git,
stub_content_text_path,
stub_content_text_data['raw_data'],
'cpp',
timestamp=stub_content_origin_visit_unix_ts)
self.origin_content_view_helper(stub_content_origin_info,
stub_content_origin_visits,
stub_content_origin_snapshot[0],
stub_content_origin_snapshot[1],
stub_content_origin_branch,
stub_content_root_dir,
stub_content_text_sha1,
stub_content_text_sha1_git,
stub_content_text_path,
stub_content_text_data['raw_data'],
'cpp',
timestamp=stub_content_origin_visit_iso_date)
def origin_directory_view_helper(self, origin_info, origin_visits,
origin_branches, origin_releases, origin_branch,
root_directory_sha1, directory_entries,
visit_id=None, timestamp=None, path=None):
dirs = [e for e in directory_entries
if e['type'] in ('dir', 'rev')]
files = [e for e in directory_entries
if e['type'] == 'file']
if not visit_id:
visit_id = origin_visits[-1]['visit']
url_args = {'origin_url': origin_info['url']}
query_params = {}
if timestamp:
url_args['timestamp'] = timestamp
else:
query_params['visit_id'] = visit_id
if path:
url_args['path'] = path
url = reverse('browse-origin-directory',
url_args=url_args,
query_params=query_params)
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertTemplateUsed('directory.html')
self.assertEqual(resp.status_code, 200)
self.assertTemplateUsed('directory.html')
self.assertContains(resp, '',
count=len(dirs))
self.assertContains(resp, ' ',
count=len(files))
if timestamp:
url_args['timestamp'] = \
format_utc_iso_date(parse_timestamp(timestamp).isoformat(),
'%Y-%m-%dT%H:%M:%S')
for d in dirs:
if d['type'] == 'rev':
dir_url = reverse('browse-revision',
url_args={'sha1_git': d['target']})
else:
dir_path = d['name']
if path:
dir_path = "%s/%s" % (path, d['name'])
dir_url_args = dict(url_args)
dir_url_args['path'] = dir_path
dir_url = reverse('browse-origin-directory',
url_args=dir_url_args,
query_params=query_params)
self.assertContains(resp, dir_url)
for f in files:
file_path = f['name']
if path:
file_path = "%s/%s" % (path, f['name'])
file_url_args = dict(url_args)
file_url_args['path'] = file_path
file_url = reverse('browse-origin-content',
url_args=file_url_args,
query_params=query_params)
self.assertContains(resp, file_url)
if 'path' in url_args:
del url_args['path']
root_dir_branch_url = \
reverse('browse-origin-directory',
url_args=url_args,
query_params=query_params)
nb_bc_paths = 1
if path:
nb_bc_paths = len(path.split('/')) + 1
self.assertContains(resp, '', count=nb_bc_paths)
self.assertContains(resp, '%s' %
(root_dir_branch_url,
root_directory_sha1[:7]))
origin_branches_url = \
reverse('browse-origin-branches',
url_args=url_args,
query_params=query_params)
self.assertContains(resp, 'Branches (%s)' %
(origin_branches_url, len(origin_branches)))
origin_releases_url = \
reverse('browse-origin-releases',
url_args=url_args,
query_params=query_params)
self.assertContains(resp, 'Releases (%s)' %
(origin_releases_url, len(origin_releases)))
if path:
url_args['path'] = path
self.assertContains(resp, ' ',
count=len(origin_branches))
for branch in origin_branches:
query_params['branch'] = branch['name']
root_dir_branch_url = \
reverse('browse-origin-directory',
url_args=url_args,
query_params=query_params)
self.assertContains(resp, '' % root_dir_branch_url)
self.assertContains(resp, '',
count=len(origin_releases))
query_params['branch'] = None
for release in origin_releases:
query_params['release'] = release['name']
root_dir_release_url = \
reverse('browse-origin-directory',
url_args=url_args,
query_params=query_params)
self.assertContains(resp, '' % root_dir_release_url)
self.assertContains(resp, 'vault-cook-directory')
self.assertContains(resp, 'vault-cook-revision')
swh_dir_id = get_swh_persistent_id('directory', directory_entries[0]['dir_id']) # noqa
swh_dir_id_url = reverse('browse-swh-id',
url_args={'swh_id': swh_dir_id})
self.assertContains(resp, swh_dir_id)
self.assertContains(resp, swh_dir_id_url)
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.origin.service')
def test_origin_root_directory_view(self, mock_origin_service,
mock_utils_service,
mock_get_origin_visit_snapshot,
mock_get_origin_visits):
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_utils_service.lookup_directory.return_value = \
stub_origin_root_directory_entries
mock_utils_service.lookup_origin.return_value = stub_origin_info
mock_utils_service.lookup_snapshot_size.return_value = {
'revision': len(stub_origin_snapshot[0]),
'release': len(stub_origin_snapshot[1])
}
self.origin_directory_view_helper(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries)
self.origin_directory_view_helper(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries,
visit_id=stub_visit_id)
self.origin_directory_view_helper(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries,
timestamp=stub_visit_unix_ts)
self.origin_directory_view_helper(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries,
timestamp=stub_visit_iso_date)
self.origin_directory_view_helper(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries)
self.origin_directory_view_helper(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries,
visit_id=stub_visit_id)
self.origin_directory_view_helper(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries,
timestamp=stub_visit_unix_ts)
self.origin_directory_view_helper(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries,
timestamp=stub_visit_iso_date)
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.utils.snapshot_context.service')
def test_origin_sub_directory_view(self, mock_origin_service,
mock_utils_service,
mock_get_origin_visit_snapshot,
mock_get_origin_visits):
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_utils_service.lookup_directory.return_value = \
stub_origin_sub_directory_entries
mock_origin_service.lookup_directory_with_path.return_value = \
{'target': stub_origin_sub_directory_entries[0]['dir_id'],
'type' : 'dir'}
mock_utils_service.lookup_origin.return_value = stub_origin_info
mock_utils_service.lookup_snapshot_size.return_value = {
'revision': len(stub_origin_snapshot[0]),
'release': len(stub_origin_snapshot[1])
}
self.origin_directory_view_helper(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
path=stub_origin_sub_directory_path)
self.origin_directory_view_helper(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
visit_id=stub_visit_id,
path=stub_origin_sub_directory_path)
self.origin_directory_view_helper(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
timestamp=stub_visit_unix_ts,
path=stub_origin_sub_directory_path)
self.origin_directory_view_helper(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
timestamp=stub_visit_iso_date,
path=stub_origin_sub_directory_path)
self.origin_directory_view_helper(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
path=stub_origin_sub_directory_path)
self.origin_directory_view_helper(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
visit_id=stub_visit_id,
path=stub_origin_sub_directory_path)
self.origin_directory_view_helper(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
timestamp=stub_visit_unix_ts,
path=stub_origin_sub_directory_path)
self.origin_directory_view_helper(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
timestamp=stub_visit_iso_date,
path=stub_origin_sub_directory_path)
@patch('swh.web.browse.views.utils.snapshot_context.request_content')
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.origin.service')
@patch('swh.web.browse.views.utils.snapshot_context.service')
@patch('swh.web.browse.views.origin.get_origin_info')
def test_origin_request_errors(self, mock_get_origin_info,
mock_snapshot_service,
mock_origin_service,
mock_utils_service,
mock_get_origin_visit_snapshot,
mock_get_origin_visits,
mock_request_content):
mock_get_origin_info.side_effect = \
NotFoundExc('origin not found')
url = reverse('browse-origin-visits',
url_args={'origin_type': 'foo',
'origin_url': 'bar'})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'origin not found', status_code=404)
mock_utils_service.lookup_origin.side_effect = None
mock_utils_service.lookup_origin.return_value = origin_info_test_data
mock_get_origin_visits.return_value = []
url = reverse('browse-origin-directory',
url_args={'origin_type': 'foo',
'origin_url': 'bar'})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, "No SWH visit", status_code=404)
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.side_effect = \
NotFoundExc('visit not found')
url = reverse('browse-origin-directory',
url_args={'origin_type': 'foo',
'origin_url': 'bar'},
query_params={'visit_id': len(stub_origin_visits)+1})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertRegex(resp.content.decode('utf-8'), 'Visit.*not found')
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.side_effect = None
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_utils_service.lookup_snapshot_size.return_value = {
'revision': len(stub_origin_snapshot[0]),
'release': len(stub_origin_snapshot[1])
}
mock_utils_service.lookup_directory.side_effect = \
NotFoundExc('Directory not found')
url = reverse('browse-origin-directory',
url_args={'origin_type': 'foo',
'origin_url': 'bar'})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'Directory not found', status_code=404)
with patch('swh.web.browse.views.utils.snapshot_context.get_snapshot_context') \
as mock_get_snapshot_context:
mock_get_snapshot_context.side_effect = \
NotFoundExc('Snapshot not found')
url = reverse('browse-origin-directory',
url_args={'origin_type': 'foo',
'origin_url': 'bar'})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'Snapshot not found', status_code=404)
mock_origin_service.lookup_origin.side_effect = None
mock_origin_service.lookup_origin.return_value = origin_info_test_data
mock_get_origin_visits.return_value = []
url = reverse('browse-origin-content',
url_args={'origin_type': 'foo',
'origin_url': 'bar',
'path': 'foo'})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, "No SWH visit", status_code=404)
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.side_effect = \
NotFoundExc('visit not found')
url = reverse('browse-origin-content',
url_args={'origin_type': 'foo',
'origin_url': 'bar',
'path': 'foo'},
query_params={'visit_id': len(stub_origin_visits)+1})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertRegex(resp.content.decode('utf-8'), 'Visit.*not found')
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.side_effect = None
mock_get_origin_visit_snapshot.return_value = ([], [])
url = reverse('browse-origin-content',
url_args={'origin_type': 'foo',
'origin_url': 'bar',
'path': 'baz'})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertRegex(resp.content.decode('utf-8'),
'Origin.*has an empty list of branches')
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_snapshot_service.lookup_directory_with_path.return_value = \
{'target': stub_content_text_data['checksums']['sha1']}
mock_request_content.side_effect = \
NotFoundExc('Content not found')
url = reverse('browse-origin-content',
url_args={'origin_type': 'foo',
'origin_url': 'bar',
'path': 'baz'})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'Content not found', status_code=404)
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.utils.service')
def test_origin_empty_snapshot(self, mock_utils_service,
mock_get_origin_visit_snapshot,
mock_get_origin_visits):
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.return_value = ([], [])
mock_utils_service.lookup_snapshot_size.return_value = {
'revision': 0,
'release': 0
}
url = reverse('browse-origin-directory',
url_args={'origin_type': 'foo',
'origin_url': 'bar'})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertTemplateUsed('content.html')
self.assertRegex(resp.content.decode('utf-8'), 'snapshot.*is empty')
def origin_branches_helper(self, origin_info, origin_snapshot):
url_args = {'origin_type': origin_info['type'],
'origin_url': origin_info['url']}
url = reverse('browse-origin-branches',
url_args=url_args)
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertTemplateUsed('branches.html')
origin_branches = origin_snapshot[0]
origin_releases = origin_snapshot[1]
origin_branches_url = \
reverse('browse-origin-branches',
url_args=url_args)
self.assertContains(resp, 'Branches (%s)' %
(origin_branches_url, len(origin_branches)))
origin_releases_url = \
reverse('browse-origin-releases',
url_args=url_args)
self.assertContains(resp, 'Releases (%s)' %
(origin_releases_url, len(origin_releases)))
- self.assertContains(resp, '',
+ self.assertContains(resp, ' %s' % (escape(browse_branch_url), branch['name']))
+ self.assertContains(resp, '' % escape(browse_branch_url))
browse_revision_url = reverse('browse-revision',
url_args={'sha1_git': branch['revision']},
query_params={'origin_type': origin_info['type'],
'origin': origin_info['url']})
- self.assertContains(resp, '%s' % (escape(browse_revision_url), branch['revision'][:7]))
+ self.assertContains(resp, '' % escape(browse_revision_url))
@patch('swh.web.browse.views.utils.snapshot_context.process_snapshot_branches')
@patch('swh.web.browse.views.utils.snapshot_context.service')
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.origin.service')
def test_origin_branches(self, mock_origin_service,
mock_utils_service,
mock_get_origin_visit_snapshot,
mock_get_origin_visits,
mock_snp_ctx_service,
mock_snp_ctx_process_branches):
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_utils_service.lookup_origin.return_value = stub_origin_info
mock_utils_service.lookup_snapshot_size.return_value = \
{'revision': len(stub_origin_snapshot[0]), 'release': len(stub_origin_snapshot[1])}
mock_snp_ctx_service.lookup_snapshot.return_value = \
_to_snapshot_dict(branches=stub_origin_snapshot[0])
mock_snp_ctx_process_branches.return_value = stub_origin_snapshot
self.origin_branches_helper(stub_origin_info, stub_origin_snapshot)
self.origin_branches_helper(stub_origin_info_no_type, stub_origin_snapshot)
def origin_releases_helper(self, origin_info, origin_snapshot):
url_args = {'origin_type': origin_info['type'],
'origin_url': origin_info['url']}
url = reverse('browse-origin-releases',
url_args=url_args)
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertTemplateUsed('releases.html')
origin_branches = origin_snapshot[0]
origin_releases = origin_snapshot[1]
origin_branches_url = \
reverse('browse-origin-branches',
url_args=url_args)
self.assertContains(resp, 'Branches (%s)' %
(origin_branches_url, len(origin_branches)))
origin_releases_url = \
reverse('browse-origin-releases',
url_args=url_args)
self.assertContains(resp, 'Releases (%s)' %
(origin_releases_url, len(origin_releases)))
- self.assertContains(resp, ' ',
+ self.assertContains(resp, ' %s' % (escape(browse_release_url), release['name']))
- self.assertContains(resp, '%s' % (escape(browse_revision_url), release['target'][:7]))
+ self.assertContains(resp, '' % escape(browse_release_url))
+ self.assertContains(resp, '' % escape(browse_revision_url))
@patch('swh.web.browse.views.utils.snapshot_context.process_snapshot_branches')
@patch('swh.web.browse.views.utils.snapshot_context.service')
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.origin.service')
def test_origin_releases(self, mock_origin_service,
mock_utils_service,
mock_get_origin_visit_snapshot,
mock_get_origin_visits,
mock_snp_ctx_service,
mock_snp_ctx_process_branches):
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_utils_service.lookup_origin.return_value = stub_origin_info
mock_utils_service.lookup_snapshot_size.return_value = \
{'revision': len(stub_origin_snapshot[0]), 'release': len(stub_origin_snapshot[1])}
mock_snp_ctx_service.lookup_snapshot.return_value = \
_to_snapshot_dict(releases=stub_origin_snapshot[1])
mock_snp_ctx_process_branches.return_value = stub_origin_snapshot
self.origin_releases_helper(stub_origin_info, stub_origin_snapshot)
self.origin_releases_helper(stub_origin_info_no_type, stub_origin_snapshot)
diff --git a/swh/web/tests/browse/views/test_revision.py b/swh/web/tests/browse/views/test_revision.py
index 4535fcce..8f67eb9b 100644
--- a/swh/web/tests/browse/views/test_revision.py
+++ b/swh/web/tests/browse/views/test_revision.py
@@ -1,255 +1,255 @@
# Copyright (C) 2017-2018 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
# flake8: noqa
from unittest.mock import patch, MagicMock
from django.utils.html import escape
from swh.web.common.exc import NotFoundExc
from swh.web.common.utils import (
reverse, format_utc_iso_date, get_swh_persistent_id,
parse_timestamp
)
from swh.web.tests.testcase import SWHWebTestCase
from .data.revision_test_data import (
revision_id_test, revision_metadata_test,
revision_history_log_test
)
from .data.origin_test_data import stub_origin_visits, stub_origin_snapshot
class SwhBrowseRevisionTest(SWHWebTestCase):
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.views.revision.service')
@patch('swh.web.browse.utils.service')
@patch('swh.web.common.utils.service')
def test_revision_browse(self, mock_service_common, mock_service_utils,
mock_service, mock_get_origin_visit_snapshot):
mock_service.lookup_revision.return_value = revision_metadata_test
url = reverse('browse-revision',
url_args={'sha1_git': revision_id_test})
author_id = revision_metadata_test['author']['id']
author_name = revision_metadata_test['author']['name']
committer_id = revision_metadata_test['committer']['id']
committer_name = revision_metadata_test['committer']['name']
dir_id = revision_metadata_test['directory']
author_url = reverse('browse-person',
url_args={'person_id': author_id})
committer_url = reverse('browse-person',
url_args={'person_id': committer_id})
directory_url = reverse('browse-directory',
url_args={'sha1_git': dir_id})
history_url = reverse('browse-revision-log',
url_args={'sha1_git': revision_id_test})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertTemplateUsed('browse/revision.html')
self.assertContains(resp, '%s' %
(author_url, author_name))
self.assertContains(resp, '%s' %
(committer_url, committer_name))
self.assertContains(resp, directory_url)
self.assertContains(resp, history_url)
for parent in revision_metadata_test['parents']:
parent_url = reverse('browse-revision',
url_args={'sha1_git': parent})
self.assertContains(resp, '%s' %
(parent_url, parent))
author_date = revision_metadata_test['date']
committer_date = revision_metadata_test['committer_date']
message_lines = revision_metadata_test['message'].split('\n')
self.assertContains(resp, format_utc_iso_date(author_date))
self.assertContains(resp, format_utc_iso_date(committer_date))
self.assertContains(resp, message_lines[0])
self.assertContains(resp, '\n'.join(message_lines[1:]))
origin_info = {
'id': '7416001',
'type': 'git',
'url': 'https://github.com/webpack/webpack'
}
mock_service_utils.lookup_origin.return_value = origin_info
mock_service_common.lookup_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_service_utils.lookup_snapshot_size.return_value = {
'revision': len(stub_origin_snapshot[0]),
'release': len(stub_origin_snapshot[1])
}
mock_service_common.MAX_LIMIT = 20
origin_directory_url = reverse('browse-origin-directory',
url_args={'origin_url': origin_info['url']},
query_params={'revision': revision_id_test})
origin_revision_log_url = reverse('browse-origin-log',
url_args={'origin_url': origin_info['url']},
query_params={'revision': revision_id_test})
url = reverse('browse-revision',
url_args={'sha1_git': revision_id_test},
query_params={'origin': origin_info['url']})
resp = self.client.get(url)
self.assertContains(resp, origin_directory_url)
self.assertContains(resp, origin_revision_log_url)
for parent in revision_metadata_test['parents']:
parent_url = reverse('browse-revision',
url_args={'sha1_git': parent},
query_params={'origin': origin_info['url']})
self.assertContains(resp, '%s' %
(parent_url, parent))
self.assertContains(resp, 'vault-cook-directory')
self.assertContains(resp, 'vault-cook-revision')
swh_rev_id = get_swh_persistent_id('revision', revision_id_test)
swh_rev_id_url = reverse('browse-swh-id',
url_args={'swh_id': swh_rev_id})
self.assertContains(resp, swh_rev_id)
self.assertContains(resp, swh_rev_id_url)
swh_dir_id = get_swh_persistent_id('directory', dir_id)
swh_dir_id_url = reverse('browse-swh-id',
url_args={'swh_id': swh_dir_id})
self.assertContains(resp, swh_dir_id)
self.assertContains(resp, swh_dir_id_url)
@patch('swh.web.browse.views.revision.service')
def test_revision_log_browse(self, mock_service):
per_page = 10
revision_history_log_test_sorted = \
sorted(revision_history_log_test,
key=lambda rev: -parse_timestamp(rev['committer_date']).timestamp())
mock_revs_walker = MagicMock()
mock_revs_walker.__iter__.return_value = revision_history_log_test_sorted
mock_revs_walker.export_state.return_value = {}
mock_service.get_revisions_walker.return_value = mock_revs_walker
url = reverse('browse-revision-log',
url_args={'sha1_git': revision_id_test},
query_params={'per_page': per_page})
resp = self.client.get(url)
next_page_url = reverse('browse-revision-log',
url_args={'sha1_git': revision_id_test},
query_params={'offset': per_page,
'per_page': per_page})
self.assertEqual(resp.status_code, 200)
self.assertTemplateUsed('browse/revision-log.html')
- self.assertContains(resp, ' Newer')
self.assertContains(resp, 'Older' %
escape(next_page_url))
for log in revision_history_log_test_sorted[:per_page]:
author_url = reverse('browse-person',
url_args={'person_id': log['author']['id']})
revision_url = reverse('browse-revision',
url_args={'sha1_git': log['id']})
self.assertContains(resp, log['id'][:7])
self.assertContains(resp, log['author']['name'])
self.assertContains(resp, format_utc_iso_date(log['date']))
self.assertContains(resp, escape(log['message']))
self.assertContains(resp, format_utc_iso_date(log['committer_date']))
self.assertContains(resp, revision_url)
resp = self.client.get(next_page_url)
prev_page_url = reverse('browse-revision-log',
url_args={'sha1_git': revision_id_test},
query_params={'per_page': per_page})
next_page_url = reverse('browse-revision-log',
url_args={'sha1_git': revision_id_test},
query_params={'offset': 2 * per_page,
'per_page': per_page})
self.assertEqual(resp.status_code, 200)
self.assertTemplateUsed('browse/revision-log.html')
- self.assertContains(resp, ' Newer' %
escape(prev_page_url))
self.assertContains(resp, 'Older' %
escape(next_page_url))
resp = self.client.get(next_page_url)
prev_page_url = reverse('browse-revision-log',
url_args={'sha1_git': revision_id_test},
query_params={'offset': per_page,
'per_page': per_page})
next_page_url = reverse('browse-revision-log',
url_args={'sha1_git': revision_id_test},
query_params={'offset': 3 * per_page,
'per_page': per_page})
self.assertEqual(resp.status_code, 200)
self.assertTemplateUsed('browse/revision-log.html')
- self.assertContains(resp, ' Newer' %
escape(prev_page_url))
self.assertContains(resp, 'Older' %
escape(next_page_url))
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.revision.service')
def test_revision_request_errors(self, mock_service, mock_utils_service):
mock_service.lookup_revision.side_effect = \
NotFoundExc('Revision not found')
url = reverse('browse-revision',
url_args={'sha1_git': revision_id_test})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'Revision not found', status_code=404)
mock_service.get_revisions_walker.side_effect = \
NotFoundExc('Revision not found')
url = reverse('browse-revision-log',
url_args={'sha1_git': revision_id_test})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'Revision not found', status_code=404)
url = reverse('browse-revision',
url_args={'sha1_git': revision_id_test},
query_params={'origin_type': 'git',
'origin': 'https://github.com/foo/bar'})
mock_service.lookup_revision.side_effect = None
mock_utils_service.lookup_origin.side_effect = \
NotFoundExc('Origin not found')
resp = self.client.get(url)
self.assertEqual(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'Origin not found', status_code=404)