@@ -156,6 +156,116 @@ def test_get_label_metrics_closed_issue_label_remains_through_closure(self):
156156expected_duration = timedelta (days = 8 )
157157self .assertEqual (metrics ["stays-applied" ],expected_duration )
158158
159+ def test_get_label_metrics_label_applied_at_creation_and_removed_before_closure (self ):
160+ """Test get_label_metrics for a label applied at issue creation and removed before closure"""
161+ # Test scenario where label is applied at creation and later removed:
162+ # Issue created: day 0 (2021-01-01) with label applied
163+ # Label removed: day 7 (2021-01-08)
164+ # Issue closed: day 20 (2021-01-21)
165+ # Expected duration: 7 days (from creation to removal)
166+
167+ issue = MagicMock ()
168+ issue .issue = MagicMock (spec = github3 .issues .Issue )
169+ issue .created_at = "2021-01-01T00:00:00Z"
170+ issue .closed_at = "2021-01-21T00:00:00Z" # 20 days after creation
171+ issue .state = "closed"
172+ issue .issue .events .return_value = [
173+ MagicMock (
174+ event = "labeled" ,
175+ label = {"name" :"creation-label" },
176+ created_at = datetime (2021 ,1 ,1 ,tzinfo = pytz .UTC ),# day 0 - at creation
177+ ),
178+ MagicMock (
179+ event = "unlabeled" ,
180+ label = {"name" :"creation-label" },
181+ created_at = datetime (2021 ,1 ,8 ,tzinfo = pytz .UTC ),# day 7
182+ ),
183+ ]
184+
185+ labels = ["creation-label" ]
186+ metrics = get_label_metrics (issue ,labels )
187+
188+ # Should be 7 days (from creation to removal), not 20 days (full issue duration)
189+ expected_duration = timedelta (days = 7 )
190+ self .assertEqual (metrics ["creation-label" ],expected_duration )
191+
192+ def test_get_label_metrics_label_applied_at_creation_remains_through_closure (self ):
193+ """Test get_label_metrics for a label applied at creation and kept through closure"""
194+ # Test scenario where label is applied at creation and never removed:
195+ # Issue created: day 0 (2021-01-01) with label applied
196+ # Issue closed: day 30 (2021-01-31)
197+ # Expected duration: 30 days (full issue duration)
198+
199+ issue = MagicMock ()
200+ issue .issue = MagicMock (spec = github3 .issues .Issue )
201+ issue .created_at = "2021-01-01T00:00:00Z"
202+ issue .closed_at = "2021-01-31T00:00:00Z" # 30 days after creation
203+ issue .state = "closed"
204+ issue .issue .events .return_value = [
205+ MagicMock (
206+ event = "labeled" ,
207+ label = {"name" :"permanent-label" },
208+ created_at = datetime (2021 ,1 ,1 ,tzinfo = pytz .UTC ),# day 0 - at creation
209+ ),
210+ # No unlabel event - label remains applied
211+ ]
212+
213+ labels = ["permanent-label" ]
214+ metrics = get_label_metrics (issue ,labels )
215+
216+ # Should be 30 days (full issue duration since label was applied at creation)
217+ expected_duration = timedelta (days = 30 )
218+ self .assertEqual (metrics ["permanent-label" ],expected_duration )
219+
220+ def test_get_label_metrics_multiple_labels_different_timeframes (self ):
221+ """Test get_label_metrics with multiple labels having different application patterns and longer timeframes"""
222+ # Test scenario with multiple labels and longer timeframes:
223+ # Issue created: day 0 (2021-01-01)
224+ # Label A applied: day 0 (at creation)
225+ # Label B applied: day 14 (2021-01-15)
226+ # Label A removed: day 21 (2021-01-22)
227+ # Label B removed: day 35 (2021-02-05)
228+ # Issue closed: day 60 (2021-03-02)
229+ # Expected: Label A = 21 days, Label B = 21 days
230+
231+ issue = MagicMock ()
232+ issue .issue = MagicMock (spec = github3 .issues .Issue )
233+ issue .created_at = "2021-01-01T00:00:00Z"
234+ issue .closed_at = "2021-03-02T00:00:00Z" # 60 days after creation
235+ issue .state = "closed"
236+ issue .issue .events .return_value = [
237+ MagicMock (
238+ event = "labeled" ,
239+ label = {"name" :"label-a" },
240+ created_at = datetime (2021 ,1 ,1 ,tzinfo = pytz .UTC ),# day 0 - at creation
241+ ),
242+ MagicMock (
243+ event = "labeled" ,
244+ label = {"name" :"label-b" },
245+ created_at = datetime (2021 ,1 ,15 ,tzinfo = pytz .UTC ),# day 14
246+ ),
247+ MagicMock (
248+ event = "unlabeled" ,
249+ label = {"name" :"label-a" },
250+ created_at = datetime (2021 ,1 ,22 ,tzinfo = pytz .UTC ),# day 21
251+ ),
252+ MagicMock (
253+ event = "unlabeled" ,
254+ label = {"name" :"label-b" },
255+ created_at = datetime (2021 ,2 ,5 ,tzinfo = pytz .UTC ),# day 35
256+ ),
257+ ]
258+
259+ labels = ["label-a" ,"label-b" ]
260+ metrics = get_label_metrics (issue ,labels )
261+
262+ # Label A: 21 days (from day 0 to day 21)
263+ # Label B: 21 days (from day 14 to day 35)
264+ expected_duration_a = timedelta (days = 21 )
265+ expected_duration_b = timedelta (days = 21 )
266+ self .assertEqual (metrics ["label-a" ],expected_duration_a )
267+ self .assertEqual (metrics ["label-b" ],expected_duration_b )
268+
159269
160270class TestGetAverageTimeInLabels (unittest .TestCase ):
161271"""Unit tests for get_stats_time_in_labels"""