Skip to content

Commit

Permalink
Add andReturnBoolean and andReturn with callable support (#590)
Browse files Browse the repository at this point in the history
* Allow callable and boolean return types for action/filter assertions

* CHANGELOG
  • Loading branch information
srtfisher authored Sep 27, 2024
1 parent 9d15e93 commit 0d5572c
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 26 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added dynamic creation of post type/taxonomy factories.
- Added `Reset_Server` trait to reset the server between tests.
- Add `with_https()` to control if the request being tested is over HTTPS.
- Add `andReturnBoolean()` and `andReturn( fn ( $value ) => ... )` support to
action/filter expectations
- Add cached HTTP response support using the `cache()` method.

### Changed
Expand Down
60 changes: 34 additions & 26 deletions src/mantle/testing/expectation/class-expectation.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,6 @@
* Expectation for an action to be added/applied.
*/
class Expectation {
/**
* Action to expect.
*
* @var string
*/
protected $action;

/**
* Hook to compare.
*
* @var string
*/
protected $hook;

/**
* Arguments for the hook.
*
Expand All @@ -39,10 +25,8 @@ class Expectation {

/**
* Number of times for the hook to execute.
*
* @var int|null
*/
protected $times;
protected int|null $times = null;

/**
* Return value comparison callback.
Expand Down Expand Up @@ -72,10 +56,7 @@ class Expectation {
* @param string $hook Hook to listen to.
* @param mixed $args Arguments for the hook.
*/
public function __construct( string $action, string $hook, $args = null ) {
$this->action = $action;
$this->hook = $hook;

public function __construct( protected readonly string $action, protected readonly string $hook, $args = null ) {
if ( ! empty( $args ) ) {
$this->args = $args;
}
Expand All @@ -92,7 +73,7 @@ protected function setup_applied_hooks() {
add_action( // @phpstan-ignore-line Action callback
$this->hook,
[ $this, 'record_start' ],
-1,
PHP_INT_MIN,
99
);

Expand All @@ -112,6 +93,7 @@ protected function setup_applied_hooks() {
*/
public function record_start( ...$args ) {
$this->record_start[] = $args;

return array_shift( $args );
}

Expand All @@ -123,6 +105,7 @@ public function record_start( ...$args ) {
*/
public function record_stop( ...$args ) {
$this->record_stop[] = $args;

return array_shift( $args );
}

Expand Down Expand Up @@ -179,7 +162,7 @@ public function validate(): void {
}

// Remove the actions for the hook.
remove_action( $this->hook, [ $this, 'record_start' ], -1 );
remove_action( $this->hook, [ $this, 'record_start' ], PHP_INT_MIN );
remove_action( $this->hook, [ $this, 'record_stop' ], PHP_INT_MAX );
}

Expand All @@ -199,6 +182,7 @@ public function validate(): void {
*/
public function never() {
$this->times = 0;

return $this;
}

Expand All @@ -209,6 +193,7 @@ public function never() {
*/
public function once() {
$this->times = 1;

return $this;
}

Expand All @@ -219,6 +204,7 @@ public function once() {
*/
public function twice() {
$this->times = 2;

return $this;
}

Expand All @@ -229,6 +215,7 @@ public function twice() {
*/
public function times( int $times ): static {
$this->times = $times;

return $this;
}

Expand All @@ -239,6 +226,7 @@ public function times( int $times ): static {
*/
public function with( ...$args ): static {
$this->args = $args;

return $this;
}

Expand All @@ -247,17 +235,30 @@ public function with( ...$args ): static {
*/
public function withAnyArgs(): static {
$this->args = null;

return $this;
}

/**
* Specify that the filter returns a specific value.
*
* @param mixed $value Return value.
* @param mixed ...$values Values to return.
*/
public function andReturn( mixed $value ): static {
public function andReturn( mixed ...$values ): static {
return $this->returnComparison(
fn ( $return_value ) => $return_value === $value
function ( $value ) use ( $values ) {
foreach ( $values as $expected ) {
if ( is_callable( $expected ) ) {
return (bool) $expected( $value );
}

if ( $value === $expected ) {
return true;
}
}

return false;
}
);
}

Expand Down Expand Up @@ -296,6 +297,13 @@ public function andReturnFalsy(): static {
return $this->returnComparison( fn ( $value ) => ! $value );
}

/**
* Specify that the filter returns a boolean value.
*/
public function andReturnBoolean(): static {
return $this->andReturn( true, false );
}

/**
* Specify that the filter returns an empty value.
*/
Expand Down
18 changes: 18 additions & 0 deletions tests/Testing/Concerns/InteractsWithHooksTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public function test_hook_added_declaration() {
public function test_hook_return_boolean() {
$this->expectApplied( 'true_hook_to_add' )->once()->andReturnTrue();
$this->expectApplied( 'false_hook_to_add' )->once()->andReturnFalse();
$this->expectApplied( 'true_hook_to_add' )->once()->andReturnBoolean();
$this->expectApplied( 'false_hook_to_add' )->once()->andReturnBoolean();

add_filter( 'true_hook_to_add', '__return_true' );
add_filter( 'false_hook_to_add', '__return_false' );
Expand Down Expand Up @@ -119,6 +121,22 @@ public function test_hook_applied_event() {

$this->assertHookApplied( Example_Event::class, 1 );
}

public function test_hook_returns_callback() {
$passed_value = null;

$this->expectApplied( 'callback_hook_to_add' )->once()->andReturn(
function ( $value ) use ( &$passed_value ) {
$passed_value = $value;

return 'filtered-value' === $value;
}
);

add_filter( 'callback_hook_to_add', fn () => 'filtered-value' );

apply_filters( 'callback_hook_to_add', 'passed-value' );
}
}

class Example_Event {}

0 comments on commit 0d5572c

Please sign in to comment.