- 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>
70 lines
2.7 KiB
Python
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())
|