Skip to content

Commit 952a373

Browse files
committed
add unit tests for event models module
1 parent f93331a commit 952a373

File tree

1 file changed

+203
-0
lines changed

1 file changed

+203
-0
lines changed

tests/event/test_models.py

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
from datetime import datetime, timezone
2+
from unittest.mock import Mock
3+
4+
from sqlalchemy.orm import DeclarativeBase
5+
6+
from crudadmin.event.models import create_admin_audit_log, create_admin_event_log
7+
from crudadmin.event.schemas import EventType
8+
9+
UTC = timezone.utc
10+
11+
12+
class MockBase(DeclarativeBase):
13+
"""Mock base class for testing."""
14+
15+
pass
16+
17+
18+
class TestCreateAdminEventLog:
19+
"""Test cases for create_admin_event_log function."""
20+
21+
def test_create_admin_event_log_basic_functionality(self):
22+
"""Test basic functionality of create_admin_event_log."""
23+
base = MockBase
24+
EventLogModel = create_admin_event_log(base)
25+
26+
assert EventLogModel.__name__ == "AdminEventLog"
27+
assert EventLogModel.__tablename__ == "admin_event_log"
28+
assert issubclass(EventLogModel, base)
29+
assert hasattr(EventLogModel, "__table_args__")
30+
assert EventLogModel.__table_args__ == {"extend_existing": True}
31+
32+
def test_create_admin_event_log_has_all_required_fields(self):
33+
"""Test that AdminEventLog has all required fields with correct types."""
34+
base = MockBase
35+
EventLogModel = create_admin_event_log(base)
36+
37+
# Check field existence and types
38+
for field in EventLogModel.__table__.columns:
39+
assert hasattr(EventLogModel, field.key)
40+
41+
def test_create_admin_event_log_repr_method(self):
42+
"""Test __repr__ method of AdminEventLog."""
43+
base = MockBase
44+
EventLogModel = create_admin_event_log(base)
45+
46+
# Create an instance to test repr
47+
instance = EventLogModel()
48+
instance.id = 1
49+
instance.event_type = EventType.CREATE
50+
instance.user_id = 123
51+
52+
repr_str = repr(instance)
53+
assert "AdminEventLog" in repr_str
54+
assert "id=1" in repr_str
55+
assert "event_type=create" in repr_str # Enum value is stored as string
56+
assert "user_id=123" in repr_str
57+
58+
def test_create_admin_event_log_returns_existing_class(self):
59+
"""Test that function returns existing class when already in registry."""
60+
base = MockBase
61+
62+
# Create the first instance
63+
EventLogModel1 = create_admin_event_log(base)
64+
65+
# Create the second instance - should return the same class
66+
EventLogModel2 = create_admin_event_log(base)
67+
68+
assert EventLogModel1 is EventLogModel2
69+
assert EventLogModel1.__name__ == "AdminEventLog"
70+
assert EventLogModel2.__name__ == "AdminEventLog"
71+
72+
def test_create_admin_event_log_with_base_without_registry(self):
73+
"""Test function behavior when base class doesn't have registry."""
74+
75+
class BaseWithoutRegistry:
76+
pass
77+
78+
EventLogModel = create_admin_event_log(BaseWithoutRegistry)
79+
80+
assert EventLogModel.__name__ == "AdminEventLog"
81+
assert EventLogModel.__tablename__ == "admin_event_log"
82+
assert issubclass(EventLogModel, BaseWithoutRegistry)
83+
84+
85+
class TestCreateAdminAuditLog:
86+
"""Test cases for create_admin_audit_log function."""
87+
88+
def test_create_admin_audit_log_basic_functionality(self):
89+
"""Test basic functionality of create_admin_audit_log."""
90+
base = MockBase
91+
AuditLogModel = create_admin_audit_log(base)
92+
93+
assert AuditLogModel.__name__ == "AdminAuditLog"
94+
assert AuditLogModel.__tablename__ == "admin_audit_log"
95+
assert issubclass(AuditLogModel, base)
96+
assert hasattr(AuditLogModel, "__table_args__")
97+
assert AuditLogModel.__table_args__ == {"extend_existing": True}
98+
99+
def test_create_admin_audit_log_has_all_required_fields(self):
100+
"""Test that AdminAuditLog has all required fields."""
101+
base = MockBase
102+
AuditLogModel = create_admin_audit_log(base)
103+
104+
# Check field existence
105+
for field in AuditLogModel.__table__.columns:
106+
assert hasattr(AuditLogModel, field.key)
107+
108+
def test_create_admin_audit_log_repr_method(self):
109+
"""Test __repr__ method of AdminAuditLog."""
110+
base = MockBase
111+
AuditLogModel = create_admin_audit_log(base)
112+
113+
# Create an instance to test repr
114+
instance = AuditLogModel()
115+
instance.id = 1
116+
instance.resource_type = "user"
117+
instance.resource_id = "123"
118+
119+
repr_str = repr(instance)
120+
assert "AdminAuditLog" in repr_str
121+
assert "id=1" in repr_str
122+
assert "resource_type=user" in repr_str
123+
assert "resource_id=123" in repr_str
124+
125+
def test_create_admin_audit_log_returns_existing_class(self):
126+
"""Test that function returns existing class when already in registry."""
127+
base = MockBase
128+
129+
# Create the first instance
130+
AuditLogModel1 = create_admin_audit_log(base)
131+
132+
# Create the second instance - should return the same class
133+
AuditLogModel2 = create_admin_audit_log(base)
134+
135+
assert AuditLogModel1 is AuditLogModel2
136+
assert AuditLogModel1.__name__ == "AdminAuditLog"
137+
assert AuditLogModel2.__name__ == "AdminAuditLog"
138+
139+
def test_create_admin_audit_log_with_base_without_registry(self):
140+
"""Test function behavior when base class doesn't have registry."""
141+
142+
class BaseWithoutRegistry:
143+
pass
144+
145+
AuditLogModel = create_admin_audit_log(BaseWithoutRegistry)
146+
147+
assert AuditLogModel.__name__ == "AdminAuditLog"
148+
assert AuditLogModel.__tablename__ == "admin_audit_log"
149+
assert issubclass(AuditLogModel, BaseWithoutRegistry)
150+
151+
152+
class TestModelIntegration:
153+
"""Integration tests for both model creation functions."""
154+
155+
def test_both_models_can_be_created_with_same_base(self):
156+
"""Test that both models can be created with the same base class."""
157+
base = MockBase
158+
159+
EventLogModel = create_admin_event_log(base)
160+
AuditLogModel = create_admin_audit_log(base)
161+
162+
assert EventLogModel.__name__ == "AdminEventLog"
163+
assert AuditLogModel.__name__ == "AdminAuditLog"
164+
assert issubclass(EventLogModel, base)
165+
assert issubclass(AuditLogModel, base)
166+
assert EventLogModel is not AuditLogModel
167+
168+
def test_models_have_different_table_names(self):
169+
"""Test that models have different table names."""
170+
base = MockBase
171+
172+
EventLogModel = create_admin_event_log(base)
173+
AuditLogModel = create_admin_audit_log(base)
174+
175+
assert EventLogModel.__tablename__ != AuditLogModel.__tablename__
176+
assert EventLogModel.__tablename__ == "admin_event_log"
177+
assert AuditLogModel.__tablename__ == "admin_audit_log"
178+
179+
def test_models_timestamp_default_behavior(self):
180+
"""Test timestamp default behavior for both models."""
181+
base = MockBase
182+
183+
EventLogModel = create_admin_event_log(base)
184+
AuditLogModel = create_admin_audit_log(base)
185+
186+
# Test that timestamp columns have default values
187+
event_timestamp = EventLogModel.__table__.columns.get("timestamp")
188+
audit_timestamp = AuditLogModel.__table__.columns.get("timestamp")
189+
190+
assert event_timestamp.default is not None
191+
assert audit_timestamp.default is not None
192+
193+
# Test that default can be called to generate current UTC time
194+
# Using a mock context as the lambda expects it
195+
mock_ctx = Mock()
196+
197+
event_default_value = event_timestamp.default.arg(mock_ctx)
198+
audit_default_value = audit_timestamp.default.arg(mock_ctx)
199+
200+
assert isinstance(event_default_value, datetime)
201+
assert isinstance(audit_default_value, datetime)
202+
assert event_default_value.tzinfo == UTC
203+
assert audit_default_value.tzinfo == UTC

0 commit comments

Comments
 (0)