Files
postshop-backend/tests/Feature/Api/V1/CartTest.php
Mekan1206 c46eccb24f Refactor code for improved readability and consistency
- Removed unnecessary blank lines in various files to enhance code clarity.
- Updated comments for consistency and clarity across multiple classes and methods.
- Adjusted spacing in test files for better formatting and readability.
2026-02-08 02:24:43 +05:00

245 lines
8.2 KiB
PHP

<?php
use App\Models\Ecommerce\Product\Cart\CartItem;
use App\Models\Ecommerce\Product\Product\Product;
use App\Models\User;
beforeEach(function () {
$this->user = User::factory()->create([
'password' => 'password',
'phone_number' => 61929248,
]);
// Helper to create product with stock
$this->createProductWithStock = function ($stock = 10) {
// Since we don't have factories for Channel/Inventory, and the Controller logic
// for 'stock' check seems to rely on the 'stock' column on the products table
// (based on CartController::index logic: if ($cartItem->product->stock < ...)),
// we can just create a product with the stock attribute.
// If Product factory doesn't exist, we'll create it manually.
return Product::create([
'name' => 'Test Product',
'slug' => 'test-product-'.uniqid(),
'stock' => $stock,
'price_amount' => 100,
'is_visible' => true,
]);
};
});
test('unauthenticated user cannot access cart', function () {
$this->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->getJson('/api/v1/carts')
->assertStatus(401);
});
test('authenticated user can view empty cart', function () {
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->getJson('/api/v1/carts');
$response->assertStatus(200)
->assertJson(['data' => []]);
});
test('authenticated user can store item in cart', function () {
$product = ($this->createProductWithStock)(10);
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->postJson('/api/v1/carts', [
'product_id' => $product->id,
'product_quantity' => 2,
]);
$response->assertStatus(201);
$this->assertDatabaseHas('cart_items', [
'user_id' => $this->user->id,
'product_id' => $product->id,
'product_quantity' => 2,
]);
});
test('storing item updates quantity if already in cart', function () {
$product = ($this->createProductWithStock)(10);
// Initial add
CartItem::create([
'user_id' => $this->user->id,
'product_id' => $product->id,
'product_quantity' => 1,
]);
// Update quantity
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->postJson('/api/v1/carts', [
'product_id' => $product->id,
'product_quantity' => 5,
]);
$response->assertStatus(201);
$this->assertDatabaseHas('cart_items', [
'user_id' => $this->user->id,
'product_id' => $product->id,
'product_quantity' => 5, // Should update to new quantity, not add
]);
});
test('cart validation fails if product does not exist', function () {
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->postJson('/api/v1/carts', [
'product_id' => 99999,
'product_quantity' => 1,
]);
// Expecting validation error.
// Note: The custom rule ProductStockIsAvailable might handle existence check or it might fail before that.
// The request doesn't use 'exists' rule explicitly but checks stock.
$response->assertStatus(422)
->assertJsonValidationErrors(['product_id']);
});
test('cart validation fails if quantity is invalid', function () {
$product = ($this->createProductWithStock)(10);
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->postJson('/api/v1/carts', [
'product_id' => $product->id,
'product_quantity' => 0, // Min is 1
]);
$response->assertStatus(422)
->assertJsonValidationErrors(['product_quantity']);
});
test('cart validation fails if stock is insufficient', function () {
$product = ($this->createProductWithStock)(5);
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->postJson('/api/v1/carts', [
'product_id' => $product->id,
'product_quantity' => 10,
]);
$response->assertStatus(422)
->assertJsonValidationErrors(['product_id']); // Rule attached to product_id
});
test('authenticated user can list cart items', function () {
$product1 = ($this->createProductWithStock)(10);
$product2 = ($this->createProductWithStock)(10);
CartItem::create(['user_id' => $this->user->id, 'product_id' => $product1->id, 'product_quantity' => 2]);
CartItem::create(['user_id' => $this->user->id, 'product_id' => $product2->id, 'product_quantity' => 1]);
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->getJson('/api/v1/carts');
$response->assertStatus(200)
->assertJsonCount(2, 'data')
->assertJsonStructure([
'data' => [
'*' => [
'id',
'user_id',
'product_id',
'product_quantity',
'product',
],
],
]);
});
test('index adjusts quantity if stock decreased', function () {
$product = ($this->createProductWithStock)(10);
CartItem::create(['user_id' => $this->user->id, 'product_id' => $product->id, 'product_quantity' => 10]);
// Reduce stock
$product->update(['stock' => 5]);
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->getJson('/api/v1/carts');
$response->assertStatus(200);
// Check DB
$this->assertDatabaseHas('cart_items', [
'user_id' => $this->user->id,
'product_id' => $product->id,
'product_quantity' => 5,
]);
});
test('index removes item if out of stock', function () {
$product = ($this->createProductWithStock)(10);
CartItem::create(['user_id' => $this->user->id, 'product_id' => $product->id, 'product_quantity' => 5]);
// Out of stock
$product->update(['stock' => 0]);
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->getJson('/api/v1/carts');
$response->assertStatus(200)
->assertJsonCount(0, 'data');
// Check DB
$this->assertDatabaseMissing('cart_items', [
'user_id' => $this->user->id,
'product_id' => $product->id,
]);
});
test('authenticated user can remove specific item from cart', function () {
$product = ($this->createProductWithStock)(10);
CartItem::create(['user_id' => $this->user->id, 'product_id' => $product->id, 'product_quantity' => 2]);
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->patchJson('/api/v1/carts', [
'product_id' => $product->id,
]);
$response->assertStatus(200);
$this->assertDatabaseMissing('cart_items', [
'user_id' => $this->user->id,
'product_id' => $product->id,
]);
});
test('remove item validation fails if product_id is missing', function () {
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->patchJson('/api/v1/carts', []);
$response->assertStatus(422)
->assertJsonValidationErrors(['product_id']);
});
test('authenticated user can clear entire cart', function () {
$product1 = ($this->createProductWithStock)(10);
$product2 = ($this->createProductWithStock)(10);
CartItem::create(['user_id' => $this->user->id, 'product_id' => $product1->id, 'product_quantity' => 2]);
CartItem::create(['user_id' => $this->user->id, 'product_id' => $product2->id, 'product_quantity' => 1]);
$response = $this->actingAs($this->user, 'sanctum')
->withHeaders(['Api-Token' => config('ecommerce.api.token')])
->deleteJson('/api/v1/carts');
$response->assertStatus(200);
$this->assertDatabaseCount('cart_items', 0);
});