Skip to content

Commit

Permalink
feat: improve ratio list command (add option "format") (#161)
Browse files Browse the repository at this point in the history
* feat: improve RatioListCommand (add option "format")

* feat: improve RatioListCommand (add option "format")

* feat: improve RatioListCommand (add option "format")

* feat: improve RatioListCommand (add option "format")

---------

Co-authored-by: Christopher Georg <[email protected]>
Co-authored-by: Johan Wilfer <[email protected]>
  • Loading branch information
3 people authored Jan 31, 2024
1 parent f23eece commit b9dd869
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 11 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,8 @@ class IndexController extends Controller

# display ratio list
./bin/console tbbc:money:ratio-list
./bin/console tbbc:money:ratio-list --format=table
./bin/console tbbc:money:ratio-list --format=json

# fetch all the ratio for all defined currencies from an external API
./bin/console tbbc:money:ratio-fetch
Expand Down
35 changes: 35 additions & 0 deletions Tests/Command/RatioListCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,39 @@ public function testCanWriteRatioList(): void
$output = $tester->getDisplay();
self::assertStringContainsString('USD;1.2', $output);
}

public function testGetRatioListAsTable(): void
{
$data = ['EUR' => 1.1, 'USD' => 1.2];
$pairManager = $this->createMock(PairManagerInterface::class);
$pairManager
->expects($this->once())
->method('getRatioList')
->willReturn($data);

$command = new RatioListCommand($pairManager);
$tester = new CommandTester($command);
$tester->execute(['--format' => 'table']);
self::assertSame(Command::SUCCESS, $tester->getStatusCode());
self::assertStringContainsString('EUR | 1.1', $tester->getDisplay());
self::assertStringContainsString('USD | 1.2', $tester->getDisplay());
}

public function testGetRatioListAsJson(): void
{
$data = ['EUR' => 1.1, 'USD' => 1.2];
$pairManager = $this->createMock(PairManagerInterface::class);
$pairManager
->expects($this->once())
->method('getRatioList')
->willReturn($data);

$command = new RatioListCommand($pairManager);
$tester = new CommandTester($command);
$tester->execute(['--format' => 'json']);
self::assertSame(Command::SUCCESS, $tester->getStatusCode());
self::assertJson($tester->getDisplay());
$output = json_decode($tester->getDisplay(), true);
self::assertSame($data, $output);
}
}
93 changes: 82 additions & 11 deletions src/Command/RatioListCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@
namespace Tbbc\MoneyBundle\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Completion\Suggestion;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Tbbc\MoneyBundle\Pair\PairManagerInterface;

/**
* Class RatioListCommand.
*/
class RatioListCommand extends Command
{
private string $format = 'txt';

public function __construct(private PairManagerInterface $pairManager)
{
parent::__construct();
Expand All @@ -23,21 +29,86 @@ protected function configure(): void
{
$this
->setName('tbbc:money:ratio-list')
->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt')
->setHelp('The <info>tbbc:money:ratio-list</info> display list of registered ratio')
->setDescription('display list of registered ratio');
}

protected function execute(InputInterface $input, OutputInterface $output): int
/**
* @param array<string, float> $ratioList
*/
protected function displayTxt(array $ratioList, OutputInterface $output, SymfonyStyle $io): int
{
$ratioList = $this->pairManager->getRatioList();
$output->writeln('Ratio list');
/**
* @var float $ratio
*/
$io->writeln('Ratio list');

foreach ($ratioList as $currencyCode => $ratio) {
$output->writeln($currencyCode.';'.(string) $ratio);
$io->writeln($currencyCode.';'.(string) $ratio);
}

return Command::SUCCESS;
}

/**
* @param array<string, float> $ratioList
*/
protected function displayTable(array $ratioList, OutputInterface $output, SymfonyStyle $io): int
{
$table = new Table($io);
$table->setHeaderTitle('Ratio list');
$table->setHeaders(['Currency', 'Ratio']);

foreach ($ratioList as $currencyCode => $ratio) {
$table->addRow([$currencyCode, $ratio]);
}

$table->render();

return Command::SUCCESS;
}

/**
* @param array<string, float> $ratioList
*/
protected function displayJson(array $ratioList, OutputInterface $output): int
{
$output->writeln(json_encode($ratioList, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES));

return Command::SUCCESS;
}

private function display(OutputInterface $output, SymfonyStyle $io): int
{
$ratioList = $this->pairManager->getRatioList();

return match ($this->format) {
'txt' => $this->displayTxt($ratioList, $output, $io),
'json' => $this->displayJson($ratioList, $output),
'table' => $this->displayTable($ratioList, $output, $io),
default => throw new InvalidArgumentException(sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))),
};
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);

/** @var string $format */
$format = $input->getOption('format') ?? 'txt';
$this->format = $format;

return $this->display($output, $io);
}

public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
if ($input->mustSuggestOptionValuesFor('format')) {
$suggestions->suggestValues($this->getAvailableFormatOptions());
}
}

return 0;
/** @return list<string|Suggestion> $values */
private function getAvailableFormatOptions(): array
{
return ['txt', 'json', 'table'];
}
}
2 changes: 2 additions & 0 deletions src/Pair/PairManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public function getReferenceCurrencyCode(): string;
/**
* return ratio list for currencies in comparison to reference currency
* array of type array("EUR" => 1, "USD" => 1.25);.
*
* @return array<string, float>
*/
public function getRatioList(): array;

Expand Down

0 comments on commit b9dd869

Please sign in to comment.