This commit is contained in:
2026-02-03 15:31:29 +05:00
commit 326c677e8d
2800 changed files with 1489388 additions and 0 deletions

View File

@@ -0,0 +1,243 @@
<?php
use App\Models\Ecommerce\Channel\Channel;
use App\Models\Ecommerce\Product\Cart\CartItem;
use App\Models\Ecommerce\Product\Order\Order;
use App\Models\Ecommerce\Product\Order\Payment\OrderPayment;
use App\Models\Ecommerce\Product\Order\Shipping\OrderShipping;
use App\Models\Ecommerce\Product\Order\Status\OrderStatus;
use App\Models\Ecommerce\Product\Product\Product;
use App\Models\System\Settings\Location\Region;
use App\Models\System\Settings\Payments\PaymentType;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
uses(RefreshDatabase::class);
beforeEach(function () {
Config::set('ecommerce.api.token', 'test-token');
$this->user = User::factory()->create([
'password' => 'password',
'phone_number' => 61929248,
]);
// Create tmpost channel required by OrderRepository
if (Channel::where('slug', 'tmpost')->doesntExist()) {
Channel::create(['slug' => 'tmpost', 'name' => 'TM Post']);
}
// Mock default payment type for OrderPayment::default()
if (PaymentType::count() === 0) {
$paymentType = new PaymentType();
$paymentType->forceFill([
'id' => 1,
'code' => 'cash',
'name' => ['en' => 'Cash'],
'tax' => 0,
'is_enabled' => true,
]);
$paymentType->save();
}
});
test('authenticated user can list their orders', function () {
$order = new Order();
$order->forceFill([
'user_id' => $this->user->id,
'number' => 'ORD-123',
'customer_name' => 'John Doe',
'customer_phone' => 61929248,
'customer_address' => 'Test Address',
'shipping_method' => OrderShipping::STANDART,
'shipping_price' => 20,
'payment_type_id' => 1, // Assuming ID 1 exists or mocked
'region' => Region::AG,
'delivery_at' => now(),
'status' => OrderStatus::PENDING,
]);
$order->save();
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => 'test-token'])
->getJson('/api/v1/orders');
$response->assertOk()
->assertJsonStructure([
'data' => [
'*' => [
'id',
'number',
// Add other fields from OrderIndexResource
]
]
]);
});
test('unauthenticated user cannot list orders', function () {
$this->withHeaders(['Api-Token' => 'test-token'])
->getJson('/api/v1/orders')
->assertUnauthorized();
});
test('can place an order', function () {
// Setup prerequisites
$product = Product::create([
'name' => 'Test Product',
'slug' => 'test-product',
'price_amount' => 100,
'cost_amount' => 80,
'stock' => 10,
'is_visible' => true,
]);
// Add item to cart
CartItem::create([
'user_id' => $this->user->id,
'product_id' => $product->id,
'product_quantity' => 2,
]);
// Mock PaymentType if needed (OrderPayment::values() uses DB)
PaymentType::create([
'code' => 'card',
'name' => ['en' => 'Card'],
'tax' => 0,
'is_enabled' => true,
]);
$paymentTypeId = PaymentType::where('code', 'card')->first()->id;
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => 'test-token'])
->postJson('/api/v1/orders', [
'customer_name' => 'John Doe',
'customer_phone' => 61929248,
'customer_address' => '123 Main St',
'shipping_method' => OrderShipping::STANDART,
'payment_type_id' => $paymentTypeId,
'region' => Region::AG,
'notes' => 'Test order',
]);
$response->assertCreated()
->assertJsonStructure(['data' => ['order_id']]);
// Verify order created
$this->assertDatabaseHas('orders', [
'user_id' => $this->user->id,
'customer_name' => 'John Doe',
'notes' => 'Test order',
]);
// Verify cart cleared
$this->assertDatabaseMissing('cart_items', [
'user_id' => $this->user->id,
]);
// Verify stock reduced
$this->assertEquals(8, $product->fresh()->stock);
});
test('cannot place order with empty cart', function () {
// Ensure cart is empty
$this->user->carts()->delete();
// Mock PaymentType
PaymentType::create([
'code' => 'online', // unique code
'name' => ['en' => 'Online'],
'tax' => 0,
'is_enabled' => true,
]);
$paymentTypeId = PaymentType::where('code', 'online')->first()->id;
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => 'test-token'])
->postJson('/api/v1/orders', [
'customer_name' => 'John Doe',
'customer_phone' => 61929248,
'customer_address' => '123 Main St',
'shipping_method' => OrderShipping::STANDART,
'payment_type_id' => $paymentTypeId,
'region' => Region::AG,
]);
// The validation 'user_without_product_in_cart' should fail
$response->assertStatus(422)
->assertJsonValidationErrors(['user_without_product_in_cart']);
});
test('order validation fails with invalid data', function () {
// Add item to cart to pass that check
$product = Product::create(['name' => 'P', 'slug' => 'p', 'stock' => 1]);
CartItem::create(['user_id' => $this->user->id, 'product_id' => $product->id, 'product_quantity' => 1]);
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => 'test-token'])
->postJson('/api/v1/orders', [
'customer_name' => '', // Required
'shipping_method' => 'invalid_method', // Invalid enum
]);
$response->assertStatus(422)
->assertJsonValidationErrors(['customer_name', 'shipping_method']);
});
test('can show specific order', function () {
$order = new Order();
$order->forceFill([
'user_id' => $this->user->id,
'number' => 'ORD-SHOW',
'customer_name' => 'John Doe',
'customer_phone' => 61929248,
'customer_address' => 'Address',
'shipping_method' => OrderShipping::STANDART,
'shipping_price' => 20,
'payment_type_id' => 1,
'region' => Region::AG,
'delivery_at' => now(),
'status' => OrderStatus::PENDING,
]);
$order->save();
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => 'test-token'])
->getJson("/api/v1/orders/{$order->id}");
$response->assertOk()
->assertJsonPath('data.id', $order->id)
->assertJsonPath('data.number', 'ORD-SHOW');
});
test('can delete order (if allowed)', function () {
// Note: The controller destroy method is basically empty: return response()->rest();
// But the route exists. Let's test it returns 200 at least.
$order = new Order();
$order->forceFill([
'user_id' => $this->user->id,
'number' => 'ORD-DEL',
'customer_name' => 'John Doe',
'customer_phone' => 61929248,
'customer_address' => 'Address',
'shipping_method' => OrderShipping::STANDART,
'shipping_price' => 20,
'payment_type_id' => 1,
'region' => Region::AG,
'delivery_at' => now(),
'status' => OrderStatus::PENDING,
]);
$order->save();
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => 'test-token'])
->deleteJson("/api/v1/orders/{$order->id}");
$response->assertOk();
$this->assertSoftDeleted('orders', [
'id' => $order->id,
]);
});