feat: réactions dans le tiroir Comments (+ suppression) et refonte du menu de sélection (v7.67.0)
Tiroir Comments - Section « Reactions » au-dessus des fils : émoji, compte (si >1) et texte ancré lu dans le DOM (reactionList() / _anchorText(), offsets source hors pastilles) ; l'état vide ne s'affiche plus s'il reste des réactions. - Suppression : ✕ sur la ligne du tiroir (mes réactions) ET croix ::after au survol de la pastille sur l'émoji que j'ai posé (aucun nœud ajouté → offsets intacts). Deux entrées → removeReaction() → POST toggle → loadReactions(). Menu de sélection (maquette ASCII) - Ligne 4 = rangée scannée : 💬 Comment (libellé) à gauche, 🙂+ réaction à droite (.ft-row-split) ; la réaction sort de la ligne 3. - Entête Skills avec ≡ à droite (::after), liste Skills scrollable. - ✨ Ask AI retiré de la toolbar : doublon exact de « Edit with AI » du pied. - Écart volontaire à la maquette : le barré (T) de la ligne 2 est conservé. Fix racine (flake de gate) - _is_public_host attrape OSError (le garde SSRF renvoie un booléen, il ne lève plus) : un socket.timeout DNS ne bascule plus fetch_og_metadata dans son except Exception → repli silencieux → AssertionError. - fixture stub_dns sur TestOGParser (même motif que test_agent_web_tools) : zéro vrai DNS dans les tests OG. Tests: pytest tests/ -q -n auto → 1390 passed / 0 failed (flake corrigé) ; ruff check app tests → OK ; e2e v764 (réactions dans le tiroir + suppression A/B), v762 (nouvelle ligne 4), v766, v7641, v763 → 6 passed sur :8081 (image flowdeck:v7.67.0 rebuild + redéployée).
This commit is contained in:
@@ -10,8 +10,10 @@ Covers the five roadmap points:
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import ipaddress
|
||||
import json
|
||||
import secrets
|
||||
import socket
|
||||
from pathlib import Path
|
||||
|
||||
import httpx
|
||||
@@ -209,7 +211,27 @@ _OG_HTML = """<!doctype html><html><head>
|
||||
</head><body>hi</body></html>"""
|
||||
|
||||
|
||||
#: IP publique factice — TestOGParser ne doit dépendre ni du réseau HTTP
|
||||
#: (MockTransport) ni du DNS : `_is_public_host` résout l'hôte pour décider si
|
||||
#: l'IP est publique, et cette résolution échoue sous `pytest -n auto` (même
|
||||
#: piège que test_agent_web_tools.stub_dns — d'où un flake récurrent ici).
|
||||
PUBLIC_IP = "93.184.216.34"
|
||||
|
||||
|
||||
class TestOGParser:
|
||||
@pytest.fixture(autouse=True)
|
||||
def stub_dns(self, monkeypatch):
|
||||
real = socket.getaddrinfo
|
||||
|
||||
def fake_getaddrinfo(host, *args, **kwargs):
|
||||
try:
|
||||
ipaddress.ip_address(host)
|
||||
except ValueError:
|
||||
return [(socket.AF_INET, socket.SOCK_STREAM, 6, "", (PUBLIC_IP, 0))]
|
||||
return real(host, *args, **kwargs)
|
||||
|
||||
monkeypatch.setattr(socket, "getaddrinfo", fake_getaddrinfo)
|
||||
|
||||
def test_parse_og_handles_attribute_order(self):
|
||||
from app.services.og_fetcher import parse_og
|
||||
|
||||
|
||||
Reference in New Issue
Block a user