diff options
Diffstat (limited to 'Biz/PodcastItLater/Web.py')
| -rw-r--r-- | Biz/PodcastItLater/Web.py | 132 |
1 files changed, 126 insertions, 6 deletions
diff --git a/Biz/PodcastItLater/Web.py b/Biz/PodcastItLater/Web.py index b41f31d..60818e9 100644 --- a/Biz/PodcastItLater/Web.py +++ b/Biz/PodcastItLater/Web.py @@ -1611,6 +1611,7 @@ def cancel_queue_item(request: Request, job_id: int) -> Response: app.delete("/queue/{job_id}")(Admin.delete_queue_item) app.get("/admin/users")(Admin.admin_users) +app.get("/admin/metrics")(Admin.admin_metrics) app.post("/admin/users/{user_id}/status")(Admin.update_user_status) app.post("/admin/episode/{episode_id}/toggle-public")( Admin.toggle_episode_public, @@ -2145,6 +2146,124 @@ class TestAdminInterface(BaseWebTest): self.assertIn("PROCESSING: 1", response.text) +class TestMetricsDashboard(BaseWebTest): + """Test metrics dashboard functionality.""" + + def setUp(self) -> None: + """Set up test client with logged-in admin user.""" + super().setUp() + + # Create and login admin user + self.user_id, _ = Core.Database.create_user( + "ben@bensima.com", + ) + Core.Database.update_user_status( + self.user_id, + "active", + ) + self.client.post("/login", data={"email": "ben@bensima.com"}) + + def test_metrics_page_requires_admin(self) -> None: + """Verify non-admin users cannot access metrics.""" + # Create non-admin user + user_id, _ = Core.Database.create_user("user@example.com") + Core.Database.update_user_status(user_id, "active") + + # Login as non-admin + self.client.get("/logout") + self.client.post("/login", data={"email": "user@example.com"}) + + # Try to access metrics + response = self.client.get("/admin/metrics") + + # Should redirect + self.assertEqual(response.status_code, 302) + self.assertEqual(response.headers["Location"], "/?error=forbidden") + + def test_metrics_page_requires_login(self) -> None: + """Verify unauthenticated users are redirected.""" + self.client.get("/logout") + + response = self.client.get("/admin/metrics") + + self.assertEqual(response.status_code, 302) + self.assertEqual(response.headers["Location"], "/") + + def test_metrics_displays_summary(self) -> None: + """Verify metrics summary is displayed.""" + # Create test episode + episode_id = Core.Database.create_episode( + title="Test Episode", + audio_url="http://example.com/audio.mp3", + content_length=1000, + duration=300, + ) + Core.Database.add_episode_to_user(self.user_id, episode_id) + + # Track some events + Core.Database.track_episode_metric(episode_id, "played") + Core.Database.track_episode_metric(episode_id, "played") + Core.Database.track_episode_metric(episode_id, "downloaded") + Core.Database.track_episode_metric(episode_id, "added", self.user_id) + + # Get metrics page + response = self.client.get("/admin/metrics") + + self.assertEqual(response.status_code, 200) + self.assertIn("Episode Metrics", response.text) + self.assertIn("Total Episodes", response.text) + self.assertIn("Total Plays", response.text) + self.assertIn("Total Downloads", response.text) + self.assertIn("Total Adds", response.text) + + def test_metrics_shows_top_episodes(self) -> None: + """Verify top episodes tables are displayed.""" + # Create test episodes + episode1 = Core.Database.create_episode( + title="Popular Episode", + audio_url="http://example.com/popular.mp3", + content_length=1000, + duration=300, + author="Test Author", + ) + Core.Database.add_episode_to_user(self.user_id, episode1) + + episode2 = Core.Database.create_episode( + title="Less Popular Episode", + audio_url="http://example.com/less.mp3", + content_length=1000, + duration=300, + ) + Core.Database.add_episode_to_user(self.user_id, episode2) + + # Track events - more for episode1 + for _ in range(5): + Core.Database.track_episode_metric(episode1, "played") + for _ in range(2): + Core.Database.track_episode_metric(episode2, "played") + + for _ in range(3): + Core.Database.track_episode_metric(episode1, "downloaded") + Core.Database.track_episode_metric(episode2, "downloaded") + + # Get metrics page + response = self.client.get("/admin/metrics") + + self.assertEqual(response.status_code, 200) + self.assertIn("Most Played", response.text) + self.assertIn("Most Downloaded", response.text) + self.assertIn("Popular Episode", response.text) + + def test_metrics_empty_state(self) -> None: + """Verify metrics page works with no data.""" + response = self.client.get("/admin/metrics") + + self.assertEqual(response.status_code, 200) + self.assertIn("Episode Metrics", response.text) + # Should show 0 for counts + self.assertIn("Total Episodes", response.text) + + class TestJobCancellation(BaseWebTest): """Test job cancellation functionality.""" @@ -2499,10 +2618,11 @@ class TestEpisodeDeduplication(BaseWebTest): for url in similar_urls: url_hash = Core.hash_url(url) - episode = Core.Database.find_episode_by_url_hash(url_hash) + episode = Core.Database.get_episode_by_url_hash(url_hash) self.assertIsNotNone(episode) - self.assertEqual(episode["id"], self.episode_id) # type: ignore[index] + if episode is not None: + self.assertEqual(episode["id"], self.episode_id) def test_add_existing_episode_to_user_feed(self) -> None: """Should add existing episode to new user's feed.""" @@ -2551,7 +2671,7 @@ class TestMetricsTracking(BaseWebTest): ) # Verify metric was recorded - metrics = Core.Database.get_episode_metrics(self.episode_id) + metrics = Core.Database.get_episode_metric_events(self.episode_id) self.assertEqual(len(metrics), 1) self.assertEqual(metrics[0]["event_type"], "added") self.assertEqual(metrics[0]["user_id"], self.user_id) @@ -2564,7 +2684,7 @@ class TestMetricsTracking(BaseWebTest): self.user_id, ) - metrics = Core.Database.get_episode_metrics(self.episode_id) + metrics = Core.Database.get_episode_metric_events(self.episode_id) self.assertEqual(len(metrics), 1) self.assertEqual(metrics[0]["event_type"], "played") @@ -2576,7 +2696,7 @@ class TestMetricsTracking(BaseWebTest): user_id=None, ) - metrics = Core.Database.get_episode_metrics(self.episode_id) + metrics = Core.Database.get_episode_metric_events(self.episode_id) self.assertEqual(len(metrics), 1) self.assertEqual(metrics[0]["event_type"], "played") self.assertIsNone(metrics[0]["user_id"]) @@ -2594,7 +2714,7 @@ class TestMetricsTracking(BaseWebTest): self.assertEqual(response.status_code, 200) # Verify metric was recorded - metrics = Core.Database.get_episode_metrics(self.episode_id) + metrics = Core.Database.get_episode_metric_events(self.episode_id) played_metrics = [m for m in metrics if m["event_type"] == "played"] self.assertGreater(len(played_metrics), 0) |
