Output:
Chunk ID: c88e20
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 2148
Output:
<?php

use App\Enums\FinancialStatus;
use App\Enums\FulfillmentShipmentStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentMethod;
use App\Enums\PaymentStatus;
use App\Models\Customer;
use App\Models\Fulfillment;
use App\Models\InventoryItem;
use App\Models\Order;
use App\Models\OrderLine;
use App\Models\Payment;
use App\Models\Product;
use App\Models\ProductVariant;
use App\Models\Store;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Pest\Browser\Playwright\Playwright;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    Playwright::setHost('shop.test');

    $this->seed(DatabaseSeeder::class);
});

afterEach(function (): void {
    Playwright::setHost(null);
});

function adminOrderHost(): array
{
    return ['host' => 'shop.test'];
}

function adminOrderAuthenticate(mixed $testCase): void
{
    $store = Store::query()->where('handle', 'acme-fashion')->firstOrFail();
    $user = User::query()->where('email', 'admin@acme.test')->firstOrFail();

    $testCase->actingAs($user);
    $testCase->withSession(['current_store_id' => $store->getKey()]);
}

/**
 * @return array{store: Store, paid: Order, fulfilled: Order, bank: Order}
 */
function adminOrderFixtures(): array
{
    $store = Store::query()->where('handle', 'acme-fashion')->firstOrFail();
    $customer = Customer::query()->where('email', 'customer@acme.test')->firstOrFail();
    $product = Product::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('handle', 'classic-cotton-t-shirt')
        ->firstOrFail();
    $variant = ProductVariant::withoutGlobalScopes()
        ->where('product_id', $product->getKey())
        ->firstOrFail();

    $paid = adminOrderCreateOrder(
        store: $store,
        customer: $customer,
        product: $product,
        variant: $variant,
        orderNumber: '#1001',
        paymentMethod: PaymentMethod::CreditCard,
        status: OrderStatus::Paid,
        financialStatus: FinancialStatus::Paid,
        fulfillmentStatus: FulfillmentStatus::Unfulfilled,
        placedAt: now()->subDays(3),
    );

    $fulfilled = adminOrderCreateOrder(
        store: $store,
        customer: $customer,
        product: $product,
        variant: $variant,
        orderNumber: '#1002',
        paymentMethod: PaymentMethod::CreditCard,
        status: OrderStatus::Fulfilled,
        financialStatus: FinancialStatus::Paid,
        fulfillmentStatus: FulfillmentStatus::Fulfilled,
        placedAt: now()->subDays(2),
    );

    adminOrderCreateDeliveredFulfillment($fulfilled);

    $bank = adminOrderCreateOrder(
        store: $store,
        customer: $customer,
        product: $product,
        variant: $variant,
        orderNumber: '#1005',
        paymentMethod: PaymentMethod::BankTransfer,
        status: OrderStatus::Pending,
        financialStatus: FinancialStatus::Pending,
        fulfillmentStatus: FulfillmentStatus::Unfulfilled,
        placedAt: now()->subDay(),
    );

    InventoryItem::withoutGlobalScopes()
        ->where('variant_id', $variant->getKey())
        ->update([
            'quantity_on_hand' => 20,
            'quantity_reserved' => 1,
        ]);

    return [
        'store' => $store,
        'paid' => $paid,
        'fulfilled' => $fulfilled,
        'bank' => $bank,
    ];
}

function adminOrderCreateOrder(
    Store $store,
    Customer $customer,
    Product $product,
    ProductVariant $variant,
    string $orderNumber,
    PaymentMethod $paymentMethod,
    OrderStatus $status,
    FinancialStatus $financialStatus,
    FulfillmentStatus $fulfillmentStatus,
    mixed $placedAt,
): Order {
    $subtotal = $variant->price_amount;
    $shipping = 499;
    $tax = 0;
    $total = $subtotal + $shipping + $tax;

    $order = Order::factory()->create([
        'store_id' => $store->getKey(),
        'customer_id' => $customer->getKey(),
        'order_number' => $orderNumber,
        'payment_method' => $paymentMethod,
        'status' => $status,
        'financial_status' => $financialStatus,
        'fulfillment_status' => $fulfillmentStatus,
        'currency' => $store->default_currency,
        'subtotal_amount' => $subtotal,
        'discount_amount' => 0,
        'shipping_amount' => $shipping,
        'tax_amount' => $tax,
        'total_amount' => $total,
        'email' => $customer->email,
        'placed_at' => $placedAt,
    ]);

    OrderLine::factory()->create([
        'order_id' => $order->getKey(),
        'product_id' => $product->getKey(),
        'variant_id' => $variant->getKey(),
        'title_snapshot' => 'Classic Cotton T-Shirt',
        'sku_snapshot' => $variant->sku,
        'quantity' => 1,
        'unit_price_amount' => $variant->price_amount,
        'total_amount' => $variant->price_amount,
    ]);

    Payment::factory()->create([
        'order_id' => $order->getKey(),
        'method' => $paymentMethod,
        'status' => $financialStatus === FinancialStatus::Pending ? PaymentStatus::Pending : PaymentStatus::Captured,
        'amount' => $total,
        'currency' => $store->default_currency,
    ]);

    return $order->refresh();
}

function adminOrderCreateDeliveredFulfillment(Order $order): void
{
    $line = $order->lines()->firstOrFail();
    $fulfillment = Fulfillment::query()->create([
        'order_id' => $order->getKey(),
        'status' => FulfillmentShipmentStatus::Delivered,
        'tracking_company' => 'DHL',
        'tracking_number' => 'DHL1234567890',
        'shipped_at' => now()->subDay(),
        'delivered_at' => now(),
    ]);

    $fulfillment->lines()->create([
        'order_line_id' => $line->getKey(),
        'quantity' => $line->quantity,
    ]);
}

function adminOrderOpenOrders(mixed $testCase): mixed
{
    adminOrderFixtures();
    adminOrderAuthenticate($testCase);

    return visit('/admin/orders', adminOrderHost())
        ->wait(1)
        ->assertPathIs('/admin/orders')
        ->assertSee('Orders')
        ->assertNoJavaScriptErrors();
}

function adminOrderOpenOrder(mixed $testCase, string $orderNumber): mixed
{
    return adminOrderOpenOrders($testCase)
        ->assertSee($orderNumber)
        ->click("a:has-text(\"{$orderNumber}\")")
        ->wait(1)
        ->assertSee($orderNumber)
        ->assertNoJavaScriptErrors();
}

function adminOrderCreateFulfillmentInBrowser(mixed $page): mixed
{
    return $page
        ->click('button[data-test="fulfillment-modal-button"]')
        ->wait(1)
        ->fill('input[wire\\:model="trackingCompany"]', 'DHL')
        ->fill('input[wire\\:model="trackingNumber"]', 'DHL123456789')
        ->click('button[data-test="fulfillment-submit-button"]')
        ->wait(1)
        ->assertSee('Fulfillment created')
        ->assertSee('DHL')
        ->assertSee('DHL123456789')
        ->assertNoJavaScriptErrors();
}

test('shows the order list with seeded orders', function (): void {
    adminOrderOpenOrders($this)
        ->assertSee('#1001')
        ->assertNoJavaScriptErrors();
});

test('can filter orders by status', function (): void {
    adminOrderOpenOrders($this)
        ->select('select[wire\\:model\\.live="financialStatusFilter"]', 'paid')
        ->wait(1)
        ->assertSee('#1001')
        ->assertDontSee('#1005')
        ->assertNoJavaScriptErrors()
        ->select('select[wire\\:model\\.live="fulfillmentStatusFilter"]', 'fulfilled')
        ->wait(1)
        ->assertSee('#1002')
        ->assertNoJavaScriptErrors()
        ->select('select[wire\\:model\\.live="financialStatusFilter"]', 'all')
        ->select('select[wire\\:model\\.live="fulfillmentStatusFilter"]', 'all')
        ->wait(1)
        ->assertSee('#1001')
        ->assertSee('#1005')
        ->assertNoJavaScriptErrors();
});

test('shows order detail with line items and totals', function (): void {
    adminOrderOpenOrder($this, '#1001')
        ->assertSee('Paid')
        ->assertSee('Unfulfilled')
        ->assertSee('Classic Cotton T-Shirt')
        ->assertSee('Subtotal')
        ->assertSee('Shipping')
        ->assertSee('Tax')
        ->assertSee('Total')
        ->assertNoJavaScriptErrors();
});

test('shows order timeline events', function (): void {
    adminOrderOpenOrder($this, '#1001')
        ->assertSee('Timeline')
        ->assertSee('Order placed')
        ->assertNoJavaScriptErrors();
});

test('can create a fulfillment', function (): void {
    adminOrderCreateFulfillmentInBrowser(adminOrderOpenOrder($this, '#1001'));
});

test('can process a refund', function (): void {


sed -n '1,280p' tests/Browser/Storefront/CustomerAccountTest.php

CustomerAccountTest.php

<?php

use App\Models\Customer;
use App\Models\Order;
use App\Models\OrderLine;
use App\Models\Store;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Collection;
use Pest\Browser\Playwright\Playwright;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    Playwright::setHost('shop.test');

    $this->seed(DatabaseSeeder::class);
});

afterEach(function (): void {
    Playwright::setHost(null);
});

function storefrontAccountHost(): array
{
    return ['host' => 'shop.test'];
}

function storefrontAccountLogin(): mixed
{
    return visit('/account/login', storefrontAccountHost())
        ->fill('input[type=email]', 'customer@acme.test')
        ->fill('input[type=password]', 'password')
        ->click('@customer-login-button')
        ->wait(1)
        ->assertPathIs('/account')
        ->assertSee('My Account')
        ->assertSee('John Doe')
        ->assertNoJavaScriptErrors();
}

function storefrontAccountStore(): Store
{
    return Store::query()->where('handle', 'acme-fashion')->firstOrFail();
}

function storefrontAccountCustomer(): Customer
{
    $store = storefrontAccountStore();

    return Customer::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('email', 'customer@acme.test')
        ->firstOrFail();
}

/**
 * @return Collection<int, Order>
 */
function storefrontAccountCreateOrders(): Collection
{
    $store = storefrontAccountStore();
    $customer = storefrontAccountCustomer();

    return collect(['#1001', '#1002', '#1004'])
        ->map(function (string $orderNumber, int $index) use ($store, $customer): Order {
            $order = Order::factory()
                ->forCustomer($customer)
                ->paid()
                ->create([
                    'store_id' => $store->getKey(),
                    'customer_id' => $customer->getKey(),
                    'order_number' => $orderNumber,
                    'email' => $customer->email,
                    'subtotal_amount' => 2499,
                    'shipping_amount' => 499,
                    'tax_amount' => 0,
                    'total_amount' => 2998,
                    'placed_at' => now()->subDays($index),
                ]);

            OrderLine::factory()->create([
                'order_id' => $order->getKey(),
                'product_id' => null,
                'variant_id' => null,
                'title_snapshot' => 'Classic Cotton T-Shirt',
                'quantity' => 1,
                'unit_price_amount' => 2499,
                'total_amount' => 2499,
            ]);

            return $order;
        });
}

test('can register a new customer', function (): void {
    visit('/account/register', storefrontAccountHost())
        ->fill('input[wire\\:model="name"]', 'New Customer')
        ->fill('input[wire\\:model="email"]', 'new-customer-e2e@example.com')
        ->fill('input[wire\\:model="password"]', 'password123')
        ->fill('input[wire\\:model="password_confirmation"]', 'password123')
        ->click('@customer-register-button')
        ->wait(1)
        ->assertPathIs('/account')
        ->assertSee('My Account')
        ->assertNoJavaScriptErrors();
});

