<commit_before><?php
declare(strict_types=1);

namespace PerFiFeatureTest\Domain;

use Behat\Behat\Context\Context;
use Behat\Behat\Tester\Exception\PendingException;

class TransactionContext implements Context
{
    /**
     * @Given I have an :type account called :title
     */
    public function iHaveAnAccountOfCertianTypeCalled($type, $title)
    {
        throw new PendingException();
    }

    /**
     * @When :amount :currency is payed for :description from :source to :destination
     */
    public function anAmountInCurrencyIsPayedForSomething($amount, $currency, $description, $source, $destination)
    {
        throw new PendingException();
    }

    /**
     * @When :amount :currency is charged for :description from :source to :destination
     */
    public function anAmountInCurrencyIsChargedForSomething($amount, $currency, $description, $source, $destination)
    {
        throw new PendingException();
    }

    /**
     * @Then I should have :amount :currency funds less in :title :type account
     */
    public function iShouldHaveLessFundsInSourceAccount($amount, $currency, $title, $type)
    {
        throw new PendingException();
    }

    /**
     * @Then I should have :amount :currency funds more in :title :type account
     */
    public function iShouldHaveMoreFundsInDestinationAccount($amount, $currency, $title, $type)
    {
        throw new PendingException();
    }
}<commit_msg>Test paying and charging between accounts scenarios<commit_after><?php
declare(strict_types=1);

namespace PerFiFeatureTest\Domain;

use Behat\Behat\Context\Context;
use PerFi\Application\Transaction\InMemoryTransactionRepository;
use PerFi\Domain\Account\Account;
use PerFi\Domain\MoneyFactory;
use PerFi\Domain\Transaction\CommandHandler\ExecuteTransaction as ExecuteTransactionHandler;
use PerFi\Domain\Transaction\Command\ExecuteTransaction as ExecuteTransactionCommand;
use Webmozart\Assert\Assert;

class TransactionContext implements Context
{

    /**
     * @var array
     */
    private $accounts;

    /** @BeforeScenario */
    public function setup()
    {
        $this->accounts = [];
    }

    /**
     * @Given I have an :type account called :title
     */
    public function iHaveAnAccountOfCertianTypeCalled($type, $title)
    {
        $hash = $this->hashAccountTitle($title);
        $this->accounts[$hash] = Account::byStringType($type, $title);
    }

    /**
     * @When :amount :currency is payed for :description from :source to :destination
     */
    public function anAmountInCurrencyIsPayedForSomething($amount, $currency, $description, $source, $destination)
    {
        $repository = new InMemoryTransactionRepository();
        $sourceAccount = $this->getAccountByTitle($source);
        $destinationAccount = $this->getAccountByTitle($destination);
        $amount = MoneyFactory::amountInCurrency($amount, $currency);
        $this->command = new ExecuteTransactionCommand(
            $sourceAccount,
            $destinationAccount,
            $amount,
            $description
        );
        $commandHandler = new ExecuteTransactionHandler($repository);
        $commandHandler->__invoke($this->command);
    }

    /**
     * @When :amount :currency is charged for :description from :source to :destination
     */
    public function anAmountInCurrencyIsChargedForSomething($amount, $currency, $description, $source, $destination)
    {
        $repository = new InMemoryTransactionRepository();
        $sourceAccount = $this->getAccountByTitle($source);
        $destinationAccount = $this->getAccountByTitle($destination);
        $amount = MoneyFactory::amountInCurrency($amount, $currency);
        $this->command = new ExecuteTransactionCommand(
            $sourceAccount,
            $destinationAccount,
            $amount,
            $description
        );
        $commandHandler = new ExecuteTransactionHandler($repository);
        $commandHandler->__invoke($this->command);
    }

    /**
     * @Then I should have :amount :currency funds less in :title :type account
     */
    public function iShouldHaveLessFundsInSourceAccount($amount, $currency, $title, $type)
    {
        $expected = MoneyFactory::amountInCurrency('-' . $amount, $currency);

        $transaction = $this->command->payload();
        $sourceAccount = $transaction->sourceAccount();

        $balances = $sourceAccount->balances();

        foreach ($balances as $result) {
            if ((string) $result->getCurrency() === $currency) {
                Assert::same($result->getAmount(), $expected->getAmount());
                Assert::same((string) $result->getCurrency(), (string) $expected->getCurrency());
            }
        }
    }

    /**
     * @Then I should have :amount :currency funds more in :title :type account
     */
    public function iShouldHaveMoreFundsInDestinationAccount($amount, $currency, $title, $type)
    {
        $expected = MoneyFactory::amountInCurrency($amount, $currency);

        $transaction = $this->command->payload();
        $destinationAccount = $transaction->destinationAccount();

        $balances = $destinationAccount->balances();

        foreach ($balances as $result) {
            if ((string) $result->getCurrency() === $currency) {
                Assert::same($result->getAmount(), $expected->getAmount());
                Assert::same((string) $result->getCurrency(), (string) $expected->getCurrency());
            }
        }
    }

    private function getAccountByTitle($title)
    {
        $hash = $this->hashAccountTitle($title);
        return $this->accounts[$hash];
    }

    private function hashAccountTitle($title)
    {
        return trim(strtolower($title));
    }
}
{'fraction_non_alphanumeric': 0.12122270742358078, 'fraction_numerical': 0.00034934497816593884, 'mean_word_length': 3.1017191977077365, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6738626', 'n_tokens_mistral': 1506, 'n_tokens_neox': 1493, 'n_words': 342}