Skip to content

Commit cf288cd

Browse files
committed
Add Bus\HasHandler Laravel constraint
1 parent f20ac47 commit cf288cd

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Craftzing\TestBench\Laravel\Constraint\Bus;
6+
7+
use Craftzing\TestBench\PHPUnit\Constraint\ProvidesAdditionalFailureDescription;
8+
use Illuminate\Contracts\Bus\Dispatcher;
9+
use Illuminate\Support\Facades\Bus;
10+
use InvalidArgumentException;
11+
use PHPUnit\Framework\Constraint\Constraint;
12+
use ReflectionClass;
13+
14+
use function class_exists;
15+
use function gettype;
16+
use function is_string;
17+
18+
final class HasHandler extends Constraint
19+
{
20+
use ProvidesAdditionalFailureDescription;
21+
22+
private readonly Dispatcher $bus;
23+
24+
public function __construct(
25+
/* @var class-string */
26+
private readonly string $handlerClassFQN,
27+
) {
28+
$this->bus = Bus::getFacadeRoot();
29+
}
30+
31+
protected function matches(mixed $other): bool
32+
{
33+
is_string($other) or throw new InvalidArgumentException(
34+
self::class . ' can only be evaluated for strings, got ' . gettype($other) . '.',
35+
);
36+
class_exists($other) or throw new InvalidArgumentException(
37+
self::class . " can only be evaluated for existing classes, got $other.",
38+
);
39+
$message = new ReflectionClass($other)->newInstanceWithoutConstructor();
40+
$actualHandler = $this->bus->getCommandHandler($message);
41+
42+
if ($actualHandler === false) {
43+
$this->additionalFailureDescriptions[] = "$other has no handler mapped to it.";
44+
45+
return false;
46+
}
47+
48+
if ($actualHandler::class !== $this->handlerClassFQN) {
49+
$this->additionalFailureDescriptions[] = "$other has a different handler mapped to it.";
50+
51+
return false;
52+
}
53+
54+
return true;
55+
}
56+
57+
public function toString(): string
58+
{
59+
return 'has handler';
60+
}
61+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Craftzing\TestBench\Laravel\Constraint\Bus;
6+
7+
use Craftzing\TestBench\PHPUnit\Doubles\SpyCallable;
8+
use Illuminate\Support\Facades\Bus;
9+
use InvalidArgumentException;
10+
use Orchestra\Testbench\TestCase;
11+
use PHPUnit\Framework\Attributes\Test;
12+
use PHPUnit\Framework\Attributes\TestWith;
13+
use PHPUnit\Framework\ExpectationFailedException;
14+
use stdClass;
15+
16+
final class HasHandlerTest extends TestCase
17+
{
18+
#[Test]
19+
#[TestWith([true], 'Boolean')]
20+
#[TestWith([1], 'Integers')]
21+
#[TestWith([['event']], 'Array')]
22+
public function itCannotEvaluateUnsupportedValueTypes(mixed $value): void
23+
{
24+
$this->expectException(InvalidArgumentException::class);
25+
$this->expectExceptionMessage(HasHandler::class . ' can only be evaluated for strings');
26+
27+
$this->assertThat($value, new HasHandler('SomeHandlerClassFCN'));
28+
}
29+
30+
#[Test]
31+
public function itCannotEvaluateStringThatAreNotExistingClasses(): void
32+
{
33+
$value = 'NotAClass';
34+
35+
$this->expectException(InvalidArgumentException::class);
36+
$this->expectExceptionMessage(HasHandler::class . " can only be evaluated for existing classes, got $value.");
37+
38+
$this->assertThat($value, new HasHandler('SomeHandlerClassFCN'));
39+
}
40+
41+
#[Test]
42+
public function itFailsWhenNoHandlerIsMapped(): void
43+
{
44+
$messageClassFCN = stdClass::class;
45+
46+
$this->expectException(ExpectationFailedException::class);
47+
$this->expectExceptionMessage('has handler');
48+
$this->expectExceptionMessage('stdClass has no handler mapped to it');
49+
50+
$this->assertThat($messageClassFCN, new HasHandler('SomeHandlerClassFCN'));
51+
}
52+
53+
#[Test]
54+
public function itFailsWhenDifferentHandlerIsMapped(): void
55+
{
56+
$messageClassFCN = stdClass::class;
57+
Bus::map([$messageClassFCN => SpyCallable::class]);
58+
59+
$this->expectException(ExpectationFailedException::class);
60+
$this->expectExceptionMessage('has handler');
61+
$this->expectExceptionMessage('stdClass has a different handler mapped to it');
62+
63+
$this->assertThat($messageClassFCN, new HasHandler('SomeHandlerClassFCN'));
64+
}
65+
66+
#[Test]
67+
public function itPassesWhenGivenHandlerIsMapped(): void
68+
{
69+
$messageClassFCN = stdClass::class;
70+
Bus::map([$messageClassFCN => SpyCallable::class]);
71+
72+
$this->assertThat($messageClassFCN, new HasHandler(SpyCallable::class));
73+
}
74+
}

0 commit comments

Comments
 (0)