Skip to content

Commit

Permalink
100% test coverage (#48)
Browse files Browse the repository at this point in the history
* restored test coverage constraint in CI workflow

* 100% test coverage in app folder

* 100% test coverage in domain folder
  • Loading branch information
osteel authored May 29, 2023
1 parent 08758c1 commit a9b2c2a
Show file tree
Hide file tree
Showing 30 changed files with 365 additions and 143 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,12 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
coverage: xdebug

- name: Install composer dependencies
uses: ramsey/composer-install@v2
with:
dependency-versions: ${{ matrix.dependency-versions }}

- name: Run test suite
run: vendor/bin/pest --coverage
run: vendor/bin/pest --coverage --min=100
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,8 @@
namespace App\Aggregates\TaxYear\Repositories;

use Domain\Aggregates\TaxYear\Repositories\TaxYearMessageRepository as TaxYearMessageRepositoryInterface;
use Domain\Aggregates\TaxYear\ValueObjects\TaxYearId;
use EventSauce\MessageRepository\IlluminateMessageRepository\IlluminateUuidV4MessageRepository;
use Generator;

final class TaxYearMessageRepository extends IlluminateUuidV4MessageRepository implements TaxYearMessageRepositoryInterface
{
public function all(TaxYearId $taxYearId): Generator
{
return $this->retrieveAll($taxYearId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ protected static function newFactory(): SharePoolingAssetAcquisitionFactory
return SharePoolingAssetAcquisitionFactory::new();
}

public function averageCostBasisPerUnit(): ?FiatAmount
public function averageCostBasisPerUnit(): FiatAmount
{
return $this->costBasis->dividedBy($this->quantity);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ public static function make(SharePoolingAssetTransaction ...$transactions): self
return new self(array_values($transactions));
}

/** @return Traversable<int, SharePoolingAssetTransaction> */
/**
* @return Traversable<int, SharePoolingAssetTransaction>
*
* @codeCoverageIgnore
*/
public function getIterator(): Traversable
{
return new ArrayIterator($this->transactions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,7 @@ private static function processAcquisitionsWithinThirtyDays(

$averageCostBasisPerUnit = $acquisition->averageCostBasisPerUnit();

$costBasis = $averageCostBasisPerUnit
? $costBasis->plus($averageCostBasisPerUnit->multipliedBy($thirtyDayQuantityToApply))
: $costBasis;
$costBasis = $costBasis->plus($averageCostBasisPerUnit->multipliedBy($thirtyDayQuantityToApply));

$thirtyDayQuantityAllocation->allocateQuantity($thirtyDayQuantityToApply, $acquisition);
$acquisition->increaseThirtyDayQuantity($thirtyDayQuantityToApply);
Expand Down

This file was deleted.

6 changes: 1 addition & 5 deletions domain/src/Aggregates/TaxYear/Projections/TaxYearSummary.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace Domain\Aggregates\TaxYear\Projections;

use Domain\Aggregates\TaxYear\Projections\Exceptions\TaxYearSummaryException;
use Domain\Enums\FiatCurrency;
use Domain\Aggregates\TaxYear\ValueObjects\TaxYearId;
use Domain\Aggregates\TaxYear\ValueObjects\CapitalGain;
Expand Down Expand Up @@ -63,16 +62,13 @@ protected function currency(): Attribute
);
}

/** @throws TaxYearSummaryException */
protected function capitalGain(): Attribute
{
return Attribute::make(
get: function (?string $value) {
$values = is_null($value) ? [] : json_decode($value, true);

if (! is_array($values)) {
throw TaxYearSummaryException::invalidCapitalGainValues($value);
}
assert(is_array($values));

return new CapitalGain(
costBasis: new FiatAmount($values['cost_basis'] ?? '0', $this->currency),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@

namespace Domain\Aggregates\TaxYear\Repositories;

use Domain\Aggregates\TaxYear\ValueObjects\TaxYearId;
use Generator;

interface TaxYearMessageRepository
{
public function all(TaxYearId $taxYearId): Generator;
}
2 changes: 1 addition & 1 deletion domain/src/Services/Math/Math.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static function add(string ...$operands): string
*/
public static function sub(string ...$operands): string
{
if (is_null($initial = array_shift($operands))) {
if (strlen($initial = (string) array_shift($operands)) === 0) {
return '0';
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Domain\Aggregates\TaxYear\Actions\UpdateNonAttributableAllowableCost;
use Domain\Services\ActionRunner\ActionRunner;
use Domain\Services\TransactionDispatcher\Handlers\Exceptions\TransferHandlerException;
use Domain\ValueObjects\Transactions\Transfer;

class TransferHandler
Expand All @@ -15,7 +14,6 @@ public function __construct(private readonly ActionRunner $runner)
{
}

/** @throws TransferHandlerException */
public function handle(Transfer $transaction): void
{
if (is_null($transaction->fee)) {
Expand Down
2 changes: 1 addition & 1 deletion domain/src/ValueObjects/Fee.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ public function isFiat(): bool

public function __toString(): string
{
return sprintf('%s %s', (string) $this->currency, $this->quantity);
return sprintf('%s %s (market value: %s)', $this->currency, $this->quantity, $this->marketValue);
}
}
2 changes: 1 addition & 1 deletion domain/src/ValueObjects/FiatAmount.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,6 @@ private function assertCurrenciesMatch(FiatAmount ...$fiatAmounts): void

public function __toString(): string
{
return sprintf('%s%s', $this->currency->symbol(), (string) $this->quantity);
return sprintf('%s%s', $this->currency->symbol(), $this->quantity);
}
}
14 changes: 8 additions & 6 deletions domain/src/ValueObjects/Transactions/Acquisition.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
{
/** @throws AcquisitionException */
public function __construct(
public LocalDate $date,
LocalDate $date,
public Asset $asset,
public Quantity $quantity,
public FiatAmount $marketValue,
public ?Fee $fee = null,
?Fee $fee = null,
public bool $isIncome = false,
) {
parent::__construct($date, $fee);

! $asset->isFiat() || throw AcquisitionException::isFiat($this);
}

Expand All @@ -45,13 +47,13 @@ public function __toString(): string
{
return sprintf(
'%s | acquired: %s | non-fungible asset: %s | quantity: %s | cost basis: %s | income: %s | Fee: %s',
(string) $this->date,
(string) $this->asset,
$this->date,
$this->asset,
$this->asset->isNonFungible ? 'yes' : 'no',
(string) $this->quantity,
$this->quantity,
(string) $this->marketValue ?: 'N/A',
$this->isIncome ? 'yes' : 'no',
(string) $this->fee ?: 'N/A',
$this->fee ?: 'N/A',
);
}
}
14 changes: 8 additions & 6 deletions domain/src/ValueObjects/Transactions/Disposal.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
{
/** @throws DisposalException */
public function __construct(
public LocalDate $date,
LocalDate $date,
public Asset $asset,
public Quantity $quantity,
public FiatAmount $marketValue,
public ?Fee $fee = null,
?Fee $fee = null,
) {
parent::__construct($date, $fee);

! $asset->isFiat() || throw DisposalException::isFiat($this);
}

Expand All @@ -44,12 +46,12 @@ public function __toString(): string
{
return sprintf(
'%s | disposed of: %s | non-fungible asset: %s | quantity: %s | cost basis: %s | Fee: %s',
(string) $this->date,
(string) $this->asset,
$this->date,
$this->asset,
$this->asset->isNonFungible ? 'yes' : 'no',
(string) $this->quantity,
$this->quantity,
(string) $this->marketValue ?: 'N/A',
(string) $this->fee ?: 'N/A',
$this->fee ?: 'N/A',
);
}
}
18 changes: 10 additions & 8 deletions domain/src/ValueObjects/Transactions/Swap.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@
{
/** @throws SwapException */
public function __construct(
public LocalDate $date,
LocalDate $date,
public Asset $disposedOfAsset,
public Quantity $disposedOfQuantity,
public Asset $acquiredAsset,
public Quantity $acquiredQuantity,
public FiatAmount $marketValue,
public ?Fee $fee = null,
?Fee $fee = null,
) {
parent::__construct($date, $fee);

! $disposedOfAsset->isFiat() || ! $acquiredAsset->isFiat() || throw SwapException::bothSidesAreFiat($this);
}

Expand Down Expand Up @@ -61,15 +63,15 @@ public function __toString(): string
{
return sprintf(
'%s | disposed of: %s | non-fungible asset: %s | quantity: %s | acquired: %s | non-fungible asset: %s | quantity: %s | cost basis: %s | Fee: %s',
(string) $this->date,
(string) $this->disposedOfAsset,
$this->date,
$this->disposedOfAsset,
$this->disposedOfAsset->isNonFungible ? 'yes' : 'no',
(string) $this->disposedOfQuantity,
(string) $this->acquiredAsset,
$this->disposedOfQuantity,
$this->acquiredAsset,
$this->acquiredAsset->isNonFungible ? 'yes' : 'no',
(string) $this->acquiredQuantity,
$this->acquiredQuantity,
(string) $this->marketValue ?: 'N/A',
(string) $this->fee ?: 'N/A',
$this->fee ?: 'N/A',
);
}
}
13 changes: 7 additions & 6 deletions domain/src/ValueObjects/Transactions/Transfer.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
final readonly class Transfer extends Transaction
{
public function __construct(
public LocalDate $date,
LocalDate $date,
public Asset $asset,
public Quantity $quantity,
public ?Fee $fee = null,
?Fee $fee = null,
) {
parent::__construct($date, $fee);
}

protected static function newFactory(): TransferFactory
Expand All @@ -39,11 +40,11 @@ public function __toString(): string
{
return sprintf(
'%s | transferred: %s | non-fungible asset: %s | quantity: %s | Fee: %s',
(string) $this->date,
(string) $this->asset,
$this->date,
$this->asset,
$this->asset->isNonFungible ? 'yes' : 'no',
(string) $this->quantity,
(string) $this->fee ?: 'N/A',
$this->quantity,
$this->fee ?: 'N/A',
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,14 @@

expect((string) $acquisition->thirtyDayQuantity())->toBe('50');
});

it('can return an acquisition as a string', function () {
/** @var SharePoolingAssetAcquisition */
$acquisition = SharePoolingAssetAcquisition::factory()->make([
'date' => LocalDate::parse('2015-10-21'),
'quantity' => new Quantity('100'),
'costBasis' => FiatAmount::GBP('100'),
]);

expect((string) $acquisition)->toBe('2015-10-21: acquired 100 tokens for £100');
});
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
'scenario 3' => [['1.12345678', '1.123456789'], '2.246913569'],
]);

it('can return the cost basis of a collection of acquisitions', function (array $costBases, string $total) {
it('can return the cost basis of a collection of acquisitions', function (array $costBases, ?string $total) {
$acquisitions = [];

foreach ($costBases as $costBasis) {
Expand All @@ -80,12 +80,13 @@
$acquisitions = SharePoolingAssetAcquisitions::make(...$acquisitions);

expect($acquisitions->costBasis())
->toBeInstanceOf(FiatAmount::class)
->toEqual(FiatAmount::GBP($total));
->when(empty($costBases), fn ($costBasis) => $costBasis->toBeNull())
->unless(empty($costBases), fn ($costBasis) => $costBasis->toBeInstanceOf(FiatAmount::class)->toEqual(FiatAmount::GBP($total)));
})->with([
'scenario 1' => [['10'], '10'],
'scenario 2' => [['4', '10', '11'], '25'],
'scenario 3' => [['1.12345678', '1.123456789'], '2.246913569'],
'scenario 4' => [[], null],
]);

it('can return the average cost basis per unit of a collection of acquisitions', function (array $costBases, string $average) {
Expand Down Expand Up @@ -171,6 +172,27 @@
->toEqual(FiatAmount::GBP('160'));
});

it('can return the section 104 pool cost basis of an empty collection of acquisitions', function () {
expect(SharePoolingAssetAcquisitions::make()->section104PoolCostBasis())->toBeNull();
});

it('can return the section 104 pool cost basis of a collection of acquisitions with no section 104 pool quantity', function () {
/** @var list<SharePoolingAssetAcquisition> */
$items = [
SharePoolingAssetAcquisition::factory()->make([
'costBasis' => FiatAmount::GBP('100'),
'quantity' => new Quantity('100'),
'sameDayQuantity' => new Quantity('100'),
]),
];

$acquisitions = SharePoolingAssetAcquisitions::make(...$items);

expect($acquisitions->section104PoolCostBasis())
->toBeInstanceOf(FiatAmount::class)
->toEqual(FiatAmount::GBP('0'));
});

it('can return the average section 104 pool cost basis per unit of a collection of acquisitions', function () {
/** @var list<SharePoolingAssetAcquisition> */
$items = [
Expand Down
Loading

0 comments on commit a9b2c2a

Please sign in to comment.