test: add e2e tests for service store install/uninstall flow
Unit Tests / test (push) Successful in 11m13s

Tests verify:
- /services page loads and lists all available services
- Admin can install calendar, files, email, and webmail via the store UI
- Install order respects dependencies (email before webmail)
- Uninstall flow shows confirmation dialog before removing
- Dashboard shows service links after install

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-30 04:51:10 -04:00
parent f7bb2cc962
commit 5ed75677c3
+175
View File
@@ -0,0 +1,175 @@
"""
Service Store E2E tests.
Tests that the admin can install and remove store services via the /store page.
Requires a running PIC stack with access to the service store index and registry.
Run with:
pytest tests/e2e/ui/test_service_store.py -v --base-url http://<pic-host>
"""
import pytest
pytestmark = pytest.mark.ui
STORE_ROUTE = '/services'
# Services to install in dependency order (webmail requires email)
INSTALL_ORDER = ['calendar', 'files', 'email', 'webmail']
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _goto_store(page, webui_base):
page.goto(f"{webui_base}{STORE_ROUTE}")
page.wait_for_load_state('networkidle')
def _service_card(page, service_name):
"""Return the card element containing the named service."""
return page.locator('.card', has=page.get_by_text(service_name, exact=False)).first
def _is_installed(page, service_name):
card = _service_card(page, service_name)
return card.get_by_text('Installed', exact=False).is_visible()
def _install_service(page, webui_base, service_name, timeout_ms=180_000):
"""Click Install on a service card and wait until the card shows Installed."""
_goto_store(page, webui_base)
card = _service_card(page, service_name)
install_btn = card.get_by_role('button', name='Install')
install_btn.click()
# Wait for the Install button to disappear (replaced by Remove) or for
# the Installed badge to appear — whichever comes first.
card.get_by_text('Installed', exact=False).wait_for(state='visible', timeout=timeout_ms)
def _remove_service(page, webui_base, service_name, timeout_ms=60_000):
"""Click Uninstall on a service card and confirm, then wait until Install reappears."""
_goto_store(page, webui_base)
card = _service_card(page, service_name)
card.get_by_role('button', name='Uninstall').click()
# A confirmation dialog appears — click the confirm Uninstall button
page.get_by_role('button', name='Uninstall Service').wait_for(state='visible', timeout=5000)
page.get_by_role('button', name='Uninstall Service').click()
card.get_by_role('button', name='Install').wait_for(state='visible', timeout=timeout_ms)
# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------
def test_store_page_loads(admin_page, webui_base):
"""Store page must load and list available services without errors."""
page = admin_page
_goto_store(page, webui_base)
# Should not show a generic error message
assert 'Could not load the service store' not in page.content(), (
'Store page showed error: could not load the service store'
)
# At least one service card should be visible
cards = page.locator('.card').all()
assert len(cards) > 0, 'No service cards found on the store page'
def test_store_shows_known_services(admin_page, webui_base):
"""Store page must list email, calendar, files, and webmail."""
page = admin_page
_goto_store(page, webui_base)
for name in ('Email Server', 'Calendar', 'File Storage', 'Webmail'):
assert page.get_by_text(name, exact=False).first.is_visible(), (
f"Expected service '{name}' not visible on store page"
)
def test_install_calendar(admin_page, webui_base):
"""Admin can install the calendar service."""
page = admin_page
_goto_store(page, webui_base)
if _is_installed(page, 'Calendar'):
pytest.skip('calendar already installed — skipping install test')
_install_service(page, webui_base, 'Calendar & Contacts', timeout_ms=180_000)
assert _is_installed(page, 'Calendar'), (
'Calendar service card did not show Installed after install'
)
def test_install_files(admin_page, webui_base):
"""Admin can install the file storage service."""
page = admin_page
_goto_store(page, webui_base)
if _is_installed(page, 'File Storage'):
pytest.skip('files already installed — skipping install test')
_install_service(page, webui_base, 'File Storage', timeout_ms=180_000)
assert _is_installed(page, 'File Storage'), (
'Files service card did not show Installed after install'
)
def test_install_email(admin_page, webui_base):
"""Admin can install the email service."""
page = admin_page
_goto_store(page, webui_base)
if _is_installed(page, 'Email Server'):
pytest.skip('email already installed — skipping install test')
_install_service(page, webui_base, 'Email Server', timeout_ms=300_000)
assert _is_installed(page, 'Email Server'), (
'Email service card did not show Installed after install'
)
def test_install_webmail(admin_page, webui_base):
"""Admin can install webmail after email is installed."""
page = admin_page
_goto_store(page, webui_base)
if not _is_installed(page, 'Email Server'):
pytest.skip('email not installed — webmail requires email first')
if _is_installed(page, 'Webmail'):
pytest.skip('webmail already installed — skipping install test')
_install_service(page, webui_base, 'Webmail', timeout_ms=180_000)
assert _is_installed(page, 'Webmail'), (
'Webmail service card did not show Installed after install'
)
def test_installed_services_appear_on_dashboard(admin_page, webui_base):
"""After installation, services should appear as links on the dashboard."""
page = admin_page
_goto_store(page, webui_base)
page.goto(f"{webui_base}/")
page.wait_for_load_state('networkidle')
# Check that at least the Cell Home link is present
assert page.get_by_text('Cell Home', exact=False).is_visible(), (
'Dashboard does not show the Cell Home service link'
)
def test_uninstall_webmail(admin_page, webui_base):
"""Admin can uninstall the webmail service."""
page = admin_page
_goto_store(page, webui_base)
if not _is_installed(page, 'Webmail'):
pytest.skip('webmail not installed — skipping uninstall test')
_remove_service(page, webui_base, 'Webmail')
assert not _is_installed(page, 'Webmail'), (
'Webmail service card still shows Installed after uninstall'
)