fix: reconcile final control panel coverage UX
This commit is contained in:
@@ -17,6 +17,8 @@ def test_fixture_creates_one_hundred_varied_installations_and_events():
|
||||
assert {row.agent_health for row in snapshots} == {"ONLINE", "DEGRADED", "OFFLINE", "FAILED", "UNKNOWN"}
|
||||
assert {row.version_drift for row in snapshots} == {"CURRENT", "OUTDATED", "UNKNOWN"}
|
||||
assert {row.installation_id for row in session.query(Installation).all()} == {str(uuid.uuid5(uuid.NAMESPACE_DNS, f"fixture-{index}")) for index in range(100)}
|
||||
assert all(row.fiscally_complete + row.safe_blocked + row.failed_products == row.total_products for row in snapshots)
|
||||
assert all(row.coverage_percent == round(row.fiscally_complete * 100 / row.total_products, 1) for row in snapshots)
|
||||
|
||||
blockers = session.query(BlockedProduct).all()
|
||||
assert len({row.blocker_fingerprint for row in blockers}) == len(blockers)
|
||||
|
||||
@@ -22,6 +22,8 @@ def _panel_client():
|
||||
snapshot = session.scalar(select(AgentSnapshot).where(AgentSnapshot.installation_id == installation.id))
|
||||
snapshot.total_products = 50
|
||||
snapshot.fiscally_complete = 49
|
||||
snapshot.safe_blocked = 1
|
||||
snapshot.failed_products = 0
|
||||
snapshot.coverage_percent = 98
|
||||
job = Job(
|
||||
agent_id=agent_id,
|
||||
@@ -80,7 +82,7 @@ def test_dashboard_renders_operational_queue_labels_and_human_dates():
|
||||
assert response.status_code == 200
|
||||
for label in ("Agents total", "Online", "Degraded", "Offline", "Failed", "Unknown"):
|
||||
assert label in response.text
|
||||
assert "Produtos bloqueados" in response.text
|
||||
assert "Produtos com blockers abertos" in response.text
|
||||
assert "Blockers abertos" in response.text
|
||||
assert "ATENÇÃO NECESSÁRIA" in response.text
|
||||
assert "Ver todos" in response.text
|
||||
@@ -89,6 +91,30 @@ def test_dashboard_renders_operational_queue_labels_and_human_dates():
|
||||
assert not re.search(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}", response.text)
|
||||
|
||||
|
||||
def test_dashboard_coverage_displays_reconciled_product_buckets():
|
||||
client, _, _ = _panel_client()
|
||||
|
||||
response = client.get("/")
|
||||
|
||||
assert response.status_code == 200
|
||||
for label in ("Produtos avaliados", "Completos", "Bloqueados com segurança", "Falhas técnicas", "Não classificados"):
|
||||
assert label in response.text
|
||||
assert "Produtos com blockers abertos" in response.text
|
||||
assert "Cobertura reconciliada" in response.text
|
||||
|
||||
|
||||
def test_login_has_centered_card_and_explicit_field_labels():
|
||||
client, _, _ = _panel_client()
|
||||
|
||||
response = client.get("/login")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert 'class="login-page"' in response.text
|
||||
assert 'class="login-card"' in response.text
|
||||
assert '<label for="login-username">Usuário</label>' in response.text
|
||||
assert '<label for="login-password">Senha</label>' in response.text
|
||||
|
||||
|
||||
def test_dashboard_lists_bounded_failed_job_rows_with_identity_error_age_and_empty_state():
|
||||
client, agent_id, _ = _panel_client()
|
||||
factory = client._session_factory
|
||||
@@ -159,6 +185,27 @@ def test_agents_render_separate_health_and_fiscal_status_with_server_sort():
|
||||
assert 'value="worst_coverage"' in response.text
|
||||
|
||||
|
||||
def test_agent_list_hides_technical_uuid_and_explains_remainder():
|
||||
client, agent_id, _ = _panel_client()
|
||||
with client._session_factory() as session:
|
||||
installation = session.scalar(select(Installation).where(Installation.agent_id == agent_id))
|
||||
technical_uuid = installation.installation_id
|
||||
agent = session.get(Agent, agent_id)
|
||||
agent.agent_version = None
|
||||
snapshot = session.scalar(select(AgentSnapshot).where(AgentSnapshot.installation_id == installation.id))
|
||||
snapshot.version_drift = "UNKNOWN"
|
||||
session.commit()
|
||||
|
||||
response = client.get("/agents")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert technical_uuid not in response.text
|
||||
assert "classificados" in response.text
|
||||
assert "bloqueados com segurança" in response.text
|
||||
assert "falhas técnicas" in response.text
|
||||
assert "<td>Desconhecida<small>Desconhecida</small></td>" not in response.text
|
||||
|
||||
|
||||
def test_agent_list_and_detail_show_localized_last_seen_with_iso_tooltip():
|
||||
client, agent_id, _ = _panel_client()
|
||||
expected_iso = '2026-09-22T19:11:37+00:00'
|
||||
@@ -310,6 +357,44 @@ def test_agent_detail_resolves_agent_after_first_hundred_installations():
|
||||
assert "Late ERP 104" in response.text
|
||||
|
||||
|
||||
def test_agent_detail_reconciles_coverage_and_formats_missing_technical_fields():
|
||||
client, agent_id, _ = _panel_client()
|
||||
with client._session_factory() as session:
|
||||
agent = session.get(Agent, agent_id)
|
||||
agent.agent_version = None
|
||||
installation = session.scalar(select(Installation).where(Installation.agent_id == agent_id))
|
||||
snapshot = session.scalar(select(AgentSnapshot).where(AgentSnapshot.installation_id == installation.id))
|
||||
snapshot.version_drift = "UNKNOWN"
|
||||
session.commit()
|
||||
|
||||
response = client.get(f"/agents/{agent_id}")
|
||||
|
||||
assert response.status_code == 200
|
||||
for label in ("Produtos", "Completos", "Bloqueados com segurança", "Falhas técnicas", "Não classificados", "Cobertura fiscal"):
|
||||
assert label in response.text
|
||||
assert "Não informado" in response.text
|
||||
assert "Desconhecida" in response.text
|
||||
assert "Desconhecida · Desconhecida" not in response.text
|
||||
assert "ODS -" not in response.text
|
||||
context = response.text.split("<h2>Contexto da empresa</h2>", 1)[1].split("</article>", 1)[0]
|
||||
assert "Reprocessar tudo" in context
|
||||
assert not re.search(r"<(?:a|button)\b[^>]*>\s*</(?:a|button)>", context)
|
||||
|
||||
|
||||
def test_agent_detail_reports_negative_coverage_counts_as_data_inconsistency():
|
||||
client, agent_id, _ = _panel_client()
|
||||
with client._session_factory() as session:
|
||||
installation = session.scalar(select(Installation).where(Installation.agent_id == agent_id))
|
||||
snapshot = session.scalar(select(AgentSnapshot).where(AgentSnapshot.installation_id == installation.id))
|
||||
snapshot.failed_products = -1
|
||||
session.commit()
|
||||
|
||||
response = client.get(f"/agents/{agent_id}")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "contagens negativas" in response.text
|
||||
|
||||
|
||||
def test_agent_event_filters_lookahead_and_safe_event_reference_links_and_confirmation():
|
||||
client, agent_id, _ = _panel_client()
|
||||
factory = client._session_factory
|
||||
|
||||
@@ -100,6 +100,70 @@ def test_dashboard_reconciles_five_health_states_and_counts_distinct_safe_produc
|
||||
assert summary["online"] == 1 and summary["safe_blocked"] == 2
|
||||
|
||||
|
||||
def test_snapshot_coverage_exposes_unclassified_residual_and_overcount():
|
||||
session_factory = setup_db()
|
||||
with session_factory() as session:
|
||||
tenant, agent, installation, snapshot = _installation(session, 1, coverage=80, blocked=1)
|
||||
snapshot.total_products = 100
|
||||
snapshot.fiscally_complete = 96
|
||||
snapshot.safe_blocked = 1
|
||||
snapshot.failed_products = 1
|
||||
session.commit()
|
||||
|
||||
item = list_installations(session, page_size=5)["items"][0]
|
||||
assert item["unclassified_products"] == 2
|
||||
assert item["coverage_overcount_products"] == 0
|
||||
assert item["coverage_invariant_pass"] is True
|
||||
assert item["total_products"] == item["fiscally_complete"] + item["safe_blocked"] + item["failed_products"] + item["unclassified_products"]
|
||||
|
||||
snapshot.fiscally_complete = 99
|
||||
session.commit()
|
||||
inconsistent = list_installations(session, page_size=5)["items"][0]
|
||||
assert inconsistent["unclassified_products"] == 0
|
||||
assert inconsistent["coverage_overcount_products"] == 1
|
||||
assert inconsistent["coverage_invariant_pass"] is False
|
||||
|
||||
|
||||
def test_dashboard_coverage_totals_reconcile_and_keep_registry_metric_separate():
|
||||
session_factory = setup_db()
|
||||
with session_factory() as session:
|
||||
tenant, _, installation, snapshot = _installation(session, 1, coverage=96, blocked=1)
|
||||
snapshot.total_products = 100
|
||||
snapshot.fiscally_complete = 96
|
||||
snapshot.safe_blocked = 1
|
||||
snapshot.failed_products = 1
|
||||
_blocker(session, tenant, product="P-OPEN", field="CFOP", index=91, installation_id=installation.id)
|
||||
session.commit()
|
||||
|
||||
summary = dashboard_summary(session, now=NOW)
|
||||
|
||||
assert summary["total_products"] == 100
|
||||
assert summary["fiscally_complete"] == 96
|
||||
assert summary["safe_blocked"] == 1
|
||||
assert summary["failed_products"] == 1
|
||||
assert summary["unclassified_products"] == 2
|
||||
assert summary["coverage_overcount_products"] == 0
|
||||
assert summary["coverage_invariant_pass"] is True
|
||||
assert summary["safe_blocked_products"] == 1
|
||||
assert summary["total_products"] == summary["fiscally_complete"] + summary["safe_blocked"] + summary["failed_products"] + summary["unclassified_products"]
|
||||
|
||||
|
||||
def test_dashboard_marks_inconsistent_snapshot_partition_instead_of_clamping():
|
||||
session_factory = setup_db()
|
||||
with session_factory() as session:
|
||||
_, _, _, snapshot = _installation(session, 1, coverage=100, blocked=2)
|
||||
snapshot.total_products = 10
|
||||
snapshot.fiscally_complete = 9
|
||||
snapshot.safe_blocked = 2
|
||||
snapshot.failed_products = 0
|
||||
session.commit()
|
||||
|
||||
summary = dashboard_summary(session, now=NOW)
|
||||
|
||||
assert summary["coverage_overcount_products"] == 1
|
||||
assert summary["coverage_invariant_pass"] is False
|
||||
|
||||
|
||||
def test_attention_items_are_ranked_and_capped_at_ten():
|
||||
session_factory = setup_db()
|
||||
with session_factory() as session:
|
||||
|
||||
Reference in New Issue
Block a user