Source code for univention.testing.browser.packagemanagement
#!/usr/bin/python3
# SPDX-FileCopyrightText: 2023-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only
import enum
import logging
import re
import apt
from playwright.sync_api import Page, expect
from univention.lib.i18n import Translation
from univention.testing.browser.lib import MIN, UMCBrowserTest
logger = logging.getLogger(__name__)
KB = 1000
MB = KB * 1000
_ = Translation('ucs-test-framework').translate
[docs]
class PackageAction(enum.Enum):
Install = 1
Uninstall = 2
def __str__(self) -> str:
if self == PackageAction.Install:
return _('Install')
elif self == PackageAction.Uninstall:
return _('Uninstall')
return ''
[docs]
def expected_status(self) -> str:
if self == PackageAction.Install:
return _('installed')
elif self == PackageAction.Uninstall:
return _('not installed')
return ''
[docs]
class PackageManagement:
"""Class for the Package Management UCS Module"""
def __init__(self, tester: UMCBrowserTest) -> None:
self.tester: UMCBrowserTest = tester
self.page: Page = tester.page
self.module_name = _('Package Management')
self.grid_load_url = re.compile('.*univention/command/appcenter/packages/query.*')
self.initial_grid_load_url = re.compile('.*univention/command/appcenter/packages/sections.*')
[docs]
def navigate(self, username='Administrator', password='univention'):
self.tester.login(username, password)
self.tester.open_module(self.module_name, self.initial_grid_load_url)
[docs]
def find_small_package(self) -> str:
"""
Finds a small package that is less than 0.5 MB, has no dependencies and recommended packages
:return: the package name
"""
logger.info('Trying to find small, uninstalled package with no dependencies and recommends')
cache = apt.cache.Cache()
cache.update()
cache.open()
for package in cache:
if (
package.candidate
and not package.is_installed
and package.candidate.installed_size < 0.5 * MB
and not package.candidate.recommends
and not package.candidate.dependencies
):
logger.info('Found %s', package)
return package.name
raise Exception('Failed to find a small package')
[docs]
def search_for_package(self, name: str):
search_bar = self.page.locator('[name=pattern]')
search_bar.fill('')
search_bar.press_sequentially(name)
with self.page.expect_response(self.grid_load_url):
search_bar.press('Enter')
[docs]
def do_package_action(self, name: str, action: PackageAction):
logger.info('Action %s on package %s', action, name)
self.search_for_package(name)
self.tester.check_checkbox_in_grid_by_name(name, 0)
self.page.get_by_role('button', name=str(action), exact=True).click()
self.handle_confirmation_dialog(str(action))
self.handle_action_dialog()
logger.info('%s done', action)
with self.page.expect_response(self.grid_load_url):
pass
[docs]
def handle_confirmation_dialog(self, action: str):
dialog = self.page.get_by_role('dialog', name=_('Confirmation'))
dialog.get_by_role('button', name=action).click()
expect(dialog).to_have_count(0)
[docs]
def handle_action_dialog(self):
dialog = self.page.get_by_role('dialog')
expect(dialog).to_have_count(0, timeout=3 * MIN)
pbar = self.page.get_by_role('progressbar')
expect(pbar).to_have_count(0, timeout=3 * MIN)
[docs]
def install_package(self, name: str):
"""Installs a package that is automatically chosen to be both small in size and has no dependencies and verifies that it is installed"""
self.do_package_action(name, PackageAction.Install)
self.verify_package_status(PackageAction.Install)
[docs]
def uninstall_package(self, name: str):
self.do_package_action(name, PackageAction.Uninstall)
self.verify_package_status(PackageAction.Uninstall)
[docs]
def verify_package_status(self, expected: PackageAction):
"""
Verify that the package actually got (un)installed
:param expected: If expected is `PackageAction.Install` this function will make sure that the package has been _installed_ and vice versa.
"""
status_cell = self.page.get_by_role('grid').get_by_role('gridcell').get_by_text(expected.expected_status())
expect(status_cell).to_have_count(1)
expect(status_cell).to_be_visible()