11"""Test cases for owasp_aggregate_contributions management command."""
22
3- from datetime import datetime , timedelta
3+ from datetime import UTC , datetime , timedelta
44from unittest import mock
55
66import pytest
7- from django .core .management import call_command
87
9- from apps .github .models import Commit , Issue , PullRequest , Release
108from apps .owasp .management .commands .owasp_aggregate_contributions import Command
119from apps .owasp .models import Chapter , Project
1210
@@ -38,24 +36,24 @@ def mock_project(self):
3836 def test_aggregate_contribution_dates_helper (self , command ):
3937 """Test the helper method that aggregates dates."""
4038 contribution_map = {}
41-
39+
4240 # Create mock queryset with dates
4341 mock_dates = [
44- datetime (2024 , 11 , 16 , 10 , 0 , 0 ),
45- datetime (2024 , 11 , 16 , 14 , 0 , 0 ), # Same day
46- datetime (2024 , 11 , 17 , 9 , 0 , 0 ),
42+ datetime (2024 , 11 , 16 , 10 , 0 , 0 , tzinfo = UTC ),
43+ datetime (2024 , 11 , 16 , 14 , 0 , 0 , tzinfo = UTC ), # Same day
44+ datetime (2024 , 11 , 17 , 9 , 0 , 0 , tzinfo = UTC ),
4745 None , # Should be skipped
4846 ]
49-
47+
5048 mock_queryset = mock .Mock ()
5149 mock_queryset .values_list .return_value = mock_dates
52-
50+
5351 command ._aggregate_contribution_dates (
5452 mock_queryset ,
5553 "created_at" ,
5654 contribution_map ,
5755 )
58-
56+
5957 assert contribution_map == {
6058 "2024-11-16" : 2 ,
6159 "2024-11-17" : 1 ,
@@ -75,24 +73,24 @@ def test_aggregate_chapter_contributions(
7573 mock_chapter ,
7674 ):
7775 """Test aggregating contributions for a chapter."""
78- start_date = datetime .now () - timedelta (days = 365 )
79-
76+ start_date = datetime .now (tz = UTC ) - timedelta (days = 365 )
77+
8078 # Mock querysets
8179 mock_commit .objects .filter .return_value .values_list .return_value = [
82- datetime (2024 , 11 , 16 , 10 , 0 , 0 ),
80+ datetime (2024 , 11 , 16 , 10 , 0 , 0 , tzinfo = UTC ),
8381 ]
8482 mock_issue .objects .filter .return_value .values_list .return_value = [
85- datetime (2024 , 11 , 16 , 11 , 0 , 0 ),
83+ datetime (2024 , 11 , 16 , 11 , 0 , 0 , tzinfo = UTC ),
8684 ]
8785 mock_pr .objects .filter .return_value .values_list .return_value = [
88- datetime (2024 , 11 , 17 , 10 , 0 , 0 ),
86+ datetime (2024 , 11 , 17 , 10 , 0 , 0 , tzinfo = UTC ),
8987 ]
9088 mock_release .objects .filter .return_value .values_list .return_value = [
91- datetime (2024 , 11 , 17 , 12 , 0 , 0 ),
89+ datetime (2024 , 11 , 17 , 12 , 0 , 0 , tzinfo = UTC ),
9290 ]
93-
91+
9492 result = command .aggregate_chapter_contributions (mock_chapter , start_date )
95-
93+
9694 assert result == {
9795 "2024-11-16" : 2 , # 1 commit + 1 issue
9896 "2024-11-17" : 2 , # 1 PR + 1 release
@@ -112,25 +110,25 @@ def test_aggregate_project_contributions(
112110 mock_project ,
113111 ):
114112 """Test aggregating contributions for a project."""
115- start_date = datetime .now () - timedelta (days = 365 )
116-
113+ start_date = datetime .now (tz = UTC ) - timedelta (days = 365 )
114+
117115 # Mock querysets
118116 mock_commit .objects .filter .return_value .values_list .return_value = [
119- datetime (2024 , 11 , 16 , 10 , 0 , 0 ),
120- datetime (2024 , 11 , 16 , 14 , 0 , 0 ),
117+ datetime (2024 , 11 , 16 , 10 , 0 , 0 , tzinfo = UTC ),
118+ datetime (2024 , 11 , 16 , 14 , 0 , 0 , tzinfo = UTC ),
121119 ]
122120 mock_issue .objects .filter .return_value .values_list .return_value = [
123- datetime (2024 , 11 , 17 , 11 , 0 , 0 ),
121+ datetime (2024 , 11 , 17 , 11 , 0 , 0 , tzinfo = UTC ),
124122 ]
125123 mock_pr .objects .filter .return_value .values_list .return_value = [
126- datetime (2024 , 11 , 18 , 10 , 0 , 0 ),
124+ datetime (2024 , 11 , 18 , 10 , 0 , 0 , tzinfo = UTC ),
127125 ]
128126 mock_release .objects .filter .return_value .values_list .return_value = [
129- datetime (2024 , 11 , 18 , 12 , 0 , 0 ),
127+ datetime (2024 , 11 , 18 , 12 , 0 , 0 , tzinfo = UTC ),
130128 ]
131-
129+
132130 result = command .aggregate_project_contributions (mock_project , start_date )
133-
131+
134132 assert result == {
135133 "2024-11-16" : 2 , # 2 commits
136134 "2024-11-17" : 1 , # 1 issue
@@ -140,35 +138,35 @@ def test_aggregate_project_contributions(
140138 def test_aggregate_chapter_without_repository (self , command , mock_chapter ):
141139 """Test that chapters without repositories return empty map."""
142140 mock_chapter .owasp_repository = None
143- start_date = datetime .now () - timedelta (days = 365 )
144-
141+ start_date = datetime .now (tz = UTC ) - timedelta (days = 365 )
142+
145143 result = command .aggregate_chapter_contributions (mock_chapter , start_date )
146-
144+
147145 assert result == {}
148146
149147 def test_aggregate_project_without_repositories (self , command , mock_project ):
150148 """Test that projects without repositories return empty map."""
151149 mock_project .owasp_repository = None
152150 mock_project .repositories .all .return_value = []
153- start_date = datetime .now () - timedelta (days = 365 )
154-
151+ start_date = datetime .now (tz = UTC ) - timedelta (days = 365 )
152+
155153 result = command .aggregate_project_contributions (mock_project , start_date )
156-
154+
157155 assert result == {}
158156
159157 @mock .patch .object (Chapter , "bulk_save" )
160158 @mock .patch .object (Chapter .objects , "filter" )
161159 def test_handle_chapters_only (self , mock_filter , mock_bulk_save , command , mock_chapter ):
162160 """Test command execution for chapters only."""
163161 mock_filter .return_value = [mock_chapter ]
164-
162+
165163 with mock .patch .object (
166164 command ,
167165 "aggregate_chapter_contributions" ,
168166 return_value = {"2024-11-16" : 5 },
169167 ):
170168 command .handle (entity_type = "chapter" , days = 365 )
171-
169+
172170 assert mock_chapter .contribution_data == {"2024-11-16" : 5 }
173171 assert mock_bulk_save .called
174172
@@ -177,14 +175,14 @@ def test_handle_chapters_only(self, mock_filter, mock_bulk_save, command, mock_c
177175 def test_handle_projects_only (self , mock_filter , mock_bulk_save , command , mock_project ):
178176 """Test command execution for projects only."""
179177 mock_filter .return_value = [mock_project ]
180-
178+
181179 with mock .patch .object (
182180 command ,
183181 "aggregate_project_contributions" ,
184182 return_value = {"2024-11-16" : 10 },
185183 ):
186184 command .handle (entity_type = "project" , days = 365 )
187-
185+
188186 assert mock_project .contribution_data == {"2024-11-16" : 10 }
189187 assert mock_bulk_save .called
190188
@@ -205,7 +203,7 @@ def test_handle_both_entities(
205203 """Test command execution for both chapters and projects."""
206204 mock_chapter_filter .return_value = [mock_chapter ]
207205 mock_project_filter .return_value = [mock_project ]
208-
206+
209207 with (
210208 mock .patch .object (
211209 command ,
@@ -219,15 +217,15 @@ def test_handle_both_entities(
219217 ),
220218 ):
221219 command .handle (entity_type = "both" , days = 365 )
222-
220+
223221 assert mock_chapter_bulk_save .called
224222 assert mock_project_bulk_save .called
225223
226224 @mock .patch .object (Chapter .objects , "filter" )
227225 def test_handle_with_specific_key (self , mock_filter , command , mock_chapter ):
228226 """Test command execution with a specific entity key."""
229227 mock_filter .return_value = [mock_chapter ]
230-
228+
231229 with (
232230 mock .patch .object (Chapter , "bulk_save" ),
233231 mock .patch .object (
@@ -237,7 +235,7 @@ def test_handle_with_specific_key(self, mock_filter, command, mock_chapter):
237235 ),
238236 ):
239237 command .handle (entity_type = "chapter" , key = "www-chapter-test" , days = 365 )
240-
238+
241239 # Verify filter was called with the specific key
242240 mock_filter .assert_called ()
243241
@@ -248,7 +246,7 @@ def test_handle_with_offset(self, mock_filter, command, mock_chapter):
248246 mock_queryset = mock .Mock ()
249247 mock_queryset .__getitem__ .return_value = chapters [2 :] # Skip first 2
250248 mock_filter .return_value = mock_queryset
251-
249+
252250 with (
253251 mock .patch .object (Chapter , "bulk_save" ),
254252 mock .patch .object (
@@ -258,7 +256,7 @@ def test_handle_with_offset(self, mock_filter, command, mock_chapter):
258256 ),
259257 ):
260258 command .handle (entity_type = "chapter" , offset = 2 , days = 365 )
261-
259+
262260 # Verify offset was applied
263261 mock_queryset .__getitem__ .assert_called_with (slice (2 , None ))
264262
@@ -274,12 +272,12 @@ def test_handle_custom_days(self, command, mock_chapter):
274272 ) as mock_aggregate ,
275273 ):
276274 command .handle (entity_type = "chapter" , days = 90 )
277-
275+
278276 # Verify aggregate was called with correct start_date
279277 assert mock_aggregate .called
280278 call_args = mock_aggregate .call_args [0 ]
281279 start_date = call_args [1 ]
282- expected_start = datetime .now () - timedelta (days = 90 )
283-
280+ expected_start = datetime .now (tz = UTC ) - timedelta (days = 90 )
281+
284282 # Allow 1 second tolerance for test execution time
285283 assert abs ((expected_start - start_date ).total_seconds ()) < 1
0 commit comments