1
0
Fork 0
get-installer-bootstrap/tests/Command/SyncScriptMappingsCommandTest.php
2026-05-05 11:14:04 +02:00

139 lines
5.7 KiB
PHP

<?php
namespace App\Tests\Command;
use App\Entity\ScriptMapping;
use App\Tests\DatabaseWebTestCase;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Process\Process;
final class SyncScriptMappingsCommandTest extends DatabaseWebTestCase
{
private Filesystem $filesystem;
private string $workDir;
protected function setUp(): void
{
parent::setUp();
$this->filesystem = new Filesystem();
$this->workDir = sys_get_temp_dir().'/get-installer-bootstrap-command-test-'.bin2hex(random_bytes(6));
$this->filesystem->mkdir($this->workDir);
}
protected function tearDown(): void
{
$this->filesystem->remove($this->workDir);
parent::tearDown();
}
public function testCommandSynchronizesEveryMapping(): void
{
$firstRepositoryDir = $this->createRepository('first', [
'install.sh' => "#!/usr/bin/env bash\nprintf 'first'\n",
]);
$secondRepositoryDir = $this->createRepository('second', [
'install.sh' => "#!/usr/bin/env bash\nprintf 'second'\n",
]);
$firstMapping = $this->mapping('mcp/first/install.sh', $firstRepositoryDir);
$secondMapping = $this->mapping('mcp/second/install.sh', $secondRepositoryDir);
$this->entityManager->persist($firstMapping);
$this->entityManager->persist($secondMapping);
$this->entityManager->flush();
$application = new Application(static::$kernel);
self::assertTrue($application->has('app:mappings:sync'));
$commandTester = new CommandTester($application->find('app:mappings:sync'));
$commandTester->execute([]);
self::assertSame(0, $commandTester->getStatusCode());
self::assertStringContainsString('2 mapping(s) synchronized, 0 failed.', $commandTester->getDisplay());
$this->entityManager->clear();
$syncedFirstMapping = $this->entityManager->getRepository(ScriptMapping::class)->find($firstMapping->getId());
$syncedSecondMapping = $this->entityManager->getRepository(ScriptMapping::class)->find($secondMapping->getId());
self::assertInstanceOf(ScriptMapping::class, $syncedFirstMapping);
self::assertInstanceOf(ScriptMapping::class, $syncedSecondMapping);
self::assertSame(ScriptMapping::SYNC_STATUS_SYNCED, $syncedFirstMapping->getLastSyncStatus());
self::assertSame(ScriptMapping::SYNC_STATUS_SYNCED, $syncedSecondMapping->getLastSyncStatus());
}
public function testCommandContinuesAfterMappingFailureAndReturnsFailure(): void
{
$failingRepositoryDir = $this->createRepository('failing', [
'install.sh' => "#!/usr/bin/env bash\nprintf 'missing target'\n",
]);
$workingRepositoryDir = $this->createRepository('working', [
'install.sh' => "#!/usr/bin/env bash\nprintf 'working'\n",
]);
$failingMapping = $this->mapping('mcp/a-failing/install.sh', $failingRepositoryDir)
->setRepositoryFilePath('missing.sh');
$workingMapping = $this->mapping('mcp/b-working/install.sh', $workingRepositoryDir);
$this->entityManager->persist($failingMapping);
$this->entityManager->persist($workingMapping);
$this->entityManager->flush();
$application = new Application(static::$kernel);
self::assertTrue($application->has('app:mappings:sync'));
$commandTester = new CommandTester($application->find('app:mappings:sync'));
$commandTester->execute([]);
self::assertSame(1, $commandTester->getStatusCode());
self::assertStringContainsString('1 mapping(s) synchronized, 1 failed.', $commandTester->getDisplay());
$this->entityManager->clear();
$syncedFailingMapping = $this->entityManager->getRepository(ScriptMapping::class)->find($failingMapping->getId());
$syncedWorkingMapping = $this->entityManager->getRepository(ScriptMapping::class)->find($workingMapping->getId());
self::assertInstanceOf(ScriptMapping::class, $syncedFailingMapping);
self::assertInstanceOf(ScriptMapping::class, $syncedWorkingMapping);
self::assertSame(ScriptMapping::SYNC_STATUS_FAILED, $syncedFailingMapping->getLastSyncStatus());
self::assertSame(ScriptMapping::SYNC_STATUS_SYNCED, $syncedWorkingMapping->getLastSyncStatus());
}
private function mapping(string $publicPath, string $repositoryDir): ScriptMapping
{
return (new ScriptMapping())
->setPublicPath($publicPath)
->setRepositoryUrl($repositoryDir)
->setGitRef('main')
->setRepositoryFilePath('install.sh')
->setActive(true);
}
/** @param array<string, string> $files */
private function createRepository(string $name, array $files): string
{
$repositoryDir = $this->workDir.'/'.$name;
$this->filesystem->mkdir($repositoryDir);
foreach ($files as $path => $content) {
$fullPath = $repositoryDir.'/'.$path;
$this->filesystem->mkdir(dirname($fullPath));
file_put_contents($fullPath, $content);
}
$this->runGit(['init'], $repositoryDir);
$this->runGit(['config', 'user.email', 'tests@example.com'], $repositoryDir);
$this->runGit(['config', 'user.name', 'Tests'], $repositoryDir);
$this->runGit(['add', '.'], $repositoryDir);
$this->runGit(['commit', '-m', 'Initial commit'], $repositoryDir);
$this->runGit(['branch', '-M', 'main'], $repositoryDir);
return $repositoryDir;
}
/** @param list<string> $arguments */
private function runGit(array $arguments, string $cwd): void
{
(new Process(['git', ...$arguments], $cwd))->mustRun();
}
}