from __future__ import annotations import asyncio import gzip import json import tempfile import time import unittest from pathlib import Path from websockets.asyncio.server import serve from polymarket_collector.state import CollectorState from polymarket_collector.storage import RotatingJsonlWriter from polymarket_collector.stream import MarketStream class StreamTests(unittest.IsolatedAsyncioTestCase): async def test_records_public_market_message(self) -> None: subscription_received = asyncio.Event() async def handler(websocket) -> None: subscription = json.loads(await websocket.recv()) self.assertEqual(subscription["assets_ids"], ["asset-1", "asset-2"]) subscription_received.set() await websocket.send( json.dumps( { "event_type": "book", "asset_id": "asset-1", "market": "condition-1", "bids": [], "asks": [], "timestamp": "1", } ) ) while True: try: message = await websocket.recv() except Exception: return if message == "PING": await websocket.send("PONG") with tempfile.TemporaryDirectory() as temporary: writer = RotatingJsonlWriter( Path(temporary), "stream", rotation_seconds=3600, max_file_bytes=1024 * 1024, flush_interval_seconds=1, ) await writer.start() state = CollectorState() stop = asyncio.Event() async with serve(handler, "127.0.0.1", 0) as websocket_server: port = websocket_server.sockets[0].getsockname()[1] stream = MarketStream( f"ws://127.0.0.1:{port}", writer, state ) stream.set_assets(["asset-1", "asset-2"]) task = asyncio.create_task(stream.run(stop)) await asyncio.wait_for(subscription_received.wait(), 2) deadline = time.monotonic() + 2 while state.messages_total < 1 and time.monotonic() < deadline: await asyncio.sleep(0.01) stop.set() await asyncio.wait_for(task, 3) await writer.close() self.assertEqual(state.messages_total, 1) archive = next(Path(temporary).rglob("*.jsonl.gz")) with gzip.open(archive, "rt", encoding="utf-8") as handle: record = json.loads(handle.readline()) self.assertEqual(record["payload"]["event_type"], "book") self.assertIn("received_at_ns", record) if __name__ == "__main__": unittest.main()