4
4
from datetime import datetime , timedelta
5
5
from unittest .mock import MagicMock
6
6
7
+ import github3
7
8
import pytz
8
9
from time_in_draft import get_stats_time_in_draft , measure_time_in_draft
9
10
@@ -18,13 +19,14 @@ def setUp(self):
18
19
Setup common test data and mocks.
19
20
"""
20
21
self .issue = MagicMock ()
22
+ self .issue .issue = MagicMock (spec = github3 .issues .Issue )
21
23
self .issue .issue .state = "open"
22
24
23
25
def test_time_in_draft_with_ready_for_review (self ):
24
26
"""
25
27
Test measure_time_in_draft with one draft and review interval.
26
28
"""
27
- self .issue .events .return_value = [
29
+ self .issue .issue . events .return_value = [
28
30
MagicMock (
29
31
event = "converted_to_draft" ,
30
32
created_at = datetime (2021 , 1 , 1 , tzinfo = pytz .utc ),
@@ -42,7 +44,7 @@ def test_time_in_draft_without_ready_for_review(self):
42
44
"""
43
45
Test measure_time_in_draft when ready_for_review_at is not provided and issue is still open.
44
46
"""
45
- self .issue .events .return_value = [
47
+ self .issue .issue . events .return_value = [
46
48
MagicMock (
47
49
event = "converted_to_draft" ,
48
50
created_at = datetime (2021 , 1 , 1 , tzinfo = pytz .utc ),
@@ -59,7 +61,7 @@ def test_time_in_draft_multiple_intervals(self):
59
61
"""
60
62
Test measure_time_in_draft with multiple draft intervals.
61
63
"""
62
- self .issue .events .return_value = [
64
+ self .issue .issue . events .return_value = [
63
65
MagicMock (
64
66
event = "converted_to_draft" ,
65
67
created_at = datetime (2021 , 1 , 1 , tzinfo = pytz .utc ),
@@ -85,7 +87,7 @@ def test_time_in_draft_ongoing_draft(self):
85
87
"""
86
88
Test measure_time_in_draft with an ongoing draft interval.
87
89
"""
88
- self .issue .events .return_value = [
90
+ self .issue .issue . events .return_value = [
89
91
MagicMock (
90
92
event = "converted_to_draft" ,
91
93
created_at = datetime (2021 , 1 , 1 , tzinfo = pytz .utc ),
@@ -103,7 +105,7 @@ def test_time_in_draft_no_draft_events(self):
103
105
"""
104
106
Test measure_time_in_draft with no draft-related events.
105
107
"""
106
- self .issue .events .return_value = []
108
+ self .issue .issue . events .return_value = []
107
109
result = measure_time_in_draft (self .issue )
108
110
self .assertIsNone (
109
111
result , "The result should be None when there are no draft events."
@@ -113,7 +115,7 @@ def test_time_in_draft_without_ready_for_review_and_closed(self):
113
115
"""
114
116
Test measure_time_in_draft for a closed issue with an ongoing draft and ready_for_review_at is not provided.
115
117
"""
116
- self .issue .events .return_value = [
118
+ self .issue .issue . events .return_value = [
117
119
MagicMock (
118
120
event = "converted_to_draft" ,
119
121
created_at = datetime (2021 , 1 , 1 , tzinfo = pytz .utc ),
@@ -126,6 +128,30 @@ def test_time_in_draft_without_ready_for_review_and_closed(self):
126
128
"The result should be None for a closed issue with an ongoing draft." ,
127
129
)
128
130
131
+ def test_time_in_draft_with_attribute_error_scenario (self ):
132
+ """
133
+ Test measure_time_in_draft to ensure it doesn't raise AttributeError when called
134
+ with issue structure similar to what get_per_issue_metrics passes.
135
+ This test reproduces the original bug scenario.
136
+ """
137
+ # This simulates the actual issue structure passed from get_per_issue_metrics
138
+ issue_search_result = MagicMock ()
139
+ issue_search_result .issue = MagicMock (spec = github3 .issues .Issue )
140
+ issue_search_result .issue .state = "open"
141
+ issue_search_result .issue .events .return_value = [
142
+ MagicMock (
143
+ event = "converted_to_draft" ,
144
+ created_at = datetime (2021 , 1 , 1 , tzinfo = pytz .utc ),
145
+ ),
146
+ ]
147
+
148
+ # This should NOT raise AttributeError: events
149
+ with unittest .mock .patch ("time_in_draft.datetime" ) as mock_datetime :
150
+ mock_datetime .now .return_value = datetime (2021 , 1 , 4 , tzinfo = pytz .utc )
151
+ result = measure_time_in_draft (issue_search_result )
152
+ expected = timedelta (days = 3 )
153
+ self .assertEqual (result , expected , "The time in draft should be 3 days." )
154
+
129
155
130
156
class TestGetStatsTimeInDraft (unittest .TestCase ):
131
157
"""
0 commit comments