From 2df9743291f0fb39f77bd6d4d9eb13a699dc0293 Mon Sep 17 00:00:00 2001 From: sspat Date: Fri, 8 Nov 2024 01:41:15 +0300 Subject: [PATCH] Add support for doctrine/dbal 4 (#8) * update packages + codestyle * update packages * update min php req --------- Co-authored-by: Patrik Foldes --- .github/workflows/ci.yml | 11 +- composer.json | 18 +- phpcs.xml.dist | 1 + phpstan.neon | 3 +- phpunit.xml.dist | 16 +- psalm.xml | 4 +- src/BaseMoney.php | 86 +- src/Currency.php | 18 +- src/Exception/CannotCreateMoney.php | 36 +- src/Exception/CannotWorkWithMoney.php | 12 +- src/Money.php | 2 +- src/Type/BTCMoneyType.php | 20 +- src/Type/CurrencyType.php | 8 +- src/Type/GaapMoneyType.php | 20 +- src/Type/MoneyType.php | 20 +- tests/BitcoinTest.php | 106 +- tests/CurrencyTest.php | 158 +- tests/Exception/CannotCreateMoneyTest.php | 194 +- tests/Exception/CannotWorkWithMoneyTest.php | 112 +- tests/GaapMoneyTest.php | 102 +- .../AmountMustBeGreaterThanZeroMoney.php | 30 +- tests/Mocks/AmountMustBeLessThanZeroMoney.php | 30 +- .../Mocks/AmountMustBeZeroOrGreaterMoney.php | 30 +- tests/Mocks/AmountMustBeZeroOrLessMoney.php | 30 +- tests/Mocks/CheckAmountMoney.php | 44 +- tests/Mocks/ExtendedCurrency.php | 22 +- tests/Mocks/ExtendedMoney.php | 22 +- tests/Mocks/InvalidSubunitCurrencyMoney.php | 44 +- tests/Mocks/ZeroSubunitMoney.php | 30 +- tests/MoneyTest.php | 2684 ++++++++--------- tests/Type/BTCMoneyTypeTest.php | 258 +- tests/Type/CurrencyTypeTest.php | 126 +- tests/Type/GaapMoneyTypeTest.php | 258 +- tests/Type/MoneyTypeTest.php | 258 +- 34 files changed, 2379 insertions(+), 2434 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c39ffe4..2ad46fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,8 +17,9 @@ jobs: - "ubuntu-latest" - "windows-latest" php-version: - - "8.0" - "8.1" + - "8.2" + - "8.3" dependencies: - "lowest" - "highest" @@ -51,7 +52,7 @@ jobs: operating-system: - "ubuntu-latest" php-version: - - "8.1" + - "8.3" steps: - name: "Checkout" uses: "actions/checkout@v2" @@ -77,7 +78,7 @@ jobs: operating-system: - "ubuntu-latest" php-version: - - "8.1" + - "8.3" steps: - name: "Checkout" uses: "actions/checkout@v2" @@ -103,7 +104,7 @@ jobs: operating-system: - "ubuntu-latest" php-version: - - "8.1" + - "8.3" steps: - name: "Checkout" uses: "actions/checkout@v2" @@ -129,7 +130,7 @@ jobs: operating-system: - "ubuntu-latest" php-version: - - "8.1" + - "8.3" steps: - name: "Checkout" uses: "actions/checkout@v2" diff --git a/composer.json b/composer.json index b37a9d4..806298b 100644 --- a/composer.json +++ b/composer.json @@ -18,20 +18,20 @@ } ], "require": { - "php": "^8.0|^8.1", + "php": "^8.1", "ext-bcmath": "*", - "doctrine/dbal": "^2|^3", + "doctrine/dbal": "^4", "moneyphp/money": "^4.0.3", "thecodingmachine/safe": "^1.3|^2" }, "require-dev": { - "doctrine/coding-standard": "^9.0", - "phpstan/phpstan": "^1.4", - "phpunit/phpunit": "^9.5.5", - "roave/no-floaters": "^1.5", - "squizlabs/php_codesniffer": "^3.6", + "doctrine/coding-standard": "^12.0", + "phpstan/phpstan": "^1.12", + "phpunit/phpunit": "^10.5", + "roave/no-floaters": "^1.11", + "squizlabs/php_codesniffer": "^3.10", "thecodingmachine/phpstan-safe-rule": "^1.1|^1.2", - "vimeo/psalm": "^4.20" + "vimeo/psalm": "^5.26" }, "minimum-stability": "stable", "config": { @@ -59,7 +59,7 @@ "psalm": "psalm", "stan": "phpstan analyze src -l 8 --memory-limit=512m", "sec": "rm -f local-php-security-checker && curl -s https://api.github.com/repos/fabpot/local-php-security-checker/releases/latest | grep -E \"browser_download_url(.+)linux_amd64\" | cut -d : -f 2,3 | tr -d \\\" | xargs -I % curl % -L -o local-php-security-checker && chmod +x local-php-security-checker && ./local-php-security-checker", - "test": "phpunit", + "test": "phpunit --display-phpunit-deprecations", "all": "composer psalm && composer stan && composer test && composer cs && composer sec" } } diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 9299ec9..b16afc1 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -16,5 +16,6 @@ src/ + tests/ diff --git a/phpstan.neon b/phpstan.neon index c888f1b..0415507 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,6 +1,5 @@ parameters: - checkMissingIterableValueType: false reportUnmatchedIgnoredErrors: false includes: - vendor/thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon - - vendor/roave/no-floaters/rules.neon \ No newline at end of file + - vendor/roave/no-floaters/rules.neon diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7a1caeb..eb9953d 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,14 @@ - - - - ./src/ - - + + ./tests/ diff --git a/psalm.xml b/psalm.xml index cf93af5..b5ff341 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,8 +1,8 @@ getAmountFormatRegexp($currencySubunits) + $this->getAmountFormatRegexp($currencySubunits), ); } @@ -88,7 +85,7 @@ final public static function create(string $amount, Currency $currency): self throw CannotCreateMoney::becauseAmountMustBeGreaterThanZero( static::humanReadableName(), $amount, - $currency->getCode() + $currency->getCode(), ); } @@ -96,7 +93,7 @@ final public static function create(string $amount, Currency $currency): self throw CannotCreateMoney::becauseAmountMustBeZeroOrGreater( static::humanReadableName(), $amount, - $currency->getCode() + $currency->getCode(), ); } @@ -104,7 +101,7 @@ final public static function create(string $amount, Currency $currency): self throw CannotCreateMoney::becauseAmountMustBeZeroOrLess( static::humanReadableName(), $amount, - $currency->getCode() + $currency->getCode(), ); } @@ -112,7 +109,7 @@ final public static function create(string $amount, Currency $currency): self throw CannotCreateMoney::becauseAmountMustBeLessThanZero( static::humanReadableName(), $amount, - $currency->getCode() + $currency->getCode(), ); } @@ -129,7 +126,7 @@ final public static function createFromMoney(self $money): self final public function convert(Converter $converter, Currency $toCurrency): self { return self::createFromLibMoney( - $converter->convert($this->getLibMoney(), new LibCurrency($toCurrency->getCode())) + $converter->convert($this->getLibMoney(), new LibCurrency($toCurrency->getCode())), ); } @@ -183,17 +180,13 @@ final public function lessThanOrEqual(self $other): bool return $this->getLibMoney()->lessThanOrEqual($other->getLibMoney()); } - /** - * @psalm-return numeric-string - */ + /** @psalm-return numeric-string */ final public function getAmount(): string { return $this->formatAmount(self::fromSubunits($this->amount)); } - /** - * @psalm-return numeric-string - */ + /** @psalm-return numeric-string */ private function formatAmount(string $amount): string { $currencySubunits = static::getAllowedCurrencies()->subunitFor(new LibCurrency($this->currency)); @@ -209,7 +202,7 @@ private function formatAmount(string $amount): string 0, $currencySubunits === 0 ? $dotPosition + $currencySubunits : - $dotPosition + $currencySubunits + 1 + $dotPosition + $currencySubunits + 1, ); return $formattedAmount; @@ -230,9 +223,9 @@ static function (self $addend): LibMoney { return $addend->getLibMoney(); }, - $addends - ) - ) + $addends, + ), + ), ); } @@ -246,9 +239,9 @@ static function (self $subtrahend): LibMoney { return $subtrahend->getLibMoney(); }, - $subtrahends - ) - ) + $subtrahends, + ), + ), ); } @@ -259,7 +252,7 @@ static function (self $subtrahend): LibMoney { final public function multiply(int|string $multiplier, int $roundingMode = LibMoney::ROUND_UP): self { return self::createFromLibMoney( - $this->getLibMoney()->multiply($multiplier, $roundingMode) + $this->getLibMoney()->multiply($multiplier, $roundingMode), ); } @@ -270,7 +263,7 @@ final public function multiply(int|string $multiplier, int $roundingMode = LibMo final public function divide(int|string $divisor, int $roundingMode = LibMoney::ROUND_UP): self { return self::createFromLibMoney( - $this->getLibMoney()->divide($divisor, $roundingMode) + $this->getLibMoney()->divide($divisor, $roundingMode), ); } @@ -279,13 +272,11 @@ final public function mod(self $divisor): self self::assertSameSubUnit($divisor, __FUNCTION__); return self::createFromLibMoney( - $this->getLibMoney()->mod($divisor->getLibMoney()) + $this->getLibMoney()->mod($divisor->getLibMoney()), ); } - /** - * @return self[] - */ + /** @return self[] */ final public function allocate(string ...$ratios): array { /** @psalm-var non-empty-array $ratios */ @@ -295,7 +286,7 @@ final public function allocate(string ...$ratios): array function (LibMoney $money): self { return $this->createFromLibMoney($money); }, - $this->getLibMoney()->allocate($ratios) + $this->getLibMoney()->allocate($ratios), ); } @@ -310,7 +301,7 @@ final public function allocateTo(int $n): array function (LibMoney $money): self { return $this->createFromLibMoney($money); }, - $this->getLibMoney()->allocateTo($n) + $this->getLibMoney()->allocateTo($n), ); } @@ -346,9 +337,7 @@ final public function isNegative(): bool return $this->getLibMoney()->isNegative(); } - /** - * @return string[] - */ + /** @return string[] */ final public function jsonSerialize(): array { return [ @@ -404,9 +393,9 @@ static function (self $money) use ($first, $method): LibMoney { return $money->getLibMoney(); }, - $collection - ) - ) + $collection, + ), + ), ); } @@ -423,9 +412,9 @@ static function (self $money) use ($first, $method): LibMoney { return $money->getLibMoney(); }, - $collection - ) - ) + $collection, + ), + ), ); } @@ -463,9 +452,7 @@ protected static function amountMustBeLessThanZero(): bool return false; } - /** - * @throws CannotCreateMoney - */ + /** @throws CannotCreateMoney */ protected static function validate(self $money): void { } @@ -501,18 +488,17 @@ private function createFromLibMoney(LibMoney $money): self { return self::create( self::fromSubunits($money->getAmount()), - Currency::create($money->getCurrency()->getCode()) + Currency::create($money->getCurrency()->getCode()), ); } private function getLibMoney(): LibMoney { + /** @psalm-suppress TooManyArguments */ return new LibMoney($this->amount, new LibCurrency($this->currency)); } - /** - * @psalm-return numeric-string - */ + /** @psalm-return numeric-string */ private static function getSubunitMultiplier(): string { /** @psalm-var numeric-string $multiplier */ @@ -531,7 +517,7 @@ private static function assertSameSubUnit(self $money, string $methodName): void static::class, $money::class, static::classSubunits(), - $money::classSubunits() + $money::classSubunits(), ); } } diff --git a/src/Currency.php b/src/Currency.php index 7e6ca11..a610030 100644 --- a/src/Currency.php +++ b/src/Currency.php @@ -9,28 +9,18 @@ class Currency { - /** @psalm-var non-empty-string */ - private string $code; - - /** - * @psalm-param non-empty-string $code - */ - final private function __construct(string $code) + /** @psalm-param non-empty-string $code */ + final private function __construct(private string $code) { - $this->code = $code; } - /** - * @psalm-param non-empty-string $code - */ + /** @psalm-param non-empty-string $code */ final public static function create(string $code): self { return new static($code); } - /** - * @psalm-return non-empty-string - */ + /** @psalm-return non-empty-string */ final public function getCode(): string { return $this->getLibCurrency()->getCode(); diff --git a/src/Exception/CannotCreateMoney.php b/src/Exception/CannotCreateMoney.php index 869f6b7..21db4da 100644 --- a/src/Exception/CannotCreateMoney.php +++ b/src/Exception/CannotCreateMoney.php @@ -11,15 +11,15 @@ final class CannotCreateMoney extends MoneyRuntimeError public static function becauseCurrencyNotAllowed( string $name, string $amount, - string $currency + string $currency, ): self { return new self( sprintf( 'Invalid %s with amount: %s and currency: %s. Currency not allowed.', $name, $amount, - $currency - ) + $currency, + ), ); } @@ -27,7 +27,7 @@ public static function becauseAmountFormatIsInvalid( string $name, string $amount, string $currency, - string $format + string $format, ): self { return new self( sprintf( @@ -35,68 +35,68 @@ public static function becauseAmountFormatIsInvalid( $name, $amount, $currency, - $format - ) + $format, + ), ); } public static function becauseAmountMustBeGreaterThanZero( string $name, string $amount, - string $currency + string $currency, ): self { return new self( sprintf( 'Invalid %s with amount: %s and currency: %s. Amount must be greater than zero.', $name, $amount, - $currency - ) + $currency, + ), ); } public static function becauseAmountMustBeZeroOrGreater( string $name, string $amount, - string $currency + string $currency, ): self { return new self( sprintf( 'Invalid %s with amount: %s and currency: %s. Amount must be zero or greater.', $name, $amount, - $currency - ) + $currency, + ), ); } public static function becauseAmountMustBeZeroOrLess( string $name, string $amount, - string $currency + string $currency, ): self { return new self( sprintf( 'Invalid %s with amount: %s and currency: %s. Amount must be zero or less.', $name, $amount, - $currency - ) + $currency, + ), ); } public static function becauseAmountMustBeLessThanZero( string $name, string $amount, - string $currency + string $currency, ): self { return new self( sprintf( 'Invalid %s with amount: %s and currency: %s. Amount must be less than zero.', $name, $amount, - $currency - ) + $currency, + ), ); } } diff --git a/src/Exception/CannotWorkWithMoney.php b/src/Exception/CannotWorkWithMoney.php index 094e9f8..ab61e3f 100644 --- a/src/Exception/CannotWorkWithMoney.php +++ b/src/Exception/CannotWorkWithMoney.php @@ -13,7 +13,7 @@ public static function becauseCurrencyExceedsSubunitLimit( string $amount, string $currency, int $currencySubunits, - int $classSubunits + int $classSubunits, ): self { return new self( sprintf( @@ -22,8 +22,8 @@ public static function becauseCurrencyExceedsSubunitLimit( $amount, $currency, $currencySubunits, - $classSubunits - ) + $classSubunits, + ), ); } @@ -32,7 +32,7 @@ public static function becauseMoneyHasDifferentSubunit( string $class, string $otherClass, int $subunits, - int $otherSubunits + int $otherSubunits, ): self { return new self( sprintf( @@ -41,8 +41,8 @@ public static function becauseMoneyHasDifferentSubunit( $class, $otherClass, $subunits, - $otherSubunits - ) + $otherSubunits, + ), ); } } diff --git a/src/Money.php b/src/Money.php index c7be55e..0fc617d 100644 --- a/src/Money.php +++ b/src/Money.php @@ -10,7 +10,7 @@ class Money extends BaseMoney { - private static ?Currencies $currencies = null; + private static Currencies|null $currencies = null; protected static function classSubunits(): int { diff --git a/src/Type/BTCMoneyType.php b/src/Type/BTCMoneyType.php index 28fed95..bee6dae 100644 --- a/src/Type/BTCMoneyType.php +++ b/src/Type/BTCMoneyType.php @@ -15,9 +15,7 @@ class BTCMoneyType extends Type { public const TYPE_NAME = 'btc_money'; - /** - * @param mixed[] $column - */ + /** @param mixed[] $column */ public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { return $platform->getDecimalTypeDeclarationSQL( @@ -26,16 +24,12 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform): st [ 'precision' => 16, 'scale' => 8, - ] - ) + ], + ), ); } - /** - * - * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint - */ - public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?string + public function convertToPHPValue(mixed $value, AbstractPlatform $platform): string|null { if ($value === null) { return null; @@ -47,11 +41,7 @@ public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?st return bcmul($value, '100000000', 0); } - /** - * - * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint - */ - public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): ?string + public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): string|null { if ($value === null) { return null; diff --git a/src/Type/CurrencyType.php b/src/Type/CurrencyType.php index 4b9bd46..eac596a 100644 --- a/src/Type/CurrencyType.php +++ b/src/Type/CurrencyType.php @@ -13,13 +13,11 @@ class CurrencyType extends Type { public const TYPE_NAME = 'currency'; - /** - * @param mixed[] $column - */ + /** @param mixed[] $column */ public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { - return $platform->getVarcharTypeDeclarationSQL( - array_merge($column, ['length' => 3]) + return $platform->getStringTypeDeclarationSQL( + array_merge($column, ['length' => 3]), ); } diff --git a/src/Type/GaapMoneyType.php b/src/Type/GaapMoneyType.php index 2382400..419b7cc 100644 --- a/src/Type/GaapMoneyType.php +++ b/src/Type/GaapMoneyType.php @@ -15,9 +15,7 @@ class GaapMoneyType extends Type { public const TYPE_NAME = 'gaap_money'; - /** - * @param mixed[] $column - */ + /** @param mixed[] $column */ public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { return $platform->getDecimalTypeDeclarationSQL( @@ -26,16 +24,12 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform): st [ 'precision' => 15, 'scale' => 4, - ] - ) + ], + ), ); } - /** - * - * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint - */ - public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?string + public function convertToPHPValue(mixed $value, AbstractPlatform $platform): string|null { if ($value === null) { return null; @@ -47,11 +41,7 @@ public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?st return bcmul($value, '10000', 0); } - /** - * - * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint - */ - public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): ?string + public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): string|null { if ($value === null) { return null; diff --git a/src/Type/MoneyType.php b/src/Type/MoneyType.php index 84b8ac1..cc5120e 100644 --- a/src/Type/MoneyType.php +++ b/src/Type/MoneyType.php @@ -15,9 +15,7 @@ class MoneyType extends Type { public const TYPE_NAME = 'money'; - /** - * @param mixed[] $column - */ + /** @param mixed[] $column */ public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { return $platform->getDecimalTypeDeclarationSQL( @@ -26,16 +24,12 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform): st [ 'precision' => 10, 'scale' => 2, - ] - ) + ], + ), ); } - /** - * - * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint - */ - public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?string + public function convertToPHPValue(mixed $value, AbstractPlatform $platform): string|null { if ($value === null) { return null; @@ -47,11 +41,7 @@ public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?st return bcmul($value, '100', 0); } - /** - * - * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint - */ - public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): ?string + public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): string|null { if ($value === null) { return null; diff --git a/tests/BitcoinTest.php b/tests/BitcoinTest.php index d60efea..5f5ce87 100644 --- a/tests/BitcoinTest.php +++ b/tests/BitcoinTest.php @@ -1,53 +1,53 @@ -getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCreateWrongAmount() : void - { - $amount = '100.0000000'; - $code = 'XBT'; - - $currency = Currency::create($code); - - $this->expectException(CannotCreateMoney::class); - $this->expectExceptionMessage('Invalid Bitcoin with amount: 100.0000000 and currency: XBT. Invalid amount format. The correct format is: /^-?\d+\.\d{8}$/.'); - - $money = Bitcoin::create($amount, $currency); - } - - public function testCreateWrongCurrency() : void - { - $amount = '100.00000000'; - $code = 'EUR'; - - $currency = Currency::create($code); - - $this->expectException(CannotCreateMoney::class); - $this->expectExceptionMessage('Invalid Bitcoin with amount: 100.00000000 and currency: EUR. Currency not allowed.'); - - $money = Bitcoin::create($amount, $currency); - } -} +getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCreateWrongAmount(): void + { + $amount = '100.0000000'; + $code = 'XBT'; + + $currency = Currency::create($code); + + $this->expectException(CannotCreateMoney::class); + $this->expectExceptionMessage('Invalid Bitcoin with amount: 100.0000000 and currency: XBT. Invalid amount format. The correct format is: /^-?\d+\.\d{8}$/.'); + + $money = Bitcoin::create($amount, $currency); + } + + public function testCreateWrongCurrency(): void + { + $amount = '100.00000000'; + $code = 'EUR'; + + $currency = Currency::create($code); + + $this->expectException(CannotCreateMoney::class); + $this->expectExceptionMessage('Invalid Bitcoin with amount: 100.00000000 and currency: EUR. Currency not allowed.'); + + $money = Bitcoin::create($amount, $currency); + } +} diff --git a/tests/CurrencyTest.php b/tests/CurrencyTest.php index ea98a90..2c2e9e3 100644 --- a/tests/CurrencyTest.php +++ b/tests/CurrencyTest.php @@ -1,79 +1,79 @@ -getCode()); - } - - public function testCreateExtendedClass() : void - { - $code = 'EUR'; - - $currency = ExtendedCurrency::create($code); - - Assert::assertInstanceOf(ExtendedCurrency::class, $currency); - } - - public function testEquals() : void - { - $firstCurrencyCode = 'EUR'; - $secondCurrencyCode = 'EUR'; - $thirdCurrencyCode = 'USD'; - - $firstCurrency = Currency::create($firstCurrencyCode); - $secondCurrency = Currency::create($secondCurrencyCode); - $thirdCurrency = Currency::create($thirdCurrencyCode); - - Assert::assertTrue($firstCurrency->equals($secondCurrency)); - Assert::assertFalse($firstCurrency->equals($thirdCurrency)); - } - - public function testIsAvailableWithin() : void - { - $firstCurrencyCode = 'EUR'; - $secondCurrencyCode = 'USD'; - - $firstCurrency = Currency::create($firstCurrencyCode); - $secondCurrency = Currency::create($secondCurrencyCode); - - $currencies = new CurrencyList([$firstCurrencyCode => 2]); - - Assert::assertTrue($firstCurrency->isAvailableWithin($currencies)); - Assert::assertFalse($secondCurrency->isAvailableWithin($currencies)); - } - - public function testToString() : void - { - $code = 'EUR'; - - $currency = Currency::create($code); - - Assert::assertSame($code, (string) $currency); - } - - public function testJsonSerialize() : void - { - $code = 'EUR'; - - $currency = Currency::create($code); - - Assert::assertSame($code, $currency->jsonSerialize()); - } -} +getCode()); + } + + public function testCreateExtendedClass(): void + { + $code = 'EUR'; + + $currency = ExtendedCurrency::create($code); + + Assert::assertInstanceOf(ExtendedCurrency::class, $currency); + } + + public function testEquals(): void + { + $firstCurrencyCode = 'EUR'; + $secondCurrencyCode = 'EUR'; + $thirdCurrencyCode = 'USD'; + + $firstCurrency = Currency::create($firstCurrencyCode); + $secondCurrency = Currency::create($secondCurrencyCode); + $thirdCurrency = Currency::create($thirdCurrencyCode); + + Assert::assertTrue($firstCurrency->equals($secondCurrency)); + Assert::assertFalse($firstCurrency->equals($thirdCurrency)); + } + + public function testIsAvailableWithin(): void + { + $firstCurrencyCode = 'EUR'; + $secondCurrencyCode = 'USD'; + + $firstCurrency = Currency::create($firstCurrencyCode); + $secondCurrency = Currency::create($secondCurrencyCode); + + $currencies = new CurrencyList([$firstCurrencyCode => 2]); + + Assert::assertTrue($firstCurrency->isAvailableWithin($currencies)); + Assert::assertFalse($secondCurrency->isAvailableWithin($currencies)); + } + + public function testToString(): void + { + $code = 'EUR'; + + $currency = Currency::create($code); + + Assert::assertSame($code, (string) $currency); + } + + public function testJsonSerialize(): void + { + $code = 'EUR'; + + $currency = Currency::create($code); + + Assert::assertSame($code, $currency->jsonSerialize()); + } +} diff --git a/tests/Exception/CannotCreateMoneyTest.php b/tests/Exception/CannotCreateMoneyTest.php index 3c8eb1b..25a2023 100644 --- a/tests/Exception/CannotCreateMoneyTest.php +++ b/tests/Exception/CannotCreateMoneyTest.php @@ -1,97 +1,97 @@ -getMessage() - ); - } - - public function testBecauseAmountFormatIsInvalid() : void - { - $name = 'Money'; - $amount = '10.000'; - $currency = 'EUR'; - $format = '/^-?\d+\.\d{2}$/'; - - $exception = CannotCreateMoney::becauseAmountFormatIsInvalid($name, $amount, $currency, $format); - - Assert::assertSame( - 'Invalid Money with amount: 10.000 and currency: EUR. Invalid amount format. The correct format is: /^-?\d+\.\d{2}$/.', - $exception->getMessage() - ); - } - - public function testBecauseAmountMustBeGreaterThanZero() : void - { - $name = 'Money'; - $amount = '0.00'; - $currency = 'EUR'; - - $exception = CannotCreateMoney::becauseAmountMustBeGreaterThanZero($name, $amount, $currency); - - Assert::assertSame( - 'Invalid Money with amount: 0.00 and currency: EUR. Amount must be greater than zero.', - $exception->getMessage() - ); - } - - public function testBecauseAmountMustBeZeroOrGreater() : void - { - $name = 'Money'; - $amount = '-0.01'; - $currency = 'EUR'; - - $exception = CannotCreateMoney::becauseAmountMustBeZeroOrGreater($name, $amount, $currency); - - Assert::assertSame( - 'Invalid Money with amount: -0.01 and currency: EUR. Amount must be zero or greater.', - $exception->getMessage() - ); - } - - public function testBecauseAmountMustBeZeroOrLess() : void - { - $name = 'Money'; - $amount = '0.01'; - $currency = 'EUR'; - - $exception = CannotCreateMoney::becauseAmountMustBeZeroOrLess($name, $amount, $currency); - - Assert::assertSame( - 'Invalid Money with amount: 0.01 and currency: EUR. Amount must be zero or less.', - $exception->getMessage() - ); - } - - public function testBecauseAmountMustBeLessThanZero() : void - { - $name = 'Money'; - $amount = '0.00'; - $currency = 'EUR'; - - $exception = CannotCreateMoney::becauseAmountMustBeLessThanZero($name, $amount, $currency); - - Assert::assertSame( - 'Invalid Money with amount: 0.00 and currency: EUR. Amount must be less than zero.', - $exception->getMessage() - ); - } -} +getMessage(), + ); + } + + public function testBecauseAmountFormatIsInvalid(): void + { + $name = 'Money'; + $amount = '10.000'; + $currency = 'EUR'; + $format = '/^-?\d+\.\d{2}$/'; + + $exception = CannotCreateMoney::becauseAmountFormatIsInvalid($name, $amount, $currency, $format); + + Assert::assertSame( + 'Invalid Money with amount: 10.000 and currency: EUR. Invalid amount format. The correct format is: /^-?\d+\.\d{2}$/.', + $exception->getMessage(), + ); + } + + public function testBecauseAmountMustBeGreaterThanZero(): void + { + $name = 'Money'; + $amount = '0.00'; + $currency = 'EUR'; + + $exception = CannotCreateMoney::becauseAmountMustBeGreaterThanZero($name, $amount, $currency); + + Assert::assertSame( + 'Invalid Money with amount: 0.00 and currency: EUR. Amount must be greater than zero.', + $exception->getMessage(), + ); + } + + public function testBecauseAmountMustBeZeroOrGreater(): void + { + $name = 'Money'; + $amount = '-0.01'; + $currency = 'EUR'; + + $exception = CannotCreateMoney::becauseAmountMustBeZeroOrGreater($name, $amount, $currency); + + Assert::assertSame( + 'Invalid Money with amount: -0.01 and currency: EUR. Amount must be zero or greater.', + $exception->getMessage(), + ); + } + + public function testBecauseAmountMustBeZeroOrLess(): void + { + $name = 'Money'; + $amount = '0.01'; + $currency = 'EUR'; + + $exception = CannotCreateMoney::becauseAmountMustBeZeroOrLess($name, $amount, $currency); + + Assert::assertSame( + 'Invalid Money with amount: 0.01 and currency: EUR. Amount must be zero or less.', + $exception->getMessage(), + ); + } + + public function testBecauseAmountMustBeLessThanZero(): void + { + $name = 'Money'; + $amount = '0.00'; + $currency = 'EUR'; + + $exception = CannotCreateMoney::becauseAmountMustBeLessThanZero($name, $amount, $currency); + + Assert::assertSame( + 'Invalid Money with amount: 0.00 and currency: EUR. Amount must be less than zero.', + $exception->getMessage(), + ); + } +} diff --git a/tests/Exception/CannotWorkWithMoneyTest.php b/tests/Exception/CannotWorkWithMoneyTest.php index 698477c..2cdf115 100644 --- a/tests/Exception/CannotWorkWithMoneyTest.php +++ b/tests/Exception/CannotWorkWithMoneyTest.php @@ -1,56 +1,56 @@ -getMessage() - ); - } - - public function testBecauseBothCurrenciesSame() : void - { - $method = 'add'; - $class = 'OnMoon\Money\Money'; - $otherClass = 'OnMoon\Money\GaapMoney'; - $subunits = 2; - $otherSubunits = 4; - - $exception = CannotWorkWithMoney::becauseMoneyHasDifferentSubunit( - $method, - $class, - $otherClass, - $subunits, - $otherSubunits - ); - - Assert::assertSame( - 'Cannot execute method: add on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.', - $exception->getMessage() - ); - } -} +getMessage(), + ); + } + + public function testBecauseBothCurrenciesSame(): void + { + $method = 'add'; + $class = 'OnMoon\Money\Money'; + $otherClass = 'OnMoon\Money\GaapMoney'; + $subunits = 2; + $otherSubunits = 4; + + $exception = CannotWorkWithMoney::becauseMoneyHasDifferentSubunit( + $method, + $class, + $otherClass, + $subunits, + $otherSubunits, + ); + + Assert::assertSame( + 'Cannot execute method: add on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.', + $exception->getMessage(), + ); + } +} diff --git a/tests/GaapMoneyTest.php b/tests/GaapMoneyTest.php index 6647e22..3383859 100644 --- a/tests/GaapMoneyTest.php +++ b/tests/GaapMoneyTest.php @@ -1,53 +1,49 @@ -getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCreateInvalidCurrency() : void - { - $amount = '10.00000000'; - $currency = 'XBT'; - - $currency = Currency::create($currency); - - $this->expectException(CannotCreateMoney::class); - $this->expectExceptionMessage('Invalid Money with amount: 10.00000000 and currency: XBT. Currency not allowed.'); - - $money = GaapMoney::create($amount, $currency); - } - - /** - * @return mixed[][] - */ - public function moneyProvider() : array - { - return [ - ['100', 'CLP'], - ['100.12', 'EUR'], - ['100.123', 'BHD'], - ['100.1234', 'CLF'], - ]; - } -} +getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCreateInvalidCurrency(): void + { + $amount = '10.00000000'; + $currency = 'XBT'; + + $currency = Currency::create($currency); + + $this->expectException(CannotCreateMoney::class); + $this->expectExceptionMessage('Invalid Money with amount: 10.00000000 and currency: XBT. Currency not allowed.'); + + $money = GaapMoney::create($amount, $currency); + } + + /** @return mixed[][] */ + public static function moneyProvider(): array + { + return [ + ['100', 'CLP'], + ['100.12', 'EUR'], + ['100.123', 'BHD'], + ['100.1234', 'CLF'], + ]; + } +} diff --git a/tests/Mocks/AmountMustBeGreaterThanZeroMoney.php b/tests/Mocks/AmountMustBeGreaterThanZeroMoney.php index a5a7927..c62333c 100644 --- a/tests/Mocks/AmountMustBeGreaterThanZeroMoney.php +++ b/tests/Mocks/AmountMustBeGreaterThanZeroMoney.php @@ -1,15 +1,15 @@ -lessThanOrEqual(Money::create('100.00', Currency::create('EUR')))) { - return; - } - - throw new CannotCreateMoney('Money amount is greater than 100.00 EUR'); - } -} +lessThanOrEqual(Money::create('100.00', Currency::create('EUR')))) { + return; + } + + throw new CannotCreateMoney('Money amount is greater than 100.00 EUR'); + } +} diff --git a/tests/Mocks/ExtendedCurrency.php b/tests/Mocks/ExtendedCurrency.php index d3fb085..3f97506 100644 --- a/tests/Mocks/ExtendedCurrency.php +++ b/tests/Mocks/ExtendedCurrency.php @@ -1,11 +1,11 @@ - 3]); - } -} + 3]); + } +} diff --git a/tests/Mocks/ZeroSubunitMoney.php b/tests/Mocks/ZeroSubunitMoney.php index 03a0391..9ebdb09 100644 --- a/tests/Mocks/ZeroSubunitMoney.php +++ b/tests/Mocks/ZeroSubunitMoney.php @@ -1,15 +1,15 @@ -getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCreateExtendedClass() : void - { - $amount = '100.00'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = ExtendedMoney::create($amount, $currency); - - Assert::assertInstanceOf(ExtendedMoney::class, $money); - Assert::assertSame($amount, $money->getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCreateFromTrailingZeroAmount() : void - { - $amount = '00.01'; - $outputAmount = '0.01'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = ExtendedMoney::create($amount, $currency); - - Assert::assertSame($outputAmount, $money->getAmount()); - } - - public function testCreateValidateSuccess() : void - { - $amount = '100.00'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = CheckAmountMoney::create($amount, $currency); - - Assert::assertInstanceOf(CheckAmountMoney::class, $money); - } - - public function testCreateValidateFailure() : void - { - $amount = '100.01'; - $code = 'EUR'; - - $currency = Currency::create($code); - - $this->expectException(CannotCreateMoney::class); - $this->expectExceptionMessage('Money amount is greater than 100.00 EUR'); - - $money = CheckAmountMoney::create($amount, $currency); - } - - public function testCanCreateWithNegativeAmount() : void - { - $amount = '-0.01'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = Money::create($amount, $currency); - - Assert::assertInstanceOf(Money::class, $money); - Assert::assertSame($amount, $money->getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCanCreateWithZeroAmount() : void - { - $amount = '0.00'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = Money::create($amount, $currency); - - Assert::assertInstanceOf(Money::class, $money); - Assert::assertSame($amount, $money->getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCanCreateWithPositiveAmount() : void - { - $amount = '0.01'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = Money::create($amount, $currency); - - Assert::assertInstanceOf(Money::class, $money); - Assert::assertSame($amount, $money->getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCantCreateWithZeroAmountIfMustBeGreaterThanZeroApplyed() : void - { - $amount = '0.00'; - $code = 'EUR'; - - $currency = Currency::create($code); - - $this->expectException(CannotCreateMoney::class); - $this->expectExceptionMessage('Invalid Money with amount: 0.00 and currency: EUR. Amount must be greater than zero.'); - - $money = AmountMustBeGreaterThanZeroMoney::create($amount, $currency); - } - - public function testCantCreateWithNegativeAmountIfMustBeGreaterThanZeroApplyed() : void - { - $amount = '-0.01'; - $code = 'EUR'; - - $currency = Currency::create($code); - - $this->expectException(CannotCreateMoney::class); - $this->expectExceptionMessage('Invalid Money with amount: -0.01 and currency: EUR. Amount must be greater than zero.'); - - $money = AmountMustBeGreaterThanZeroMoney::create($amount, $currency); - } - - public function testCanCreateWithPositiveAmountIfMustBeGreaterThanZeroApplyed() : void - { - $amount = '0.01'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = AmountMustBeGreaterThanZeroMoney::create($amount, $currency); - - Assert::assertSame($amount, $money->getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCantCreateWithNegativeAmountIfMustBeZeroOrGreaterApplyed() : void - { - $amount = '-0.01'; - $code = 'EUR'; - - $currency = Currency::create($code); - - $this->expectException(CannotCreateMoney::class); - $this->expectExceptionMessage('Invalid Money with amount: -0.01 and currency: EUR. Amount must be zero or greater.'); - - $money = AmountMustBeZeroOrGreaterMoney::create($amount, $currency); - } - - public function testCanCreateWithZeroAmountIfMustBeZeroOrGreaterApplyed() : void - { - $amount = '0.00'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = AmountMustBeZeroOrGreaterMoney::create($amount, $currency); - - Assert::assertSame($amount, $money->getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCanCreateWithPositiveAmountIfMustBeZeroOrGreaterApplyed() : void - { - $amount = '0.01'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = AmountMustBeZeroOrGreaterMoney::create($amount, $currency); - - Assert::assertSame($amount, $money->getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCantCreateWithPositiveAmountIfMustBeZeroOrLessApplyed() : void - { - $amount = '0.01'; - $code = 'EUR'; - - $currency = Currency::create($code); - - $this->expectException(CannotCreateMoney::class); - $this->expectExceptionMessage('Invalid Money with amount: 0.01 and currency: EUR. Amount must be zero or less.'); - - $money = AmountMustBeZeroOrLessMoney::create($amount, $currency); - } - - public function testCanCreateWithZeroAmountIfMustBeZeroOrLessApplyed() : void - { - $amount = '0.00'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = AmountMustBeZeroOrLessMoney::create($amount, $currency); - - Assert::assertSame($amount, $money->getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCanCreateWithNegativeAmountIfMustBeZeroOrLessApplyed() : void - { - $amount = '-0.01'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = AmountMustBeZeroOrLessMoney::create($amount, $currency); - - Assert::assertSame($amount, $money->getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCantCreateWithPositiveAmountIfMustBeLessThanZeroApplyed() : void - { - $amount = '0.01'; - $code = 'EUR'; - - $currency = Currency::create($code); - - $this->expectException(CannotCreateMoney::class); - $this->expectExceptionMessage('Invalid Money with amount: 0.01 and currency: EUR. Amount must be less than zero.'); - - $money = AmountMustBeLessThanZeroMoney::create($amount, $currency); - } - - public function testCantCreateWithZeroAmountIfMustBeLessThanZeroApplyed() : void - { - $amount = '0.00'; - $code = 'EUR'; - - $currency = Currency::create($code); - - $this->expectException(CannotCreateMoney::class); - $this->expectExceptionMessage('Invalid Money with amount: 0.00 and currency: EUR. Amount must be less than zero.'); - - $money = AmountMustBeLessThanZeroMoney::create($amount, $currency); - } - - public function testCanCreateWithNegativeAmountIfMustBeLessThanZeroApplyed() : void - { - $amount = '-0.01'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = AmountMustBeLessThanZeroMoney::create($amount, $currency); - - Assert::assertSame($amount, $money->getAmount()); - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testCantCreateWithInvalidAmountFormat() : void - { - $amount = '10.000'; - $code = 'EUR'; - - $currency = Currency::create($code); - - $this->expectException(CannotCreateMoney::class); - $this->expectExceptionMessage('Invalid Money with amount: 10.000 and currency: EUR. Invalid amount format. The correct format is: /^-?\d+\.\d{2}$/.'); - - $money = Money::create($amount, $currency); - } - - public function testCantCreateWithExceedingSubunitCurrency() : void - { - $amount = '10.000'; - $code = 'OMR'; - - $currency = Currency::create($code); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot instantiate OnMoon\Money\Tests\Mocks\InvalidSubunitCurrencyMoney with amount: 10.000 and currency: OMR. The currency has more subunits: 3 then the class allows: 2.'); - - $money = InvalidSubunitCurrencyMoney::create($amount, $currency); - } - - public function testCanCreateFromSameSubunitMoney() : void - { - $amount = '10.00'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = Money::create($amount, $currency); - $otherMoney = ExtendedMoney::createFromMoney($money); - - Assert::assertInstanceOf(ExtendedMoney::class, $otherMoney); - Assert::assertSame($amount, $otherMoney->getAmount()); - Assert::assertNotSame($currency, $otherMoney->getCurrency()); - Assert::assertSame($code, $otherMoney->getCurrency()->getCode()); - } - - public function testCantCreateFromOtherSubunitMoney() : void - { - $amount = '10.00'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = Money::create($amount, $currency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: createFromMoney on Money object: OnMoon\Money\GaapMoney with other Money object as argument: OnMoon\Money\Money. The classes have different subunits: 4 and 2.'); - - $otherMoney = GaapMoney::createFromMoney($money); - } - - public function testCanCreateZeroSubunitMoney() : void - { - $amount = '123'; - $code = 'DJF'; - - $currency = Currency::create($code); - $money = ZeroSubunitMoney::create($amount, $currency); - - Assert::assertSame($amount, $money->getAmount()); - } - - public function testCreateZeroSubunitMoneyInvalidFormatError() : void - { - $amount = '100.0'; - $code = 'DJF'; - - $currency = Currency::create($code); - - $this->expectException(CannotCreateMoney::class); - $this->expectExceptionMessage('Invalid Money with amount: 100.0 and currency: DJF. Invalid amount format. The correct format is: /^-?\d+$/.'); - - $money = ZeroSubunitMoney::create($amount, $currency); - } - - public function testIsSameCurrency() : void - { - $amount = '10.00'; - $firstCode = 'EUR'; - $secondCode = 'EUR'; - $thirdCode = 'USD'; - - $firstCurrency = Currency::create($firstCode); - $firstMoney = Money::create($amount, $firstCurrency); - $secondCurrency = Currency::create($secondCode); - $secondMoney = Money::create($amount, $secondCurrency); - $thirdCurrency = Currency::create($thirdCode); - $thirdMoney = Money::create($amount, $thirdCurrency); - - Assert::assertTrue($firstMoney->isSameCurrency($secondMoney)); - Assert::assertFalse($firstMoney->isSameCurrency($thirdMoney)); - } - - public function testEquals() : void - { - $ten = '10.00'; - $five = '5.00'; - $euro = 'EUR'; - $dollar = 'USD'; - - $euroCurrency = Currency::create($euro); - $dollarCurrency = Currency::create($dollar); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = Money::create($ten, $euroCurrency); - $fiveEuros = Money::create($five, $euroCurrency); - $tenDollars = Money::create($ten, $dollarCurrency); - - Assert::assertTrue($tenEuros->equals($anotherTenEuros)); - Assert::assertFalse($tenEuros->equals($fiveEuros)); - Assert::assertFalse($tenEuros->equals($tenDollars)); - } - - public function testCantCheckEqualityWithOtherSubunitMoney() : void - { - $ten = '10.00'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: equals on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - $tenEuros->equals($anotherTenEuros); - } - - public function testCompare() : void - { - $ten = '10.00'; - $five = '5.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = Money::create($ten, $euroCurrency); - $fiveEuros = Money::create($five, $euroCurrency); - $fifteenEuros = Money::create($fifteen, $euroCurrency); - - Assert::assertSame(0, $tenEuros->compare($anotherTenEuros)); - Assert::assertSame(1, $tenEuros->compare($fiveEuros)); - Assert::assertSame(-1, $tenEuros->compare($fifteenEuros)); - } - - public function testCantCompareWithOtherCurrencyMoney() : void - { - $ten = '10.00'; - $euro = 'EUR'; - $dollar = 'USD'; - - $euroCurrency = Currency::create($euro); - $dollarCurrency = Currency::create($dollar); - $tenEuros = Money::create($ten, $euroCurrency); - $tenDollars = Money::create($ten, $dollarCurrency); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Currencies must be identical'); - - $tenEuros->compare($tenDollars); - } - - public function testCantCompareWithOtherSubunitMoney() : void - { - $ten = '10.00'; - $euro = 'EUR'; - $subunits = 2; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: compare on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - $tenEuros->compare($anotherTenEuros); - } - - public function testGreaterThan() : void - { - $ten = '10.00'; - $five = '5.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = Money::create($ten, $euroCurrency); - $fiveEuros = Money::create($five, $euroCurrency); - $fifteenEuros = Money::create($fifteen, $euroCurrency); - - Assert::assertFalse($tenEuros->greaterThan($anotherTenEuros)); - Assert::assertTrue($tenEuros->greaterThan($fiveEuros)); - Assert::assertFalse($tenEuros->greaterThan($fifteenEuros)); - } - - public function testCantCompareGreaterThanWithOtherSubunitMoney() : void - { - $ten = '10.00'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: greaterThan on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - $tenEuros->greaterThan($anotherTenEuros); - } - - public function testGreaterThanOrEqual() : void - { - $ten = '10.00'; - $five = '5.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = Money::create($ten, $euroCurrency); - $fiveEuros = Money::create($five, $euroCurrency); - $fifteenEuros = Money::create($fifteen, $euroCurrency); - - Assert::assertTrue($tenEuros->greaterThanOrEqual($anotherTenEuros)); - Assert::assertTrue($tenEuros->greaterThanOrEqual($fiveEuros)); - Assert::assertFalse($tenEuros->greaterThanOrEqual($fifteenEuros)); - } - - public function testCantCompareGreaterThanOrEqualWithOtherSubunitMoney() : void - { - $ten = '10.00'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: greaterThanOrEqual on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - $tenEuros->greaterThanOrEqual($anotherTenEuros); - } - - public function testLessThan() : void - { - $ten = '10.00'; - $five = '5.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = Money::create($ten, $euroCurrency); - $fiveEuros = Money::create($five, $euroCurrency); - $fifteenEuros = Money::create($fifteen, $euroCurrency); - - Assert::assertFalse($tenEuros->lessThan($anotherTenEuros)); - Assert::assertFalse($tenEuros->lessThan($fiveEuros)); - Assert::assertTrue($tenEuros->lessThan($fifteenEuros)); - } - - public function testCantCompareLessThanWithOtherSubunitMoney() : void - { - $ten = '10.00'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: lessThan on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - $tenEuros->lessThan($anotherTenEuros); - } - - public function testLessThanOrEqual() : void - { - $ten = '10.00'; - $five = '5.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = Money::create($ten, $euroCurrency); - $fiveEuros = Money::create($five, $euroCurrency); - $fifteenEuros = Money::create($fifteen, $euroCurrency); - - Assert::assertTrue($tenEuros->lessThanOrEqual($anotherTenEuros)); - Assert::assertFalse($tenEuros->lessThanOrEqual($fiveEuros)); - Assert::assertTrue($tenEuros->lessThanOrEqual($fifteenEuros)); - } - - public function testCantCompareLessThanOrEqualWithOtherSubunitMoney() : void - { - $ten = '10.00'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: lessThanOrEqual on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - $tenEuros->lessThanOrEqual($anotherTenEuros); - } - - public function testGetAmount() : void - { - $amount = '12.34'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = Money::create($amount, $currency); - - Assert::assertSame($amount, $money->getAmount()); - } - - public function testGetCurrency() : void - { - $amount = '12.34'; - $code = 'EUR'; - - $currency = Currency::create($code); - $money = Money::create($amount, $currency); - - Assert::assertSame($code, $money->getCurrency()->getCode()); - } - - public function testAdd() : void - { - $ten = '10.00'; - $minusFive = '-5.00'; - $half = '0.50'; - $fiveAndHalf = '5.50'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $minusFiveEuros = Money::create($minusFive, $euroCurrency); - $halfEuro = Money::create($half, $euroCurrency); - - $fiveAndHalfEuros = $tenEuros->add($minusFiveEuros, $halfEuro); - - Assert::assertInstanceOf(Money::class, $fiveAndHalfEuros); - Assert::assertSame($fiveAndHalf, $fiveAndHalfEuros->getAmount()); - Assert::assertSame($euro, $fiveAndHalfEuros->getCurrency()->getCode()); - } - - public function testAddExtendedClassReturnsBaseClass() : void - { - $ten = '10.00'; - $half = '0.50'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = ExtendedMoney::create($ten, $euroCurrency); - $halfEuro = ExtendedMoney::create($half, $euroCurrency); - - $tenAndHalfEuros = $tenEuros->add($halfEuro); - - Assert::assertInstanceOf(Money::class, $tenAndHalfEuros); - } - - public function testCantAddOtherCurrencyMoney() : void - { - $ten = '10.00'; - $euro = 'EUR'; - $dollar = 'USD'; - - $euroCurrency = Currency::create($euro); - $dollarCurrency = Currency::create($dollar); - $tenEuros = Money::create($ten, $euroCurrency); - $tenDollars = Money::create($ten, $dollarCurrency); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Currencies must be identical'); - - $tenEuros->add($tenDollars); - } - - public function testCantAddOtherSubunitMoney() : void - { - $ten = '10.00'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: add on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - $tenEuros->add($anotherTenEuros); - } - - public function testSubtract() : void - { - $ten = '10.00'; - $minusFive = '-5.00'; - $half = '0.50'; - $fourteenAndHalf = '14.50'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $minusFiveEuros = Money::create($minusFive, $euroCurrency); - $halfEuro = Money::create($half, $euroCurrency); - - $fourteenAndHalfEuros = $tenEuros->subtract($minusFiveEuros, $halfEuro); - - Assert::assertInstanceOf(Money::class, $fourteenAndHalfEuros); - Assert::assertSame($fourteenAndHalf, $fourteenAndHalfEuros->getAmount()); - Assert::assertSame($euro, $fourteenAndHalfEuros->getCurrency()->getCode()); - } - - public function testSubtractExtendedClassReturnsBaseClass() : void - { - $ten = '10.00'; - $half = '0.50'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = ExtendedMoney::create($ten, $euroCurrency); - $halfEuro = ExtendedMoney::create($half, $euroCurrency); - - $nineAndHalfEuros = $tenEuros->subtract($halfEuro); - - Assert::assertInstanceOf(Money::class, $nineAndHalfEuros); - } - - public function testCantSubtractOtherCurrencyMoney() : void - { - $ten = '10.00'; - $euro = 'EUR'; - $dollar = 'USD'; - $subunits = 2; - - $euroCurrency = Currency::create($euro); - $dollarCurrency = Currency::create($dollar); - $tenEuros = Money::create($ten, $euroCurrency); - $tenDollars = Money::create($ten, $dollarCurrency); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Currencies must be identical'); - - $tenEuros->subtract($tenDollars); - } - - public function testCantSubtractOtherSubunitMoney() : void - { - $ten = '10.00'; - $euro = 'EUR'; - - $euroCurrency = Currency::create($euro); - $tenEuros = Money::create($ten, $euroCurrency); - $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: subtract on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - $tenEuros->subtract($anotherTenEuros); - } - - public function testMultiply() : void - { - $amount = '3.33'; - $multiplier = '2.22'; - $multipliedAmount = '7.40'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = Money::create($amount, $currency); - - $multipliedMoney = $money->multiply($multiplier); - - Assert::assertInstanceOf(Money::class, $multipliedMoney); - Assert::assertSame($multipliedAmount, $multipliedMoney->getAmount()); - Assert::assertSame($euro, $multipliedMoney->getCurrency()->getCode()); - } - - public function testMultiplyRoundingModeOtherThanDefault() : void - { - $amount = '3.33'; - $multiplier = '2.22'; - $multipliedAmount = '7.39'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = Money::create($amount, $currency); - - $multipliedMoney = $money->multiply($multiplier, LibMoney::ROUND_DOWN); - - Assert::assertSame($multipliedAmount, $multipliedMoney->getAmount()); - } - - public function testMultiplyExtendedClassReturnsBaseClass() : void - { - $amount = '3.33'; - $multiplier = '2.22'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = ExtendedMoney::create($amount, $currency); - - $multipliedMoney = $money->multiply($multiplier); - - Assert::assertInstanceOf(Money::class, $multipliedMoney); - } - - public function testDivide() : void - { - $amount = '3.33'; - $divisor = '1.55'; - $dividedAmount = '2.15'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = Money::create($amount, $currency); - - $dividedMoney = $money->divide($divisor); - - Assert::assertInstanceOf(Money::class, $dividedMoney); - Assert::assertSame($dividedAmount, $dividedMoney->getAmount()); - Assert::assertSame($euro, $dividedMoney->getCurrency()->getCode()); - } - - public function testDivideRoundingModeOtherThanDefault() : void - { - $amount = '3.33'; - $divisor = '1.55'; - $dividedAmount = '2.14'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = Money::create($amount, $currency); - - $dividedMoney = $money->divide($divisor, LibMoney::ROUND_DOWN); - - Assert::assertInstanceOf(Money::class, $dividedMoney); - Assert::assertSame($dividedAmount, $dividedMoney->getAmount()); - Assert::assertSame($euro, $dividedMoney->getCurrency()->getCode()); - } - - public function testDivideExtendedClassReturnsBaseClass() : void - { - $amount = '3.33'; - $divisor = '1.55'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = Money::create($amount, $currency); - - $dividedMoney = $money->divide($divisor); - - Assert::assertInstanceOf(Money::class, $dividedMoney); - } - - public function testMod() : void - { - $amount = '3.33'; - $divisorAmount = '3.00'; - $remainingAmount = '0.33'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = Money::create($amount, $currency); - $divisorMoney = Money::create($divisorAmount, $currency); - - $remainingMoney = $money->mod($divisorMoney); - - Assert::assertInstanceOf(Money::class, $remainingMoney); - Assert::assertSame($remainingAmount, $remainingMoney->getAmount()); - Assert::assertSame($euro, $remainingMoney->getCurrency()->getCode()); - } - - public function testModExtendedClassReturnsBaseClass() : void - { - $amount = '3.33'; - $divisorAmount = '3.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = ExtendedMoney::create($amount, $currency); - $divisorMoney = Money::create($divisorAmount, $currency); - - $remainingMoney = $money->mod($divisorMoney); - - Assert::assertInstanceOf(Money::class, $remainingMoney); - } - - public function testCantModOtherCurrencyMoney() : void - { - $amount = '3.33'; - $divisorAmount = '3.00'; - $remainingAmount = '0.33'; - $euro = 'EUR'; - $dollar = 'USD'; - - $euroCurrency = Currency::create($euro); - $dollarCurrency = Currency::create($dollar); - $money = Money::create($amount, $euroCurrency); - $divisorMoney = Money::create($divisorAmount, $dollarCurrency); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Currencies must be identical'); - - $money->mod($divisorMoney); - } - - public function testCantModOtherSubunitMoney() : void - { - $amount = '3.33'; - $divisorAmount = '3.00'; - $remainingAmount = '0.33'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = Money::create($amount, $currency); - $divisorMoney = GaapMoney::create($divisorAmount, $currency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: mod on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - $money->mod($divisorMoney); - } - - public function testAllocate() : void - { - $amount = '0.05'; - $ratios = ['70', '30']; - $firstAllocatedAmount = '0.04'; - $secondAllocatedAmount = '0.01'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = Money::create($amount, $currency); - - [$firstAllocatedMoney, $secondAllocatedMoney] = $money->allocate(...$ratios); - - Assert::assertInstanceOf(Money::class, $firstAllocatedMoney); - Assert::assertSame($firstAllocatedAmount, $firstAllocatedMoney->getAmount()); - Assert::assertSame($euro, $firstAllocatedMoney->getCurrency()->getCode()); - Assert::assertInstanceOf(Money::class, $secondAllocatedMoney); - Assert::assertSame($secondAllocatedAmount, $secondAllocatedMoney->getAmount()); - Assert::assertSame($euro, $secondAllocatedMoney->getCurrency()->getCode()); - } - - public function testAllocateExtendedClassReturnsBaseClass() : void - { - $amount = '0.05'; - $ratios = ['70', '30']; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = ExtendedMoney::create($amount, $currency); - - [$firstAllocatedMoney, $secondAllocatedMoney] = $money->allocate(...$ratios); - - Assert::assertInstanceOf(Money::class, $firstAllocatedMoney); - Assert::assertInstanceOf(Money::class, $secondAllocatedMoney); - } - - public function testAllocateTo() : void - { - $amount = '8.00'; - $n = 3; - $firstAllocatedAmount = '2.67'; - $secondAllocatedAmount = '2.67'; - $thirdAllocatedAmount = '2.66'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = Money::create($amount, $currency); - - [$firstAllocatedMoney, $secondAllocatedMoney, $thirdAllocatedMoney] = $money->allocateTo($n); - - Assert::assertInstanceOf(Money::class, $firstAllocatedMoney); - Assert::assertSame($firstAllocatedAmount, $firstAllocatedMoney->getAmount()); - Assert::assertSame($euro, $firstAllocatedMoney->getCurrency()->getCode()); - Assert::assertInstanceOf(Money::class, $secondAllocatedMoney); - Assert::assertSame($secondAllocatedAmount, $secondAllocatedMoney->getAmount()); - Assert::assertSame($euro, $secondAllocatedMoney->getCurrency()->getCode()); - Assert::assertInstanceOf(Money::class, $thirdAllocatedMoney); - Assert::assertSame($thirdAllocatedAmount, $thirdAllocatedMoney->getAmount()); - Assert::assertSame($euro, $thirdAllocatedMoney->getCurrency()->getCode()); - } - - public function testAllocateToExtendedClassReturnsBaseClass() : void - { - $amount = '8.00'; - $n = 3; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = ExtendedMoney::create($amount, $currency); - - [$firstAllocatedMoney, $secondAllocatedMoney, $thirdAllocatedMoney] = $money->allocateTo($n); - - Assert::assertInstanceOf(Money::class, $firstAllocatedMoney); - Assert::assertInstanceOf(Money::class, $secondAllocatedMoney); - Assert::assertInstanceOf(Money::class, $thirdAllocatedMoney); - } - - public function testRatioOf() : void - { - $three = '3.00'; - $six = '6.00'; - $expectedRatio = '0.50000000000000'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $threeEuros = Money::create($three, $currency); - $sixEuros = Money::create($six, $currency); - - $ratio = $threeEuros->ratioOf($sixEuros); - - Assert::assertSame($expectedRatio, $ratio); - } - - public function testCantRatioOfOtherSubunitMoney() : void - { - $three = '3.00'; - $six = '6.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $threeEuros = Money::create($three, $currency); - $sixEuros = GaapMoney::create($six, $currency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: ratioOf on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - $threeEuros->ratioOf($sixEuros); - } - - public function testAbsolute() : void - { - $amount = '-3.00'; - $absoluteAmount = '3.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = Money::create($amount, $currency); - - $absoluteMoney = $money->absolute(); - - Assert::assertInstanceOf(Money::class, $absoluteMoney); - Assert::assertSame($absoluteAmount, $absoluteMoney->getAmount()); - Assert::assertSame($euro, $absoluteMoney->getCurrency()->getCode()); - } - - public function testAbsoluteExtendedClassReturnsBaseClass() : void - { - $amount = '-3.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = ExtendedMoney::create($amount, $currency); - - $absoluteMoney = $money->absolute(); - - Assert::assertInstanceOf(Money::class, $absoluteMoney); - } - - public function testNegative() : void - { - $amount = '3.00'; - $negativeAmount = '-3.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = Money::create($amount, $currency); - - $negativeMoney = $money->negative(); - - Assert::assertInstanceOf(Money::class, $negativeMoney); - Assert::assertSame($negativeAmount, $negativeMoney->getAmount()); - Assert::assertSame($euro, $negativeMoney->getCurrency()->getCode()); - } - - public function testNegativeExtendedClassReturnsBaseClass() : void - { - $amount = '3.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $money = ExtendedMoney::create($amount, $currency); - - $negativeMoney = $money->negative(); - - Assert::assertInstanceOf(Money::class, $negativeMoney); - } - - public function testIsZero() : void - { - $zeroAmount = '0.00'; - $positiveAmount = '0.01'; - $negativeAmount = '-0.01'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $zeroAmountMoney = Money::create($zeroAmount, $currency); - $positiveAmountMoney = Money::create($positiveAmount, $currency); - $negativeAmountMoney = Money::create($negativeAmount, $currency); - - Assert::assertTrue($zeroAmountMoney->isZero()); - Assert::assertFalse($positiveAmountMoney->isZero()); - Assert::assertFalse($negativeAmountMoney->isZero()); - } - - public function testIsPositive() : void - { - $zeroAmount = '0.00'; - $positiveAmount = '0.01'; - $negativeAmount = '-0.01'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $zeroAmountMoney = Money::create($zeroAmount, $currency); - $positiveAmountMoney = Money::create($positiveAmount, $currency); - $negativeAmountMoney = Money::create($negativeAmount, $currency); - - Assert::assertFalse($zeroAmountMoney->isPositive()); - Assert::assertTrue($positiveAmountMoney->isPositive()); - Assert::assertFalse($negativeAmountMoney->isPositive()); - } - - public function testIsNegative() : void - { - $zeroAmount = '0.00'; - $positiveAmount = '0.01'; - $negativeAmount = '-0.01'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $zeroAmountMoney = Money::create($zeroAmount, $currency); - $positiveAmountMoney = Money::create($positiveAmount, $currency); - $negativeAmountMoney = Money::create($negativeAmount, $currency); - - Assert::assertFalse($zeroAmountMoney->isNegative()); - Assert::assertFalse($positiveAmountMoney->isNegative()); - Assert::assertTrue($negativeAmountMoney->isNegative()); - } - - public function testJsonSerialize() : void - { - $amount = '10.00'; - $euro = 'EUR'; - $expectedSerialized = [ - 'amount' => $amount, - 'currency' => $euro, - ]; - - $currency = Currency::create($euro); - $money = Money::create($amount, $currency); - - Assert::assertSame($expectedSerialized, $money->jsonSerialize()); - } - - public function testMin() : void - { - $ten = '10.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $tenEuros = Money::create($ten, $currency); - $fifteenEuros = Money::create($fifteen, $currency); - - Assert::assertSame($tenEuros, Money::min($tenEuros, $fifteenEuros)); - } - - public function testCantMinOtherCurrencyMoney() : void - { - $ten = '10.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - $dollar = 'USD'; - - $euroCurrency = Currency::create($euro); - $dollarCurrency = Currency::create($dollar); - $tenEuros = Money::create($ten, $euroCurrency); - $fifteenDollars = Money::create($fifteen, $dollarCurrency); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Currencies must be identical'); - - Money::min($tenEuros, $fifteenDollars); - } - - public function testCantMinOtherSubunitMoney() : void - { - $ten = '10.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $tenEuros = Money::create($ten, $currency); - $fifteenEuros = GaapMoney::create($fifteen, $currency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: min on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - Money::min($tenEuros, $fifteenEuros); - } - - public function testMax() : void - { - $ten = '10.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $tenEuros = Money::create($ten, $currency); - $fifteenEuros = Money::create($fifteen, $currency); - - Assert::assertSame($fifteenEuros, Money::max($tenEuros, $fifteenEuros)); - } - - public function testCantMaxOtherCurrencyMoney() : void - { - $ten = '10.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - $dollar = 'USD'; - - $euroCurrency = Currency::create($euro); - $dollarCurrency = Currency::create($dollar); - $tenEuros = Money::create($ten, $euroCurrency); - $fifteenDollars = Money::create($fifteen, $dollarCurrency); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Currencies must be identical'); - - Money::max($tenEuros, $fifteenDollars); - } - - public function testCantMaxOtherSubunitMoney() : void - { - $ten = '10.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $tenEuros = Money::create($ten, $currency); - $fifteenEuros = GaapMoney::create($fifteen, $currency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: max on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - Money::max($tenEuros, $fifteenEuros); - } - - public function testSum() : void - { - $ten = '10.00'; - $fifteen = '15.00'; - $twentyFive = '25.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $tenEuros = Money::create($ten, $currency); - $fifteenEuros = Money::create($fifteen, $currency); - - $moneySum = Money::sum($tenEuros, $fifteenEuros); - - Assert::assertInstanceOf(Money::class, $moneySum); - Assert::assertSame($twentyFive, $moneySum->getAmount()); - Assert::assertSame($euro, $moneySum->getCurrency()->getCode()); - } - - public function testCantSumOtherCurrencyMoney() : void - { - $ten = '10.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - $dollar = 'USD'; - - $euroCurrency = Currency::create($euro); - $dollarCurrency = Currency::create($dollar); - $tenEuros = Money::create($ten, $euroCurrency); - $fifteenDollars = Money::create($fifteen, $dollarCurrency); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Currencies must be identical'); - - Money::sum($tenEuros, $fifteenDollars); - } - - public function testCantSumOtherSubunitMoney() : void - { - $ten = '10.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $tenEuros = Money::create($ten, $currency); - $fifteenEuros = GaapMoney::create($fifteen, $currency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: sum on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - Money::sum($tenEuros, $fifteenEuros); - } - - public function testAvg() : void - { - $ten = '10.00'; - $twenty = '20.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $tenEuros = Money::create($ten, $currency); - $twentyEuros = Money::create($twenty, $currency); - - $avgMoney = Money::avg($tenEuros, $twentyEuros); - - Assert::assertInstanceOf(Money::class, $avgMoney); - Assert::assertSame($fifteen, $avgMoney->getAmount()); - Assert::assertSame($euro, $avgMoney->getCurrency()->getCode()); - } - - public function testCantAvgOtherCurrencyMoney() : void - { - $ten = '10.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - $dollar = 'USD'; - - $euroCurrency = Currency::create($euro); - $dollarCurrency = Currency::create($dollar); - $tenEuros = Money::create($ten, $euroCurrency); - $fifteenDollars = Money::create($fifteen, $dollarCurrency); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Currencies must be identical'); - - Money::avg($tenEuros, $fifteenDollars); - } - - public function testCantAvgOtherSubunitMoney() : void - { - $ten = '10.00'; - $fifteen = '15.00'; - $euro = 'EUR'; - - $currency = Currency::create($euro); - $tenEuros = Money::create($ten, $currency); - $fifteenEuros = GaapMoney::create($fifteen, $currency); - - $this->expectException(CannotWorkWithMoney::class); - $this->expectExceptionMessage('Cannot execute method: avg on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); - - Money::avg($tenEuros, $fifteenEuros); - } -} +getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCreateExtendedClass(): void + { + $amount = '100.00'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = ExtendedMoney::create($amount, $currency); + + Assert::assertInstanceOf(ExtendedMoney::class, $money); + Assert::assertSame($amount, $money->getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCreateFromTrailingZeroAmount(): void + { + $amount = '00.01'; + $outputAmount = '0.01'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = ExtendedMoney::create($amount, $currency); + + Assert::assertSame($outputAmount, $money->getAmount()); + } + + public function testCreateValidateSuccess(): void + { + $amount = '100.00'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = CheckAmountMoney::create($amount, $currency); + + Assert::assertInstanceOf(CheckAmountMoney::class, $money); + } + + public function testCreateValidateFailure(): void + { + $amount = '100.01'; + $code = 'EUR'; + + $currency = Currency::create($code); + + $this->expectException(CannotCreateMoney::class); + $this->expectExceptionMessage('Money amount is greater than 100.00 EUR'); + + $money = CheckAmountMoney::create($amount, $currency); + } + + public function testCanCreateWithNegativeAmount(): void + { + $amount = '-0.01'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = Money::create($amount, $currency); + + Assert::assertInstanceOf(Money::class, $money); + Assert::assertSame($amount, $money->getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCanCreateWithZeroAmount(): void + { + $amount = '0.00'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = Money::create($amount, $currency); + + Assert::assertInstanceOf(Money::class, $money); + Assert::assertSame($amount, $money->getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCanCreateWithPositiveAmount(): void + { + $amount = '0.01'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = Money::create($amount, $currency); + + Assert::assertInstanceOf(Money::class, $money); + Assert::assertSame($amount, $money->getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCantCreateWithZeroAmountIfMustBeGreaterThanZeroApplyed(): void + { + $amount = '0.00'; + $code = 'EUR'; + + $currency = Currency::create($code); + + $this->expectException(CannotCreateMoney::class); + $this->expectExceptionMessage('Invalid Money with amount: 0.00 and currency: EUR. Amount must be greater than zero.'); + + $money = AmountMustBeGreaterThanZeroMoney::create($amount, $currency); + } + + public function testCantCreateWithNegativeAmountIfMustBeGreaterThanZeroApplyed(): void + { + $amount = '-0.01'; + $code = 'EUR'; + + $currency = Currency::create($code); + + $this->expectException(CannotCreateMoney::class); + $this->expectExceptionMessage('Invalid Money with amount: -0.01 and currency: EUR. Amount must be greater than zero.'); + + $money = AmountMustBeGreaterThanZeroMoney::create($amount, $currency); + } + + public function testCanCreateWithPositiveAmountIfMustBeGreaterThanZeroApplyed(): void + { + $amount = '0.01'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = AmountMustBeGreaterThanZeroMoney::create($amount, $currency); + + Assert::assertSame($amount, $money->getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCantCreateWithNegativeAmountIfMustBeZeroOrGreaterApplyed(): void + { + $amount = '-0.01'; + $code = 'EUR'; + + $currency = Currency::create($code); + + $this->expectException(CannotCreateMoney::class); + $this->expectExceptionMessage('Invalid Money with amount: -0.01 and currency: EUR. Amount must be zero or greater.'); + + $money = AmountMustBeZeroOrGreaterMoney::create($amount, $currency); + } + + public function testCanCreateWithZeroAmountIfMustBeZeroOrGreaterApplyed(): void + { + $amount = '0.00'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = AmountMustBeZeroOrGreaterMoney::create($amount, $currency); + + Assert::assertSame($amount, $money->getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCanCreateWithPositiveAmountIfMustBeZeroOrGreaterApplyed(): void + { + $amount = '0.01'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = AmountMustBeZeroOrGreaterMoney::create($amount, $currency); + + Assert::assertSame($amount, $money->getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCantCreateWithPositiveAmountIfMustBeZeroOrLessApplyed(): void + { + $amount = '0.01'; + $code = 'EUR'; + + $currency = Currency::create($code); + + $this->expectException(CannotCreateMoney::class); + $this->expectExceptionMessage('Invalid Money with amount: 0.01 and currency: EUR. Amount must be zero or less.'); + + $money = AmountMustBeZeroOrLessMoney::create($amount, $currency); + } + + public function testCanCreateWithZeroAmountIfMustBeZeroOrLessApplyed(): void + { + $amount = '0.00'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = AmountMustBeZeroOrLessMoney::create($amount, $currency); + + Assert::assertSame($amount, $money->getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCanCreateWithNegativeAmountIfMustBeZeroOrLessApplyed(): void + { + $amount = '-0.01'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = AmountMustBeZeroOrLessMoney::create($amount, $currency); + + Assert::assertSame($amount, $money->getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCantCreateWithPositiveAmountIfMustBeLessThanZeroApplyed(): void + { + $amount = '0.01'; + $code = 'EUR'; + + $currency = Currency::create($code); + + $this->expectException(CannotCreateMoney::class); + $this->expectExceptionMessage('Invalid Money with amount: 0.01 and currency: EUR. Amount must be less than zero.'); + + $money = AmountMustBeLessThanZeroMoney::create($amount, $currency); + } + + public function testCantCreateWithZeroAmountIfMustBeLessThanZeroApplyed(): void + { + $amount = '0.00'; + $code = 'EUR'; + + $currency = Currency::create($code); + + $this->expectException(CannotCreateMoney::class); + $this->expectExceptionMessage('Invalid Money with amount: 0.00 and currency: EUR. Amount must be less than zero.'); + + $money = AmountMustBeLessThanZeroMoney::create($amount, $currency); + } + + public function testCanCreateWithNegativeAmountIfMustBeLessThanZeroApplyed(): void + { + $amount = '-0.01'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = AmountMustBeLessThanZeroMoney::create($amount, $currency); + + Assert::assertSame($amount, $money->getAmount()); + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testCantCreateWithInvalidAmountFormat(): void + { + $amount = '10.000'; + $code = 'EUR'; + + $currency = Currency::create($code); + + $this->expectException(CannotCreateMoney::class); + $this->expectExceptionMessage('Invalid Money with amount: 10.000 and currency: EUR. Invalid amount format. The correct format is: /^-?\d+\.\d{2}$/.'); + + $money = Money::create($amount, $currency); + } + + public function testCantCreateWithExceedingSubunitCurrency(): void + { + $amount = '10.000'; + $code = 'OMR'; + + $currency = Currency::create($code); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot instantiate OnMoon\Money\Tests\Mocks\InvalidSubunitCurrencyMoney with amount: 10.000 and currency: OMR. The currency has more subunits: 3 then the class allows: 2.'); + + $money = InvalidSubunitCurrencyMoney::create($amount, $currency); + } + + public function testCanCreateFromSameSubunitMoney(): void + { + $amount = '10.00'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = Money::create($amount, $currency); + $otherMoney = ExtendedMoney::createFromMoney($money); + + Assert::assertInstanceOf(ExtendedMoney::class, $otherMoney); + Assert::assertSame($amount, $otherMoney->getAmount()); + Assert::assertNotSame($currency, $otherMoney->getCurrency()); + Assert::assertSame($code, $otherMoney->getCurrency()->getCode()); + } + + public function testCantCreateFromOtherSubunitMoney(): void + { + $amount = '10.00'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = Money::create($amount, $currency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: createFromMoney on Money object: OnMoon\Money\GaapMoney with other Money object as argument: OnMoon\Money\Money. The classes have different subunits: 4 and 2.'); + + $otherMoney = GaapMoney::createFromMoney($money); + } + + public function testCanCreateZeroSubunitMoney(): void + { + $amount = '123'; + $code = 'DJF'; + + $currency = Currency::create($code); + $money = ZeroSubunitMoney::create($amount, $currency); + + Assert::assertSame($amount, $money->getAmount()); + } + + public function testCreateZeroSubunitMoneyInvalidFormatError(): void + { + $amount = '100.0'; + $code = 'DJF'; + + $currency = Currency::create($code); + + $this->expectException(CannotCreateMoney::class); + $this->expectExceptionMessage('Invalid Money with amount: 100.0 and currency: DJF. Invalid amount format. The correct format is: /^-?\d+$/.'); + + $money = ZeroSubunitMoney::create($amount, $currency); + } + + public function testIsSameCurrency(): void + { + $amount = '10.00'; + $firstCode = 'EUR'; + $secondCode = 'EUR'; + $thirdCode = 'USD'; + + $firstCurrency = Currency::create($firstCode); + $firstMoney = Money::create($amount, $firstCurrency); + $secondCurrency = Currency::create($secondCode); + $secondMoney = Money::create($amount, $secondCurrency); + $thirdCurrency = Currency::create($thirdCode); + $thirdMoney = Money::create($amount, $thirdCurrency); + + Assert::assertTrue($firstMoney->isSameCurrency($secondMoney)); + Assert::assertFalse($firstMoney->isSameCurrency($thirdMoney)); + } + + public function testEquals(): void + { + $ten = '10.00'; + $five = '5.00'; + $euro = 'EUR'; + $dollar = 'USD'; + + $euroCurrency = Currency::create($euro); + $dollarCurrency = Currency::create($dollar); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = Money::create($ten, $euroCurrency); + $fiveEuros = Money::create($five, $euroCurrency); + $tenDollars = Money::create($ten, $dollarCurrency); + + Assert::assertTrue($tenEuros->equals($anotherTenEuros)); + Assert::assertFalse($tenEuros->equals($fiveEuros)); + Assert::assertFalse($tenEuros->equals($tenDollars)); + } + + public function testCantCheckEqualityWithOtherSubunitMoney(): void + { + $ten = '10.00'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: equals on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + $tenEuros->equals($anotherTenEuros); + } + + public function testCompare(): void + { + $ten = '10.00'; + $five = '5.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = Money::create($ten, $euroCurrency); + $fiveEuros = Money::create($five, $euroCurrency); + $fifteenEuros = Money::create($fifteen, $euroCurrency); + + Assert::assertSame(0, $tenEuros->compare($anotherTenEuros)); + Assert::assertSame(1, $tenEuros->compare($fiveEuros)); + Assert::assertSame(-1, $tenEuros->compare($fifteenEuros)); + } + + public function testCantCompareWithOtherCurrencyMoney(): void + { + $ten = '10.00'; + $euro = 'EUR'; + $dollar = 'USD'; + + $euroCurrency = Currency::create($euro); + $dollarCurrency = Currency::create($dollar); + $tenEuros = Money::create($ten, $euroCurrency); + $tenDollars = Money::create($ten, $dollarCurrency); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Currencies must be identical'); + + $tenEuros->compare($tenDollars); + } + + public function testCantCompareWithOtherSubunitMoney(): void + { + $ten = '10.00'; + $euro = 'EUR'; + $subunits = 2; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: compare on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + $tenEuros->compare($anotherTenEuros); + } + + public function testGreaterThan(): void + { + $ten = '10.00'; + $five = '5.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = Money::create($ten, $euroCurrency); + $fiveEuros = Money::create($five, $euroCurrency); + $fifteenEuros = Money::create($fifteen, $euroCurrency); + + Assert::assertFalse($tenEuros->greaterThan($anotherTenEuros)); + Assert::assertTrue($tenEuros->greaterThan($fiveEuros)); + Assert::assertFalse($tenEuros->greaterThan($fifteenEuros)); + } + + public function testCantCompareGreaterThanWithOtherSubunitMoney(): void + { + $ten = '10.00'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: greaterThan on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + $tenEuros->greaterThan($anotherTenEuros); + } + + public function testGreaterThanOrEqual(): void + { + $ten = '10.00'; + $five = '5.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = Money::create($ten, $euroCurrency); + $fiveEuros = Money::create($five, $euroCurrency); + $fifteenEuros = Money::create($fifteen, $euroCurrency); + + Assert::assertTrue($tenEuros->greaterThanOrEqual($anotherTenEuros)); + Assert::assertTrue($tenEuros->greaterThanOrEqual($fiveEuros)); + Assert::assertFalse($tenEuros->greaterThanOrEqual($fifteenEuros)); + } + + public function testCantCompareGreaterThanOrEqualWithOtherSubunitMoney(): void + { + $ten = '10.00'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: greaterThanOrEqual on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + $tenEuros->greaterThanOrEqual($anotherTenEuros); + } + + public function testLessThan(): void + { + $ten = '10.00'; + $five = '5.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = Money::create($ten, $euroCurrency); + $fiveEuros = Money::create($five, $euroCurrency); + $fifteenEuros = Money::create($fifteen, $euroCurrency); + + Assert::assertFalse($tenEuros->lessThan($anotherTenEuros)); + Assert::assertFalse($tenEuros->lessThan($fiveEuros)); + Assert::assertTrue($tenEuros->lessThan($fifteenEuros)); + } + + public function testCantCompareLessThanWithOtherSubunitMoney(): void + { + $ten = '10.00'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: lessThan on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + $tenEuros->lessThan($anotherTenEuros); + } + + public function testLessThanOrEqual(): void + { + $ten = '10.00'; + $five = '5.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = Money::create($ten, $euroCurrency); + $fiveEuros = Money::create($five, $euroCurrency); + $fifteenEuros = Money::create($fifteen, $euroCurrency); + + Assert::assertTrue($tenEuros->lessThanOrEqual($anotherTenEuros)); + Assert::assertFalse($tenEuros->lessThanOrEqual($fiveEuros)); + Assert::assertTrue($tenEuros->lessThanOrEqual($fifteenEuros)); + } + + public function testCantCompareLessThanOrEqualWithOtherSubunitMoney(): void + { + $ten = '10.00'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: lessThanOrEqual on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + $tenEuros->lessThanOrEqual($anotherTenEuros); + } + + public function testGetAmount(): void + { + $amount = '12.34'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = Money::create($amount, $currency); + + Assert::assertSame($amount, $money->getAmount()); + } + + public function testGetCurrency(): void + { + $amount = '12.34'; + $code = 'EUR'; + + $currency = Currency::create($code); + $money = Money::create($amount, $currency); + + Assert::assertSame($code, $money->getCurrency()->getCode()); + } + + public function testAdd(): void + { + $ten = '10.00'; + $minusFive = '-5.00'; + $half = '0.50'; + $fiveAndHalf = '5.50'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $minusFiveEuros = Money::create($minusFive, $euroCurrency); + $halfEuro = Money::create($half, $euroCurrency); + + $fiveAndHalfEuros = $tenEuros->add($minusFiveEuros, $halfEuro); + + Assert::assertInstanceOf(Money::class, $fiveAndHalfEuros); + Assert::assertSame($fiveAndHalf, $fiveAndHalfEuros->getAmount()); + Assert::assertSame($euro, $fiveAndHalfEuros->getCurrency()->getCode()); + } + + public function testAddExtendedClassReturnsBaseClass(): void + { + $ten = '10.00'; + $half = '0.50'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = ExtendedMoney::create($ten, $euroCurrency); + $halfEuro = ExtendedMoney::create($half, $euroCurrency); + + $tenAndHalfEuros = $tenEuros->add($halfEuro); + + Assert::assertInstanceOf(Money::class, $tenAndHalfEuros); + } + + public function testCantAddOtherCurrencyMoney(): void + { + $ten = '10.00'; + $euro = 'EUR'; + $dollar = 'USD'; + + $euroCurrency = Currency::create($euro); + $dollarCurrency = Currency::create($dollar); + $tenEuros = Money::create($ten, $euroCurrency); + $tenDollars = Money::create($ten, $dollarCurrency); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Currencies must be identical'); + + $tenEuros->add($tenDollars); + } + + public function testCantAddOtherSubunitMoney(): void + { + $ten = '10.00'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: add on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + $tenEuros->add($anotherTenEuros); + } + + public function testSubtract(): void + { + $ten = '10.00'; + $minusFive = '-5.00'; + $half = '0.50'; + $fourteenAndHalf = '14.50'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $minusFiveEuros = Money::create($minusFive, $euroCurrency); + $halfEuro = Money::create($half, $euroCurrency); + + $fourteenAndHalfEuros = $tenEuros->subtract($minusFiveEuros, $halfEuro); + + Assert::assertInstanceOf(Money::class, $fourteenAndHalfEuros); + Assert::assertSame($fourteenAndHalf, $fourteenAndHalfEuros->getAmount()); + Assert::assertSame($euro, $fourteenAndHalfEuros->getCurrency()->getCode()); + } + + public function testSubtractExtendedClassReturnsBaseClass(): void + { + $ten = '10.00'; + $half = '0.50'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = ExtendedMoney::create($ten, $euroCurrency); + $halfEuro = ExtendedMoney::create($half, $euroCurrency); + + $nineAndHalfEuros = $tenEuros->subtract($halfEuro); + + Assert::assertInstanceOf(Money::class, $nineAndHalfEuros); + } + + public function testCantSubtractOtherCurrencyMoney(): void + { + $ten = '10.00'; + $euro = 'EUR'; + $dollar = 'USD'; + $subunits = 2; + + $euroCurrency = Currency::create($euro); + $dollarCurrency = Currency::create($dollar); + $tenEuros = Money::create($ten, $euroCurrency); + $tenDollars = Money::create($ten, $dollarCurrency); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Currencies must be identical'); + + $tenEuros->subtract($tenDollars); + } + + public function testCantSubtractOtherSubunitMoney(): void + { + $ten = '10.00'; + $euro = 'EUR'; + + $euroCurrency = Currency::create($euro); + $tenEuros = Money::create($ten, $euroCurrency); + $anotherTenEuros = GaapMoney::create($ten, $euroCurrency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: subtract on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + $tenEuros->subtract($anotherTenEuros); + } + + public function testMultiply(): void + { + $amount = '3.33'; + $multiplier = '2.22'; + $multipliedAmount = '7.40'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = Money::create($amount, $currency); + + $multipliedMoney = $money->multiply($multiplier); + + Assert::assertInstanceOf(Money::class, $multipliedMoney); + Assert::assertSame($multipliedAmount, $multipliedMoney->getAmount()); + Assert::assertSame($euro, $multipliedMoney->getCurrency()->getCode()); + } + + public function testMultiplyRoundingModeOtherThanDefault(): void + { + $amount = '3.33'; + $multiplier = '2.22'; + $multipliedAmount = '7.39'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = Money::create($amount, $currency); + + $multipliedMoney = $money->multiply($multiplier, LibMoney::ROUND_DOWN); + + Assert::assertSame($multipliedAmount, $multipliedMoney->getAmount()); + } + + public function testMultiplyExtendedClassReturnsBaseClass(): void + { + $amount = '3.33'; + $multiplier = '2.22'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = ExtendedMoney::create($amount, $currency); + + $multipliedMoney = $money->multiply($multiplier); + + Assert::assertInstanceOf(Money::class, $multipliedMoney); + } + + public function testDivide(): void + { + $amount = '3.33'; + $divisor = '1.55'; + $dividedAmount = '2.15'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = Money::create($amount, $currency); + + $dividedMoney = $money->divide($divisor); + + Assert::assertInstanceOf(Money::class, $dividedMoney); + Assert::assertSame($dividedAmount, $dividedMoney->getAmount()); + Assert::assertSame($euro, $dividedMoney->getCurrency()->getCode()); + } + + public function testDivideRoundingModeOtherThanDefault(): void + { + $amount = '3.33'; + $divisor = '1.55'; + $dividedAmount = '2.14'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = Money::create($amount, $currency); + + $dividedMoney = $money->divide($divisor, LibMoney::ROUND_DOWN); + + Assert::assertInstanceOf(Money::class, $dividedMoney); + Assert::assertSame($dividedAmount, $dividedMoney->getAmount()); + Assert::assertSame($euro, $dividedMoney->getCurrency()->getCode()); + } + + public function testDivideExtendedClassReturnsBaseClass(): void + { + $amount = '3.33'; + $divisor = '1.55'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = Money::create($amount, $currency); + + $dividedMoney = $money->divide($divisor); + + Assert::assertInstanceOf(Money::class, $dividedMoney); + } + + public function testMod(): void + { + $amount = '3.33'; + $divisorAmount = '3.00'; + $remainingAmount = '0.33'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = Money::create($amount, $currency); + $divisorMoney = Money::create($divisorAmount, $currency); + + $remainingMoney = $money->mod($divisorMoney); + + Assert::assertInstanceOf(Money::class, $remainingMoney); + Assert::assertSame($remainingAmount, $remainingMoney->getAmount()); + Assert::assertSame($euro, $remainingMoney->getCurrency()->getCode()); + } + + public function testModExtendedClassReturnsBaseClass(): void + { + $amount = '3.33'; + $divisorAmount = '3.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = ExtendedMoney::create($amount, $currency); + $divisorMoney = Money::create($divisorAmount, $currency); + + $remainingMoney = $money->mod($divisorMoney); + + Assert::assertInstanceOf(Money::class, $remainingMoney); + } + + public function testCantModOtherCurrencyMoney(): void + { + $amount = '3.33'; + $divisorAmount = '3.00'; + $remainingAmount = '0.33'; + $euro = 'EUR'; + $dollar = 'USD'; + + $euroCurrency = Currency::create($euro); + $dollarCurrency = Currency::create($dollar); + $money = Money::create($amount, $euroCurrency); + $divisorMoney = Money::create($divisorAmount, $dollarCurrency); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Currencies must be identical'); + + $money->mod($divisorMoney); + } + + public function testCantModOtherSubunitMoney(): void + { + $amount = '3.33'; + $divisorAmount = '3.00'; + $remainingAmount = '0.33'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = Money::create($amount, $currency); + $divisorMoney = GaapMoney::create($divisorAmount, $currency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: mod on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + $money->mod($divisorMoney); + } + + public function testAllocate(): void + { + $amount = '0.05'; + $ratios = ['70', '30']; + $firstAllocatedAmount = '0.04'; + $secondAllocatedAmount = '0.01'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = Money::create($amount, $currency); + + [$firstAllocatedMoney, $secondAllocatedMoney] = $money->allocate(...$ratios); + + Assert::assertInstanceOf(Money::class, $firstAllocatedMoney); + Assert::assertSame($firstAllocatedAmount, $firstAllocatedMoney->getAmount()); + Assert::assertSame($euro, $firstAllocatedMoney->getCurrency()->getCode()); + Assert::assertInstanceOf(Money::class, $secondAllocatedMoney); + Assert::assertSame($secondAllocatedAmount, $secondAllocatedMoney->getAmount()); + Assert::assertSame($euro, $secondAllocatedMoney->getCurrency()->getCode()); + } + + public function testAllocateExtendedClassReturnsBaseClass(): void + { + $amount = '0.05'; + $ratios = ['70', '30']; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = ExtendedMoney::create($amount, $currency); + + [$firstAllocatedMoney, $secondAllocatedMoney] = $money->allocate(...$ratios); + + Assert::assertInstanceOf(Money::class, $firstAllocatedMoney); + Assert::assertInstanceOf(Money::class, $secondAllocatedMoney); + } + + public function testAllocateTo(): void + { + $amount = '8.00'; + $n = 3; + $firstAllocatedAmount = '2.67'; + $secondAllocatedAmount = '2.67'; + $thirdAllocatedAmount = '2.66'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = Money::create($amount, $currency); + + [$firstAllocatedMoney, $secondAllocatedMoney, $thirdAllocatedMoney] = $money->allocateTo($n); + + Assert::assertInstanceOf(Money::class, $firstAllocatedMoney); + Assert::assertSame($firstAllocatedAmount, $firstAllocatedMoney->getAmount()); + Assert::assertSame($euro, $firstAllocatedMoney->getCurrency()->getCode()); + Assert::assertInstanceOf(Money::class, $secondAllocatedMoney); + Assert::assertSame($secondAllocatedAmount, $secondAllocatedMoney->getAmount()); + Assert::assertSame($euro, $secondAllocatedMoney->getCurrency()->getCode()); + Assert::assertInstanceOf(Money::class, $thirdAllocatedMoney); + Assert::assertSame($thirdAllocatedAmount, $thirdAllocatedMoney->getAmount()); + Assert::assertSame($euro, $thirdAllocatedMoney->getCurrency()->getCode()); + } + + public function testAllocateToExtendedClassReturnsBaseClass(): void + { + $amount = '8.00'; + $n = 3; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = ExtendedMoney::create($amount, $currency); + + [$firstAllocatedMoney, $secondAllocatedMoney, $thirdAllocatedMoney] = $money->allocateTo($n); + + Assert::assertInstanceOf(Money::class, $firstAllocatedMoney); + Assert::assertInstanceOf(Money::class, $secondAllocatedMoney); + Assert::assertInstanceOf(Money::class, $thirdAllocatedMoney); + } + + public function testRatioOf(): void + { + $three = '3.00'; + $six = '6.00'; + $expectedRatio = '0.50000000000000'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $threeEuros = Money::create($three, $currency); + $sixEuros = Money::create($six, $currency); + + $ratio = $threeEuros->ratioOf($sixEuros); + + Assert::assertSame($expectedRatio, $ratio); + } + + public function testCantRatioOfOtherSubunitMoney(): void + { + $three = '3.00'; + $six = '6.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $threeEuros = Money::create($three, $currency); + $sixEuros = GaapMoney::create($six, $currency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: ratioOf on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + $threeEuros->ratioOf($sixEuros); + } + + public function testAbsolute(): void + { + $amount = '-3.00'; + $absoluteAmount = '3.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = Money::create($amount, $currency); + + $absoluteMoney = $money->absolute(); + + Assert::assertInstanceOf(Money::class, $absoluteMoney); + Assert::assertSame($absoluteAmount, $absoluteMoney->getAmount()); + Assert::assertSame($euro, $absoluteMoney->getCurrency()->getCode()); + } + + public function testAbsoluteExtendedClassReturnsBaseClass(): void + { + $amount = '-3.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = ExtendedMoney::create($amount, $currency); + + $absoluteMoney = $money->absolute(); + + Assert::assertInstanceOf(Money::class, $absoluteMoney); + } + + public function testNegative(): void + { + $amount = '3.00'; + $negativeAmount = '-3.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = Money::create($amount, $currency); + + $negativeMoney = $money->negative(); + + Assert::assertInstanceOf(Money::class, $negativeMoney); + Assert::assertSame($negativeAmount, $negativeMoney->getAmount()); + Assert::assertSame($euro, $negativeMoney->getCurrency()->getCode()); + } + + public function testNegativeExtendedClassReturnsBaseClass(): void + { + $amount = '3.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $money = ExtendedMoney::create($amount, $currency); + + $negativeMoney = $money->negative(); + + Assert::assertInstanceOf(Money::class, $negativeMoney); + } + + public function testIsZero(): void + { + $zeroAmount = '0.00'; + $positiveAmount = '0.01'; + $negativeAmount = '-0.01'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $zeroAmountMoney = Money::create($zeroAmount, $currency); + $positiveAmountMoney = Money::create($positiveAmount, $currency); + $negativeAmountMoney = Money::create($negativeAmount, $currency); + + Assert::assertTrue($zeroAmountMoney->isZero()); + Assert::assertFalse($positiveAmountMoney->isZero()); + Assert::assertFalse($negativeAmountMoney->isZero()); + } + + public function testIsPositive(): void + { + $zeroAmount = '0.00'; + $positiveAmount = '0.01'; + $negativeAmount = '-0.01'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $zeroAmountMoney = Money::create($zeroAmount, $currency); + $positiveAmountMoney = Money::create($positiveAmount, $currency); + $negativeAmountMoney = Money::create($negativeAmount, $currency); + + Assert::assertFalse($zeroAmountMoney->isPositive()); + Assert::assertTrue($positiveAmountMoney->isPositive()); + Assert::assertFalse($negativeAmountMoney->isPositive()); + } + + public function testIsNegative(): void + { + $zeroAmount = '0.00'; + $positiveAmount = '0.01'; + $negativeAmount = '-0.01'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $zeroAmountMoney = Money::create($zeroAmount, $currency); + $positiveAmountMoney = Money::create($positiveAmount, $currency); + $negativeAmountMoney = Money::create($negativeAmount, $currency); + + Assert::assertFalse($zeroAmountMoney->isNegative()); + Assert::assertFalse($positiveAmountMoney->isNegative()); + Assert::assertTrue($negativeAmountMoney->isNegative()); + } + + public function testJsonSerialize(): void + { + $amount = '10.00'; + $euro = 'EUR'; + $expectedSerialized = [ + 'amount' => $amount, + 'currency' => $euro, + ]; + + $currency = Currency::create($euro); + $money = Money::create($amount, $currency); + + Assert::assertSame($expectedSerialized, $money->jsonSerialize()); + } + + public function testMin(): void + { + $ten = '10.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $tenEuros = Money::create($ten, $currency); + $fifteenEuros = Money::create($fifteen, $currency); + + Assert::assertSame($tenEuros, Money::min($tenEuros, $fifteenEuros)); + } + + public function testCantMinOtherCurrencyMoney(): void + { + $ten = '10.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + $dollar = 'USD'; + + $euroCurrency = Currency::create($euro); + $dollarCurrency = Currency::create($dollar); + $tenEuros = Money::create($ten, $euroCurrency); + $fifteenDollars = Money::create($fifteen, $dollarCurrency); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Currencies must be identical'); + + Money::min($tenEuros, $fifteenDollars); + } + + public function testCantMinOtherSubunitMoney(): void + { + $ten = '10.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $tenEuros = Money::create($ten, $currency); + $fifteenEuros = GaapMoney::create($fifteen, $currency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: min on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + Money::min($tenEuros, $fifteenEuros); + } + + public function testMax(): void + { + $ten = '10.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $tenEuros = Money::create($ten, $currency); + $fifteenEuros = Money::create($fifteen, $currency); + + Assert::assertSame($fifteenEuros, Money::max($tenEuros, $fifteenEuros)); + } + + public function testCantMaxOtherCurrencyMoney(): void + { + $ten = '10.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + $dollar = 'USD'; + + $euroCurrency = Currency::create($euro); + $dollarCurrency = Currency::create($dollar); + $tenEuros = Money::create($ten, $euroCurrency); + $fifteenDollars = Money::create($fifteen, $dollarCurrency); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Currencies must be identical'); + + Money::max($tenEuros, $fifteenDollars); + } + + public function testCantMaxOtherSubunitMoney(): void + { + $ten = '10.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $tenEuros = Money::create($ten, $currency); + $fifteenEuros = GaapMoney::create($fifteen, $currency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: max on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + Money::max($tenEuros, $fifteenEuros); + } + + public function testSum(): void + { + $ten = '10.00'; + $fifteen = '15.00'; + $twentyFive = '25.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $tenEuros = Money::create($ten, $currency); + $fifteenEuros = Money::create($fifteen, $currency); + + $moneySum = Money::sum($tenEuros, $fifteenEuros); + + Assert::assertInstanceOf(Money::class, $moneySum); + Assert::assertSame($twentyFive, $moneySum->getAmount()); + Assert::assertSame($euro, $moneySum->getCurrency()->getCode()); + } + + public function testCantSumOtherCurrencyMoney(): void + { + $ten = '10.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + $dollar = 'USD'; + + $euroCurrency = Currency::create($euro); + $dollarCurrency = Currency::create($dollar); + $tenEuros = Money::create($ten, $euroCurrency); + $fifteenDollars = Money::create($fifteen, $dollarCurrency); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Currencies must be identical'); + + Money::sum($tenEuros, $fifteenDollars); + } + + public function testCantSumOtherSubunitMoney(): void + { + $ten = '10.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $tenEuros = Money::create($ten, $currency); + $fifteenEuros = GaapMoney::create($fifteen, $currency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: sum on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + Money::sum($tenEuros, $fifteenEuros); + } + + public function testAvg(): void + { + $ten = '10.00'; + $twenty = '20.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $tenEuros = Money::create($ten, $currency); + $twentyEuros = Money::create($twenty, $currency); + + $avgMoney = Money::avg($tenEuros, $twentyEuros); + + Assert::assertInstanceOf(Money::class, $avgMoney); + Assert::assertSame($fifteen, $avgMoney->getAmount()); + Assert::assertSame($euro, $avgMoney->getCurrency()->getCode()); + } + + public function testCantAvgOtherCurrencyMoney(): void + { + $ten = '10.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + $dollar = 'USD'; + + $euroCurrency = Currency::create($euro); + $dollarCurrency = Currency::create($dollar); + $tenEuros = Money::create($ten, $euroCurrency); + $fifteenDollars = Money::create($fifteen, $dollarCurrency); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Currencies must be identical'); + + Money::avg($tenEuros, $fifteenDollars); + } + + public function testCantAvgOtherSubunitMoney(): void + { + $ten = '10.00'; + $fifteen = '15.00'; + $euro = 'EUR'; + + $currency = Currency::create($euro); + $tenEuros = Money::create($ten, $currency); + $fifteenEuros = GaapMoney::create($fifteen, $currency); + + $this->expectException(CannotWorkWithMoney::class); + $this->expectExceptionMessage('Cannot execute method: avg on Money object: OnMoon\Money\Money with other Money object as argument: OnMoon\Money\GaapMoney. The classes have different subunits: 2 and 4.'); + + Money::avg($tenEuros, $fifteenEuros); + } +} diff --git a/tests/Type/BTCMoneyTypeTest.php b/tests/Type/BTCMoneyTypeTest.php index 0e8f8d7..bdb1257 100644 --- a/tests/Type/BTCMoneyTypeTest.php +++ b/tests/Type/BTCMoneyTypeTest.php @@ -1,129 +1,129 @@ -createMock(AbstractPlatform::class); - $platformMock - ->expects($this->once()) - ->method('getDecimalTypeDeclarationSQL') - ->with( - [ - 'precision' => 16, - 'scale' => 8, - ] - ) - ->willReturn(''); - - $type->getSQLDeclaration([], $platformMock); - } - - public function testGetSQLDeclarationWithFieldDeclaration() : void - { - $type = Type::getType(BTCMoneyType::TYPE_NAME); - - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - $platformMock - ->expects($this->once()) - ->method('getDecimalTypeDeclarationSQL') - ->with( - [ - 'something' => 10, - 'precision' => 16, - 'scale' => 8, - ] - ) - ->willReturn(''); - - $type->getSQLDeclaration( - [ - 'something' => 10, - 'scale' => 2, - ], - $platformMock - ); - } - - public function testConvertToPHPValue() : void - { - $expectedPhpValue = '10012345678'; - - $type = Type::getType(BTCMoneyType::TYPE_NAME); - - $databaseValue = '100.12345678'; - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - - $phpValue = $type->convertToPHPValue($databaseValue, $platformMock); - - Assert::assertSame($expectedPhpValue, $phpValue); - } - - public function testConvertToNullPHPValue() : void - { - $expectedPhpValue = null; - - $type = Type::getType(BTCMoneyType::TYPE_NAME); - - $databaseValue = null; - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - - $phpValue = $type->convertToPHPValue($databaseValue, $platformMock); - - Assert::assertSame($expectedPhpValue, $phpValue); - } - - public function testConvertToDatabaseValue() : void - { - $expectedDatabaseValue = '100.12345678'; - - $type = Type::getType(BTCMoneyType::TYPE_NAME); - - $phpValue = '10012345678'; - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - - $phpValue = $type->convertToDatabaseValue($phpValue, $platformMock); - - Assert::assertSame($expectedDatabaseValue, $phpValue); - } - - public function testConvertToNullDatabaseValue() : void - { - $expectedDatabaseValue = null; - - $type = Type::getType(BTCMoneyType::TYPE_NAME); - - $phpValue = null; - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - - $phpValue = $type->convertToDatabaseValue($phpValue, $platformMock); - - Assert::assertSame($expectedDatabaseValue, $phpValue); - } - - public function testGetName() : void - { - $type = Type::getType(BTCMoneyType::TYPE_NAME); - - Assert::assertSame(BTCMoneyType::TYPE_NAME, $type->getName()); - } -} +createMock(AbstractPlatform::class); + $platformMock + ->expects($this->once()) + ->method('getDecimalTypeDeclarationSQL') + ->with( + [ + 'precision' => 16, + 'scale' => 8, + ], + ) + ->willReturn(''); + + $type->getSQLDeclaration([], $platformMock); + } + + public function testGetSQLDeclarationWithFieldDeclaration(): void + { + $type = Type::getType(BTCMoneyType::TYPE_NAME); + + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + $platformMock + ->expects($this->once()) + ->method('getDecimalTypeDeclarationSQL') + ->with( + [ + 'something' => 10, + 'precision' => 16, + 'scale' => 8, + ], + ) + ->willReturn(''); + + $type->getSQLDeclaration( + [ + 'something' => 10, + 'scale' => 2, + ], + $platformMock, + ); + } + + public function testConvertToPHPValue(): void + { + $expectedPhpValue = '10012345678'; + + $type = Type::getType(BTCMoneyType::TYPE_NAME); + + $databaseValue = '100.12345678'; + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + + $phpValue = $type->convertToPHPValue($databaseValue, $platformMock); + + Assert::assertSame($expectedPhpValue, $phpValue); + } + + public function testConvertToNullPHPValue(): void + { + $expectedPhpValue = null; + + $type = Type::getType(BTCMoneyType::TYPE_NAME); + + $databaseValue = null; + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + + $phpValue = $type->convertToPHPValue($databaseValue, $platformMock); + + Assert::assertSame($expectedPhpValue, $phpValue); + } + + public function testConvertToDatabaseValue(): void + { + $expectedDatabaseValue = '100.12345678'; + + $type = Type::getType(BTCMoneyType::TYPE_NAME); + + $phpValue = '10012345678'; + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + + $phpValue = $type->convertToDatabaseValue($phpValue, $platformMock); + + Assert::assertSame($expectedDatabaseValue, $phpValue); + } + + public function testConvertToNullDatabaseValue(): void + { + $expectedDatabaseValue = null; + + $type = Type::getType(BTCMoneyType::TYPE_NAME); + + $phpValue = null; + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + + $phpValue = $type->convertToDatabaseValue($phpValue, $platformMock); + + Assert::assertSame($expectedDatabaseValue, $phpValue); + } + + public function testGetName(): void + { + $type = Type::getType(BTCMoneyType::TYPE_NAME); + + Assert::assertSame(BTCMoneyType::TYPE_NAME, $type->getName()); + } +} diff --git a/tests/Type/CurrencyTypeTest.php b/tests/Type/CurrencyTypeTest.php index d2b9a63..70a5def 100644 --- a/tests/Type/CurrencyTypeTest.php +++ b/tests/Type/CurrencyTypeTest.php @@ -1,63 +1,63 @@ -createMock(AbstractPlatform::class); - $platformMock - ->expects($this->once()) - ->method('getVarcharTypeDeclarationSQL') - ->with(['length' => 3]) - ->willReturn(''); - - $type->getSQLDeclaration([], $platformMock); - } - - public function testGetSQLDeclarationWithFieldDeclaration() : void - { - $type = Type::getType(CurrencyType::TYPE_NAME); - - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - $platformMock - ->expects($this->once()) - ->method('getVarcharTypeDeclarationSQL') - ->with( - [ - 'something' => 10, - 'length' => 3, - ] - ) - ->willReturn(''); - - $type->getSQLDeclaration( - [ - 'something' => 10, - 'length' => 2, - ], - $platformMock - ); - } - - public function testGetName() : void - { - $type = Type::getType(CurrencyType::TYPE_NAME); - - Assert::assertSame(CurrencyType::TYPE_NAME, $type->getName()); - } -} +createMock(AbstractPlatform::class); + $platformMock + ->expects($this->once()) + ->method('getStringTypeDeclarationSQL') + ->with(['length' => 3]) + ->willReturn(''); + + $type->getSQLDeclaration([], $platformMock); + } + + public function testGetSQLDeclarationWithFieldDeclaration(): void + { + $type = Type::getType(CurrencyType::TYPE_NAME); + + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + $platformMock + ->expects($this->once()) + ->method('getStringTypeDeclarationSQL') + ->with( + [ + 'something' => 10, + 'length' => 3, + ], + ) + ->willReturn(''); + + $type->getSQLDeclaration( + [ + 'something' => 10, + 'length' => 2, + ], + $platformMock, + ); + } + + public function testGetName(): void + { + $type = Type::getType(CurrencyType::TYPE_NAME); + + Assert::assertSame(CurrencyType::TYPE_NAME, $type->getName()); + } +} diff --git a/tests/Type/GaapMoneyTypeTest.php b/tests/Type/GaapMoneyTypeTest.php index 9f8e312..e2bf267 100644 --- a/tests/Type/GaapMoneyTypeTest.php +++ b/tests/Type/GaapMoneyTypeTest.php @@ -1,129 +1,129 @@ -createMock(AbstractPlatform::class); - $platformMock - ->expects($this->once()) - ->method('getDecimalTypeDeclarationSQL') - ->with( - [ - 'precision' => 15, - 'scale' => 4, - ] - ) - ->willReturn(''); - - $type->getSQLDeclaration([], $platformMock); - } - - public function testGetSQLDeclarationWithFieldDeclaration() : void - { - $type = Type::getType(GaapMoneyType::TYPE_NAME); - - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - $platformMock - ->expects($this->once()) - ->method('getDecimalTypeDeclarationSQL') - ->with( - [ - 'something' => 10, - 'precision' => 15, - 'scale' => 4, - ] - ) - ->willReturn(''); - - $type->getSQLDeclaration( - [ - 'something' => 10, - 'scale' => 2, - ], - $platformMock - ); - } - - public function testConvertToPHPValue() : void - { - $expectedPhpValue = '1001234'; - - $type = Type::getType(GaapMoneyType::TYPE_NAME); - - $databaseValue = '100.1234'; - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - - $phpValue = $type->convertToPHPValue($databaseValue, $platformMock); - - Assert::assertSame($expectedPhpValue, $phpValue); - } - - public function testConvertToNullPHPValue() : void - { - $expectedPhpValue = null; - - $type = Type::getType(GaapMoneyType::TYPE_NAME); - - $databaseValue = null; - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - - $phpValue = $type->convertToPHPValue($databaseValue, $platformMock); - - Assert::assertSame($expectedPhpValue, $phpValue); - } - - public function testConvertToDatabaseValue() : void - { - $expectedDatabaseValue = '100.1234'; - - $type = Type::getType(GaapMoneyType::TYPE_NAME); - - $phpValue = '1001234'; - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - - $phpValue = $type->convertToDatabaseValue($phpValue, $platformMock); - - Assert::assertSame($expectedDatabaseValue, $phpValue); - } - - public function testConvertToNullDatabaseValue() : void - { - $expectedDatabaseValue = null; - - $type = Type::getType(GaapMoneyType::TYPE_NAME); - - $phpValue = null; - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - - $phpValue = $type->convertToDatabaseValue($phpValue, $platformMock); - - Assert::assertSame($expectedDatabaseValue, $phpValue); - } - - public function testGetName() : void - { - $type = Type::getType(GaapMoneyType::TYPE_NAME); - - Assert::assertSame(GaapMoneyType::TYPE_NAME, $type->getName()); - } -} +createMock(AbstractPlatform::class); + $platformMock + ->expects($this->once()) + ->method('getDecimalTypeDeclarationSQL') + ->with( + [ + 'precision' => 15, + 'scale' => 4, + ], + ) + ->willReturn(''); + + $type->getSQLDeclaration([], $platformMock); + } + + public function testGetSQLDeclarationWithFieldDeclaration(): void + { + $type = Type::getType(GaapMoneyType::TYPE_NAME); + + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + $platformMock + ->expects($this->once()) + ->method('getDecimalTypeDeclarationSQL') + ->with( + [ + 'something' => 10, + 'precision' => 15, + 'scale' => 4, + ], + ) + ->willReturn(''); + + $type->getSQLDeclaration( + [ + 'something' => 10, + 'scale' => 2, + ], + $platformMock, + ); + } + + public function testConvertToPHPValue(): void + { + $expectedPhpValue = '1001234'; + + $type = Type::getType(GaapMoneyType::TYPE_NAME); + + $databaseValue = '100.1234'; + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + + $phpValue = $type->convertToPHPValue($databaseValue, $platformMock); + + Assert::assertSame($expectedPhpValue, $phpValue); + } + + public function testConvertToNullPHPValue(): void + { + $expectedPhpValue = null; + + $type = Type::getType(GaapMoneyType::TYPE_NAME); + + $databaseValue = null; + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + + $phpValue = $type->convertToPHPValue($databaseValue, $platformMock); + + Assert::assertSame($expectedPhpValue, $phpValue); + } + + public function testConvertToDatabaseValue(): void + { + $expectedDatabaseValue = '100.1234'; + + $type = Type::getType(GaapMoneyType::TYPE_NAME); + + $phpValue = '1001234'; + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + + $phpValue = $type->convertToDatabaseValue($phpValue, $platformMock); + + Assert::assertSame($expectedDatabaseValue, $phpValue); + } + + public function testConvertToNullDatabaseValue(): void + { + $expectedDatabaseValue = null; + + $type = Type::getType(GaapMoneyType::TYPE_NAME); + + $phpValue = null; + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + + $phpValue = $type->convertToDatabaseValue($phpValue, $platformMock); + + Assert::assertSame($expectedDatabaseValue, $phpValue); + } + + public function testGetName(): void + { + $type = Type::getType(GaapMoneyType::TYPE_NAME); + + Assert::assertSame(GaapMoneyType::TYPE_NAME, $type->getName()); + } +} diff --git a/tests/Type/MoneyTypeTest.php b/tests/Type/MoneyTypeTest.php index c9a8bfc..2e799c8 100644 --- a/tests/Type/MoneyTypeTest.php +++ b/tests/Type/MoneyTypeTest.php @@ -1,129 +1,129 @@ -createMock(AbstractPlatform::class); - $platformMock - ->expects($this->once()) - ->method('getDecimalTypeDeclarationSQL') - ->with( - [ - 'precision' => 10, - 'scale' => 2, - ] - ) - ->willReturn(''); - - $type->getSQLDeclaration([], $platformMock); - } - - public function testGetSQLDeclarationWithFieldDeclaration() : void - { - $type = Type::getType(MoneyType::TYPE_NAME); - - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - $platformMock - ->expects($this->once()) - ->method('getDecimalTypeDeclarationSQL') - ->with( - [ - 'something' => 11, - 'precision' => 10, - 'scale' => 2, - ] - ) - ->willReturn(''); - - $type->getSQLDeclaration( - [ - 'something' => 11, - 'scale' => 1, - ], - $platformMock - ); - } - - public function testConvertToPHPValue() : void - { - $expectedPhpValue = '10012'; - - $type = Type::getType(MoneyType::TYPE_NAME); - - $databaseValue = '100.12'; - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - - $phpValue = $type->convertToPHPValue($databaseValue, $platformMock); - - Assert::assertSame($expectedPhpValue, $phpValue); - } - - public function testConvertToNullPHPValue() : void - { - $expectedPhpValue = null; - - $type = Type::getType(MoneyType::TYPE_NAME); - - $databaseValue = null; - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - - $phpValue = $type->convertToPHPValue($databaseValue, $platformMock); - - Assert::assertSame($expectedPhpValue, $phpValue); - } - - public function testConvertToDatabaseValue() : void - { - $expectedDatabaseValue = '100.12'; - - $type = Type::getType(MoneyType::TYPE_NAME); - - $phpValue = '10012'; - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - - $phpValue = $type->convertToDatabaseValue($phpValue, $platformMock); - - Assert::assertSame($expectedDatabaseValue, $phpValue); - } - - public function testConvertToNullDatabaseValue() : void - { - $expectedDatabaseValue = null; - - $type = Type::getType(MoneyType::TYPE_NAME); - - $phpValue = null; - /** @var AbstractPlatform&MockObject $platformMock */ - $platformMock = $this->createMock(AbstractPlatform::class); - - $phpValue = $type->convertToDatabaseValue($phpValue, $platformMock); - - Assert::assertSame($expectedDatabaseValue, $phpValue); - } - - public function testGetName() : void - { - $type = Type::getType(MoneyType::TYPE_NAME); - - Assert::assertSame(MoneyType::TYPE_NAME, $type->getName()); - } -} +createMock(AbstractPlatform::class); + $platformMock + ->expects($this->once()) + ->method('getDecimalTypeDeclarationSQL') + ->with( + [ + 'precision' => 10, + 'scale' => 2, + ], + ) + ->willReturn(''); + + $type->getSQLDeclaration([], $platformMock); + } + + public function testGetSQLDeclarationWithFieldDeclaration(): void + { + $type = Type::getType(MoneyType::TYPE_NAME); + + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + $platformMock + ->expects($this->once()) + ->method('getDecimalTypeDeclarationSQL') + ->with( + [ + 'something' => 11, + 'precision' => 10, + 'scale' => 2, + ], + ) + ->willReturn(''); + + $type->getSQLDeclaration( + [ + 'something' => 11, + 'scale' => 1, + ], + $platformMock, + ); + } + + public function testConvertToPHPValue(): void + { + $expectedPhpValue = '10012'; + + $type = Type::getType(MoneyType::TYPE_NAME); + + $databaseValue = '100.12'; + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + + $phpValue = $type->convertToPHPValue($databaseValue, $platformMock); + + Assert::assertSame($expectedPhpValue, $phpValue); + } + + public function testConvertToNullPHPValue(): void + { + $expectedPhpValue = null; + + $type = Type::getType(MoneyType::TYPE_NAME); + + $databaseValue = null; + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + + $phpValue = $type->convertToPHPValue($databaseValue, $platformMock); + + Assert::assertSame($expectedPhpValue, $phpValue); + } + + public function testConvertToDatabaseValue(): void + { + $expectedDatabaseValue = '100.12'; + + $type = Type::getType(MoneyType::TYPE_NAME); + + $phpValue = '10012'; + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + + $phpValue = $type->convertToDatabaseValue($phpValue, $platformMock); + + Assert::assertSame($expectedDatabaseValue, $phpValue); + } + + public function testConvertToNullDatabaseValue(): void + { + $expectedDatabaseValue = null; + + $type = Type::getType(MoneyType::TYPE_NAME); + + $phpValue = null; + /** @var AbstractPlatform&MockObject $platformMock */ + $platformMock = $this->createMock(AbstractPlatform::class); + + $phpValue = $type->convertToDatabaseValue($phpValue, $platformMock); + + Assert::assertSame($expectedDatabaseValue, $phpValue); + } + + public function testGetName(): void + { + $type = Type::getType(MoneyType::TYPE_NAME); + + Assert::assertSame(MoneyType::TYPE_NAME, $type->getName()); + } +}