diff --git a/src/Symfony/Component/Workflow/Debug/TraceableWorkflow.php b/src/Symfony/Component/Workflow/Debug/TraceableWorkflow.php index b8ac0867d4194..6d0afd80cf620 100644 --- a/src/Symfony/Component/Workflow/Debug/TraceableWorkflow.php +++ b/src/Symfony/Component/Workflow/Debug/TraceableWorkflow.php @@ -16,6 +16,7 @@ use Symfony\Component\Workflow\Marking; use Symfony\Component\Workflow\MarkingStore\MarkingStoreInterface; use Symfony\Component\Workflow\Metadata\MetadataStoreInterface; +use Symfony\Component\Workflow\Transition; use Symfony\Component\Workflow\TransitionBlockerList; use Symfony\Component\Workflow\WorkflowInterface; @@ -57,6 +58,11 @@ public function getEnabledTransitions(object $subject): array return $this->callInner(__FUNCTION__, \func_get_args()); } + public function getEnabledTransition(object $subject, string $name): ?Transition + { + return $this->callInner(__FUNCTION__, \func_get_args()); + } + public function getName(): string { return $this->workflow->getName(); diff --git a/src/Symfony/Component/Workflow/Tests/Debug/TraceableWorkflowTest.php b/src/Symfony/Component/Workflow/Tests/Debug/TraceableWorkflowTest.php new file mode 100644 index 0000000000000..5bfcee9b9f25e --- /dev/null +++ b/src/Symfony/Component/Workflow/Tests/Debug/TraceableWorkflowTest.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Workflow\Tests\Debug; + +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\Workflow\Debug\TraceableWorkflow; +use Symfony\Component\Workflow\Marking; +use Symfony\Component\Workflow\TransitionBlockerList; +use Symfony\Component\Workflow\Workflow; + +class TraceableWorkflowTest extends TestCase +{ + private MockObject|Workflow $innerWorkflow; + + private StopWatch $stopwatch; + + private TraceableWorkflow $traceableWorkflow; + + protected function setUp(): void + { + $this->innerWorkflow = $this->createMock(Workflow::class); + $this->stopwatch = new Stopwatch(); + + $this->traceableWorkflow = new TraceableWorkflow( + $this->innerWorkflow, + $this->stopwatch + ); + } + + /** + * @dataProvider provideFunctionNames + */ + public function testCallsInner(string $function, array $args, mixed $returnValue) + { + $this->innerWorkflow->expects($this->once()) + ->method($function) + ->willReturn($returnValue); + + $this->assertSame($returnValue, $this->traceableWorkflow->{$function}(...$args)); + + $calls = $this->traceableWorkflow->getCalls(); + + $this->assertCount(1, $calls); + $this->assertSame($function, $calls[0]['method']); + $this->assertArrayHasKey('duration', $calls[0]); + $this->assertSame($returnValue, $calls[0]['return']); + } + + public function testCallsInnerCatchesException() + { + $exception = new \Exception('foo'); + $this->innerWorkflow->expects($this->once()) + ->method('can') + ->willThrowException($exception); + + try { + $this->traceableWorkflow->can(new \stdClass(), 'foo'); + + $this->fail('An exception should have been thrown.'); + } catch (\Exception $e) { + $this->assertSame($exception, $e); + + $calls = $this->traceableWorkflow->getCalls(); + + $this->assertCount(1, $calls); + $this->assertSame('can', $calls[0]['method']); + $this->assertArrayHasKey('duration', $calls[0]); + $this->assertArrayHasKey('exception', $calls[0]); + $this->assertSame($exception, $calls[0]['exception']); + } + } + + public static function provideFunctionNames(): \Generator + { + $subject = new \stdClass(); + + yield ['getMarking', [$subject], new Marking(['place' => 1])]; + + yield ['can', [$subject, 'foo'], true]; + + yield ['buildTransitionBlockerList', [$subject, 'foo'], new TransitionBlockerList()]; + + yield ['apply', [$subject, 'foo'], new Marking(['place' => 1])]; + + yield ['getEnabledTransitions', [$subject], []]; + + yield ['getEnabledTransition', [$subject, 'foo'], null]; + } +} diff --git a/src/Symfony/Component/Workflow/composer.json b/src/Symfony/Component/Workflow/composer.json index 689219800eea1..2c277fcc090e5 100644 --- a/src/Symfony/Component/Workflow/composer.json +++ b/src/Symfony/Component/Workflow/composer.json @@ -31,6 +31,7 @@ "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^6.4|^7.0", "symfony/security-core": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", "symfony/validator": "^5.4|^6.0|^7.0" }, "conflict": {