PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Symfony/Component/Translation/Tests/Command/XliffLintCommandTest.php

https://github.com/FabienD/symfony
PHP | 269 lines | 197 code | 53 blank | 19 comment | 3 complexity | b6cfee992d4ecd8c41cc640eaee69175 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Translation\Tests\Command;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\Console\Application;
  13. use Symfony\Component\Console\Command\Command;
  14. use Symfony\Component\Console\Output\OutputInterface;
  15. use Symfony\Component\Console\Tester\CommandCompletionTester;
  16. use Symfony\Component\Console\Tester\CommandTester;
  17. use Symfony\Component\Translation\Command\XliffLintCommand;
  18. /**
  19. * Tests the XliffLintCommand.
  20. *
  21. * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  22. */
  23. class XliffLintCommandTest extends TestCase
  24. {
  25. private $files;
  26. public function testLintCorrectFile()
  27. {
  28. $tester = $this->createCommandTester();
  29. $filename = $this->createFile();
  30. $tester->execute(
  31. ['filename' => $filename],
  32. ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]
  33. );
  34. $tester->assertCommandIsSuccessful('Returns 0 in case of success');
  35. $this->assertStringContainsString('OK', trim($tester->getDisplay()));
  36. }
  37. public function testLintCorrectFiles()
  38. {
  39. $tester = $this->createCommandTester();
  40. $filename1 = $this->createFile();
  41. $filename2 = $this->createFile();
  42. $tester->execute(
  43. ['filename' => [$filename1, $filename2]],
  44. ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]
  45. );
  46. $tester->assertCommandIsSuccessful('Returns 0 in case of success');
  47. $this->assertStringContainsString('OK', trim($tester->getDisplay()));
  48. }
  49. /**
  50. * @dataProvider provideStrictFilenames
  51. */
  52. public function testStrictFilenames($requireStrictFileNames, $fileNamePattern, $targetLanguage, $mustFail)
  53. {
  54. $tester = $this->createCommandTester($requireStrictFileNames);
  55. $filename = $this->createFile('note', $targetLanguage, $fileNamePattern);
  56. $tester->execute(
  57. ['filename' => $filename],
  58. ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]
  59. );
  60. $this->assertEquals($mustFail ? 1 : 0, $tester->getStatusCode());
  61. $this->assertStringContainsString($mustFail ? '[WARNING] 0 XLIFF files have valid syntax and 1 contain errors.' : '[OK] All 1 XLIFF files contain valid syntax.', $tester->getDisplay());
  62. }
  63. public function testLintIncorrectXmlSyntax()
  64. {
  65. $tester = $this->createCommandTester();
  66. $filename = $this->createFile('note <target>');
  67. $tester->execute(['filename' => $filename], ['decorated' => false]);
  68. $this->assertEquals(1, $tester->getStatusCode(), 'Returns 1 in case of error');
  69. $this->assertStringContainsString('Opening and ending tag mismatch: target line 6 and source', trim($tester->getDisplay()));
  70. }
  71. public function testLintIncorrectTargetLanguage()
  72. {
  73. $tester = $this->createCommandTester();
  74. $filename = $this->createFile('note', 'es');
  75. $tester->execute(['filename' => $filename], ['decorated' => false]);
  76. $this->assertEquals(1, $tester->getStatusCode(), 'Returns 1 in case of error');
  77. $this->assertStringContainsString('There is a mismatch between the language included in the file name ("messages.en.xlf") and the "es" value used in the "target-language" attribute of the file.', trim($tester->getDisplay()));
  78. }
  79. public function testLintTargetLanguageIsCaseInsensitive()
  80. {
  81. $tester = $this->createCommandTester();
  82. $filename = $this->createFile('note', 'zh-cn', 'messages.zh_CN.xlf');
  83. $tester->execute(['filename' => $filename], ['decorated' => false]);
  84. $tester->assertCommandIsSuccessful();
  85. $this->assertStringContainsString('[OK] All 1 XLIFF files contain valid syntax.', trim($tester->getDisplay()));
  86. }
  87. public function testLintSucceedsWhenLocaleInFileAndInTargetLanguageNameUsesDashesInsteadOfUnderscores()
  88. {
  89. $tester = $this->createCommandTester();
  90. $filename = $this->createFile('note', 'en-GB', 'messages.en-GB.xlf');
  91. $tester->execute(['filename' => $filename], ['decorated' => false]);
  92. $tester->assertCommandIsSuccessful();
  93. $this->assertStringContainsString('[OK] All 1 XLIFF files contain valid syntax.', trim($tester->getDisplay()));
  94. }
  95. public function testLintFileNotReadable()
  96. {
  97. $this->expectException(\RuntimeException::class);
  98. $tester = $this->createCommandTester();
  99. $filename = $this->createFile();
  100. unlink($filename);
  101. $tester->execute(['filename' => $filename], ['decorated' => false]);
  102. }
  103. public function testGetHelp()
  104. {
  105. $command = new XliffLintCommand();
  106. $expected = <<<EOF
  107. Or of a whole directory:
  108. <info>php %command.full_name% dirname</info>
  109. <info>php %command.full_name% dirname --format=json</info>
  110. EOF;
  111. $this->assertStringContainsString($expected, $command->getHelp());
  112. }
  113. public function testLintIncorrectFileWithGithubFormat()
  114. {
  115. $filename = $this->createFile('note <target>');
  116. $tester = $this->createCommandTester();
  117. $tester->execute(['filename' => [$filename], '--format' => 'github'], ['decorated' => false]);
  118. self::assertEquals(1, $tester->getStatusCode(), 'Returns 1 in case of error');
  119. self::assertStringMatchesFormat('%A::error file=%s,line=6,col=47::Opening and ending tag mismatch: target line 6 and source%A', trim($tester->getDisplay()));
  120. }
  121. public function testLintAutodetectsGithubActionEnvironment()
  122. {
  123. $prev = getenv('GITHUB_ACTIONS');
  124. putenv('GITHUB_ACTIONS');
  125. try {
  126. putenv('GITHUB_ACTIONS=1');
  127. $filename = $this->createFile('note <target>');
  128. $tester = $this->createCommandTester();
  129. $tester->execute(['filename' => [$filename]], ['decorated' => false]);
  130. self::assertStringMatchesFormat('%A::error file=%s,line=6,col=47::Opening and ending tag mismatch: target line 6 and source%A', trim($tester->getDisplay()));
  131. } finally {
  132. putenv('GITHUB_ACTIONS'.($prev ? "=$prev" : ''));
  133. }
  134. }
  135. public function testPassingClosureAndCallableToConstructor()
  136. {
  137. $command = new XliffLintCommand('translation:xliff:lint',
  138. $this->testPassingClosureAndCallableToConstructor(...),
  139. [$this, 'testPassingClosureAndCallableToConstructor']
  140. );
  141. self::assertInstanceOf(XliffLintCommand::class, $command);
  142. }
  143. private function createFile($sourceContent = 'note', $targetLanguage = 'en', $fileNamePattern = 'messages.%locale%.xlf'): string
  144. {
  145. $xliffContent = <<<XLIFF
  146. <?xml version="1.0"?>
  147. <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  148. <file source-language="en" target-language="$targetLanguage" datatype="plaintext" original="file.ext">
  149. <body>
  150. <trans-unit id="note">
  151. <source>$sourceContent</source>
  152. <target>NOTE</target>
  153. </trans-unit>
  154. </body>
  155. </file>
  156. </xliff>
  157. XLIFF;
  158. $filename = sprintf('%s/translation-xliff-lint-test/%s', sys_get_temp_dir(), str_replace('%locale%', 'en', $fileNamePattern));
  159. file_put_contents($filename, $xliffContent);
  160. $this->files[] = $filename;
  161. return $filename;
  162. }
  163. private function createCommand($requireStrictFileNames = true, $application = null): Command
  164. {
  165. if (!$application) {
  166. $application = new Application();
  167. $application->add(new XliffLintCommand(null, null, null, $requireStrictFileNames));
  168. }
  169. $command = $application->find('lint:xliff');
  170. if ($application) {
  171. $command->setApplication($application);
  172. }
  173. return $command;
  174. }
  175. private function createCommandTester($requireStrictFileNames = true, $application = null): CommandTester
  176. {
  177. return new CommandTester($this->createCommand($requireStrictFileNames, $application));
  178. }
  179. protected function setUp(): void
  180. {
  181. $this->files = [];
  182. @mkdir(sys_get_temp_dir().'/translation-xliff-lint-test');
  183. }
  184. protected function tearDown(): void
  185. {
  186. foreach ($this->files as $file) {
  187. if (file_exists($file)) {
  188. @unlink($file);
  189. }
  190. }
  191. @rmdir(sys_get_temp_dir().'/translation-xliff-lint-test');
  192. }
  193. public function provideStrictFilenames()
  194. {
  195. yield [false, 'messages.%locale%.xlf', 'en', false];
  196. yield [false, 'messages.%locale%.xlf', 'es', true];
  197. yield [false, '%locale%.messages.xlf', 'en', false];
  198. yield [false, '%locale%.messages.xlf', 'es', true];
  199. yield [true, 'messages.%locale%.xlf', 'en', false];
  200. yield [true, 'messages.%locale%.xlf', 'es', true];
  201. yield [true, '%locale%.messages.xlf', 'en', true];
  202. yield [true, '%locale%.messages.xlf', 'es', true];
  203. }
  204. /**
  205. * @dataProvider provideCompletionSuggestions
  206. */
  207. public function testComplete(array $input, array $expectedSuggestions)
  208. {
  209. $tester = new CommandCompletionTester($this->createCommand());
  210. $this->assertSame($expectedSuggestions, $tester->complete($input));
  211. }
  212. public function provideCompletionSuggestions()
  213. {
  214. yield 'option' => [['--format', ''], ['txt', 'json', 'github']];
  215. }
  216. }