From fd78affe382ef713658d80a3fa007ca15aa22625 Mon Sep 17 00:00:00 2001 From: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> Date: Thu, 24 Sep 2026 21:25:49 +0530 Subject: [PATCH] test(stream): move full-fallback-resend threading test to thread routing suite The Telegram final-delivery suite is the wrong home and its delete assertion duplicates test_stream_consumer.py. Keep only the new behaviour: a full resend threads its first chunk to the originating message; later chunks stay unthreaded. --- .../test_stream_consumer_thread_routing.py | 24 +++++++++++++++++++ tests/gateway/test_telegram_final_delivery.py | 22 ----------------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/tests/gateway/test_stream_consumer_thread_routing.py b/tests/gateway/test_stream_consumer_thread_routing.py index 62e44f459e..01d20dc389 100644 --- a/tests/gateway/test_stream_consumer_thread_routing.py +++ b/tests/gateway/test_stream_consumer_thread_routing.py @@ -172,3 +172,27 @@ class TestFeishuFallbackThreadRouting: f"Expected receive_id_type='thread_id', got '{receive_id_type}'" ) + +class TestFallbackResendThreading: + """#103068: a full fallback resend replaces the preview, so it must land in + the originating thread; tail continuations keep their unthreaded delivery.""" + + @pytest.mark.asyncio + async def test_full_fallback_resend_threads_first_chunk_only(self): + adapter = _make_adapter(max_length=700) + adapter.send.side_effect = [ + SimpleNamespace(success=True, message_id=f"full_{i}") for i in range(10) + ] + consumer = GatewayStreamConsumer(adapter, "chat_123", initial_reply_to_id="om_user_1") + consumer._message_id = "om_preview" + consumer._last_sent_text = "truncated snapshot" + consumer._already_sent = True + consumer._fallback_final_send = True + + final = " ".join(["word"] * 400) # not prefixed by the snapshot -> full resend + await consumer._send_fallback_final(final) + + calls = adapter.send.await_args_list + assert len(calls) > 1 + assert calls[0].kwargs["reply_to"] == "om_user_1" + assert all("reply_to" not in c.kwargs for c in calls[1:]) diff --git a/tests/gateway/test_telegram_final_delivery.py b/tests/gateway/test_telegram_final_delivery.py index 82b8c54be9..b5c85e73c3 100644 --- a/tests/gateway/test_telegram_final_delivery.py +++ b/tests/gateway/test_telegram_final_delivery.py @@ -149,28 +149,6 @@ async def test_complete_preview_survives_long_flood_fallback_failure(monkeypatch assert consumer.delivered_final_matches("Final answer") is True -@pytest.mark.asyncio -async def test_full_fallback_resend_threads_and_deletes_truncated_preview(): - """When the visible prefix is not a prefix of the final (Feishu post vs - cleaned text), fallback resends the whole answer. Thread it to the user - message and delete the truncated edit bubble (#103068).""" - adapter = _adapter() - adapter.send.return_value = SendResult(success=True, message_id="full-1") - - consumer = GatewayStreamConsumer( - adapter, "chat-1", initial_reply_to_id="user-1", - ) - consumer._message_id = "preview-1" - consumer._last_sent_text = "truncated snapshot" - consumer._already_sent = True - consumer._fallback_final_send = True - - await consumer._send_fallback_final("full completed answer that does not start with the snapshot") - - assert adapter.send.await_args.kwargs["reply_to"] == "user-1" - adapter.delete_message.assert_awaited() - - @pytest.mark.asyncio async def test_telegram_long_flood_result_keeps_retry_after(): """The real adapter contract preserves the server delay for consumers."""