percent(); $percent55 = $tax55->percent(); // THEN expect($percent20)->toBe(20.0) ->and($percent55)->toBe(5.5); }); it('returns correct rate', function () { // GIVEN $tax20 = TaxRate::TVA_20; $tax55 = TaxRate::TVA_5_5; // WHEN $rate20 = $tax20->rate(); $rate55 = $tax55->rate(); // THEN expect($rate20)->toBe(0.2) ->and($rate55)->toBe(0.055); }); it('applies tax correctly to money', function () { // GIVEN $price = new Money(10000, new Currency('EUR')); // 100.00 EUR $tax20 = TaxRate::TVA_20; $tax55 = TaxRate::TVA_5_5; // WHEN $amountWithTax20 = $tax20->applyTo($price)->getAmount(); $amountWithTax55 = $tax55->applyTo($price)->getAmount(); // THEN expect($amountWithTax20)->toBe('12000') // 120.00 EUR ->and($amountWithTax55)->toBe('10550'); // 105.50 EUR }); it('creates TaxRate from percent with float, int, or string', function () { // GIVEN $int20 = 20; $float20 = 20.0; $float55 = 5.5; // WHEN $rateFromInt = TaxRate::fromPercent($int20); $rateFromFloat20 = TaxRate::fromPercent($float20); $rateFromFloat55 = TaxRate::fromPercent($float55); // THEN expect($rateFromInt)->toBe(TaxRate::TVA_20) ->and($rateFromFloat20)->toBe(TaxRate::TVA_20) ->and($rateFromFloat55)->toBe(TaxRate::TVA_5_5); }); it('creates TaxRate from enum value fallback', function () { // GIVEN $val1 = 1; $val2 = 2; // WHEN $rate1 = TaxRate::fromPercent($val1); $rate2 = TaxRate::fromPercent($val2); // THEN expect($rate1)->toBe(TaxRate::TVA_20) ->and($rate2)->toBe(TaxRate::TVA_5_5); }); it('throws when percent is not numeric', function () { // GIVEN $invalid = 0.8; // WHEN / THEN expect(fn () => TaxRate::fromPercent($invalid)) ->toThrow(\UnexpectedValueException::class, 'Unhandled tax rate: 0.8'); }); it('throws when percent is unhandled', function () { // GIVEN $unhandled = 10.0; // WHEN / THEN expect(fn () => TaxRate::fromPercent($unhandled)) ->toThrow(\UnexpectedValueException::class, 'Unhandled tax rate: 10'); }); });