"""
Peer dashboard and My Services page tests.
Scenarios:
12. Peer sees their own dashboard (PeerDashboard.jsx renders peer.name as
)
13. Peer's My Services page loads and shows all service sections
14. Peer dashboard shows service icon links (calendar, files, mail, webdav)
15. My Services shows correct CalDAV URL (calendar.dev not radicale.dev:5232)
16. My Services shows email address field (not username)
Key selectors from PeerDashboard.jsx:
- h1 shows peer.name (peer.name from /api/peer/dashboard)
- "VPN Address" stat card label
- "Quick Access" section with service icon links from service_urls
- "My Services" link
Key selectors from MyServices.jsx:
- h2 "WireGuard VPN"
- h2 "Email", h2 "Calendar & Contacts", h2 "Files"
- "Address" label for email (not "Username")
- "CalDAV URL" label with calendar.dev value
"""
import pytest
pytestmark = pytest.mark.ui
# ── 12. Peer dashboard ───────────────────────────────────────────────────────
def test_peer_sees_peer_dashboard(peer_page, webui_base):
"""Peer lands on the root route which renders PeerDashboard, not the admin Dashboard."""
page, peer = peer_page
page.wait_for_load_state('networkidle')
assert '/login' not in page.url
def test_peer_dashboard_shows_peer_name(peer_page, webui_base):
"""PeerDashboard.jsx renders peer.name as the page ."""
page, peer = peer_page
page.wait_for_load_state('networkidle')
try:
# PeerDashboard line 61: {peer.name || 'My Dashboard'}
page.wait_for_selector(
f'h1:has-text("{peer["name"]}")',
timeout=6000,
)
except Exception:
pytest.xfail(
f"Peer name '{peer['name']}' not found as on PeerDashboard. "
"Check that the /api/peer/dashboard endpoint returns the peer name "
"and that PeerDashboard.jsx renders it."
)
def test_peer_dashboard_shows_vpn_address_label(peer_page, webui_base):
"""PeerDashboard.jsx shows a 'VPN Address' stat card."""
page, _ = peer_page
page.wait_for_load_state('networkidle')
try:
page.wait_for_selector('text=VPN Address', timeout=5000)
except Exception:
pytest.xfail(
"VPN Address stat card not found — check PeerDashboard.jsx stat card labels"
)
def test_peer_dashboard_has_my_services_link(peer_page, webui_base):
"""PeerDashboard.jsx renders a 'My Services' quick-access link."""
page, _ = peer_page
page.wait_for_load_state('networkidle')
try:
page.wait_for_selector('a:has-text("My Services"), button:has-text("My Services")', timeout=5000)
except Exception:
pytest.xfail(
"'My Services' link not found on peer dashboard — check PeerDashboard.jsx Quick Access section"
)
# ── 13. My Services page ─────────────────────────────────────────────────────
def test_peer_my_services_page_loads(peer_page, webui_base):
"""Peer can navigate to /my-services without being redirected."""
page, _ = peer_page
page.goto(f"{webui_base}/my-services")
page.wait_for_load_state('networkidle')
assert '/login' not in page.url
def test_peer_my_services_shows_wireguard_section(peer_page, webui_base):
"""MyServices.jsx renders a 'WireGuard VPN' section heading."""
page, _ = peer_page
page.goto(f"{webui_base}/my-services")
page.wait_for_load_state('networkidle')
try:
page.wait_for_selector('h2:has-text("WireGuard VPN")', timeout=5000)
except Exception:
pytest.xfail(
"WireGuard VPN section heading not found on /my-services — "
"check MyServices.jsx and /api/peer/services endpoint"
)
def test_peer_my_services_shows_email_section(peer_page, webui_base):
"""MyServices.jsx renders an 'Email' section heading."""
page, _ = peer_page
page.goto(f"{webui_base}/my-services")
page.wait_for_load_state('networkidle')
try:
page.wait_for_selector('h2:has-text("Email")', timeout=5000)
except Exception:
pytest.xfail(
"Email section heading not found on /my-services"
)
def test_peer_my_services_shows_calendar_section(peer_page, webui_base):
"""MyServices.jsx renders a 'Calendar & Contacts' section heading."""
page, _ = peer_page
page.goto(f"{webui_base}/my-services")
page.wait_for_load_state('networkidle')
try:
page.wait_for_selector('h2:has-text("Calendar")', timeout=5000)
except Exception:
pytest.xfail(
"Calendar section heading not found on /my-services"
)
def test_peer_my_services_shows_files_section(peer_page, webui_base):
"""MyServices.jsx renders a 'Files' section heading."""
page, _ = peer_page
page.goto(f"{webui_base}/my-services")
page.wait_for_load_state('networkidle')
try:
page.wait_for_selector('h2:has-text("Files")', timeout=5000)
except Exception:
pytest.xfail(
"Files section heading not found on /my-services"
)
# ── 14. Service icon links ────────────────────────────────────────────────────
def test_peer_dashboard_has_calendar_link(peer_page, webui_base):
"""PeerDashboard Quick Access section renders a Calendar icon link."""
page, _ = peer_page
page.wait_for_load_state('networkidle')
try:
page.wait_for_selector('a:has-text("Calendar")', timeout=5000)
except Exception:
pytest.xfail(
"Calendar link not found on peer dashboard Quick Access — "
"check that service_urls.calendar is populated and PeerDashboard.jsx renders it"
)
def test_peer_dashboard_has_files_link(peer_page, webui_base):
"""PeerDashboard Quick Access section renders a Files icon link."""
page, _ = peer_page
page.wait_for_load_state('networkidle')
try:
page.wait_for_selector('a:has-text("Files")', timeout=5000)
except Exception:
pytest.xfail(
"Files link not found on peer dashboard Quick Access"
)
def test_peer_dashboard_has_mail_link(peer_page, webui_base):
"""PeerDashboard Quick Access section renders a Mail icon link."""
page, _ = peer_page
page.wait_for_load_state('networkidle')
try:
page.wait_for_selector('a:has-text("Mail")', timeout=5000)
except Exception:
pytest.xfail(
"Mail link not found on peer dashboard Quick Access"
)
# ── 15. CalDAV URL correctness ────────────────────────────────────────────────
def test_peer_my_services_caldav_url_no_radicale(peer_page, webui_base):
"""CalDAV URL shown in My Services must not contain 'radicale' (no DNS record)."""
page, _ = peer_page
page.goto(f"{webui_base}/my-services")
page.wait_for_load_state('networkidle')
try:
# If radicale.dev appears as CalDAV URL it means the bug is back
radicale_url = page.query_selector('text=radicale')
assert radicale_url is None, (
"Found 'radicale' text on My Services page — "
"CalDAV URL should be calendar.dev, not radicale.dev:5232"
)
except AssertionError:
raise
except Exception:
pass # page didn't load — other tests cover that
# ── 16. Email address display ─────────────────────────────────────────────────
def test_peer_my_services_shows_address_label(peer_page, webui_base):
"""MyServices.jsx renders 'Address' label for email (reads email.address)."""
page, _ = peer_page
page.goto(f"{webui_base}/my-services")
page.wait_for_load_state('networkidle')
try:
page.wait_for_selector('text=Address', timeout=5000)
except Exception:
pytest.xfail(
"'Address' label not found on My Services email section — "
"check that email.address is populated in /api/peer/services"
)