summaryrefslogtreecommitdiff
path: root/Biz/PodcastItLater/TestMetricsView.py
blob: c6fdd467b490251f595d92c640e88a451e6c0fdf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
"""Tests for Admin metrics view."""

# : out podcastitlater-test-metrics
# : dep pytest
# : dep starlette
# : dep httpx
# : dep ludic
# : dep feedgen
# : dep itsdangerous
# : dep uvicorn
# : dep stripe
# : dep sqids

import Biz.PodcastItLater.Core as Core
import Biz.PodcastItLater.Web as Web
import Omni.Test as Test
from starlette.testclient import TestClient


class BaseWebTest(Test.TestCase):
    """Base class for web tests."""

    def setUp(self) -> None:
        """Set up test database and client."""
        Core.Database.init_db()
        self.client = TestClient(Web.app)

    @staticmethod
    def tearDown() -> None:
        """Clean up test database."""
        Core.Database.teardown()


class TestMetricsView(BaseWebTest):
    """Test Admin Metrics View."""

    def test_admin_metrics_view_access(self) -> None:
        """Admin user should be able to access metrics view."""
        # Create admin user
        _admin_id, _ = Core.Database.create_user("ben@bensima.com")
        self.client.post("/login", data={"email": "ben@bensima.com"})

        response = self.client.get("/admin/metrics")
        self.assertEqual(response.status_code, 200)
        self.assertIn("Growth & Usage", response.text)
        self.assertIn("Total Users", response.text)

    def test_admin_metrics_data(self) -> None:
        """Metrics view should show correct data."""
        # Create admin user
        admin_id, _ = Core.Database.create_user("ben@bensima.com")
        self.client.post("/login", data={"email": "ben@bensima.com"})

        # Create some data
        # 1. Users
        Core.Database.create_user("user1@example.com")
        user2_id, _ = Core.Database.create_user("user2@example.com")

        # 2. Subscriptions (simulate by setting subscription_status)
        with Core.Database.get_connection() as conn:
            conn.execute(
                "UPDATE users SET subscription_status = 'active' WHERE id = ?",
                (user2_id,),
            )
            conn.commit()

        # 3. Submissions
        Core.Database.add_to_queue(
            "http://example.com/1",
            "user1@example.com",
            admin_id,
        )

        # Get metrics page
        response = self.client.get("/admin/metrics")
        self.assertEqual(response.status_code, 200)

        # Check labels
        self.assertIn("Total Users", response.text)
        self.assertIn("Active Subs", response.text)
        self.assertIn("Submissions (24h)", response.text)

        # Check values (metrics dict is passed to template,
        # we check rendered HTML)
        # Total users: 3 (admin + user1 + user2)
        # Active subs: 1 (user2)
        # Submissions 24h: 1

        # Check for values in HTML
        # Note: This is a bit brittle, but effective for quick verification
        self.assertIn('<h3 class="mb-0">3</h3>', response.text)
        self.assertIn('<h3 class="mb-0">1</h3>', response.text)

    def test_non_admin_access_denied(self) -> None:
        """Non-admin users should be denied access."""
        # Create regular user
        Core.Database.create_user("regular@example.com")
        self.client.post("/login", data={"email": "regular@example.com"})

        response = self.client.get("/admin/metrics")
        # Should redirect to /?error=forbidden
        self.assertEqual(response.status_code, 302)
        self.assertIn("error=forbidden", response.headers["Location"])

    def test_anonymous_access_redirect(self) -> None:
        """Anonymous users should be redirected to login."""
        response = self.client.get("/admin/metrics")
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response.headers["Location"], "/")


def main() -> None:
    """Run the tests."""
    Test.run(
        Web.area,
        [TestMetricsView],
    )


if __name__ == "__main__":
    main()