mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-28 08:03:36 +00:00
- Move non-reusable app specific step definitions and helper methods into <app>/tests/test_functional.py. - Merge reusable helper methods into plinth.tests.functional - Merge reusable step definitions into plinth.tests.functional.step_definitions - avahi, datetime, ikiwiki: Reuse common methods to avoid repetition. Avoid mapping from app nicknames to actual app names. - deluge, transmission: Make a copy of sample.torrent for each app to avoid clogging common place. - Implement functional.visit() to simplify a lot of browser.visit() calls. - Ensure that name of the mark on functional tests for an app is same as name of the app. This will help with predicting the mark when running tests for a particular app. Tests performed: - Run all functional tests. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: Joseph Nuthalapati <njoseph@riseup.net>
314 lines
11 KiB
Python
314 lines
11 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
"""
|
|
Functional, browser based tests for gitweb app.
|
|
"""
|
|
|
|
import contextlib
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
|
|
from pytest_bdd import given, parsers, scenarios, then, when
|
|
|
|
from plinth.tests import functional
|
|
|
|
scenarios('gitweb.feature')
|
|
|
|
_default_url = functional.config['DEFAULT']['url']
|
|
|
|
|
|
@given('a public repository')
|
|
@given('a repository')
|
|
@given('at least one repository exists')
|
|
def gitweb_repo(session_browser):
|
|
_create_repo(session_browser, 'Test-repo', 'public', True)
|
|
|
|
|
|
@given('a private repository')
|
|
def gitweb_private_repo(session_browser):
|
|
_create_repo(session_browser, 'Test-repo', 'private', True)
|
|
|
|
|
|
@given('both public and private repositories exist')
|
|
def gitweb_public_and_private_repo(session_browser):
|
|
_create_repo(session_browser, 'Test-repo', 'public', True)
|
|
_create_repo(session_browser, 'Test-repo2', 'private', True)
|
|
|
|
|
|
@given(parsers.parse("a {access:w} repository that doesn't exist"))
|
|
def gitweb_nonexistent_repo(session_browser, access):
|
|
_delete_repo(session_browser, 'Test-repo', ignore_missing=True)
|
|
return dict(access=access)
|
|
|
|
|
|
@given('all repositories are private')
|
|
def gitweb_all_repositories_private(session_browser):
|
|
_set_all_repos_private(session_browser)
|
|
|
|
|
|
@given(parsers.parse('a repository metadata:\n{metadata}'))
|
|
def gitweb_repo_metadata(session_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(session_browser, access):
|
|
_create_repo(session_browser, 'Test-repo', access)
|
|
|
|
|
|
@when('I delete the repository')
|
|
def gitweb_delete_repo(session_browser):
|
|
_delete_repo(session_browser, 'Test-repo')
|
|
|
|
|
|
@when('I set the metadata of the repository')
|
|
def gitweb_edit_repo_metadata(session_browser, gitweb_repo_metadata):
|
|
_edit_repo_metadata(session_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(session_browser):
|
|
assert _repo_exists(session_browser, 'Test-repo', access='public')
|
|
|
|
|
|
@then('the repository should be listed as a private')
|
|
def gitweb_private_repo_should_exists(session_browser):
|
|
assert _repo_exists(session_browser, 'Test-repo', 'private')
|
|
|
|
|
|
@then('the repository should not be listed')
|
|
def gitweb_repo_should_not_exist(session_browser, gitweb_repo):
|
|
assert not _repo_exists(session_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(session_browser):
|
|
assert _site_repo_exists(session_browser, 'Test-repo')
|
|
|
|
|
|
@then('the private repository should not be listed on gitweb')
|
|
def gitweb_private_repo_should_exists_on_gitweb(session_browser):
|
|
assert not _site_repo_exists(session_browser, 'Test-repo2')
|
|
|
|
|
|
@then('the metadata of the repository should be as set')
|
|
def gitweb_repo_metadata_should_match(session_browser, gitweb_repo_metadata):
|
|
actual_metadata = _get_repo_metadata(session_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 _repo_is_readable('Test-repo')
|
|
assert _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 _repo_is_readable('Test-repo')
|
|
assert not _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 _repo_is_writable('Test-repo')
|
|
assert not _repo_is_writable('Test-repo', url_git_extension=True)
|
|
|
|
|
|
@then('the repository should be privately readable')
|
|
def gitweb_repo_privately_readable():
|
|
assert _repo_is_readable('Test-repo', with_auth=True)
|
|
assert _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 _repo_is_writable('Test-repo', with_auth=True)
|
|
assert _repo_is_writable('Test-repo', with_auth=True,
|
|
url_git_extension=True)
|
|
|
|
|
|
def _create_repo(browser, repo, access=None, ok_if_exists=False):
|
|
"""Create repository."""
|
|
if not _repo_exists(browser, repo, access):
|
|
_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()
|
|
functional.submit(browser)
|
|
elif not ok_if_exists:
|
|
assert False, 'Repo already exists.'
|
|
|
|
|
|
def _delete_repo(browser, repo, ignore_missing=False):
|
|
"""Delete repository."""
|
|
functional.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()
|
|
functional.submit(browser)
|
|
|
|
|
|
def _edit_repo_metadata(browser, repo, metadata):
|
|
"""Set repository metadata."""
|
|
functional.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()
|
|
functional.submit(browser)
|
|
|
|
|
|
def _get_repo_metadata(browser, repo):
|
|
"""Get repository metadata."""
|
|
functional.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 _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 = functional.config['DEFAULT']['password']
|
|
|
|
return '{0}://{1}:{2}@{3}/gitweb/{4}'.format(
|
|
scheme, functional.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 _repo_exists(browser, repo, access=None):
|
|
"""Check whether the repository exists."""
|
|
functional.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 = bool(private_icon)
|
|
if access == 'public':
|
|
access_matches = not bool(private_icon)
|
|
return bool(links_found) and access_matches
|
|
|
|
|
|
def _repo_is_readable(repo, with_auth=False, url_git_extension=False):
|
|
"""Check if a git repo is readable with git client."""
|
|
url = _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 _repo_is_writable(repo, with_auth=False, url_git_extension=False):
|
|
"""Check if a git repo is writable with git client."""
|
|
url = _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 -c "user.name=Tester" -c "user.email=tester" '
|
|
'commit -q --allow-empty -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 _set_repo_access(browser, repo, access):
|
|
"""Set repository as public or private."""
|
|
functional.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()
|
|
functional.submit(browser)
|
|
|
|
|
|
def _set_all_repos_private(browser):
|
|
"""Set all repositories private"""
|
|
functional.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:
|
|
_set_repo_access(browser, repo, 'private')
|
|
|
|
|
|
def _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))
|