Skip to content
Open
Changes from all commits
Commits
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
122 changes: 94 additions & 28 deletions tests/phpunit/tests/abilities-api/wpAbility.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ public function set_up(): void {
'output_schema' => array(
'type' => 'number',
'description' => 'The result of performing a math operation.',
'required' => true,
),
'execute_callback' => static function (): int {
return 0;
Expand Down Expand Up @@ -274,7 +273,6 @@ public function data_execute_input() {
array(
'type' => array( 'null', 'integer' ),
'description' => 'The null or integer to convert to integer.',
'required' => true,
),
static function ( $input ): int {
return null === $input ? 0 : (int) $input;
Expand All @@ -286,7 +284,6 @@ static function ( $input ): int {
array(
'type' => 'boolean',
'description' => 'The boolean to convert to integer.',
'required' => true,
),
static function ( bool $input ): int {
return $input ? 1 : 0;
Expand All @@ -298,7 +295,6 @@ static function ( bool $input ): int {
array(
'type' => 'integer',
'description' => 'The integer to add 5 to.',
'required' => true,
),
static function ( int $input ): int {
return 5 + $input;
Expand All @@ -310,7 +306,6 @@ static function ( int $input ): int {
array(
'type' => 'number',
'description' => 'The floating number to round.',
'required' => true,
),
static function ( float $input ): int {
return (int) round( $input );
Expand All @@ -322,7 +317,6 @@ static function ( float $input ): int {
array(
'type' => 'string',
'description' => 'The string to measure the length of.',
'required' => true,
),
static function ( string $input ): int {
return strlen( $input );
Expand Down Expand Up @@ -361,7 +355,6 @@ static function ( array $input ): int {
array(
'type' => 'array',
'description' => 'An array containing two numbers to add.',
'required' => true,
'minItems' => 2,
'maxItems' => 2,
'items' => array(
Expand Down Expand Up @@ -403,6 +396,100 @@ public function test_execute_input( $input_schema, $execute_callback, $input, $r
$this->assertSame( $result, $ability->execute( $input ) );
}

/**
* Data provider for top-level `required` validation behavior.
*
* Each schema variant is paired with both a valid and an invalid input so the
* inert behavior of a top-level `required` boolean — and the meaningful
* behavior of a draft-04 `required` array on an object — are sealed.
*
* @return array<string, array{0: array, 1: mixed, 2: bool}> Data sets.
*/
public function data_validate_input_top_level_required() {
$required_true = array(
'type' => 'string',
'required' => true,
);
$required_false = array(
'type' => 'string',
'required' => false,
);
$required_unset = array(
'type' => 'string',
);
$object_required = array(
'type' => 'object',
'properties' => array(
'a' => array( 'type' => 'integer' ),
'b' => array( 'type' => 'integer' ),
),
'required' => array( 'a', 'b' ),
);

return array(
// A top-level `required: true` is inert: only `type` is enforced.
'required true: valid input' => array( $required_true, 'hello', true ),
'required true: invalid input' => array( $required_true, 123, false ),

// A top-level `required: false` is equally inert and does not permit null.
'required false: valid input' => array( $required_false, 'hello', true ),
'required false: invalid input' => array( $required_false, 123, false ),
'required false: null still invalid' => array( $required_false, null, false ),

// Omitting `required` behaves identically to setting it.
'required unset: valid input' => array( $required_unset, 'hello', true ),
'required unset: invalid input' => array( $required_unset, 123, false ),

// A draft-04 `required` array on an object type IS honored.
'object required array: valid input' => array(
$object_required,
array(
'a' => 1,
'b' => 2,
),
true,
),
'object required array: invalid input' => array( $object_required, array( 'a' => 1 ), false ),
);
}

/**
* Tests how a top-level `required` keyword is handled during input validation.
*
* For a non-object root type, a top-level `required` flag is inert: validation
* gates solely on `type`, so the outcome is identical whether `required` is
* `true`, `false`, or omitted — and `required: false` notably does not make a
* `null` value acceptable. For an object root type, a draft-04 `required` array
* of property names is honored and enforces the presence of those properties.
*
* @ticket 64955
*
* @covers WP_Ability::validate_input
*
* @dataProvider data_validate_input_top_level_required
*
* @param array $input_schema The input schema under test.
* @param mixed $input The input value to validate.
* @param bool $is_valid Whether the input is expected to pass validation.
*/
public function test_validate_input_top_level_required( $input_schema, $input, $is_valid ) {
$ability = new WP_Ability(
self::$test_ability_name,
array_merge(
self::$test_ability_properties,
array( 'input_schema' => $input_schema )
)
);

$result = $ability->validate_input( $input );

if ( $is_valid ) {
$this->assertTrue( $result, 'Expected the input to pass validation.' );
} else {
$this->assertWPError( $result, 'Expected the input to fail validation.' );
}
}

/**
* A static method to be used as a callback in tests.
*
Expand Down Expand Up @@ -466,7 +553,6 @@ public function test_execute_with_different_callbacks( $execute_callback ) {
'input_schema' => array(
'type' => 'string',
'description' => 'Test input string.',
'required' => true,
),
'execute_callback' => $execute_callback,
)
Expand Down Expand Up @@ -561,7 +647,6 @@ public function test_before_execute_ability_action() {
'input_schema' => array(
'type' => 'integer',
'description' => 'Test input parameter.',
'required' => true,
),
'execute_callback' => static function ( int $input ): int {
return $input * 2;
Expand Down Expand Up @@ -645,7 +730,6 @@ public function test_after_execute_ability_action() {
'input_schema' => array(
'type' => 'integer',
'description' => 'Test input parameter.',
'required' => true,
),
'execute_callback' => static function ( int $input ): int {
return $input * 3;
Expand Down Expand Up @@ -813,7 +897,6 @@ public function test_after_action_not_fired_on_output_validation_error() {
'output_schema' => array(
'type' => 'string',
'description' => 'Expected string output.',
'required' => true,
),
'execute_callback' => static function (): int {
return 42;
Expand Down Expand Up @@ -856,12 +939,10 @@ public function test_normalize_input_filter_can_transform_input() {
'input_schema' => array(
'type' => 'string',
'description' => 'Test input string.',
'required' => true,
),
'output_schema' => array(
'type' => 'integer',
'description' => 'Result integer.',
'required' => true,
),
'execute_callback' => static function ( string $input ): int {
return strlen( $input );
Expand Down Expand Up @@ -898,7 +979,6 @@ public function test_normalize_input_filter_wp_error_halts_execution() {
'input_schema' => array(
'type' => 'string',
'description' => 'Test input string.',
'required' => true,
),
'execute_callback' => static function ( string $input ) {
return strlen( $input );
Expand Down Expand Up @@ -934,12 +1014,10 @@ public function test_permission_result_filter_can_grant_permission() {
'input_schema' => array(
'type' => 'integer',
'description' => 'Test input integer.',
'required' => true,
),
'output_schema' => array(
'type' => 'integer',
'description' => 'Result integer.',
'required' => true,
),
'execute_callback' => static function ( int $input ): int {
return $input;
Expand Down Expand Up @@ -1105,7 +1183,6 @@ public function test_pre_execute_ability_filter_short_circuits_pipeline() {
'input_schema' => array(
'type' => 'integer',
'description' => 'Test input integer.',
'required' => true,
),
'execute_callback' => static function (): int {
return 1;
Expand Down Expand Up @@ -1272,7 +1349,6 @@ public function test_execute_result_filter_can_transform_result() {
'input_schema' => array(
'type' => 'integer',
'description' => 'Test input integer.',
'required' => true,
),
'execute_callback' => static function ( int $input ): int {
return $input * 2;
Expand Down Expand Up @@ -1416,7 +1492,6 @@ public function test_validate_input_filter_receives_all_parameters() {
'input_schema' => array(
'type' => 'string',
'description' => 'Test input string.',
'required' => true,
),
'execute_callback' => static function ( string $input ): int {
return strlen( $input );
Expand Down Expand Up @@ -1454,12 +1529,10 @@ public function test_validate_input_filter_overrides_validation_failure() {
'input_schema' => array(
'type' => 'integer',
'description' => 'Test input integer.',
'required' => true,
),
'output_schema' => array(
'type' => 'integer',
'description' => 'Result integer.',
'required' => true,
),
'execute_callback' => static function () {
return 99;
Expand Down Expand Up @@ -1496,7 +1569,6 @@ public function test_validate_input_filter_receives_error_on_invalid_input() {
'input_schema' => array(
'type' => 'integer',
'description' => 'Test input integer.',
'required' => true,
),
'execute_callback' => static function ( int $input ): int {
return $input * 2;
Expand Down Expand Up @@ -1534,7 +1606,6 @@ public function test_validate_input_filter_replaces_error_with_custom() {
'input_schema' => array(
'type' => 'integer',
'description' => 'Test input integer.',
'required' => true,
),
'execute_callback' => static function ( int $input ): int {
return $input * 2;
Expand Down Expand Up @@ -1572,7 +1643,6 @@ public function test_validate_output_filter_receives_all_parameters() {
'output_schema' => array(
'type' => 'integer',
'description' => 'The result integer.',
'required' => true,
),
'execute_callback' => static function (): int {
return 42;
Expand Down Expand Up @@ -1610,7 +1680,6 @@ public function test_validate_output_filter_overrides_validation_failure() {
'output_schema' => array(
'type' => 'string',
'description' => 'The result string.',
'required' => true,
),
'execute_callback' => static function (): int {
return 42;
Expand Down Expand Up @@ -1647,7 +1716,6 @@ public function test_validate_output_filter_receives_error_on_invalid_output() {
'output_schema' => array(
'type' => 'string',
'description' => 'The result string.',
'required' => true,
),
'execute_callback' => static function (): int {
return 42;
Expand Down Expand Up @@ -1685,7 +1753,6 @@ public function test_validate_output_filter_replaces_error_with_custom() {
'output_schema' => array(
'type' => 'string',
'description' => 'The result string.',
'required' => true,
),
'execute_callback' => static function (): int {
return 42;
Expand Down Expand Up @@ -1805,7 +1872,6 @@ public function test_ability_invoked_action_fires_on_validation_failure() {
'input_schema' => array(
'type' => 'integer',
'description' => 'Int input.',
'required' => true,
),
'execute_callback' => static function ( int $input ): int {
return $input;
Expand Down
Loading