diff --git a/.gitignore b/.gitignore index 7d5e145..fff9157 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .idea/ -composer.lock .phpcs.cache +.phpunit.cache +composer.lock +tests/coverage vendor/ \ No newline at end of file diff --git a/README.md b/README.md index 68b949f..0e1e6e0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ # Composer i18n Scripts Simplify the internationalization of your WordPress plugin or theme using WP-CLI — powered by Composer. + diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 0ad9c3e..9d8a25f 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,4 +1,4 @@ parameters: - level: 8 + level: 10 paths: - src/ diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 5e76c56..ce0df9c 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,25 @@ - - + + - + tests - \ No newline at end of file + + + + src + + + diff --git a/src/Commands/CreatePoCommand.php b/src/Commands/CreatePoCommand.php index 791c9a7..aac1f7c 100644 --- a/src/Commands/CreatePoCommand.php +++ b/src/Commands/CreatePoCommand.php @@ -18,6 +18,8 @@ */ class CreatePoCommand extends CustomCommand { + const DEFAULT_LANGUAGE = 'invalid_LOCALE'; + /** * Configures the command. */ @@ -54,6 +56,9 @@ protected function configure(): void { */ protected function command( I18nConfig $config, InputInterface $input ): string { $locale = $input->getArgument( 'locale' ); + if ( empty( $locale ) || ! is_string( $locale ) ) { + $locale = self::DEFAULT_LANGUAGE; + } return sprintf( 'if [ ! -e %1$s ]; then cp %2$s %1$s; fi', diff --git a/src/Commands/CustomCommand.php b/src/Commands/CustomCommand.php index 714be71..6b255e8 100644 --- a/src/Commands/CustomCommand.php +++ b/src/Commands/CustomCommand.php @@ -69,7 +69,10 @@ protected function execute( InputInterface $input, OutputInterface $output ): in $output->writeln( 'Running: ' . $command . '' ); - $this->runner->exec( $command, $output_lines, $exit_code ); + $output_lines = []; + $exit_code = 0; + + $this->runner->exec( $command, $output_lines, $exit_code ); foreach ( $output_lines as $line ) { $output->writeln( $line ); diff --git a/src/ShellRunner.php b/src/ShellRunner.php index b26470d..4869831 100644 --- a/src/ShellRunner.php +++ b/src/ShellRunner.php @@ -18,11 +18,11 @@ class ShellRunner { * Executes a shell command. * * @param string $command The command to execute. - * @param ?string[] $output The output in an array. - * @param ?int $result_code The result code of the command execution. + * @param string[] $output The output in an array. + * @param int $result_code The result code of the command execution. * @return void */ - public function exec( string $command, ?array &$output, ?int &$result_code ): void { + public function exec( string $command, array &$output, int &$result_code ): void { // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.system_calls_exec exec( $command, $output, $result_code ); } diff --git a/tests/Commands/CreatePoCommandTest.php b/tests/Commands/CreatePoCommandTest.php new file mode 100644 index 0000000..731a724 --- /dev/null +++ b/tests/Commands/CreatePoCommandTest.php @@ -0,0 +1,44 @@ +createMock(ShellRunner::class); + $runner->method('exec') + ->willReturnCallback(function ($cmd, &$output, &$exitCode) { + $output = ['Mocked .po creation']; + $exitCode = 0; + }); + + $command = new CreatePoCommand($runner); + + $this->application = new Application(); + $this->application->setAutoExit(false); // Important for tests + $this->application->add($command); + } + + public function testCommandIsRegisteredAndConfigured(): void { + $command = $this->application->find( 'i18n:create-po' ); + + $this->assertSame( 'i18n:create-po', $command->getName() ); + $this->assertNotEmpty( $command->getDescription() ); + $this->assertNotEmpty( $command->getHelp() ); + } +} diff --git a/tests/Commands/MakeJsonCommandTest.php b/tests/Commands/MakeJsonCommandTest.php new file mode 100644 index 0000000..d3e9192 --- /dev/null +++ b/tests/Commands/MakeJsonCommandTest.php @@ -0,0 +1,44 @@ +createMock(ShellRunner::class); + $runner->method('exec') + ->willReturnCallback(function ($cmd, &$output, &$exitCode) { + $output = ['Mocked .json generation']; + $exitCode = 0; + }); + + $command = new MakeJsonCommand($runner); + + $this->application = new Application(); + $this->application->setAutoExit(false); // Important for tests + $this->application->add($command); + } + + + public function testCommandIsRegisteredAndConfigured(): void { + $command = $this->application->find( 'i18n:make-json' ); + + $this->assertSame( 'i18n:make-json', $command->getName() ); + $this->assertNotEmpty( $command->getDescription() ); + $this->assertNotEmpty( $command->getHelp() ); + } +} diff --git a/tests/Commands/MakeMoCommandTest.php b/tests/Commands/MakeMoCommandTest.php new file mode 100644 index 0000000..d6e2594 --- /dev/null +++ b/tests/Commands/MakeMoCommandTest.php @@ -0,0 +1,43 @@ +createMock(ShellRunner::class); + $runner->method('exec') + ->willReturnCallback(function ($cmd, &$output, &$exitCode) { + $output = ['Mocked .mo generation']; + $exitCode = 0; + }); + + $command = new MakeMoCommand($runner); + + $this->application = new Application(); + $this->application->setAutoExit(false); // Important for tests + $this->application->add($command); + } + + public function testCommandIsRegisteredAndConfigured(): void { + $command = $this->application->find( 'i18n:make-mo' ); + + $this->assertSame( 'i18n:make-mo', $command->getName() ); + $this->assertNotEmpty( $command->getDescription() ); + $this->assertNotEmpty( $command->getHelp() ); + } +} diff --git a/tests/Commands/MakePhpCommandTest.php b/tests/Commands/MakePhpCommandTest.php new file mode 100644 index 0000000..0bc7c9f --- /dev/null +++ b/tests/Commands/MakePhpCommandTest.php @@ -0,0 +1,44 @@ +createMock(ShellRunner::class); + $runner->method('exec') + ->willReturnCallback(function ($cmd, &$output, &$exitCode) { + $output = ['Mocked .php generation']; + $exitCode = 0; + }); + + $command = new MakePhpCommand($runner); + + $this->application = new Application(); + $this->application->setAutoExit(false); // Important for tests + $this->application->add($command); + } + + public function testCommandIsRegisteredAndConfigured(): void { + $command = $this->application->find( 'i18n:make-php' ); + + $this->assertSame( 'i18n:make-php', $command->getName() ); + $this->assertNotEmpty( $command->getDescription() ); + $this->assertNotEmpty( $command->getHelp() ); + } +} diff --git a/tests/Commands/MakePotCommandTest.php b/tests/Commands/MakePotCommandTest.php index 9927185..2a10780 100644 --- a/tests/Commands/MakePotCommandTest.php +++ b/tests/Commands/MakePotCommandTest.php @@ -10,35 +10,35 @@ use lloc\ComposerI18nScripts\Commands\MakePotCommand; use lloc\ComposerI18nScripts\ShellRunner; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; -use Symfony\Component\Console\Tester\CommandTester; +#[CoversClass(MakePotCommand::class)] class MakePotCommandTest extends TestCase { - public function testCommandIsRegisteredAndConfigured(): void { - $runner = new ShellRunner(); - $application = new Application(); - $application->add( new MakePotCommand($runner) ); + protected Application $application; - $command = $application->find( 'i18n:make-pot' ); - $this->assertSame( 'i18n:make-pot', $command->getName() ); - $this->assertNotEmpty( $command->getDescription() ); - $this->assertNotEmpty( $command->getHelp() ); - } + protected function setUp(): void { + $runner = $this->createMock(ShellRunner::class); + $runner->method('exec') + ->willReturnCallback(function ($cmd, &$output, &$exitCode) { + $output = ['Mocked .pot generation']; + $exitCode = 0; + }); - public function testCommandExecutionReturnsSuccess(): void { - $runner = new ShellRunner(); - $application = new Application(); - $application->add( new MakePotCommand($runner) ); + $command = new MakePotCommand($runner); - $command = $application->find( 'i18n:make-pot' ); - $tester = new CommandTester( $command ); + $this->application = new Application(); + $this->application->setAutoExit(false); // Important for tests + $this->application->add($command); + } - // You may need to mock or override shell exec inside the command to make this testable - $tester->execute( array() ); + public function testCommandIsRegisteredAndConfigured(): void { + $command = $this->application->find( 'i18n:make-pot' ); - // Just test if it runs (for now) - $this->assertSame( 0, $tester->getStatusCode() ); + $this->assertSame( 'i18n:make-pot', $command->getName() ); + $this->assertNotEmpty( $command->getDescription() ); + $this->assertNotEmpty( $command->getHelp() ); } } diff --git a/tests/Commands/UpdatePoCommandTest.php b/tests/Commands/UpdatePoCommandTest.php new file mode 100644 index 0000000..2d4c3f7 --- /dev/null +++ b/tests/Commands/UpdatePoCommandTest.php @@ -0,0 +1,43 @@ +createMock(ShellRunner::class); + $runner->method('exec') + ->willReturnCallback(function ($cmd, &$output, &$exitCode) { + $output = ['Mocked .po update']; + $exitCode = 0; + }); + + $command = new UpdatePoCommand($runner); + + $this->application = new Application(); + $this->application->setAutoExit(false); // Important for tests + $this->application->add($command); + } + + public function testCommandIsRegisteredAndConfigured(): void { + $command = $this->application->find( 'i18n:update-po' ); + + $this->assertSame( 'i18n:update-po', $command->getName() ); + $this->assertNotEmpty( $command->getDescription() ); + $this->assertNotEmpty( $command->getHelp() ); + } +}