127 lines
4.5 KiB
Python
127 lines
4.5 KiB
Python
import unittest
|
|
from pathlib import Path
|
|
|
|
from frigate_camera_control_bridge.ui import camera_stream_url, render_page
|
|
|
|
|
|
class DummyAction:
|
|
def __init__(self, suffix="siren", name_key="action.siren", state="ON", kind="dahua_coaxial_io"):
|
|
self.id = f"example_camera_{suffix}"
|
|
self.platform = "switch"
|
|
self.kind = kind
|
|
self.state = state
|
|
self.auto_off_seconds = 180
|
|
self.auto_off_at = 1234567890
|
|
self.snapshot_version = 42
|
|
self.cfg = {
|
|
"name_key": name_key,
|
|
"camera_name": "Example camera",
|
|
"requires_ack": name_key == "action.siren",
|
|
"snapshot": {
|
|
"camera": "example",
|
|
"frigate_url": "http://frigate.example.test:5000",
|
|
},
|
|
}
|
|
|
|
def display_name(self, lang):
|
|
return f"Example {self.id}"
|
|
|
|
def command_list(self):
|
|
return ["on", "off"]
|
|
|
|
|
|
class UiRenderTest(unittest.TestCase):
|
|
def test_timer_timestamp_and_ack_survive_server_render(self):
|
|
html = render_page([DummyAction()], "en")
|
|
|
|
self.assertIn('data-auto-off-at="1234567890"', html)
|
|
self.assertIn('data-requires-ack="true"', html)
|
|
self.assertIn("Example camera", html)
|
|
self.assertIn("v=42", html)
|
|
self.assertIn('class="snapshot-refresh"', html)
|
|
self.assertIn('title="Refresh snapshot"', html)
|
|
self.assertIn('disabled title="Already active until automatic turn-off"', html)
|
|
|
|
def test_controls_from_same_camera_share_one_card(self):
|
|
actions = [
|
|
DummyAction("siren", "action.siren"),
|
|
DummyAction("white", "action.manual_white", state="OFF"),
|
|
DummyAction("red_blue", "action.red_blue", state="OFF"),
|
|
]
|
|
|
|
html = render_page(actions, "en")
|
|
|
|
self.assertIn('class="control-grid grid-single"', html)
|
|
self.assertEqual(html.count('class="camera-card"'), 1)
|
|
self.assertEqual(html.count('class="action-control"'), 3)
|
|
self.assertIn("3 controls", html)
|
|
self.assertIn("White light", html)
|
|
self.assertIn("Red-blue light", html)
|
|
self.assertIn("Siren", html)
|
|
|
|
def test_all_off_renders_in_topbar_not_camera_grid(self):
|
|
action = DummyAction("all_off", "action.all_off", state=None, kind="all_off")
|
|
|
|
html = render_page([action], "en")
|
|
|
|
self.assertIn('class="global-strip"', html)
|
|
self.assertIn('class="global-action"', html)
|
|
self.assertNotIn('class="camera-card"', html)
|
|
|
|
def test_refresh_button_preserves_language_and_token(self):
|
|
html = render_page([DummyAction()], "en", token_param="secret")
|
|
|
|
self.assertIn('class="refresh-form"', html)
|
|
self.assertIn('action="/refresh?lang=en&token=secret"', html)
|
|
self.assertIn('title="Refresh cameras"', html)
|
|
self.assertIn('aria-label="Refresh cameras"', html)
|
|
self.assertIn('data-refresh-status', html)
|
|
self.assertIn('data-working-label="Refreshing cameras..."', html)
|
|
self.assertIn("<svg", html)
|
|
|
|
def test_camera_stream_link_uses_default_frigate_url(self):
|
|
action = DummyAction()
|
|
|
|
self.assertEqual(
|
|
camera_stream_url(action),
|
|
"http://frigate.example.test:5000/#example",
|
|
)
|
|
|
|
def test_camera_stream_link_uses_public_proxy_url_from_env_config(self):
|
|
action = DummyAction()
|
|
action.cfg["snapshot"]["public_url"] = "https://frigate.example.test"
|
|
|
|
self.assertEqual(
|
|
camera_stream_url(action),
|
|
"https://frigate.example.test/#example",
|
|
)
|
|
|
|
def test_on_button_is_available_when_no_auto_off_timer_runs(self):
|
|
action = DummyAction()
|
|
action.auto_off_at = None
|
|
|
|
html = render_page([action], "en")
|
|
|
|
self.assertIn('class="cmd cmd-on"', html)
|
|
self.assertNotIn('Already active until automatic turn-off', html)
|
|
|
|
def test_camera_card_uses_friendly_display_name(self):
|
|
action = DummyAction()
|
|
action.cfg["camera_name"] = "camera_key"
|
|
action.cfg["camera_display_name"] = "Camera Friendly"
|
|
|
|
html = render_page([action], "en")
|
|
|
|
self.assertIn("<h2>Camera Friendly</h2>", html)
|
|
self.assertNotIn("<h2>camera_key</h2>", html)
|
|
|
|
def test_manual_snapshot_refresh_waits_before_fetch(self):
|
|
script = Path("frigate_camera_control_bridge/static/app.js").read_text(encoding="utf-8")
|
|
|
|
self.assertIn("SNAPSHOT_REFRESH_DELAY_MS = 2000", script)
|
|
self.assertIn("window.setTimeout", script)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|