test_app.py raw

   1  """App loading tests — verify the sm3sh app renders in the browser."""
   2  
   3  import json
   4  import time
   5  
   6  import pytest
   7  import websocket
   8  from selenium.webdriver.common.by import By
   9  
  10  from nostr_helpers import TEST_SECKEY, TEST_PUBKEY, make_event
  11  
  12  
  13  class TestAppLoad:
  14      """Verify the app loads and renders basic UI."""
  15  
  16      def test_page_loads(self, relay, browser):
  17          browser.get(relay["url"])
  18          time.sleep(2)
  19          title = browser.title
  20          assert "smesh" in title.lower()
  21  
  22      def test_root_element(self, relay, browser, h):
  23          browser.get(relay["url"])
  24          time.sleep(2)
  25          root = browser.find_element(By.ID, "app-root")
  26          assert root is not None
  27          # The root should have children (the app rendered).
  28          children = root.find_elements(By.XPATH, "./*")
  29          assert len(children) > 0, "app-root has no children — JS may have failed"
  30  
  31      def test_console_log_version(self, relay, browser, h):
  32          browser.get(relay["url"])
  33          time.sleep(2)
  34          # The app logs "starting smesh <version>" on init.
  35          version = h.js("return document.querySelector('[data-version]')?.getAttribute('data-version')")
  36          assert version is not None, "data-version attribute not found"
  37  
  38      def test_login_screen(self, relay, browser, h):
  39          """Without a stored pubkey, the app should show a login screen."""
  40          # Clear localStorage to ensure clean state.
  41          browser.get(relay["url"])
  42          time.sleep(1)
  43          h.js("localStorage.clear()")
  44          browser.refresh()
  45          time.sleep(2)
  46          # Look for login-related elements (button or input).
  47          page = h.js("return document.body.innerText")
  48          assert page is not None
  49  
  50  
  51  class TestFeed:
  52      """Verify the kind-1 note feed renders."""
  53  
  54      def test_feed_notes_appear(self, relay, browser, h):
  55          """Seed events to local relay, then verify feed renders them."""
  56          # Publish a few kind-1 notes to the local relay via WebSocket.
  57          ws = websocket.create_connection(relay["ws"])
  58          for i in range(3):
  59              ev = make_event(TEST_SECKEY, f"test note {i}")
  60              ws.send(json.dumps(["EVENT", ev]))
  61              resp = ws.recv()
  62          ws.close()
  63  
  64          # Load app with the test pubkey.
  65          browser.get(relay["url"])
  66          time.sleep(1)
  67          h.js(f"localStorage.setItem('smesh-pubkey', '{TEST_PUBKEY}')")
  68          browser.get(relay["url"])
  69          time.sleep(12)
  70          notes = h.js("return document.querySelectorAll('div[style*=\"border-bottom\"]').length")
  71          assert notes > 0, "no kind-1 notes rendered in the feed"
  72  
  73  
  74  class TestAppTheme:
  75      """Theme toggle works."""
  76  
  77      def test_dark_mode_toggle(self, relay, browser, h):
  78          browser.get(relay["url"])
  79          time.sleep(2)
  80          has_dark = h.js("return document.body.classList.contains('dark')")
  81          # Toggle — find any button in the top bar area.
  82          # The theme button is a small button with a sun/moon emoji.
  83          # We can't easily target it by text since it's an HTML entity,
  84          # so we'll check the class toggles by setting localStorage.
  85          h.js("localStorage.setItem('smesh-theme', 'dark')")
  86          browser.refresh()
  87          time.sleep(2)
  88          is_dark = h.js("return document.body.classList.contains('dark')")
  89          assert is_dark, "dark class not applied after setting theme preference"
  90  
  91          h.js("localStorage.setItem('smesh-theme', 'light')")
  92          browser.refresh()
  93          time.sleep(2)
  94          is_light = not h.js("return document.body.classList.contains('dark')")
  95          assert is_light, "dark class still present after setting light theme"
  96