Release Fenris 0.3.7
Release / release (push) Successful in 1m6s

This commit is contained in:
xavierk
2026-09-16 08:53:38 +05:30
parent 714e69be52
commit 69e08d9d3a
6 changed files with 352 additions and 118 deletions
+85 -33
View File
@@ -771,12 +771,29 @@ class TestQueryDailyGraphData:
assert result[0]["is_gap"] is True
conn.close()
def test_window_is_consecutive_utc_days_with_explicit_gaps(self, tmp_path):
conn = init_store(tmp_path / "test.db")
_insert_day(conn, "2026-09-14", bw=500)
result = _query_daily_graph_data(
conn, datetime(2026, 9, 16, 12, tzinfo=timezone.utc),
)
assert len(result) == 90
assert result[-3]["day"] == "2026-09-14"
assert result[-2]["day"] == "2026-09-15"
assert result[-2]["is_gap"] is True
assert result[-1]["day"] == "2026-09-16"
assert result[-1]["is_partial"] is True
conn.close()
class TestQueryHourlyGraphData:
def test_empty_day(self, tmp_path):
conn = init_store(tmp_path / "test.db")
result = _query_hourly_graph_data(conn, "2026-09-20")
assert result == []
result = _query_hourly_graph_data(
conn, "2026-09-20", datetime(2026, 9, 21, tzinfo=timezone.utc),
)
assert len(result) == 24
assert all(item["is_gap"] for item in result)
conn.close()
def test_with_hours(self, tmp_path):
@@ -795,9 +812,25 @@ class TestQueryHourlyGraphData:
def test_hour_labels(self, tmp_path):
conn = init_store(tmp_path / "test.db")
_insert_hour(conn, "2026-09-20T12:00:00+00:00", bw=1000)
result = _query_hourly_graph_data(conn, "2026-09-20")
assert len(result) == 1
assert result[0]["local_label"] == "12"
result = _query_hourly_graph_data(
conn, "2026-09-20", datetime(2026, 9, 21, tzinfo=timezone.utc),
)
assert len(result) == 24
assert result[12]["local_label"] == "12"
assert result[12]["bytes_written"] == 1000
conn.close()
def test_current_hour_is_partial_and_future_hours_are_not_gaps(self, tmp_path):
conn = init_store(tmp_path / "test.db")
result = _query_hourly_graph_data(
conn, "2026-09-20",
datetime(2026, 9, 20, 14, 30, tzinfo=timezone.utc),
)
assert result[13]["is_gap"] is True
assert result[14]["is_partial"] is True
assert result[14]["is_gap"] is True
assert result[15]["is_future"] is True
assert result[15]["is_gap"] is False
conn.close()
@@ -848,6 +881,17 @@ class TestDailyBarGraph:
graph._trim_to_range()
assert len(graph._day_data) == 7
def test_scale_includes_allocated_and_unallocated_writes(self):
graph = DailyBarGraph()
graph._all_day_data = [{
"day": "2026-09-16",
"total_bytes": 800,
"allocated_bytes": 500,
"unallocated_bytes": 300,
}]
graph._trim_to_range()
assert graph._max_bytes == 800
# ---------------------------------------------------------------------------
# Bar graph headless TUI tests (issue #75)
@@ -877,6 +921,13 @@ class TestBarGraphTUI:
legend = str(app.query_one("#bar-legend").render())
assert "Alloc" in legend
assert "Zero" in legend
range_label = str(app.query_one("#bar-range").render())
assert "14 days" in range_label
assert "UTC" in range_label
plotted = str(app.query_one("#bar-render").render())
assert "Writes (" in plotted
assert "Day UTC" in plotted
assert "→" in plotted
@pytest.mark.asyncio
async def test_arrow_selection(self, tmp_path):
@@ -897,20 +948,16 @@ class TestBarGraphTUI:
await pilot.pause()
await pilot.pause()
# Right arrow selects first bar
await pilot.press("right")
await pilot.pause()
assert graph.selected_index == 0
# Right again moves to second
await pilot.press("right")
await pilot.pause()
assert graph.selected_index == 1
# Left moves back
# The newest day is selected by default; left moves backward.
initial = graph.selected_index
await pilot.press("left")
await pilot.pause()
assert graph.selected_index == 0
assert graph.selected_index == initial - 1
# Right returns to the newest day.
await pilot.press("right")
await pilot.pause()
assert graph.selected_index == initial
@pytest.mark.asyncio
async def test_range_switching(self, tmp_path):
@@ -941,17 +988,17 @@ class TestBarGraphTUI:
assert graph.range_days == 7
assert len(graph._day_data) == 7
# Press 3 for 28-day range
# Press 3 for 30-day range
await pilot.press("3")
await pilot.pause()
assert graph.range_days == 28
assert len(graph._day_data) == 28
assert graph.range_days == 30
assert len(graph._day_data) == 30
# Press 4 for 90-day range (only 30 days available)
# Exact windows retain gap slots instead of compressing time.
await pilot.press("4")
await pilot.pause()
assert graph.range_days == 90
assert len(graph._day_data) == 30
assert len(graph._day_data) == 90
@pytest.mark.asyncio
async def test_readout_updates_on_selection(self, tmp_path):
@@ -972,12 +1019,13 @@ class TestBarGraphTUI:
await pilot.pause()
await pilot.pause()
# No selection initially
# Newest day is selected initially.
readout = str(app.query_one("#bar-readout").render())
assert "select" in readout.lower()
assert "UTC" in readout
assert "GB" in readout
# Select first bar
await pilot.press("right")
# Moving left updates the selected-day readout.
await pilot.press("left")
await pilot.pause()
readout = str(app.query_one("#bar-readout").render())
assert "2026-09" in readout
@@ -1007,10 +1055,8 @@ class TestBarGraphTUI:
await pilot.pause()
await pilot.pause()
# Select a day
await pilot.press("right")
await pilot.pause()
assert graph.selected_index == 0
# The newest day is selected automatically.
assert graph.selected_index == len(graph._day_data) - 1
assert graph.view_mode == "daily"
# Enter drill-down
@@ -1020,6 +1066,14 @@ class TestBarGraphTUI:
assert graph.drill_day is not None
assert len(graph._hour_data) == 24
# Five-minute data refreshes retain the selected hour.
graph._hourly_selected = 12
selected_hour = graph._hour_data[12]["hour"]
app._refresh()
await pilot.pause()
assert graph.view_mode == "hourly"
assert graph._hour_data[graph._hourly_selected]["hour"] == selected_hour
# Esc returns to daily
await pilot.press("escape")
await pilot.pause()
@@ -1208,9 +1262,7 @@ class TestConstrainedLayout:
# Focus and select a day
app.set_focus(graph)
await pilot.pause()
await pilot.press("right")
await pilot.pause()
assert graph.selected_index == 0
assert graph.selected_index == len(graph._day_data) - 1
# Resize to constrained — pilot.resize_terminal changes terminal size
await pilot.resize_terminal(79, 24)