Skip to content

Commit 2cbb1af

Browse files
committed
test: confirm agent gathers correct thread ts
1 parent 1e1c167 commit 2cbb1af

File tree

2 files changed

+122
-0
lines changed

2 files changed

+122
-0
lines changed

tests/scenario_tests/test_events_agent.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,54 @@ def handle_action(ack, agent: BoltAgent):
8080
assert response.status == 200
8181
assert_target_called()
8282

83+
def test_agent_thread_ts_from_event_in_thread(self):
84+
"""Agent gets thread_ts from event when in a thread."""
85+
app = App(client=self.web_client)
86+
87+
state = {"thread_ts": None}
88+
89+
def assert_target_called():
90+
count = 0
91+
while state["thread_ts"] is None and count < 20:
92+
sleep(0.1)
93+
count += 1
94+
assert state["thread_ts"] is not None
95+
96+
@app.event("app_mention")
97+
def handle_mention(agent: BoltAgent):
98+
state["thread_ts"] = agent._thread_ts
99+
100+
request = BoltRequest(body=app_mention_in_thread_body, mode="socket_mode")
101+
response = app.dispatch(request)
102+
assert response.status == 200
103+
assert_target_called()
104+
# Should use event.thread_ts (the thread root), not event.ts
105+
assert state["thread_ts"] == "1111111111.111111"
106+
107+
def test_agent_thread_ts_falls_back_to_ts(self):
108+
"""Agent falls back to event.ts when not in a thread."""
109+
app = App(client=self.web_client)
110+
111+
state = {"thread_ts": None}
112+
113+
def assert_target_called():
114+
count = 0
115+
while state["thread_ts"] is None and count < 20:
116+
sleep(0.1)
117+
count += 1
118+
assert state["thread_ts"] is not None
119+
120+
@app.event("app_mention")
121+
def handle_mention(agent: BoltAgent):
122+
state["thread_ts"] = agent._thread_ts
123+
124+
request = BoltRequest(body=app_mention_event_body, mode="socket_mode")
125+
response = app.dispatch(request)
126+
assert response.status == 200
127+
assert_target_called()
128+
# Should fall back to event.ts since no thread_ts
129+
assert state["thread_ts"] == "1234567890.123456"
130+
83131
def test_agent_kwarg_emits_experimental_warning(self):
84132
app = App(client=self.web_client)
85133

@@ -140,6 +188,18 @@ def build_payload(event: dict) -> dict:
140188
}
141189
)
142190

191+
app_mention_in_thread_body = build_payload(
192+
{
193+
"type": "app_mention",
194+
"user": "W222",
195+
"text": "<@W111> hello in thread",
196+
"ts": "2222222222.222222",
197+
"thread_ts": "1111111111.111111", # Thread root timestamp
198+
"channel": "C111",
199+
"event_ts": "2222222222.222222",
200+
}
201+
)
202+
143203
action_event_body = {
144204
"type": "block_actions",
145205
"user": {"id": "W222", "username": "test_user", "name": "test_user", "team_id": "T111"},

tests/scenario_tests_async/test_events_agent.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,56 @@ async def handle_action(ack, agent: AsyncBoltAgent):
8686
assert response.status == 200
8787
await assert_target_called()
8888

89+
@pytest.mark.asyncio
90+
async def test_agent_thread_ts_from_event_in_thread(self):
91+
"""Agent gets thread_ts from event when in a thread."""
92+
app = AsyncApp(client=self.web_client)
93+
94+
state = {"thread_ts": None}
95+
96+
async def assert_target_called():
97+
count = 0
98+
while state["thread_ts"] is None and count < 20:
99+
await asyncio.sleep(0.1)
100+
count += 1
101+
assert state["thread_ts"] is not None
102+
103+
@app.event("app_mention")
104+
async def handle_mention(agent: AsyncBoltAgent):
105+
state["thread_ts"] = agent._thread_ts
106+
107+
request = AsyncBoltRequest(body=app_mention_in_thread_body, mode="socket_mode")
108+
response = await app.async_dispatch(request)
109+
assert response.status == 200
110+
await assert_target_called()
111+
# Should use event.thread_ts (the thread root), not event.ts
112+
assert state["thread_ts"] == "1111111111.111111"
113+
114+
@pytest.mark.asyncio
115+
async def test_agent_thread_ts_falls_back_to_ts(self):
116+
"""Agent falls back to event.ts when not in a thread."""
117+
app = AsyncApp(client=self.web_client)
118+
119+
state = {"thread_ts": None}
120+
121+
async def assert_target_called():
122+
count = 0
123+
while state["thread_ts"] is None and count < 20:
124+
await asyncio.sleep(0.1)
125+
count += 1
126+
assert state["thread_ts"] is not None
127+
128+
@app.event("app_mention")
129+
async def handle_mention(agent: AsyncBoltAgent):
130+
state["thread_ts"] = agent._thread_ts
131+
132+
request = AsyncBoltRequest(body=app_mention_event_body, mode="socket_mode")
133+
response = await app.async_dispatch(request)
134+
assert response.status == 200
135+
await assert_target_called()
136+
# Should fall back to event.ts since no thread_ts
137+
assert state["thread_ts"] == "1234567890.123456"
138+
89139
@pytest.mark.asyncio
90140
async def test_agent_kwarg_emits_experimental_warning(self):
91141
app = AsyncApp(client=self.web_client)
@@ -147,6 +197,18 @@ def build_payload(event: dict) -> dict:
147197
}
148198
)
149199

200+
app_mention_in_thread_body = build_payload(
201+
{
202+
"type": "app_mention",
203+
"user": "W222",
204+
"text": "<@W111> hello in thread",
205+
"ts": "2222222222.222222",
206+
"thread_ts": "1111111111.111111", # Thread root timestamp
207+
"channel": "C111",
208+
"event_ts": "2222222222.222222",
209+
}
210+
)
211+
150212
action_event_body = {
151213
"type": "block_actions",
152214
"user": {"id": "W222", "username": "test_user", "name": "test_user", "team_id": "T111"},

0 commit comments

Comments
 (0)