1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Bundle\FrameworkBundle\Tests\Command;
13
14use PHPUnit\Framework\TestCase;
15use Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand;
16use Symfony\Bundle\FrameworkBundle\Console\Application;
17use Symfony\Component\Console\Application as BaseApplication;
18use Symfony\Component\Console\Helper\HelperSet;
19use Symfony\Component\Console\Input\InputDefinition;
20use Symfony\Component\Console\Output\OutputInterface;
21use Symfony\Component\Console\Tester\CommandTester;
22use Symfony\Component\HttpKernel\KernelInterface;
23
24/**
25 * Tests the YamlLintCommand.
26 *
27 * @author Robin Chalas <robin.chalas@gmail.com>
28 */
29class YamlLintCommandTest extends TestCase
30{
31    private $files;
32
33    public function testLintCorrectFile()
34    {
35        $tester = $this->createCommandTester();
36        $filename = $this->createFile('foo: bar');
37
38        $tester->execute(
39            ['filename' => $filename],
40            ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]
41        );
42
43        $this->assertEquals(0, $tester->getStatusCode(), 'Returns 0 in case of success');
44        $this->assertStringContainsString('OK', trim($tester->getDisplay()));
45    }
46
47    public function testLintIncorrectFile()
48    {
49        $incorrectContent = '
50foo:
51bar';
52        $tester = $this->createCommandTester();
53        $filename = $this->createFile($incorrectContent);
54
55        $tester->execute(['filename' => $filename], ['decorated' => false]);
56
57        $this->assertEquals(1, $tester->getStatusCode(), 'Returns 1 in case of error');
58        $this->assertStringContainsString('Unable to parse at line 3 (near "bar").', trim($tester->getDisplay()));
59    }
60
61    public function testLintFileNotReadable()
62    {
63        $this->expectException('RuntimeException');
64        $tester = $this->createCommandTester();
65        $filename = $this->createFile('');
66        unlink($filename);
67
68        $tester->execute(['filename' => $filename], ['decorated' => false]);
69    }
70
71    public function testGetHelp()
72    {
73        $command = new YamlLintCommand();
74        $expected = <<<EOF
75Or find all files in a bundle:
76
77  <info>php %command.full_name% @AcmeDemoBundle</info>
78EOF;
79
80        $this->assertStringContainsString($expected, $command->getHelp());
81    }
82
83    public function testLintFilesFromBundleDirectory()
84    {
85        $tester = $this->createCommandTester($this->getKernelAwareApplicationMock());
86        $tester->execute(
87            ['filename' => '@AppBundle/Resources'],
88            ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]
89        );
90
91        $this->assertEquals(0, $tester->getStatusCode(), 'Returns 0 in case of success');
92        $this->assertStringContainsString('[OK] All 0 YAML files contain valid syntax', trim($tester->getDisplay()));
93    }
94
95    /**
96     * @return string Path to the new file
97     */
98    private function createFile($content)
99    {
100        $filename = tempnam(sys_get_temp_dir().'/yml-lint-test', 'sf-');
101        file_put_contents($filename, $content);
102
103        $this->files[] = $filename;
104
105        return $filename;
106    }
107
108    /**
109     * @return CommandTester
110     */
111    private function createCommandTester($application = null)
112    {
113        if (!$application) {
114            $application = new BaseApplication();
115            $application->add(new YamlLintCommand());
116        }
117
118        $command = $application->find('lint:yaml');
119
120        if ($application) {
121            $command->setApplication($application);
122        }
123
124        return new CommandTester($command);
125    }
126
127    private function getKernelAwareApplicationMock()
128    {
129        $kernel = $this->getMockBuilder(KernelInterface::class)
130            ->disableOriginalConstructor()
131            ->getMock();
132
133        $kernel
134            ->expects($this->once())
135            ->method('locateResource')
136            ->with('@AppBundle/Resources')
137            ->willReturn(sys_get_temp_dir().'/yml-lint-test');
138
139        $application = $this->getMockBuilder(Application::class)
140            ->disableOriginalConstructor()
141            ->getMock();
142
143        $application
144            ->expects($this->once())
145            ->method('getKernel')
146            ->willReturn($kernel);
147
148        $application
149            ->expects($this->once())
150            ->method('getHelperSet')
151            ->willReturn(new HelperSet());
152
153        $application
154            ->expects($this->any())
155            ->method('getDefinition')
156            ->willReturn(new InputDefinition());
157
158        $application
159            ->expects($this->once())
160            ->method('find')
161            ->with('lint:yaml')
162            ->willReturn(new YamlLintCommand());
163
164        return $application;
165    }
166
167    protected function setUp()
168    {
169        @mkdir(sys_get_temp_dir().'/yml-lint-test');
170        $this->files = [];
171    }
172
173    protected function tearDown()
174    {
175        foreach ($this->files as $file) {
176            if (file_exists($file)) {
177                @unlink($file);
178            }
179        }
180        @rmdir(sys_get_temp_dir().'/yml-lint-test');
181    }
182}
183