Skip to content

Commit 900f511

Browse files
committed
add more unit tests per gemini review.
1 parent 87b9116 commit 900f511

File tree

1 file changed

+85
-1
lines changed

1 file changed

+85
-1
lines changed

tests/test_scheduler_fn.py

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import unittest
1717
from datetime import datetime, timezone
18-
from unittest.mock import Mock
18+
from unittest.mock import Mock, patch
1919

2020
from flask import Flask, Request
2121
from werkzeug.test import EnvironBuilder
@@ -146,6 +146,90 @@ def test_on_schedule_call_with_exception(self):
146146
self.assertEqual(response.status_code, 500)
147147
self.assertEqual(response.data, b"Test exception")
148148

149+
def test_on_schedule_call_with_fractional_seconds(self):
150+
"""
151+
Tests to ensure that timestamps with fractional seconds are parsed correctly.
152+
"""
153+
with Flask(__name__).test_request_context("/"):
154+
environ = EnvironBuilder(
155+
headers={
156+
"X-CloudScheduler-JobName": "example-job",
157+
"X-CloudScheduler-ScheduleTime": "2023-04-13T19:00:00.123456Z",
158+
}
159+
).get_environ()
160+
mock_request = Request(environ)
161+
example_func = Mock(__name__="example_func")
162+
decorated_func = scheduler_fn.on_schedule(schedule="* * * * *")(example_func)
163+
response = decorated_func(mock_request)
164+
165+
self.assertEqual(response.status_code, 200)
166+
example_func.assert_called_once_with(
167+
scheduler_fn.ScheduledEvent(
168+
job_name="example-job",
169+
schedule_time=datetime(2023, 4, 13, 19, 0, 0, 123456, tzinfo=timezone.utc),
170+
)
171+
)
172+
173+
def test_on_schedule_call_fallback_parsing(self):
174+
"""
175+
Tests fallback parsing for formats that might fail fromisoformat
176+
but pass strptime (e.g., offset without colon).
177+
"""
178+
with Flask(__name__).test_request_context("/"):
179+
environ = EnvironBuilder(
180+
headers={
181+
"X-CloudScheduler-JobName": "example-job",
182+
# Offset without colon might fail fromisoformat in some versions
183+
# but should pass strptime("%Y-%m-%dT%H:%M:%S%z")
184+
"X-CloudScheduler-ScheduleTime": "2023-04-13T12:00:00-0700",
185+
}
186+
).get_environ()
187+
mock_request = Request(environ)
188+
example_func = Mock(__name__="example_func")
189+
decorated_func = scheduler_fn.on_schedule(schedule="* * * * *")(example_func)
190+
response = decorated_func(mock_request)
191+
192+
self.assertEqual(response.status_code, 200)
193+
194+
# Create expected datetime with fixed offset -07:00
195+
tz = datetime.strptime("-0700", "%z").tzinfo
196+
expected_dt = datetime(2023, 4, 13, 12, 0, 0, tzinfo=tz)
197+
198+
example_func.assert_called_once_with(
199+
scheduler_fn.ScheduledEvent(
200+
job_name="example-job",
201+
schedule_time=expected_dt,
202+
)
203+
)
204+
205+
def test_on_schedule_call_invalid_timestamp(self):
206+
"""
207+
Tests that invalid timestamps log an error and fallback to current time.
208+
"""
209+
with Flask(__name__).test_request_context("/"):
210+
environ = EnvironBuilder(
211+
headers={
212+
"X-CloudScheduler-JobName": "example-job",
213+
"X-CloudScheduler-ScheduleTime": "invalid-timestamp",
214+
}
215+
).get_environ()
216+
mock_request = Request(environ)
217+
example_func = Mock(__name__="example_func")
218+
219+
with patch("firebase_functions.scheduler_fn._logging") as mock_logging:
220+
decorated_func = scheduler_fn.on_schedule(schedule="* * * * *")(example_func)
221+
response = decorated_func(mock_request)
222+
223+
self.assertEqual(response.status_code, 200)
224+
mock_logging.exception.assert_called_once()
225+
226+
# Should have called with *some* time (current time), so we just check it's not None
227+
self.assertEqual(example_func.call_count, 1)
228+
called_event = example_func.call_args[0][0]
229+
self.assertEqual(called_event.job_name, "example-job")
230+
self.assertIsNotNone(called_event.schedule_time)
231+
self.assertIsNotNone(called_event.schedule_time.tzinfo)
232+
149233
def test_calls_init(self):
150234
hello = None
151235

0 commit comments

Comments
 (0)