test('shows validation errors for duplicate email registration', function (): void {
    visit('/account/register', storefrontAccountHost())
        ->fill('input[wire\\:model="name"]', 'Duplicate Customer')
        ->fill('input[wire\\:model="email"]', 'customer@acme.test')
        ->fill('input[wire\\:model="password"]', 'password123')
        ->fill('input[wire\\:model="password_confirmation"]', 'password123')
        ->click('@customer-register-button')
        ->wait(1)
        ->assertPathIs('/account/register')
        ->assertSee('already been taken')
        ->assertNoJavaScriptErrors();
});

test('shows validation errors for mismatched passwords', function (): void {
    visit('/account/register', storefrontAccountHost())
        ->fill('input[wire\\:model="name"]', 'Test Customer')
        ->fill('input[wire\\:model="email"]', 'mismatch@example.com')
        ->fill('input[wire\\:model="password"]', 'password123')
        ->fill('input[wire\\:model="password_confirmation"]', 'different456')
        ->click('@customer-register-button')
        ->wait(1)
        ->assertPathIs('/account/register')
        ->assertSee('password')
        ->assertNoJavaScriptErrors();
});

test('can log in as existing customer', function (): void {
    storefrontAccountLogin();
});

test('shows error for invalid customer credentials', function (): void {
    visit('/account/login', storefrontAccountHost())
        ->fill('input[type=email]', 'customer@acme.test')
        ->fill('input[type=password]', 'wrongpassword')
        ->click('@customer-login-button')
        ->wait(1)
        ->assertPathIs('/account/login')
        ->assertSee('Invalid credentials')
        ->assertNoJavaScriptErrors();
});

test('redirects unauthenticated customers to login', function (): void {
    visit('/account', storefrontAccountHost())
        ->wait(1)
        ->assertPathIs('/account/login')
        ->assertSee('Log in')
        ->assertNoJavaScriptErrors();
});

test('shows order history for logged in customer', function (): void {
    storefrontAccountCreateOrders();

    storefrontAccountLogin()
        ->click('nav[aria-label="Account navigation"] a[href$="/account/orders"]')
        ->wait(1)
        ->assertPathIs('/account/orders')
        ->assertSee('#1001')
        ->assertSee('#1002')
        ->assertSee('#1004')
        ->assertNoJavaScriptErrors();
});

test('shows order detail for customer order', function (): void {
    $orders = storefrontAccountCreateOrders();
    $order = $orders->first();

    storefrontAccountLogin()
        ->click('nav[aria-label="Account navigation"] a[href$="/account/orders"]')
        ->wait(1)
        ->click('a[href$="/account/orders/'.$order->getKey().'"]')
        ->wait(1)
        ->assertPathIs('/account/orders/'.$order->getKey())
        ->assertSee('#1001')
        ->assertSee('Subtotal')
        ->assertSee('Total')
        ->assertNoJavaScriptErrors();
});

test('can view addresses', function (): void {
    storefrontAccountLogin()
        ->click('nav[aria-label="Account navigation"] a[href$="/account/addresses"]')
        ->wait(1)
        ->assertPathIs('/account/addresses')
        ->assertSee('Main Street 1')
        ->assertSee('Berlin')
        ->assertNoJavaScriptErrors();
});

test('can add a new address', function (): void {
    storefrontAccountLogin()
        ->click('nav[aria-label="Account navigation"] a[href$="/account/addresses"]')
        ->wait(1)
        ->click('button:has-text("Add address")')
        ->wait(1)
        ->fill('input[wire\\:model="address.first_name"]', 'John')
        ->fill('input[wire\\:model="address.last_name"]', 'Doe')
        ->fill('input[wire\\:model="address.address1"]', 'New Street 42')
        ->fill('input[wire\\:model="address.city"]', 'Hamburg')
        ->fill('input[wire\\:model="address.postal_code"]', '20095')
        ->select('select[wire\\:model="address.country"]', 'DE')
        ->click('form[wire\\:submit="saveAddress"] button[type="submit"]')
        ->wait(1)
        ->assertSee('Address saved')
        ->assertSee('New Street 42')
        ->assertSee('Hamburg')
        ->assertNoJavaScriptErrors();
});

test('can edit an existing address', function (): void {
    storefrontAccountLogin()
        ->click('nav[aria-label="Account navigation"] a[href$="/account/addresses"]')
        ->wait(1)
        ->click('article:has-text("Main Street 1") button:has-text("Edit")')
        ->wait(1)
        ->fill('input[wire\\:model="address.city"]', 'Frankfurt')
        ->click('form[wire\\:submit="saveAddress"] button[type="submit"]')
        ->wait(1)
        ->assertSee('Address saved')
        ->assertSee('Frankfurt')
        ->assertNoJavaScriptErrors();
});

test('can log out', function (): void {
    storefrontAccountLogin()
        ->click('@customer-logout-button')
        ->wait(1)
        ->assertPathIs('/account/login')
        ->assertSee('Log in')
        ->assertNoJavaScriptErrors();
});


Output:
Chunk ID: aac378
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 2052
Output:
<?php

use App\Models\Customer;
use App\Models\Order;
use App\Models\OrderLine;
use App\Models\Store;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Collection;
use Pest\Browser\Playwright\Playwright;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    Playwright::setHost('shop.test');

    $this->seed(DatabaseSeeder::class);
});

afterEach(function (): void {
    Playwright::setHost(null);
});

function storefrontAccountHost(): array
{
    return ['host' => 'shop.test'];
}

function storefrontAccountLogin(): mixed
{
    return visit('/account/login', storefrontAccountHost())
        ->fill('input[type=email]', 'customer@acme.test')
        ->fill('input[type=password]', 'password')
        ->click('@customer-login-button')
        ->wait(1)
        ->assertPathIs('/account')
        ->assertSee('My Account')
        ->assertSee('John Doe')
        ->assertNoJavaScriptErrors();
}

function storefrontAccountStore(): Store
{
    return Store::query()->where('handle', 'acme-fashion')->firstOrFail();
}

function storefrontAccountCustomer(): Customer
{
    $store = storefrontAccountStore();

    return Customer::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('email', 'customer@acme.test')
        ->firstOrFail();
}

/**
 * @return Collection<int, Order>
 */
function storefrontAccountCreateOrders(): Collection
{
    $store = storefrontAccountStore();
    $customer = storefrontAccountCustomer();

    return collect(['#1001', '#1002', '#1004'])
        ->map(function (string $orderNumber, int $index) use ($store, $customer): Order {
            $order = Order::factory()
                ->forCustomer($customer)
                ->paid()
                ->create([
                    'store_id' => $store->getKey(),
                    'customer_id' => $customer->getKey(),
                    'order_number' => $orderNumber,
                    'email' => $customer->email,
                    'subtotal_amount' => 2499,
                    'shipping_amount' => 499,
                    'tax_amount' => 0,
                    'total_amount' => 2998,
                    'placed_at' => now()->subDays($index),
                ]);

            OrderLine::factory()->create([
                'order_id' => $order->getKey(),
                'product_id' => null,
                'variant_id' => null,
                'title_snapshot' => 'Classic Cotton T-Shirt',
                'quantity' => 1,
                'unit_price_amount' => 2499,
                'total_amount' => 2499,
            ]);

            return $order;
        });
}

test('can register a new customer', function (): void {
    visit('/account/register', storefrontAccountHost())
        ->fill('input[wire\\:model="name"]', 'New Customer')
        ->fill('input[wire\\:model="email"]', 'new-customer-e2e@example.com')
        ->fill('input[wire\\:model="password"]', 'password123')
        ->fill('input[wire\\:model="password_confirmation"]', 'password123')
        ->click('@customer-register-button')
        ->wait(1)
        ->assertPathIs('/account')
        ->assertSee('My Account')
        ->assertNoJavaScriptErrors();
});

test('shows validation errors for duplicate email registration', function (): void {
    visit('/account/register', storefrontAccountHost())
        ->fill('input[wire\\:model="name"]', 'Duplicate Customer')
        ->fill('input[wire\\:model="email"]', 'customer@acme.test')
        ->fill('input[wire\\:model="password"]', 'password123')
        ->fill('input[wire\\:model="password_confirmation"]', 'password123')
        ->click('@customer-register-button')
        ->wait(1)
        ->assertPathIs('/account/register')
        ->assertSee('already been taken')
        ->assertNoJavaScriptErrors();
});

test('shows validation errors for mismatched passwords', function (): void {
    visit('/account/register', storefrontAccountHost())
        ->fill('input[wire\\:model="name"]', 'Test Customer')
        ->fill('input[wire\\:model="email"]', 'mismatch@example.com')
        ->fill('input[wire\\:model="password"]', 'password123')
        ->fill('input[wire\\:model="password_confirmation"]', 'different456')
        ->click('@customer-register-button')
        ->wait(1)
        ->assertPathIs('/account/register')
        ->assertSee('password')
        ->assertNoJavaScriptErrors();
});

test('can log in as existing customer', function (): void {
    storefrontAccountLogin();
});

test('shows error for invalid customer credentials', function (): void {
    visit('/account/login', storefrontAccountHost())
        ->fill('input[type=email]', 'customer@acme.test')
        ->fill('input[type=password]', 'wrongpassword')
        ->click('@customer-login-button')
        ->wait(1)
        ->assertPathIs('/account/login')
        ->assertSee('Invalid credentials')
        ->assertNoJavaScriptErrors();
});

test('redirects unauthenticated customers to login', function (): void {
    visit('/account', storefrontAccountHost())
        ->wait(1)
        ->assertPathIs('/account/login')
        ->assertSee('Log in')
        ->assertNoJavaScriptErrors();
});

test('shows order history for logged in customer', function (): void {
    storefrontAccountCreateOrders();

    storefrontAccountLogin()
        ->click('nav[aria-label="Account navigation"] a[href$="/account/orders"]')
        ->wait(1)
        ->assertPathIs('/account/orders')
        ->assertSee('#1001')
        ->assertSee('#1002')
        ->assertSee('#1004')
        ->assertNoJavaScriptErrors();
});

test('shows order detail for customer order', function (): void {
    $orders = storefrontAccountCreateOrders();
    $order = $orders->first();

    storefrontAccountLogin()
        ->click('nav[aria-label="Account navigation"] a[href$="/account/orders"]')
        ->wait(1)
        ->click('a[href$="/account/orders/'.$order->getKey().'"]')
        ->wait(1)
        ->assertPathIs('/account/orders/'.$order->getKey())
        ->assertSee('#1001')
        ->assertSee('Subtotal')
        ->assertSee('Total')
        ->assertNoJavaScriptErrors();
});

test('can view addresses', function (): void {
    storefrontAccountLogin()
        ->click('nav[aria-label="Account navigation"] a[href$="/account/addresses"]')
        ->wait(1)
        ->assertPathIs('/account/addresses')
        ->assertSee('Main Street 1')
        ->assertSee('Berlin')
        ->assertNoJavaScriptErrors();
});

test('can add a new address', function (): void {
    storefrontAccountLogin()
        ->click('nav[aria-label="Account navigation"] a[href$="/account/addresses"]')
        ->wait(1)
        ->click('button:has-text("Add address")')
        ->wait(1)
        ->fill('input[wire\\:model="address.first_name"]', 'John')
        ->fill('input[wire\\:model="address.last_name"]', 'Doe')
        ->fill('input[wire\\:model="address.address1"]', 'New Street 42')
        ->fill('input[wire\\:model="address.city"]', 'Hamburg')
        ->fill('input[wire\\:model="address.postal_code"]', '20095')
        ->select('select[wire\\:model="address.country"]', 'DE')
        ->click('form[wire\\:submit="saveAddress"] button[type="submit"]')
        ->wait(1)
        ->assertSee('Address saved')
        ->assertSee('New Street 42')
        ->assertSee('Hamburg')
        ->assertNoJavaScriptErrors();
});

test('can edit an existing address', function (): void {
    storefrontAccountLogin()
        ->click('nav[aria-label="Account navigation"] a[href$="/account/addresses"]')
        ->wait(1)
        ->click('article:has-text("Main Street 1") button:has-text("Edit")')
        ->wait(1)
        ->fill('input[wire\\:model="address.city"]', 'Frankfurt')
        ->click('form[wire\\:submit="saveAddress"] button[type="submit"]')
        ->wait(1)
        ->assertSee('Address saved')
        ->assertSee('Frankfurt')
        ->assertNoJavaScriptErrors();
});

test('can log out', function (): void {
    storefrontAccountLogin()
        ->click('@customer-logout-button')
        ->wait(1)
        ->assertPathIs('/account/login')
        ->assertSee('Log in')
        ->assertNoJavaScriptErrors();
});


sed -n '280,560p' tests/Browser/Admin/OrderManagementTest.php


sed -n '1,260p' tests/Browser/Admin/CustomerManagementTest.php


sed -n '1,320p' tests/Browser/Storefront/TenantIsolationTest.php


sed -n '1,280p' tests/Feature/Admin/OrderManagementTest.php


sed -n '1,260p' tests/Feature/Admin/CustomerManagementTest.php


sed -n '280,560p' tests/Browser/Admin/OrderManagementTest.php

test('can process a refund', function (): void {
    adminOrderOpenOrder($this, '#1001')
        ->click('button[data-test="refund-modal-button"]')
        ->wait(1)
        ->fill('input[wire\\:model="refundAmount"]', '10.00')
        ->fill('textarea[wire\\:model="refundReason"]', 'Customer requested partial refund')
        ->click('button[data-test="refund-submit-button"]')
        ->wait(1)
        ->assertSee('Refund processed')
        ->assertSee('Partially Refunded')
        ->assertNoJavaScriptErrors();
});

test('shows customer information in order detail', function (): void {
    adminOrderOpenOrder($this, '#1001')
        ->assertSee('customer@acme.test')
        ->assertNoJavaScriptErrors();
});

test('can confirm bank transfer payment', function (): void {
    adminOrderOpenOrder($this, '#1005')
        ->assertSee('Pending')
        ->assertPresent('button[data-test="confirm-payment-button"]')
        ->click('button[data-test="confirm-payment-button"]')
        ->wait(1)
        ->assertSee('Payment confirmed')
        ->assertSee('Paid')
        ->assertDontSee('Confirm payment')
        ->assertNoJavaScriptErrors();
});

test('shows fulfillment guard for unpaid order', function (): void {
    adminOrderOpenOrder($this, '#1005')
        ->assertSee('Cannot create fulfillment')
        ->assertSee('Payment must be confirmed before items can be fulfilled')
        ->assertScript('document.querySelector("button[data-test=\"fulfillment-modal-button\"]") === null')
        ->assertNoJavaScriptErrors();
});

test('can mark fulfillment as shipped', function (): void {
    $page = adminOrderCreateFulfillmentInBrowser(adminOrderOpenOrder($this, '#1001'));

    $page->click('button[data-test="mark-fulfillment-shipped-button"]')
        ->wait(1)
        ->assertSee('Shipped')
        ->assertNoJavaScriptErrors();
});

test('can mark fulfillment as delivered', function (): void {
    $page = adminOrderCreateFulfillmentInBrowser(adminOrderOpenOrder($this, '#1001'));

    $page->click('button[data-test="mark-fulfillment-shipped-button"]')
        ->wait(1)
        ->click('button[data-test="mark-fulfillment-delivered-button"]')
        ->wait(1)
        ->assertSee('Delivered')
        ->assertSee('Fulfilled')
        ->assertNoJavaScriptErrors();
});


sed -n '1,260p' tests/Browser/Admin/CustomerManagementTest.php

<?php

use App\Enums\FinancialStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentMethod;
use App\Enums\PaymentStatus;
use App\Models\Customer;
use App\Models\Order;
use App\Models\OrderLine;
use App\Models\Payment;
use App\Models\Product;
use App\Models\ProductVariant;
use App\Models\Store;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Pest\Browser\Playwright\Playwright;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    Playwright::setHost('shop.test');

    $this->seed(DatabaseSeeder::class);
});

afterEach(function (): void {
    Playwright::setHost(null);
});

function adminCustomerBrowserHost(): array
{
    return ['host' => 'shop.test'];
}

function adminCustomerBrowserAuthenticate(mixed $testCase): Store
{
    $store = Store::query()->where('handle', 'acme-fashion')->firstOrFail();
    $user = User::query()->where('email', 'admin@acme.test')->firstOrFail();

    $testCase->actingAs($user);
    $testCase->withSession(['current_store_id' => $store->getKey()]);

    return $store;
}

function adminCustomerBrowserCustomer(Store $store): Customer
{
    return Customer::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('email', 'customer@acme.test')
        ->firstOrFail();
}

function adminCustomerBrowserCreateOrder(Store $store, Customer $customer): Order
{
    $product = Product::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('handle', 'classic-cotton-t-shirt')
        ->firstOrFail();
    $variant = ProductVariant::withoutGlobalScopes()
        ->where('product_id', $product->getKey())
        ->firstOrFail();
    $shipping = 499;
    $total = $variant->price_amount + $shipping;

    $order = Order::factory()->create([
        'store_id' => $store->getKey(),
        'customer_id' => $customer->getKey(),
        'order_number' => '#1001',
        'payment_method' => PaymentMethod::CreditCard,
        'status' => OrderStatus::Paid,
        'financial_status' => FinancialStatus::Paid,
        'fulfillment_status' => FulfillmentStatus::Unfulfilled,
        'currency' => $store->default_currency,
        'subtotal_amount' => $variant->price_amount,
        'discount_amount' => 0,
        'shipping_amount' => $shipping,
        'tax_amount' => 0,
        'total_amount' => $total,
        'email' => $customer->email,
        'placed_at' => now()->subDay(),
    ]);

    OrderLine::factory()->create([
        'order_id' => $order->getKey(),
        'product_id' => $product->getKey(),
        'variant_id' => $variant->getKey(),
        'title_snapshot' => 'Classic Cotton T-Shirt',
        'sku_snapshot' => $variant->sku,
        'quantity' => 1,
        'unit_price_amount' => $variant->price_amount,
        'total_amount' => $variant->price_amount,
    ]);

    Payment::factory()->create([
        'order_id' => $order->getKey(),
        'method' => PaymentMethod::CreditCard,
        'status' => PaymentStatus::Captured,
        'amount' => $total,
        'currency' => $store->default_currency,
    ]);

    return $order->refresh();
}

function adminCustomerBrowserOpenCustomers(mixed $testCase): mixed
{
    adminCustomerBrowserAuthenticate($testCase);

    return visit('/admin/customers', adminCustomerBrowserHost())
        ->wait(1)
        ->assertPathIs('/admin/customers')
        ->assertSee('Customers')
        ->assertNoJavaScriptErrors();
}

function adminCustomerBrowserOpenCustomer(mixed $testCase): mixed
{
    return adminCustomerBrowserOpenCustomers($testCase)
        ->assertSee('John Doe')
        ->click('a:has-text("John Doe")')
        ->wait(1)
        ->assertPathContains('/admin/customers/')
        ->assertNoJavaScriptErrors();
}

test('shows the customer list', function (): void {
    adminCustomerBrowserOpenCustomers($this)
        ->assertSee('customer@acme.test')
        ->assertSee('John Doe')
        ->assertNoJavaScriptErrors();
});

test('shows customer detail with order history', function (): void {
    $store = adminCustomerBrowserAuthenticate($this);
    $customer = adminCustomerBrowserCustomer($store);
    adminCustomerBrowserCreateOrder($store, $customer);

    visit('/admin/customers', adminCustomerBrowserHost())
        ->wait(1)
        ->assertPathIs('/admin/customers')
        ->click('a:has-text("John Doe")')
        ->wait(1)
        ->assertPathContains('/admin/customers/')
        ->assertSee('John Doe')
        ->assertSee('customer@acme.test')
        ->assertSee('Order history')
        ->assertSee('#1001')
        ->assertNoJavaScriptErrors();
});

test('shows customer addresses', function (): void {
    adminCustomerBrowserOpenCustomer($this)
        ->assertSee('John Doe')
        ->assertSee('Addresses')
        ->assertSee('Home')
        ->assertNoJavaScriptErrors();
});


sed -n '1,320p' tests/Browser/Storefront/TenantIsolationTest.php

<?php

use App\Models\Customer;
use App\Models\Order;
use App\Models\Store;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Pest\Browser\Playwright\Playwright;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    Playwright::setHost('acme-fashion.test');

    $this->seed(DatabaseSeeder::class);
});

afterEach(function (): void {
    Playwright::setHost(null);
});

function tenantIsolationHost(): array
{
    return ['host' => 'acme-fashion.test'];
}

function tenantIsolationStore(string $handle): Store
{
    return Store::query()->where('handle', $handle)->firstOrFail();
}

function tenantIsolationFashionCustomer(): Customer
{
    $store = tenantIsolationStore('acme-fashion');

    return Customer::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('email', 'customer@acme.test')
        ->firstOrFail();
}

function tenantIsolationCreateOrders(): void
{
    $fashionStore = tenantIsolationStore('acme-fashion');
    $electronicsStore = tenantIsolationStore('acme-electronics');
    $fashionCustomer = tenantIsolationFashionCustomer();
    $electronicsCustomer = Customer::factory()->create([
        'store_id' => $electronicsStore->getKey(),
        'email' => 'customer@acme.test',
        'password' => 'password',
        'name' => 'Electronics Customer',
    ]);

    foreach (['#1001', '#1002', '#1004'] as $orderNumber) {
        Order::factory()
            ->forCustomer($fashionCustomer)
            ->paid()
            ->create([
                'store_id' => $fashionStore->getKey(),
                'customer_id' => $fashionCustomer->getKey(),
                'order_number' => $orderNumber,
                'email' => $fashionCustomer->email,
            ]);
    }

    Order::factory()
        ->forCustomer($electronicsCustomer)
        ->paid()
        ->create([
            'store_id' => $electronicsStore->getKey(),
            'customer_id' => $electronicsCustomer->getKey(),
            'order_number' => '#2001',
            'email' => $electronicsCustomer->email,
        ]);
}

function tenantIsolationAdminLogin(): mixed
{
    return visit('/admin/login', tenantIsolationHost())
        ->fill('input[type=email]', 'admin@acme.test')
        ->fill('input[type=password]', 'password')
        ->click('@admin-login-button')
        ->wait(1)
        ->assertPathIs('/admin')
        ->assertSee('Dashboard')
        ->assertNoJavaScriptErrors();
}

function tenantIsolationCustomerLogin(): mixed
{
    return visit('/account/login', tenantIsolationHost())
        ->fill('input[type=email]', 'customer@acme.test')
        ->fill('input[type=password]', 'password')
        ->click('@customer-login-button')
        ->wait(1)
        ->assertPathIs('/account')
        ->assertSee('My Account')
        ->assertSee('John Doe')
        ->assertNoJavaScriptErrors();
}

