55from reflex .utils import telemetry
66
77
8- def _mock_event_defaults () -> dict :
9- return {
8+ @pytest .fixture
9+ def event_defaults (mocker : MockerFixture ) -> dict :
10+ """Patch ``get_event_defaults()`` with a fresh dict.
11+
12+ Returns:
13+ The dict that ``get_event_defaults()`` is patched to return, so tests
14+ can assert it isn't mutated by the code under test.
15+ """
16+ defaults = {
1017 "api_key" : "test_api_key" ,
1118 "properties" : {
1219 "distinct_id" : 12345 ,
@@ -23,11 +30,18 @@ def _mock_event_defaults() -> dict:
2330 "cpu_info" : {},
2431 },
2532 }
33+ mocker .patch ("reflex.utils.telemetry.get_event_defaults" , return_value = defaults )
34+ return defaults
2635
2736
28- def _patch_event_defaults (mocker : MockerFixture , value ):
29- """Replace the cached get_event_defaults() so it returns ``value``, bypassing the once_unless_none cache."""
30- mocker .patch ("reflex.utils.telemetry.get_event_defaults" , return_value = value )
37+ @pytest .fixture
38+ def httpx_post (mocker : MockerFixture ):
39+ """Mock ``httpx.post`` used by ``telemetry._send``.
40+
41+ Returns:
42+ The mock for ``httpx.post`` so tests can assert on the posted payload.
43+ """
44+ return mocker .patch ("httpx.post" )
3145
3246
3347def test_telemetry ():
@@ -84,24 +98,17 @@ def test_disable():
8498 ),
8599 ],
86100)
87- def test_send (mocker : MockerFixture , event , kwargs , expected_props ):
88- httpx_post_mock = mocker .patch ("httpx.post" )
89- _patch_event_defaults (mocker , _mock_event_defaults ())
90-
101+ def test_send (event_defaults , httpx_post , event , kwargs , expected_props ):
91102 telemetry ._send (event , telemetry_enabled = True , ** kwargs )
92- httpx_post_mock .assert_called_once ()
93- posted = httpx_post_mock .call_args .kwargs ["json" ]
103+ httpx_post .assert_called_once ()
104+ posted = httpx_post .call_args .kwargs ["json" ]
94105 assert posted ["event" ] == event
95106 for key , value in expected_props .items ():
96107 assert posted ["properties" ][key ] == value
97108
98109
99- def test_send_does_not_leak_kwargs_between_events (mocker : MockerFixture ):
110+ def test_send_does_not_leak_kwargs_between_events (event_defaults , httpx_post ):
100111 """Per-event kwargs must not leak into a subsequent event's payload."""
101- httpx_post_mock = mocker .patch ("httpx.post" )
102- defaults = _mock_event_defaults ()
103- _patch_event_defaults (mocker , defaults )
104-
105112 telemetry ._send ("export" , telemetry_enabled = True , status = "success" , duration = 1.0 )
106113 telemetry ._send (
107114 "export" ,
@@ -111,9 +118,9 @@ def test_send_does_not_leak_kwargs_between_events(mocker: MockerFixture):
111118 duration = 2.0 ,
112119 )
113120
114- assert httpx_post_mock .call_count == 2
115- first_props = httpx_post_mock .call_args_list [0 ].kwargs ["json" ]["properties" ]
116- second_props = httpx_post_mock .call_args_list [1 ].kwargs ["json" ]["properties" ]
121+ assert httpx_post .call_count == 2
122+ first_props = httpx_post .call_args_list [0 ].kwargs ["json" ]["properties" ]
123+ second_props = httpx_post .call_args_list [1 ].kwargs ["json" ]["properties" ]
117124
118125 assert first_props ["status" ] == "success"
119126 assert first_props ["duration" ] == pytest .approx (1.0 )
@@ -124,28 +131,22 @@ def test_send_does_not_leak_kwargs_between_events(mocker: MockerFixture):
124131 assert second_props ["duration" ] == pytest .approx (2.0 )
125132
126133 # The cached defaults must not have been polluted by either call.
127- assert "status" not in defaults ["properties" ]
128- assert "duration" not in defaults ["properties" ]
129- assert "detail" not in defaults ["properties" ]
134+ assert "status" not in event_defaults ["properties" ]
135+ assert "duration" not in event_defaults ["properties" ]
136+ assert "detail" not in event_defaults ["properties" ]
130137
131138
132- def test_send_drops_unknown_kwargs (mocker : MockerFixture ):
139+ def test_send_drops_unknown_kwargs (event_defaults , httpx_post ):
133140 """Unknown kwargs must not land in the posted payload."""
134- httpx_post_mock = mocker .patch ("httpx.post" )
135- _patch_event_defaults (mocker , _mock_event_defaults ())
136-
137141 telemetry ._send ("export" , telemetry_enabled = True , foo = "bar" , secret = "leak" )
138- httpx_post_mock .assert_called_once ()
139- props = httpx_post_mock .call_args .kwargs ["json" ]["properties" ]
142+ httpx_post .assert_called_once ()
143+ props = httpx_post .call_args .kwargs ["json" ]["properties" ]
140144 assert "foo" not in props
141145 assert "secret" not in props
142146
143147
144- def test_send_drops_none_kwargs (mocker : MockerFixture ):
148+ def test_send_drops_none_kwargs (event_defaults , httpx_post ):
145149 """None-valued kwargs for allowed keys are omitted from the posted payload."""
146- httpx_post_mock = mocker .patch ("httpx.post" )
147- _patch_event_defaults (mocker , _mock_event_defaults ())
148-
149150 telemetry ._send (
150151 "export" ,
151152 telemetry_enabled = True ,
@@ -156,19 +157,17 @@ def test_send_drops_none_kwargs(mocker: MockerFixture):
156157 build_duration = 0.05 ,
157158 zip_duration = None ,
158159 )
159- httpx_post_mock .assert_called_once ()
160- props = httpx_post_mock .call_args .kwargs ["json" ]["properties" ]
160+ httpx_post .assert_called_once ()
161+ props = httpx_post .call_args .kwargs ["json" ]["properties" ]
161162 assert props ["status" ] == "success"
162163 assert props ["build_duration" ] == pytest .approx (0.05 )
163164 assert "detail" not in props
164165 assert "compile_duration" not in props
165166 assert "zip_duration" not in props
166167
167168
168- def test_prepare_event_merges_properties (mocker : MockerFixture ):
169+ def test_prepare_event_merges_properties (event_defaults ):
169170 """``properties`` payloads are merged into the event properties."""
170- _patch_event_defaults (mocker , _mock_event_defaults ())
171-
172171 event = telemetry ._prepare_event (
173172 "compile" ,
174173 properties = {"pages_count" : 7 , "trigger" : "initial" },
@@ -183,29 +182,24 @@ def test_prepare_event_merges_properties(mocker: MockerFixture):
183182 assert props ["user_os" ] == "Test OS"
184183
185184
186- def test_prepare_event_does_not_mutate_cached_defaults (mocker : MockerFixture ):
185+ def test_prepare_event_does_not_mutate_cached_defaults (event_defaults ):
187186 """``_prepare_event`` must not mutate the @once_unless_none cached defaults."""
188- cached = _mock_event_defaults ()
189- _patch_event_defaults (mocker , cached )
190-
191- cached_props_snapshot = dict (cached ["properties" ])
187+ cached_props_snapshot = dict (event_defaults ["properties" ])
192188
193189 telemetry ._prepare_event ("init" , template = "my-template" )
194190 telemetry ._prepare_event (
195191 "compile" ,
196192 properties = {"pages_count" : 3 , "duration_ms" : 42 },
197193 )
198194
199- assert cached ["properties" ] == cached_props_snapshot
200- assert "template" not in cached ["properties" ]
201- assert "pages_count" not in cached ["properties" ]
202- assert "duration_ms" not in cached ["properties" ]
195+ assert event_defaults ["properties" ] == cached_props_snapshot
196+ assert "template" not in event_defaults ["properties" ]
197+ assert "pages_count" not in event_defaults ["properties" ]
198+ assert "duration_ms" not in event_defaults ["properties" ]
203199
204200
205- def test_prepare_event_properties_override_kwargs (mocker : MockerFixture ):
201+ def test_prepare_event_properties_override_kwargs (event_defaults ):
206202 """If both kwargs and properties supply the same key, properties wins."""
207- _patch_event_defaults (mocker , _mock_event_defaults ())
208-
209203 event = telemetry ._prepare_event (
210204 "init" ,
211205 template = "from-kwarg" ,
0 commit comments