diff --git a/src/Turbo/src/Twig/TurboRuntime.php b/src/Turbo/src/Twig/TurboRuntime.php index 30238c64ee3..78fcba2d3b4 100644 --- a/src/Turbo/src/Twig/TurboRuntime.php +++ b/src/Turbo/src/Twig/TurboRuntime.php @@ -36,7 +36,11 @@ public function __construct( */ public function renderTurboStreamListen(Environment $env, $topic, ?string $transport = null, array $options = []): string { - $options['transport'] = $transport ??= $this->defaultTransport; + if (\array_key_exists('hub', $options) && $transport !== $options['hub']) { + throw new \InvalidArgumentException('When passing the "transport" option, the "hub" key in options is not allowed.'); + } + + $options['hub'] = $transport ??= $this->defaultTransport; if (!$this->turboStreamListenRenderers->has($transport)) { throw new \InvalidArgumentException(\sprintf('The Turbo stream transport "%s" does not exist.', $transport)); diff --git a/src/Turbo/tests/Twig/TurboRuntimeTest.php b/src/Turbo/tests/Twig/TurboRuntimeTest.php new file mode 100644 index 00000000000..666ab68200f --- /dev/null +++ b/src/Turbo/tests/Twig/TurboRuntimeTest.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\UX\Turbo\Tests\Twig; + +use PHPUnit\Framework\TestCase; +use Symfony\Contracts\Service\ServiceLocatorTrait; +use Symfony\Contracts\Service\ServiceProviderInterface; +use Symfony\UX\Turbo\Twig\TurboRuntime; +use Symfony\UX\Turbo\Twig\TurboStreamListenRendererInterface; +use Symfony\UX\Turbo\Twig\TurboStreamListenRendererWithOptionsInterface; +use Twig\Environment; + +final class TurboRuntimeTest extends TestCase +{ + public function testRenderTurboStreamListen() + { + $twig = $this->createMock(Environment::class); + $renderer = $this->createMock(TurboStreamListenRendererInterface::class); + $renderer->expects($this->once()) + ->method('renderTurboStreamListen') + ->willReturn('rendered-attributes') + ; + $container = new class(['default' => fn () => $renderer]) implements ServiceProviderInterface { + use ServiceLocatorTrait; + }; + + $runtime = new TurboRuntime($container, 'default'); + $runtime->renderTurboStreamListen($twig, 'a_topic'); + } + + public function testRenderTurboStreamListenWithMultipleHubs() + { + $twig = $this->createMock(Environment::class); + $renderer1 = $this->createMock(TurboStreamListenRendererInterface::class); + $renderer2 = $this->createMock(TurboStreamListenRendererWithOptionsInterface::class); + $renderer2->expects($this->once()) + ->method('renderTurboStreamListen') + ->with($twig, 'a_topic', ['hub' => 'hub2']) + ->willReturn('rendered-attributes') + ; + $container = new class(['hub1' => fn () => $renderer1, 'hub2' => fn () => $renderer2]) implements ServiceProviderInterface { + use ServiceLocatorTrait; + }; + + $runtime = new TurboRuntime($container, 'hub1'); + $runtime->renderTurboStreamListen($twig, 'a_topic', 'hub2'); + } + + public function testRenderTurboStreamListenWithDifferentsHub() + { + $this->expectException(\InvalidArgumentException::class); + + $twig = $this->createMock(Environment::class); + $renderer = $this->createMock(TurboStreamListenRendererInterface::class); + $container = new class(['default' => fn () => $renderer]) implements ServiceProviderInterface { + use ServiceLocatorTrait; + }; + + $runtime = new TurboRuntime($container, 'default'); + $runtime->renderTurboStreamListen($twig, 'a_topic', 'default', ['hub' => 'hub3']); + } +}