@@ -1189,3 +1189,238 @@ def test_wait_for_pane_content_with_line_range(wait_pane: Pane) -> None:
1189
1189
assert result .success
1190
1190
assert result .matched_content == "Line 2"
1191
1191
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