""" 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:// """ 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' )