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:
Veiko Aasa 2019-10-22 20:42:09 +03:00 committed by Sunil Mohan Adapa
parent 273c419a26
commit 8694849701
No known key found for this signature in database
GPG Key ID: 43EA1CFF0AA7C5F2
4 changed files with 412 additions and 1 deletions

View 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

View File

@ -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)

View File

@ -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')

View File

@ -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 %}"