@@ -1114,3 +1114,130 @@ async def mock_async_streaming_response():
11141114 assert props ["$ai_web_search_count" ] == 1
11151115 assert props ["$ai_input_tokens" ] == 30
11161116 assert props ["$ai_output_tokens" ] == 15
1117+
1118+
1119+ def test_empty_grounding_metadata_no_web_search (mock_client , mock_google_genai_client ):
1120+ """Test that empty grounding_metadata (all null fields) does not count as web search."""
1121+
1122+ # Create mock response with empty grounding metadata (all null fields)
1123+ mock_response = MagicMock ()
1124+
1125+ # Mock usage metadata
1126+ mock_usage = MagicMock ()
1127+ mock_usage .prompt_token_count = 10
1128+ mock_usage .candidates_token_count = 10
1129+ mock_usage .cached_content_token_count = 0
1130+ mock_usage .thoughts_token_count = 0
1131+ mock_response .usage_metadata = mock_usage
1132+
1133+ # Mock empty grounding metadata (all fields are None)
1134+ mock_grounding_metadata = MagicMock ()
1135+ mock_grounding_metadata .web_search_queries = None
1136+ mock_grounding_metadata .grounding_chunks = None
1137+ mock_grounding_metadata .grounding_supports = None
1138+ mock_grounding_metadata .retrieval_metadata = None
1139+ mock_grounding_metadata .retrieval_queries = None
1140+ mock_grounding_metadata .search_entry_point = None
1141+
1142+ # Mock text part
1143+ mock_text_part = MagicMock ()
1144+ mock_text_part .text = "Hey there! How can I help you today?"
1145+ type(mock_text_part ).text = mock_text_part .text
1146+
1147+ # Mock content with parts
1148+ mock_content = MagicMock ()
1149+ mock_content .parts = [mock_text_part ]
1150+
1151+ # Mock candidate with empty grounding metadata
1152+ mock_candidate = MagicMock ()
1153+ mock_candidate .content = mock_content
1154+ mock_candidate .grounding_metadata = mock_grounding_metadata
1155+ type(mock_candidate ).grounding_metadata = mock_candidate .grounding_metadata
1156+
1157+ mock_response .candidates = [mock_candidate ]
1158+ mock_response .text = "Hey there! How can I help you today?"
1159+
1160+ # Mock the generate_content method
1161+ mock_google_genai_client .models .generate_content .return_value = mock_response
1162+
1163+ client = Client (api_key = "test-key" , posthog_client = mock_client )
1164+
1165+ response = client .models .generate_content (
1166+ model = "gemini-2.5-flash" ,
1167+ contents = "Hello" ,
1168+ posthog_distinct_id = "test-id" ,
1169+ )
1170+
1171+ assert response == mock_response
1172+ assert mock_client .capture .call_count == 1
1173+
1174+ call_args = mock_client .capture .call_args [1 ]
1175+ props = call_args ["properties" ]
1176+
1177+ # Verify web search count is 0 (not present in properties when 0)
1178+ assert "$ai_web_search_count" not in props
1179+ assert props ["$ai_input_tokens" ] == 10
1180+ assert props ["$ai_output_tokens" ] == 10
1181+
1182+
1183+ def test_empty_array_grounding_metadata_no_web_search (
1184+ mock_client , mock_google_genai_client
1185+ ):
1186+ """Test that grounding_metadata with empty arrays does not count as web search."""
1187+
1188+ # Create mock response with grounding metadata having empty arrays
1189+ mock_response = MagicMock ()
1190+
1191+ # Mock usage metadata
1192+ mock_usage = MagicMock ()
1193+ mock_usage .prompt_token_count = 15
1194+ mock_usage .candidates_token_count = 12
1195+ mock_usage .cached_content_token_count = 0
1196+ mock_usage .thoughts_token_count = 0
1197+ mock_response .usage_metadata = mock_usage
1198+
1199+ # Mock grounding metadata with empty arrays
1200+ mock_grounding_metadata = MagicMock ()
1201+ mock_grounding_metadata .web_search_queries = []
1202+ mock_grounding_metadata .grounding_chunks = []
1203+ mock_grounding_metadata .grounding_supports = []
1204+
1205+ # Mock text part
1206+ mock_text_part = MagicMock ()
1207+ mock_text_part .text = "I can help with that."
1208+ type(mock_text_part ).text = mock_text_part .text
1209+
1210+ # Mock content with parts
1211+ mock_content = MagicMock ()
1212+ mock_content .parts = [mock_text_part ]
1213+
1214+ # Mock candidate with grounding metadata containing empty arrays
1215+ mock_candidate = MagicMock ()
1216+ mock_candidate .content = mock_content
1217+ mock_candidate .grounding_metadata = mock_grounding_metadata
1218+ type(mock_candidate ).grounding_metadata = mock_candidate .grounding_metadata
1219+
1220+ mock_response .candidates = [mock_candidate ]
1221+ mock_response .text = "I can help with that."
1222+
1223+ # Mock the generate_content method
1224+ mock_google_genai_client .models .generate_content .return_value = mock_response
1225+
1226+ client = Client (api_key = "test-key" , posthog_client = mock_client )
1227+
1228+ response = client .models .generate_content (
1229+ model = "gemini-2.5-flash" ,
1230+ contents = "What can you do?" ,
1231+ posthog_distinct_id = "test-id" ,
1232+ )
1233+
1234+ assert response == mock_response
1235+ assert mock_client .capture .call_count == 1
1236+
1237+ call_args = mock_client .capture .call_args [1 ]
1238+ props = call_args ["properties" ]
1239+
1240+ # Verify web search count is 0 (not present in properties when 0)
1241+ assert "$ai_web_search_count" not in props
1242+ assert props ["$ai_input_tokens" ] == 15
1243+ assert props ["$ai_output_tokens" ] == 12
0 commit comments