Passed
Pull Request — 1.x (#74)
by Kevin
02:19
created

BrowserTests::can_use_cookie_jar()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Zenstruck\Browser\Tests;
4
5
use Symfony\Component\BrowserKit\Cookie;
6
use Symfony\Component\BrowserKit\CookieJar;
7
use Symfony\Component\DomCrawler\Crawler;
8
use Symfony\Component\Filesystem\Filesystem;
9
use Symfony\Component\VarDumper\VarDumper;
10
use Zenstruck\Browser;
11
use Zenstruck\Browser\Response;
12
use Zenstruck\Browser\Response\HtmlResponse;
13
use Zenstruck\Browser\Test\HasBrowser;
14
use Zenstruck\Browser\Tests\Fixture\TestComponent1;
15
use Zenstruck\Browser\Tests\Fixture\TestComponent2;
16
use Zenstruck\Callback\Exception\UnresolveableArgument;
17
18
/**
19
 * @author Kevin Bond <[email protected]>
20
 */
21
trait BrowserTests
22
{
23
    use HasBrowser {
24
        browser as kernelBrowser;
25
    }
26
27
    /**
28
     * @test
29
     */
30
    public function multiple_browsers(): void
31
    {
32
        $browser1 = $this->browser()
33
            ->visit('/page1')
34
            ->assertOn('/page1')
35
        ;
36
37
        $browser2 = $this->browser()
0 ignored issues
show
Unused Code introduced by
The assignment to $browser2 is dead and can be removed.
Loading history...
38
            ->visit('/page2')
39
            ->assertOn('/page2')
40
        ;
41
42
        // this ensures a different browser is actually used
43
        $browser1->assertOn('/page1');
44
    }
45
46
    /**
47
     * @test
48
     */
49
    public function assert_on(): void
50
    {
51
        $this->browser()
52
            ->visit('/page1')
53
            ->assertOn('/page1')
54
            ->assertOn('http://www.example.com/page1')
55
            ->assertNotOn('/page2')
56
            ->assertNotOn('http://www.example.com/page1', ['path', 'host'])
57
            ->visit('/page1?foo=bar')
58
            ->assertOn('/page1?foo=bar')
59
            ->assertOn('/page1', ['path'])
60
            ->assertOn('/page1', ['path', 'fragment'])
61
            ->assertNotOn('/page1?foo=baz')
62
        ;
63
    }
64
65
    /**
66
     * @test
67
     * @dataProvider encodedUrlProvider
68
     */
69
    public function assert_on_encoded($url, $expected): void
70
    {
71
        $this->browser()
72
            ->visit($url)
73
            ->assertOn($expected)
74
        ;
75
    }
76
77
    public static function encodedUrlProvider(): iterable
78
    {
79
        yield ['/page1?filter[q]=value', '/page1?filter[q]=value'];
80
        yield ['/page1?filter%5Bq%5D=value', '/page1?filter[q]=value'];
81
        yield ['/page1?filter[q]=value', '/page1?filter%5Bq%5D=value'];
82
        yield ['/page1#foo bar', '/page1#foo bar'];
83
        yield ['/page1#foo%20bar', '/page1#foo bar'];
84
        yield ['/page1#foo bar', '/page1#foo%20bar'];
85
        yield ['/page1#foo+bar', '/page1#foo bar'];
86
        yield ['/page1#foo bar', '/page1#foo+bar'];
87
    }
88
89
    /**
90
     * @test
91
     */
92
    public function can_use_current_browser(): void
93
    {
94
        $browser = $this->browser();
95
96
        $browser
97
            ->use(function(Browser $b) use ($browser) {
98
                $this->assertSame($b, $browser);
0 ignored issues
show
Bug introduced by
The method assertSame() does not exist on Zenstruck\Browser\Tests\BrowserTests. Did you maybe mean assert_on()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

98
                $this->/** @scrutinizer ignore-call */ 
99
                       assertSame($b, $browser);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
99
100
                $browser->visit('/redirect1');
101
            })
102
            ->assertOn('/page1')
103
            ->use(function() {
104
                $this->assertTrue(true);
0 ignored issues
show
Bug introduced by
The method assertTrue() does not exist on Zenstruck\Browser\Tests\BrowserTests. Did you maybe mean assert_on()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

104
                $this->/** @scrutinizer ignore-call */ 
105
                       assertTrue(true);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
105
            })
106
        ;
107
    }
108
109
    /**
110
     * @test
111
     */
112
    public function can_use_components(): void
113
    {
114
        $this->browser()
115
            ->use(function(TestComponent1 $component) {
116
                $component->assertTitle('h1 title');
117
            })
118
            ->assertOn('/page1')
119
        ;
120
    }
121
122
    /**
123
     * @test
124
     */
125
    public function component_pre_assertions_and_actions_are_called(): void
126
    {
127
        $this->browser()
128
            ->use(function(TestComponent2 $component) {
129
                $this->assertTrue($component->preActionsCalled);
130
                $this->assertTrue($component->preAssertionsCalled);
131
            })
132
        ;
133
    }
134
135
    /**
136
     * @test
137
     */
138
    public function can_use_response(): void
139
    {
140
        $this->browser()
141
            ->visit('/page1')
142
            ->use(function(Response $response) {
143
                $this->assertStringContainsString('<h1>h1 title</h1>', $response->body());
0 ignored issues
show
Bug introduced by
It seems like assertStringContainsString() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

143
                $this->/** @scrutinizer ignore-call */ 
144
                       assertStringContainsString('<h1>h1 title</h1>', $response->body());
Loading history...
144
            })
145
            ->use(function(HtmlResponse $response) {
146
                $this->assertCount(2, $response->crawler()->filter('ul li'));
0 ignored issues
show
Bug introduced by
The method assertCount() does not exist on Zenstruck\Browser\Tests\BrowserTests. Did you maybe mean assert_on()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

146
                $this->/** @scrutinizer ignore-call */ 
147
                       assertCount(2, $response->crawler()->filter('ul li'));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
147
            })
148
        ;
149
    }
150
151
    /**
152
     * @test
153
     */
154
    public function can_use_crawler(): void
155
    {
156
        $this->browser()
157
            ->visit('/page1')
158
            ->use(function(Crawler $crawler) {
159
                $this->assertSame('h1 title', $crawler->filter('h1')->text());
160
            })
161
        ;
162
    }
163
164
    /**
165
     * @test
166
     */
167
    public function can_use_cookie_jar(): void
168
    {
169
        $this->browser()
170
            ->visit('/page1?start-session=1')
171
            ->use(function(CookieJar $jar) {
172
                $this->assertInstanceOf(Cookie::class, $jar->get('MOCKSESSID'));
0 ignored issues
show
Bug introduced by
It seems like assertInstanceOf() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

172
                $this->/** @scrutinizer ignore-call */ 
173
                       assertInstanceOf(Cookie::class, $jar->get('MOCKSESSID'));
Loading history...
173
            })
174
        ;
175
    }
176
177
    /**
178
     * @test
179
     */
180
    public function with_can_accept_multiple_browsers_and_components(): void
181
    {
182
        $browser = $this->browser();
183
184
        $browser
185
            ->use(function(Browser $browser1, $browser2, TestComponent1 $component1, TestComponent2 $component2, Crawler $crawler) use ($browser) {
0 ignored issues
show
Unused Code introduced by
The parameter $crawler is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

185
            ->use(function(Browser $browser1, $browser2, TestComponent1 $component1, TestComponent2 $component2, /** @scrutinizer ignore-unused */ Crawler $crawler) use ($browser) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
186
                $this->assertInstanceOf(Browser::class, $browser1);
187
                $this->assertInstanceOf(Browser::class, $browser2);
188
                $this->assertInstanceOf(\get_class($browser), $browser1);
189
                $this->assertInstanceOf(\get_class($browser), $browser2);
190
                $this->assertInstanceOf(TestComponent1::class, $component1);
191
                $this->assertInstanceOf(TestComponent2::class, $component2);
192
            })
193
        ;
194
    }
195
196
    /**
197
     * @test
198
     */
199
    public function invalid_use_callback_parameter_throws_type_error(): void
200
    {
201
        $this->expectException(UnresolveableArgument::class);
0 ignored issues
show
Bug introduced by
It seems like expectException() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

201
        $this->/** @scrutinizer ignore-call */ 
202
               expectException(UnresolveableArgument::class);
Loading history...
202
203
        $this->browser()->use(function(string $invalidType) {});
0 ignored issues
show
Unused Code introduced by
The parameter $invalidType is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

203
        $this->browser()->use(function(/** @scrutinizer ignore-unused */ string $invalidType) {});

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
204
    }
205
206
    /**
207
     * @test
208
     */
209
    public function redirects_are_followed_by_default(): void
210
    {
211
        $this->browser()
212
            ->visit('/redirect1')
213
            ->assertOn('/page1')
214
        ;
215
    }
216
217
    /**
218
     * @test
219
     */
220
    public function content_assertions(): void
221
    {
222
        $this->browser()
223
            ->visit('/page1')
224
            ->assertContains('h1 title')
225
            ->assertNotContains('invalid text')
226
        ;
227
    }
228
229
    /**
230
     * @test
231
     */
232
    public function can_dump_response(): void
233
    {
234
        $output = self::catchVarDumperOutput(function() {
235
            $this->browser()
236
                ->visit('/page1')
237
                ->dump()
238
            ;
239
        });
240
241
        $this->assertStringContainsString('/page1', $output[0]);
242
        $this->assertStringContainsString('<html', $output[0]);
243
        $this->assertStringContainsString('<h1>h1 title</h1>', $output[0]);
244
    }
245
246
    /**
247
     * @test
248
     */
249
    public function can_save_source(): void
250
    {
251
        $contents = self::catchFileContents(__DIR__.'/../var/browser/source/source.txt', function() {
252
            $this->browser()
253
                ->visit('/page1')
254
                ->saveSource('source.txt')
255
            ;
256
        });
257
258
        $this->assertStringContainsString('/page1', $contents);
259
        $this->assertStringContainsString('<html', $contents);
260
        $this->assertStringContainsString('<h1>h1 title</h1>', $contents);
261
    }
262
263
    /**
264
     * @test
265
     */
266
    public function html_assertions(): void
267
    {
268
        $this->browser()
269
            ->visit('/page1')
270
            ->assertSee('h1 title')
271
            ->assertNotSee('invalid text')
272
            ->assertSeeIn('h1', 'title')
273
            ->assertNotSeeIn('h1', 'invalid text')
274
            ->assertSeeElement('h1')
275
            ->assertNotSeeElement('h2')
276
            ->assertElementCount('ul li', 2)
277
        ;
278
    }
279
280
    /**
281
     * @test
282
     */
283
    public function html_head_assertions(): void
284
    {
285
        $this->browser()
286
            ->visit('/page1')
287
            ->assertSeeIn('title', 'meta title')
288
            ->assertElementAttributeContains('meta[name="description"]', 'content', 'meta')
289
            ->assertElementAttributeNotContains('meta[name="description"]', 'content', 'invalid')
290
            ->assertElementAttributeContains('html', 'lang', 'en')
291
        ;
292
    }
293
294
    /**
295
     * @test
296
     */
297
    public function form_assertions(): void
298
    {
299
        $this->browser()
300
            ->visit('/page1')
301
            ->assertFieldEquals('Input 1', 'input 1')
302
            ->assertFieldEquals('input1', 'input 1')
303
            ->assertFieldEquals('input_1', 'input 1')
304
            ->assertFieldNotEquals('Input 1', 'invalid')
305
            ->assertFieldNotEquals('input1', 'invalid')
306
            ->assertFieldNotEquals('input_1', 'invalid')
307
            ->assertChecked('Input 3')
308
            ->assertChecked('input3')
309
            ->assertChecked('input_3')
310
            ->assertNotChecked('Input 2')
311
            ->assertNotChecked('input2')
312
            ->assertNotChecked('input_2')
313
            ->assertSelected('Input 4', 'option 1')
314
            ->assertSelected('input4', 'option 1')
315
            ->assertSelected('input_4', 'option 1')
316
            ->assertSelected('Input 7', 'option 1')
317
            ->assertSelected('input7', 'option 1')
318
            ->assertSelected('input_7[]', 'option 1')
319
            ->assertSelected('Input 7', 'option 3')
320
            ->assertSelected('input7', 'option 3')
321
            ->assertSelected('input_7[]', 'option 3')
322
            ->assertNotSelected('Input 4', 'option 2')
323
            ->assertNotSelected('input4', 'option 2')
324
            ->assertNotSelected('input_4', 'option 2')
325
            ->assertNotSelected('Input 7', 'option 2')
326
            ->assertNotSelected('input7', 'option 2')
327
            ->assertNotSelected('input_7[]', 'option 2')
328
            ->assertNotSelected('input_8', 'option 1')
329
            ->assertSelected('input_8', 'option 2')
330
            ->assertNotChecked('Radio 1')
331
            ->assertNotChecked('radio1')
332
            ->assertNotChecked('Radio 3')
333
            ->assertNotChecked('radio3')
334
            ->assertChecked('Radio 2')
335
            ->assertChecked('radio2')
336
        ;
337
    }
338
339
    /**
340
     * @test
341
     */
342
    public function link_action(): void
343
    {
344
        $this->browser()
345
            ->visit('/page1')
346
            ->follow('a link')
347
            ->assertOn('/page2')
348
            ->visit('/page1')
349
            ->click('a link')
350
            ->assertOn('/page2')
351
        ;
352
    }
353
354
    /**
355
     * @test
356
     */
357
    public function click_on_element(): void
358
    {
359
        $this->browser()
360
            ->visit('/page1')
361
            ->click('#link a')
362
            ->assertOn('/page2')
363
        ;
364
    }
365
366
    /**
367
     * @test
368
     */
369
    public function form_actions_by_field_label(): void
370
    {
371
        $this->browser()
372
            ->visit('/page1')
373
            ->fillField('Input 1', 'Kevin')
374
            ->checkField('Input 2')
375
            ->uncheckField('Input 3')
376
            ->selectFieldOption('Input 4', 'option 2')
377
            ->attachFile('Input 5', __FILE__)
378
            ->selectFieldOptions('Input 6', ['option 1', 'option 3'])
379
            ->checkField('Radio 3')
380
            ->click('Submit')
381
            ->assertOn('/submit-form')
382
            ->assertContains('"input_1":"Kevin"')
383
            ->assertContains('"input_2":"on"')
384
            ->assertNotContains('"input_3')
385
            ->assertContains('"input_4":"option 2"')
386
            ->assertContains(\sprintf('"input_5":"%s"', \pathinfo(__FILE__, \PATHINFO_BASENAME)))
0 ignored issues
show
Bug introduced by
It seems like pathinfo(__FILE__, PATHINFO_BASENAME) can also be of type array; however, parameter $values of sprintf() does only seem to accept double|integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

386
            ->assertContains(\sprintf('"input_5":"%s"', /** @scrutinizer ignore-type */ \pathinfo(__FILE__, \PATHINFO_BASENAME)))
Loading history...
387
            ->assertContains('"input_6":["option 1","option 3"]')
388
            ->assertContains('"input_8":"option 3"')
389
        ;
390
    }
391
392
    /**
393
     * @test
394
     */
395
    public function form_actions_by_field_id(): void
396
    {
397
        $this->browser()
398
            ->visit('/page1')
399
            ->fillField('input1', 'Kevin')
400
            ->checkField('input2')
401
            ->uncheckField('input3')
402
            ->selectFieldOption('input4', 'option 2')
403
            ->attachFile('input5', __FILE__)
404
            ->selectFieldOptions('input6', ['option 1', 'option 3'])
405
            ->checkField('radio3')
406
            ->click('Submit')
407
            ->assertOn('/submit-form')
408
            ->assertContains('"input_1":"Kevin"')
409
            ->assertContains('"input_2":"on"')
410
            ->assertNotContains('"input_3')
411
            ->assertContains('"input_4":"option 2"')
412
            ->assertContains(\sprintf('"input_5":"%s"', \pathinfo(__FILE__, \PATHINFO_BASENAME)))
0 ignored issues
show
Bug introduced by
It seems like pathinfo(__FILE__, PATHINFO_BASENAME) can also be of type array; however, parameter $values of sprintf() does only seem to accept double|integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

412
            ->assertContains(\sprintf('"input_5":"%s"', /** @scrutinizer ignore-type */ \pathinfo(__FILE__, \PATHINFO_BASENAME)))
Loading history...
413
            ->assertContains('"input_6":["option 1","option 3"]')
414
            ->assertContains('"input_8":"option 3"')
415
        ;
416
    }
417
418
    /**
419
     * @test
420
     */
421
    public function form_actions_by_field_name(): void
422
    {
423
        $this->browser()
424
            ->visit('/page1')
425
            ->fillField('input_1', 'Kevin')
426
            ->checkField('input_2')
427
            ->uncheckField('input_3')
428
            ->selectFieldOption('input_4', 'option 2')
429
            ->attachFile('input_5', __FILE__)
430
            ->selectFieldOptions('input_6[]', ['option 1', 'option 3'])
431
            ->selectFieldOption('input_8', 'option 3')
432
            ->click('Submit')
433
            ->assertOn('/submit-form')
434
            ->assertContains('"input_1":"Kevin"')
435
            ->assertContains('"input_2":"on"')
436
            ->assertNotContains('"input_3')
437
            ->assertContains('"input_4":"option 2"')
438
            ->assertContains(\sprintf('"input_5":"%s"', \pathinfo(__FILE__, \PATHINFO_BASENAME)))
0 ignored issues
show
Bug introduced by
It seems like pathinfo(__FILE__, PATHINFO_BASENAME) can also be of type array; however, parameter $values of sprintf() does only seem to accept double|integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

438
            ->assertContains(\sprintf('"input_5":"%s"', /** @scrutinizer ignore-type */ \pathinfo(__FILE__, \PATHINFO_BASENAME)))
Loading history...
439
            ->assertContains('"input_6":["option 1","option 3"]')
440
            ->assertContains('"input_8":"option 3"')
441
        ;
442
    }
443
444
    /**
445
     * @test
446
     */
447
    public function select_field(): void
448
    {
449
        $this->browser()
450
            ->visit('/page1')
451
            ->selectField('Input 2')
452
            ->selectField('Input 4', 'option 2')
453
            ->selectField('Input 6', ['option 1', 'option 3'])
454
            ->selectField('Radio 3')
455
            ->click('Submit')
456
            ->assertOn('/submit-form')
457
            ->assertContains('"input_2":"on"')
458
            ->assertContains('"input_4":"option 2"')
459
            ->assertContains('"input_6":["option 1","option 3"]')
460
            ->assertContains('"input_8":"option 3"')
461
        ;
462
    }
463
464
    /**
465
     * @test
466
     */
467
    public function can_submit_form_with_different_submit_buttons(): void
468
    {
469
        // Submit and Submit B, have the same field name but different values
470
        // Submit C has a different field name (and value)
471
472
        $this->browser()
473
            ->visit('/page1')
474
            ->click('Submit')
475
            ->assertOn('/submit-form')
476
            ->assertContains('"submit_1":"a"')
477
            ->assertNotContains('submit_2')
478
            ->visit('/page1')
479
            ->click('Submit B')
480
            ->assertOn('/submit-form')
481
            ->assertContains('"submit_1":"b"')
482
            ->assertNotContains('submit_2')
483
            ->visit('/page1')
484
            ->click('Submit C')
485
            ->assertOn('/submit-form')
486
            ->assertContains('"submit_2":"c"')
487
            ->assertNotContains('submit_1')
488
            ->visit('/page1')
489
            ->click('Submit D')
490
            ->assertOn('/submit-form')
491
            ->assertContains('"submit_2":"d"')
492
            ->assertNotContains('submit_1')
493
        ;
494
    }
495
496
    /**
497
     * @see https://github.com/zenstruck/browser/issues/55
498
     *
499
     * @test
500
     */
501
    public function can_submit_filled_form_with_different_submit_buttons(): void
502
    {
503
        // Submit and Submit B, have the same field name but different values
504
        // Submit C has a different field name (and value)
505
506
        $this->browser()
507
            ->visit('/page1')
508
            ->fillField('input_1', 'Kevin')
509
            ->click('Submit')
510
            ->assertOn('/submit-form')
511
            ->assertContains('"input_1":"Kevin"')
512
            ->assertContains('"submit_1":"a"')
513
            ->assertNotContains('submit_2')
514
            ->visit('/page1')
515
            ->fillField('input_1', 'Kevin')
516
            ->click('Submit B')
517
            ->assertOn('/submit-form')
518
            ->assertContains('"input_1":"Kevin"')
519
            ->assertContains('"submit_1":"b"')
520
            ->assertNotContains('submit_2')
521
            ->visit('/page1')
522
            ->fillField('input_1', 'Kevin')
523
            ->click('Submit C')
524
            ->assertOn('/submit-form')
525
            ->assertContains('"input_1":"Kevin"')
526
            ->assertContains('"submit_2":"c"')
527
            ->assertNotContains('submit_1')
528
            ->visit('/page1')
529
            ->fillField('input_1', 'Kevin')
530
            ->click('Submit D')
531
            ->assertOn('/submit-form')
532
            ->assertContains('"input_1":"Kevin"')
533
            ->assertContains('"submit_2":"d"')
534
            ->assertNotContains('submit_1')
535
        ;
536
    }
537
538
    /**
539
     * @test
540
     */
541
    public function cannot_attach_file_that_does_not_exist(): void
542
    {
543
        $this->expectException(\InvalidArgumentException::class);
544
545
        $this->browser()
546
            ->visit('/page1')
547
            ->attachFile('Input 5', '/invalid/file')
548
        ;
549
    }
550
551
    /**
552
     * @test
553
     */
554
    public function can_attach_multiple_files(): void
555
    {
556
        $this->browser()
557
            ->visit('/page1')
558
            ->attachFile('Input 9', [__DIR__.'/Fixture/files/attachment.txt', __DIR__.'/Fixture/files/xml.xml'])
559
            ->click('Submit')
560
            ->assertContains('"input_9":["attachment.txt","xml.xml"]')
561
        ;
562
    }
563
564
    /**
565
     * @test
566
     */
567
    public function cannot_attach_multiple_files_to_a_non_multiple_input(): void
568
    {
569
        $this->expectException(\InvalidArgumentException::class);
570
571
        $this->browser()
572
            ->visit('/page1')
573
            ->attachFile('Input 5', [__DIR__.'/Fixture/files/attachment.txt', __DIR__.'/Fixture/files/xml.xml'])
574
        ;
575
    }
576
577
    /**
578
     * @test
579
     */
580
    public function can_dump_html_element(): void
581
    {
582
        $output = self::catchVarDumperOutput(function() {
583
            $this->browser()
584
                ->visit('/page1')
585
                ->dump('p#link')
586
            ;
587
        });
588
589
        $this->assertCount(1, $output);
590
        $this->assertSame('<p id="link"><a href="/page2">a link</a> not a link</p>', $output[0]);
591
    }
592
593
    /**
594
     * @test
595
     */
596
    public function if_dump_selector_matches_multiple_elements_all_are_dumped(): void
597
    {
598
        $output = self::catchVarDumperOutput(function() {
599
            $this->browser()
600
                ->visit('/page1')
601
                ->dump('li')
602
            ;
603
        });
604
605
        $this->assertCount(2, $output);
606
        $this->assertSame('<li>list 1</li>', $output[0]);
607
        $this->assertSame('<li>list 2</li>', $output[1]);
608
    }
609
610
    /**
611
     * @test
612
     */
613
    public function can_access_the_html_crawler(): void
614
    {
615
        $crawler = $this->browser()
616
            ->visit('/page1')
617
            ->response()
618
            ->assertHtml()
619
            ->crawler()
620
            ->filter('ul li')
621
        ;
622
623
        $this->assertCount(2, $crawler);
624
    }
625
626
    protected static function catchFileContents(string $expectedFile, callable $callback): string
627
    {
628
        (new Filesystem())->remove($expectedFile);
629
630
        $callback();
631
632
        self::assertFileExists($expectedFile);
633
634
        return \file_get_contents($expectedFile);
635
    }
636
637
    protected static function catchVarDumperOutput(callable $callback): array
638
    {
639
        $output[] = null;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$output was never initialized. Although not strictly required by PHP, it is generally a good practice to add $output = array(); before regardless.
Loading history...
640
641
        VarDumper::setHandler(function($var) use (&$output) {
642
            $output[] = $var;
643
        });
644
645
        $callback();
646
647
        // reset to default handler
648
        VarDumper::setHandler();
649
650
        // a null value is added to the beginning
651
        return \array_values(\array_filter($output));
652
    }
653
654
    abstract protected function browser(): Browser;
655
}
656