Files
bvandeusenandClaude Opus 5.5 5492336f1e
CI / lint (push) Successful in 2s
CI / integration (push) Successful in 50s
CI / unit (push) Failing after 1m16s
CI / publish (push) Skipped
feat(dashboard): a curated default layout, merged duplicate widgets, a labelled Overview (#5213)
- New installs start from widgets.RECOMMENDED, packed row by row for the
  enabled plugins; the edit drawer can reset a dashboard to it.
- Host Agent — Resources folds into Hosts — Overview (which gains load 1m),
  UniFi — Devices into UniFi — Overview; migration 0032 moves existing
  dashboards onto the survivors.
- The Overview labels what it counts (hosts, monitors up/down/pending,
  alerts firing) and lists firing alerts and down monitors with since-times.
- Uptime polls every 5 minutes (poll_seconds) instead of every cycle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:42:04 -04:00

70 lines
2.7 KiB
Python

"""Integration: "Reset to the recommended layout" replaces a dashboard's
widgets with widgets.RECOMMENDED, and only for someone who may edit it
(#5213), against real Postgres."""
from __future__ import annotations
import asyncio
import os
import time
import uuid
import pytest
pytestmark = pytest.mark.integration
@pytest.fixture
def app():
if not os.environ.get("STEWARD_DATABASE_URL"):
pytest.skip("needs Postgres")
from steward.app import create_app
return create_app(testing=False)
async def _client(app, role):
from steward.models.users import User, UserRole
uid, tag = str(uuid.uuid4()), uuid.uuid4().hex[:8]
async with app.db_sessionmaker() as s:
async with s.begin():
s.add(User(id=uid, username=f"reset-{tag}", email=f"reset-{tag}@test",
password_hash="x", role=UserRole(role), is_active=True))
client = app.test_client()
async with client.session_transaction() as sess:
sess.update(user_id=uid, user_role=role, username=f"reset-{tag}",
_csrf="test-token", login_at=time.time())
return client, uid
CSRF = {"X-CSRF-Token": "test-token"}
def test_reset_puts_back_the_recommended_layout_for_its_owner_only(app):
from sqlalchemy import select
from steward.core.widgets import recommended_layout
from steward.models.dashboard import Dashboard, DashboardWidget
async def _go():
owner, owner_id = await _client(app, "operator")
other, _ = await _client(app, "operator")
async with app.db_sessionmaker() as s:
async with s.begin():
dash = Dashboard(name="mine", owner_id=owner_id)
s.add(dash)
await s.flush()
s.add(DashboardWidget(dashboard_id=dash.id, widget_key="monitors",
grid_x=3, grid_y=9, grid_w=2, grid_h=2))
dash_id = dash.id
assert (await other.post(f"/d/{dash_id}/edit/reset", headers=CSRF)).status_code == 403
resp = await owner.post(f"/d/{dash_id}/edit/reset", headers=CSRF)
assert resp.status_code == 302 and resp.headers["Location"].endswith(f"/d/{dash_id}")
async with app.db_sessionmaker() as s:
rows = (await s.execute(select(DashboardWidget).where(DashboardWidget.dashboard_id == dash_id)
.order_by(DashboardWidget.grid_y, DashboardWidget.grid_x))).scalars().all()
want = recommended_layout(app.config.get("PLUGINS", {}))
assert [(w.widget_key, w.grid_x, w.grid_y, w.grid_w, w.grid_h) for w in rows] == \
[(i["key"], i["x"], i["y"], i["w"], i["h"]) for i in want]
asyncio.run(_go())