Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
2cfc0d5
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
187a00d
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
c07623c
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
e1853c1
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
5a2a664
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
eccc2a8
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
28cc757
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
77d3501
Tests: Rename and move data providers to match their tests.
peterwilsoncc Nov 13, 2026
9581664
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
dc396fa
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
ee83af6
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
a24219b
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
b6fcbcb
Tests: Rename and move data providers to match their tests.
peterwilsoncc Nov 13, 2026
106c820
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
1ae448b
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
9bd0888
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
c35b78c
Tests: Rename and move a data provider to match its test.
peterwilsoncc Nov 13, 2026
3cafdbe
Tests: Move a data provider below its test.
peterwilsoncc Nov 13, 2026
0b8e8d4
Tests: Rename and move data providers to match their tests.
peterwilsoncc Nov 13, 2026
70c9c38
Tests: Rename and move data providers to match their tests.
peterwilsoncc Nov 13, 2026
d6d603c
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
7528b4f
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
3ca17c1
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
ed253ab
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
3481a5a
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
14fd7e4
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
975ee79
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
4193e56
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
2a56865
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
d43f22c
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
fc80734
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
2fae979
Tests: Move data providers below their tests.
peterwilsoncc Nov 13, 2026
63d5815
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
7afe81d
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
a6fe9c0
Tests: Rename and move data providers to match their tests.
peterwilsoncc Nov 13, 2026
2873ba7
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
f37d35f
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
3e95969
Tests: Rename and move data providers to match their tests.
peterwilsoncc Nov 13, 2026
a853671
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
c595983
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
23efd47
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
db63a10
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
34bd799
Tests: Rename and move data providers to match their tests.
peterwilsoncc Nov 13, 2026
f88635f
Tests: Rename and move data providers to match their tests.
peterwilsoncc Nov 13, 2026
d633a59
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
b9be803
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
55f45ba
Tests: Move data providers below their tests.
peterwilsoncc Nov 13, 2026
12a9f0a
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
b2489e8
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
f23f9df
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
d939660
Tests: Rename and move data providers to match their tests.
peterwilsoncc Nov 13, 2026
2f8fc08
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
e89ee5f
Tests: Move a data provider below its test.
peterwilsoncc Nov 13, 2026
d6050ba
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
30723ff
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
b922bf4
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
de7042c
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
0c95838
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
64eb5e7
Tests: Move a data provider below its test.
peterwilsoncc Nov 13, 2026
40f2f52
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
d0502cc
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
f357f33
Tests: Rename and move a data provider to match its test.
peterwilsoncc Nov 13, 2026
dee72b2
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
9750f9f
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
5bf157e
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
3b7373a
Tests: Move a data provider below its test.
peterwilsoncc Nov 13, 2026
709b16c
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
bfb241d
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
7b051aa
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
3d6aed9
Tests: Rename and move data providers to match their tests.
peterwilsoncc Nov 13, 2026
6daf82b
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
8090d38
Tests: Rename data providers to match their tests.
peterwilsoncc Nov 13, 2026
face05a
Tests: Rename a data provider to match its test.
peterwilsoncc Nov 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions tests/phpunit/tests/abilities-api/wpAbilitiesRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ public function test_register_ability_nonexistent_category(): void {
*
* @ticket 65569
*
* @dataProvider data_invalid_category_types
* @dataProvider data_register_ability_rejects_invalid_category_type
*
* @covers WP_Abilities_Registry::register
*
Expand All @@ -255,7 +255,7 @@ public function test_register_ability_rejects_invalid_category_type( $category )
*
* @return array<string, array<mixed>> Test cases.
*/
public static function data_invalid_category_types(): array {
public static function data_register_ability_rejects_invalid_category_type(): array {
return array(
'null' => array( null ),
'boolean' => array( false ),
Expand Down
204 changes: 102 additions & 102 deletions tests/phpunit/tests/abilities-api/wpAbility.php
Original file line number Diff line number Diff line change
Expand Up @@ -2354,23 +2354,11 @@ public function test_prepare_input( array $schema, $input, $expected ): void {
$this->assertSame( $expected, $ability->prepare_input( $input ) );
}

/**
* Provides representative inputs for execution lifecycle integration.
*
* @return array
*/
public static function data_input_coercion(): array {
return array_intersect_key(
self::data_input_is_coerced(),
array_flip( array( 'integer number', 'stdClass object input', 'default', 'text-field format' ) )
);
}

/**
* Tests coercion after validation and consistent input throughout execution.
*
* @ticket 66383
* @dataProvider data_input_coercion
* @dataProvider data_execute_coerces_validated_input
*
* @param array $schema Input schema.
* @param mixed $input Original input.
Expand Down Expand Up @@ -2427,39 +2415,14 @@ static function ( $name, $value ) use ( &$seen ) {
}

/**
* Provides top-level and nested collisions introduced by sanitization.
* Provides representative inputs for execution lifecycle integration.
*
* @return array
*/
public static function data_input_sanitization_errors(): array {
$unique = array(
'type' => 'array',
'items' => array( 'type' => 'integer' ),
'uniqueItems' => true,
);
$object = array(
'type' => 'object',
'properties' => array(
'flag' => array( 'type' => 'boolean' ),
'ids' => $unique,
),
);
$input = array(
'flag' => 'false',
'ids' => '1,01',
);

return array(
'top-level array' => array( $unique, array( '1', '01' ), 'input' ),
'nested object' => array( $object, $input, 'input[ids]' ),
'object in list' => array(
array(
'type' => 'array',
'items' => $object,
),
array( $input ),
'input[0][ids]',
),
public static function data_execute_coerces_validated_input(): array {
return array_intersect_key(
self::data_input_is_coerced(),
array_flip( array( 'integer number', 'stdClass object input', 'default', 'text-field format' ) )
);
}

Expand Down Expand Up @@ -2496,6 +2459,43 @@ public function test_input_sanitization_errors( array $schema, $input, string $p
$this->assertEquals( $error, $ability->execute( $input ), 'Execution should propagate the sanitization error.' );
}

/**
* Provides top-level and nested collisions introduced by sanitization.
*
* @return array
*/
public static function data_input_sanitization_errors(): array {
$unique = array(
'type' => 'array',
'items' => array( 'type' => 'integer' ),
'uniqueItems' => true,
);
$object = array(
'type' => 'object',
'properties' => array(
'flag' => array( 'type' => 'boolean' ),
'ids' => $unique,
),
);
$input = array(
'flag' => 'false',
'ids' => '1,01',
);

return array(
'top-level array' => array( $unique, array( '1', '01' ), 'input' ),
'nested object' => array( $object, $input, 'input[ids]' ),
'object in list' => array(
array(
'type' => 'array',
'items' => $object,
),
array( $input ),
'input[0][ids]',
),
);
}

/**
* Tests that sanitization cannot rescue invalid input or bypass validation filters.
*
Expand Down Expand Up @@ -2575,18 +2575,6 @@ private function create_custom_class_ability( array $args ): WP_Ability {
return new class( self::$test_ability_name, $args ) extends WP_Ability {};
}

/**
* Data provider for required capabilities that default to an empty array.
*
* @return array<string, array{0: array<string, mixed>}>
*/
public static function data_required_capabilities_default_to_empty_array(): array {
return array(
'not set' => array( array() ),
'null' => array( array( 'required_capabilities' => null ) ),
);
}

/**
* Tests that required capabilities default to an empty array.
*
Expand All @@ -2605,6 +2593,18 @@ public function test_required_capabilities_default_to_empty_array( array $overri
$this->assertSame( array(), $ability->get_required_capabilities() );
}

/**
* Data provider for required capabilities that default to an empty array.
*
* @return array<string, array{0: array<string, mixed>}>
*/
public static function data_required_capabilities_default_to_empty_array(): array {
return array(
'not set' => array( array() ),
'null' => array( array( 'required_capabilities' => null ) ),
);
}

/**
* Tests that an ability can declare required capabilities without a permission callback.
*
Expand Down Expand Up @@ -2653,33 +2653,14 @@ public function test_invalid_permission_callback_with_required_capabilities_thro
new WP_Ability( self::$test_ability_name, $args );
}

/**
* Data provider for invalid required capabilities.
*
* @return array<string, array{0: mixed}>
*/
public static function data_invalid_required_capabilities(): array {
return array(
'string' => array( 'manage_options' ),
'empty string' => array( array( '' ) ),
'whitespace only' => array( array( " \t" ) ),
'non-string' => array( array( 'read', 1 ) ),
'associative' => array( array( 'cap' => 'manage_options' ) ),
'non-sequential' => array( array( 1 => 'manage_options' ) ),
'nested array' => array( array( array( 'manage_options' ) ) ),
'boolean' => array( true ),
'null in the list' => array( array( null ) ),
);
}

/**
* Tests that invalid required capabilities throw an exception.
*
* @ticket 66325
*
* @covers WP_Ability::prepare_properties
*
* @dataProvider data_invalid_required_capabilities
* @dataProvider data_invalid_required_capabilities_throw_exception
*
* @param mixed $capabilities The invalid required capabilities.
*/
Expand All @@ -2694,15 +2675,21 @@ public function test_invalid_required_capabilities_throw_exception( $capabilitie
}

/**
* Data provider for permission checks based on required capabilities.
* Data provider for invalid required capabilities.
*
* @return array<string, array{0: string, 1: bool}>
* @return array<string, array{0: mixed}>
*/
public static function data_check_permissions_with_required_capabilities(): array {
public static function data_invalid_required_capabilities_throw_exception(): array {
return array(
'user has all capabilities' => array( 'administrator', true ),
'user misses one capability' => array( 'editor', false ),
'user misses all capabilities' => array( 'subscriber', false ),
'string' => array( 'manage_options' ),
'empty string' => array( array( '' ) ),
'whitespace only' => array( array( " \t" ) ),
'non-string' => array( array( 'read', 1 ) ),
'associative' => array( array( 'cap' => 'manage_options' ) ),
'non-sequential' => array( array( 1 => 'manage_options' ) ),
'nested array' => array( array( array( 'manage_options' ) ) ),
'boolean' => array( true ),
'null in the list' => array( array( null ) ),
);
}

Expand All @@ -2729,6 +2716,19 @@ public function test_check_permissions_with_required_capabilities( string $role,
$this->assertSame( $expected, $ability->check_permissions() );
}

/**
* Data provider for permission checks based on required capabilities.
*
* @return array<string, array{0: string, 1: bool}>
*/
public static function data_check_permissions_with_required_capabilities(): array {
return array(
'user has all capabilities' => array( 'administrator', true ),
'user misses one capability' => array( 'editor', false ),
'user misses all capabilities' => array( 'subscriber', false ),
);
}

/**
* Tests that the permission callback doesn't run when a required capability is missing.
*
Expand Down Expand Up @@ -2807,6 +2807,27 @@ public function test_permission_result_filter_can_grant_missing_required_capabil
$this->assertSame( 0, $result, 'The filter should be able to grant a missing required capability.' );
}

/**
* Tests that check_permissions() returns an error when a custom class has no valid
* permission callback, even if the user has all required capabilities.
*
* @ticket 66325
*
* @covers WP_Ability::check_permissions
*
* @dataProvider data_check_permissions_custom_class_without_valid_permission_check
*
* @param array<string, mixed> $overrides The properties to merge into the test ability properties.
*/
public function test_check_permissions_custom_class_without_valid_permission_check( array $overrides ) {
wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );

$result = $this->create_custom_class_ability( array_merge( self::$test_ability_properties, $overrides ) )->check_permissions();

$this->assertWPError( $result );
$this->assertSame( 'ability_invalid_permission_callback', $result->get_error_code() );
}

/**
* Data provider for custom class abilities without a valid permission check.
*
Expand All @@ -2829,27 +2850,6 @@ public static function data_check_permissions_custom_class_without_valid_permiss
);
}

/**
* Tests that check_permissions() returns an error when a custom class has no valid
* permission callback, even if the user has all required capabilities.
*
* @ticket 66325
*
* @covers WP_Ability::check_permissions
*
* @dataProvider data_check_permissions_custom_class_without_valid_permission_check
*
* @param array<string, mixed> $overrides The properties to merge into the test ability properties.
*/
public function test_check_permissions_custom_class_without_valid_permission_check( array $overrides ) {
wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );

$result = $this->create_custom_class_ability( array_merge( self::$test_ability_properties, $overrides ) )->check_permissions();

$this->assertWPError( $result );
$this->assertSame( 'ability_invalid_permission_callback', $result->get_error_code() );
}

/**
* Tests that check_permissions() works for a custom class with only required capabilities.
*
Expand Down
42 changes: 21 additions & 21 deletions tests/phpunit/tests/abilities-api/wpGetAbilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,27 @@ private function register_abilities_with_required_capabilities(): void {
);
}

/**
* Tests that the has_required_capabilities filter leaves out abilities whose declared
* capabilities the current user lacks. Abilities without required capabilities stay.
*
* @ticket 66325
*
* @dataProvider data_filter_by_has_required_capabilities
*
* @param string $role The role of the current user. Empty for a logged-out user.
* @param array<string, mixed> $args The arguments passed to wp_get_abilities().
* @param string[] $expected The expected ability names.
*/
public function test_filter_by_has_required_capabilities( string $role, array $args, array $expected ): void {
$this->register_abilities_with_required_capabilities();
wp_set_current_user( '' === $role ? 0 : self::factory()->user->create( array( 'role' => $role ) ) );

$result = wp_get_abilities( array_merge( array( 'namespace' => 'test' ), $args ) );

$this->assertSameSets( $expected, array_keys( $result ) );
}

/**
* Data provider for filtering by the current user's required capabilities.
*
Expand All @@ -857,27 +878,6 @@ public static function data_filter_by_has_required_capabilities(): array {
);
}

/**
* Tests that the has_required_capabilities filter leaves out abilities whose declared
* capabilities the current user lacks. Abilities without required capabilities stay.
*
* @ticket 66325
*
* @dataProvider data_filter_by_has_required_capabilities
*
* @param string $role The role of the current user. Empty for a logged-out user.
* @param array<string, mixed> $args The arguments passed to wp_get_abilities().
* @param string[] $expected The expected ability names.
*/
public function test_filter_by_has_required_capabilities( string $role, array $args, array $expected ): void {
$this->register_abilities_with_required_capabilities();
wp_set_current_user( '' === $role ? 0 : self::factory()->user->create( array( 'role' => $role ) ) );

$result = wp_get_abilities( array_merge( array( 'namespace' => 'test' ), $args ) );

$this->assertSameSets( $expected, array_keys( $result ) );
}

/**
* Tests that the has_required_capabilities filter doesn't call permission callbacks.
*
Expand Down
4 changes: 2 additions & 2 deletions tests/phpunit/tests/abilities-api/wpRegisterCoreAbilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ public static function data_core_ability_field_lists(): array {
*
* @ticket 66493
*
* @dataProvider data_users_who_cannot_manage_options
* @dataProvider data_core_get_site_info_denies_users_who_cannot_manage_options
*
* @param string $role Role of the current user, or an empty string for a logged-out visitor.
*/
Expand All @@ -555,7 +555,7 @@ public function test_core_get_site_info_denies_users_who_cannot_manage_options(
*
* @return array[]
*/
public static function data_users_who_cannot_manage_options(): array {
public static function data_core_get_site_info_denies_users_who_cannot_manage_options(): array {
return array(
'subscriber' => array( 'subscriber' ),
'logged-out user' => array( '' ),
Expand Down
Loading