simbiot-harness/tests/test_tg_group_ux.py
Simbiot Harness 72727c6339 TG: 👀 реально ставится, ответы в группе — reply'ем, правка сообщения не дублирует входящее
Жалоба Alex: «реплаю на сообщения Коди — не реагирует». Триаж реплай на
бота распознавал (07:57, rule=reply_to_bot, ответ через 25 с), но:
- set_reaction слал reaction_type одиночным объектом вместо reaction —
  массива ReactionType: Telegram видел пустую реакцию — в личке молча
  «снимал реакции» (ok → MessageSeen, 596/нед, 👀 не было видно), в
  группе 400 REACTION_EMPTY. Тест test_seen_indication закреплял баг —
  исправлен под Bot API;
- ответ в группе уходил отдельным сообщением: теперь reply на сообщение
  (батч — на последнее, досылка --followup — на исходный вопрос) с
  allow_sending_without_reply; личка — как было;
- edited_message уже принятого сообщения писался новым входящим
  (m-516174914/915 — исправленная опечатка дала дубль в батче) — пропуск.
Тест: test_tg_group_ux 10 PASS; полный набор — без регрессий.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 08:01:15 +00:00

76 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""TG в группах (аудит 2026-10-17, «реплаю Коди — не реагирует»). Hermetic.
Запуск: ./venv/bin/python tests/test_tg_group_ux.py
Проверяет: setMessageReaction шлёт reaction МАССИВОМ (было reaction_type
одиночным объектом → REACTION_EMPTY в группе, пустая реакция в личке);
ответ в группе — reply на сообщение (батч — на последнее), с
allow_sending_without_reply; в личке — без цитаты; досылка итога в группе —
тоже reply; правка уже принятого сообщения распознаётся как не новое.
"""
import json
import os
import sys
import tempfile
sys.path.insert(0, "/root/simbiot-harness")
os.environ["SIMBIOT_DB"] = os.path.join(tempfile.mkdtemp(prefix="simbiot_grpux_"), "harness.db")
from harness import es, tg_inbox
es.init_db()
fails = []
def check(name, cond, extra=""):
print(("PASS" if cond else "FAIL"), name, ("| " + str(extra)) if not cond else "")
if not cond:
fails.append(name)
API = []
tg_inbox._load_env = lambda: None
tg_inbox._api = lambda method, params, timeout=35: API.append((method, dict(params))) or {"ok": True, "result": True}
tg_inbox.set_reaction(-100, 7)
meth, prm = API[-1]
check("реакция: метод setMessageReaction", meth == "setMessageReaction")
check("реакция: параметр reaction — массив ReactionType",
json.loads(prm.get("reaction", "null")) == [{"type": "emoji", "emoji": "👀"}], prm)
check("реакция: нет мусорного reaction_type", "reaction_type" not in prm, prm)
G, P = -1004402779881, 7569223131
for uid, chat, ct, mid, ts in ((1, G, "supergroup", 2420, "2026-10-17T07:57:30"),
(2, G, "supergroup", 2428, "2026-10-17T07:57:31"),
(3, P, "private", 4950, "2026-10-17T07:57:32"),
(4, G, "supergroup", 2500, "2026-10-17T08:00:00")):
es.append_event("inbox", f"m-{uid}", "MessageReceived", {
"update_id": uid, "chat_id": chat, "chat_type": ct, "message_id": mid,
"text": "вопрос", "kind": "text", "first_name": "Alex"})
def sent():
return [p for m, p in API if m == "sendMessage"][-1]
API.clear()
tg_inbox.send_batch_reply(["m-1", "m-2"], "сводный ответ")
s = sent()
check("батч в группе: reply на последнее сообщение", s.get("reply_to_message_id") == 2428, s)
check("reply не теряется, если цель удалена", s.get("allow_sending_without_reply") == "true", s)
tg_inbox.send_reply("m-3", "ответ в личку")
check("личка: без цитаты", "reply_to_message_id" not in sent(), sent())
tg_inbox.send_reply("m-4", "ответ в группу")
check("одиночный ответ в группе: reply", sent().get("reply_to_message_id") == 2500, sent())
tg_inbox.send_followup("m-4", "итог работы")
check("досылка в группе: reply на исходный вопрос", sent().get("reply_to_message_id") == 2500
and sent().get("text") == "итог работы", sent())
check("правка принятого сообщения — не новое",
tg_inbox._already_received({"chat": {"id": G}, "message_id": 2428}))
check("новое сообщение — новое",
not tg_inbox._already_received({"chat": {"id": G}, "message_id": 9999}))
print(f"\n{'OK' if not fails else 'FAILED'}: {len(fails)} fail(s)")
sys.exit(1 if fails else 0)