- 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.
245 lines
8.2 KiB
PHP
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);
|
|
});
|