fix: 🐛 change some file place + add tests
This commit is contained in:
parent
2c463eab03
commit
f8c2dd2a3f
8 changed files with 366 additions and 1 deletions
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects\RequestedCoupon;
|
||||
namespace Domain\Models\ValueObjects;
|
||||
|
||||
use Shared\ValueObjects\DateTime;
|
||||
|
||||
|
|
|
|||
81
tests/Unit/Domain/Enums/CountryTest.php
Normal file
81
tests/Unit/Domain/Enums/CountryTest.php
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Shared\Enums;
|
||||
|
||||
use Domain\Enums\Country;
|
||||
|
||||
covers(Country::class);
|
||||
|
||||
describe('country', function (): void {
|
||||
it('has the expected cases with their backing values', function (): void {
|
||||
// THEN
|
||||
expect(Country::FR->value())->toBe(1)
|
||||
->and(Country::BE->value())->toBe(2)
|
||||
->and(Country::LU->value())->toBe(3);
|
||||
});
|
||||
|
||||
it('exposes its case name', function (): void {
|
||||
// THEN
|
||||
expect(Country::FR->name())->toBe('FR');
|
||||
});
|
||||
|
||||
it('returns the defined label', function (): void {
|
||||
// THEN
|
||||
expect(Country::FR->label())->toBe('FR')
|
||||
->and(Country::BE->label())->toBe('BE')
|
||||
->and(Country::LU->label())->toBe('LU');
|
||||
});
|
||||
|
||||
it('lists all labels keyed by case name', function (): void {
|
||||
// THEN
|
||||
expect(Country::toLabels())->toBe([
|
||||
'FR' => 'FR',
|
||||
'BE' => 'BE',
|
||||
'LU' => 'LU',
|
||||
]);
|
||||
});
|
||||
|
||||
it('lists all values keyed by case name', function (): void {
|
||||
// THEN
|
||||
expect(Country::toValues())->toBe([
|
||||
'FR' => 1,
|
||||
'BE' => 2,
|
||||
'LU' => 3,
|
||||
]);
|
||||
});
|
||||
|
||||
it('makes an instance from its backing value', function (): void {
|
||||
// THEN
|
||||
expect(Country::make(1))->toBe(Country::FR);
|
||||
});
|
||||
|
||||
it('makes an instance from a label', function (): void {
|
||||
// THEN
|
||||
expect(Country::make('BE', 'label'))->toBe(Country::BE);
|
||||
});
|
||||
|
||||
it('returns the same instance when already an enum case', function (): void {
|
||||
// THEN
|
||||
expect(Country::make(Country::LU))->toBe(Country::LU);
|
||||
});
|
||||
|
||||
it('returns null for an unknown value', function (): void {
|
||||
// THEN
|
||||
expect(Country::make(99))->toBeNull();
|
||||
});
|
||||
|
||||
it('implements equals correctly', function (): void {
|
||||
// THEN
|
||||
expect(Country::FR->equals(Country::FR))->toBeTrue()
|
||||
->and(Country::FR->equals(Country::BE))->toBeFalse()
|
||||
->and(Country::FR->equals(null))->toBeFalse();
|
||||
});
|
||||
|
||||
it('serializes to json as its backing value', function (): void {
|
||||
// THEN
|
||||
expect(Country::FR->jsonSerialize())->toBe(1)
|
||||
->and(json_encode(Country::FR))->toBe('1');
|
||||
});
|
||||
});
|
||||
45
tests/Unit/Domain/Models/ValueObjects/MoneyAmountTest.php
Normal file
45
tests/Unit/Domain/Models/ValueObjects/MoneyAmountTest.php
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\ValueObjects;
|
||||
|
||||
use Domain\Models\ValueObjects\MoneyAmount;
|
||||
use Shared\Enums\Currency;
|
||||
use Shared\ValueObjects\Money;
|
||||
|
||||
covers(MoneyAmount::class);
|
||||
|
||||
describe('money amount', function (): void {
|
||||
it('wraps a Money value', function (): void {
|
||||
// GIVEN
|
||||
$money = new Money(Currency::EUR, 300);
|
||||
|
||||
// WHEN
|
||||
$amount = new MoneyAmount($money);
|
||||
|
||||
// THEN
|
||||
expect($amount)->toBeInstanceOf(MoneyAmount::class)
|
||||
->and($amount->value)->toBe($money);
|
||||
});
|
||||
|
||||
it('implements equals by delegating to the wrapped Money', function (): void {
|
||||
// GIVEN
|
||||
$amount1 = new MoneyAmount(new Money(Currency::EUR, 300));
|
||||
$amount2 = new MoneyAmount(new Money(Currency::EUR, 300));
|
||||
$amount3 = new MoneyAmount(new Money(Currency::EUR, 500));
|
||||
|
||||
// THEN
|
||||
expect($amount1->equals($amount2))->toBeTrue()
|
||||
->and($amount1->equals($amount3))->toBeFalse()
|
||||
->and($amount1->equals(null))->toBeFalse();
|
||||
});
|
||||
|
||||
it('converts to string by delegating to the wrapped Money', function (): void {
|
||||
// GIVEN
|
||||
$amount = new MoneyAmount(new Money(Currency::EUR, 300));
|
||||
|
||||
// THEN
|
||||
expect((string) $amount)->toBe((string) $amount->value);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\ValueObjects\RequestedCoupon;
|
||||
|
||||
use Domain\Models\ValueObjects\Period;
|
||||
use Shared\ValueObjects\DateTime;
|
||||
|
||||
covers(Period::class);
|
||||
|
||||
describe('period', function (): void {
|
||||
it('creates a valid period', function (): void {
|
||||
// GIVEN
|
||||
$start = new DateTime('2026-01-01');
|
||||
$end = new DateTime('2026-01-31');
|
||||
|
||||
// WHEN
|
||||
$period = new Period($start, $end);
|
||||
|
||||
// THEN
|
||||
expect($period)->toBeInstanceOf(Period::class)
|
||||
->and($period->start)->toBe($start)
|
||||
->and($period->end)->toBe($end);
|
||||
});
|
||||
});
|
||||
66
tests/Unit/Shared/Enums/CurrencyTest.php
Normal file
66
tests/Unit/Shared/Enums/CurrencyTest.php
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Shared\Enums;
|
||||
|
||||
use Shared\Enums\Currency;
|
||||
|
||||
covers(Currency::class);
|
||||
|
||||
describe('currency', function (): void {
|
||||
it('has the expected cases with their backing values', function (): void {
|
||||
// THEN
|
||||
expect(Currency::EUR->value())->toBe(1);
|
||||
});
|
||||
|
||||
it('exposes its case name', function (): void {
|
||||
// THEN
|
||||
expect(Currency::EUR->name())->toBe('EUR');
|
||||
});
|
||||
|
||||
it('returns the defined label', function (): void {
|
||||
// THEN
|
||||
expect(Currency::EUR->label())->toBe('Euro');
|
||||
});
|
||||
|
||||
it('lists all labels keyed by case name', function (): void {
|
||||
// THEN
|
||||
expect(Currency::toLabels())->toBe([
|
||||
'EUR' => 'Euro',
|
||||
]);
|
||||
});
|
||||
|
||||
it('lists all values keyed by case name', function (): void {
|
||||
// THEN
|
||||
expect(Currency::toValues())->toBe([
|
||||
'EUR' => 1,
|
||||
]);
|
||||
});
|
||||
|
||||
it('makes an instance from its backing value', function (): void {
|
||||
// THEN
|
||||
expect(Currency::make(1))->toBe(Currency::EUR);
|
||||
});
|
||||
|
||||
it('makes an instance from a label', function (): void {
|
||||
// THEN
|
||||
expect(Currency::make('Euro', 'label'))->toBe(Currency::EUR);
|
||||
});
|
||||
|
||||
it('returns the same instance when already an enum case', function (): void {
|
||||
// THEN
|
||||
expect(Currency::make(Currency::EUR))->toBe(Currency::EUR);
|
||||
});
|
||||
|
||||
it('returns null for an unknown value', function (): void {
|
||||
// THEN
|
||||
expect(Currency::make(99))->toBeNull();
|
||||
});
|
||||
|
||||
it('implements equals correctly', function (): void {
|
||||
// THEN
|
||||
expect(Currency::EUR->equals(Currency::EUR))->toBeTrue()
|
||||
->and(Currency::EUR->equals(null))->toBeFalse();
|
||||
});
|
||||
});
|
||||
86
tests/Unit/Shared/ValueObjects/DateTimeTest.php
Normal file
86
tests/Unit/Shared/ValueObjects/DateTimeTest.php
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Shared\ValueObjects;
|
||||
|
||||
use Shared\Helpers\DatesHelper;
|
||||
use Shared\Helpers\Exceptions\InvalidDateFormatException;
|
||||
use Shared\ValueObjects\DateTime;
|
||||
|
||||
covers(DateTime::class);
|
||||
|
||||
describe('date time', function (): void {
|
||||
it('accepts a DateTimeInterface instance and normalizes it to UTC', function (): void {
|
||||
// GIVEN
|
||||
$paris = new \DateTimeImmutable('2026-06-15 14:00:00', new \DateTimeZone('Europe/Paris'));
|
||||
|
||||
// WHEN
|
||||
$dateTime = new DateTime($paris);
|
||||
|
||||
// THEN
|
||||
expect($dateTime->value)->toBeInstanceOf(\DateTimeImmutable::class)
|
||||
->and($dateTime->value->getTimezone()->getName())->toBe('UTC')
|
||||
->and($dateTime->value->format('H:i:s'))->toBe('12:00:00');
|
||||
});
|
||||
|
||||
it('parses a valid date string', function (): void {
|
||||
// WHEN
|
||||
$dateTime = new DateTime('2026-01-15');
|
||||
|
||||
// THEN
|
||||
expect($dateTime->value->format('Y-m-d'))->toBe('2026-01-15');
|
||||
});
|
||||
|
||||
it('rejects an invalid date string', function (): void {
|
||||
// WHEN
|
||||
$action = fn (): DateTime => new DateTime('not-a-date');
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(InvalidDateFormatException::class);
|
||||
});
|
||||
|
||||
it('creates the current instant via now', function (): void {
|
||||
// GIVEN
|
||||
\Carbon\CarbonImmutable::setTestNow('2026-06-15T12:00:00Z');
|
||||
|
||||
// WHEN
|
||||
$dateTime = DateTime::now();
|
||||
|
||||
// THEN
|
||||
expect($dateTime)->toBeInstanceOf(DateTime::class)
|
||||
->and($dateTime->value->getTimezone()->getName())->toBe('UTC')
|
||||
->and($dateTime->value->format(\DateTimeInterface::ATOM))->toBe('2026-06-15T12:00:00+00:00');
|
||||
|
||||
// TEARDOWN
|
||||
\Carbon\CarbonImmutable::setTestNow();
|
||||
});
|
||||
|
||||
it('implements equals correctly', function (): void {
|
||||
// GIVEN
|
||||
$a = new DateTime('2026-01-15T10:00:00Z');
|
||||
$b = new DateTime('2026-01-15T10:00:00Z');
|
||||
$c = new DateTime('2026-01-16T10:00:00Z');
|
||||
|
||||
// THEN
|
||||
expect($a->equals($b))->toBeTrue()
|
||||
->and($a->equals($c))->toBeFalse()
|
||||
->and($a->equals(null))->toBeFalse();
|
||||
});
|
||||
|
||||
it('converts to a RFC3339 string', function (): void {
|
||||
// GIVEN
|
||||
$dateTime = new DateTime('2026-01-15T10:00:00Z');
|
||||
|
||||
// THEN
|
||||
expect((string) $dateTime)->toBe(DatesHelper::toRfc3339($dateTime->value));
|
||||
});
|
||||
|
||||
it('serializes to json as a RFC3339 string', function (): void {
|
||||
// GIVEN
|
||||
$dateTime = new DateTime('2026-01-15T10:00:00Z');
|
||||
|
||||
// THEN
|
||||
expect($dateTime->jsonSerialize())->toBe((string) $dateTime);
|
||||
});
|
||||
});
|
||||
61
tests/Unit/Shared/ValueObjects/MoneyTest.php
Normal file
61
tests/Unit/Shared/ValueObjects/MoneyTest.php
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Shared\ValueObjects;
|
||||
|
||||
use Shared\Enums\Currency;
|
||||
use Shared\ValueObjects\Money;
|
||||
|
||||
covers(Money::class);
|
||||
|
||||
describe('money', function (): void {
|
||||
it('creates a valid money value', function (): void {
|
||||
// GIVEN
|
||||
$value = 300;
|
||||
|
||||
// WHEN
|
||||
$money = new Money(Currency::EUR, $value);
|
||||
|
||||
// THEN
|
||||
expect($money)->toBeInstanceOf(Money::class)
|
||||
->and($money->currency)->toBe(Currency::EUR)
|
||||
->and($money->value)->toBe($value);
|
||||
});
|
||||
|
||||
it('accepts a zero value', function (): void {
|
||||
// WHEN
|
||||
$money = new Money(Currency::EUR, 0);
|
||||
|
||||
// THEN
|
||||
expect($money->value)->toBe(0);
|
||||
});
|
||||
|
||||
it('rejects a negative value', function (): void {
|
||||
// WHEN
|
||||
$action = fn (): Money => new Money(Currency::EUR, -1);
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(\DomainException::class, 'Money value cannot be negative.');
|
||||
});
|
||||
|
||||
it('implements equals correctly', function (): void {
|
||||
// GIVEN
|
||||
$money1 = new Money(Currency::EUR, 300);
|
||||
$money2 = new Money(Currency::EUR, 300);
|
||||
$money3 = new Money(Currency::EUR, 500);
|
||||
|
||||
// THEN
|
||||
expect($money1->equals($money2))->toBeTrue()
|
||||
->and($money1->equals($money3))->toBeFalse()
|
||||
->and($money1->equals(null))->toBeFalse();
|
||||
});
|
||||
|
||||
it('converts to string', function (): void {
|
||||
// GIVEN
|
||||
$money = new Money(Currency::EUR, 300);
|
||||
|
||||
// THEN
|
||||
expect((string) $money)->toBe('300 EUR');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue