mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-04-01 09:30:29 +00:00
gitweb: Add functional tests
- add eleven functional tests - gitweb_configure.html template: add id to the repository list element to distinct it better. Closes #1668 Signed-off-by: Veiko Aasa <veiko17@disroot.org> Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org> Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
parent
273c419a26
commit
8694849701
107
functional_tests/features/gitweb.feature
Normal file
107
functional_tests/features/gitweb.feature
Normal file
@ -0,0 +1,107 @@
|
||||
#
|
||||
# This file is part of FreedomBox.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
@apps @gitweb @backups @sso
|
||||
Feature: gitweb Simple Git Hosting
|
||||
Git web interface.
|
||||
|
||||
Background:
|
||||
Given I'm a logged in user
|
||||
And the gitweb application is installed
|
||||
|
||||
Scenario: Enable gitweb application
|
||||
Given the gitweb application is disabled
|
||||
When I enable the gitweb application
|
||||
Then the gitweb site should be available
|
||||
|
||||
Scenario: Create public repository
|
||||
Given the gitweb application is enabled
|
||||
And a public repository that doesn't exist
|
||||
When I create the repository
|
||||
Then the repository should be listed as a public
|
||||
And the repository should be listed on gitweb
|
||||
|
||||
Scenario: Create private repository
|
||||
Given the gitweb application is enabled
|
||||
And a private repository that doesn't exist
|
||||
When I create the repository
|
||||
Then the repository should be listed as a private
|
||||
And the repository should be listed on gitweb
|
||||
|
||||
Scenario: Delete repository
|
||||
Given the gitweb application is enabled
|
||||
And a repository
|
||||
When I delete the repository
|
||||
Then the repository should not be listed
|
||||
|
||||
Scenario: Backup and restore gitweb
|
||||
Given the gitweb application is enabled
|
||||
And a repository
|
||||
When I create a backup of the gitweb app data
|
||||
And I delete the repository
|
||||
And I restore the gitweb app data backup
|
||||
Then the repository should be restored
|
||||
And the gitweb site should be available
|
||||
|
||||
Scenario: Disable gitweb application
|
||||
Given the gitweb application is enabled
|
||||
When I disable the gitweb application
|
||||
Then the gitweb site should not be available
|
||||
|
||||
Scenario: Public gitweb site shows only public repositories
|
||||
Given the gitweb application is enabled
|
||||
And both public and private repositories exist
|
||||
When I log out
|
||||
Then the public repository should be listed on gitweb
|
||||
And the private repository should not be listed on gitweb
|
||||
|
||||
Scenario: Gitweb is not public if there are only private repositories
|
||||
Given the gitweb application is enabled
|
||||
And at least one repository exists
|
||||
And all repositories are private
|
||||
When I log out
|
||||
And I access gitweb application
|
||||
Then I should be prompted for login
|
||||
And gitweb app should not be visible on the front page
|
||||
|
||||
Scenario: Edit repository metadata
|
||||
Given the gitweb application is enabled
|
||||
And a public repository that doesn't exist
|
||||
And a repository metadata:
|
||||
description: Test Description
|
||||
owner: Test Owner
|
||||
access: private
|
||||
When I create the repository
|
||||
And I set the metadata of the repository
|
||||
Then the metadata of the repository should be as set
|
||||
|
||||
Scenario: Access public repository with git client
|
||||
Given the gitweb application is enabled
|
||||
And a public repository
|
||||
When using a git client
|
||||
Then the repository should be publicly readable
|
||||
And the repository should not be publicly writable
|
||||
And the repository should be privately writable
|
||||
|
||||
Scenario: Access private repository with git client
|
||||
Given the gitweb application is enabled
|
||||
And a private repository
|
||||
When using a git client
|
||||
Then the repository should not be publicly readable
|
||||
And the repository should not be publicly writable
|
||||
And the repository should be privately readable
|
||||
And the repository should be privately writable
|
||||
@ -456,3 +456,133 @@ def app_visible_on_front_page(browser, app_name):
|
||||
def app_not_visible_on_front_page(browser, app_name):
|
||||
shortcuts = application.find_on_front_page(browser, app_name)
|
||||
assert len(shortcuts) == 0
|
||||
|
||||
|
||||
@given('a public repository')
|
||||
@given('a repository')
|
||||
@given('at least one repository exists')
|
||||
def gitweb_repo(browser):
|
||||
application.gitweb_create_repo(browser, 'Test-repo', 'public', True)
|
||||
|
||||
|
||||
@given('a private repository')
|
||||
def gitweb_private_repo(browser):
|
||||
application.gitweb_create_repo(browser, 'Test-repo', 'private', True)
|
||||
|
||||
|
||||
@given('both public and private repositories exist')
|
||||
def gitweb_public_and_private_repo(browser):
|
||||
application.gitweb_create_repo(browser, 'Test-repo', 'public', True)
|
||||
application.gitweb_create_repo(browser, 'Test-repo2', 'private', True)
|
||||
|
||||
|
||||
@given(parsers.parse("a {access:w} repository that doesn't exist"))
|
||||
def gitweb_nonexistent_repo(browser, access):
|
||||
application.gitweb_delete_repo(browser, 'Test-repo', ignore_missing=True)
|
||||
return dict(access=access)
|
||||
|
||||
|
||||
@given('all repositories are private')
|
||||
def gitweb_all_repositories_private(browser):
|
||||
application.gitweb_set_all_repos_private(browser)
|
||||
|
||||
|
||||
@given(parsers.parse('a repository metadata:\n{metadata}'))
|
||||
def gitweb_repo_metadata(browser, metadata):
|
||||
metadata_dict = {}
|
||||
for item in metadata.split('\n'):
|
||||
item = item.split(': ')
|
||||
metadata_dict[item[0]] = item[1]
|
||||
return metadata_dict
|
||||
|
||||
|
||||
@when('I create the repository')
|
||||
def gitweb_create_repo(browser, access):
|
||||
application.gitweb_create_repo(browser, 'Test-repo', access)
|
||||
|
||||
|
||||
@when('I delete the repository')
|
||||
def gitweb_delete_repo(browser):
|
||||
application.gitweb_delete_repo(browser, 'Test-repo')
|
||||
|
||||
|
||||
@when('I set the metadata of the repository')
|
||||
def gitweb_edit_repo_metadata(browser, gitweb_repo_metadata):
|
||||
application.gitweb_edit_repo_metadata(browser, 'Test-repo',
|
||||
gitweb_repo_metadata)
|
||||
|
||||
|
||||
@when('using a git client')
|
||||
def gitweb_using_git_client():
|
||||
pass
|
||||
|
||||
|
||||
@then('the repository should be restored')
|
||||
@then('the repository should be listed as a public')
|
||||
def gitweb_repo_should_exists(browser):
|
||||
assert application.gitweb_repo_exists(browser, 'Test-repo',
|
||||
access='public')
|
||||
|
||||
|
||||
@then('the repository should be listed as a private')
|
||||
def gitweb_private_repo_should_exists(browser):
|
||||
assert application.gitweb_repo_exists(browser, 'Test-repo', 'private')
|
||||
|
||||
|
||||
@then('the repository should not be listed')
|
||||
def gitweb_repo_should_not_exist(browser, gitweb_repo):
|
||||
assert not application.gitweb_repo_exists(browser, gitweb_repo)
|
||||
|
||||
|
||||
@then('the public repository should be listed on gitweb')
|
||||
@then('the repository should be listed on gitweb')
|
||||
def gitweb_repo_should_exist_on_gitweb(browser):
|
||||
assert application.gitweb_site_repo_exists(browser, 'Test-repo')
|
||||
|
||||
|
||||
@then('the private repository should not be listed on gitweb')
|
||||
def gitweb_private_repo_should_exists_on_gitweb(browser):
|
||||
assert not application.gitweb_site_repo_exists(browser, 'Test-repo2')
|
||||
|
||||
|
||||
@then('the metadata of the repository should be as set')
|
||||
def gitweb_repo_metadata_should_match(browser, gitweb_repo_metadata):
|
||||
actual_metadata = application.gitweb_get_repo_metadata(
|
||||
browser, 'Test-repo')
|
||||
assert all(item in actual_metadata.items()
|
||||
for item in gitweb_repo_metadata.items())
|
||||
|
||||
|
||||
@then('the repository should be publicly readable')
|
||||
def gitweb_repo_publicly_readable():
|
||||
assert application.gitweb_repo_is_readable('Test-repo')
|
||||
assert application.gitweb_repo_is_readable('Test-repo',
|
||||
url_git_extension=True)
|
||||
|
||||
|
||||
@then('the repository should not be publicly readable')
|
||||
def gitweb_repo_not_publicly_readable():
|
||||
assert not application.gitweb_repo_is_readable('Test-repo')
|
||||
assert not application.gitweb_repo_is_readable('Test-repo',
|
||||
url_git_extension=True)
|
||||
|
||||
|
||||
@then('the repository should not be publicly writable')
|
||||
def gitweb_repo_not_publicly_writable():
|
||||
assert not application.gitweb_repo_is_writable('Test-repo')
|
||||
assert not application.gitweb_repo_is_writable('Test-repo',
|
||||
url_git_extension=True)
|
||||
|
||||
|
||||
@then('the repository should be privately readable')
|
||||
def gitweb_repo_privately_readable():
|
||||
assert application.gitweb_repo_is_readable('Test-repo', with_auth=True)
|
||||
assert application.gitweb_repo_is_readable('Test-repo', with_auth=True,
|
||||
url_git_extension=True)
|
||||
|
||||
|
||||
@then('the repository should be privately writable')
|
||||
def gitweb_repo_privately_writable():
|
||||
assert application.gitweb_repo_is_writable('Test-repo', with_auth=True)
|
||||
assert application.gitweb_repo_is_writable('Test-repo', with_auth=True,
|
||||
url_git_extension=True)
|
||||
|
||||
@ -15,6 +15,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
from time import sleep
|
||||
|
||||
import requests
|
||||
@ -319,6 +324,175 @@ def ejabberd_has_contact(browser):
|
||||
return eventually(site.jsxc_has_contact, [browser])
|
||||
|
||||
|
||||
def gitweb_create_repo(browser, repo, access=None, ok_if_exists=False):
|
||||
"""Create repository."""
|
||||
if not gitweb_repo_exists(browser, repo, access):
|
||||
gitweb_delete_repo(browser, repo, ignore_missing=True)
|
||||
browser.find_link_by_href('/plinth/apps/gitweb/create/').first.click()
|
||||
browser.find_by_id('id_gitweb-name').fill(repo)
|
||||
if access == 'private':
|
||||
browser.find_by_id('id_gitweb-is_private').check()
|
||||
elif access == 'public':
|
||||
browser.find_by_id('id_gitweb-is_private').uncheck()
|
||||
submit(browser)
|
||||
elif not ok_if_exists:
|
||||
assert False, 'Repo already exists.'
|
||||
|
||||
|
||||
def gitweb_delete_repo(browser, repo, ignore_missing=False):
|
||||
"""Delete repository."""
|
||||
interface.nav_to_module(browser, 'gitweb')
|
||||
delete_link = browser.find_link_by_href(
|
||||
'/plinth/apps/gitweb/{}/delete/'.format(repo))
|
||||
if delete_link or not ignore_missing:
|
||||
delete_link.first.click()
|
||||
submit(browser)
|
||||
|
||||
|
||||
def gitweb_edit_repo_metadata(browser, repo, metadata):
|
||||
"""Set repository metadata."""
|
||||
interface.nav_to_module(browser, 'gitweb')
|
||||
browser.find_link_by_href(
|
||||
'/plinth/apps/gitweb/{}/edit/'.format(repo)).first.click()
|
||||
if 'name' in metadata:
|
||||
browser.find_by_id('id_gitweb-name').fill(metadata['name'])
|
||||
if 'description' in metadata:
|
||||
browser.find_by_id('id_gitweb-description').fill(
|
||||
metadata['description'])
|
||||
if 'owner' in metadata:
|
||||
browser.find_by_id('id_gitweb-owner').fill(metadata['owner'])
|
||||
if 'access' in metadata:
|
||||
if metadata['access'] == 'private':
|
||||
browser.find_by_id('id_gitweb-is_private').check()
|
||||
else:
|
||||
browser.find_by_id('id_gitweb-is_private').uncheck()
|
||||
submit(browser)
|
||||
|
||||
|
||||
def gitweb_get_repo_metadata(browser, repo):
|
||||
"""Get repository metadata."""
|
||||
interface.nav_to_module(browser, 'gitweb')
|
||||
browser.find_link_by_href(
|
||||
'/plinth/apps/gitweb/{}/edit/'.format(repo)).first.click()
|
||||
metadata = {}
|
||||
for item in ['name', 'description', 'owner']:
|
||||
metadata[item] = browser.find_by_id('id_gitweb-' + item).value
|
||||
if browser.find_by_id('id_gitweb-is_private').value:
|
||||
metadata['access'] = 'private'
|
||||
else:
|
||||
metadata['access'] = 'public'
|
||||
return metadata
|
||||
|
||||
|
||||
def _gitweb_get_repo_url(repo, with_auth):
|
||||
""""Get repository URL"""
|
||||
scheme = 'http'
|
||||
if default_url.startswith('https://'):
|
||||
scheme = 'https'
|
||||
url = default_url.split('://')[1] if '://' in default_url else default_url
|
||||
password = 'gitweb_wrong_password'
|
||||
if with_auth:
|
||||
password = config['DEFAULT']['password']
|
||||
|
||||
return '{0}://{1}:{2}@{3}/gitweb/{4}'.format(
|
||||
scheme, config['DEFAULT']['username'], password, url, repo)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _gitweb_temp_directory():
|
||||
"""Create temporary directory"""
|
||||
name = tempfile.mkdtemp(prefix='plinth_test_gitweb_')
|
||||
yield name
|
||||
shutil.rmtree(name)
|
||||
|
||||
|
||||
def _gitweb_git_command_is_successful(command, cwd):
|
||||
"""Check if a command runs successfully or gives authentication error"""
|
||||
process = subprocess.run(command, capture_output=True, cwd=cwd)
|
||||
if process.returncode != 0:
|
||||
if 'Authentication failed' in process.stderr.decode():
|
||||
return False
|
||||
print(process.stdout.decode())
|
||||
# raise exception
|
||||
process.check_returncode()
|
||||
return True
|
||||
|
||||
|
||||
def gitweb_repo_exists(browser, repo, access=None):
|
||||
"""Check whether the repository exists."""
|
||||
interface.nav_to_module(browser, 'gitweb')
|
||||
links_found = browser.find_link_by_href('/gitweb/{}.git'.format(repo))
|
||||
access_matches = True
|
||||
if links_found and access:
|
||||
parent = links_found.first.find_by_xpath('..').first
|
||||
private_icon = parent.find_by_css('.repo-private-icon')
|
||||
if access == 'private':
|
||||
access_matches = True if private_icon else False
|
||||
if access == 'public':
|
||||
access_matches = True if not private_icon else False
|
||||
return bool(links_found) and access_matches
|
||||
|
||||
|
||||
def gitweb_repo_is_readable(repo, with_auth=False, url_git_extension=False):
|
||||
"""Check if a git repo is readable with git client."""
|
||||
url = _gitweb_get_repo_url(repo, with_auth)
|
||||
if url_git_extension:
|
||||
url = url + '.git'
|
||||
git_command = ['git', 'clone', '-c', 'http.sslverify=false', url]
|
||||
with _gitweb_temp_directory() as cwd:
|
||||
return _gitweb_git_command_is_successful(git_command, cwd)
|
||||
|
||||
|
||||
def gitweb_repo_is_writable(repo, with_auth=False, url_git_extension=False):
|
||||
"""Check if a git repo is writable with git client."""
|
||||
url = _gitweb_get_repo_url(repo, with_auth)
|
||||
if url_git_extension:
|
||||
url = url + '.git'
|
||||
|
||||
with _gitweb_temp_directory() as cwd:
|
||||
subprocess.run(['mkdir', 'test-project'], check=True, cwd=cwd)
|
||||
cwd = os.path.join(cwd, 'test-project')
|
||||
prepare_git_repo_commands = [
|
||||
'git init -q', 'git config http.sslVerify false',
|
||||
'git commit -q --allow-empty --author "Tester <>" -m "test"'
|
||||
]
|
||||
for command in prepare_git_repo_commands:
|
||||
subprocess.run(command, shell=True, check=True, cwd=cwd)
|
||||
git_push_command = ['git', 'push', '-qf', url, 'master']
|
||||
|
||||
return _gitweb_git_command_is_successful(git_push_command, cwd)
|
||||
|
||||
|
||||
def gitweb_set_repo_access(browser, repo, access):
|
||||
"""Set repository as public or private."""
|
||||
interface.nav_to_module(browser, 'gitweb')
|
||||
browser.find_link_by_href(
|
||||
'/plinth/apps/gitweb/{}/edit/'.format(repo)).first.click()
|
||||
if access == 'private':
|
||||
browser.find_by_id('id_gitweb-is_private').check()
|
||||
else:
|
||||
browser.find_by_id('id_gitweb-is_private').uncheck()
|
||||
submit(browser)
|
||||
|
||||
|
||||
def gitweb_set_all_repos_private(browser):
|
||||
"""Set all repositories private"""
|
||||
interface.nav_to_module(browser, 'gitweb')
|
||||
public_repos = []
|
||||
for element in browser.find_by_css('#gitweb-repo-list .list-group-item'):
|
||||
if not element.find_by_css('.repo-private-icon'):
|
||||
repo = element.find_by_css('.repo-label').first.text
|
||||
public_repos.append(repo)
|
||||
for repo in public_repos:
|
||||
gitweb_set_repo_access(browser, repo, 'private')
|
||||
|
||||
|
||||
def gitweb_site_repo_exists(browser, repo):
|
||||
"""Check whether the repository exists on Gitweb site."""
|
||||
browser.visit('{}/gitweb'.format(default_url))
|
||||
return browser.find_by_css('a[href="/gitweb/{0}.git"]'.format(repo))
|
||||
|
||||
|
||||
def ikiwiki_create_wiki_if_needed(browser):
|
||||
"""Create wiki if it does not exist."""
|
||||
interface.nav_to_module(browser, 'ikiwiki')
|
||||
|
||||
@ -54,7 +54,7 @@
|
||||
{% if not repos %}
|
||||
<p>{% trans 'No repositories available.' %}</p>
|
||||
{% else %}
|
||||
<div class="list-group">
|
||||
<div id="gitweb-repo-list" class="list-group">
|
||||
{% for repo in repos %}
|
||||
<div class="list-group-item clearfix">
|
||||
<a href="{% url 'gitweb:delete' repo.name %}"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user