12
12
namespace Symfony \UX \LiveComponent \Tests \Functional \EventListener ;
13
13
14
14
use Symfony \Bundle \FrameworkBundle \Test \KernelTestCase ;
15
- use Symfony \Component \DomCrawler \Crawler ;
16
- use Symfony \Component \HttpKernel \Exception \BadRequestHttpException ;
17
15
use Symfony \Component \Security \Core \User \InMemoryUser ;
18
16
use Symfony \Component \Security \Http \Attribute \IsGranted ;
19
17
use Symfony \UX \LiveComponent \Tests \Fixtures \Entity \Entity1 ;
20
18
use Symfony \UX \LiveComponent \Tests \LiveComponentTestHelper ;
19
+ use Zenstruck \Browser ;
21
20
use Zenstruck \Browser \Test \HasBrowser ;
22
21
use Zenstruck \Foundry \Test \Factories ;
23
22
use Zenstruck \Foundry \Test \ResetDatabase ;
@@ -70,8 +69,7 @@ public function testCanRenderComponentAsHtml(): void
70
69
->assertContains ('Prop1: ' .$ entity ->id )
71
70
->assertContains ('Prop2: 2021-03-05 9:23 ' )
72
71
->assertContains ('Prop3: value3 ' )
73
- ->assertContains ('Prop4: (none) ' )
74
- ;
72
+ ->assertContains ('Prop4: (none) ' );
75
73
}
76
74
77
75
public function testCanRenderComponentAsHtmlWithAlternateRoute (): void
@@ -89,8 +87,7 @@ public function testCanRenderComponentAsHtmlWithAlternateRoute(): void
89
87
])
90
88
->assertSuccessful ()
91
89
->assertOn ('/alt/alternate_route ' , parts: ['path ' ])
92
- ->assertContains ('From alternate route. (count: 0) ' )
93
- ;
90
+ ->assertContains ('From alternate route. (count: 0) ' );
94
91
}
95
92
96
93
public function testCanExecuteComponentActionNormalRoute (): void
@@ -127,8 +124,7 @@ public function testCanExecuteComponentActionNormalRoute(): void
127
124
->assertSuccessful ()
128
125
->assertHeaderContains ('Content-Type ' , 'html ' )
129
126
->assertContains ('Count: 2 ' )
130
- ->assertSee ('Embedded content with access to context, like count=2 ' )
131
- ;
127
+ ->assertSee ('Embedded content with access to context, like count=2 ' );
132
128
}
133
129
134
130
public function testCanExecuteComponentActionWithAlternateRoute (): void
@@ -151,24 +147,21 @@ public function testCanExecuteComponentActionWithAlternateRoute(): void
151
147
])
152
148
->assertSuccessful ()
153
149
->assertOn ('/alt/alternate_route/increase ' )
154
- ->assertContains ('count: 1 ' )
155
- ;
150
+ ->assertContains ('count: 1 ' );
156
151
}
157
152
158
153
public function testCannotExecuteComponentActionForGetRequest (): void
159
154
{
160
155
$ this ->browser ()
161
156
->get ('/_components/component2/increase ' )
162
- ->assertStatus (405 )
163
- ;
157
+ ->assertStatus (405 );
164
158
}
165
159
166
160
public function testCannotExecuteComponentDefaultActionForGetRequestWhenMethodIsPost (): void
167
161
{
168
162
$ this ->browser ()
169
163
->get ('/_components/with_method_post/__invoke ' )
170
- ->assertStatus (405 )
171
- ;
164
+ ->assertStatus (405 );
172
165
}
173
166
174
167
public function testPreReRenderHookOnlyExecutedDuringAjax (): void
@@ -187,8 +180,7 @@ public function testPreReRenderHookOnlyExecutedDuringAjax(): void
187
180
],
188
181
])
189
182
->assertSuccessful ()
190
- ->assertSee ('PreReRenderCalled: Yes ' )
191
- ;
183
+ ->assertSee ('PreReRenderCalled: Yes ' );
192
184
}
193
185
194
186
public function testItAddsEmbeddedTemplateContextToEmbeddedComponents (): void
@@ -224,8 +216,7 @@ public function testItAddsEmbeddedTemplateContextToEmbeddedComponents(): void
224
216
])
225
217
->assertSuccessful ()
226
218
->assertSee ('PreReRenderCalled: Yes ' )
227
- ->assertSee ('Embedded content with access to context, like count=1 ' )
228
- ;
219
+ ->assertSee ('Embedded content with access to context, like count=1 ' );
229
220
}
230
221
231
222
public function testItWorksWithNamespacedTemplateNamesForEmbeddedComponents (): void
@@ -237,8 +228,7 @@ public function testItWorksWithNamespacedTemplateNamesForEmbeddedComponents(): v
237
228
$ this ->browser ()
238
229
->visit ('/render-namespaced-template/render_embedded_with_blocks ' )
239
230
->assertSuccessful ()
240
- ->assertElementAttributeContains ('.component2 ' , 'data-live-props-value ' , '"data-host-template":" ' .$ obscuredName .'" ' )
241
- ;
231
+ ->assertElementAttributeContains ('.component2 ' , 'data-live-props-value ' , '"data-host-template":" ' .$ obscuredName .'" ' );
242
232
}
243
233
244
234
public function testItUseBlocksFromEmbeddedContextUsingMultipleComponents (): void
@@ -269,8 +259,7 @@ public function testItUseBlocksFromEmbeddedContextUsingMultipleComponents(): voi
269
259
])
270
260
->assertSuccessful ()
271
261
->assertHeaderContains ('Content-Type ' , 'html ' )
272
- ->assertSee ('Overridden content from component 2 on same line - count: 2 ' )
273
- ;
262
+ ->assertSee ('Overridden content from component 2 on same line - count: 2 ' );
274
263
}
275
264
276
265
public function testItUseBlocksFromEmbeddedContextUsingMultipleComponentsWithNamespacedTemplate (): void
@@ -301,8 +290,7 @@ public function testItUseBlocksFromEmbeddedContextUsingMultipleComponentsWithNam
301
290
])
302
291
->assertSuccessful ()
303
292
->assertHeaderContains ('Content-Type ' , 'html ' )
304
- ->assertSee ('Overridden content from component 2 on same line - count: 2 ' )
305
- ;
293
+ ->assertSee ('Overridden content from component 2 on same line - count: 2 ' );
306
294
}
307
295
308
296
public function testCanRedirectFromComponentAction (): void
@@ -336,10 +324,71 @@ public function testCanRedirectFromComponentAction(): void
336
324
->assertStatus (204 )
337
325
->assertHeaderEquals ('Location ' , '/ ' )
338
326
->assertHeaderContains ('X-Live-Redirect ' , '1 ' )
339
- ->assertHeaderEquals ('X-Custom-Header ' , '1 ' )
327
+ ->assertHeaderEquals ('X-Custom-Header ' , '1 ' );
328
+ }
329
+
330
+ public function testCanDownloadFileFromComponentAction (): void
331
+ {
332
+ $ dehydrated = $ this ->dehydrateComponent ($ this ->mountComponent ('download_file ' ));
333
+
334
+ $ this ->browser ()
335
+ ->throwExceptions ()
336
+ ->post ('/_components/download_file ' , [
337
+ 'body ' => [
338
+ 'data ' => json_encode ([
339
+ 'props ' => $ dehydrated ->getProps (),
340
+ ]),
341
+ ],
342
+ ])
343
+
344
+ ->interceptRedirects ()
345
+ ->post ('/_components/download_file/download ' , [
346
+ 'headers ' => [
347
+ 'Accept ' => 'application/vnd.live-component+html ' ,
348
+ ],
349
+ 'body ' => ['data ' => json_encode (['props ' => $ dehydrated ->getProps ()])],
350
+ ])
351
+ ->assertStatus (200 )
352
+ ->assertHeaderContains ('X-Live-Download ' , '1 ' )
353
+ ->assertHeaderContains ('Content-Type ' , 'application/octet-stream ' )
354
+ ->assertHeaderContains ('Content-Disposition ' , 'attachment ' )
355
+ ->assertHeaderEquals ('Content-Length ' , '21 ' )
340
356
;
341
357
}
342
358
359
+ public function testCanDownloadGeneratedFileFromComponentAction (): void
360
+ {
361
+ $ dehydrated = $ this ->dehydrateComponent ($ this ->mountComponent ('download_file ' ));
362
+
363
+ $ this ->browser ()
364
+ ->throwExceptions ()
365
+ ->post ('/_components/download_file ' , [
366
+ 'body ' => [
367
+ 'data ' => json_encode ([
368
+ 'props ' => $ dehydrated ->getProps (),
369
+ ]),
370
+ ],
371
+ ])
372
+ ->interceptRedirects ()
373
+ ->assertSuccessful ()
374
+ ->post ('/_components/download_file/generate ' , [
375
+ 'body ' => [
376
+ 'data ' => json_encode ([
377
+ 'props ' => $ dehydrated ->getProps (),
378
+ ]),
379
+ ],
380
+ ])
381
+ ->assertStatus (200 )
382
+ ->assertHeaderContains ('X-Live-Download ' , '1 ' )
383
+ ->assertHeaderContains ('Content-Type ' , 'application/octet-stream ' )
384
+ ->assertHeaderContains ('Content-Disposition ' , 'attachment ' )
385
+ ->assertHeaderEquals ('Content-Length ' , '21 ' )
386
+ ->use (function (Browser $ browser ) {
387
+ self ::assertJson ($ browser ->content ());
388
+ self ::assertSame (['foo ' => 'bar ' ], \json_decode ($ browser ->content (), true ));
389
+ });
390
+ }
391
+
343
392
public function testInjectsLiveArgs (): void
344
393
{
345
394
$ dehydrated = $ this ->dehydrateComponent ($ this ->mountComponent ('component6 ' ));
@@ -371,8 +420,7 @@ public function testInjectsLiveArgs(): void
371
420
->assertHeaderContains ('Content-Type ' , 'html ' )
372
421
->assertContains ('Arg1: hello ' )
373
422
->assertContains ('Arg2: 666 ' )
374
- ->assertContains ('Arg3: 33.3 ' )
375
- ;
423
+ ->assertContains ('Arg3: 33.3 ' );
376
424
}
377
425
378
426
public function testWithNullableEntity (): void
@@ -389,8 +437,7 @@ public function testWithNullableEntity(): void
389
437
],
390
438
])
391
439
->assertSuccessful ()
392
- ->assertContains ('Prop1: default ' )
393
- ;
440
+ ->assertContains ('Prop1: default ' );
394
441
}
395
442
396
443
public function testCanHaveControllerAttributes (): void
@@ -407,8 +454,7 @@ public function testCanHaveControllerAttributes(): void
407
454
->actingAs (new InMemoryUser ('kevin ' , 'pass ' , ['ROLE_USER ' ]))
408
455
->assertAuthenticated ('kevin ' )
409
456
->post ('/_components/with_security?props= ' .urlencode (json_encode ($ dehydrated ->getProps ())))
410
- ->assertSuccessful ()
411
- ;
457
+ ->assertSuccessful ();
412
458
}
413
459
414
460
public function testCanInjectSecurityUserIntoAction (): void
@@ -436,7 +482,6 @@ public function testCanInjectSecurityUserIntoAction(): void
436
482
],
437
483
])
438
484
->assertSuccessful ()
439
- ->assertSee ('username: kevin ' )
440
- ;
485
+ ->assertSee ('username: kevin ' );
441
486
}
442
487
}
0 commit comments