Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/wiki
Submodule wiki updated from 5cea16 to 936be0
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"ecs",
"fast-forward"
],
"readme": "README.md",
"authors": [
{
"name": "Felipe Sayão Lobato Abreu",
Expand Down
7 changes: 7 additions & 0 deletions src/Console/Command/UpdateComposerJsonCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Composer\Command\BaseCommand;
use Composer\Factory;
use Composer\Json\JsonManipulator;
use FastForward\DevTools\Composer\Json\ComposerJsonInterface;
use FastForward\DevTools\Filesystem\FilesystemInterface;
use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Console\Attribute\AsCommand;
Expand All @@ -45,10 +46,12 @@ final class UpdateComposerJsonCommand extends BaseCommand
/**
* Creates a new UpdateComposerJsonCommand instance.
*
* @param ComposerJsonInterface $composer the composer.json metadata accessor
* @param FilesystemInterface $filesystem the filesystem used to read and write composer.json
* @param FileLocatorInterface $fileLocator the locator used to resolve packaged configuration files
*/
public function __construct(
private readonly ComposerJsonInterface $composer,
private readonly FilesystemInterface $filesystem,
private readonly FileLocatorInterface $fileLocator,
) {
Expand Down Expand Up @@ -95,6 +98,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$manipulator->addSubNode('scripts', $name, $command);
}

if ('' === $this->composer->getReadme() && $this->filesystem->exists('README.md', \dirname($file))) {
$manipulator->addProperty('readme', 'README.md');
}

$manipulator->addSubNode('extra', 'grumphp', [
'config-default-path' => Path::makeRelative($grumphpConfig, getcwd()),
], true);
Expand Down
106 changes: 105 additions & 1 deletion tests/Console/Command/UpdateComposerJsonCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

namespace FastForward\DevTools\Tests\Console\Command;

use FastForward\DevTools\Composer\Json\ComposerJsonInterface;
use FastForward\DevTools\Console\Command\UpdateComposerJsonCommand;
use FastForward\DevTools\Filesystem\FilesystemInterface;
use PHPUnit\Framework\Attributes\CoversClass;
Expand All @@ -32,13 +33,17 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

use function Safe\json_decode;

#[CoversClass(UpdateComposerJsonCommand::class)]
final class UpdateComposerJsonCommandTest extends TestCase
{
use ProphecyTrait;

private ObjectProphecy $filesystem;

private ObjectProphecy $composer;

private ObjectProphecy $fileLocator;

private ObjectProphecy $input;
Expand All @@ -52,12 +57,17 @@ final class UpdateComposerJsonCommandTest extends TestCase
*/
protected function setUp(): void
{
$this->composer = $this->prophesize(ComposerJsonInterface::class);
$this->filesystem = $this->prophesize(FilesystemInterface::class);
$this->fileLocator = $this->prophesize(FileLocatorInterface::class);
$this->input = $this->prophesize(InputInterface::class);
$this->output = $this->prophesize(OutputInterface::class);

$this->command = new UpdateComposerJsonCommand($this->filesystem->reveal(), $this->fileLocator->reveal());
$this->command = new UpdateComposerJsonCommand(
$this->composer->reveal(),
$this->filesystem->reveal(),
$this->fileLocator->reveal(),
);
}

/**
Expand Down Expand Up @@ -89,6 +99,10 @@ public function executeWillUpdateComposerJsonScriptsAndExtraConfiguration(): voi
->willReturn(true);
$this->filesystem->readFile('/app/composer.json')
->willReturn('{"name":"example/package"}');
$this->composer->getReadme()
->willReturn('');
$this->filesystem->exists('README.md', '/app')
->willReturn(false);
$this->fileLocator->locate('grumphp.yml', Argument::type('string'))
->willReturn('/app/vendor/fast-forward/dev-tools/grumphp.yml');
$this->filesystem->dumpFile(
Expand All @@ -100,6 +114,96 @@ public function executeWillUpdateComposerJsonScriptsAndExtraConfiguration(): voi
self::assertSame(UpdateComposerJsonCommand::SUCCESS, $this->executeCommand());
}

/**
* @return void
*/
#[Test]
public function executeWillAddReadmeMetadataWhenReadmeExistsAndComposerJsonDoesNotDeclareReadme(): void
{
$this->input->getOption('file')
->willReturn('/app/composer.json');
$this->filesystem->exists('/app/composer.json')
->willReturn(true);
$this->filesystem->readFile('/app/composer.json')
->willReturn('{"name":"example/package"}');
$this->composer->getReadme()
->willReturn('');
$this->filesystem->exists('README.md', '/app')
->willReturn(true);
$this->fileLocator->locate('grumphp.yml', Argument::type('string'))
->willReturn('/app/vendor/fast-forward/dev-tools/grumphp.yml');
$this->filesystem->dumpFile(
'/app/composer.json',
Argument::that(static function (string $contents): bool {
$composerJson = json_decode($contents, true);

return 'README.md' === $composerJson['readme'];
}),
)->shouldBeCalledOnce();

self::assertSame(UpdateComposerJsonCommand::SUCCESS, $this->executeCommand());
}

/**
* @return void
*/
#[Test]
public function executeWillPreserveExistingReadmeMetadata(): void
{
$this->input->getOption('file')
->willReturn('/app/composer.json');
$this->filesystem->exists('/app/composer.json')
->willReturn(true);
$this->filesystem->readFile('/app/composer.json')
->willReturn('{"name":"example/package","readme":"docs/readme.md"}');
$this->composer->getReadme()
->willReturn('docs/readme.md');
$this->filesystem->exists('README.md', '/app')
->shouldNotBeCalled();
$this->fileLocator->locate('grumphp.yml', Argument::type('string'))
->willReturn('/app/vendor/fast-forward/dev-tools/grumphp.yml');
$this->filesystem->dumpFile(
'/app/composer.json',
Argument::that(static function (string $contents): bool {
$composerJson = json_decode($contents, true);

return 'docs/readme.md' === $composerJson['readme'];
}),
)->shouldBeCalledOnce();

self::assertSame(UpdateComposerJsonCommand::SUCCESS, $this->executeCommand());
}

/**
* @return void
*/
#[Test]
public function executeWillSkipReadmeMetadataWhenReadmeDoesNotExist(): void
{
$this->input->getOption('file')
->willReturn('/app/composer.json');
$this->filesystem->exists('/app/composer.json')
->willReturn(true);
$this->filesystem->readFile('/app/composer.json')
->willReturn('{"name":"example/package"}');
$this->composer->getReadme()
->willReturn('');
$this->filesystem->exists('README.md', '/app')
->willReturn(false);
$this->fileLocator->locate('grumphp.yml', Argument::type('string'))
->willReturn('/app/vendor/fast-forward/dev-tools/grumphp.yml');
$this->filesystem->dumpFile(
'/app/composer.json',
Argument::that(static function (string $contents): bool {
$composerJson = json_decode($contents, true);

return ! \array_key_exists('readme', $composerJson);
}),
)->shouldBeCalledOnce();

self::assertSame(UpdateComposerJsonCommand::SUCCESS, $this->executeCommand());
}

/**
* @return int
*/
Expand Down
Loading