import asyncio import tempfile import unittest from pathlib import Path import httpx from halloween.web import create_app class WebTest(unittest.TestCase): def test_demo_live_image_and_controls(self): async def scenario(): with tempfile.TemporaryDirectory() as folder: app = create_app(demo=True, state_dir=Path(folder)) app.state.camera.start() try: transport = httpx.ASGITransport(app=app) async with httpx.AsyncClient(transport=transport, base_url="http://local") as client: page = await client.get("/") self.assertEqual(page.status_code, 200) self.assertIn("/stream.mjpg", page.text) self.assertIn("Grabablauf nur simuliert", page.text) for _ in range(30): if (await client.get("/api/status")).json()["camera"]["ready"]: break await asyncio.sleep(0.05) image = await client.get("/snapshot.jpg") self.assertEqual(image.status_code, 200) self.assertTrue(image.content.startswith(b"\xff\xd8")) self.assertEqual((await client.post("/api/stop")).status_code, 403) headers = {"X-Halloween-UI": "1"} self.assertEqual((await client.post("/api/stop", headers=headers)).status_code, 200) self.assertTrue((await client.get("/api/status")).json()["controller"]["stopped"]) self.assertEqual((await client.post("/api/reset", headers=headers)).status_code, 200) result = await client.post( "/api/mode", headers=headers, json={"mode": "sanft"} ) self.assertEqual(result.status_code, 200) self.assertEqual((await client.get("/api/status")).json()["controller"]["mode"], "sanft") route = next(route for route in app.routes if route.path == "/stream.mjpg") response = await route.endpoint() first = await response.body_iterator.__anext__() self.assertTrue(first.startswith(b"--frame\r\nContent-Type: image/jpeg")) await response.body_iterator.aclose() finally: app.state.camera.stop() asyncio.run(scenario()) if __name__ == "__main__": unittest.main()