Skip to content

Commit 4415921

Browse files
test(ws): assert real data on /liquidation/feed live test (#202)
* test(ws): assert real data on /liquidation/feed live test backend now replays last N liquidations on connect (snap:true), so a fresh connection deterministically yields data — assert it like ticker, quiet window is a FAIL. Close #201. * test(ws): coerce liquidation feed d to int for wire str/int tolerance
1 parent 96adc9a commit 4415921

1 file changed

Lines changed: 43 additions & 3 deletions

File tree

tests/test_ws_live.py

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
window (no message in the timeout) is a PASS — the value is that connect +
99
auth + SUBSCRIBE succeed without raising; when a message does arrive its shape
1010
is still checked.
11-
- High-traffic (continuous): `/ticker` and `/premium`. These emit non-stop, so
12-
a quiet window is a FAIL — the test asserts a real, well-formed data payload
13-
actually arrives, proving the SDK decodes and yields end-to-end.
11+
- Guaranteed-data: `/ticker` and `/premium` emit non-stop; `/liquidation/feed`
12+
replays the last N liquidations immediately on connect. Either way a fresh
13+
connection yields data, so a quiet window is a FAIL — the test asserts a real,
14+
well-formed data payload actually arrives, proving the SDK decodes and yields
15+
end-to-end.
1416
1517
Opt-in and deselected from the keyless CI lane via the `integration` marker;
1618
needs DATAMAXI_API_KEY. Skipped when `websockets` absent.
@@ -41,6 +43,11 @@
4143
# /forex is quiet-tolerant but its first tick can lag (~14s observed); wait a bit
4244
# longer than _QUIET_TIMEOUT so an arriving tick gets shape-checked, not skipped.
4345
_FOREX_TIMEOUT = 20.0
46+
# /liquidation/feed replays the last N liquidations immediately on connect, so
47+
# data lands within the handshake — a short timeout suffices and a quiet window
48+
# is a FAIL. Number of leading frames to collect for the snap-replay assertion.
49+
_REPLAY_TIMEOUT = 10.0
50+
_REPLAY_FRAMES = 5
4451

4552

4653
def _run(coro):
@@ -141,6 +148,39 @@ async def run():
141148
assert "premium" in msg
142149

143150

151+
def test_ws_liquidation_feed_replays_on_connect():
152+
# /liquidation/feed is a connect-only firehose (no SUBSCRIBE, no params). The
153+
# backend replays the last N liquidations immediately on connect (each frame
154+
# tagged `snap: true`), so a fresh connection deterministically yields data
155+
# and — like ticker — a quiet window is a FAIL. A live event may interleave
156+
# between replayed frames, so the first frame is not guaranteed to be replay;
157+
# assert `snap: true` on at least one of the first few frames, not frame[0].
158+
# (This couples the test to replay being enabled: with
159+
# LIQUIDATION_FEED_REPLAY_N=0 in the target env, it FAILs rather than skips —
160+
# deliberately, so an accidentally-disabled replay is caught.)
161+
async def run():
162+
async with AsyncDatamaxiWS(api_key=API_KEY, base_url=BASE_URL) as ws:
163+
stream = await ws.liquidation_feed.stream()
164+
frames = []
165+
try:
166+
while len(frames) < _REPLAY_FRAMES:
167+
frames.append(
168+
await asyncio.wait_for(stream.__anext__(), _REPLAY_TIMEOUT)
169+
)
170+
except asyncio.TimeoutError:
171+
pass # fewer than N in the ring; keep what arrived
172+
return frames
173+
174+
frames = _run(run())
175+
assert frames, "no liquidation frame within timeout (replay disabled?)"
176+
first = frames[0]
177+
assert isinstance(first, dict)
178+
for field in ("e", "d", "s", "b", "q", "sd"):
179+
assert field in first, f"missing {field!r} in {first!r}"
180+
assert int(first["d"]) > 1_000_000_000_000 # plausible UNIX-ms (str or int)
181+
assert any(f.get("snap") is True for f in frames)
182+
183+
144184
def test_ws_forex_tolerates_quiet_window():
145185
# /forex is continuous during FX market hours but the first tick can lag
146186
# (~14s observed) and FX spot does not trade weekends — so a quiet window is

0 commit comments

Comments
 (0)