mirror of
https://github.com/wearepixel/laravel-cart.git
synced 2026-11-14 13:51:44 +00:00
feat: add ShippingRate base class
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Wearepixel\Cart\Shipping;
|
||||
|
||||
use Wearepixel\Cart\CartCondition;
|
||||
use Wearepixel\Cart\Contracts\CartConditionable;
|
||||
use Wearepixel\Cart\Exceptions\InvalidShippingRateException;
|
||||
|
||||
abstract class ShippingRate implements CartConditionable
|
||||
{
|
||||
protected string $name;
|
||||
|
||||
protected string $value;
|
||||
|
||||
protected string $target = 'total';
|
||||
|
||||
protected ?float $minimum = null;
|
||||
|
||||
protected ?float $maximum = null;
|
||||
|
||||
abstract public function isApplicable(): bool;
|
||||
|
||||
public function toCondition(): CartCondition
|
||||
{
|
||||
if (! $this->isApplicable()) {
|
||||
throw new InvalidShippingRateException("Shipping rate [{$this->name}] is not applicable.");
|
||||
}
|
||||
|
||||
$data = [
|
||||
'name' => $this->name,
|
||||
'type' => 'shipping',
|
||||
'value' => $this->value,
|
||||
'target' => $this->target,
|
||||
];
|
||||
|
||||
if ($this->minimum !== null) {
|
||||
$data['minimum'] = $this->minimum;
|
||||
}
|
||||
|
||||
if ($this->maximum !== null) {
|
||||
$data['maximum'] = $this->maximum;
|
||||
}
|
||||
|
||||
return new CartCondition($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Wearepixel\Cart\CartCondition;
|
||||
use Wearepixel\Cart\Shipping\ShippingRate;
|
||||
use Wearepixel\Cart\Exceptions\InvalidShippingRateException;
|
||||
|
||||
class FlatRateShipping extends ShippingRate
|
||||
{
|
||||
protected string $name = 'Standard Shipping';
|
||||
protected string $value = '+10';
|
||||
|
||||
public function isApplicable(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class FreeShipping extends ShippingRate
|
||||
{
|
||||
protected string $name = 'Free Shipping';
|
||||
protected string $value = '+0';
|
||||
|
||||
public function isApplicable(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
describe('ShippingRate', function () {
|
||||
test('converts to a CartCondition', function () {
|
||||
$condition = (new FlatRateShipping)->toCondition();
|
||||
|
||||
expect($condition)->toBeInstanceOf(CartCondition::class);
|
||||
expect($condition->getName())->toBe('Standard Shipping');
|
||||
expect($condition->getValue())->toBe('+10');
|
||||
expect($condition->getType())->toBe('shipping');
|
||||
expect($condition->getTarget())->toBe('total');
|
||||
});
|
||||
|
||||
test('isApplicable() returning false causes toCondition() to throw', function () {
|
||||
expect(fn() => (new FreeShipping)->toCondition())
|
||||
->toThrow(InvalidShippingRateException::class);
|
||||
});
|
||||
|
||||
test('supports subtotal as target', function () {
|
||||
$rate = new class extends ShippingRate {
|
||||
protected string $name = 'Express';
|
||||
protected string $value = '+25';
|
||||
protected string $target = 'subtotal';
|
||||
public function isApplicable(): bool { return true; }
|
||||
};
|
||||
|
||||
expect($rate->toCondition()->getTarget())->toBe('subtotal');
|
||||
});
|
||||
|
||||
test('supports maximum free shipping threshold', function () {
|
||||
$rate = new class extends ShippingRate {
|
||||
protected string $name = 'Conditional Shipping';
|
||||
protected string $value = '+15';
|
||||
protected ?float $maximum = 100.0;
|
||||
public function isApplicable(): bool { return true; }
|
||||
};
|
||||
|
||||
expect($rate->toCondition()->getMaximum())->toBe(100.0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user