test('storefront only shows current store products', function (): void {
    visit('/', tenantIsolationHost())
        ->assertSee('Acme Fashion')
        ->assertSee('Classic Cotton T-Shirt')
        ->assertDontSee('Pro Laptop 15')
        ->assertDontSee('Wireless Headphones')
        ->assertNoJavaScriptErrors();
});

test('storefront collections only contain current store products', function (): void {
    visit('/collections/t-shirts', tenantIsolationHost())
        ->assertSee('T-Shirts')
        ->assertSee('Classic Cotton T-Shirt')
        ->assertDontSee('Pro Laptop 15')
        ->assertDontSee('Wireless Headphones')
        ->assertNoJavaScriptErrors();
});

test('admin cannot see other store products or orders', function (): void {
    tenantIsolationCreateOrders();

    tenantIsolationAdminLogin()
        ->click('a[href$="/admin/products"]')
        ->wait(1)
        ->assertPathIs('/admin/products')
        ->assertSee('Products')
        ->assertDontSee('Pro Laptop 15')
        ->assertDontSee('Wireless Headphones')
        ->click('a[href$="/admin/orders"]')
        ->wait(1)
        ->assertPathIs('/admin/orders')
        ->assertSee('#1001')
        ->assertDontSee('#2001')
        ->assertNoJavaScriptErrors();
});

test('search only returns current store products', function (): void {
    visit('/search?q=cotton', tenantIsolationHost())
        ->assertSee('Classic Cotton T-Shirt')
        ->assertDontSee('Pro Laptop 15')
        ->assertNoJavaScriptErrors();

    visit('/search?q=laptop', tenantIsolationHost())
        ->assertDontSee('Pro Laptop 15')
        ->assertSee('No products found')
        ->assertNoJavaScriptErrors();
});

test('customer accounts are scoped to their store', function (): void {
    tenantIsolationCreateOrders();

    tenantIsolationCustomerLogin()
        ->click('nav[aria-label="Account navigation"] a[href$="/account/orders"]')
        ->wait(1)
        ->assertPathIs('/account/orders')
        ->assertSee('#1001')
        ->assertSee('#1002')
        ->assertSee('#1004')
        ->assertDontSee('#2001')
        ->assertNoJavaScriptErrors();
});


sed -n '1,280p' tests/Feature/Admin/OrderManagementTest.php

<?php

use App\Enums\FinancialStatus;
use App\Enums\FulfillmentShipmentStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentMethod;
use App\Enums\PaymentStatus;
use App\Livewire\Admin\Orders\Index as AdminOrdersIndex;
use App\Livewire\Admin\Orders\Show as AdminOrderShow;
use App\Models\Fulfillment;
use App\Models\InventoryItem;
use App\Models\Order;
use App\Models\OrderLine;
use App\Models\Payment;
use App\Models\Product;
use App\Models\ProductVariant;
use App\Models\Store;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;

uses(RefreshDatabase::class);

beforeEach(function () {
    $this->withoutVite();
    $this->seed(DatabaseSeeder::class);
});

function adminOrderManagementStore(): Store
{
    $store = Store::query()->where('handle', 'acme-fashion')->firstOrFail();
    app()->instance('current_store', $store);

    return $store;
}

function adminOrderManagementUser(): User
{
    return User::query()->where('email', 'admin@acme.test')->firstOrFail();
}

/**
 * @return array{0: Order, 1: OrderLine, 2: ProductVariant}
 */
function adminOrderManagementOrder(Store $store, array $orderAttributes = [], int $quantity = 2, int $unitPrice = 2500): array
{
    $product = Product::factory()
        ->withDefaultVariant($unitPrice)
        ->create(['store_id' => $store->getKey()]);
    $variant = ProductVariant::withoutGlobalScopes()
        ->where('product_id', $product->getKey())
        ->firstOrFail();

    InventoryItem::withoutGlobalScopes()
        ->where('variant_id', $variant->getKey())
        ->update([
            'quantity_on_hand' => 10,
            'quantity_reserved' => 0,
        ]);

    $total = $quantity * $unitPrice;
    $order = Order::factory()->paid()->create(array_merge([
        'store_id' => $store->getKey(),
        'subtotal_amount' => $total,
        'shipping_amount' => 0,
        'tax_amount' => 0,
        'total_amount' => $total,
        'email' => 'buyer@example.test',
    ], $orderAttributes));
    $line = OrderLine::factory()->create([
        'order_id' => $order->getKey(),
        'product_id' => $product->getKey(),
        'variant_id' => $variant->getKey(),
        'title_snapshot' => 'Admin Test Product',
        'sku_snapshot' => 'ADMIN-TEST-001',
        'quantity' => $quantity,
        'unit_price_amount' => $unitPrice,
        'total_amount' => $total,
    ]);

    Payment::factory()->create([
        'order_id' => $order->getKey(),
        'method' => $order->payment_method,
        'status' => $order->financial_status === FinancialStatus::Pending ? PaymentStatus::Pending : PaymentStatus::Captured,
        'amount' => $total,
        'currency' => $order->currency,
    ]);

    return [$order, $line, $variant];
}

test('admin order routes require authentication and render scoped orders', function () {
    $store = adminOrderManagementStore();
    [$order] = adminOrderManagementOrder($store, [
        'order_number' => '#7001',
        'email' => 'alpha@example.test',
    ]);

    $otherStore = Store::factory()->create();
    adminOrderManagementOrder($otherStore, [
        'order_number' => '#9001',
        'email' => 'other@example.test',
    ]);

    $this->get('/admin/orders')->assertRedirect('/admin/login');

    $user = adminOrderManagementUser();

    $this->actingAs($user)
        ->get('/admin/orders')
        ->assertSuccessful()
        ->assertSee('#7001')
        ->assertDontSee('#9001');

    $this->actingAs($user)
        ->get('/admin/orders/'.$order->getKey())
        ->assertSuccessful()
        ->assertSee('#7001')
        ->assertSee('Admin Test Product');
});

test('admin order index filters by search and status dimensions', function () {
    $store = adminOrderManagementStore();
    $user = adminOrderManagementUser();
    adminOrderManagementOrder($store, [
        'order_number' => '#7001',
        'email' => 'alpha@example.test',
    ]);
    adminOrderManagementOrder($store, [
        'order_number' => '#7002',
        'email' => 'bravo@example.test',
        'status' => OrderStatus::Pending,
        'financial_status' => FinancialStatus::Pending,
        'payment_method' => PaymentMethod::BankTransfer,
    ]);

    Livewire::actingAs($user)
        ->test(AdminOrdersIndex::class)
        ->assertSee('#7001')
        ->assertSee('#7002')
        ->set('search', 'alpha')
        ->assertSee('#7001')
        ->assertDontSee('#7002')
        ->set('search', '')
        ->set('financialStatusFilter', 'pending')
        ->assertSee('#7002')
        ->assertDontSee('#7001');
});

test('admin order detail confirms bank transfer payments', function () {
    $store = adminOrderManagementStore();
    $user = adminOrderManagementUser();
    [$order, $line, $variant] = adminOrderManagementOrder($store, [
        'payment_method' => PaymentMethod::BankTransfer,
        'status' => OrderStatus::Pending,
        'financial_status' => FinancialStatus::Pending,
    ]);

    InventoryItem::withoutGlobalScopes()
        ->where('variant_id', $variant->getKey())
        ->update(['quantity_reserved' => $line->quantity]);

    Livewire::actingAs($user)
        ->test(AdminOrderShow::class, ['order' => $order])
        ->call('confirmBankTransferPayment')
        ->assertHasNoErrors();

    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();

    expect($order->refresh()->status)->toBe(OrderStatus::Paid)
        ->and($order->financial_status)->toBe(FinancialStatus::Paid)
        ->and($order->payments()->first()?->status)->toBe(PaymentStatus::Captured)
        ->and($inventory->quantity_on_hand)->toBe(8)
        ->and($inventory->quantity_reserved)->toBe(0);
});

test('admin order detail processes refunds and fulfillment transitions', function () {
    $store = adminOrderManagementStore();
    $user = adminOrderManagementUser();
    [$order, $line] = adminOrderManagementOrder($store, quantity: 2, unitPrice: 2500);

    Livewire::actingAs($user)
        ->test(AdminOrderShow::class, ['order' => $order])
        ->set('refundAmount', '10.00')
        ->set('refundReason', 'Customer return')
        ->call('processRefund')
        ->assertHasNoErrors();

    expect($order->refresh()->financial_status)->toBe(FinancialStatus::PartiallyRefunded)
        ->and($order->refunds()->first()?->amount)->toBe(1000);

    Livewire::actingAs($user)
        ->test(AdminOrderShow::class, ['order' => $order->refresh()])
        ->set("fulfillmentLineQuantities.{$line->getKey()}", 1)
        ->set('trackingCompany', 'DHL')
        ->set('trackingNumber', 'DHL123')
        ->call('createFulfillment')
        ->assertHasNoErrors();

    $fulfillment = Fulfillment::query()->where('order_id', $order->getKey())->firstOrFail();

    expect($order->refresh()->fulfillment_status)->toBe(FulfillmentStatus::Partial)
        ->and($fulfillment->lines()->first()?->quantity)->toBe(1);

    Livewire::actingAs($user)
        ->test(AdminOrderShow::class, ['order' => $order->refresh()])
        ->call('markFulfillmentShipped', $fulfillment->getKey())
        ->call('markFulfillmentDelivered', $fulfillment->getKey())
        ->assertHasNoErrors();

    expect($fulfillment->refresh()->status)->toBe(FulfillmentShipmentStatus::Delivered)
        ->and($fulfillment->delivered_at)->not->toBeNull();
});

test('admin order detail rejects orders from another store', function () {
    $store = adminOrderManagementStore();
    $otherStore = Store::factory()->create();
    $user = adminOrderManagementUser();
    [$otherOrder] = adminOrderManagementOrder($otherStore, [
        'order_number' => '#9001',
    ]);

    app()->instance('current_store', $store);

    Livewire::actingAs($user)
        ->test(AdminOrderShow::class, ['order' => $otherOrder])
        ->assertStatus(404);
});


sed -n '1,260p' tests/Feature/Admin/CustomerManagementTest.php

<?php

use App\Livewire\Admin\Customers\Index as AdminCustomersIndex;
use App\Livewire\Admin\Customers\Show as AdminCustomerShow;
use App\Models\Customer;
use App\Models\CustomerAddress;
use App\Models\Order;
use App\Models\Store;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    $this->withoutVite();
    $this->seed(DatabaseSeeder::class);
});

function adminCustomerManagementStore(): Store
{
    $store = Store::query()->where('handle', 'acme-fashion')->firstOrFail();
    app()->instance('current_store', $store);

    return $store;
}

function adminCustomerManagementUser(): User
{
    return User::query()->where('email', 'admin@acme.test')->firstOrFail();
}

function adminCustomerManagementCustomer(Store $store, string $email, string $name): Customer
{
    return Customer::factory()->create([
        'store_id' => $store->getKey(),
        'email' => $email,
        'name' => $name,
    ]);
}

function adminCustomerManagementOrder(Store $store, Customer $customer, string $orderNumber, int $totalAmount): Order
{
    return Order::factory()->paid()->create([
        'store_id' => $store->getKey(),
        'customer_id' => $customer->getKey(),
        'order_number' => $orderNumber,
        'subtotal_amount' => $totalAmount,
        'shipping_amount' => 0,
        'tax_amount' => 0,
        'total_amount' => $totalAmount,
        'email' => $customer->email,
    ]);
}

