Skip to content

Commit f8c1e42

Browse files
committed
test(websockets): add regression tests for no-arg control send_ methods
Also fixes AgentV1KeepAlive default to include type='KeepAlive' (bare AgentV1KeepAlive() fails Pydantic validation since type is required).
1 parent d09de8d commit f8c1e42

2 files changed

Lines changed: 188 additions & 2 deletions

File tree

src/deepgram/agent/v1/socket_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ async def send_keep_alive(self, message: typing.Optional[AgentV1KeepAlive] = Non
164164
Send a message to the websocket connection.
165165
The message will be sent as a AgentV1KeepAlive.
166166
"""
167-
await self._send_model(message or AgentV1KeepAlive())
167+
await self._send_model(message or AgentV1KeepAlive(type="KeepAlive"))
168168

169169
async def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None:
170170
"""
@@ -297,7 +297,7 @@ def send_keep_alive(self, message: typing.Optional[AgentV1KeepAlive] = None) ->
297297
Send a message to the websocket connection.
298298
The message will be sent as a AgentV1KeepAlive.
299299
"""
300-
self._send_model(message or AgentV1KeepAlive())
300+
self._send_model(message or AgentV1KeepAlive(type="KeepAlive"))
301301

302302
def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None:
303303
"""
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
"""Tests that control send_ methods work without requiring a message argument.
2+
3+
Regression test for the breaking change where optional message params were lost
4+
during a Fern regen, causing TypeError for callers using no-arg control calls.
5+
"""
6+
7+
import json
8+
from unittest.mock import AsyncMock, MagicMock
9+
10+
import pytest
11+
12+
from deepgram.agent.v1.socket_client import AsyncV1SocketClient as AsyncAgentV1SocketClient
13+
from deepgram.agent.v1.socket_client import V1SocketClient as AgentV1SocketClient
14+
from deepgram.listen.v1.socket_client import AsyncV1SocketClient as AsyncListenV1SocketClient
15+
from deepgram.listen.v1.socket_client import V1SocketClient as ListenV1SocketClient
16+
from deepgram.listen.v2.socket_client import AsyncV2SocketClient as AsyncListenV2SocketClient
17+
from deepgram.listen.v2.socket_client import V2SocketClient as ListenV2SocketClient
18+
from deepgram.speak.v1.socket_client import AsyncV1SocketClient as AsyncSpeakV1SocketClient
19+
from deepgram.speak.v1.socket_client import V1SocketClient as SpeakV1SocketClient
20+
21+
22+
# ---------------------------------------------------------------------------
23+
# Helpers
24+
# ---------------------------------------------------------------------------
25+
26+
def _make_async_ws():
27+
ws = AsyncMock()
28+
ws.send = AsyncMock()
29+
return ws
30+
31+
32+
def _make_sync_ws():
33+
ws = MagicMock()
34+
ws.send = MagicMock()
35+
return ws
36+
37+
38+
def _sent_json(ws):
39+
"""Return the parsed JSON from the first send() call."""
40+
call_args = ws.send.call_args
41+
data = call_args[0][0]
42+
return json.loads(data)
43+
44+
45+
# ---------------------------------------------------------------------------
46+
# speak/v1 — async
47+
# ---------------------------------------------------------------------------
48+
49+
class TestAsyncSpeakV1ControlMessages:
50+
async def test_send_flush_no_args(self):
51+
ws = _make_async_ws()
52+
client = AsyncSpeakV1SocketClient(websocket=ws)
53+
await client.send_flush()
54+
assert _sent_json(ws)["type"] == "Flush"
55+
56+
async def test_send_clear_no_args(self):
57+
ws = _make_async_ws()
58+
client = AsyncSpeakV1SocketClient(websocket=ws)
59+
await client.send_clear()
60+
assert _sent_json(ws)["type"] == "Clear"
61+
62+
async def test_send_close_no_args(self):
63+
ws = _make_async_ws()
64+
client = AsyncSpeakV1SocketClient(websocket=ws)
65+
await client.send_close()
66+
assert _sent_json(ws)["type"] == "Close"
67+
68+
69+
# ---------------------------------------------------------------------------
70+
# speak/v1 — sync
71+
# ---------------------------------------------------------------------------
72+
73+
class TestSyncSpeakV1ControlMessages:
74+
def test_send_flush_no_args(self):
75+
ws = _make_sync_ws()
76+
client = SpeakV1SocketClient(websocket=ws)
77+
client.send_flush()
78+
assert _sent_json(ws)["type"] == "Flush"
79+
80+
def test_send_clear_no_args(self):
81+
ws = _make_sync_ws()
82+
client = SpeakV1SocketClient(websocket=ws)
83+
client.send_clear()
84+
assert _sent_json(ws)["type"] == "Clear"
85+
86+
def test_send_close_no_args(self):
87+
ws = _make_sync_ws()
88+
client = SpeakV1SocketClient(websocket=ws)
89+
client.send_close()
90+
assert _sent_json(ws)["type"] == "Close"
91+
92+
93+
# ---------------------------------------------------------------------------
94+
# listen/v1 — async
95+
# ---------------------------------------------------------------------------
96+
97+
class TestAsyncListenV1ControlMessages:
98+
async def test_send_finalize_no_args(self):
99+
ws = _make_async_ws()
100+
client = AsyncListenV1SocketClient(websocket=ws)
101+
await client.send_finalize()
102+
assert _sent_json(ws)["type"] == "Finalize"
103+
104+
async def test_send_close_stream_no_args(self):
105+
ws = _make_async_ws()
106+
client = AsyncListenV1SocketClient(websocket=ws)
107+
await client.send_close_stream()
108+
assert _sent_json(ws)["type"] == "CloseStream"
109+
110+
async def test_send_keep_alive_no_args(self):
111+
ws = _make_async_ws()
112+
client = AsyncListenV1SocketClient(websocket=ws)
113+
await client.send_keep_alive()
114+
assert _sent_json(ws)["type"] == "KeepAlive"
115+
116+
117+
# ---------------------------------------------------------------------------
118+
# listen/v1 — sync
119+
# ---------------------------------------------------------------------------
120+
121+
class TestSyncListenV1ControlMessages:
122+
def test_send_finalize_no_args(self):
123+
ws = _make_sync_ws()
124+
client = ListenV1SocketClient(websocket=ws)
125+
client.send_finalize()
126+
assert _sent_json(ws)["type"] == "Finalize"
127+
128+
def test_send_close_stream_no_args(self):
129+
ws = _make_sync_ws()
130+
client = ListenV1SocketClient(websocket=ws)
131+
client.send_close_stream()
132+
assert _sent_json(ws)["type"] == "CloseStream"
133+
134+
def test_send_keep_alive_no_args(self):
135+
ws = _make_sync_ws()
136+
client = ListenV1SocketClient(websocket=ws)
137+
client.send_keep_alive()
138+
assert _sent_json(ws)["type"] == "KeepAlive"
139+
140+
141+
# ---------------------------------------------------------------------------
142+
# listen/v2 — async
143+
# ---------------------------------------------------------------------------
144+
145+
class TestAsyncListenV2ControlMessages:
146+
async def test_send_close_stream_no_args(self):
147+
ws = _make_async_ws()
148+
client = AsyncListenV2SocketClient(websocket=ws)
149+
await client.send_close_stream()
150+
assert _sent_json(ws)["type"] == "CloseStream"
151+
152+
153+
# ---------------------------------------------------------------------------
154+
# listen/v2 — sync
155+
# ---------------------------------------------------------------------------
156+
157+
class TestSyncListenV2ControlMessages:
158+
def test_send_close_stream_no_args(self):
159+
ws = _make_sync_ws()
160+
client = ListenV2SocketClient(websocket=ws)
161+
client.send_close_stream()
162+
assert _sent_json(ws)["type"] == "CloseStream"
163+
164+
165+
# ---------------------------------------------------------------------------
166+
# agent/v1 — async
167+
# ---------------------------------------------------------------------------
168+
169+
class TestAsyncAgentV1ControlMessages:
170+
async def test_send_keep_alive_no_args(self):
171+
ws = _make_async_ws()
172+
client = AsyncAgentV1SocketClient(websocket=ws)
173+
await client.send_keep_alive()
174+
assert _sent_json(ws)["type"] == "KeepAlive"
175+
176+
177+
# ---------------------------------------------------------------------------
178+
# agent/v1 — sync
179+
# ---------------------------------------------------------------------------
180+
181+
class TestSyncAgentV1ControlMessages:
182+
def test_send_keep_alive_no_args(self):
183+
ws = _make_sync_ws()
184+
client = AgentV1SocketClient(websocket=ws)
185+
client.send_keep_alive()
186+
assert _sent_json(ws)["type"] == "KeepAlive"

0 commit comments

Comments
 (0)