@@ -1189,3 +1189,238 @@ def test_wait_for_pane_content_with_line_range(wait_pane: Pane) -> None:
11891189 assert result .success
11901190 assert result .matched_content == "Line 2"
11911191 assert result .match_line is not None
1192+
1193+
1194+ def test_wait_for_all_content_empty_patterns (wait_pane : Pane ) -> None :
1195+ """Test wait_for_all_content with empty patterns list raises ValueError."""
1196+ error_msg = "At least one content pattern must be provided"
1197+ with pytest .raises (ValueError , match = error_msg ):
1198+ wait_for_all_content (
1199+ wait_pane ,
1200+ [], # Empty patterns list
1201+ ContentMatchType .CONTAINS ,
1202+ )
1203+
1204+
1205+ def test_wait_for_any_content_empty_patterns (wait_pane : Pane ) -> None :
1206+ """Test wait_for_any_content with empty patterns list raises ValueError."""
1207+ error_msg = "At least one content pattern must be provided"
1208+ with pytest .raises (ValueError , match = error_msg ):
1209+ wait_for_any_content (
1210+ wait_pane ,
1211+ [], # Empty patterns list
1212+ ContentMatchType .CONTAINS ,
1213+ )
1214+
1215+
1216+ def test_wait_for_all_content_exception_handling (wait_pane : Pane ) -> None :
1217+ """Test exception handling in wait_for_all_content."""
1218+ # Test with raises=False and a pattern that won't be found (timeout case)
1219+ result = wait_for_all_content (
1220+ wait_pane ,
1221+ ["pattern that will never be found" ],
1222+ ContentMatchType .CONTAINS ,
1223+ timeout = 0.1 , # Very short timeout to ensure it fails
1224+ interval = 0.01 ,
1225+ raises = False ,
1226+ )
1227+
1228+ assert not result .success
1229+ assert result .error is not None
1230+ assert "timed out" in result .error .lower ()
1231+
1232+ # Test with raises=True (default) - should raise WaitTimeout
1233+ with pytest .raises (WaitTimeout ):
1234+ wait_for_all_content (
1235+ wait_pane ,
1236+ ["pattern that will never be found" ],
1237+ ContentMatchType .CONTAINS ,
1238+ timeout = 0.1 , # Very short timeout to ensure it fails
1239+ )
1240+
1241+
1242+ def test_wait_for_any_content_exception_handling (wait_pane : Pane ) -> None :
1243+ """Test exception handling in wait_for_any_content."""
1244+ # Test with raises=False and a pattern that won't be found (timeout case)
1245+ result = wait_for_any_content (
1246+ wait_pane ,
1247+ ["pattern that will never be found" ],
1248+ ContentMatchType .CONTAINS ,
1249+ timeout = 0.1 , # Very short timeout to ensure it fails
1250+ interval = 0.01 ,
1251+ raises = False ,
1252+ )
1253+
1254+ assert not result .success
1255+ assert result .error is not None
1256+ assert "timed out" in result .error .lower ()
1257+
1258+ # Test with raises=True (default) - should raise WaitTimeout
1259+ with pytest .raises (WaitTimeout ):
1260+ wait_for_any_content (
1261+ wait_pane ,
1262+ ["pattern that will never be found" ],
1263+ ContentMatchType .CONTAINS ,
1264+ timeout = 0.1 , # Very short timeout to ensure it fails
1265+ )
1266+
1267+
1268+ def test_wait_for_pane_content_exception_handling (wait_pane : Pane ) -> None :
1269+ """Test exception handling in wait_for_pane_content."""
1270+ # Test with raises=False and a pattern that won't be found (timeout case)
1271+ result = wait_for_pane_content (
1272+ wait_pane ,
1273+ "pattern that will never be found" ,
1274+ ContentMatchType .CONTAINS ,
1275+ timeout = 0.1 , # Very short timeout to ensure it fails
1276+ interval = 0.01 ,
1277+ raises = False ,
1278+ )
1279+
1280+ assert not result .success
1281+ assert result .error is not None
1282+ assert "timed out" in result .error .lower ()
1283+
1284+ # Test with raises=True (default) - should raise WaitTimeout
1285+ with pytest .raises (WaitTimeout ):
1286+ wait_for_pane_content (
1287+ wait_pane ,
1288+ "pattern that will never be found" ,
1289+ ContentMatchType .CONTAINS ,
1290+ timeout = 0.1 , # Very short timeout to ensure it fails
1291+ )
1292+
1293+
1294+ def test_wait_for_pane_content_exact_match_type_error (wait_pane : Pane ) -> None :
1295+ """Test TypeError is raised with non-string pattern and EXACT match type."""
1296+ # Try to pass a non-string value with EXACT match type
1297+ with pytest .raises (TypeError , match = "must be a string when match_type is EXACT" ):
1298+ wait_for_pane_content (
1299+ wait_pane ,
1300+ 123 , # type: ignore # This should be a string for EXACT type
1301+ ContentMatchType .EXACT ,
1302+ timeout = 0.1 ,
1303+ )
1304+
1305+
1306+ def test_wait_for_pane_content_contains_match_type_error (wait_pane : Pane ) -> None :
1307+ """Test TypeError is raised with non-string pattern and CONTAINS match type."""
1308+ # Try to pass a non-string value with CONTAINS match type
1309+ with pytest .raises (TypeError , match = "must be a string when match_type is CONTAINS" ):
1310+ wait_for_pane_content (
1311+ wait_pane ,
1312+ 123 , # type: ignore # This should be a string for CONTAINS type
1313+ ContentMatchType .CONTAINS ,
1314+ timeout = 0.1 ,
1315+ )
1316+
1317+
1318+ def test_predicate_match_type_error (wait_pane : Pane ) -> None :
1319+ """Test that PREDICATE match type raises TypeError with non-callable pattern."""
1320+ # Try to pass a non-callable value as predicate
1321+ error_msg = "must be callable when match_type is PREDICATE"
1322+ with pytest .raises (TypeError , match = error_msg ):
1323+ wait_for_pane_content (
1324+ wait_pane ,
1325+ "not a callable" , # This should be a function for PREDICATE type
1326+ ContentMatchType .PREDICATE ,
1327+ timeout = 0.1 ,
1328+ )
1329+
1330+
1331+ def test_wait_for_pane_content_invalid_match_type (wait_pane : Pane ) -> None :
1332+ """Test ValueError is raised when an invalid match type is used."""
1333+ # The check for valid match types happens inside the check_content function
1334+ # which is only called during the retry loop
1335+ # Create our own invalid match type enum value (intentionally a string)
1336+ invalid_match_type = "INVALID_TYPE"
1337+
1338+ # Pass an invalid match type directly to the function
1339+ with pytest .raises (ValueError , match = "Unsupported match type" ):
1340+ # Create a custom function that will check the match type validation
1341+ def test_invalid_match_type () -> bool :
1342+ """Test function to check invalid match type handling."""
1343+ # This comparison is intentional to trigger ValueError
1344+ valid_match_types = [
1345+ ContentMatchType .PREDICATE ,
1346+ ContentMatchType .EXACT ,
1347+ ContentMatchType .CONTAINS ,
1348+ ContentMatchType .REGEX ,
1349+ ]
1350+ if invalid_match_type not in valid_match_types : # type: ignore
1351+ error_message = f"Unsupported match type: { invalid_match_type } "
1352+ raise ValueError (error_message )
1353+ return False
1354+
1355+ from libtmux .test .retry_extended import retry_until_extended
1356+
1357+ # Call retry_until_extended directly with our test function
1358+ retry_until_extended (
1359+ test_invalid_match_type ,
1360+ seconds = 0.1 ,
1361+ interval = 0.01 ,
1362+ raises = True ,
1363+ )
1364+
1365+
1366+ def test_pane_content_waiter_wait_for_exact_text_with_line_range (
1367+ wait_pane : Pane ,
1368+ ) -> None :
1369+ """Test PaneContentWaiter.wait_for_exact_text with line range parameters."""
1370+ # Set up pane with content
1371+ wait_pane .send_keys ("Line 1" , enter = True )
1372+ wait_pane .send_keys ("Line 2" , enter = True )
1373+ wait_pane .send_keys ("Line 3" , enter = True )
1374+
1375+ # Wait a moment for the content to appear
1376+ time .sleep (0.1 )
1377+
1378+ # Create a PaneContentWaiter with line range
1379+ waiter = (
1380+ PaneContentWaiter (wait_pane )
1381+ .with_timeout (1.0 )
1382+ .with_line_range (1 , 2 ) # Start from the second line, end at the third line
1383+ )
1384+
1385+ # Test waiting for exact text match using the line range
1386+ # The captured content should only include lines 1-2
1387+ lines = wait_pane .capture_pane ()
1388+ test_content = "\n " .join (lines [1 :3 ])
1389+
1390+ # Now wait for this exact content
1391+ result = waiter .wait_for_exact_text (test_content )
1392+
1393+ # Verify the result
1394+ assert result .success
1395+ assert result .matched_content == test_content
1396+
1397+ # Modify the range and show it fails to match
1398+ waiter = PaneContentWaiter (wait_pane ).with_timeout (0.1 ).with_line_range (0 , 3 )
1399+
1400+ # With a different range, the exact match should fail
1401+ with pytest .raises (WaitTimeout ):
1402+ waiter .wait_for_exact_text (test_content )
1403+
1404+
1405+ def test_wait_for_any_content_mismatched_match_types (wait_pane : Pane ) -> None :
1406+ """Test wait_for_any_content with mismatched match_types length."""
1407+ with pytest .raises (ValueError , match = "match_types list .* doesn't match patterns" ):
1408+ wait_for_any_content (
1409+ wait_pane ,
1410+ ["pattern1" , "pattern2" , "pattern3" ],
1411+ # Only 2 match types for 3 patterns
1412+ [ContentMatchType .CONTAINS , ContentMatchType .EXACT ],
1413+ timeout = 0.1 ,
1414+ )
1415+
1416+
1417+ def test_wait_for_all_content_mismatched_match_types (wait_pane : Pane ) -> None :
1418+ """Test wait_for_all_content with mismatched match_types length."""
1419+ with pytest .raises (ValueError , match = "match_types list .* doesn't match patterns" ):
1420+ wait_for_all_content (
1421+ wait_pane ,
1422+ ["pattern1" , "pattern2" , "pattern3" ],
1423+ # Only 2 match types for 3 patterns
1424+ [ContentMatchType .CONTAINS , ContentMatchType .EXACT ],
1425+ timeout = 0.1 ,
1426+ )
0 commit comments