Skip to content

Commit ce84462

Browse files
committed
feat(live): improve TestLiveComponent::actingAs()
1 parent aec04ad commit ce84462

File tree

2 files changed

+71
-34
lines changed

2 files changed

+71
-34
lines changed

src/LiveComponent/src/Test/TestLiveComponent.php

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,48 +28,22 @@
2828
*/
2929
final class TestLiveComponent
3030
{
31+
private bool $performedInitialRequest = false;
32+
3133
/**
3234
* @internal
3335
*/
3436
public function __construct(
3537
private ComponentMetadata $metadata,
36-
array $data,
38+
private array $data,
3739
private ComponentFactory $factory,
3840
private KernelBrowser $client,
3941
private LiveComponentHydrator $hydrator,
4042
private LiveComponentMetadataFactory $metadataFactory,
4143
private UrlGeneratorInterface $router,
4244
) {
4345
$this->client->catchExceptions(false);
44-
45-
$data['attributes']['id'] ??= 'in-a-real-scenario-it-would-already-have-one---provide-one-yourself-if-needed';
46-
47-
$mounted = $this->factory->create($this->metadata->getName(), $data);
48-
$props = $this->hydrator->dehydrate(
49-
$mounted->getComponent(),
50-
$mounted->getAttributes(),
51-
$this->metadataFactory->getMetadata($mounted->getName())
52-
);
53-
54-
if ('POST' === strtoupper($this->metadata->get('method'))) {
55-
$this->client->request(
56-
'POST',
57-
$this->router->generate($this->metadata->get('route'), [
58-
'_live_component' => $this->metadata->getName(),
59-
]),
60-
[
61-
'data' => json_encode(['props' => $props->getProps()], flags: \JSON_THROW_ON_ERROR),
62-
],
63-
);
64-
} else {
65-
$this->client->request('GET', $this->router->generate(
66-
$this->metadata->get('route'),
67-
[
68-
'_live_component' => $this->metadata->getName(),
69-
'props' => json_encode($props->getProps(), flags: \JSON_THROW_ON_ERROR),
70-
]
71-
));
72-
}
46+
$this->data['attributes']['data-live-id'] ??= 'in-a-real-scenario-it-would-already-have-one---provide-one-yourself-if-needed';
7347
}
7448

7549
public function render(): RenderedComponent
@@ -95,6 +69,7 @@ public function component(): object
9569
*/
9670
public function actingAs(object $user, string $firewallContext = 'main'): self
9771
{
72+
// we call loginUser() on the raw client in case the entire component requires authentication
9873
$this->client->loginUser($user, $firewallContext);
9974

10075
return $this;
@@ -145,14 +120,14 @@ public function refresh(): self
145120

146121
public function response(): Response
147122
{
148-
return $this->client->getResponse();
123+
return $this->client()->getResponse();
149124
}
150125

151126
private function request(array $content = [], ?string $action = null): self
152127
{
153128
$csrfToken = $this->csrfToken();
154129

155-
$this->client->request(
130+
$this->client()->request(
156131
'POST',
157132
$this->router->generate(
158133
$this->metadata->get('route'),
@@ -170,7 +145,7 @@ private function request(array $content = [], ?string $action = null): self
170145

171146
private function props(): array
172147
{
173-
$crawler = $this->client->getCrawler();
148+
$crawler = $this->client()->getCrawler();
174149

175150
if (!\count($node = $crawler->filter('[data-live-props-value]'))) {
176151
throw new \LogicException('A live component action has redirected and you can no longer access the component.');
@@ -181,12 +156,50 @@ private function props(): array
181156

182157
private function csrfToken(): ?string
183158
{
184-
$crawler = $this->client->getCrawler();
159+
$crawler = $this->client()->getCrawler();
185160

186161
if (!\count($node = $crawler->filter('[data-live-csrf-value]'))) {
187162
return null;
188163
}
189164

190165
return $node->attr('data-live-csrf-value');
191166
}
167+
168+
private function client(): KernelBrowser
169+
{
170+
if ($this->performedInitialRequest) {
171+
return $this->client;
172+
}
173+
174+
$mounted = $this->factory->create($this->metadata->getName(), $this->data);
175+
$props = $this->hydrator->dehydrate(
176+
$mounted->getComponent(),
177+
$mounted->getAttributes(),
178+
$this->metadataFactory->getMetadata($mounted->getName())
179+
);
180+
181+
if ('POST' === strtoupper($this->metadata->get('method'))) {
182+
$this->client->request(
183+
'POST',
184+
$this->router->generate($this->metadata->get('route'), [
185+
'_live_component' => $this->metadata->getName(),
186+
]),
187+
[
188+
'data' => json_encode(['props' => $props->getProps()], flags: \JSON_THROW_ON_ERROR),
189+
],
190+
);
191+
} else {
192+
$this->client->request('GET', $this->router->generate(
193+
$this->metadata->get('route'),
194+
[
195+
'_live_component' => $this->metadata->getName(),
196+
'props' => json_encode($props->getProps(), flags: \JSON_THROW_ON_ERROR),
197+
]
198+
));
199+
}
200+
201+
$this->performedInitialRequest = true;
202+
203+
return $this->client;
204+
}
192205
}

src/LiveComponent/tests/Functional/Test/InteractsWithLiveComponentsTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
namespace Symfony\UX\LiveComponent\Tests\Functional\Test;
1313

1414
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
15+
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
16+
use Symfony\Component\Security\Core\User\InMemoryUser;
1517
use Symfony\UX\LiveComponent\Test\InteractsWithLiveComponents;
1618
use Symfony\UX\LiveComponent\Tests\Fixtures\Component\Component2;
1719

@@ -140,4 +142,26 @@ public function testCannotUpdateComponentIfNoLongerInContext(): void
140142

141143
$testComponent->call('increase');
142144
}
145+
146+
public function testRenderingIsLazy(): void
147+
{
148+
$testComponent = $this->createLiveComponent('with_security');
149+
150+
$this->expectException(AccessDeniedException::class);
151+
152+
$testComponent->render();
153+
}
154+
155+
public function testActingAs(): void
156+
{
157+
$testComponent = $this->createLiveComponent('with_security')
158+
->actingAs(new InMemoryUser('kevin', 'pass', ['ROLE_USER']))
159+
;
160+
161+
$this->assertStringNotContainsString('Username: kevin', $testComponent->render());
162+
163+
$testComponent->call('setUsername');
164+
165+
$this->assertStringContainsString('Username: kevin', $testComponent->render());
166+
}
143167
}

0 commit comments

Comments
 (0)