fix: serialize conditions to arrays before storage; type \$events

- serializeConditions() now maps CartCondition objects to arrays via
  toArray() before passing to the driver, preventing json_encode()
  producing {} for object values in the DatabaseDriver
- Add Dispatcher type hint to \$events property and constructor parameter
- Add database round-trip test for cart-level conditions
- Fix CartConditionsTest to retrieve condition objects from the cart
  rather than relying on object-reference side-effects that no longer
  hold after proper serialization
This commit is contained in:
Joel Male
2026-05-27 21:21:44 +10:00
parent f3e5e958b7
commit 4877911cdd
3 changed files with 38 additions and 5 deletions
+4 -3
View File
@@ -10,13 +10,14 @@
use Wearepixel\Cart\Exceptions\InvalidItemException;
use Wearepixel\Cart\Exceptions\UnknownModelException;
use Wearepixel\Cart\Exceptions\InvalidConditionException;
use Illuminate\Contracts\Events\Dispatcher;
use Wearepixel\Cart\Drivers\Contracts\CartDriver;
class Cart
{
protected CartDriver $driver;
protected $events;
protected Dispatcher $events;
protected string $instanceName;
@@ -24,7 +25,7 @@ class Cart
protected mixed $currentItemId;
public function __construct(CartDriver $driver, $events, string $instanceName, array $config)
public function __construct(CartDriver $driver, Dispatcher $events, string $instanceName, array $config)
{
$this->driver = $driver;
$this->events = $events;
@@ -581,7 +582,7 @@ private function serializeItems(CartCollection $cart): array
private function serializeConditions(CartConditionCollection $conditions): array
{
return $conditions->all();
return $conditions->map(fn(CartCondition $c) => $c->toArray())->all();
}
protected function itemHasConditions(ItemCollection $item): bool
+2 -2
View File
@@ -950,8 +950,8 @@
expect($this->cart->getCalculatedValueForCondition('Coupon Discount'))->toEqual(200.0, 'Coupon Discount should be 200.0');
expect($this->cart->getCalculatedValueForCondition('Gift Card'))->toEqual(0, 'Gift Card should be 0');
expect($couponDiscount->getCalculatedValue())->toEqual(200.0, 'Coupon Discount value should be 200.0');
expect($giftCard->getCalculatedValue())->toEqual(0, 'Gift Card value should be 0');
expect($this->cart->getCondition('Coupon Discount')->getCalculatedValue(200.0))->toEqual(200.0, 'Coupon Discount value should be 200.0');
expect($this->cart->getCondition('Gift Card')->getCalculatedValue(0))->toEqual(0, 'Gift Card value should be 0');
});
test('calculate the subtotal correctly when one condition makes it $0, and the other adds $10', function () {
+32
View File
@@ -112,6 +112,38 @@
expect($this->cart->getTotal())->toEqual(18.45, 'Cart should have total of 18.45');
});
test('cart-level conditions survive database round-trip', function () {
$this->cart->condition(new CartCondition([
'name' => 'GST',
'type' => 'tax',
'value' => '10%',
'target' => 'subtotal',
]));
// Create a fresh cart instance pointing at the same DB row
$events2 = Mockery::mock('Illuminate\Contracts\Events\Dispatcher');
$events2->shouldReceive('dispatch');
$cart2 = new \Wearepixel\Cart\Cart(
new \Wearepixel\Cart\Drivers\DatabaseDriver(
\Wearepixel\Cart\Tests\Helpers\MockCartModel::class,
'session_id',
'items',
'conditions',
'SAMPLESESSIONKEY',
),
$events2,
'cart',
require (__DIR__ . '/../Helpers/ConfigDatabaseMock.php')
);
$condition = $cart2->getCondition('GST');
expect($condition)->not->toBeNull();
expect($condition->getName())->toBe('GST');
expect($condition->getValue())->toBe('10%');
});
test('can clear a simple cart', function () {
$this->cart->add(1, 'Sample Item', 100.99, 2, []);