Passed
Pull Request — master (#71)
by Cees-Jan
02:05
created

ConsoleTest::testGenerateNonGroupedLabel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 13
nc 1
nop 0
dl 0
loc 20
rs 9.8333
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ChangelogGenerator\Tests\Functional;
6
7
use ChangelogGenerator\ChangelogConfig;
8
use ChangelogGenerator\ChangelogGenerator;
9
use ChangelogGenerator\Command\GenerateChangelogCommand;
10
use InvalidArgumentException;
11
use PackageVersions\Versions;
12
use PHPUnit\Framework\MockObject\MockObject;
13
use PHPUnit\Framework\TestCase;
14
use Symfony\Component\Console\Application;
15
use Symfony\Component\Console\Input\ArrayInput;
16
use Symfony\Component\Console\Output\BufferedOutput;
17
use Symfony\Component\Console\Output\OutputInterface;
18
use Symfony\Component\Console\Output\StreamOutput;
19
20
use function file_exists;
21
use function sprintf;
22
use function sys_get_temp_dir;
23
use function tempnam;
24
use function uniqid;
25
use function unlink;
26
27
final class ConsoleTest extends TestCase
28
{
29
    /** @var MockObject&ChangelogGenerator */
30
    private $changelogGenerator;
31
32
    /** @var MockObject&GenerateChangelogCommand */
33
    private $generateChangelogCommand;
34
35
    private Application $application;
36
37
    public function testGenerate(): void
38
    {
39
        $input = new ArrayInput([
40
            'command'       => 'generate',
41
            '--user'        => 'jwage',
42
            '--repository'  => 'changelog-generator',
43
            '--milestone'   => '1.0',
44
        ]);
45
46
        $output = $this->createMock(OutputInterface::class);
47
48
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', []);
49
50
        $this->changelogGenerator->expects(self::once())
51
            ->method('generate')
52
            ->with($changelogConfig, $output);
53
54
        $this->application->run($input, $output);
55
    }
56
57
    public function testGenerateShowContributors(): void
58
    {
59
        $input = new ArrayInput([
60
            'command'             => 'generate',
61
            '--user'              => 'jwage',
62
            '--repository'        => 'changelog-generator',
63
            '--milestone'         => '1.0',
64
            '--show-contributors' => null,
65
        ]);
66
67
        $output = $this->createMock(OutputInterface::class);
68
69
        $changelogConfig = (new ChangelogConfig('jwage', 'changelog-generator', '1.0', []))
70
            ->setShowContributors(true);
71
72
        $this->changelogGenerator->expects(self::once())
73
            ->method('generate')
74
            ->with($changelogConfig, $output);
75
76
        $this->application->run($input, $output);
77
    }
78
79
    public function testGenerateInvalidConfig(): void
80
    {
81
        $this->expectException(InvalidArgumentException::class);
82
        $this->expectExceptionMessage('You must pass a config file with the --config option or manually specify the --user --repository and --milestone options.');
83
84
        $input = new ArrayInput(['command' => 'generate']);
85
86
        $output = $this->createMock(OutputInterface::class);
87
88
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', []);
89
90
        $this->changelogGenerator->expects(self::never())
91
            ->method('generate')
92
            ->with($changelogConfig, $output);
93
94
        $this->application->run($input, $output);
95
    }
96
97
    public function testGenerateFile(): void
98
    {
99
        $input = new ArrayInput([
100
            'command'       => 'generate',
101
            '--user'        => 'jwage',
102
            '--repository'  => 'changelog-generator',
103
            '--milestone'   => '1.0',
104
            '--file'        => null,
105
        ]);
106
107
        $output       = $this->createMock(OutputInterface::class);
108
        $streamOutput = $this->createMock(StreamOutput::class);
109
110
        $this->generateChangelogCommand->expects(self::once())
111
            ->method('createOutput')
112
            ->willReturn($streamOutput);
113
114
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', []);
115
116
        $this->changelogGenerator->expects(self::once())
117
            ->method('generate')
118
            ->with($changelogConfig, $streamOutput);
119
120
        $this->application->run($input, $output);
121
    }
122
123
    public function testGenerateFilePathGiven(): void
124
    {
125
        $input = new ArrayInput([
126
            'command'       => 'generate',
127
            '--user'        => 'jwage',
128
            '--repository'  => 'changelog-generator',
129
            '--milestone'   => '1.0',
130
            '--file'        => tempnam(sys_get_temp_dir(), 'CHANGELOG.md'),
131
        ]);
132
133
        $output       = $this->createMock(OutputInterface::class);
134
        $streamOutput = $this->createMock(StreamOutput::class);
135
136
        $this->generateChangelogCommand->expects(self::once())
137
            ->method('createOutput')
138
            ->willReturn($streamOutput);
139
140
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', []);
141
142
        $this->changelogGenerator->expects(self::once())
143
            ->method('generate')
144
            ->with($changelogConfig, $streamOutput);
145
146
        $this->application->run($input, $output);
147
    }
148
149
    public function testGenerateFileAppend(): void
150
    {
151
        $input = new ArrayInput([
152
            'command'       => 'generate',
153
            '--user'        => 'jwage',
154
            '--repository'  => 'changelog-generator',
155
            '--milestone'   => '1.0',
156
            '--file'        => tempnam(sys_get_temp_dir(), 'CHANGELOG.md'),
157
            '--append'      => true,
158
        ]);
159
160
        $output       = $this->createMock(OutputInterface::class);
161
        $streamOutput = $this->createMock(StreamOutput::class);
162
163
        $this->generateChangelogCommand->expects(self::once())
164
            ->method('createOutput')
165
            ->willReturn($streamOutput);
166
167
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', []);
168
169
        $this->changelogGenerator->expects(self::once())
170
            ->method('generate')
171
            ->with($changelogConfig, $streamOutput);
172
173
        $this->application->run($input, $output);
174
    }
175
176
    public function testGenerateFilePrepend(): void
177
    {
178
        $input = new ArrayInput([
179
            'command'       => 'generate',
180
            '--user'        => 'jwage',
181
            '--repository'  => 'changelog-generator',
182
            '--milestone'   => '1.0',
183
            '--file'        => tempnam(sys_get_temp_dir(), 'CHANGELOG.md'),
184
            '--prepend'     => true,
185
        ]);
186
187
        $output         = $this->createMock(OutputInterface::class);
188
        $bufferedOutput = $this->createMock(BufferedOutput::class);
189
190
        $this->generateChangelogCommand->expects(self::once())
191
            ->method('createOutput')
192
            ->willReturn($bufferedOutput);
193
194
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', []);
195
196
        $this->changelogGenerator->expects(self::once())
197
            ->method('generate')
198
            ->with($changelogConfig, $bufferedOutput);
199
200
        $this->application->run($input, $output);
201
    }
202
203
    public function testGenerateFilePrependStreamOutput(): void
204
    {
205
        $input = new ArrayInput([
206
            'command'       => 'generate',
207
            '--user'        => 'jwage',
208
            '--repository'  => 'changelog-generator',
209
            '--milestone'   => '1.0',
210
            '--file'        => tempnam(sys_get_temp_dir(), 'CHANGELOG.md'),
211
            '--prepend'     => true,
212
        ]);
213
214
        $output       = $this->createMock(OutputInterface::class);
215
        $streamOutput = $this->createMock(StreamOutput::class);
216
217
        $this->generateChangelogCommand->expects(self::once())
218
            ->method('createOutput')
219
            ->willReturn($streamOutput);
220
221
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', []);
222
223
        $this->changelogGenerator->expects(self::once())
224
            ->method('generate')
225
            ->with($changelogConfig, $streamOutput);
226
227
        $this->application->run($input, $output);
228
    }
229
230
    public function testGenerateFilePrependCreatesFileThatDoesNotExist(): void
231
    {
232
        $file = sprintf('%s/%sCHANGELOG.md', sys_get_temp_dir(), uniqid());
233
234
        $input = new ArrayInput([
235
            'command'       => 'generate',
236
            '--user'        => 'jwage',
237
            '--repository'  => 'changelog-generator',
238
            '--milestone'   => '1.0',
239
            '--file'        => $file,
240
            '--prepend'     => true,
241
        ]);
242
243
        $output         = $this->createMock(OutputInterface::class);
244
        $bufferedOutput = $this->createMock(BufferedOutput::class);
245
246
        $this->generateChangelogCommand->expects(self::once())
247
            ->method('createOutput')
248
            ->willReturn($bufferedOutput);
249
250
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', []);
251
252
        $this->changelogGenerator->expects(self::once())
253
            ->method('generate')
254
            ->with($changelogConfig, $bufferedOutput);
255
256
        $this->application->run($input, $output);
257
258
        $exists = file_exists($file);
259
260
        unlink($file);
261
262
        self::assertTrue($exists);
263
    }
264
265
    public function testGenerateLabel(): void
266
    {
267
        $input = new ArrayInput([
268
            'command'       => 'generate',
269
            '--user'        => 'jwage',
270
            '--repository'  => 'changelog-generator',
271
            '--milestone'   => '1.0',
272
            '--label'       => ['Enhancement', 'Bug'],
273
        ]);
274
275
        $output = $this->createMock(OutputInterface::class);
276
277
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', ['Enhancement', 'Bug']);
278
279
        $this->changelogGenerator->expects(self::once())
280
            ->method('generate')
281
            ->with($changelogConfig, $output);
282
283
        $this->application->run($input, $output);
284
    }
285
286
    public function testGenerateNonGroupedLabel(): void
287
    {
288
        $input = new ArrayInput([
289
            'command'             => 'generate',
290
            '--user'              => 'jwage',
291
            '--repository'        => 'changelog-generator',
292
            '--milestone'         => '1.0',
293
            '--label'             => ['Enhancement', 'Bug'],
294
            '--non-grouped-label' => 'Non Grouped',
295
        ]);
296
297
        $output = $this->createMock(OutputInterface::class);
298
299
        $changelogConfig = (new ChangelogConfig('jwage', 'changelog-generator', '1.0', ['Enhancement', 'Bug']))->setNonGroupedLabel('Non Grouped');
300
301
        $this->changelogGenerator->expects(self::once())
302
            ->method('generate')
303
            ->with($changelogConfig, $output);
304
305
        $this->application->run($input, $output);
306
    }
307
308
    public function testGenerateConfig(): void
309
    {
310
        $input = new ArrayInput([
311
            'command'       => 'generate',
312
            '--user'        => 'jwage',
313
            '--repository'  => 'changelog-generator',
314
            '--milestone'   => '1.0',
315
            '--label'       => ['Enhancement', 'Bug'],
316
            '--config'      => __DIR__ . '/_files/config.php',
317
            '--project'     => 'changelog-generator',
318
        ]);
319
320
        $output = $this->createMock(OutputInterface::class);
321
322
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', ['Enhancement', 'Bug']);
323
324
        $this->changelogGenerator->expects(self::once())
325
            ->method('generate')
326
            ->with($changelogConfig, $output);
327
328
        $this->application->run($input, $output);
329
    }
330
331
    public function testGenerateConfigDoesNotExist(): void
332
    {
333
        $this->expectException(InvalidArgumentException::class);
334
        $this->expectExceptionMessage('Configuration file "unknown.php" does not exist.');
335
336
        $input = new ArrayInput([
337
            'command'       => 'generate',
338
            '--user'        => 'jwage',
339
            '--repository'  => 'changelog-generator',
340
            '--milestone'   => '1.0',
341
            '--label'       => ['Enhancement', 'Bug'],
342
            '--config'      => 'unknown.php',
343
        ]);
344
345
        $output = $this->createMock(OutputInterface::class);
346
347
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', ['Enhancement', 'Bug']);
348
349
        $this->changelogGenerator->expects(self::never())
350
            ->method('generate')
351
            ->with($changelogConfig, $output);
352
353
        $this->application->run($input, $output);
354
    }
355
356
    public function testGenerateConfigEmpty(): void
357
    {
358
        $configFile = __DIR__ . '/_files/empty.php';
359
360
        $this->expectException(InvalidArgumentException::class);
361
        $this->expectExceptionMessage(sprintf('Configuration file "%s" did not return anything.', $configFile));
362
363
        $input = new ArrayInput([
364
            'command'       => 'generate',
365
            '--user'        => 'jwage',
366
            '--repository'  => 'changelog-generator',
367
            '--milestone'   => '1.0',
368
            '--label'       => ['Enhancement', 'Bug'],
369
            '--config'      => $configFile,
370
        ]);
371
372
        $output = $this->createMock(OutputInterface::class);
373
374
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', ['Enhancement', 'Bug']);
375
376
        $this->changelogGenerator->expects(self::never())
377
            ->method('generate')
378
            ->with($changelogConfig, $output);
379
380
        $this->application->run($input, $output);
381
    }
382
383
    public function testGenerateConfigInvalidProject(): void
384
    {
385
        $this->expectException(InvalidArgumentException::class);
386
        $this->expectExceptionMessage('Could not find project named "unknown" configured');
387
388
        $input = new ArrayInput([
389
            'command'       => 'generate',
390
            '--user'        => 'jwage',
391
            '--repository'  => 'changelog-generator',
392
            '--milestone'   => '1.0',
393
            '--label'       => ['Enhancement', 'Bug'],
394
            '--config'      => __DIR__ . '/_files/config.php',
395
            '--project'     => 'unknown',
396
        ]);
397
398
        $output = $this->createMock(OutputInterface::class);
399
400
        $changelogConfig = new ChangelogConfig('jwage', 'changelog-generator', '1.0', ['Enhancement', 'Bug']);
401
402
        $this->changelogGenerator->expects(self::never())
403
            ->method('generate')
404
            ->with($changelogConfig, $output);
405
406
        $this->application->run($input, $output);
407
    }
408
409
    public function testGenerateIncludeOpenOptionNotProvided(): void
410
    {
411
        $input = new ArrayInput([
412
            'command'        => 'generate',
413
            '--user'         => 'doctrine',
414
            '--repository'   => 'migrations',
415
            '--milestone'    => '2.0',
416
            '--label'        => ['Improvement', 'Bug'],
417
            '--config'       => __DIR__ . '/_files/config.php',
418
            '--project'      => 'changelog-generator',
419
        ]);
420
421
        $output = $this->createMock(OutputInterface::class);
422
423
        $changelogConfig = new ChangelogConfig('doctrine', 'migrations', '2.0', ['Improvement', 'Bug'], false);
424
425
        $this->changelogGenerator->expects(self::once())
426
            ->method('generate')
427
            ->with($changelogConfig, $output);
428
429
        $this->application->run($input, $output);
430
    }
431
432
    public function testGenerateIncludeOpenDefault(): void
433
    {
434
        $input = new ArrayInput([
435
            'command'        => 'generate',
436
            '--user'         => 'doctrine',
437
            '--repository'   => 'migrations',
438
            '--milestone'    => '2.0',
439
            '--label'        => ['Improvement', 'Bug'],
440
            '--config'       => __DIR__ . '/_files/config.php',
441
            '--project'      => 'changelog-generator',
442
            '--include-open' => null,
443
        ]);
444
445
        $output = $this->createMock(OutputInterface::class);
446
447
        $changelogConfig = new ChangelogConfig('doctrine', 'migrations', '2.0', ['Improvement', 'Bug'], true);
448
449
        $this->changelogGenerator->expects(self::once())
450
            ->method('generate')
451
            ->with($changelogConfig, $output);
452
453
        $this->application->run($input, $output);
454
    }
455
456
    public function testGenerateIncludeOpenTrue(): void
457
    {
458
        $input = new ArrayInput([
459
            'command'        => 'generate',
460
            '--user'         => 'doctrine',
461
            '--repository'   => 'migrations',
462
            '--milestone'    => '2.0',
463
            '--label'        => ['Improvement', 'Bug'],
464
            '--config'       => __DIR__ . '/_files/config.php',
465
            '--project'      => 'changelog-generator',
466
            '--include-open' => '1',
467
        ]);
468
469
        $output = $this->createMock(OutputInterface::class);
470
471
        $changelogConfig = new ChangelogConfig('doctrine', 'migrations', '2.0', ['Improvement', 'Bug'], true);
472
473
        $this->changelogGenerator->expects(self::once())
474
            ->method('generate')
475
            ->with($changelogConfig, $output);
476
477
        $this->application->run($input, $output);
478
    }
479
480
    public function testGenerateIncludeOpenFalse(): void
481
    {
482
        $input = new ArrayInput([
483
            'command'        => 'generate',
484
            '--user'         => 'doctrine',
485
            '--repository'   => 'migrations',
486
            '--milestone'    => '2.0',
487
            '--label'        => ['Improvement', 'Bug'],
488
            '--config'       => __DIR__ . '/_files/config.php',
489
            '--project'      => 'changelog-generator',
490
            '--include-open' => '0',
491
        ]);
492
493
        $output = $this->createMock(OutputInterface::class);
494
495
        $changelogConfig = new ChangelogConfig('doctrine', 'migrations', '2.0', ['Improvement', 'Bug'], false);
496
497
        $this->changelogGenerator->expects(self::once())
498
            ->method('generate')
499
            ->with($changelogConfig, $output);
500
501
        $this->application->run($input, $output);
502
    }
503
504
    public function testGenerateConfigOverrideNoLabels(): void
505
    {
506
        $input = new ArrayInput([
507
            'command'       => 'generate',
508
            '--user'        => 'doctrine',
509
            '--repository'  => 'migrations',
510
            '--milestone'   => '2.0',
511
            '--config'      => __DIR__ . '/_files/config.php',
512
            '--project'     => 'changelog-generator',
513
        ]);
514
515
        $output = $this->createMock(OutputInterface::class);
516
517
        $changelogConfig = new ChangelogConfig('doctrine', 'migrations', '2.0', ['Enhancement', 'Bug']);
518
519
        $this->changelogGenerator->expects(self::once())
520
            ->method('generate')
521
            ->with($changelogConfig, $output);
522
523
        $this->application->run($input, $output);
524
    }
525
526
    public function testCreateOutput(): void
527
    {
528
        $generateChangelogCommand = new GenerateChangelogCommandStub($this->changelogGenerator);
529
530
        $file = sprintf('%s/test.md', sys_get_temp_dir());
531
532
        self::assertInstanceOf(
533
            StreamOutput::class,
534
            $generateChangelogCommand->createOutputTest($file, GenerateChangelogCommand::WRITE_STRATEGY_APPEND)
535
        );
536
537
        self::assertInstanceOf(
538
            BufferedOutput::class,
539
            $generateChangelogCommand->createOutputTest($file, GenerateChangelogCommand::WRITE_STRATEGY_PREPEND)
540
        );
541
542
        self::assertInstanceOf(
543
            StreamOutput::class,
544
            $generateChangelogCommand->createOutputTest($file, GenerateChangelogCommand::WRITE_STRATEGY_REPLACE)
545
        );
546
547
        unlink($file);
548
    }
549
550
    public function testCreateOutputCouldNotOpenHandleInvalidArgumentException(): void
551
    {
552
        $this->expectException(InvalidArgumentException::class);
553
        $this->expectExceptionMessage('Could not open handle for /tmp/test.md');
554
555
        $file = sprintf('%s/test.md', sys_get_temp_dir());
556
557
        $generateChangelogCommand = $this->getMockBuilder(GenerateChangelogCommandStub::class)
558
            ->setConstructorArgs([$this->changelogGenerator])
559
            ->onlyMethods(['fopen'])
560
            ->getMock();
561
562
        $generateChangelogCommand->expects(self::once())
563
            ->method('fopen')
564
            ->with($file, 'a+')
565
            ->willReturn(false);
566
567
        $generateChangelogCommand->createOutputTest($file, GenerateChangelogCommand::WRITE_STRATEGY_APPEND);
568
    }
569
570
    protected function setUp(): void
571
    {
572
        $this->changelogGenerator = $this->createMock(ChangelogGenerator::class);
573
574
        $this->application = new Application('Changelog Generator', Versions::getVersion('jwage/changelog-generator'));
575
        $this->application->setAutoExit(false);
576
        $this->application->setCatchExceptions(false);
577
578
        $this->generateChangelogCommand = $this->getMockBuilder(GenerateChangelogCommand::class)
579
            ->setConstructorArgs([$this->changelogGenerator])
580
            ->onlyMethods(['createOutput'])
581
            ->getMock();
582
583
        $this->application->add($this->generateChangelogCommand);
584
    }
585
}
586
587
class GenerateChangelogCommandStub extends GenerateChangelogCommand
588
{
589
    public function createOutputTest(string $file, string $fileWriteStrategy): OutputInterface
590
    {
591
        return $this->createOutput($file, $fileWriteStrategy);
592
    }
593
}
594