test('admin customer routes require authentication and render store scoped customers', function (): void {
    $store = adminCustomerManagementStore();
    $customer = adminCustomerManagementCustomer($store, 'jane@example.test', 'Jane Example');
    adminCustomerManagementOrder($store, $customer, '#8101', 7000);
    CustomerAddress::factory()->default()->create([
        'customer_id' => $customer->getKey(),
        'label' => 'Home',
    ]);

    $otherStore = Store::factory()->create();
    $otherCustomer = adminCustomerManagementCustomer($otherStore, 'other@example.test', 'Other Customer');

    $this->get('/admin/customers')->assertRedirect('/admin/login');

    $this->actingAs(adminCustomerManagementUser())
        ->withSession(['current_store_id' => $store->getKey()])
        ->get('/admin/customers')
        ->assertSuccessful()
        ->assertSee('Jane Example')
        ->assertSee('70.00 EUR')
        ->assertDontSee('Other Customer');

    $this->actingAs(adminCustomerManagementUser())
        ->withSession(['current_store_id' => $store->getKey()])
        ->get('/admin/customers/'.$customer->getKey())
        ->assertSuccessful()
        ->assertSee('Jane Example')
        ->assertSee('#8101')
        ->assertSee('Home');

    $this->actingAs(adminCustomerManagementUser())
        ->withSession(['current_store_id' => $store->getKey()])
        ->get('/admin/customers/'.$otherCustomer->getKey())
        ->assertNotFound();
});

test('admin customer index filters by name and email', function (): void {
    $store = adminCustomerManagementStore();
    $user = adminCustomerManagementUser();
    adminCustomerManagementCustomer($store, 'jane@example.test', 'Jane Example');
    adminCustomerManagementCustomer($store, 'bravo@example.test', 'Bravo Example');

    Livewire::actingAs($user)
        ->test(AdminCustomersIndex::class)
        ->assertSee('Jane Example')
        ->assertSee('Bravo Example')
        ->set('search', 'jane')
        ->assertSee('Jane Example')
        ->assertDontSee('Bravo Example')
        ->set('search', 'bravo@example.test')
        ->assertSee('Bravo Example')
        ->assertDontSee('Jane Example');
});

test('admin customer detail manages addresses', function (): void {
    $store = adminCustomerManagementStore();
    $user = adminCustomerManagementUser();
    $customer = adminCustomerManagementCustomer($store, 'jane@example.test', 'Jane Example');
    $home = CustomerAddress::factory()->default()->create([
        'customer_id' => $customer->getKey(),
        'label' => 'Home',
    ]);

    Livewire::actingAs($user)
        ->test(AdminCustomerShow::class, ['customer' => $customer])
        ->call('openAddressForm')
        ->set('addressLabel', 'Office')
        ->set('addressJson.address1', 'Business Street 5')
        ->set('addressJson.city', 'Berlin')
        ->set('addressJson.postal_code', '10115')
        ->set('addressJson.country', 'DE')
        ->call('saveAddress')
        ->assertHasNoErrors();

    $office = CustomerAddress::query()
        ->where('customer_id', $customer->getKey())
        ->where('label', 'Office')
        ->firstOrFail();

    expect($office->is_default)->toBeFalse();

    Livewire::actingAs($user)
        ->test(AdminCustomerShow::class, ['customer' => $customer])
        ->call('setDefaultAddress', $office->getKey())
        ->assertHasNoErrors()
        ->call('openAddressForm', $office->getKey())
        ->set('addressLabel', 'HQ')
        ->call('saveAddress')
        ->assertHasNoErrors()
        ->call('deleteAddress', $home->getKey())
        ->assertHasNoErrors();

    expect($office->refresh()->is_default)->toBeTrue()
        ->and($office->label)->toBe('HQ')
        ->and(CustomerAddress::query()->whereKey($home->getKey())->exists())->toBeFalse();
});

test('admin customer detail rejects customers from another store', function (): void {
    $store = adminCustomerManagementStore();
    $otherStore = Store::factory()->create();
    $otherCustomer = adminCustomerManagementCustomer($otherStore, 'other@example.test', 'Other Customer');

    app()->instance('current_store', $store);

    Livewire::actingAs(adminCustomerManagementUser())
        ->test(AdminCustomerShow::class, ['customer' => $otherCustomer])
        ->assertStatus(404);
});


Output:
Chunk ID: f90ec2
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 575
Output:
test('can process a refund', function (): void {
    adminOrderOpenOrder($this, '#1001')
        ->click('button[data-test="refund-modal-button"]')
        ->wait(1)
        ->fill('input[wire\\:model="refundAmount"]', '10.00')
        ->fill('textarea[wire\\:model="refundReason"]', 'Customer requested partial refund')
        ->click('button[data-test="refund-submit-button"]')
        ->wait(1)
        ->assertSee('Refund processed')
        ->assertSee('Partially Refunded')
        ->assertNoJavaScriptErrors();
});

test('shows customer information in order detail', function (): void {
    adminOrderOpenOrder($this, '#1001')
        ->assertSee('customer@acme.test')
        ->assertNoJavaScriptErrors();
});

test('can confirm bank transfer payment', function (): void {
    adminOrderOpenOrder($this, '#1005')
        ->assertSee('Pending')
        ->assertPresent('button[data-test="confirm-payment-button"]')
        ->click('button[data-test="confirm-payment-button"]')
        ->wait(1)
        ->assertSee('Payment confirmed')
        ->assertSee('Paid')
        ->assertDontSee('Confirm payment')
        ->assertNoJavaScriptErrors();
});

test('shows fulfillment guard for unpaid order', function (): void {
    adminOrderOpenOrder($this, '#1005')
        ->assertSee('Cannot create fulfillment')
        ->assertSee('Payment must be confirmed before items can be fulfilled')
        ->assertScript('document.querySelector("button[data-test=\"fulfillment-modal-button\"]") === null')
        ->assertNoJavaScriptErrors();
});

test('can mark fulfillment as shipped', function (): void {
    $page = adminOrderCreateFulfillmentInBrowser(adminOrderOpenOrder($this, '#1001'));

    $page->click('button[data-test="mark-fulfillment-shipped-button"]')
        ->wait(1)
        ->assertSee('Shipped')
        ->assertNoJavaScriptErrors();
});

test('can mark fulfillment as delivered', function (): void {
    $page = adminOrderCreateFulfillmentInBrowser(adminOrderOpenOrder($this, '#1001'));

    $page->click('button[data-test="mark-fulfillment-shipped-button"]')
        ->wait(1)
        ->click('button[data-test="mark-fulfillment-delivered-button"]')
        ->wait(1)
        ->assertSee('Delivered')
        ->assertSee('Fulfilled')
        ->assertNoJavaScriptErrors();
});


Output:
Chunk ID: 2429a3
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1224
Output:
<?php

use App\Enums\FinancialStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentMethod;
use App\Enums\PaymentStatus;
use App\Models\Customer;
use App\Models\Order;
use App\Models\OrderLine;
use App\Models\Payment;
use App\Models\Product;
use App\Models\ProductVariant;
use App\Models\Store;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Pest\Browser\Playwright\Playwright;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    Playwright::setHost('shop.test');

    $this->seed(DatabaseSeeder::class);
});

afterEach(function (): void {
    Playwright::setHost(null);
});

function adminCustomerBrowserHost(): array
{
    return ['host' => 'shop.test'];
}

function adminCustomerBrowserAuthenticate(mixed $testCase): Store
{
    $store = Store::query()->where('handle', 'acme-fashion')->firstOrFail();
    $user = User::query()->where('email', 'admin@acme.test')->firstOrFail();

    $testCase->actingAs($user);
    $testCase->withSession(['current_store_id' => $store->getKey()]);

    return $store;
}

function adminCustomerBrowserCustomer(Store $store): Customer
{
    return Customer::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('email', 'customer@acme.test')
        ->firstOrFail();
}

function adminCustomerBrowserCreateOrder(Store $store, Customer $customer): Order
{
    $product = Product::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('handle', 'classic-cotton-t-shirt')
        ->firstOrFail();
    $variant = ProductVariant::withoutGlobalScopes()
        ->where('product_id', $product->getKey())
        ->firstOrFail();
    $shipping = 499;
    $total = $variant->price_amount + $shipping;

    $order = Order::factory()->create([
        'store_id' => $store->getKey(),
        'customer_id' => $customer->getKey(),
        'order_number' => '#1001',
        'payment_method' => PaymentMethod::CreditCard,
        'status' => OrderStatus::Paid,
        'financial_status' => FinancialStatus::Paid,
        'fulfillment_status' => FulfillmentStatus::Unfulfilled,
        'currency' => $store->default_currency,
        'subtotal_amount' => $variant->price_amount,
        'discount_amount' => 0,
        'shipping_amount' => $shipping,
        'tax_amount' => 0,
        'total_amount' => $total,
        'email' => $customer->email,
        'placed_at' => now()->subDay(),
    ]);

    OrderLine::factory()->create([
        'order_id' => $order->getKey(),
        'product_id' => $product->getKey(),
        'variant_id' => $variant->getKey(),
        'title_snapshot' => 'Classic Cotton T-Shirt',
        'sku_snapshot' => $variant->sku,
        'quantity' => 1,
        'unit_price_amount' => $variant->price_amount,
        'total_amount' => $variant->price_amount,
    ]);

    Payment::factory()->create([
        'order_id' => $order->getKey(),
        'method' => PaymentMethod::CreditCard,
        'status' => PaymentStatus::Captured,
        'amount' => $total,
        'currency' => $store->default_currency,
    ]);

    return $order->refresh();
}

function adminCustomerBrowserOpenCustomers(mixed $testCase): mixed
{
    adminCustomerBrowserAuthenticate($testCase);

    return visit('/admin/customers', adminCustomerBrowserHost())
        ->wait(1)
        ->assertPathIs('/admin/customers')
        ->assertSee('Customers')
        ->assertNoJavaScriptErrors();
}

function adminCustomerBrowserOpenCustomer(mixed $testCase): mixed
{
    return adminCustomerBrowserOpenCustomers($testCase)
        ->assertSee('John Doe')
        ->click('a:has-text("John Doe")')
        ->wait(1)
        ->assertPathContains('/admin/customers/')
        ->assertNoJavaScriptErrors();
}

test('shows the customer list', function (): void {
    adminCustomerBrowserOpenCustomers($this)
        ->assertSee('customer@acme.test')
        ->assertSee('John Doe')
        ->assertNoJavaScriptErrors();
});

test('shows customer detail with order history', function (): void {
    $store = adminCustomerBrowserAuthenticate($this);
    $customer = adminCustomerBrowserCustomer($store);
    adminCustomerBrowserCreateOrder($store, $customer);

    visit('/admin/customers', adminCustomerBrowserHost())
        ->wait(1)
        ->assertPathIs('/admin/customers')
        ->click('a:has-text("John Doe")')
        ->wait(1)
        ->assertPathContains('/admin/customers/')
        ->assertSee('John Doe')
        ->assertSee('customer@acme.test')
        ->assertSee('Order history')
        ->assertSee('#1001')
        ->assertNoJavaScriptErrors();
});

test('shows customer addresses', function (): void {
    adminCustomerBrowserOpenCustomer($this)
        ->assertSee('John Doe')
        ->assertSee('Addresses')
        ->assertSee('Home')
        ->assertNoJavaScriptErrors();
});


Output:
Chunk ID: 16dd88
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1257
Output:
<?php

use App\Models\Customer;
use App\Models\Order;
use App\Models\Store;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Pest\Browser\Playwright\Playwright;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    Playwright::setHost('acme-fashion.test');

    $this->seed(DatabaseSeeder::class);
});

afterEach(function (): void {
    Playwright::setHost(null);
});

function tenantIsolationHost(): array
{
    return ['host' => 'acme-fashion.test'];
}

