Passed
Push — master ( d7ad8d...2766ff )
by Alessandro
55s queued 10s
created

testItThrowsTheProperExceptionWhenFileExistsAndNotOverwritting()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

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