Passed
Push — master ( b2f5d9...a9c687 )
by Alessandro
51s queued 12s
created

AbstractGeneratorTest::dataForIsAssociativeArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 37
rs 9.328
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Tests\Knp\Snappy;
4
5
use Knp\Snappy\AbstractGenerator;
6
use PHPUnit\Framework\TestCase;
7
use Psr\Log\LoggerInterface;
8
9
class AbstractGeneratorTest extends TestCase
10
{
11
    public function testAddOption(): void
12
    {
13
        $media = $this->getMockForAbstractClass(AbstractGenerator::class, [], '', false);
14
15
        $this->assertEquals([], $media->getOptions());
16
17
        $r = new \ReflectionMethod($media, 'addOption');
18
        $r->setAccessible(true);
19
        $r->invokeArgs($media, ['foo', 'bar']);
20
21
        $this->assertEquals(['foo' => 'bar'], $media->getOptions(), '->addOption() adds an option');
22
23
        $r->invokeArgs($media, ['baz', 'bat']);
24
25
        $this->assertEquals(
26
            [
27
                'foo' => 'bar',
28
                'baz' => 'bat',
29
            ],
30
            $media->getOptions(),
31
            '->addOption() appends the option to the existing ones'
32
        );
33
34
        $message = '->addOption() raises an exception when the specified option already exists';
35
36
        try {
37
            $r->invokeArgs($media, ['baz', 'bat']);
38
            $this->fail($message);
39
        } catch (\InvalidArgumentException $e) {
40
            $this->anything();
41
        }
42
    }
43
44
    public function testAddOptions(): void
45
    {
46
        $media = $this->getMockForAbstractClass(AbstractGenerator::class, [], '', false);
47
48
        $this->assertEquals([], $media->getOptions());
49
50
        $r = new \ReflectionMethod($media, 'addOptions');
51
        $r->setAccessible(true);
52
        $r->invokeArgs($media, [['foo' => 'bar', 'baz' => 'bat']]);
53
54
        $this->assertEquals(
55
            [
56
                'foo' => 'bar',
57
                'baz' => 'bat',
58
            ],
59
            $media->getOptions(),
60
            '->addOptions() adds all the given options'
61
        );
62
63
        $r->invokeArgs($media, [['ban' => 'bag', 'bal' => 'bac']]);
64
65
        $this->assertEquals(
66
            [
67
                'foo' => 'bar',
68
                'baz' => 'bat',
69
                'ban' => 'bag',
70
                'bal' => 'bac',
71
            ],
72
            $media->getOptions(),
73
            '->addOptions() adds the given options to the existing ones'
74
        );
75
76
        $message = '->addOptions() raises an exception when one of the given options already exists';
77
78
        try {
79
            $r->invokeArgs($media, [['bak' => 'bam', 'bah' => 'bap', 'baz' => 'bat']]);
80
            $this->fail($message);
81
        } catch (\InvalidArgumentException $e) {
82
            $this->anything();
83
        }
84
    }
85
86
    public function testSetOption(): void
87
    {
88
        $media = $this
89
            ->getMockBuilder(AbstractGenerator::class)
90
            ->setConstructorArgs(['/usr/local/bin/wkhtmltopdf'])
91
            ->getMockForAbstractClass()
92
        ;
93
94
        $logger = $this
95
            ->getMockBuilder(LoggerInterface::class)
96
            ->getMock()
97
        ;
98
        $media->setLogger($logger);
99
        $logger->expects($this->once())->method('debug');
100
101
        $r = new \ReflectionMethod($media, 'addOption');
102
        $r->setAccessible(true);
103
        $r->invokeArgs($media, ['foo', 'bar']);
104
105
        $media->setOption('foo', 'abc');
106
107
        $this->assertEquals(
108
            [
109
                'foo' => 'abc',
110
            ],
111
            $media->getOptions(),
112
            '->setOption() defines the value of an option'
113
        );
114
115
        $message = '->setOption() raises an exception when the specified option does not exist';
116
117
        try {
118
            $media->setOption('bad', 'def');
119
            $this->fail($message);
120
        } catch (\InvalidArgumentException $e) {
121
            $this->anything();
122
        }
123
    }
124
125
    public function testSetOptions(): void
126
    {
127
        $media = $this
128
            ->getMockBuilder(AbstractGenerator::class)
129
            ->setConstructorArgs(['/usr/local/bin/wkhtmltopdf'])
130
            ->getMockForAbstractClass()
131
        ;
132
133
        $logger = $this
134
            ->getMockBuilder(LoggerInterface::class)
135
            ->getMock()
136
        ;
137
        $media->setLogger($logger);
138
        $logger->expects($this->exactly(4))->method('debug');
139
140
        $r = new \ReflectionMethod($media, 'addOptions');
141
        $r->setAccessible(true);
142
        $r->invokeArgs($media, [['foo' => 'bar', 'baz' => 'bat']]);
143
144
        $media->setOptions(['foo' => 'abc', 'baz' => 'def']);
145
146
        $this->assertEquals(
147
            [
148
                'foo'   => 'abc',
149
                'baz'   => 'def',
150
            ],
151
            $media->getOptions(),
152
            '->setOptions() defines the values of all the specified options'
153
        );
154
155
        $message = '->setOptions() raises an exception when one of the specified options does not exist';
156
157
        try {
158
            $media->setOptions(['foo' => 'abc', 'baz' => 'def', 'bad' => 'ghi']);
159
            $this->fail($message);
160
        } catch (\InvalidArgumentException $e) {
161
            $this->anything();
162
        }
163
    }
164
165
    public function testGenerate(): void
166
    {
167
        $media = $this->getMockBuilder(AbstractGenerator::class)
168
            ->setMethods([
169
                'configure',
170
                'prepareOutput',
171
                'getCommand',
172
                'executeCommand',
173
                'checkOutput',
174
                'checkProcessStatus',
175
            ])
176
            ->setConstructorArgs(['the_binary', []])
177
            ->getMock()
178
        ;
179
180
        $logger = $this
181
            ->getMockBuilder(LoggerInterface::class)
182
            ->getMock()
183
        ;
184
        $media->setLogger($logger);
185
        $logger
186
            ->expects($this->exactly(2))
187
            ->method('info')
188
            ->with(
189
                $this->logicalOr(
190
                    'Generate from file(s) "the_input_file" to file "the_output_file".',
191
                    'File "the_output_file" has been successfully generated.'
192
                ),
193
                $this->logicalOr(
194
                    ['command' => 'the command', 'env' => null, 'timeout' => false],
195
                    ['command' => 'the command', 'stdout'  => 'stdout', 'stderr'  => 'stderr']
196
                )
197
            )
198
        ;
199
200
        $media
201
            ->expects($this->once())
202
            ->method('prepareOutput')
203
            ->with($this->equalTo('the_output_file'))
204
        ;
205
        $media
206
            ->expects($this->any())
207
            ->method('getCommand')
208
            ->with(
209
                $this->equalTo('the_input_file'),
210
                $this->equalTo('the_output_file'),
211
                $this->equalTo(['foo' => 'bar'])
212
            )
213
            ->will($this->returnValue('the command'))
214
        ;
215
        $media
216
            ->expects($this->once())
217
            ->method('executeCommand')
218
            ->with($this->equalTo('the command'))
219
            ->willReturn([0, 'stdout', 'stderr'])
220
        ;
221
        $media
222
            ->expects($this->once())
223
            ->method('checkProcessStatus')
224
            ->with(0, 'stdout', 'stderr', 'the command')
225
        ;
226
        $media
227
            ->expects($this->once())
228
            ->method('checkOutput')
229
            ->with(
230
                $this->equalTo('the_output_file'),
231
                $this->equalTo('the command')
232
            )
233
        ;
234
235
        $media->generate('the_input_file', 'the_output_file', ['foo' => 'bar']);
236
    }
237
238
    public function testFailingGenerate(): void
239
    {
240
        $media = $this->getMockBuilder(AbstractGenerator::class)
241
            ->setMethods([
242
                'configure',
243
                'prepareOutput',
244
                'getCommand',
245
                'executeCommand',
246
                'checkOutput',
247
                'checkProcessStatus',
248
            ])
249
            ->setConstructorArgs(['the_binary', [], ['PATH' => '/usr/bin']])
250
            ->getMock()
251
        ;
252
253
        $logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
254
        $media->setLogger($logger);
255
        $media->setTimeout(2000);
256
257
        $logger
258
            ->expects($this->once())
259
            ->method('info')
260
            ->with(
261
                $this->equalTo('Generate from file(s) "the_input_file" to file "the_output_file".'),
262
                $this->equalTo(['command' => 'the command', 'env' => ['PATH' => '/usr/bin'], 'timeout' => 2000])
263
            )
264
        ;
265
266
        $logger
267
            ->expects($this->once())
268
            ->method('error')
269
            ->with(
270
                $this->equalTo('An error happened while generating "the_output_file".'),
271
                $this->equalTo(['command' => 'the command', 'status' => 1, 'stdout'  => 'stdout', 'stderr'  => 'stderr'])
272
            )
273
        ;
274
275
        $media
276
            ->expects($this->once())
277
            ->method('prepareOutput')
278
            ->with($this->equalTo('the_output_file'))
279
        ;
280
        $media
281
            ->expects($this->any())
282
            ->method('getCommand')
283
            ->with(
284
                $this->equalTo('the_input_file'),
285
                $this->equalTo('the_output_file')
286
            )
287
            ->will($this->returnValue('the command'))
288
        ;
289
        $media
290
            ->expects($this->once())
291
            ->method('executeCommand')
292
            ->with($this->equalTo('the command'))
293
            ->willReturn([1, 'stdout', 'stderr'])
294
        ;
295
        $media
296
            ->expects($this->once())
297
            ->method('checkProcessStatus')
298
            ->with(1, 'stdout', 'stderr', 'the command')
299
            ->willThrowException(new \RuntimeException())
300
        ;
301
302
        $this->expectException(\RuntimeException::class);
303
304
        $media->generate('the_input_file', 'the_output_file', ['foo' => 'bar']);
305
    }
306
307
    public function testGenerateFromHtml(): void
308
    {
309
        $media = $this->getMockBuilder(AbstractGenerator::class)
310
            ->setMethods([
311
                'configure',
312
                'generate',
313
                'createTemporaryFile',
314
            ])
315
            ->setConstructorArgs(['the_binary'])
316
            ->disableOriginalConstructor()
317
            ->getMock()
318
        ;
319
320
        $media
321
            ->expects($this->once())
322
            ->method('createTemporaryFile')
323
            ->with(
324
                $this->equalTo('<html>foo</html>'),
325
                $this->equalTo('html')
326
            )
327
            ->will($this->returnValue('the_temporary_file'))
328
        ;
329
        $media
330
            ->expects($this->once())
331
            ->method('generate')
332
            ->with(
333
                $this->equalTo(['the_temporary_file']),
334
                $this->equalTo('the_output_file'),
335
                $this->equalTo(['foo' => 'bar'])
336
            )
337
        ;
338
339
        $media->generateFromHtml('<html>foo</html>', 'the_output_file', ['foo' => 'bar']);
340
    }
341
342
    public function testGenerateFromHtmlWithHtmlArray(): void
343
    {
344
        $media = $this->getMockBuilder(AbstractGenerator::class)
345
            ->setMethods([
346
                'configure',
347
                'generate',
348
                'createTemporaryFile',
349
            ])
350
            ->setConstructorArgs(['the_binary'])
351
            ->disableOriginalConstructor()
352
            ->getMock()
353
        ;
354
        $media
355
            ->expects($this->once())
356
            ->method('createTemporaryFile')
357
            ->with(
358
                $this->equalTo('<html>foo</html>'),
359
                $this->equalTo('html')
360
            )
361
            ->will($this->returnValue('the_temporary_file'))
362
        ;
363
        $media
364
            ->expects($this->once())
365
            ->method('generate')
366
            ->with(
367
                $this->equalTo(['the_temporary_file']),
368
                $this->equalTo('the_output_file'),
369
                $this->equalTo(['foo' => 'bar'])
370
            )
371
        ;
372
373
        $media->generateFromHtml(['<html>foo</html>'], 'the_output_file', ['foo' => 'bar']);
374
    }
375
376
    public function testGetOutput(): void
377
    {
378
        $media = $this->getMockBuilder(AbstractGenerator::class)
379
            ->setMethods([
380
                'configure',
381
                'getDefaultExtension',
382
                'createTemporaryFile',
383
                'generate',
384
                'getFileContents',
385
                'unlink',
386
            ])
387
            ->disableOriginalConstructor()
388
            ->getMock()
389
        ;
390
        $media
391
            ->expects($this->any())
392
            ->method('getDefaultExtension')
393
            ->will($this->returnValue('ext'))
394
        ;
395
        $media
396
            ->expects($this->any())
397
            ->method('createTemporaryFile')
398
            ->with(
399
                $this->equalTo(null),
400
                $this->equalTo('ext')
401
            )
402
            ->will($this->returnValue('the_temporary_file'))
403
        ;
404
        $media
405
            ->expects($this->once())
406
            ->method('generate')
407
            ->with(
408
                $this->equalTo('the_input_file'),
409
                $this->equalTo('the_temporary_file'),
410
                $this->equalTo(['foo' => 'bar'])
411
            )
412
        ;
413
        $media
414
            ->expects($this->once())
415
            ->method('getFileContents')
416
            ->will($this->returnValue('the file contents'))
417
        ;
418
419
        $media
420
            ->expects($this->any())
421
            ->method('unlink')
422
            ->with($this->equalTo('the_temporary_file'))
423
            ->will($this->returnValue(true))
424
        ;
425
426
        $this->assertEquals('the file contents', $media->getOutput('the_input_file', ['foo' => 'bar']));
427
    }
428
429
    public function testGetOutputFromHtml(): void
430
    {
431
        $media = $this->getMockBuilder(AbstractGenerator::class)
432
            ->setMethods([
433
                'configure',
434
                'getOutput',
435
                'createTemporaryFile',
436
            ])
437
            ->disableOriginalConstructor()
438
            ->getMock()
439
        ;
440
        $media
441
            ->expects($this->once())
442
            ->method('createTemporaryFile')
443
            ->with(
444
                $this->equalTo('<html>foo</html>'),
445
                $this->equalTo('html')
446
            )
447
            ->will($this->returnValue('the_temporary_file'))
448
        ;
449
        $media
450
            ->expects($this->once())
451
            ->method('getOutput')
452
            ->with(
453
                $this->equalTo(['the_temporary_file']),
454
                $this->equalTo(['foo' => 'bar'])
455
            )
456
            ->will($this->returnValue('the output'))
457
        ;
458
459
        $this->assertEquals('the output', $media->getOutputFromHtml('<html>foo</html>', ['foo' => 'bar']));
460
    }
461
462
    public function testGetOutputFromHtmlWithHtmlArray(): void
463
    {
464
        $media = $this->getMockBuilder(AbstractGenerator::class)
465
            ->setMethods([
466
                'configure',
467
                'getOutput',
468
                'createTemporaryFile',
469
            ])
470
            ->disableOriginalConstructor()
471
            ->getMock()
472
        ;
473
        $media
474
            ->expects($this->once())
475
            ->method('createTemporaryFile')
476
            ->with(
477
                $this->equalTo('<html>foo</html>'),
478
                $this->equalTo('html')
479
            )
480
            ->will($this->returnValue('the_temporary_file'))
481
        ;
482
        $media
483
            ->expects($this->once())
484
            ->method('getOutput')
485
            ->with(
486
                $this->equalTo(['the_temporary_file']),
487
                $this->equalTo(['foo' => 'bar'])
488
            )
489
            ->will($this->returnValue('the output'))
490
        ;
491
492
        $this->assertEquals('the output', $media->getOutputFromHtml(['<html>foo</html>'], ['foo' => 'bar']));
493
    }
494
495
    public function testMergeOptions(): void
496
    {
497
        $media = $this->getMockForAbstractClass(AbstractGenerator::class, [], '', false);
498
499
        $originalOptions = ['foo' => 'bar', 'baz' => 'bat'];
500
501
        $addOptions = new \ReflectionMethod($media, 'addOptions');
502
        $addOptions->setAccessible(true);
503
        $addOptions->invokeArgs($media, [$originalOptions]);
504
505
        $r = new \ReflectionMethod($media, 'mergeOptions');
506
        $r->setAccessible(true);
507
508
        $mergedOptions = $r->invokeArgs($media, [['foo' => 'ban']]);
509
510
        $this->assertEquals(
511
            [
512
                'foo' => 'ban',
513
                'baz' => 'bat',
514
            ],
515
            $mergedOptions,
516
            '->mergeOptions() merges an option to the instance ones and returns the result options array'
517
        );
518
519
        $this->assertEquals(
520
            $originalOptions,
521
            $media->getOptions(),
522
            '->mergeOptions() does NOT change the instance options'
523
        );
524
525
        $mergedOptions = $r->invokeArgs($media, [['foo' => 'ban', 'baz' => 'bag']]);
526
527
        $this->assertEquals(
528
            [
529
                'foo' => 'ban',
530
                'baz' => 'bag',
531
            ],
532
            $mergedOptions,
533
            '->mergeOptions() merges many options to the instance ones and returns the result options array'
534
        );
535
536
        $message = '->mergeOptions() throws an InvalidArgumentException once there is an undefined option in the given array';
537
538
        try {
539
            $r->invokeArgs($media, [['foo' => 'ban', 'bad' => 'bah']]);
540
            $this->fail($message);
541
        } catch (\InvalidArgumentException $e) {
542
            $this->anything();
543
        }
544
    }
545
546
    /**
547
     * @dataProvider dataForBuildCommand
548
     */
549
    public function testBuildCommand(string $binary, string $url, string $path, array $options, string $expected): void
550
    {
551
        $media = $this->getMockForAbstractClass(AbstractGenerator::class, [], '', false);
552
553
        $r = new \ReflectionMethod($media, 'buildCommand');
554
        $r->setAccessible(true);
555
556
        $this->assertEquals($expected, $r->invokeArgs($media, [$binary, $url, $path, $options]));
557
    }
558
559
    private function getPHPExecutableFromPath(): ?string
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
560
    {
561
        if (isset($_SERVER['_'])) {
562
            return $_SERVER['_'];
563
        }
564
565
        if (@defined(PHP_BINARY)) {
566
            return PHP_BINARY;
567
        }
568
569
        if (false === getenv('PATH')) {
570
            return null;
571
        }
572
573
        $paths = explode(PATH_SEPARATOR, getenv('PATH'));
574
        foreach ($paths as $path) {
575
            // we need this for XAMPP (Windows)
576
            if (strstr($path, 'php.exe') && isset($_SERVER['WINDIR']) && file_exists($path) && is_file($path)) {
577
                return $path;
578
            } else {
579
                $php_executable = $path . DIRECTORY_SEPARATOR . 'php' . (isset($_SERVER['WINDIR']) ? '.exe' : '');
580
                if (file_exists($php_executable) && is_file($php_executable)) {
581
                    return $php_executable;
582
                }
583
            }
584
        }
585
586
        return null; // not found
587
    }
588
589
    public function dataForBuildCommand(): array
590
    {
591
        $theBinary = $this->getPHPExecutableFromPath() . ' -v'; // i.e.: '/usr/bin/php -v'
592
593
        return [
594
            [
595
                $theBinary,
596
                'http://the.url/',
597
                '/the/path',
598
                [],
599
                $theBinary . ' ' . escapeshellarg('http://the.url/') . ' ' . escapeshellarg('/the/path'),
600
            ],
601
            [
602
                $theBinary,
603
                'http://the.url/',
604
                '/the/path',
605
                [
606
                    'foo'   => null,
607
                    'bar'   => false,
608
                    'baz'   => [],
609
                ],
610
                $theBinary . ' ' . escapeshellarg('http://the.url/') . ' ' . escapeshellarg('/the/path'),
611
            ],
612
            [
613
                $theBinary,
614
                'http://the.url/',
615
                '/the/path',
616
                [
617
                    'foo'   => 'foovalue',
618
                    'bar'   => ['barvalue1', 'barvalue2'],
619
                    'baz'   => true,
620
                ],
621
                $theBinary . ' --foo ' . escapeshellarg('foovalue') . ' --bar ' . escapeshellarg('barvalue1') . ' --bar ' . escapeshellarg('barvalue2') . ' --baz ' . escapeshellarg('http://the.url/') . ' ' . escapeshellarg('/the/path'),
622
            ],
623
            [
624
                $theBinary,
625
                'http://the.url/',
626
                '/the/path',
627
                [
628
                    'cookie'          => ['session' => 'bla', 'phpsess' => 12],
629
                    'no-background'   => '1',
630
                ],
631
                $theBinary . ' --cookie ' . escapeshellarg('session') . ' ' . escapeshellarg('bla') . ' --cookie ' . escapeshellarg('phpsess') . ' ' . escapeshellarg('12') . ' --no-background ' . escapeshellarg('1') . ' ' . escapeshellarg('http://the.url/') . ' ' . escapeshellarg('/the/path'),
632
            ],
633
            [
634
                $theBinary,
635
                'http://the.url/',
636
                '/the/path',
637
                [
638
                    'allow'           => ['/path1', '/path2'],
639
                    'no-background'   => '1',
640
                ],
641
                $theBinary . ' --allow ' . escapeshellarg('/path1') . ' --allow ' . escapeshellarg('/path2') . ' --no-background ' . escapeshellarg('1') . ' ' . escapeshellarg('http://the.url/') . ' ' . escapeshellarg('/the/path'),
642
            ],
643
            [
644
                $theBinary,
645
                'http://the.url/',
646
                '/the/path',
647
                [
648
                    'image-dpi'     => 100,
649
                    'image-quality' => 50,
650
                ],
651
                $theBinary . ' ' . '--image-dpi 100 --image-quality 50 ' . escapeshellarg('http://the.url/') . ' ' . escapeshellarg('/the/path'),
652
            ],
653
        ];
654
    }
655
656
    public function testCheckOutput(): void
657
    {
658
        $media = $this->getMockBuilder(AbstractGenerator::class)
659
            ->setMethods([
660
                'configure',
661
                'fileExists',
662
                'filesize',
663
            ])
664
            ->disableOriginalConstructor()
665
            ->getMock()
666
        ;
667
        $media
668
            ->expects($this->once())
669
            ->method('fileExists')
670
            ->with($this->equalTo('the_output_file'))
671
            ->will($this->returnValue(true))
672
        ;
673
        $media
674
            ->expects($this->once())
675
            ->method('filesize')
676
            ->with($this->equalTo('the_output_file'))
677
            ->will($this->returnValue(123))
678
        ;
679
680
        $r = new \ReflectionMethod($media, 'checkOutput');
681
        $r->setAccessible(true);
682
683
        $message = '->checkOutput() checks both file existence and size';
684
685
        try {
686
            $r->invokeArgs($media, ['the_output_file', 'the command']);
687
            $this->anything();
688
        } catch (\RuntimeException $e) {
689
            $this->fail($message);
690
        }
691
    }
692
693
    public function testCheckOutputWhenTheFileDoesNotExist(): void
694
    {
695
        $media = $this->getMockBuilder(AbstractGenerator::class)
696
            ->setMethods([
697
                'configure',
698
                'fileExists',
699
                'filesize',
700
            ])
701
            ->disableOriginalConstructor()
702
            ->getMock()
703
        ;
704
        $media
705
            ->expects($this->once())
706
            ->method('fileExists')
707
            ->with($this->equalTo('the_output_file'))
708
            ->will($this->returnValue(false))
709
        ;
710
711
        $r = new \ReflectionMethod($media, 'checkOutput');
712
        $r->setAccessible(true);
713
714
        $message = '->checkOutput() throws an InvalidArgumentException when the file does not exist';
715
716
        try {
717
            $r->invokeArgs($media, ['the_output_file', 'the command']);
718
            $this->fail($message);
719
        } catch (\RuntimeException $e) {
720
            $this->anything();
721
        }
722
    }
723
724
    public function testCheckOutputWhenTheFileIsEmpty(): void
725
    {
726
        $media = $this->getMockBuilder(AbstractGenerator::class)
727
            ->setMethods([
728
                'configure',
729
                'fileExists',
730
                'filesize',
731
            ])
732
            ->disableOriginalConstructor()
733
            ->getMock()
734
        ;
735
736
        $media
737
            ->expects($this->once())
738
            ->method('fileExists')
739
            ->with($this->equalTo('the_output_file'))
740
            ->will($this->returnValue(true))
741
        ;
742
        $media
743
            ->expects($this->once())
744
            ->method('filesize')
745
            ->with($this->equalTo('the_output_file'))
746
            ->will($this->returnValue(0))
747
        ;
748
749
        $r = new \ReflectionMethod($media, 'checkOutput');
750
        $r->setAccessible(true);
751
752
        $message = '->checkOutput() throws an InvalidArgumentException when the file is empty';
753
754
        try {
755
            $r->invokeArgs($media, ['the_output_file', 'the command']);
756
            $this->fail($message);
757
        } catch (\RuntimeException $e) {
758
            $this->anything();
759
        }
760
    }
761
762
    public function testCheckProcessStatus(): void
763
    {
764
        $media = $this->getMockBuilder(AbstractGenerator::class)
765
            ->setMethods(['configure'])
766
            ->disableOriginalConstructor()
767
            ->getMock()
768
        ;
769
770
        $r = new \ReflectionMethod($media, 'checkProcessStatus');
771
        $r->setAccessible(true);
772
773
        try {
774
            $r->invokeArgs($media, [0, '', '', 'the command']);
775
            $this->anything();
776
        } catch (\RuntimeException $e) {
777
            $this->fail('0 status means success');
778
        }
779
780
        try {
781
            $r->invokeArgs($media, [1, '', '', 'the command']);
782
            $this->anything();
783
        } catch (\RuntimeException $e) {
784
            $this->fail('1 status means failure, but no stderr content');
785
        }
786
787
        try {
788
            $r->invokeArgs($media, [1, '', 'Could not connect to X', 'the command']);
789
            $this->fail('1 status means failure');
790
        } catch (\RuntimeException $e) {
791
            $this->assertEquals(1, $e->getCode(), 'Exception thrown by checkProcessStatus should pass on the error code');
792
        }
793
    }
794
795
    /**
796
     * @dataProvider dataForIsAssociativeArray
797
     */
798
    public function testIsAssociativeArray(array $array, bool $isAssociativeArray): void
799
    {
800
        $generator = $this->getMockForAbstractClass(AbstractGenerator::class, [], '', false);
801
802
        $r = new \ReflectionMethod($generator, 'isAssociativeArray');
803
        $r->setAccessible(true);
804
        $this->assertEquals($isAssociativeArray, $r->invokeArgs($generator, [$array]));
805
    }
806
807
    /**
808
     * @expectedException Knp\Snappy\Exception\FileAlreadyExistsException
809
     */
810
    public function testItThrowsTheProperExceptionWhenFileExistsAndNotOverwritting(): void
811
    {
812
        $media = $this->getMockBuilder(AbstractGenerator::class)
813
            ->setMethods([
814
                'configure',
815
                'fileExists',
816
                'isFile',
817
            ])
818
            ->disableOriginalConstructor()
819
            ->getMock()
820
        ;
821
822
        $media
823
            ->expects($this->any())
824
            ->method('fileExists')
825
            ->will($this->returnValue(true))
826
        ;
827
        $media
828
            ->expects($this->any())
829
            ->method('isFile')
830
            ->will($this->returnValue(true))
831
        ;
832
        $r = new \ReflectionMethod($media, 'prepareOutput');
833
        $r->setAccessible(true);
834
835
        $r->invokeArgs($media, ['', false]);
836
    }
837
838
    public function dataForIsAssociativeArray(): array
839
    {
840
        return [
841
            [
842
                ['key' => 'value'],
843
                true,
844
            ],
845
            [
846
                ['key' => 2],
847
                true,
848
            ],
849
            [
850
                ['key' => 'value', 'key2' => 'value2'],
851
                true,
852
            ],
853
            [
854
                [0 => 'value', 1 => 'value2', 'deux' => 'value3'],
855
                true,
856
            ],
857
            [
858
                [0 => 'value'],
859
                false,
860
            ],
861
            [
862
                [0 => 'value', 1 => 'value2', 3 => 'value3'],
863
                false,
864
            ],
865
            [
866
                ['0' => 'value', '1' => 'value2', '3' => 'value3'],
867
                false,
868
            ],
869
            [
870
                [],
871
                false,
872
            ],
873
        ];
874
    }
875
876
    public function testCleanupEmptyTemporaryFiles(): void
877
    {
878
        $generator = $this->getMockBuilder(AbstractGenerator::class)
879
            ->setMethods([
880
                'configure',
881
                'unlink',
882
            ])
883
            ->setConstructorArgs(['the_binary'])
884
            ->getMock()
885
        ;
886
887
        $generator
888
            ->expects($this->once())
889
            ->method('unlink');
890
891
        $create = new \ReflectionMethod($generator, 'createTemporaryFile');
892
        $create->setAccessible(true);
893
        $create->invoke($generator, null, null);
894
895
        $files = new \ReflectionProperty($generator, 'temporaryFiles');
896
        $files->setAccessible(true);
897
        $this->assertCount(1, $files->getValue($generator));
898
899
        $remove = new \ReflectionMethod($generator, 'removeTemporaryFiles');
900
        $remove->setAccessible(true);
901
        $remove->invoke($generator);
902
    }
903
904
    public function testleanupTemporaryFiles(): void
905
    {
906
        $generator = $this->getMockBuilder(AbstractGenerator::class)
907
            ->setMethods([
908
                'configure',
909
                'unlink',
910
            ])
911
            ->setConstructorArgs(['the_binary'])
912
            ->getMock()
913
        ;
914
915
        $generator
916
            ->expects($this->once())
917
            ->method('unlink');
918
919
        $create = new \ReflectionMethod($generator, 'createTemporaryFile');
920
        $create->setAccessible(true);
921
        $create->invoke($generator, '<html/>', 'html');
922
923
        $files = new \ReflectionProperty($generator, 'temporaryFiles');
924
        $files->setAccessible(true);
925
        $this->assertCount(1, $files->getValue($generator));
926
927
        $remove = new \ReflectionMethod($generator, 'removeTemporaryFiles');
928
        $remove->setAccessible(true);
929
        $remove->invoke($generator);
930
    }
931
932
    public function testResetOptions(): void
933
    {
934
        $media = new class('/usr/local/bin/wkhtmltopdf') extends AbstractGenerator {
935
            protected function configure(): void
936
            {
937
                $this->addOptions([
938
                    'optionA' => null,
939
                    'optionB' => 'abc',
940
                ]);
941
            }
942
        };
943
944
        $media->setOption('optionA', 'bar');
945
946
        $this->assertEquals(
947
            [
948
                'optionA' => 'bar',
949
                'optionB' => 'abc',
950
            ],
951
            $media->getOptions()
952
        );
953
954
        $media->resetOptions();
955
956
        $this->assertEquals(
957
            [
958
                'optionA' => null,
959
                'optionB' => 'abc',
960
            ],
961
            $media->getOptions()
962
        );
963
    }
964
}
965