function tenantIsolationStore(string $handle): Store
{
    return Store::query()->where('handle', $handle)->firstOrFail();
}

function tenantIsolationFashionCustomer(): Customer
{
    $store = tenantIsolationStore('acme-fashion');

    return Customer::withoutGlobalScopes()
        ->where('store_id', $store->getKey())
        ->where('email', 'customer@acme.test')
        ->firstOrFail();
}

function tenantIsolationCreateOrders(): void
{
    $fashionStore = tenantIsolationStore('acme-fashion');
    $electronicsStore = tenantIsolationStore('acme-electronics');
    $fashionCustomer = tenantIsolationFashionCustomer();
    $electronicsCustomer = Customer::factory()->create([
        'store_id' => $electronicsStore->getKey(),
        'email' => 'customer@acme.test',
        'password' => 'password',
        'name' => 'Electronics Customer',
    ]);

    foreach (['#1001', '#1002', '#1004'] as $orderNumber) {
        Order::factory()
            ->forCustomer($fashionCustomer)
            ->paid()
            ->create([
                'store_id' => $fashionStore->getKey(),
                'customer_id' => $fashionCustomer->getKey(),
                'order_number' => $orderNumber,
                'email' => $fashionCustomer->email,
            ]);
    }

    Order::factory()
        ->forCustomer($electronicsCustomer)
        ->paid()
        ->create([
            'store_id' => $electronicsStore->getKey(),
            'customer_id' => $electronicsCustomer->getKey(),
            'order_number' => '#2001',
            'email' => $electronicsCustomer->email,
        ]);
}

function tenantIsolationAdminLogin(): mixed
{
    return visit('/admin/login', tenantIsolationHost())
        ->fill('input[type=email]', 'admin@acme.test')
        ->fill('input[type=password]', 'password')
        ->click('@admin-login-button')
        ->wait(1)
        ->assertPathIs('/admin')
        ->assertSee('Dashboard')
        ->assertNoJavaScriptErrors();
}

function tenantIsolationCustomerLogin(): mixed
{
    return visit('/account/login', tenantIsolationHost())
        ->fill('input[type=email]', 'customer@acme.test')
        ->fill('input[type=password]', 'password')
        ->click('@customer-login-button')
        ->wait(1)
        ->assertPathIs('/account')
        ->assertSee('My Account')
        ->assertSee('John Doe')
        ->assertNoJavaScriptErrors();
}

test('storefront only shows current store products', function (): void {
    visit('/', tenantIsolationHost())
        ->assertSee('Acme Fashion')
        ->assertSee('Classic Cotton T-Shirt')
        ->assertDontSee('Pro Laptop 15')
        ->assertDontSee('Wireless Headphones')
        ->assertNoJavaScriptErrors();
});

test('storefront collections only contain current store products', function (): void {
    visit('/collections/t-shirts', tenantIsolationHost())
        ->assertSee('T-Shirts')
        ->assertSee('Classic Cotton T-Shirt')
        ->assertDontSee('Pro Laptop 15')
        ->assertDontSee('Wireless Headphones')
        ->assertNoJavaScriptErrors();
});

test('admin cannot see other store products or orders', function (): void {
    tenantIsolationCreateOrders();

    tenantIsolationAdminLogin()
        ->click('a[href$="/admin/products"]')
        ->wait(1)
        ->assertPathIs('/admin/products')
        ->assertSee('Products')
        ->assertDontSee('Pro Laptop 15')
        ->assertDontSee('Wireless Headphones')
        ->click('a[href$="/admin/orders"]')
        ->wait(1)
        ->assertPathIs('/admin/orders')
        ->assertSee('#1001')
        ->assertDontSee('#2001')
        ->assertNoJavaScriptErrors();
});

test('search only returns current store products', function (): void {
    visit('/search?q=cotton', tenantIsolationHost())
        ->assertSee('Classic Cotton T-Shirt')
        ->assertDontSee('Pro Laptop 15')
        ->assertNoJavaScriptErrors();

    visit('/search?q=laptop', tenantIsolationHost())
        ->assertDontSee('Pro Laptop 15')
        ->assertSee('No products found')
        ->assertNoJavaScriptErrors();
});

test('customer accounts are scoped to their store', function (): void {
    tenantIsolationCreateOrders();

    tenantIsolationCustomerLogin()
        ->click('nav[aria-label="Account navigation"] a[href$="/account/orders"]')
        ->wait(1)
        ->assertPathIs('/account/orders')
        ->assertSee('#1001')
        ->assertSee('#1002')
        ->assertSee('#1004')
        ->assertDontSee('#2001')
        ->assertNoJavaScriptErrors();
});


Output:
Chunk ID: 2a34a2
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1975
Output:
<?php

use App\Enums\FinancialStatus;
use App\Enums\FulfillmentShipmentStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentMethod;
use App\Enums\PaymentStatus;
use App\Livewire\Admin\Orders\Index as AdminOrdersIndex;
use App\Livewire\Admin\Orders\Show as AdminOrderShow;
use App\Models\Fulfillment;
use App\Models\InventoryItem;
use App\Models\Order;
use App\Models\OrderLine;
use App\Models\Payment;
use App\Models\Product;
use App\Models\ProductVariant;
use App\Models\Store;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;

uses(RefreshDatabase::class);

beforeEach(function () {
    $this->withoutVite();
    $this->seed(DatabaseSeeder::class);
});

function adminOrderManagementStore(): Store
{
    $store = Store::query()->where('handle', 'acme-fashion')->firstOrFail();
    app()->instance('current_store', $store);

    return $store;
}

function adminOrderManagementUser(): User
{
    return User::query()->where('email', 'admin@acme.test')->firstOrFail();
}

/**
 * @return array{0: Order, 1: OrderLine, 2: ProductVariant}
 */
function adminOrderManagementOrder(Store $store, array $orderAttributes = [], int $quantity = 2, int $unitPrice = 2500): array
{
    $product = Product::factory()
        ->withDefaultVariant($unitPrice)
        ->create(['store_id' => $store->getKey()]);
    $variant = ProductVariant::withoutGlobalScopes()
        ->where('product_id', $product->getKey())
        ->firstOrFail();

    InventoryItem::withoutGlobalScopes()
        ->where('variant_id', $variant->getKey())
        ->update([
            'quantity_on_hand' => 10,
            'quantity_reserved' => 0,
        ]);

    $total = $quantity * $unitPrice;
    $order = Order::factory()->paid()->create(array_merge([
        'store_id' => $store->getKey(),
        'subtotal_amount' => $total,
        'shipping_amount' => 0,
        'tax_amount' => 0,
        'total_amount' => $total,
        'email' => 'buyer@example.test',
    ], $orderAttributes));
    $line = OrderLine::factory()->create([
        'order_id' => $order->getKey(),
        'product_id' => $product->getKey(),
        'variant_id' => $variant->getKey(),
        'title_snapshot' => 'Admin Test Product',
        'sku_snapshot' => 'ADMIN-TEST-001',
        'quantity' => $quantity,
        'unit_price_amount' => $unitPrice,
        'total_amount' => $total,
    ]);

    Payment::factory()->create([
        'order_id' => $order->getKey(),
        'method' => $order->payment_method,
        'status' => $order->financial_status === FinancialStatus::Pending ? PaymentStatus::Pending : PaymentStatus::Captured,
        'amount' => $total,
        'currency' => $order->currency,
    ]);

    return [$order, $line, $variant];
}

test('admin order routes require authentication and render scoped orders', function () {
    $store = adminOrderManagementStore();
    [$order] = adminOrderManagementOrder($store, [
        'order_number' => '#7001',
        'email' => 'alpha@example.test',
    ]);

    $otherStore = Store::factory()->create();
    adminOrderManagementOrder($otherStore, [
        'order_number' => '#9001',
        'email' => 'other@example.test',
    ]);

    $this->get('/admin/orders')->assertRedirect('/admin/login');

    $user = adminOrderManagementUser();

    $this->actingAs($user)
        ->get('/admin/orders')
        ->assertSuccessful()
        ->assertSee('#7001')
        ->assertDontSee('#9001');

    $this->actingAs($user)
        ->get('/admin/orders/'.$order->getKey())
        ->assertSuccessful()
        ->assertSee('#7001')
        ->assertSee('Admin Test Product');
});

test('admin order index filters by search and status dimensions', function () {
    $store = adminOrderManagementStore();
    $user = adminOrderManagementUser();
    adminOrderManagementOrder($store, [
        'order_number' => '#7001',
        'email' => 'alpha@example.test',
    ]);
    adminOrderManagementOrder($store, [
        'order_number' => '#7002',
        'email' => 'bravo@example.test',
        'status' => OrderStatus::Pending,
        'financial_status' => FinancialStatus::Pending,
        'payment_method' => PaymentMethod::BankTransfer,
    ]);

    Livewire::actingAs($user)
        ->test(AdminOrdersIndex::class)
        ->assertSee('#7001')
        ->assertSee('#7002')
        ->set('search', 'alpha')
        ->assertSee('#7001')
        ->assertDontSee('#7002')
        ->set('search', '')
        ->set('financialStatusFilter', 'pending')
        ->assertSee('#7002')
        ->assertDontSee('#7001');
});

test('admin order detail confirms bank transfer payments', function () {
    $store = adminOrderManagementStore();
    $user = adminOrderManagementUser();
    [$order, $line, $variant] = adminOrderManagementOrder($store, [
        'payment_method' => PaymentMethod::BankTransfer,
        'status' => OrderStatus::Pending,
        'financial_status' => FinancialStatus::Pending,
    ]);

    InventoryItem::withoutGlobalScopes()
        ->where('variant_id', $variant->getKey())
        ->update(['quantity_reserved' => $line->quantity]);

    Livewire::actingAs($user)
        ->test(AdminOrderShow::class, ['order' => $order])
        ->call('confirmBankTransferPayment')
        ->assertHasNoErrors();

    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();

    expect($order->refresh()->status)->toBe(OrderStatus::Paid)
        ->and($order->financial_status)->toBe(FinancialStatus::Paid)
        ->and($order->payments()->first()?->status)->toBe(PaymentStatus::Captured)
        ->and($inventory->quantity_on_hand)->toBe(8)
        ->and($inventory->quantity_reserved)->toBe(0);
});

test('admin order detail processes refunds and fulfillment transitions', function () {
    $store = adminOrderManagementStore();
    $user = adminOrderManagementUser();
    [$order, $line] = adminOrderManagementOrder($store, quantity: 2, unitPrice: 2500);

    Livewire::actingAs($user)
        ->test(AdminOrderShow::class, ['order' => $order])
        ->set('refundAmount', '10.00')
        ->set('refundReason', 'Customer return')
        ->call('processRefund')
        ->assertHasNoErrors();

    expect($order->refresh()->financial_status)->toBe(FinancialStatus::PartiallyRefunded)
        ->and($order->refunds()->first()?->amount)->toBe(1000);

    Livewire::actingAs($user)
        ->test(AdminOrderShow::class, ['order' => $order->refresh()])
        ->set("fulfillmentLineQuantities.{$line->getKey()}", 1)
        ->set('trackingCompany', 'DHL')
        ->set('trackingNumber', 'DHL123')
        ->call('createFulfillment')
        ->assertHasNoErrors();

    $fulfillment = Fulfillment::query()->where('order_id', $order->getKey())->firstOrFail();

    expect($order->refresh()->fulfillment_status)->toBe(FulfillmentStatus::Partial)
        ->and($fulfillment->lines()->first()?->quantity)->toBe(1);

    Livewire::actingAs($user)
        ->test(AdminOrderShow::class, ['order' => $order->refresh()])
        ->call('markFulfillmentShipped', $fulfillment->getKey())
        ->call('markFulfillmentDelivered', $fulfillment->getKey())
        ->assertHasNoErrors();

    expect($fulfillment->refresh()->status)->toBe(FulfillmentShipmentStatus::Delivered)
        ->and($fulfillment->delivered_at)->not->toBeNull();
});

