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