This commit is contained in:
1 parent
9ca28e42f5
commit
65bc8c63de
2 files changed
+135
-11
No files matched your search
@@ -63,17 +63,6 @@ class Checkout extends Component
|
|||||||
$this->plan = $this->plan_id ? $this->product->plans->findOrFail($this->plan_id) : $this->product->plans->first();
|
$this->plan = $this->plan_id ? $this->product->plans->findOrFail($this->plan_id) : $this->product->plans->first();
|
||||||
$this->plan_id = $this->plan->id;
|
$this->plan_id = $this->plan->id;
|
||||||
|
|
||||||
// Prepare the config options
|
|
||||||
$this->configOptions = $this->product->configOptions->mapWithKeys(function ($option) {
|
|
||||||
if (in_array($option->type, ['text', 'number'])) {
|
|
||||||
return [$option->id => $this->configOptions[$option->id] ?? null];
|
|
||||||
}
|
|
||||||
if ($option->type === 'checkbox') {
|
|
||||||
return [$option->id => isset($this->configOptions[$option->id]) && in_array($this->configOptions[$option->id], [true, 'true'], true) ? true : false];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [$option->id => $this->configOptions[$option->id] ?? $option->children->first()->id];
|
|
||||||
})->toArray();
|
|
||||||
foreach ($this->getCheckoutConfig() as $config) {
|
foreach ($this->getCheckoutConfig() as $config) {
|
||||||
if (in_array($config['type'], ['select', 'radio'])) {
|
if (in_array($config['type'], ['select', 'radio'])) {
|
||||||
$this->checkoutConfig[$config['name']] = $this->checkoutConfig[$config['name']] ?? $config['default'] ?? array_key_first($config['options']);
|
$this->checkoutConfig[$config['name']] = $this->checkoutConfig[$config['name']] ?? $config['default'] ?? array_key_first($config['options']);
|
||||||
@@ -82,6 +71,22 @@ class Checkout extends Component
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare the config options. Also done for an item that is already in the cart, because the
|
||||||
|
// product may have gained, lost or changed options since it was added.
|
||||||
|
$this->configOptions = $this->product->configOptions->mapWithKeys(function ($option) {
|
||||||
|
if (in_array($option->type, ['text', 'number'])) {
|
||||||
|
return [$option->id => $this->configOptions[$option->id] ?? null];
|
||||||
|
}
|
||||||
|
if ($option->type === 'checkbox') {
|
||||||
|
return [$option->id => isset($this->configOptions[$option->id]) && in_array($this->configOptions[$option->id], [true, 'true'], true) ? true : false];
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = $this->configOptions[$option->id] ?? null;
|
||||||
|
|
||||||
|
return [$option->id => $option->children->contains('id', $value) ? $value : $option->children->first()->id];
|
||||||
|
})->toArray();
|
||||||
|
|
||||||
// Update the pricing
|
// Update the pricing
|
||||||
$this->updatePricing();
|
$this->updatePricing();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use App\Models\Cart;
|
||||||
|
use App\Models\ConfigOption;
|
||||||
|
use App\Models\Plan;
|
||||||
|
use App\Models\Price;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Illuminate\Support\Once;
|
||||||
|
use Livewire\Livewire;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class CartConfigOptionChangeTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
private $product = null;
|
||||||
|
|
||||||
|
private ConfigOption $option;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$this->product = $this->createProduct();
|
||||||
|
|
||||||
|
$this->option = ConfigOption::create([
|
||||||
|
'name' => 'Location',
|
||||||
|
'type' => 'radio',
|
||||||
|
'sort' => 0,
|
||||||
|
]);
|
||||||
|
$this->option->products()->attach($this->product->product->id);
|
||||||
|
|
||||||
|
foreach (['Amsterdam', 'Frankfurt'] as $sort => $name) {
|
||||||
|
$this->createOptionValue($name, $sort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createOptionValue(string $name, int $sort): ConfigOption
|
||||||
|
{
|
||||||
|
$value = ConfigOption::create([
|
||||||
|
'name' => $name,
|
||||||
|
'sort' => $sort,
|
||||||
|
'parent_id' => $this->option->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$plan = Plan::factory()->create([
|
||||||
|
'priceable_id' => $value->id,
|
||||||
|
'priceable_type' => ConfigOption::class,
|
||||||
|
'name' => $name,
|
||||||
|
'billing_unit' => 'month',
|
||||||
|
'billing_period' => 1,
|
||||||
|
'type' => 'recurring',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Price::factory()->create([
|
||||||
|
'plan_id' => $plan->id,
|
||||||
|
'price' => 1.00,
|
||||||
|
'currency_code' => 'USD',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addToCart(ConfigOption $value): array
|
||||||
|
{
|
||||||
|
Livewire::test('products.checkout', [
|
||||||
|
'category' => $this->product->product->category,
|
||||||
|
'product' => $this->product->product->slug,
|
||||||
|
])
|
||||||
|
->set('configOptions.' . $this->option->id, $value->id)
|
||||||
|
->call('checkout');
|
||||||
|
|
||||||
|
$cart = Cart::firstOrFail();
|
||||||
|
Once::flush();
|
||||||
|
|
||||||
|
return [$cart, $cart->items()->firstOrFail()];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function editCartItem(Cart $cart, $item)
|
||||||
|
{
|
||||||
|
return Livewire::withCookie('cart', $cart->ulid)->test('products.checkout', [
|
||||||
|
'category' => $this->product->product->category,
|
||||||
|
'product' => $this->product->product->slug,
|
||||||
|
'cartProductKey' => $item->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_cart_item_can_be_edited_after_its_option_value_is_removed(): void
|
||||||
|
{
|
||||||
|
$values = $this->option->children()->get();
|
||||||
|
[$cart, $item] = $this->addToCart($values[0]);
|
||||||
|
|
||||||
|
// The option value the item was ordered with is removed from the product.
|
||||||
|
$values[0]->delete();
|
||||||
|
|
||||||
|
$this->editCartItem($cart, $item)
|
||||||
|
->assertSet('configOptions.' . $this->option->id, $values[1]->id)
|
||||||
|
->call('checkout')
|
||||||
|
->assertHasNoErrors();
|
||||||
|
|
||||||
|
$this->assertSame(1, $cart->items()->count());
|
||||||
|
$this->assertSame($values[1]->id, $cart->items()->first()->config_options[0]['value']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_cart_item_keeps_its_option_value_when_it_is_still_available(): void
|
||||||
|
{
|
||||||
|
$values = $this->option->children()->get();
|
||||||
|
[$cart, $item] = $this->addToCart($values[1]);
|
||||||
|
|
||||||
|
$this->editCartItem($cart, $item)
|
||||||
|
->assertSet('configOptions.' . $this->option->id, $values[1]->id)
|
||||||
|
->call('checkout')
|
||||||
|
->assertHasNoErrors();
|
||||||
|
|
||||||
|
$this->assertSame(1, $cart->items()->count());
|
||||||
|
$this->assertSame($values[1]->id, $cart->items()->first()->config_options[0]['value']);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user