test('admin order detail rejects orders from another store', function () {
    $store = adminOrderManagementStore();
    $otherStore = Store::factory()->create();
    $user = adminOrderManagementUser();
    [$otherOrder] = adminOrderManagementOrder($otherStore, [
        'order_number' => '#9001',
    ]);

    app()->instance('current_store', $store);

    Livewire::actingAs($user)
        ->test(AdminOrderShow::class, ['order' => $otherOrder])
        ->assertStatus(404);
});


Output:
Chunk ID: eb7a49
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1460
Output:
<?php

use App\Livewire\Admin\Customers\Index as AdminCustomersIndex;
use App\Livewire\Admin\Customers\Show as AdminCustomerShow;
use App\Models\Customer;
use App\Models\CustomerAddress;
use App\Models\Order;
use App\Models\Store;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    $this->withoutVite();
    $this->seed(DatabaseSeeder::class);
});

function adminCustomerManagementStore(): Store
{
    $store = Store::query()->where('handle', 'acme-fashion')->firstOrFail();
    app()->instance('current_store', $store);

    return $store;
}

function adminCustomerManagementUser(): User
{
    return User::query()->where('email', 'admin@acme.test')->firstOrFail();
}

function adminCustomerManagementCustomer(Store $store, string $email, string $name): Customer
{
    return Customer::factory()->create([
        'store_id' => $store->getKey(),
        'email' => $email,
        'name' => $name,
    ]);
}

function adminCustomerManagementOrder(Store $store, Customer $customer, string $orderNumber, int $totalAmount): Order
{
    return Order::factory()->paid()->create([
        'store_id' => $store->getKey(),
        'customer_id' => $customer->getKey(),
        'order_number' => $orderNumber,
        'subtotal_amount' => $totalAmount,
        'shipping_amount' => 0,
        'tax_amount' => 0,
        'total_amount' => $totalAmount,
        'email' => $customer->email,
    ]);
}

test('admin customer routes require authentication and render store scoped customers', function (): void {
    $store = adminCustomerManagementStore();
    $customer = adminCustomerManagementCustomer($store, 'jane@example.test', 'Jane Example');
    adminCustomerManagementOrder($store, $customer, '#8101', 7000);
    CustomerAddress::factory()->default()->create([
        'customer_id' => $customer->getKey(),
        'label' => 'Home',
    ]);

    $otherStore = Store::factory()->create();
    $otherCustomer = adminCustomerManagementCustomer($otherStore, 'other@example.test', 'Other Customer');

    $this->get('/admin/customers')->assertRedirect('/admin/login');

    $this->actingAs(adminCustomerManagementUser())
        ->withSession(['current_store_id' => $store->getKey()])
        ->get('/admin/customers')
        ->assertSuccessful()
        ->assertSee('Jane Example')
        ->assertSee('70.00 EUR')
        ->assertDontSee('Other Customer');

    $this->actingAs(adminCustomerManagementUser())
        ->withSession(['current_store_id' => $store->getKey()])
        ->get('/admin/customers/'.$customer->getKey())
        ->assertSuccessful()
        ->assertSee('Jane Example')
        ->assertSee('#8101')
        ->assertSee('Home');

    $this->actingAs(adminCustomerManagementUser())
        ->withSession(['current_store_id' => $store->getKey()])
        ->get('/admin/customers/'.$otherCustomer->getKey())
        ->assertNotFound();
});

test('admin customer index filters by name and email', function (): void {
    $store = adminCustomerManagementStore();
    $user = adminCustomerManagementUser();
    adminCustomerManagementCustomer($store, 'jane@example.test', 'Jane Example');
    adminCustomerManagementCustomer($store, 'bravo@example.test', 'Bravo Example');

    Livewire::actingAs($user)
        ->test(AdminCustomersIndex::class)
        ->assertSee('Jane Example')
        ->assertSee('Bravo Example')
        ->set('search', 'jane')
        ->assertSee('Jane Example')
        ->assertDontSee('Bravo Example')
        ->set('search', 'bravo@example.test')
        ->assertSee('Bravo Example')
        ->assertDontSee('Jane Example');
});

test('admin customer detail manages addresses', function (): void {
    $store = adminCustomerManagementStore();
    $user = adminCustomerManagementUser();
    $customer = adminCustomerManagementCustomer($store, 'jane@example.test', 'Jane Example');
    $home = CustomerAddress::factory()->default()->create([
        'customer_id' => $customer->getKey(),
        'label' => 'Home',
    ]);

    Livewire::actingAs($user)
        ->test(AdminCustomerShow::class, ['customer' => $customer])
        ->call('openAddressForm')
        ->set('addressLabel', 'Office')
        ->set('addressJson.address1', 'Business Street 5')
        ->set('addressJson.city', 'Berlin')
        ->set('addressJson.postal_code', '10115')
        ->set('addressJson.country', 'DE')
        ->call('saveAddress')
        ->assertHasNoErrors();

    $office = CustomerAddress::query()
        ->where('customer_id', $customer->getKey())
        ->where('label', 'Office')
        ->firstOrFail();

    expect($office->is_default)->toBeFalse();

    Livewire::actingAs($user)
        ->test(AdminCustomerShow::class, ['customer' => $customer])
        ->call('setDefaultAddress', $office->getKey())
        ->assertHasNoErrors()
        ->call('openAddressForm', $office->getKey())
        ->set('addressLabel', 'HQ')
        ->call('saveAddress')
        ->assertHasNoErrors()
        ->call('deleteAddress', $home->getKey())
        ->assertHasNoErrors();

    expect($office->refresh()->is_default)->toBeTrue()
        ->and($office->label)->toBe('HQ')
        ->and(CustomerAddress::query()->whereKey($home->getKey())->exists())->toBeFalse();
});

test('admin customer detail rejects customers from another store', function (): void {
    $store = adminCustomerManagementStore();
    $otherStore = Store::factory()->create();
    $otherCustomer = adminCustomerManagementCustomer($otherStore, 'other@example.test', 'Other Customer');

    app()->instance('current_store', $store);

    Livewire::actingAs(adminCustomerManagementUser())
        ->test(AdminCustomerShow::class, ['customer' => $otherCustomer])
        ->assertStatus(404);
});


sed -n '1,260p' database/seeders/DiscountSeeder.php


sed -n '1,220p' database/seeders/StoreSeeder.php


sed -n '1,240p' database/seeders/AnalyticsSeeder.php


sed -n '1,180p' app/Models/ProductVariant.php


sed -n '1,180p' app/Models/ProductOptionValue.php


sed -n '1,220p' database/seeders/StoreSeeder.php

<?php

namespace Database\Seeders;

use App\Models\Organization;
use App\Models\Store;
use Illuminate\Database\Seeder;

class StoreSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $organization = Organization::query()->where('billing_email', 'billing@acme.test')->firstOrFail();

        foreach ([
            ['handle' => 'acme-fashion', 'name' => 'Acme Fashion'],
            ['handle' => 'acme-electronics', 'name' => 'Acme Electronics'],
        ] as $store) {
            Store::query()->updateOrCreate(
                ['handle' => $store['handle']],
                [
                    'organization_id' => $organization->getKey(),
                    'name' => $store['name'],
                    'status' => 'active',
                    'default_currency' => 'EUR',
                    'default_locale' => 'en',
                    'timezone' => 'Europe/Berlin',
                ],
            );
        }
    }
}


sed -n '1,260p' database/seeders/DiscountSeeder.php

<?php

namespace Database\Seeders;

use App\Models\Discount;
use App\Models\Store;
use Illuminate\Database\Seeder;

class DiscountSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        Store::query()->get()->each(function (Store $store): void {
            foreach ($this->discounts() as $discount) {
                Discount::withoutGlobalScopes()->updateOrCreate(
                    [
                        'store_id' => $store->getKey(),
                        'code' => $discount['code'],
                    ],
                    [
                        'type' => 'code',
                        'value_type' => $discount['value_type'],
                        'value_amount' => $discount['value_amount'],
                        'starts_at' => $discount['starts_at'] ?? now()->subDay(),
                        'ends_at' => $discount['ends_at'] ?? now()->addMonth(),
                        'usage_limit' => $discount['usage_limit'] ?? null,
                        'usage_count' => $discount['usage_count'] ?? 0,
                        'rules_json' => $discount['rules_json'],
                        'status' => $discount['status'] ?? 'active',
                    ],
                );
            }
        });
    }

    /**
     * @return array<int, array{code: string, value_type: string, value_amount: int, rules_json: array<string, mixed>, starts_at?: \Illuminate\Support\Carbon, ends_at?: \Illuminate\Support\Carbon, usage_limit?: int|null, usage_count?: int, status?: string}>
     */
    private function discounts(): array
    {
        return [
            ['code' => 'WELCOME10', 'value_type' => 'percent', 'value_amount' => 10, 'usage_count' => 3, 'rules_json' => ['min_purchase_amount' => 2000]],
            ['code' => 'FLAT5', 'value_type' => 'fixed', 'value_amount' => 500, 'rules_json' => []],
            ['code' => 'SAVE10', 'value_type' => 'percent', 'value_amount' => 10, 'rules_json' => ['customer_eligibility' => 'all']],
            ['code' => '5OFF', 'value_type' => 'fixed', 'value_amount' => 500, 'rules_json' => ['min_purchase_amount' => 2500, 'customer_eligibility' => 'all']],
            ['code' => 'FREESHIP', 'value_type' => 'free_shipping', 'value_amount' => 0, 'rules_json' => ['customer_eligibility' => 'all']],
            ['code' => 'EXPIRED20', 'value_type' => 'percent', 'value_amount' => 20, 'ends_at' => now()->subDay(), 'rules_json' => [], 'status' => 'expired'],
            ['code' => 'MAXED', 'value_type' => 'percent', 'value_amount' => 10, 'usage_limit' => 5, 'usage_count' => 5, 'rules_json' => []],
        ];
    }
}


Output:
Chunk ID: fa7340
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 662
Output:
<?php

namespace Database\Seeders;

use App\Models\Discount;
use App\Models\Store;
use Illuminate\Database\Seeder;

class DiscountSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        Store::query()->get()->each(function (Store $store): void {
            foreach ($this->discounts() as $discount) {
                Discount::withoutGlobalScopes()->updateOrCreate(
                    [
                        'store_id' => $store->getKey(),
                        'code' => $discount['code'],
                    ],
                    [
                        'type' => 'code',
                        'value_type' => $discount['value_type'],
                        'value_amount' => $discount['value_amount'],
                        'starts_at' => $discount['starts_at'] ?? now()->subDay(),
                        'ends_at' => $discount['ends_at'] ?? now()->addMonth(),
                        'usage_limit' => $discount['usage_limit'] ?? null,
                        'usage_count' => $discount['usage_count'] ?? 0,
                        'rules_json' => $discount['rules_json'],
                        'status' => $discount['status'] ?? 'active',
                    ],
                );
            }
        });
    }

    /**
     * @return array<int, array{code: string, value_type: string, value_amount: int, rules_json: array<string, mixed>, starts_at?: \Illuminate\Support\Carbon, ends_at?: \Illuminate\Support\Carbon, usage_limit?: int|null, usage_count?: int, status?: string}>
     */
    private function discounts(): array
    {
        return [
            ['code' => 'WELCOME10', 'value_type' => 'percent', 'value_amount' => 10, 'usage_count' => 3, 'rules_json' => ['min_purchase_amount' => 2000]],
            ['code' => 'FLAT5', 'value_type' => 'fixed', 'value_amount' => 500, 'rules_json' => []],
            ['code' => 'SAVE10', 'value_type' => 'percent', 'value_amount' => 10, 'rules_json' => ['customer_eligibility' => 'all']],
            ['code' => '5OFF', 'value_type' => 'fixed', 'value_amount' => 500, 'rules_json' => ['min_purchase_amount' => 2500, 'customer_eligibility' => 'all']],
            ['code' => 'FREESHIP', 'value_type' => 'free_shipping', 'value_amount' => 0, 'rules_json' => ['customer_eligibility' => 'all']],
            ['code' => 'EXPIRED20', 'value_type' => 'percent', 'value_amount' => 20, 'ends_at' => now()->subDay(), 'rules_json' => [], 'status' => 'expired'],
            ['code' => 'MAXED', 'value_type' => 'percent', 'value_amount' => 10, 'usage_limit' => 5, 'usage_count' => 5, 'rules_json' => []],
        ];
    }
}


Output:
Chunk ID: 2505f5
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 249
Output:
<?php

namespace Database\Seeders;

use App\Models\Organization;
use App\Models\Store;
use Illuminate\Database\Seeder;

class StoreSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $organization = Organization::query()->where('billing_email', 'billing@acme.test')->firstOrFail();

        foreach ([
            ['handle' => 'acme-fashion', 'name' => 'Acme Fashion'],
            ['handle' => 'acme-electronics', 'name' => 'Acme Electronics'],
        ] as $store) {
            Store::query()->updateOrCreate(
                ['handle' => $store['handle']],
                [
                    'organization_id' => $organization->getKey(),
                    'name' => $store['name'],
                    'status' => 'active',
                    'default_currency' => 'EUR',
                    'default_locale' => 'en',
                    'timezone' => 'Europe/Berlin',
                ],
            );
        }
    }
}


sed -n '1,240p' database/seeders/AnalyticsSeeder.php

<?php

namespace Database\Seeders;

use App\Enums\AnalyticsEventType;
use App\Models\AnalyticsEvent;
use App\Models\Customer;
use App\Models\Store;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class AnalyticsSeeder extends Seeder
{
    public function run(): void
    {
        Store::query()->get()->each(function (Store $store): void {
            $this->seedDailyMetrics($store);

            if ($store->handle === 'acme-fashion') {
                $this->seedEventStream($store);
            }
        });
    }

    private function seedDailyMetrics(Store $store): void
    {
        foreach (range(0, 29) as $daysAgo) {
            $date = now()->subDays($daysAgo)->toDateString();
            $orders = max(0, 10 - ($daysAgo % 6));
            $revenue = $orders * (5200 + (($daysAgo % 5) * 800));

            DB::table('analytics_daily')->updateOrInsert(
                [
                    'store_id' => $store->getKey(),
                    'date' => $date,
                ],
                [
                    'orders_count' => $orders,
                    'revenue_amount' => $revenue,
                    'aov_amount' => $orders > 0 ? intdiv($revenue, $orders) : 0,
                    'visits_count' => 160 + (($daysAgo * 7) % 80),
                    'add_to_cart_count' => 42 + ($daysAgo % 13),
                    'checkout_started_count' => 18 + ($daysAgo % 8),
                    'checkout_completed_count' => $orders,
                ],
            );
        }
    }

    private function seedEventStream(Store $store): void
    {
        $customer = Customer::withoutGlobalScopes()
            ->where('store_id', $store->getKey())
            ->first();

        $types = [
            AnalyticsEventType::PageView,
            AnalyticsEventType::PageView,
            AnalyticsEventType::PageView,
            AnalyticsEventType::ProductView,
            AnalyticsEventType::ProductView,
            AnalyticsEventType::AddToCart,
            AnalyticsEventType::CheckoutStarted,
            AnalyticsEventType::CheckoutCompleted,
            AnalyticsEventType::Search,
            AnalyticsEventType::RemoveFromCart,
        ];

        $referrers = [
            'https://google.com/search?q=acme+fashion',
            'https://instagram.com/acme-fashion',
            'direct',
            'https://newsletter.example/acme',
        ];

        foreach (range(1, 210) as $index) {
            $type = $types[$index % count($types)];
            $occurredAt = now()
                ->subDays($index % 7)
                ->setTime($index % 24, ($index * 7) % 60, 0);

            AnalyticsEvent::withoutGlobalScopes()->updateOrCreate(
                [
                    'store_id' => $store->getKey(),
                    'client_event_id' => "seed_evt_{$store->handle}_{$index}",
                ],
                [
                    'type' => $type,
                    'session_id' => 'seed_sess_'.($index % 48),
                    'customer_id' => $index % 5 === 0 ? $customer?->getKey() : null,
                    'properties_json' => $this->propertiesFor($type, $index, $referrers[$index % count($referrers)]),
                    'occurred_at' => $occurredAt,
                    'created_at' => $occurredAt,
                ],
            );
        }
    }

    /**
     * @return array<string, mixed>
     */
    private function propertiesFor(AnalyticsEventType $type, int $index, string $referrer): array
    {
        $base = [
            'channel' => $index % 4 === 0 ? 'api' : 'storefront',
            'device' => ['desktop', 'mobile', 'tablet'][$index % 3],
            'referrer' => $referrer,
        ];

        return match ($type) {
            AnalyticsEventType::PageView => [
                ...$base,
                'url' => $index % 2 === 0 ? '/' : '/collections/t-shirts',
            ],
            AnalyticsEventType::ProductView => [
                ...$base,
                'product_id' => ($index % 20) + 1,
                'product_title' => 'Seeded product '.$index,
                'url' => '/products/classic-cotton-t-shirt',
            ],
            AnalyticsEventType::AddToCart, AnalyticsEventType::RemoveFromCart => [
                ...$base,
                'product_id' => ($index % 20) + 1,
                'variant_id' => ($index % 120) + 1,
                'quantity' => 1 + ($index % 3),
                'price_amount' => 2499 + (($index % 5) * 500),
            ],
            AnalyticsEventType::CheckoutStarted => [
                ...$base,
                'cart_id' => $index,
                'subtotal_amount' => 4500 + (($index % 9) * 500),
            ],
            AnalyticsEventType::CheckoutCompleted => [
                ...$base,
                'order_id' => $index,
                'order_number' => 'SEED-'.$index,
                'total_amount' => 6500 + (($index % 9) * 750),
            ],
            AnalyticsEventType::Search => [
                ...$base,
                'query' => ['cotton', 'hoodie', 'jeans', 'sneakers'][$index % 4],
                'results_count' => 3 + ($index % 8),
            ],
        };
    }
}


Output:
Chunk ID: cecc9b
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1293
Output:
<?php

namespace Database\Seeders;

use App\Enums\AnalyticsEventType;
use App\Models\AnalyticsEvent;
use App\Models\Customer;
use App\Models\Store;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class AnalyticsSeeder extends Seeder
{
    public function run(): void
    {
        Store::query()->get()->each(function (Store $store): void {
            $this->seedDailyMetrics($store);

            if ($store->handle === 'acme-fashion') {
                $this->seedEventStream($store);
            }
        });
    }

    private function seedDailyMetrics(Store $store): void
    {
        foreach (range(0, 29) as $daysAgo) {
            $date = now()->subDays($daysAgo)->toDateString();
            $orders = max(0, 10 - ($daysAgo % 6));
            $revenue = $orders * (5200 + (($daysAgo % 5) * 800));

            DB::table('analytics_daily')->updateOrInsert(
                [
                    'store_id' => $store->getKey(),
                    'date' => $date,
                ],
                [
                    'orders_count' => $orders,
                    'revenue_amount' => $revenue,
                    'aov_amount' => $orders > 0 ? intdiv($revenue, $orders) : 0,
                    'visits_count' => 160 + (($daysAgo * 7) % 80),
                    'add_to_cart_count' => 42 + ($daysAgo % 13),
                    'checkout_started_count' => 18 + ($daysAgo % 8),
                    'checkout_completed_count' => $orders,
                ],
            );
        }
    }

    private function seedEventStream(Store $store): void
    {
        $customer = Customer::withoutGlobalScopes()
            ->where('store_id', $store->getKey())
            ->first();

        $types = [
            AnalyticsEventType::PageView,
            AnalyticsEventType::PageView,
            AnalyticsEventType::PageView,
            AnalyticsEventType::ProductView,
            AnalyticsEventType::ProductView,
            AnalyticsEventType::AddToCart,
            AnalyticsEventType::CheckoutStarted,
            AnalyticsEventType::CheckoutCompleted,
            AnalyticsEventType::Search,
            AnalyticsEventType::RemoveFromCart,
        ];

        $referrers = [
            'https://google.com/search?q=acme+fashion',
            'https://instagram.com/acme-fashion',
            'direct',
            'https://newsletter.example/acme',
        ];

        foreach (range(1, 210) as $index) {
            $type = $types[$index % count($types)];
            $occurredAt = now()
                ->subDays($index % 7)
                ->setTime($index % 24, ($index * 7) % 60, 0);

            AnalyticsEvent::withoutGlobalScopes()->updateOrCreate(
                [
                    'store_id' => $store->getKey(),
                    'client_event_id' => "seed_evt_{$store->handle}_{$index}",
                ],
                [
                    'type' => $type,
                    'session_id' => 'seed_sess_'.($index % 48),
                    'customer_id' => $index % 5 === 0 ? $customer?->getKey() : null,
                    'properties_json' => $this->propertiesFor($type, $index, $referrers[$index % count($referrers)]),
                    'occurred_at' => $occurredAt,
                    'created_at' => $occurredAt,
                ],
            );
        }
    }

    /**
     * @return array<string, mixed>
     */
    private function propertiesFor(AnalyticsEventType $type, int $index, string $referrer): array
    {
        $base = [
            'channel' => $index % 4 === 0 ? 'api' : 'storefront',
            'device' => ['desktop', 'mobile', 'tablet'][$index % 3],
            'referrer' => $referrer,
        ];

        return match ($type) {
            AnalyticsEventType::PageView => [
                ...$base,
                'url' => $index % 2 === 0 ? '/' : '/collections/t-shirts',
            ],
            AnalyticsEventType::ProductView => [
                ...$base,
                'product_id' => ($index % 20) + 1,
                'product_title' => 'Seeded product '.$index,
                'url' => '/products/classic-cotton-t-shirt',
            ],
            AnalyticsEventType::AddToCart, AnalyticsEventType::RemoveFromCart => [
                ...$base,
                'product_id' => ($index % 20) + 1,
                'variant_id' => ($index % 120) + 1,
                'quantity' => 1 + ($index % 3),
                'price_amount' => 2499 + (($index % 5) * 500),
            ],
            AnalyticsEventType::CheckoutStarted => [
                ...$base,
                'cart_id' => $index,
                'subtotal_amount' => 4500 + (($index % 9) * 500),
            ],
            AnalyticsEventType::CheckoutCompleted => [
                ...$base,
                'order_id' => $index,
                'order_number' => 'SEED-'.$index,
                'total_amount' => 6500 + (($index % 9) * 750),
            ],
            AnalyticsEventType::Search => [
                ...$base,
                'query' => ['cotton', 'hoodie', 'jeans', 'sneakers'][$index % 4],
                'results_count' => 3 + ($index % 8),
            ],
        };
    }
}