FossilRepo

fossilrepo / core / tests.py
Blame History Raw 148 lines
1
import pytest
2
from django.contrib.auth.models import User
3
from django.test import TestCase
4
from django.urls import reverse
5
6
from .permissions import P
7
8
9
class TrackingModelTest(TestCase):
10
"""Test the Tracking abstract model via a concrete model that uses it."""
11
12
def setUp(self):
13
from organization.models import Organization
14
from projects.models import Project
15
16
self.user = User.objects.create_superuser(username="test", password="x")
17
self.org = Organization.objects.create(name="Test Org", created_by=self.user)
18
self.project = Project.objects.create(name="Test Project", organization=self.org, created_by=self.user)
19
20
def test_version_increments_on_save(self):
21
initial_version = self.project.version
22
self.project.name = "Updated Project"
23
self.project.save()
24
self.project.refresh_from_db()
25
self.assertEqual(self.project.version, initial_version + 1)
26
27
def test_soft_delete_sets_deleted_at(self):
28
self.project.soft_delete(user=self.user)
29
self.project.refresh_from_db()
30
self.assertIsNotNone(self.project.deleted_at)
31
self.assertEqual(self.project.deleted_by, self.user)
32
self.assertTrue(self.project.is_deleted)
33
34
def test_created_at_auto_set(self):
35
self.assertIsNotNone(self.project.created_at)
36
37
def test_updated_at_auto_set(self):
38
self.assertIsNotNone(self.project.updated_at)
39
40
41
class BaseCoreModelTest(TestCase):
42
"""Test BaseCoreModel slug generation and UUID."""
43
44
def setUp(self):
45
from organization.models import Organization
46
from projects.models import Project
47
48
self.user = User.objects.create_superuser(username="test", password="x")
49
self.org = Organization.objects.create(name="Test Org", created_by=self.user)
50
self.project = Project.objects.create(name="My Project", organization=self.org, created_by=self.user)
51
52
def test_slug_auto_generated(self):
53
self.assertEqual(self.project.slug, "my-project")
54
55
def test_guid_is_uuid(self):
56
import uuid
57
58
self.assertIsInstance(self.project.guid, uuid.UUID)
59
60
def test_slug_uniqueness(self):
61
from projects.models import Project
62
63
p2 = Project.objects.create(name="My Project", organization=self.org, created_by=self.user)
64
self.assertNotEqual(self.project.slug, p2.slug)
65
self.assertTrue(p2.slug.startswith("my-project"))
66
67
def test_str_returns_name(self):
68
self.assertEqual(str(self.project), "My Project")
69
70
71
class PermissionsTest(TestCase):
72
"""Test the P permission enum."""
73
74
def setUp(self):
75
self.superuser = User.objects.create_superuser(username="super", password="x")
76
self.regular = User.objects.create_user(username="regular", password="x")
77
78
def test_superuser_passes_all_checks(self):
79
self.assertTrue(P.PROJECT_VIEW.check(self.superuser))
80
self.assertTrue(P.PROJECT_ADD.check(self.superuser))
81
82
def test_regular_user_without_perm_denied(self):
83
from django.core.exceptions import PermissionDenied
84
85
with self.assertRaises(PermissionDenied):
86
P.PROJECT_ADD.check(self.regular)
87
88
def test_regular_user_without_perm_returns_false(self):
89
self.assertFalse(P.PROJECT_ADD.check(self.regular, raise_error=False))
90
91
def test_unauthenticated_user_denied(self):
92
from django.contrib.auth.models import AnonymousUser
93
from django.core.exceptions import PermissionDenied
94
95
with self.assertRaises(PermissionDenied):
96
P.PROJECT_VIEW.check(AnonymousUser())
97
98
99
@pytest.mark.django_db
100
class TestDashboard:
101
def test_dashboard_requires_login(self, client):
102
response = client.get(reverse("dashboard"))
103
assert response.status_code == 302
104
assert "/auth/login/" in response.url
105
106
def test_dashboard_renders_for_authenticated_user(self, admin_client):
107
response = admin_client.get(reverse("dashboard"))
108
assert response.status_code == 200
109
assert b"Dashboard" in response.content
110
111
112
@pytest.mark.django_db
113
class TestHealthCheck:
114
def test_health_returns_ok(self, client):
115
response = client.get(reverse("health"))
116
assert response.status_code == 200
117
data = response.json()
118
assert data["status"] == "ok"
119
assert data["service"] == "fossilrepo-django-htmx"
120
assert "version" in data
121
assert "uptime" in data
122
assert "timestamp" in data
123
assert data["checks"]["database"] == "ok"
124
assert data["links"]["status"] == "/status/"
125
126
127
@pytest.mark.django_db
128
class TestStatusPage:
129
def test_status_page_accessible_unauthenticated(self, client):
130
response = client.get(reverse("status"))
131
assert response.status_code == 200
132
assert b"Fossilrepo" in response.content
133
assert b"Server-rendered Django + HTMX." in response.content
134
135
def test_status_page_contains_links(self, client):
136
response = client.get(reverse("status"))
137
content = response.content.decode()
138
assert "/dashboard/" in content
139
assert "/admin/" in content
140
assert "/health/" in content
141
assert "/auth/login/" in content
142
143
def test_status_page_contains_meta(self, client):
144
response = client.get(reverse("status"))
145
content = response.content.decode()
146
assert "fossilrepo-django-htmx" in content
147
assert "All systems operational" in content
148

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button