Files
rar-autopass/tests/test_web_refresh.py
Claude Agent 283299ff20 feat(ux): import compact + preview format Trimiteri + navigatie + scoatere auto_send (5.11)
8 stories TDD (echipa Sonnet, lead orchestreaza). US-001 scoate hold-ul auto_send din mapare
(has_no_auto_send->False, simbol pastrat; cod rezolvat->queued). US-002 scoate bifa auto_send
din UI. US-003 preview pas 3 in format .tabel-trimiteri (STARI_PREVIEW + nota_umana_preview,
fara repr Python; view-model prez). US-004 filtre layout/stil ca referinta + buton Custom.
US-005 navigatie Trimiteri/Mapari sub contoare pe toate paginile. US-006 import <details> nativ
colapsabil. US-007 post-commit reveal (OOB _coada/_status + HX-Trigger). US-008 auto-refresh
dupa actiuni (nudge eliminat).

VERIFY context curat PASS (8/8). /code-review high: 3 buguri reparate (tab nav la self-refresh,
pill Custom valori stale, nota_umana_preview precedenta needs_mapping). 934 passed, 1 skipped.
Backend trimitere + schema NEATINSE.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 15:16:28 +00:00

271 lines
11 KiB
Python

"""Teste US-008 (PRD 5.11) — Auto-refresh dupa actiuni proprii.
Comportament dorit:
1. Dupa actiune proprie (mapare inline, corectie, repune, commit), lista
Trimiteri se reincarca automat, fara click pe Reincarca.
Mecanism: server emite HX-Trigger: trimiteriChanged; #submissions-wrap
asculta 'trimiteriChanged from:body' si re-fetches imediat.
2. Filtrul activ si pagina curenta NU se reseteaza la auto-refresh.
Mecanism: hx-include="#filtre-trimiteri" pe #submissions-wrap.
3. Pollerul de fundal face auto-refresh direct la date noi (versiune diferita)
in loc sa afiseze nudge-ul "Date noi. Reincarca".
Decizie (documentata): nudge eliminat. Distinctia own vs externe nu e posibila
pe client fara sesiune dedicata — auto-refresh e mai consistent si mai simplu.
4. Elementul #nudge-trimiteri eliminat din template (dead code dupa schimbarea poller).
TDD: testele 1-2 sunt GREEN (comportament deja implementat — regresie).
testele 3-4 sunt RED→GREEN (implementate in aceeasi sesiune).
testele 5-6 (test_actiune_proprie_reincarca_automat, test_nudge_nu_mai_blocheaza)
sunt adaugate cu numele exacte din spec PRD (GREEN de la primul run — implementarea
existenta le satisface).
"""
from __future__ import annotations
import json
import os
import tempfile
import pytest
from fastapi.testclient import TestClient
# --------------------------------------------------------------------------- #
# Fixture #
# --------------------------------------------------------------------------- #
@pytest.fixture()
def client(monkeypatch):
tmp = tempfile.mkdtemp()
monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "us008.db"))
monkeypatch.setenv("AUTOPASS_WEB_AUTH_REQUIRED", "false")
from app.config import get_settings
get_settings.cache_clear()
from app.main import app
with TestClient(app) as c:
yield c
get_settings.cache_clear()
def _add_submission(account_id: int = 1, status: str = "queued", payload: dict | None = None) -> int:
"""Adauga un submission si returneaza id-ul sau.
status: starea dorita (implicit 'queued'); use 'needs_mapping' pentru testele de mapare.
payload: continut JSON (implicit minimal).
"""
from app.db import get_connection
conn = get_connection()
try:
cur = conn.execute(
"INSERT INTO submissions (idempotency_key, account_id, status, payload_json) "
"VALUES (?, ?, ?, ?)",
(f"us008_key_{account_id}_{status}", account_id, status,
json.dumps(payload or {"test": True})),
)
return cur.lastrowid
finally:
conn.close()
def _add_nomenclator(cod: str = "R-FRANE", nume: str = "Reparatie frane") -> None:
"""Insereaza un cod RAR in nomenclatorul local."""
from app.db import get_connection
conn = get_connection()
try:
conn.execute(
"INSERT OR REPLACE INTO nomenclator_rar (cod_prestatie, nume_prestatie) VALUES (?,?)",
(cod, nume),
)
finally:
conn.close()
# --------------------------------------------------------------------------- #
# Test 1 — GREEN (regresie): submissions-wrap reincarca la trimiteriChanged #
# --------------------------------------------------------------------------- #
def test_submissions_wrap_reincarca_la_trimiteriChanged(client):
"""#submissions-wrap se reincarca automat la evenimentul trimiteriChanged.
Actiunile proprii (mapare inline, corectie, repune, commit) emit
HX-Trigger: trimiteriChanged. #submissions-wrap asculta
'trimiteriChanged from:body' si re-fetches imediat, fara click pe Reincarca.
Nota: _coada.html se randeaza doar cand exista submission-uri (are_trimiteri=True).
Semanarea unui submission inainte de GET garanteaza randarea sectionii complete.
"""
_add_submission()
r = client.get("/_fragments/acasa")
assert r.status_code == 200, r.text
assert "submissions-wrap" in r.text, (
"#submissions-wrap lipseste din /_fragments/acasa (cu submission existent)"
)
assert "trimiteriChanged from:body" in r.text, (
"#submissions-wrap nu asculta 'trimiteriChanged from:body'"
"auto-refresh dupa actiuni proprii nu va functiona"
)
# --------------------------------------------------------------------------- #
# Test 2 — GREEN (regresie): filtrul nu se reseteaza la auto-refresh #
# --------------------------------------------------------------------------- #
def test_submissions_wrap_pastreaza_filtrul_la_auto_refresh(client):
"""Auto-refresh-ul nu reseteaza filtrul activ sau pagina curenta.
#submissions-wrap include #filtre-trimiteri la fiecare request HTMX.
La reincarcarea declansata de trimiteriChanged, filtrul curent (stare,
vehicul, data) si pagina curenta se retransmit automat.
"""
_add_submission()
r = client.get("/_fragments/acasa")
assert r.status_code == 200, r.text
html = r.text
assert 'hx-include="#filtre-trimiteri"' in html or "hx-include='#filtre-trimiteri'" in html, (
"hx-include=#filtre-trimiteri lipseste din #submissions-wrap — "
"filtrul se va reseta la auto-refresh"
)
# --------------------------------------------------------------------------- #
# Test 3 — RED: pollerul face auto-refresh, nu arata nudge #
# --------------------------------------------------------------------------- #
def test_poller_auto_refresh_nu_nudge(client):
"""Pollerul de fundal face auto-refresh la date noi, NU afiseaza nudge.
Pattern curent (RED): cand versiunea difera, pollerul face nudge.hidden = false.
Pattern dorit (GREEN): cand versiunea difera, pollerul cheama reincarcaTrimiteri()
care re-fetches #submissions-wrap pastrand filtrul curent.
Decizie: nudge eliminat complet (nu ramane 'doar pentru schimbari externe')
pentru ca distinctia propriu vs extern e imposibila pe client fara
mecanism de sesiune dedicat (too complex, no gain).
"""
r = client.get("/")
assert r.status_code == 200, r.text
html = r.text
# Pollerul NU mai seteaza nudge.hidden = false in handler-ul de versiune diferita.
# (Prezenta acestui pattern indica implementarea veche — RED.)
assert "nudge.hidden = false" not in html, (
"Pollerul inca arata nudge in loc de auto-refresh — "
"schimbati 'nudge.hidden = false' cu 'reincarcaTrimiteri()' in base.html"
)
# --------------------------------------------------------------------------- #
# Test 4 — RED: nudge-ul e eliminat din template #
# --------------------------------------------------------------------------- #
def test_nudge_eliminat_din_lista(client):
"""Elementul #nudge-trimiteri este eliminat din template-ul listei.
Dupa ce pollerul trece la auto-refresh, nudge-ul devine dead code.
Eliminarea lui simplifica template-ul si elimina un element de UI confuz
(utilizatorul vedea 'Date noi. Reincarca' chiar daca lista era actuala,
din cauza refreshului propriu care nu actualiza versiunea fast enough).
Nota: _coada.html se randeaza doar cand sunt submission-uri. Semanarea
asigura ca _coada.html e inclus in raspuns (altfel testul ar pasa vacuos).
"""
_add_submission()
r = client.get("/_fragments/acasa")
assert r.status_code == 200, r.text
assert "nudge-trimiteri" not in r.text, (
"#nudge-trimiteri inca exista in template — "
"eliminati elementul din _coada.html dupa ce pollerul e migrat la auto-refresh"
)
# --------------------------------------------------------------------------- #
# Test 5 (spec PRD): actiune proprie reincarca automat fara click Reincarca #
# --------------------------------------------------------------------------- #
def test_actiune_proprie_reincarca_automat(client):
"""Dupa o actiune proprie (mapare inline), lista se reincarca automat.
Verifica doua componente ale mecanismului:
1. Server-side: POST la mapare inline returneaza HX-Trigger: trimiteriChanged
in headerele raspunsului (indiferent de starea noua a submission-ului).
2. Client-side: #submissions-wrap asculta 'trimiteriChanged from:body' in
hx-trigger — HTMX va declansa re-fetch imediat la primirea headerului,
fara click pe Reincarca.
Testeaza calea mapare-inline; corectie/repune/commit sunt acoperite similar
(toate emit HX-Trigger: trimiteriChanged — verificate in test_import_commit.py).
"""
_add_nomenclator("R-FRANE", "Reparatie frane")
sub_id = _add_submission(
status="needs_mapping",
payload={"prestatii": [{"cod_op_service": "OP-FRANE"}]},
)
# POST mapare inline — emite HX-Trigger: trimiteriChanged
r = client.post(
f"/trimitere/{sub_id}/mapeaza",
data={"csrf_token": "", "cod_op_service": "OP-FRANE", "cod_prestatie": "R-FRANE"},
)
assert r.status_code == 200, r.text
# Server emite triggerul — HTMX va declansa auto-refresh pe client
hx = r.headers.get("HX-Trigger", "")
assert "trimiteriChanged" in hx, (
f"Mapare inline nu emite HX-Trigger: trimiteriChanged — "
f"lista nu se va reincarca automat. Header primit: {hx!r}"
)
# Client-side: #submissions-wrap asculta triggerul (markup existent in template)
r_acasa = client.get("/_fragments/acasa")
assert "trimiteriChanged from:body" in r_acasa.text, (
"#submissions-wrap nu asculta 'trimiteriChanged from:body'"
"auto-refresh nu va functiona dupa actiune proprie"
)
# --------------------------------------------------------------------------- #
# Test 6 (spec PRD): nudge nu mai blocheaza actualizarea #
# --------------------------------------------------------------------------- #
def test_nudge_nu_mai_blocheaza_actualizarea(client):
"""Nudge-ul 'Date noi. Reincarca' nu mai poate bloca actualizarea listei.
Inainte de US-008, mecanismul era: poller detecteaza versiune diferita →
arata nudge → utilizatorul trebuia sa apese 'Reincarca' manual.
Dupa US-008, nudge-ul e eliminat (decizie documentata mai jos) si pollerul
cheama direct reincarcaTrimiteri() → actualizare automata, fara click.
Decizie privind nudge: ELIMINAT complet (nu pastrat pentru schimbari externe).
Rationale: distinctia 'actiune proprie vs schimbare externa' nu e posibila
pe client fara mecanism dedicat de sesiune. Auto-refresh periodic (la versiune
diferita) acopera si schimbarile externe (worker, alt browser) fara friction.
"""
_add_submission() # are_trimiteri=True → _coada.html se randeaza
r_pagina = client.get("/_fragments/acasa")
assert r_pagina.status_code == 200, r_pagina.text
html = r_pagina.text
# Nudge eliminat: nu mai poate bloca utilizatorul cu un banner "Reincarca"
assert "nudge-trimiteri" not in html, (
"#nudge-trimiteri inca exista — poate bloca actualizarea (US-008 il elimina)"
)
# Pollerul JS nu mai seteaza nudge.hidden = false: nu poate "bloca" prin afisare nudge
r_home = client.get("/")
assert r_home.status_code == 200, r_home.text
assert "nudge.hidden = false" not in r_home.text, (
"Pollerul JS inca poate afisa nudge-ul — schimbati cu reincarcaTrimiteri()"
)
# Pollerul cheama reincarcaTrimiteri() la versiune diferita (auto-refresh)
assert "reincarcaTrimiteri" in r_home.text, (
"reincarcaTrimiteri() lipseste din poller — auto-refresh nu va functiona"
)