@@ -497,6 +497,54 @@ public function test_execute_no_input() {
497497 $ this ->assertSame ( 42 , $ ability ->execute () );
498498 }
499499
500+ /**
501+ * Tests that an exception thrown by the execute callback is converted to a WP_Error
502+ * instead of being propagated as an uncaught throwable.
503+ *
504+ * @ticket 65058
505+ */
506+ public function test_execute_catches_callback_exception () {
507+ $ args = array_merge (
508+ self ::$ test_ability_properties ,
509+ array (
510+ 'execute_callback ' => static function (): int {
511+ throw new RuntimeException ( 'boom ' );
512+ },
513+ )
514+ );
515+
516+ $ ability = new WP_Ability ( self ::$ test_ability_name , $ args );
517+ $ result = $ ability ->execute ();
518+
519+ $ this ->assertWPError ( $ result , 'Ability::execute() should return WP_Error when the callback throws. ' );
520+ $ this ->assertSame ( 'ability_callback_exception ' , $ result ->get_error_code () );
521+ $ this ->assertStringContainsString ( 'boom ' , $ result ->get_error_message () );
522+ }
523+
524+ /**
525+ * Tests that an exception thrown by the permission callback is converted to a WP_Error
526+ * instead of being propagated as an uncaught throwable.
527+ *
528+ * @ticket 65058
529+ */
530+ public function test_check_permissions_catches_callback_exception () {
531+ $ args = array_merge (
532+ self ::$ test_ability_properties ,
533+ array (
534+ 'permission_callback ' => static function (): bool {
535+ throw new RuntimeException ( 'permission exploded ' );
536+ },
537+ )
538+ );
539+
540+ $ ability = new WP_Ability ( self ::$ test_ability_name , $ args );
541+ $ result = $ ability ->check_permissions ();
542+
543+ $ this ->assertWPError ( $ result , 'Ability::check_permissions() should return WP_Error when the callback throws. ' );
544+ $ this ->assertSame ( 'ability_callback_exception ' , $ result ->get_error_code () );
545+ $ this ->assertStringContainsString ( 'permission exploded ' , $ result ->get_error_message () );
546+ }
547+
500548 /**
501549 * Tests that before_execute_ability action is fired with correct parameters.
502550 *
0 commit comments