BFI cart single item
This commit is contained in:
parent
816e8661e2
commit
9e7812c70e
|
|
@ -849,8 +849,8 @@ class Cart extends Model
|
|||
Model $cartable,
|
||||
int $quantity = 1,
|
||||
array $parameters = [],
|
||||
\DateTimeInterface $from = null,
|
||||
\DateTimeInterface $until = null
|
||||
null|\DateTimeInterface $from = null,
|
||||
null|\DateTimeInterface $until = null
|
||||
): CartItem {
|
||||
// $cartable must implement Cartable
|
||||
if (! $cartable instanceof Cartable) {
|
||||
|
|
@ -873,8 +873,20 @@ class Cart extends Model
|
|||
$until = $this->until;
|
||||
}
|
||||
|
||||
if ($cartable instanceof Product) {
|
||||
$is_pool = $cartable->isPool();
|
||||
$is_booking = $cartable->isBooking();
|
||||
} elseif (
|
||||
$cartable instanceof ProductPrice
|
||||
&& $cartable->purchasable instanceof Product
|
||||
) {
|
||||
$is_pool = $cartable->purchasable->isPool();
|
||||
$is_booking = $cartable->purchasable->isBooking();
|
||||
}
|
||||
|
||||
|
||||
// For pool products with quantity > 1, add them one at a time to get progressive pricing
|
||||
if ($cartable instanceof Product && $cartable->isPool() && $quantity > 1) {
|
||||
if ($is_pool && $quantity > 1) {
|
||||
// Validate availability if dates are provided
|
||||
if ($from && $until) {
|
||||
$available = $cartable->getPoolMaxQuantity($from, $until);
|
||||
|
|
@ -912,7 +924,9 @@ class Cart extends Model
|
|||
->where('purchasable_type', get_class($cartable))
|
||||
->sum('quantity');
|
||||
|
||||
$availableForThisRequest = $totalCapacity === PHP_INT_MAX ? PHP_INT_MAX : max(0, $totalCapacity - $itemsInCart);
|
||||
$availableForThisRequest = $totalCapacity === PHP_INT_MAX
|
||||
? PHP_INT_MAX
|
||||
: max(0, $totalCapacity - $itemsInCart);
|
||||
|
||||
if ($availableForThisRequest !== PHP_INT_MAX && $quantity > $availableForThisRequest) {
|
||||
throw new NotEnoughStockException(
|
||||
|
|
@ -942,14 +956,18 @@ class Cart extends Model
|
|||
}
|
||||
|
||||
// Check booking product availability if dates are provided
|
||||
if ($cartable->isBooking() && !$cartable->isPool() && !$cartable->isAvailableForBooking($from, $until, $quantity)) {
|
||||
if (
|
||||
$is_booking
|
||||
&& !$is_pool
|
||||
&& !$cartable->isAvailableForBooking($from, $until, $quantity)
|
||||
) {
|
||||
throw new NotEnoughStockException(
|
||||
"Product '{$cartable->name}' is not available for the requested period ({$from->format('Y-m-d')} to {$until->format('Y-m-d')})."
|
||||
);
|
||||
}
|
||||
|
||||
// Check pool product availability if dates are provided
|
||||
if ($cartable->isPool()) {
|
||||
if ($is_pool) {
|
||||
$maxQuantity = $cartable->getPoolMaxQuantity($from, $until);
|
||||
|
||||
// Subtract items already in cart for the same period
|
||||
|
|
@ -987,7 +1005,7 @@ class Cart extends Model
|
|||
} else {
|
||||
// When adding pool items without dates, validate against total pool capacity
|
||||
// This allows adding items even if currently claimed - date-based validation happens later
|
||||
if ($cartable->isPool()) {
|
||||
if ($is_pool) {
|
||||
$totalCapacity = $cartable->getPoolTotalCapacity(); // Total capacity ignoring claims
|
||||
|
||||
// Subtract items already in cart (without dates or with any dates)
|
||||
|
|
@ -1015,7 +1033,7 @@ class Cart extends Model
|
|||
$poolSingleItem = null;
|
||||
$poolPriceId = null;
|
||||
|
||||
if ($cartable instanceof Product && $cartable->isPool()) {
|
||||
if ($is_pool) {
|
||||
$this->unsetRelation('items'); // Clear cached relationship
|
||||
$currentQuantityInCart = $this->items()
|
||||
->where('purchasable_id', $cartable->getKey())
|
||||
|
|
@ -1035,7 +1053,7 @@ class Cart extends Model
|
|||
->where('purchasable_id', $cartable->getKey())
|
||||
->where('purchasable_type', get_class($cartable))
|
||||
->get()
|
||||
->first(function ($item) use ($parameters, $from, $until, $cartable, $poolPriceId) {
|
||||
->first(function ($item) use ($parameters, $from, $until, $cartable, $poolPriceId, $is_pool) {
|
||||
$existingParams = is_array($item->parameters)
|
||||
? $item->parameters
|
||||
: (array) $item->parameters;
|
||||
|
|
@ -1061,7 +1079,7 @@ class Cart extends Model
|
|||
// This is critical because different single items have their own stock limits
|
||||
// even if they happen to share the same price (e.g., via pool fallback price)
|
||||
$priceMatch = true;
|
||||
if ($cartable instanceof Product && $cartable->isPool()) {
|
||||
if ($is_pool) {
|
||||
// Calculate expected price for this item
|
||||
$poolItemData = $cartable->getNextAvailablePoolItemWithPrice($this, null, $from, $until);
|
||||
$expectedPrice = $poolItemData['price'] ?? null;
|
||||
|
|
@ -1085,7 +1103,7 @@ class Cart extends Model
|
|||
|
||||
// Calculate price per day (base price)
|
||||
// For pool products, get price based on how many items are already in cart
|
||||
if ($cartable instanceof Product && $cartable->isPool()) {
|
||||
if ($is_pool) {
|
||||
// Use smarter pricing that considers which price tiers are used
|
||||
$poolItemData = $cartable->getNextAvailablePoolItemWithPrice($this, null, $from, $until);
|
||||
|
||||
|
|
@ -1115,7 +1133,7 @@ class Cart extends Model
|
|||
|
||||
// Ensure prices are not null
|
||||
if ($pricePerDay === null) {
|
||||
if ($cartable instanceof Product && $cartable->isPool()) {
|
||||
if ($is_pool) {
|
||||
// For pool products, throw specific error when neither pool nor single items have prices
|
||||
throw \Blax\Shop\Exceptions\HasNoPriceException::poolProductNoPriceAndNoSingleItemPrices($cartable->name);
|
||||
}
|
||||
|
|
@ -1129,8 +1147,15 @@ class Cart extends Model
|
|||
}
|
||||
|
||||
// Calculate price per unit for the entire period and round to nearest cent for consistency
|
||||
$pricePerUnit = (int) round($pricePerDay * $days);
|
||||
$regularPricePerUnit = (int) round($regularPricePerDay * $days);
|
||||
if ($is_booking) {
|
||||
// For bookings, price scales with days
|
||||
$pricePerUnit = (int) round($pricePerDay * $days);
|
||||
$regularPricePerUnit = (int) round($regularPricePerDay * $days);
|
||||
} else {
|
||||
// For non-bookings, price is per unit regardless of days
|
||||
$pricePerUnit = (int) round($pricePerDay);
|
||||
$regularPricePerUnit = (int) round($regularPricePerDay);
|
||||
}
|
||||
|
||||
// Defensive check - ensure pricePerUnit is not null
|
||||
if ($pricePerUnit === null) {
|
||||
|
|
@ -1158,7 +1183,7 @@ class Cart extends Model
|
|||
$priceId = null;
|
||||
if ($cartable instanceof Product) {
|
||||
// For pool products, use the single item's price_id
|
||||
if ($cartable->isPool() && $poolPriceId) {
|
||||
if ($is_pool && $poolPriceId) {
|
||||
$priceId = $poolPriceId;
|
||||
} else {
|
||||
// Get the default price for the product
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ use Blax\Shop\Enums\ProductType;
|
|||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Models\ProductPurchase;
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class BookingFeatureTest extends TestCase
|
||||
{
|
||||
|
|
@ -48,7 +48,7 @@ class BookingFeatureTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_a_booking_product()
|
||||
{
|
||||
$this->assertNotNull($this->bookingProduct);
|
||||
|
|
@ -56,7 +56,7 @@ class BookingFeatureTest extends TestCase
|
|||
$this->assertTrue($this->bookingProduct->isBooking());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_purchase_a_booking_with_dates()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -77,7 +77,7 @@ class BookingFeatureTest extends TestCase
|
|||
$this->assertEquals($until->format('Y-m-d H:i:s'), $purchase->until->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_booking_without_dates()
|
||||
{
|
||||
$this->expectException(\Exception::class);
|
||||
|
|
@ -86,7 +86,7 @@ class BookingFeatureTest extends TestCase
|
|||
$this->user->purchase($this->price, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_decreases_stock_for_booking_duration()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -108,7 +108,7 @@ class BookingFeatureTest extends TestCase
|
|||
$this->assertEquals($initialStock - 2, $remainingStock);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_releases_stock_after_booking_period()
|
||||
{
|
||||
$from = Carbon::now()->subDays(3);
|
||||
|
|
@ -134,7 +134,7 @@ class BookingFeatureTest extends TestCase
|
|||
$this->assertEquals($until->format('Y-m-d H:i:s'), $claim->expires_at->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_booking_availability()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5);
|
||||
|
|
@ -147,7 +147,7 @@ class BookingFeatureTest extends TestCase
|
|||
$this->assertFalse($this->bookingProduct->isAvailableForBooking($from, $until, 15));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_add_booking_to_cart_with_dates()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -172,7 +172,7 @@ class BookingFeatureTest extends TestCase
|
|||
$this->assertEquals($until->toDateTimeString(), $cartItem->parameters['until']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_checkout_cart_with_booking_product()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -207,7 +207,7 @@ class BookingFeatureTest extends TestCase
|
|||
$this->assertEquals($initialStock - 2, $this->bookingProduct->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_prevents_overbooking()
|
||||
{
|
||||
$from = Carbon::now()->addDays(20);
|
||||
|
|
@ -234,7 +234,7 @@ class BookingFeatureTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_booking_purchases()
|
||||
{
|
||||
$from = Carbon::now()->addDays(25);
|
||||
|
|
@ -267,7 +267,7 @@ class BookingFeatureTest extends TestCase
|
|||
$this->assertTrue($bookingPurchases->first()->isBooking());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_ended_bookings()
|
||||
{
|
||||
$pastFrom = Carbon::now()->subDays(5);
|
||||
|
|
@ -302,7 +302,7 @@ class BookingFeatureTest extends TestCase
|
|||
$this->assertFalse($futurePurchase->isBookingEnded());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_booking_products()
|
||||
{
|
||||
// Create regular product
|
||||
|
|
@ -315,7 +315,7 @@ class BookingFeatureTest extends TestCase
|
|||
$this->assertEquals($this->bookingProduct->id, $bookingProducts->first()->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function booking_stock_expires_after_until_date()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -340,7 +340,7 @@ class BookingFeatureTest extends TestCase
|
|||
$this->assertEquals($until->format('Y-m-d H:i:s'), $stockRecord->expires_at->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function multiple_bookings_with_different_dates_work_independently()
|
||||
{
|
||||
$booking1From = Carbon::now()->addDays(1);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ use Blax\Shop\Tests\TestCase;
|
|||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
|
||||
class BookingPerMinutePricingTest extends TestCase
|
||||
{
|
||||
|
|
@ -48,7 +50,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_exact_24_hours()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(9, 0, 0);
|
||||
|
|
@ -61,7 +63,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(10000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_12_hours_as_half_day()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(9, 0, 0);
|
||||
|
|
@ -74,7 +76,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(5000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_36_hours()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(9, 0, 0);
|
||||
|
|
@ -87,7 +89,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(15000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_6_hours()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(10, 0, 0);
|
||||
|
|
@ -100,7 +102,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(2500, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_90_minutes()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(14, 0, 0);
|
||||
|
|
@ -114,7 +116,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(625, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_2_days_and_3_hours()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(9, 0, 0);
|
||||
|
|
@ -128,7 +130,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(21250, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_with_quantity_for_fractional_days()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(10, 0, 0);
|
||||
|
|
@ -142,7 +144,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(15000, $cartItem->subtotal); // total for 3 units
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_recalculates_price_when_dates_are_updated()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(9, 0, 0);
|
||||
|
|
@ -162,7 +164,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(7500, $cartItem->fresh()->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_45_minutes()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(14, 0, 0);
|
||||
|
|
@ -175,7 +177,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(313, round($cartItem->price, 2)); // Rounded due to decimal precision
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_purchases_booking_with_per_minute_pricing()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(14, 0, 0);
|
||||
|
|
@ -197,7 +199,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(8, $this->bookingProduct->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_updates_cart_item_from_date_recalculates_per_minute_price()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(12, 0, 0);
|
||||
|
|
@ -220,7 +222,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(12500, $cartItem->fresh()->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_updates_cart_item_until_date_recalculates_per_minute_price()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(10, 0, 0);
|
||||
|
|
@ -243,7 +245,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(7500, $cartItem->fresh()->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_weekend_booking_friday_to_monday()
|
||||
{
|
||||
// Friday 6pm to Monday 10am = 64 hours = 2.666... days
|
||||
|
|
@ -258,7 +260,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals($expectedPrice, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_multiple_bookings_with_different_durations()
|
||||
{
|
||||
$cart = \Blax\Shop\Models\Cart::factory()->create([
|
||||
|
|
@ -283,7 +285,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(7500, $cart->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_precise_price_for_irregular_time_spans()
|
||||
{
|
||||
// Test various odd time spans
|
||||
|
|
@ -312,7 +314,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_booking_removal_and_readdition()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(10, 0, 0);
|
||||
|
|
@ -339,7 +341,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(7500, $cartItem2->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_half_hour_increments()
|
||||
{
|
||||
$testCases = [
|
||||
|
|
@ -366,7 +368,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_exact_hour_boundaries()
|
||||
{
|
||||
// Test exact hour boundaries from 1-10 hours
|
||||
|
|
@ -389,7 +391,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_maintains_price_consistency_across_cart_operations()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(14, 0, 0);
|
||||
|
|
@ -416,7 +418,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(5000, $cart->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_very_long_booking_periods()
|
||||
{
|
||||
// 7 days = 168 hours
|
||||
|
|
@ -430,7 +432,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(70000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_7_hour_30_minute_booking()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(9, 0, 0);
|
||||
|
|
@ -442,7 +444,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals('3125', $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_booking_crossing_midnight()
|
||||
{
|
||||
// 11 PM to 3 AM = 4 hours
|
||||
|
|
@ -455,7 +457,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals('1667', $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_validates_minimum_price_for_very_short_bookings()
|
||||
{
|
||||
// 2 minutes
|
||||
|
|
@ -471,7 +473,7 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$this->assertLessThan(100, (float)$cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_15_minute_interval_bookings()
|
||||
{
|
||||
$intervals = [15, 30, 45, 60, 75, 90, 105, 120];
|
||||
|
|
@ -494,4 +496,59 @@ class BookingPerMinutePricingTest extends TestCase
|
|||
$cartItem->delete();
|
||||
}
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_does_only_adjust_price_for_booking_not_for_other_products()
|
||||
{
|
||||
// 2 minutes
|
||||
$from = Carbon::now()->addDays(5)->setTime(10, 0, 0);
|
||||
$until = Carbon::now()->addDays(6)->setTime(10, 2, 0);
|
||||
|
||||
$cartItem = Cart::addBooking($this->bookingProduct, 1, $from, $until);
|
||||
$cart = Cart::current();
|
||||
|
||||
$cart->setDates($from, $until);
|
||||
|
||||
$cart->refresh();
|
||||
|
||||
// 2 minutes = 0.001389 days, $100 * 0.001389 = $0.1389, rounds to $0.14
|
||||
$this->assertEquals(10014, $cartItem->price);
|
||||
|
||||
$single_product = Product::factory()
|
||||
->withStocks(5)
|
||||
->withPrices(1, 5000) // $50.00
|
||||
->create([
|
||||
'name' => 'Wine Bottle',
|
||||
'slug' => 'wine-bottle',
|
||||
'type' => ProductType::SIMPLE,
|
||||
'manage_stock' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(5, $single_product->getAvailableStock());
|
||||
$this->assertEquals(5000, $single_product->getCurrentPrice());
|
||||
|
||||
$this->assertEquals(1, $cart->items()->count());
|
||||
$this->assertEquals(10014, $cart->getTotal());
|
||||
|
||||
$cart->addToCart($single_product, 1);
|
||||
|
||||
$this->assertEquals(2, $cart->items()->count());
|
||||
$this->assertEquals(15014, $cart->getTotal());
|
||||
|
||||
$cart->addToCart($single_product, 1);
|
||||
|
||||
$this->assertEquals(2, $cart->items()->count());
|
||||
$this->assertEquals(20014, $cart->getTotal());
|
||||
|
||||
|
||||
$until = $until->copy()->addDays(10);
|
||||
|
||||
$cart->setDates($from, $until);
|
||||
|
||||
$cart->refresh();
|
||||
|
||||
$this->assertEquals(110014, $cartItem->fresh()->price);
|
||||
$this->assertEquals(5000, $single_product->getCurrentPrice());
|
||||
$this->assertEquals(120014, $cart->getTotal());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ namespace Blax\Shop\Tests\Feature;
|
|||
use Blax\Shop\Enums\ProductRelationType;
|
||||
use Blax\Shop\Enums\ProductType;
|
||||
use Blax\Shop\Exceptions\NotPurchasable;
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Services\CartService;
|
||||
|
|
@ -13,6 +12,7 @@ use Workbench\App\Models\User;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class BookingTimespanValidationTest extends TestCase
|
||||
{
|
||||
|
|
@ -47,7 +47,7 @@ class BookingTimespanValidationTest extends TestCase
|
|||
$this->cartService = new CartService();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_rejects_booking_when_from_is_after_until()
|
||||
{
|
||||
$from = now()->addDays(5);
|
||||
|
|
@ -64,7 +64,7 @@ class BookingTimespanValidationTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_rejects_booking_when_from_equals_until()
|
||||
{
|
||||
$from = now()->addDays(3);
|
||||
|
|
@ -81,7 +81,7 @@ class BookingTimespanValidationTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_rejects_booking_when_from_is_in_the_past()
|
||||
{
|
||||
$from = now()->subDays(2);
|
||||
|
|
@ -98,7 +98,7 @@ class BookingTimespanValidationTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_accepts_booking_when_from_is_exactly_now()
|
||||
{
|
||||
$from = now()->addSeconds(1); // Very slightly in the future to avoid timing issues
|
||||
|
|
@ -113,7 +113,7 @@ class BookingTimespanValidationTest extends TestCase
|
|||
$this->assertNotNull($cartItem->until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_validates_timespan_availability_across_date_range()
|
||||
{
|
||||
// Create a pool product with 1 single item
|
||||
|
|
@ -169,7 +169,7 @@ class BookingTimespanValidationTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_allows_back_to_back_bookings_without_overlap()
|
||||
{
|
||||
// Create a pool product with 2 single items so both bookings can succeed
|
||||
|
|
@ -245,7 +245,7 @@ class BookingTimespanValidationTest extends TestCase
|
|||
$this->assertCount(1, $newUser->currentCart()->items);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_detects_overlap_when_new_booking_ends_during_existing_booking()
|
||||
{
|
||||
// Book days 5-10
|
||||
|
|
@ -276,7 +276,7 @@ class BookingTimespanValidationTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_detects_overlap_when_new_booking_starts_during_existing_booking()
|
||||
{
|
||||
// Book days 5-10
|
||||
|
|
@ -307,7 +307,7 @@ class BookingTimespanValidationTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_detects_overlap_when_new_booking_completely_contains_existing_booking()
|
||||
{
|
||||
// Book days 6-8
|
||||
|
|
@ -338,7 +338,7 @@ class BookingTimespanValidationTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_detects_overlap_when_new_booking_is_completely_contained_by_existing_booking()
|
||||
{
|
||||
// Book days 5-10
|
||||
|
|
@ -369,7 +369,7 @@ class BookingTimespanValidationTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_timezone_aware_timespan_validation()
|
||||
{
|
||||
Carbon::setTestNow(now('America/New_York'));
|
||||
|
|
@ -388,7 +388,7 @@ class BookingTimespanValidationTest extends TestCase
|
|||
$this->assertTrue($cartItem->from->lessThan($cartItem->until));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_allows_same_product_multiple_non_overlapping_timespans()
|
||||
{
|
||||
// Create pool with 2 single items
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use Blax\Shop\Models\ProductPrice;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class CartAddToCartPoolPricingTest extends TestCase
|
||||
{
|
||||
|
|
@ -62,7 +63,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_adds_pool_with_direct_price_to_cart_without_dates()
|
||||
{
|
||||
// Set direct price on pool
|
||||
|
|
@ -85,7 +86,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertNull($cartItem->until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_adds_pool_with_inherited_price_to_cart_without_dates()
|
||||
{
|
||||
// Set prices on single items (20€ and 50€)
|
||||
|
|
@ -118,7 +119,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(3500, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_adds_pool_with_direct_price_to_cart_with_booking_dates()
|
||||
{
|
||||
// Set direct price on pool
|
||||
|
|
@ -145,7 +146,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals($until->format('Y-m-d H:i:s'), $cartItem->until->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_adds_pool_with_inherited_price_to_cart_with_booking_dates()
|
||||
{
|
||||
// Set prices on single items (20€ and 50€)
|
||||
|
|
@ -184,7 +185,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals($until->format('Y-m-d H:i:s'), $cartItem->until->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_multiple_pool_items_with_booking_dates()
|
||||
{
|
||||
// Set direct price on pool
|
||||
|
|
@ -213,7 +214,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(25000, $this->cart->fresh()->getTotal()); // 125.00 × 2 units = 250.00
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_uses_lowest_pricing_strategy_with_mixed_single_item_prices()
|
||||
{
|
||||
// Set prices on single items (20€ and 50€)
|
||||
|
|
@ -242,7 +243,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(2000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_uses_highest_pricing_strategy_with_mixed_single_item_prices()
|
||||
{
|
||||
// Set prices on single items (20€ and 50€)
|
||||
|
|
@ -271,7 +272,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(5000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_uses_lowest_pricing_strategy_with_booking_dates()
|
||||
{
|
||||
// Set prices on single items (20€ and 50€)
|
||||
|
|
@ -303,7 +304,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(6000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_adds_regular_product_to_cart_without_dates()
|
||||
{
|
||||
$regularProduct = Product::factory()->create([
|
||||
|
|
@ -330,7 +331,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertNull($cartItem->until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_creates_separate_items_when_adding_same_pool_product_with_same_dates()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -360,7 +361,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(12000, $this->cart->fresh()->getTotal()); // 6000 × 2 = 12000
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_creates_separate_cart_items_for_same_pool_with_different_dates()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -386,7 +387,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(2, $this->cart->items()->count());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_correct_total_for_cart_with_multiple_pool_items()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -409,7 +410,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(15000, $total);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_pool_with_sale_price()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -436,7 +437,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(10000, $cartItem->regular_price); // 50.00 × 2 days (regular price)
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_pool_with_inherited_sale_price()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -482,7 +483,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(6000, $cartItem->regular_price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_zero_days_as_one_day_minimum()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -503,7 +504,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals('5.00', $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_adding_pool_without_any_pricing()
|
||||
{
|
||||
// Pool with no direct price and single items with no prices
|
||||
|
|
@ -528,7 +529,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->cart->addToCart($pool, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_pool_not_available_for_booking_period()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -552,7 +553,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->cart->addToCart($this->poolProduct, 1, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_booking_product_not_available_for_period()
|
||||
{
|
||||
$bookingProduct = Product::factory()->create([
|
||||
|
|
@ -582,7 +583,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->cart->addToCart($bookingProduct, 1, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_only_from_date_provided()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -600,7 +601,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->cart->addToCart($this->poolProduct, 1, [], $from, null);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_only_until_date_provided()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -618,7 +619,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->cart->addToCart($this->poolProduct, 1, [], null, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_from_is_after_until()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -637,7 +638,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->cart->addToCart($this->poolProduct, 1, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_from_equals_until()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -655,7 +656,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->cart->addToCart($this->poolProduct, 1, [], $date, $date);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_creates_separate_items_for_same_product_same_dates_different_parameters()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -678,7 +679,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(['zone' => 'B'], $cartItem2->parameters);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_pool_quantity_exceeds_available_items()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -698,7 +699,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->cart->addToCart($this->poolProduct, 3, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_partial_pool_availability()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -724,7 +725,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->cart->addToCart($this->poolProduct, 2, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_for_regular_product_without_price()
|
||||
{
|
||||
$regularProduct = Product::factory()->create([
|
||||
|
|
@ -738,7 +739,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->cart->addToCart($regularProduct, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_allows_adding_booking_product_without_dates()
|
||||
{
|
||||
$bookingProduct = Product::factory()->create([
|
||||
|
|
@ -766,7 +767,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(5000, $cartItem->price); // 1 day default
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_allows_adding_pool_product_without_dates()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -787,7 +788,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(3000, $cartItem->price); // 1 day default
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_allows_updating_cart_item_dates_later()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -820,7 +821,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(6000, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_limits_pool_in_cart_quantity_by_single_products()
|
||||
{
|
||||
// Set price on pool
|
||||
|
|
@ -857,7 +858,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->cart->addToCart($this->poolProduct, 1, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_counts_single_item_stock_quantities_in_pool_availability()
|
||||
{
|
||||
// Create a pool with multiple single items having different stock quantities
|
||||
|
|
@ -929,7 +930,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$cart->addToCart($pool, 1, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_counts_available_stock_with_booking_dates()
|
||||
{
|
||||
// Create pool with single items having stock
|
||||
|
|
@ -983,7 +984,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(5, $cart->fresh()->items->sum('quantity'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_allows_unlimited_pool_when_single_items_dont_manage_stock()
|
||||
{
|
||||
// Create pool with single items that don't manage stock
|
||||
|
|
@ -1037,7 +1038,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
$this->assertEquals(500, $cartItem2->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_picks_correct_price_for_pool_and_items_and_respects_stocks()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
|
|
@ -1182,7 +1183,7 @@ class CartAddToCartPoolPricingTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_picks_correct_price_respects_stocks_respects_timespan_for_price()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use Blax\Shop\Models\ProductPrice;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class CartCheckoutSessionTest extends TestCase
|
||||
{
|
||||
|
|
@ -28,7 +29,7 @@ class CartCheckoutSessionTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_stripe_is_disabled()
|
||||
{
|
||||
config(['shop.stripe.enabled' => false]);
|
||||
|
|
@ -50,7 +51,7 @@ class CartCheckoutSessionTest extends TestCase
|
|||
$this->cart->checkoutSession();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_builds_checkout_session_with_simple_product_without_stripe_api()
|
||||
{
|
||||
// Enable Stripe but don't actually call the API
|
||||
|
|
@ -87,7 +88,7 @@ class CartCheckoutSessionTest extends TestCase
|
|||
$this->assertEquals('mock_session_id', $session->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_uses_short_description_for_product_name_if_available()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
@ -127,7 +128,7 @@ class CartCheckoutSessionTest extends TestCase
|
|||
$this->assertEquals('Short Name', $sessionParams['line_items'][0]['price_data']['product_data']['name']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_includes_booking_dates_in_product_name()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
@ -174,7 +175,7 @@ class CartCheckoutSessionTest extends TestCase
|
|||
$this->assertStringContainsString('to', $productName);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_correct_unit_amount_in_cents()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
@ -210,7 +211,7 @@ class CartCheckoutSessionTest extends TestCase
|
|||
$this->assertEquals(2550, $sessionParams['line_items'][0]['price_data']['unit_amount']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_booking_with_fractional_days()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
@ -258,7 +259,7 @@ class CartCheckoutSessionTest extends TestCase
|
|||
$this->assertEquals($cartItem->price, $sessionParams['line_items'][0]['price_data']['unit_amount']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_creates_separate_line_items_for_multiple_products()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
@ -305,7 +306,7 @@ class CartCheckoutSessionTest extends TestCase
|
|||
$this->assertEquals(1, $sessionParams['line_items'][1]['quantity']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_uses_configured_currency()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
@ -341,7 +342,7 @@ class CartCheckoutSessionTest extends TestCase
|
|||
$this->assertEquals('eur', $sessionParams['line_items'][0]['price_data']['currency']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_stores_session_id_in_cart_meta()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
namespace Blax\Shop\Tests\Feature;
|
||||
|
||||
use Blax\Shop\Exceptions\InvalidDateRangeException;
|
||||
use Blax\Shop\Exceptions\NotEnoughAvailableInTimespanException;
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
|
|
@ -11,10 +10,11 @@ use Blax\Shop\Enums\ProductType;
|
|||
use Blax\Shop\Enums\PriceType;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class CartDateManagementTest extends TestCase
|
||||
{
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_set_cart_dates()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
@ -28,7 +28,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($until->toDateTimeString(), $cart->until->toDateTimeString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_stores_dates_as_provided_even_if_backwards()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
@ -44,7 +44,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($until->toDateTimeString(), $cart->until->toDateTimeString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_set_from_date_individually()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
@ -56,7 +56,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($from->toDateTimeString(), $cart->from->toDateTimeString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_set_until_date_individually()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
@ -68,7 +68,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($until->toDateTimeString(), $cart->until->toDateTimeString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_stores_from_date_even_if_after_existing_until_date()
|
||||
{
|
||||
$until = Carbon::now()->addDays(2);
|
||||
|
|
@ -85,7 +85,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($until->toDateTimeString(), $cart->until->toDateTimeString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_stores_until_date_even_if_before_existing_from_date()
|
||||
{
|
||||
$from = Carbon::now()->addDays(3);
|
||||
|
|
@ -102,7 +102,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($until->toDateTimeString(), $cart->until->toDateTimeString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_uses_own_dates_when_set()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -133,7 +133,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($itemUntilDate->toDateString(), $item->getEffectiveUntilDate()->toDateString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_falls_back_to_cart_dates_when_no_own_dates()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -163,7 +163,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($cartUntilDate->toDateString(), $item->getEffectiveUntilDate()->toDateString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_returns_null_when_no_dates_available()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -187,7 +187,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertFalse($item->hasEffectiveDates());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_has_effective_dates_returns_true_when_dates_are_set()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -213,7 +213,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertTrue($item->hasEffectiveDates());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function apply_dates_to_items_sets_dates_on_items_without_dates()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -248,7 +248,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($untilDate->toDateString(), $item->until->toDateString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function apply_dates_to_items_does_not_override_existing_item_dates()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -283,7 +283,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($itemUntilDate->toDateString(), $item->until->toDateString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function apply_dates_to_items_overwrites_when_overwrite_is_true()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -318,7 +318,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($cartUntilDate->toDateString(), $item->until->toDateString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function apply_dates_to_items_fills_only_null_from_date_when_overwrite_false()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -354,7 +354,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($itemUntilDate->toDateString(), $item->until->toDateString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function apply_dates_to_items_fills_only_null_until_date_when_overwrite_false()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -390,7 +390,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertEquals($cartUntilDate->toDateString(), $item->until->toDateString());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function is_ready_to_checkout_uses_cart_fallback_dates()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -417,7 +417,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertTrue($item->is_ready_to_checkout);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_set_from_date_throws_invalid_date_range_exception()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -442,7 +442,7 @@ class CartDateManagementTest extends TestCase
|
|||
$item->setFromDate(Carbon::now()->addDays(3));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_set_until_date_throws_invalid_date_range_exception()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -467,7 +467,7 @@ class CartDateManagementTest extends TestCase
|
|||
$item->setUntilDate(Carbon::now()->addDays(2));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_date_availability_marks_items_unavailable_when_product_not_available()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -499,7 +499,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertFalse($item->is_ready_to_checkout, 'Unavailable item should not be ready for checkout');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function apply_dates_to_items_marks_items_unavailable_when_product_not_available()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -538,7 +538,7 @@ class CartDateManagementTest extends TestCase
|
|||
$this->assertFalse($item->is_ready_to_checkout, 'Unavailable item should not be ready for checkout');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function can_skip_validation_when_setting_dates()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@
|
|||
namespace Blax\Shop\Tests\Feature;
|
||||
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\CartItem;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Enums\ProductType;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class CartDateStringParsingTest extends TestCase
|
||||
{
|
||||
|
|
@ -46,7 +46,7 @@ class CartDateStringParsingTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_set_dates_accepts_string_dates()
|
||||
{
|
||||
$cart = $this->cart->setDates('2025-12-20', '2025-12-25', false);
|
||||
|
|
@ -57,7 +57,7 @@ class CartDateStringParsingTest extends TestCase
|
|||
$this->assertEquals('2025-12-25', $cart->until->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_set_dates_accepts_datetime_objects()
|
||||
{
|
||||
$from = Carbon::parse('2025-12-20');
|
||||
|
|
@ -69,7 +69,7 @@ class CartDateStringParsingTest extends TestCase
|
|||
$this->assertEquals('2025-12-25', $cart->until->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_set_from_date_accepts_string()
|
||||
{
|
||||
$cart = $this->cart->setFromDate('2025-12-20', false);
|
||||
|
|
@ -78,7 +78,7 @@ class CartDateStringParsingTest extends TestCase
|
|||
$this->assertEquals('2025-12-20', $cart->from->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_set_until_date_accepts_string()
|
||||
{
|
||||
$this->cart->update(['from' => Carbon::parse('2025-12-20')]);
|
||||
|
|
@ -88,7 +88,7 @@ class CartDateStringParsingTest extends TestCase
|
|||
$this->assertEquals('2025-12-25', $cart->until->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_set_dates_parses_various_string_formats()
|
||||
{
|
||||
// Test different date string formats that Carbon can parse
|
||||
|
|
@ -112,7 +112,7 @@ class CartDateStringParsingTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_set_from_date_accepts_string()
|
||||
{
|
||||
$cartItem = $this->cart->addToCart(
|
||||
|
|
@ -128,7 +128,7 @@ class CartDateStringParsingTest extends TestCase
|
|||
$this->assertEquals('2025-12-21', $cartItem->from->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_set_until_date_accepts_string()
|
||||
{
|
||||
$cartItem = $this->cart->addToCart(
|
||||
|
|
@ -144,7 +144,7 @@ class CartDateStringParsingTest extends TestCase
|
|||
$this->assertEquals('2025-12-26', $cartItem->until->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_update_dates_accepts_string_dates()
|
||||
{
|
||||
$cartItem = $this->cart->addToCart(
|
||||
|
|
@ -165,7 +165,7 @@ class CartDateStringParsingTest extends TestCase
|
|||
$this->assertEquals($expectedPrice, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_update_dates_accepts_mixed_string_and_datetime()
|
||||
{
|
||||
$cartItem = $this->cart->addToCart(
|
||||
|
|
@ -183,7 +183,7 @@ class CartDateStringParsingTest extends TestCase
|
|||
$this->assertEquals('2025-12-27', $cartItem->until->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_date_parsing_works_with_now_relative_strings()
|
||||
{
|
||||
$cartItem = $this->cart->addToCart(
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use Blax\Shop\Models\CartItem;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class CartFacadeTest extends TestCase
|
||||
{
|
||||
|
|
@ -20,7 +21,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->actingAs(User::factory()->create());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_current_cart()
|
||||
{
|
||||
$cart = Cart::current();
|
||||
|
|
@ -28,7 +29,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertInstanceOf(CartModel::class, $cart);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_cart_for_specific_user()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -39,7 +40,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertEquals($user->id, $cart->customer_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_find_cart_by_id()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -51,7 +52,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertEquals($cart->id, $foundCart->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_null_for_nonexistent_cart()
|
||||
{
|
||||
$cart = Cart::find('nonexistent-id');
|
||||
|
|
@ -59,7 +60,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertNull($cart);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_add_item_to_cart()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->withPrices()->create();
|
||||
|
|
@ -71,7 +72,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertCount(1, Cart::current()->items);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_add_item_with_parameters()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->withPrices()->create();
|
||||
|
|
@ -86,7 +87,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertEquals('blue', $cartItem->parameters['color']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_remove_item_from_cart()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->withPrices()->create();
|
||||
|
|
@ -98,7 +99,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertEquals(2, $cartItem->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_completely_remove_item_from_cart()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->withPrices()->create();
|
||||
|
|
@ -109,7 +110,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertCount(0, Cart::current()->items);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_update_cart_item_quantity()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->withPrices(1, 100)->create();
|
||||
|
|
@ -120,7 +121,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertEquals(5, $updated->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_clear_cart()
|
||||
{
|
||||
$product1 = Product::factory()->withStocks(50)->withPrices()->create();
|
||||
|
|
@ -134,7 +135,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertCount(0, Cart::current()->items);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_checkout_cart()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->withPrices(1, 100)->create();
|
||||
|
|
@ -145,7 +146,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertNotEmpty($purchases);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_cart_total()
|
||||
{
|
||||
$product1 = Product::factory()->withStocks(50)->withPrices(1, 100)->create();
|
||||
|
|
@ -158,7 +159,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertEquals(200.00, $total);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_cart_item_count()
|
||||
{
|
||||
$product1 = Product::factory()->withStocks(50)->withPrices()->create();
|
||||
|
|
@ -171,7 +172,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertEquals(5, $count);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_cart_items()
|
||||
{
|
||||
$product1 = Product::factory()->withStocks(50)->withPrices()->create();
|
||||
|
|
@ -184,7 +185,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertCount(2, $items);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_if_cart_is_empty()
|
||||
{
|
||||
$this->assertTrue(Cart::isEmpty());
|
||||
|
|
@ -195,7 +196,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertFalse(Cart::isEmpty());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_if_cart_is_expired()
|
||||
{
|
||||
$cart = Cart::current();
|
||||
|
|
@ -204,13 +205,13 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertFalse($cart->isExpired());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_if_cart_is_converted()
|
||||
{
|
||||
$this->assertFalse(Cart::isConverted());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_unpaid_amount()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->withPrices(1, 100)->create();
|
||||
|
|
@ -221,7 +222,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertEquals(200.00, $unpaid);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_paid_amount()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->withPrices(1, 100)->create();
|
||||
|
|
@ -232,21 +233,21 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertEquals(0.00, $paid);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_trying_to_add_without_user()
|
||||
{
|
||||
// Skip this test - logging out is complex in tests
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_trying_to_remove_without_user()
|
||||
{
|
||||
// Skip this test - logging out is complex in tests
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_add_multiple_quantities_of_same_product()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->withPrices()->create();
|
||||
|
|
@ -258,7 +259,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertEquals(5, $items[0]->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_add_same_product_with_different_parameters()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->withPrices()->create();
|
||||
|
|
@ -269,7 +270,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertCount(2, $items);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_maintains_separate_carts_for_different_users()
|
||||
{
|
||||
// Verify separate carts exist for different users
|
||||
|
|
@ -280,7 +281,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertEquals(1, $count1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_total_with_multiple_items()
|
||||
{
|
||||
$p1 = Product::factory()->withStocks(50)->withPrices(1, 50)->create();
|
||||
|
|
@ -294,7 +295,7 @@ class CartFacadeTest extends TestCase
|
|||
$this->assertEquals(275.00, Cart::total());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_updates_total_after_removing_items()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->withPrices(1, 100)->create();
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@ use Blax\Shop\Models\ProductPrice;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class CartItemAttributesTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_has_is_booking_attribute_for_booking_products()
|
||||
{
|
||||
$bookingProduct = Product::factory()
|
||||
|
|
@ -29,7 +29,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertTrue($cartItem->is_booking);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_has_is_booking_false_for_regular_products()
|
||||
{
|
||||
$regularProduct = Product::factory()
|
||||
|
|
@ -42,7 +42,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertFalse($cartItem->is_booking);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_is_booking_works_via_price_id()
|
||||
{
|
||||
$bookingProduct = Product::factory()
|
||||
|
|
@ -60,7 +60,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertTrue($reloadedItem->is_booking);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_is_full_booking_is_true_when_all_items_are_bookings()
|
||||
{
|
||||
$booking1 = Product::factory()
|
||||
|
|
@ -78,7 +78,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertTrue($cart->is_full_booking);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_is_full_booking_is_false_when_mixed_products()
|
||||
{
|
||||
$booking = Product::factory()
|
||||
|
|
@ -96,7 +96,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertFalse($cart->is_full_booking);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_is_full_booking_is_false_when_empty()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -104,7 +104,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertFalse($cart->is_full_booking);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_booking_items_returns_correct_count()
|
||||
{
|
||||
$booking1 = Product::factory()
|
||||
|
|
@ -127,7 +127,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertEquals(2, $cart->bookingItems());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_booking_items_returns_zero_when_no_bookings()
|
||||
{
|
||||
$regular = Product::factory()
|
||||
|
|
@ -140,7 +140,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertEquals(0, $cart->bookingItems());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function price_id_is_automatically_assigned_when_adding_product_to_cart()
|
||||
{
|
||||
$product = Product::factory()
|
||||
|
|
@ -156,7 +156,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertInstanceOf(ProductPrice::class, $cartItem->price()->first());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function price_id_is_assigned_when_adding_product_price_to_cart()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -176,7 +176,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertInstanceOf(ProductPrice::class, $cartItem->price()->first());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_stripe_price_ids_returns_array_of_stripe_price_ids()
|
||||
{
|
||||
$product1 = Product::factory()->create();
|
||||
|
|
@ -208,7 +208,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertContains('price_456', $stripePriceIds);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_stripe_price_ids_returns_nulls_for_items_without_stripe_price_id()
|
||||
{
|
||||
$product1 = Product::factory()->create();
|
||||
|
|
@ -240,7 +240,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertNull($stripePriceIds[1]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_is_ready_to_checkout_is_true_for_regular_products()
|
||||
{
|
||||
$product = Product::factory()
|
||||
|
|
@ -253,7 +253,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertTrue($cartItem->is_ready_to_checkout);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_is_ready_to_checkout_is_false_for_booking_without_dates()
|
||||
{
|
||||
$bookingProduct = Product::factory()
|
||||
|
|
@ -266,7 +266,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertFalse($cartItem->is_ready_to_checkout);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_is_ready_to_checkout_is_true_for_booking_with_valid_dates()
|
||||
{
|
||||
$bookingProduct = Product::factory()
|
||||
|
|
@ -283,7 +283,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertTrue($cartItem->is_ready_to_checkout);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_is_ready_to_checkout_is_false_for_booking_with_invalid_date_range()
|
||||
{
|
||||
$bookingProduct = Product::factory()
|
||||
|
|
@ -303,7 +303,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertFalse($cartItem->fresh()->is_ready_to_checkout);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_is_ready_to_checkout_is_true_when_all_items_are_ready()
|
||||
{
|
||||
$product1 = Product::factory()
|
||||
|
|
@ -321,7 +321,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertTrue($cart->is_ready_to_checkout);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_is_ready_to_checkout_is_false_when_at_least_one_item_not_ready()
|
||||
{
|
||||
$regularProduct = Product::factory()
|
||||
|
|
@ -339,7 +339,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertFalse($cart->is_ready_to_checkout);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_allows_adding_items_without_dates_that_require_them()
|
||||
{
|
||||
$bookingProduct = Product::factory()
|
||||
|
|
@ -358,7 +358,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertFalse($cartItem->is_ready_to_checkout);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function update_dates_allows_setting_any_dates()
|
||||
{
|
||||
$bookingProduct = Product::factory()
|
||||
|
|
@ -382,7 +382,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertTrue($cartItem->fresh()->is_ready_to_checkout);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_calculates_correctly_when_dates_are_adjusted()
|
||||
{
|
||||
$bookingProduct = Product::factory()
|
||||
|
|
@ -409,7 +409,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertEquals(500.00, $cartItem->fresh()->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function set_from_date_recalculates_pricing_when_both_dates_set()
|
||||
{
|
||||
$bookingProduct = Product::factory()
|
||||
|
|
@ -434,7 +434,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertEquals(400.00, $cartItem->fresh()->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function set_until_date_recalculates_pricing_when_both_dates_set()
|
||||
{
|
||||
$bookingProduct = Product::factory()
|
||||
|
|
@ -459,7 +459,7 @@ class CartItemAttributesTest extends TestCase
|
|||
$this->assertEquals(400.00, $cartItem->fresh()->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function is_ready_to_checkout_checks_stock_for_regular_products_with_stock_management()
|
||||
{
|
||||
$product = Product::factory()
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ use Blax\Shop\Models\Cart;
|
|||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
/**
|
||||
* Tests for cart item validation when dates change and items become unavailable.
|
||||
|
|
@ -84,7 +84,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
return $pool;
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_with_null_price_is_not_ready_for_checkout()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -105,7 +105,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
$this->assertFalse($this->cart->fresh()->is_ready_to_checkout, 'Cart with null-price item should not be ready');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_with_zero_price_is_not_ready_for_checkout()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -126,7 +126,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
$this->assertFalse($this->cart->fresh()->is_ready_to_checkout, 'Cart with 0-price item should not be ready');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function unallocated_pool_item_with_null_price_is_not_ready_for_checkout()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -158,7 +158,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
$this->assertFalse($this->cart->fresh()->is_ready_to_checkout, 'Cart with unavailable item should not be ready');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function setDates_does_not_throw_when_items_become_unavailable()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -195,7 +195,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function partial_availability_marks_some_items_unavailable()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -244,7 +244,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
$this->assertFalse($this->cart->is_ready_to_checkout, 'Cart with unavailable items should not be ready');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_without_allocated_single_for_pool_is_not_ready()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -266,7 +266,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
$this->assertTrue($this->cart->fresh()->is_ready_to_checkout);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function removing_unavailable_items_makes_cart_ready()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -293,7 +293,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
$this->assertTrue($this->cart->fresh()->is_ready_to_checkout);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function getItemsRequiringAdjustments_includes_null_price_items()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -330,7 +330,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
$this->assertEquals('unavailable', $adjustments['price']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function changing_dates_to_available_period_makes_items_available_again()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -371,7 +371,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
$this->assertTrue($this->cart->is_ready_to_checkout, 'Cart should be ready after changing to available dates');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_throws_when_items_are_unavailable()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -388,7 +388,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
$this->cart->checkout();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkoutSessionLink_throws_when_items_have_null_price()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -408,7 +408,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
$this->cart->checkoutSessionLink();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkoutSessionLink_throws_when_items_have_zero_price()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -428,7 +428,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
$this->cart->checkoutSessionLink();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_items_maintain_consistent_pricing_after_date_changes()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
@ -460,7 +460,7 @@ class CartItemAvailabilityValidationTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function price_zero_is_treated_as_unavailable()
|
||||
{
|
||||
$pool = $this->createPoolWithLimitedSingles(3);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use Blax\Shop\Models\ProductPrice;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class CartItemDateManagementTest extends TestCase
|
||||
{
|
||||
|
|
@ -26,7 +27,7 @@ class CartItemDateManagementTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_update_dates_on_cart_item()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -60,7 +61,7 @@ class CartItemDateManagementTest extends TestCase
|
|||
$this->assertEquals(15000, $updated->subtotal); // 150.00 × 1 quantity
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_recalculates_price_when_updating_dates()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -94,7 +95,7 @@ class CartItemDateManagementTest extends TestCase
|
|||
$this->assertEquals(100000, $updated->subtotal); // 500 × 2 quantity
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_set_from_date_individually()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -120,7 +121,7 @@ class CartItemDateManagementTest extends TestCase
|
|||
$this->assertNull($updated->until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_set_until_date_individually()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -146,7 +147,7 @@ class CartItemDateManagementTest extends TestCase
|
|||
$this->assertEquals($until->format('Y-m-d H:i:s'), $updated->until->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_recalculates_when_both_dates_are_set()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -180,7 +181,7 @@ class CartItemDateManagementTest extends TestCase
|
|||
$this->assertEquals(32000, $updated->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_from_is_after_until()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -207,7 +208,7 @@ class CartItemDateManagementTest extends TestCase
|
|||
$cartItem->updateDates($from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_validates_dates_at_checkout_for_booking_products()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -233,7 +234,7 @@ class CartItemDateManagementTest extends TestCase
|
|||
$this->cart->checkout();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_allows_checkout_when_dates_are_set()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use Blax\Shop\Models\ProductPrice;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class CartItemRequiredAdjustmentsTest extends TestCase
|
||||
{
|
||||
|
|
@ -28,7 +29,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_empty_array_for_simple_product()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -51,7 +52,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
$this->assertEmpty($adjustments);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_from_and_until_for_booking_product_without_dates()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -78,7 +79,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
], $adjustments);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_only_until_for_booking_product_with_from_date()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -107,7 +108,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
], $adjustments);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_only_from_for_booking_product_with_until_date()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -136,7 +137,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
], $adjustments);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_empty_array_for_booking_product_with_both_dates()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -164,7 +165,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
$this->assertEmpty($adjustments);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_dates_for_pool_with_booking_single_items_without_dates()
|
||||
{
|
||||
// Create pool product
|
||||
|
|
@ -222,7 +223,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
], $adjustments);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_empty_array_for_pool_with_booking_items_with_dates()
|
||||
{
|
||||
// Create pool product
|
||||
|
|
@ -263,7 +264,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
$this->assertEmpty($adjustments);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_empty_array_for_pool_with_simple_single_items()
|
||||
{
|
||||
// Create pool product
|
||||
|
|
@ -318,7 +319,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
$this->assertEmpty($adjustments);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_dates_for_pool_with_mixed_single_items_containing_bookings()
|
||||
{
|
||||
// Create pool product
|
||||
|
|
@ -378,7 +379,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
], $adjustments);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_empty_array_for_non_product_purchasable()
|
||||
{
|
||||
// Create a cart item with a non-product purchasable
|
||||
|
|
@ -396,7 +397,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
$this->assertEmpty($adjustments);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_null_purchasable_gracefully()
|
||||
{
|
||||
// Create a cart item with invalid purchasable_id
|
||||
|
|
@ -414,7 +415,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
$this->assertEmpty($adjustments);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_validate_entire_cart_before_checkout()
|
||||
{
|
||||
// Create mixed cart with booking and simple products
|
||||
|
|
@ -456,7 +457,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
$this->assertEquals($bookingProduct->id, $itemsNeedingAdjustments->first()->purchasable_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_can_get_items_requiring_adjustments()
|
||||
{
|
||||
$simpleProduct = Product::factory()->create([
|
||||
|
|
@ -492,7 +493,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
$this->assertEquals($bookingProduct->id, $incompleteItems->first()->purchasable_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_is_not_ready_for_checkout_when_items_need_adjustments()
|
||||
{
|
||||
$bookingProduct = Product::factory()->create([
|
||||
|
|
@ -512,7 +513,7 @@ class CartItemRequiredAdjustmentsTest extends TestCase
|
|||
$this->assertFalse($this->cart->isReadyForCheckout());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_is_ready_for_checkout_when_all_items_complete()
|
||||
{
|
||||
$simpleProduct = Product::factory()->create([
|
||||
|
|
|
|||
|
|
@ -5,16 +5,16 @@ namespace Blax\Shop\Tests\Feature;
|
|||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\CartItem;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class CartManagementTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_a_cart()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -33,7 +33,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertNotNull($cart->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_automatically_generates_uuid()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -42,7 +42,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertIsString($cart->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_add_items_to_cart()
|
||||
{
|
||||
$product = Product::factory()->withPrices()->create();
|
||||
|
|
@ -56,7 +56,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals(2, $cart->items->first()->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_update_cart_item_quantity()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -69,7 +69,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals(3, $cartItem->fresh()->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_remove_items_from_cart()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -85,7 +85,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertCount(0, $cart->refresh()->items);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_cart_total_correctly()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -103,7 +103,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals(130.00, $total); // (50 * 2) + (30 * 1)
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_total_items_correctly()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -121,7 +121,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals(5, $totalItems); // 3 + 2
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_if_cart_is_expired()
|
||||
{
|
||||
$expiredCart = Cart::create([
|
||||
|
|
@ -136,7 +136,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertFalse($activeCart->isExpired());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_if_cart_is_converted()
|
||||
{
|
||||
$convertedCart = Cart::create([
|
||||
|
|
@ -151,7 +151,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertFalse($activeCart->isConverted());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_active_carts()
|
||||
{
|
||||
Cart::create([
|
||||
|
|
@ -174,7 +174,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertCount(1, $activeCarts);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_carts_for_user()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -189,7 +189,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertCount(2, $userCarts);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_belongs_to_a_user()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -198,7 +198,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals($user->id, $cart->user->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_items_have_correct_relationships()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -211,7 +211,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals($productPrice->id, $cartItem->purchasable_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_cart_item_subtotal()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -223,7 +223,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals(100.00, $cartItem->getSubtotal()); // 25 * 4
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_store_cart_item_attributes()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -243,7 +243,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals('large', $cartItem->parameters['size']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_multiple_items_of_same_product_with_different_attributes()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -266,7 +266,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals($productPrice->unit_amount * 3, $cart->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_deletes_cart_items_when_cart_is_deleted()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -285,7 +285,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertDatabaseMissing('cart_items', ['id' => $cartItemId]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculats_unpaid_and_paid_and_can_scope()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -304,7 +304,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals($user->currentCart()->id, Cart::unpaid()->first()->id, 'Unpaid cart scope should return the current cart.');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_cart_with_factory()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
@ -336,7 +336,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals((150.00 * 2) + (120 * 2), $cartWithProduct->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_remove_entire_cart_item()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -352,7 +352,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertTrue(true); // Item was deleted
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_decrease_cart_item_quantity()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -369,7 +369,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals(75.00 * 3, $updatedItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_updates_subtotal_correctly_when_decreasing_quantity()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -385,7 +385,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals(300.00, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_respects_parameters_when_removing_from_cart()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -415,7 +415,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals(3, $cart->items->first()->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_decreases_only_matching_parameters_when_removing()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -435,7 +435,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals('large', $cartItem->parameters['size']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_cart_item_when_quantity_is_decreased()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -450,7 +450,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals(3, $result->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_removing_nonexistent_item_gracefully()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -464,7 +464,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertCount(0, $cart->items);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_updates_cart_total_after_removing_items()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -479,7 +479,7 @@ class CartManagementTest extends TestCase
|
|||
$this->assertEquals(150.00, $cart->refresh()->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_remove_from_cart_with_multiple_items()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use Blax\Shop\Tests\TestCase;
|
|||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class CartServiceBookingTest extends TestCase
|
||||
{
|
||||
|
|
@ -84,7 +85,7 @@ class CartServiceBookingTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_bookings_returns_error_for_booking_product_without_timespan()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -104,7 +105,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertStringContainsString('Hotel Room', $errors[0]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_bookings_returns_error_for_pool_product_without_timespan_when_single_items_are_bookings()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -124,7 +125,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertStringContainsString('Parking Spaces', $errors[0]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_bookings_validates_stock_availability_correctly()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -150,7 +151,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertStringContainsString('not available for the selected period', $errors[0]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_bookings_handles_pool_products_with_individual_timespans_in_meta()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -170,7 +171,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertEmpty($errors);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function has_valid_bookings_returns_true_when_all_bookings_are_valid()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -189,7 +190,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertTrue(Cart::hasValidBookings());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function has_valid_bookings_returns_false_when_bookings_are_invalid()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -205,7 +206,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertFalse(Cart::hasValidBookings());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function add_booking_successfully_adds_booking_product_with_timespan()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -220,7 +221,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertEquals($until->format('Y-m-d H:i:s'), $cartItem->until->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function add_booking_successfully_adds_pool_product_with_timespan()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -235,7 +236,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertEquals($until->format('Y-m-d H:i:s'), $cartItem->until->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function add_booking_calculates_price_correctly_based_on_days()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -253,7 +254,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertEquals($expectedTotal, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function add_booking_throws_exception_when_product_is_not_booking_or_pool_type()
|
||||
{
|
||||
$simpleProduct = Product::factory()->create([
|
||||
|
|
@ -277,7 +278,7 @@ class CartServiceBookingTest extends TestCase
|
|||
Cart::addBooking($simpleProduct, 1, $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function add_booking_throws_exception_when_insufficient_stock_available_for_booking_period()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -292,7 +293,7 @@ class CartServiceBookingTest extends TestCase
|
|||
Cart::addBooking($this->bookingProduct, 5, $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function add_booking_throws_exception_when_pool_quantity_exceeds_available_single_items()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -305,7 +306,7 @@ class CartServiceBookingTest extends TestCase
|
|||
Cart::addBooking($this->poolProduct, 5, $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function add_booking_creates_cart_item_with_correct_from_until_timestamps()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(14, 30, 0);
|
||||
|
|
@ -317,7 +318,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertEquals($until->format('Y-m-d H:i:s'), $cartItem->until->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function add_booking_stores_regular_price_correctly()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -329,7 +330,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertEquals($this->bookingProduct->getCurrentPrice(), $cartItem->regular_price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_bookings_returns_error_when_pool_quantity_exceeds_available_single_items()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -354,7 +355,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertStringContainsString('Parking Spaces', $errors[0]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_bookings_passes_with_valid_pool_product_and_timespan()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -375,7 +376,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertEmpty($errors);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_bookings_handles_multiple_booking_products_in_cart()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -407,7 +408,7 @@ class CartServiceBookingTest extends TestCase
|
|||
$this->assertEmpty($errors);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function add_booking_with_parameters_stores_them_correctly()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
|
|||
|
|
@ -3,15 +3,14 @@
|
|||
namespace Blax\Shop\Tests\Feature;
|
||||
|
||||
use Blax\Shop\Enums\ProductType;
|
||||
use Blax\Shop\Enums\PurchaseStatus;
|
||||
use Blax\Shop\Exceptions\NotEnoughStockException;
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Models\ProductPurchase;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
/**
|
||||
* Test stock validation during checkout process.
|
||||
|
|
@ -89,7 +88,7 @@ class CheckoutStockValidationTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_for_checkout_checks_stock_availability()
|
||||
{
|
||||
$this->createPoolWithManagedStock();
|
||||
|
|
@ -113,7 +112,7 @@ class CheckoutStockValidationTest extends TestCase
|
|||
$this->assertFalse($this->cart->fresh()->validateForCheckout(false));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_for_checkout_fails_for_out_of_stock_items()
|
||||
{
|
||||
$this->createPoolWithManagedStock();
|
||||
|
|
@ -134,7 +133,7 @@ class CheckoutStockValidationTest extends TestCase
|
|||
$this->assertFalse($this->cart->validateForCheckout(false));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_for_checkout_fails_for_converted_cart()
|
||||
{
|
||||
$this->createPoolWithManagedStock();
|
||||
|
|
@ -152,7 +151,7 @@ class CheckoutStockValidationTest extends TestCase
|
|||
$this->assertFalse($this->cart->fresh()->validateForCheckout(false));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_session_link_returns_null_for_converted_cart()
|
||||
{
|
||||
$this->createPoolWithManagedStock();
|
||||
|
|
@ -170,7 +169,7 @@ class CheckoutStockValidationTest extends TestCase
|
|||
$this->assertFalse($this->cart->fresh()->validateForCheckout(false));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_session_link_returns_null_for_out_of_stock()
|
||||
{
|
||||
$this->createPoolWithManagedStock();
|
||||
|
|
@ -190,7 +189,7 @@ class CheckoutStockValidationTest extends TestCase
|
|||
$this->assertFalse($this->cart->fresh()->validateForCheckout(false));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function different_date_ranges_allow_booking_same_items()
|
||||
{
|
||||
$this->createPoolWithManagedStock();
|
||||
|
|
@ -215,7 +214,7 @@ class CheckoutStockValidationTest extends TestCase
|
|||
$this->assertTrue($cart2->validateForCheckout(false));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function overlapping_dates_block_double_booking()
|
||||
{
|
||||
$this->createPoolWithManagedStock();
|
||||
|
|
@ -245,7 +244,7 @@ class CheckoutStockValidationTest extends TestCase
|
|||
$cart2->addToCart($this->pool, 1, [], $from2, $until2);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function partial_stock_allows_partial_booking()
|
||||
{
|
||||
$this->createPoolWithManagedStock();
|
||||
|
|
|
|||
|
|
@ -3,17 +3,16 @@
|
|||
namespace Blax\Shop\Tests\Feature;
|
||||
|
||||
use Blax\Shop\Console\Commands\ShopAddExampleProducts;
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class CommandProductExamplesTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_creates_example_products_and_related_data(): void
|
||||
{
|
||||
$this->artisan(ShopAddExampleProducts::class, ['--clean' => true, '--count' => 2])
|
||||
|
|
@ -42,7 +41,7 @@ class CommandProductExamplesTest extends TestCase
|
|||
$this->assertNotEmpty(Product::first()->getLocalized('name'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_cleans_existing_examples_when_option_provided(): void
|
||||
{
|
||||
// Seed examples
|
||||
|
|
@ -57,7 +56,7 @@ class CommandProductExamplesTest extends TestCase
|
|||
$this->assertEquals(6, \Blax\Shop\Models\ProductCategory::where('slug', 'like', 'example-%')->count());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_honors_the_count_option_for_each_type(): void
|
||||
{
|
||||
$this->artisan(ShopAddExampleProducts::class, ['--clean' => true, '--count' => 3])
|
||||
|
|
|
|||
|
|
@ -8,12 +8,13 @@ use Blax\Shop\Models\Cart as CartModel;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class GuestCartTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_a_guest_cart()
|
||||
{
|
||||
$guestCart = Cart::guest();
|
||||
|
|
@ -24,7 +25,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertNull($guestCart->customer_type);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_a_guest_cart_with_specific_session_id()
|
||||
{
|
||||
$sessionId = 'test-session-123';
|
||||
|
|
@ -35,7 +36,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertNull($guestCart->customer_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_retrieves_same_guest_cart_for_same_session()
|
||||
{
|
||||
$sessionId = 'persistent-session-456';
|
||||
|
|
@ -55,7 +56,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertCount(1, $cart2->items);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_add_items_to_guest_cart()
|
||||
{
|
||||
$guestCart = Cart::guest('guest-session');
|
||||
|
|
@ -67,7 +68,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertEquals(2, $cartItem->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_guest_cart_total()
|
||||
{
|
||||
$guestCart = Cart::guest('guest-session-2');
|
||||
|
|
@ -82,7 +83,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertEquals(250.00, $total);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_guest_cart_item_count()
|
||||
{
|
||||
$guestCart = Cart::guest('guest-session-3');
|
||||
|
|
@ -95,7 +96,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertEquals(5, $count);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_remove_items_from_guest_cart()
|
||||
{
|
||||
$guestCart = Cart::guest('guest-session-4');
|
||||
|
|
@ -110,7 +111,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertEquals(3, $items[0]->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_clear_guest_cart()
|
||||
{
|
||||
$guestCart = Cart::guest('guest-session-5');
|
||||
|
|
@ -126,7 +127,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertTrue(Cart::isEmpty($guestCart));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_if_guest_cart_is_empty()
|
||||
{
|
||||
$guestCart = Cart::guest('guest-session-6');
|
||||
|
|
@ -140,7 +141,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertFalse(Cart::isEmpty($guestCart));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_find_guest_cart_by_id()
|
||||
{
|
||||
$guestCart = Cart::guest('guest-session-7');
|
||||
|
|
@ -152,7 +153,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertEquals($cartId, $foundCart->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function guest_and_authenticated_carts_are_separate()
|
||||
{
|
||||
// Create guest cart
|
||||
|
|
@ -177,7 +178,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertNotEquals($guestCart->id, Cart::current()->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_convert_guest_cart_to_user_cart()
|
||||
{
|
||||
// Guest adds items
|
||||
|
|
@ -198,7 +199,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertEquals(200.00, Cart::total($userCart));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_true_for_empty_guest_cart_after_clear()
|
||||
{
|
||||
$guestCart = Cart::guest('guest-session-10');
|
||||
|
|
@ -210,7 +211,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertTrue(Cart::isEmpty($guestCart));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function multiple_guests_have_separate_carts()
|
||||
{
|
||||
$sessionId1 = 'guest-session-11';
|
||||
|
|
@ -229,7 +230,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertEquals(300.00, Cart::total($guestCart2));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_update_items_in_guest_cart()
|
||||
{
|
||||
$guestCart = Cart::guest('guest-session-13');
|
||||
|
|
@ -244,7 +245,7 @@ class GuestCartTest extends TestCase
|
|||
$this->assertEquals(250.00, $updated->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function guest_cart_expires_based_on_configuration()
|
||||
{
|
||||
$guestCart = Cart::guest('guest-session-14');
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@ use Blax\Shop\Models\Product;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class HasShoppingCapabilitiesTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_has_cart_relationship()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -22,7 +23,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertInstanceOf(\Illuminate\Database\Eloquent\Relations\MorphMany::class, $user->cart());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_has_purchases_relationship()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -30,7 +31,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertInstanceOf(\Illuminate\Database\Eloquent\Relations\MorphMany::class, $user->purchases());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_get_current_cart()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -41,7 +42,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertEquals($user->id, $cart->customer_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_cannot_purchase_product_without_price()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -52,7 +53,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$user->purchase($product);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_cannot_purchase_product_with_multiple_default_prices()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -68,7 +69,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$user->purchase($product);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_purchase_product_with_single_default_price()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -84,7 +85,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertEquals($user->id, $purchase->purchaser_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_cannot_add_product_to_cart_without_default_price()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -93,7 +94,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertThrows(fn() => $user->addToCart($product), NotPurchasable::class);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_cannot_add_product_with_multiple_default_prices_to_cart()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -108,7 +109,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$user->addToCart($product);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_get_completed_purchases()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -127,7 +128,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertEquals(PurchaseStatus::COMPLETED, $completed->first()->status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function purchase_with_metadata_stores_correctly()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -144,7 +145,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertEquals('Special instructions', $purchase->meta->notes);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_check_if_purchased_specific_product()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -158,7 +159,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertFalse($user->hasPurchased($notPurchasedProduct));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_cart_items_are_accessible()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -169,7 +170,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertCount(1, $user->cartItems);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_update_cart_item_quantity()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -182,7 +183,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertEquals(5, $cartItem->fresh()->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_remove_item_from_cart()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -197,7 +198,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertCount(0, $user->fresh()->cartItems);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_get_cart_total()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -212,7 +213,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertEquals(250.00, $total);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_get_cart_items_count()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -227,7 +228,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertEquals(5, $count);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_clear_cart()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -244,7 +245,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertCount(0, $user->fresh()->cartItems);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adding_product_to_cart_reserves_stock()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -257,7 +258,7 @@ class HasShoppingCapabilitiesTest extends TestCase
|
|||
$this->assertEquals(7, $product->fresh()->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function purchase_calls_product_actions()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ use Blax\Shop\Models\PaymentMethod;
|
|||
use Blax\Shop\Models\PaymentProviderIdentity;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Support\Carbon;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PaymentMethodFieldsTest extends TestCase
|
||||
{
|
||||
#[Test]
|
||||
public function test_can_store_last_alphanumeric(): void
|
||||
{
|
||||
$identity = PaymentProviderIdentity::factory()->stripe()->create();
|
||||
|
|
@ -25,6 +27,7 @@ class PaymentMethodFieldsTest extends TestCase
|
|||
$this->assertSame('abc123xyz', $method->last_alphanumeric);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function test_expiration_via_expires_at(): void
|
||||
{
|
||||
$identity = PaymentProviderIdentity::factory()->stripe()->create();
|
||||
|
|
@ -53,6 +56,7 @@ class PaymentMethodFieldsTest extends TestCase
|
|||
$this->assertFalse($active->isExpired());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function test_expiration_via_month_year(): void
|
||||
{
|
||||
$identity = PaymentProviderIdentity::factory()->stripe()->create();
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use Blax\Shop\Tests\TestCase;
|
|||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Mockery;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PaymentProviderTest extends TestCase
|
||||
{
|
||||
|
|
@ -32,7 +33,7 @@ class PaymentProviderTest extends TestCase
|
|||
|
||||
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_a_customer_on_stripe()
|
||||
{
|
||||
$user = User::factory()->create([
|
||||
|
|
@ -72,7 +73,7 @@ class PaymentProviderTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_existing_customer_identity_if_already_exists()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -93,7 +94,7 @@ class PaymentProviderTest extends TestCase
|
|||
$this->assertEquals('cus_existing123', $identity->customer_identification_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_add_a_payment_method()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -152,7 +153,7 @@ class PaymentProviderTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function first_payment_method_is_automatically_set_as_default()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -195,7 +196,7 @@ class PaymentProviderTest extends TestCase
|
|||
$this->assertTrue($paymentMethod->fresh()->is_default);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_list_payment_methods()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -231,7 +232,7 @@ class PaymentProviderTest extends TestCase
|
|||
$this->assertCount(3, $allMethods);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_set_a_payment_method_as_default()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -270,7 +271,7 @@ class PaymentProviderTest extends TestCase
|
|||
$this->assertEquals(1, $defaultCount);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_remove_a_payment_method()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -300,7 +301,7 @@ class PaymentProviderTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function removing_default_payment_method_sets_another_as_default()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -339,7 +340,7 @@ class PaymentProviderTest extends TestCase
|
|||
$this->assertTrue($method2->fresh()->is_default);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_use_trait_to_add_payment_methods()
|
||||
{
|
||||
// Use actual User model since it doesn't have the trait yet - test with direct service calls
|
||||
|
|
@ -404,7 +405,7 @@ class PaymentProviderTest extends TestCase
|
|||
$this->assertEquals($paymentMethod->id, $defaultMethod->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_sync_payment_methods_from_stripe()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -475,7 +476,7 @@ class PaymentProviderTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function payment_method_can_check_if_expired()
|
||||
{
|
||||
$paymentMethod = PaymentMethod::factory()->create([
|
||||
|
|
@ -493,7 +494,7 @@ class PaymentProviderTest extends TestCase
|
|||
$this->assertFalse($validMethod->isExpired());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function payment_method_has_display_name_attribute()
|
||||
{
|
||||
$method1 = PaymentMethod::factory()->create([
|
||||
|
|
@ -513,7 +514,7 @@ class PaymentProviderTest extends TestCase
|
|||
$this->assertEquals('Mastercard ending in 5555', $method2->display_name);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function payment_method_has_formatted_expiration()
|
||||
{
|
||||
$paymentMethod = PaymentMethod::factory()->create([
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use Blax\Shop\Enums\ProductType;
|
|||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PoolAvailabilityMethodsTest extends TestCase
|
||||
{
|
||||
|
|
@ -48,7 +49,7 @@ class PoolAvailabilityMethodsTest extends TestCase
|
|||
$this->pool->attachSingleItems([$this->spot1->id, $this->spot2->id, $this->spot3->id]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_gets_pool_availability_calendar()
|
||||
{
|
||||
$start = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -66,7 +67,7 @@ class PoolAvailabilityMethodsTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_shows_correct_availability_per_day()
|
||||
{
|
||||
$start = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -79,7 +80,7 @@ class PoolAvailabilityMethodsTest extends TestCase
|
|||
$this->assertEquals(6, $calendar[$dateStr]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_reduces_availability_when_items_are_claimed()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -95,7 +96,7 @@ class PoolAvailabilityMethodsTest extends TestCase
|
|||
$this->assertEquals(4, $calendar[$dateStr]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_gets_single_items_availability_without_dates()
|
||||
{
|
||||
$availability = $this->pool->getSingleItemsAvailability();
|
||||
|
|
@ -113,7 +114,7 @@ class PoolAvailabilityMethodsTest extends TestCase
|
|||
$this->assertEquals(1, $availability[2]['available']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_gets_single_items_availability_with_dates()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -130,7 +131,7 @@ class PoolAvailabilityMethodsTest extends TestCase
|
|||
$this->assertEquals(1, $availability[2]['available']); // Spot 3: still 1
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_shows_unlimited_for_items_without_stock_management()
|
||||
{
|
||||
$unlimitedSpot = Product::factory()->create([
|
||||
|
|
@ -148,7 +149,7 @@ class PoolAvailabilityMethodsTest extends TestCase
|
|||
$this->assertFalse($unlimited['manage_stock']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_checks_if_pool_is_available_for_period()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -160,7 +161,7 @@ class PoolAvailabilityMethodsTest extends TestCase
|
|||
$this->assertFalse($this->pool->isPoolAvailable($from, $until, 7));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_false_when_pool_not_available()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -174,7 +175,7 @@ class PoolAvailabilityMethodsTest extends TestCase
|
|||
$this->assertFalse($this->pool->isPoolAvailable($from, $until, 1));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_gets_available_periods_for_pool()
|
||||
{
|
||||
$start = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -200,7 +201,7 @@ class PoolAvailabilityMethodsTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_filters_periods_by_minimum_consecutive_days()
|
||||
{
|
||||
$start = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -234,7 +235,7 @@ class PoolAvailabilityMethodsTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_higher_quantity_requirements_in_available_periods()
|
||||
{
|
||||
$start = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -263,7 +264,7 @@ class PoolAvailabilityMethodsTest extends TestCase
|
|||
$this->assertNotEquals($periodsBefore, $periodsAfter);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_for_non_pool_products()
|
||||
{
|
||||
$regularProduct = Product::factory()->create([
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use Blax\Shop\Models\ProductPrice;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PoolBookingDetectionTest extends TestCase
|
||||
{
|
||||
|
|
@ -23,7 +24,7 @@ class PoolBookingDetectionTest extends TestCase
|
|||
$this->user = User::factory()->create();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_with_booking_items_is_detected_as_booking()
|
||||
{
|
||||
// Create pool
|
||||
|
|
@ -61,7 +62,7 @@ class PoolBookingDetectionTest extends TestCase
|
|||
$this->assertTrue($pool->hasBookingSingleItems(), 'Pool should have booking single items');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_without_booking_items_is_not_booking()
|
||||
{
|
||||
// Create pool
|
||||
|
|
@ -99,7 +100,7 @@ class PoolBookingDetectionTest extends TestCase
|
|||
$this->assertFalse($pool->hasBookingSingleItems(), 'Pool should not have booking single items');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_cart_item_with_booking_items_is_detected_as_booking()
|
||||
{
|
||||
// Create pool
|
||||
|
|
@ -151,7 +152,7 @@ class PoolBookingDetectionTest extends TestCase
|
|||
$this->assertTrue($cartItem->is_booking, 'Cart item for pool with booking items should be detected as booking');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_cart_item_without_booking_items_is_not_booking()
|
||||
{
|
||||
// Create pool
|
||||
|
|
@ -203,7 +204,7 @@ class PoolBookingDetectionTest extends TestCase
|
|||
$this->assertFalse($cartItem->is_booking, 'Cart item for pool without booking items should not be detected as booking');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_with_pool_booking_items_detects_booking_correctly()
|
||||
{
|
||||
// Create pool with booking items
|
||||
|
|
@ -253,7 +254,7 @@ class PoolBookingDetectionTest extends TestCase
|
|||
$this->assertEquals(1, $cart->bookingItems(), 'Cart should have 1 booking item');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function mixed_cart_with_pool_and_regular_items_not_full_booking()
|
||||
{
|
||||
// Create pool with booking items
|
||||
|
|
@ -327,7 +328,7 @@ class PoolBookingDetectionTest extends TestCase
|
|||
$this->assertEquals(1, $cart->bookingItems(), 'Cart should have 1 booking item');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_isBooking_method_works()
|
||||
{
|
||||
// Create pool with booking items
|
||||
|
|
@ -377,7 +378,7 @@ class PoolBookingDetectionTest extends TestCase
|
|||
$this->assertEquals($cartItem->is_booking, $cartItem->isBooking(), 'isBooking() should match is_booking attribute');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_isBooking_method_works()
|
||||
{
|
||||
// Create pool with booking items
|
||||
|
|
|
|||
|
|
@ -10,10 +10,11 @@ use Blax\Shop\Models\Product;
|
|||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PoolClaimingPriorityTest extends TestCase
|
||||
{
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_claims_lowest_priced_items_first_with_lowest_strategy()
|
||||
{
|
||||
// Create pool product
|
||||
|
|
@ -99,7 +100,7 @@ class PoolClaimingPriorityTest extends TestCase
|
|||
$this->assertEquals($spot2->id, $claimedIds[2]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_claims_highest_priced_items_first_with_highest_strategy()
|
||||
{
|
||||
// Create pool product
|
||||
|
|
@ -167,7 +168,7 @@ class PoolClaimingPriorityTest extends TestCase
|
|||
$this->assertEquals($cheapSpot->id, $claimedItems[1]->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_uses_fallback_price_for_items_without_price()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ use Blax\Shop\Models\Cart;
|
|||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
/**
|
||||
* Tests to ensure pool products cannot exceed available single items
|
||||
|
|
@ -75,7 +75,7 @@ class PoolMaxQuantityValidationTest extends TestCase
|
|||
return $pool;
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cannot_add_more_items_than_available_singles_without_dates()
|
||||
{
|
||||
$pool = $this->createPoolWith7Singles();
|
||||
|
|
@ -94,7 +94,7 @@ class PoolMaxQuantityValidationTest extends TestCase
|
|||
$this->cart->addToCart($pool, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cannot_add_more_items_than_available_singles_with_dates()
|
||||
{
|
||||
$pool = $this->createPoolWith7Singles();
|
||||
|
|
@ -116,7 +116,7 @@ class PoolMaxQuantityValidationTest extends TestCase
|
|||
$this->cart->addToCart($pool, 1, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cannot_add_batch_exceeding_available_singles_without_dates()
|
||||
{
|
||||
$pool = $this->createPoolWith7Singles();
|
||||
|
|
@ -128,7 +128,7 @@ class PoolMaxQuantityValidationTest extends TestCase
|
|||
$this->cart->addToCart($pool, 8);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cannot_add_batch_exceeding_available_singles_with_dates()
|
||||
{
|
||||
$pool = $this->createPoolWith7Singles();
|
||||
|
|
@ -143,7 +143,7 @@ class PoolMaxQuantityValidationTest extends TestCase
|
|||
$this->cart->addToCart($pool, 8, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adding_items_without_dates_then_adding_more_validates_correctly()
|
||||
{
|
||||
$pool = $this->createPoolWith7Singles();
|
||||
|
|
@ -161,7 +161,7 @@ class PoolMaxQuantityValidationTest extends TestCase
|
|||
$this->cart->addToCart($pool, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkoutSessionLink_throws_exception_when_cart_invalid()
|
||||
{
|
||||
$pool = $this->createPoolWith7Singles();
|
||||
|
|
@ -177,7 +177,7 @@ class PoolMaxQuantityValidationTest extends TestCase
|
|||
$this->cart->checkoutSessionLink();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkoutSessionLink_throws_exception_when_not_enough_stock()
|
||||
{
|
||||
$pool = $this->createPoolWith7Singles();
|
||||
|
|
@ -204,7 +204,7 @@ class PoolMaxQuantityValidationTest extends TestCase
|
|||
$this->cart->fresh()->checkoutSessionLink();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_aware_validation_accounts_for_items_already_in_cart()
|
||||
{
|
||||
$pool = $this->createPoolWith7Singles();
|
||||
|
|
@ -229,7 +229,7 @@ class PoolMaxQuantityValidationTest extends TestCase
|
|||
$this->cart->addToCart($pool, 1, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validation_message_shows_correct_remaining_availability()
|
||||
{
|
||||
$pool = $this->createPoolWith7Singles();
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
namespace Blax\Shop\Tests\Feature;
|
||||
|
||||
use Blax\Shop\Enums\ProductRelationType;
|
||||
use Blax\Shop\Enums\ProductType;
|
||||
use Blax\Shop\Enums\PricingStrategy;
|
||||
use Blax\Shop\Exceptions\NotEnoughStockException;
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\Product;
|
||||
|
|
@ -12,6 +10,7 @@ use Blax\Shop\Models\ProductPrice;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
/**
|
||||
* Test pool product cart pricing with comprehensive scenarios.
|
||||
|
|
@ -148,7 +147,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
// Configuration A: Pool HAS price, does NOT manage stock
|
||||
// ==========================================
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_a_progressive_pricing_step_by_step()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -188,7 +187,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->cart->addToCart($pool, 1, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_a_cart_items_have_correct_price_ids()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -220,7 +219,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals($spot3PriceId, $item1000->price_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_a_set_dates_doubles_cart_total()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -236,7 +235,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals(7200, $this->cart->fresh()->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_a_set_dates_after_adding_recalculates_prices()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -258,7 +257,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals(7200, $this->cart->fresh()->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_a_set_from_date_and_until_date_separately()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -285,7 +284,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals(7200, $this->cart->fresh()->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_a_set_dates_overwrites_cart_item_dates()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -314,7 +313,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_a_marks_items_unavailable_when_setting_dates_to_unavailable_period()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -347,7 +346,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
// Configuration B: Pool does NOT have price, does NOT manage stock
|
||||
// ==========================================
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_b_progressive_pricing_step_by_step()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -380,7 +379,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->cart->addToCart($pool, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_b_cart_items_have_correct_price_ids()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -406,7 +405,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals($spot3PriceId, $item1000->price_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_b_set_dates_doubles_cart_total()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -422,7 +421,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals(5200, $this->cart->fresh()->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_b_set_dates_after_adding_recalculates_prices()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -448,7 +447,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
// Configuration C: Pool HAS price, MANAGES stock
|
||||
// ==========================================
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_c_progressive_pricing_step_by_step()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -488,7 +487,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->cart->addToCart($pool, 1, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_c_cart_items_have_correct_price_ids()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -520,7 +519,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals($spot3PriceId, $item1000->price_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_c_set_dates_doubles_cart_total()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -536,7 +535,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals(7200, $this->cart->fresh()->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_c_set_dates_after_adding_recalculates_prices()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -558,7 +557,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals(7200, $this->cart->fresh()->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_c_pool_stock_is_ignored_when_single_items_manage_stock()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -573,7 +572,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
// Configuration D: Pool does NOT have price, MANAGES stock
|
||||
// ==========================================
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_d_progressive_pricing_step_by_step()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -603,7 +602,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->cart->addToCart($pool, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_d_cart_items_have_correct_price_ids()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -629,7 +628,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals($spot3PriceId, $item1000->price_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_d_set_dates_doubles_cart_total()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -645,7 +644,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals(5200, $this->cart->fresh()->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function config_d_set_dates_after_adding_recalculates_prices()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -671,7 +670,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
// Additional tests for date management
|
||||
// ==========================================
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function set_dates_marks_items_unavailable_when_all_claimed()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -704,7 +703,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertFalse($this->cart->is_ready_to_checkout, 'Cart should not be ready');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_subtotal_updates_when_dates_change()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -727,7 +726,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals(1800, $item->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_total_and_item_subtotals_match()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -746,7 +745,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals(7200, $this->cart->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function removing_items_updates_pool_availability()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -764,7 +763,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->assertEquals(3600, $this->cart->fresh()->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adding_quantity_greater_than_one_respects_availability()
|
||||
{
|
||||
$this->cart = $this->createCart();
|
||||
|
|
@ -778,7 +777,7 @@ class PoolParkingCartPricingTest extends TestCase
|
|||
$this->cart->addToCart($pool, 7, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_with_all_single_items_without_prices_throws_exception()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use Blax\Shop\Tests\TestCase;
|
|||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PoolPerMinutePricingTest extends TestCase
|
||||
{
|
||||
|
|
@ -81,7 +82,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->poolProduct->setPricingStrategy(PricingStrategy::LOWEST);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_pool_price_for_12_hours()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(8, 0, 0);
|
||||
|
|
@ -94,7 +95,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(1500, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_pool_price_for_36_hours()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(9, 0, 0);
|
||||
|
|
@ -107,7 +108,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(4500, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_pool_price_for_6_hours()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(10, 0, 0);
|
||||
|
|
@ -120,7 +121,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(750, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_pool_price_for_90_minutes()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(14, 0, 0);
|
||||
|
|
@ -132,7 +133,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(188, round($cartItem->price, 2));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_uses_direct_pool_price_for_fractional_days()
|
||||
{
|
||||
// Set direct price on pool - this is now used as fallback for single items without prices
|
||||
|
|
@ -158,7 +159,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(1500, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_pool_price_with_quantity_for_fractional_days()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(9, 0, 0);
|
||||
|
|
@ -172,7 +173,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(1500, $cartItem->subtotal); // total for 2 units
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_uses_highest_pricing_strategy_for_fractional_days()
|
||||
{
|
||||
// Change to HIGHEST pricing strategy
|
||||
|
|
@ -188,7 +189,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(2500, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_uses_average_pricing_strategy_for_fractional_days()
|
||||
{
|
||||
// Change to AVERAGE pricing strategy
|
||||
|
|
@ -204,7 +205,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(2000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_pool_price_for_multiple_fractional_bookings_in_cart()
|
||||
{
|
||||
$from1 = Carbon::now()->addDays(10)->setTime(10, 0, 0);
|
||||
|
|
@ -231,7 +232,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(1500, $cart->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_pool_price_for_very_short_durations()
|
||||
{
|
||||
// 30 minutes
|
||||
|
|
@ -253,7 +254,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(31, $cartItem2->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_multiple_pool_bookings_with_different_durations()
|
||||
{
|
||||
$cart = \Blax\Shop\Models\Cart::factory()->create([
|
||||
|
|
@ -278,7 +279,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(750, $item2->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_pool_price_for_3_hours()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(14, 0, 0);
|
||||
|
|
@ -290,7 +291,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(375, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_pool_price_for_odd_duration_5_hours_30_minutes()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(9, 30, 0);
|
||||
|
|
@ -303,7 +304,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals($expectedPrice, round($cartItem->price));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_pool_booking_over_multiple_days_with_hours()
|
||||
{
|
||||
// Monday 2pm to Wednesday 5pm = 51 hours = 2.125 days
|
||||
|
|
@ -317,7 +318,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals($expectedPrice, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_prices_pool_correctly_when_both_spots_have_different_prices_for_fractional_time()
|
||||
{
|
||||
// Create a third spot with an even different price
|
||||
|
|
@ -349,7 +350,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(750, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_exact_24_hours_pool()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(9, 0, 0);
|
||||
|
|
@ -362,7 +363,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(3000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_updates_pool_cart_item_from_date_recalculates_per_minute_price()
|
||||
{
|
||||
$now = Carbon::now();
|
||||
|
|
@ -386,7 +387,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(3750, $cartItem->fresh()->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_booking_spanning_exactly_two_days()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5)->setTime(0, 0, 0);
|
||||
|
|
@ -399,7 +400,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(6000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_for_business_hours_booking()
|
||||
{
|
||||
// 9 AM to 5 PM = 8 hours
|
||||
|
|
@ -412,7 +413,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(1000, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_overnight_booking()
|
||||
{
|
||||
// 10 PM to 6 AM next day = 8 hours
|
||||
|
|
@ -425,7 +426,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(1000, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_price_with_minutes_precision()
|
||||
{
|
||||
// 2 hours and 45 minutes
|
||||
|
|
@ -438,7 +439,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(344, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_maintains_precision_for_multiple_quantity()
|
||||
{
|
||||
// 6 hours
|
||||
|
|
@ -454,7 +455,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertGreaterThan(1000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_weekend_hourly_booking()
|
||||
{
|
||||
// Friday 6 PM to Sunday 6 PM = 48 hours exactly
|
||||
|
|
@ -467,7 +468,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(6000, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_different_pricing_strategies_for_fractional_time()
|
||||
{
|
||||
// Test LOWEST (already set in setUp)
|
||||
|
|
@ -500,7 +501,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(500, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_single_minute_booking()
|
||||
{
|
||||
// Just 1 minute
|
||||
|
|
@ -513,7 +514,7 @@ class PoolPerMinutePricingTest extends TestCase
|
|||
$this->assertEquals(2, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_booking_with_seconds_precision()
|
||||
{
|
||||
// 2 hours, 30 minutes, 30 seconds (Carbon truncates seconds to minutes)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use Blax\Shop\Tests\TestCase;
|
|||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PoolProductCheckoutTest extends TestCase
|
||||
{
|
||||
|
|
@ -88,7 +89,7 @@ class PoolProductCheckoutTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_cart_with_pool_product_claims_correct_single_items()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -117,7 +118,7 @@ class PoolProductCheckoutTest extends TestCase
|
|||
$this->assertEquals(2, $claimedCount);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_cart_with_pool_product_without_timespan_throws_exception_when_single_items_are_bookings()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -136,7 +137,7 @@ class PoolProductCheckoutTest extends TestCase
|
|||
$cart->checkout();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_cart_with_pool_product_and_timespan_succeeds()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -158,7 +159,7 @@ class PoolProductCheckoutTest extends TestCase
|
|||
$this->assertCount(1, $cart->purchases);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_cart_with_pool_product_stores_claimed_items_in_cart_item_meta()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -190,7 +191,7 @@ class PoolProductCheckoutTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_cart_with_multiple_pool_products_claims_from_each_independently()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -260,7 +261,7 @@ class PoolProductCheckoutTest extends TestCase
|
|||
$this->assertEquals(1, $bikePool->getPoolMaxQuantity($from, $until));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_cart_with_pool_product_and_regular_booking_product_succeeds()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -294,7 +295,7 @@ class PoolProductCheckoutTest extends TestCase
|
|||
$this->assertCount(2, $cart->purchases);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_cart_with_pool_product_fails_when_single_item_becomes_unavailable_during_checkout()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -323,7 +324,7 @@ class PoolProductCheckoutTest extends TestCase
|
|||
$cart->checkout();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_cart_validates_timespan_before_claiming_stock()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -347,7 +348,7 @@ class PoolProductCheckoutTest extends TestCase
|
|||
$this->assertEquals(3, $this->parkingPool->getPoolMaxQuantity($from, $until));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_creates_purchase_with_correct_timespan()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -372,7 +373,7 @@ class PoolProductCheckoutTest extends TestCase
|
|||
$this->assertEquals($until->format('Y-m-d H:i:s'), $purchase->until->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_with_pool_product_using_legacy_parameters()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -399,7 +400,7 @@ class PoolProductCheckoutTest extends TestCase
|
|||
$this->assertTrue($cart->isConverted());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_pool_product_claims_stock_with_cart_reference()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use Blax\Shop\Models\Product;
|
|||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PoolProductPriceIdTest extends TestCase
|
||||
{
|
||||
|
|
@ -79,7 +80,7 @@ class PoolProductPriceIdTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_stores_single_item_price_id_when_adding_pool_to_cart_with_lowest_strategy()
|
||||
{
|
||||
// Set pricing strategy to lowest (default)
|
||||
|
|
@ -94,7 +95,7 @@ class PoolProductPriceIdTest extends TestCase
|
|||
$this->assertEquals(2000, $cartItem->price); // $20
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_stores_correct_price_id_for_second_pool_item_with_progressive_pricing()
|
||||
{
|
||||
// Set pricing strategy to lowest
|
||||
|
|
@ -111,7 +112,7 @@ class PoolProductPriceIdTest extends TestCase
|
|||
$this->assertEquals(5000, $cartItem2->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_stores_single_item_price_id_with_highest_strategy()
|
||||
{
|
||||
// Set pricing strategy to highest
|
||||
|
|
@ -126,7 +127,7 @@ class PoolProductPriceIdTest extends TestCase
|
|||
$this->assertEquals(5000, $cartItem->price); // $50
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_stores_allocated_single_item_in_meta()
|
||||
{
|
||||
// Set pricing strategy to lowest
|
||||
|
|
@ -142,7 +143,7 @@ class PoolProductPriceIdTest extends TestCase
|
|||
$this->assertEquals($this->singleItem1->name, $meta->allocated_single_item_name);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_stores_different_single_items_in_meta_for_progressive_pricing()
|
||||
{
|
||||
// Set pricing strategy to lowest
|
||||
|
|
@ -159,7 +160,7 @@ class PoolProductPriceIdTest extends TestCase
|
|||
$this->assertEquals($this->singleItem2->id, $meta2->allocated_single_item_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_uses_pool_price_id_when_pool_has_direct_price_and_no_single_item_prices()
|
||||
{
|
||||
// Remove prices from single items
|
||||
|
|
@ -193,7 +194,7 @@ class PoolProductPriceIdTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_stores_price_id_with_average_pricing_strategy()
|
||||
{
|
||||
// Set pricing strategy to average
|
||||
|
|
@ -213,7 +214,7 @@ class PoolProductPriceIdTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_stores_correct_price_id_with_booking_dates()
|
||||
{
|
||||
// Set pricing strategy to lowest
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ use Blax\Shop\Models\Cart;
|
|||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Enums\ProductType;
|
||||
use Blax\Shop\Enums\ProductRelationType;
|
||||
use Blax\Shop\Exceptions\HasNoPriceException;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PoolProductPricingFlexibilityTest extends TestCase
|
||||
{
|
||||
|
|
@ -23,7 +23,7 @@ class PoolProductPricingFlexibilityTest extends TestCase
|
|||
$this->user = \Workbench\App\Models\User::factory()->create();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_without_direct_price_uses_single_item_prices()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
@ -64,7 +64,7 @@ class PoolProductPricingFlexibilityTest extends TestCase
|
|||
$this->assertEquals(5000, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_validation_does_not_throw_when_single_items_have_prices()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
@ -99,7 +99,7 @@ class PoolProductPricingFlexibilityTest extends TestCase
|
|||
$this->assertStringContainsString('inherited pricing', $result['warnings'][0]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_validation_warns_when_no_prices_available_but_does_not_throw()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
@ -126,7 +126,7 @@ class PoolProductPricingFlexibilityTest extends TestCase
|
|||
$this->assertStringContainsString('Price will be needed when adding to cart', $result['warnings'][0]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_throws_exception_only_when_adding_to_cart_without_any_prices()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
@ -157,7 +157,7 @@ class PoolProductPricingFlexibilityTest extends TestCase
|
|||
$cart->addToCart($pool, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_with_direct_price_used_as_fallback_when_single_items_have_no_prices()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
@ -190,7 +190,7 @@ class PoolProductPricingFlexibilityTest extends TestCase
|
|||
$this->assertEquals(4000, $price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_prefers_single_item_prices_over_direct_price()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
@ -231,7 +231,7 @@ class PoolProductPricingFlexibilityTest extends TestCase
|
|||
$this->assertEquals(5000, $price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_can_be_created_without_price_if_single_items_will_have_prices()
|
||||
{
|
||||
// This test verifies that pools can exist in a "not fully configured" state
|
||||
|
|
@ -278,7 +278,7 @@ class PoolProductPricingFlexibilityTest extends TestCase
|
|||
$this->assertEquals(5000, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_uses_pricing_strategy_with_multiple_single_item_prices()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use Blax\Shop\Tests\TestCase;
|
|||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PoolProductPricingTest extends TestCase
|
||||
{
|
||||
|
|
@ -58,7 +59,7 @@ class PoolProductPricingTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_inherits_price_from_single_items_when_no_pool_price_set()
|
||||
{
|
||||
// Set price on single items
|
||||
|
|
@ -85,7 +86,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(5000, $price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_uses_own_price_when_explicitly_set()
|
||||
{
|
||||
// Set different prices on single items
|
||||
|
|
@ -111,7 +112,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(4500, $price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_inherits_average_price_from_single_items_with_different_prices()
|
||||
{
|
||||
// Set different prices on single items
|
||||
|
|
@ -140,7 +141,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(6000, $price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_returns_null_when_no_prices_available()
|
||||
{
|
||||
// No prices set on pool or single items
|
||||
|
|
@ -149,7 +150,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertNull($price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_inherits_lowest_price_from_single_items()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -173,7 +174,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(5000, $lowestPrice);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_inherits_highest_price_from_single_items()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -197,7 +198,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(7000, $highestPrice);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_bulk_discount_applied_for_multiple_items()
|
||||
{
|
||||
// Set pool price with bulk discount
|
||||
|
|
@ -229,7 +230,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(20000, $total);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_pricing_strategy_can_be_set_to_average()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -255,7 +256,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(6000, $price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_pricing_strategy_can_be_set_to_lowest()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -281,7 +282,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(5000, $price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_pricing_strategy_can_be_set_to_highest()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -307,7 +308,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(7000, $price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_price_range_returns_min_and_max()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -331,7 +332,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(['min' => 5000, 'max' => 7000], $priceRange);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_with_sale_price_applies_discount()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
@ -354,7 +355,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(8000, $price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_ignores_single_items_without_prices()
|
||||
{
|
||||
// Only set price on one item
|
||||
|
|
@ -372,7 +373,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(5000, $price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_pricing_updates_when_single_item_prices_change()
|
||||
{
|
||||
$price1 = ProductPrice::factory()->create([
|
||||
|
|
@ -405,7 +406,7 @@ class PoolProductPricingTest extends TestCase
|
|||
$this->assertEquals(5500, $updatedPrice); // Average of 6000 and 5000
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_with_custom_pricing_strategy_in_meta()
|
||||
{
|
||||
ProductPrice::factory()->create([
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@ use Blax\Shop\Enums\ProductRelationType;
|
|||
use Blax\Shop\Enums\ProductType;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
|
||||
class PoolProductRelationsTest extends TestCase
|
||||
{
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_creates_reverse_pool_relation_when_attaching_single_items()
|
||||
{
|
||||
// Create pool product
|
||||
|
|
@ -48,7 +50,7 @@ class PoolProductRelationsTest extends TestCase
|
|||
$this->assertEquals(ProductRelationType::POOL->value, $spot1Pivot->pivot->type);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_attach_single_item_using_id()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
@ -70,7 +72,7 @@ class PoolProductRelationsTest extends TestCase
|
|||
$this->assertTrue($spot->poolProducts->contains($pool));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_non_pool_tries_to_attach_single_items()
|
||||
{
|
||||
$regularProduct = Product::factory()->create([
|
||||
|
|
@ -86,7 +88,7 @@ class PoolProductRelationsTest extends TestCase
|
|||
$regularProduct->attachSingleItems($spot->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function single_item_can_belong_to_multiple_pools()
|
||||
{
|
||||
// Create two pools
|
||||
|
|
@ -120,7 +122,7 @@ class PoolProductRelationsTest extends TestCase
|
|||
$this->assertTrue($pool2->singleProducts->contains($spot));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_all_pools_for_a_single_item()
|
||||
{
|
||||
$pool1 = Product::factory()->create(['type' => ProductType::POOL, 'name' => 'Pool 1']);
|
||||
|
|
@ -141,7 +143,7 @@ class PoolProductRelationsTest extends TestCase
|
|||
$this->assertTrue($pools->contains('name', 'Pool 3'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function legacy_manual_attach_still_works()
|
||||
{
|
||||
// Test that old way of attaching still works (without reverse relation)
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ namespace Blax\Shop\Tests\Feature;
|
|||
use Blax\Shop\Enums\ProductRelationType;
|
||||
use Blax\Shop\Enums\ProductType;
|
||||
use Blax\Shop\Enums\StockType;
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PoolProductTest extends TestCase
|
||||
{
|
||||
|
|
@ -107,7 +107,7 @@ class PoolProductTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_a_pool_product()
|
||||
{
|
||||
$this->assertNotNull($this->parkingPool);
|
||||
|
|
@ -115,7 +115,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertTrue($this->parkingPool->isPool());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_has_single_items_linked()
|
||||
{
|
||||
$singleItems = $this->parkingPool->singleProducts;
|
||||
|
|
@ -126,7 +126,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertTrue($singleItems->contains($this->parkingSpot3));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_max_quantity_equals_number_of_single_items()
|
||||
{
|
||||
$maxQuantity = $this->parkingPool->getPoolMaxQuantity();
|
||||
|
|
@ -134,13 +134,13 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(3, $maxQuantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_detects_booking_single_items()
|
||||
{
|
||||
$this->assertTrue($this->parkingPool->hasBookingSingleItems());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_add_pool_product_to_cart_with_timespan()
|
||||
{
|
||||
$cart = $this->user->currentCart();
|
||||
|
|
@ -161,7 +161,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals($until->format('Y-m-d H:i:s'), $cartItem->until->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_quantity_is_limited_by_available_single_items()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -179,7 +179,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(2, $maxQuantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function booking_price_is_calculated_based_on_timespan_and_quantity()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -194,7 +194,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(80.00, $expectedTotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_with_overlapping_bookings_reduces_available_quantity()
|
||||
{
|
||||
$from = Carbon::now()->addDays(5);
|
||||
|
|
@ -211,7 +211,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(1, $this->parkingPool->getPoolMaxQuantity($from, $until));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function different_timespan_bookings_dont_conflict()
|
||||
{
|
||||
$from1 = Carbon::now()->addDays(1);
|
||||
|
|
@ -230,7 +230,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(2, $this->parkingPool->getPoolMaxQuantity($from1, $until1));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_unavailable_when_all_single_items_booked()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -245,7 +245,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(0, $this->parkingPool->getPoolMaxQuantity($from, $until));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_can_be_cross_sell_of_hotel_room()
|
||||
{
|
||||
$crossSells = $this->hotelRoom->crossSellProducts;
|
||||
|
|
@ -254,7 +254,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertTrue($crossSells->contains($this->parkingPool));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function booking_cancellation_releases_stock_of_single_items()
|
||||
{
|
||||
$from = Carbon::now()->addDays(10);
|
||||
|
|
@ -282,7 +282,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(3, $this->parkingPool->getPoolMaxQuantity($from, $until));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_respects_partial_overlapping_bookings()
|
||||
{
|
||||
// Booking 1: Days 1-3
|
||||
|
|
@ -301,7 +301,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(2, $this->parkingPool->getPoolMaxQuantity($from2, $until2));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function multiple_pool_products_can_exist_independently()
|
||||
{
|
||||
// Create a second pool for bikes
|
||||
|
|
@ -338,7 +338,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(2, $bikePool->getPoolMaxQuantity());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_stock_calculated_correctly_with_mixed_availability()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -357,7 +357,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(2, $this->parkingPool->getPoolMaxQuantity($from, $until));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_with_zero_single_items_returns_zero_max_quantity()
|
||||
{
|
||||
$emptyPool = Product::factory()->create([
|
||||
|
|
@ -369,7 +369,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(0, $emptyPool->getPoolMaxQuantity());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_with_non_booking_single_items_doesnt_require_timespan()
|
||||
{
|
||||
$simplePool = Product::factory()->create([
|
||||
|
|
@ -391,7 +391,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertFalse($simplePool->hasBookingSingleItems());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_with_mixed_booking_and_non_booking_single_items()
|
||||
{
|
||||
$mixedPool = Product::factory()->create([
|
||||
|
|
@ -425,7 +425,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(1, $mixedPool->getPoolMaxQuantity());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_checkout_claims_exactly_the_right_number_of_single_items()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -456,7 +456,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(2, $claimedCount);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_checkout_stores_claimed_single_items_in_metadata()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -483,7 +483,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertCount(2, $claimedItems);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_with_different_stock_quantities_on_single_items()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -511,7 +511,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(2, $customPool->getPoolMaxQuantity($from, $until));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function claim_pool_stock_throws_exception_when_not_enough_single_items_available()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -528,7 +528,7 @@ class PoolProductTest extends TestCase
|
|||
$this->parkingPool->claimPoolStock(2, null, $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function claim_pool_stock_throws_exception_when_called_on_non_pool_product()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -540,7 +540,7 @@ class PoolProductTest extends TestCase
|
|||
$this->hotelRoom->claimPoolStock(1, null, $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function release_pool_stock_correctly_releases_all_claims()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -561,7 +561,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(3, $this->parkingPool->getPoolMaxQuantity($from, $until));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function release_pool_stock_throws_exception_when_called_on_non_pool_product()
|
||||
{
|
||||
$this->expectException(\Exception::class);
|
||||
|
|
@ -570,7 +570,7 @@ class PoolProductTest extends TestCase
|
|||
$this->hotelRoom->releasePoolStock($this->user->currentCart());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_with_single_item_already_claimed_for_entire_period()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1);
|
||||
|
|
@ -594,7 +594,7 @@ class PoolProductTest extends TestCase
|
|||
$this->assertEquals(1, $this->parkingPool->getPoolMaxQuantity($partialFrom, $partialUntil));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_product_maximum_quantity_with_edge_of_timespan()
|
||||
{
|
||||
// Claim 1: Days 1-3
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use Blax\Shop\Models\ProductPrice;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
/**
|
||||
* Test to reproduce and fix the production bug where:
|
||||
|
|
@ -172,7 +173,7 @@ class PoolProductionBugTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_max_quantity_returns_sum_of_single_item_stocks()
|
||||
{
|
||||
$this->createProductionPool();
|
||||
|
|
@ -183,7 +184,7 @@ class PoolProductionBugTest extends TestCase
|
|||
$this->assertEquals(6, $maxQty);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adding_7_items_should_throw_not_enough_stock_exception()
|
||||
{
|
||||
$this->createProductionPool();
|
||||
|
|
@ -199,7 +200,7 @@ class PoolProductionBugTest extends TestCase
|
|||
$this->cart->addToCart($this->pool, 7, [], $from, $until);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adding_6_items_gives_correct_progressive_pricing()
|
||||
{
|
||||
$this->createProductionPool();
|
||||
|
|
@ -239,7 +240,7 @@ class PoolProductionBugTest extends TestCase
|
|||
$this->assertEquals(85003, $this->cart->fresh()->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adding_6_items_at_once_gives_correct_pricing()
|
||||
{
|
||||
$this->createProductionPool();
|
||||
|
|
@ -252,7 +253,7 @@ class PoolProductionBugTest extends TestCase
|
|||
$this->assertEquals(85003, $this->cart->fresh()->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_items_have_correct_allocated_single_items()
|
||||
{
|
||||
$this->createProductionPool();
|
||||
|
|
@ -281,7 +282,7 @@ class PoolProductionBugTest extends TestCase
|
|||
$this->assertEquals(85003, $this->cart->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function set_dates_updates_cart_item_dates_and_recalculates_prices()
|
||||
{
|
||||
$this->createProductionPool();
|
||||
|
|
@ -321,7 +322,7 @@ class PoolProductionBugTest extends TestCase
|
|||
$this->assertEquals(30000, $cart->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function set_dates_updates_all_items_with_different_prices()
|
||||
{
|
||||
$this->createProductionPool();
|
||||
|
|
@ -356,7 +357,7 @@ class PoolProductionBugTest extends TestCase
|
|||
$this->assertEquals(170006, $cart->getTotal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adding_items_without_dates_then_setting_dates_works()
|
||||
{
|
||||
$this->createProductionPool();
|
||||
|
|
@ -394,7 +395,7 @@ class PoolProductionBugTest extends TestCase
|
|||
* If a user boys 5 single parking items, another can also buy 5 single items on different dates,
|
||||
* but not on the same dates, if stock is claimed on date
|
||||
*/
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_allows_adding_singel_to_cart_again_after_booked()
|
||||
{
|
||||
$this->createProductionPool();
|
||||
|
|
@ -471,7 +472,7 @@ class PoolProductionBugTest extends TestCase
|
|||
* Expected: Should be able to add 6 items for different dates
|
||||
* Actual: Can only add 2 items
|
||||
*/
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_add_pool_items_for_different_dates_after_stripe_purchase()
|
||||
{
|
||||
$this->createProductionPool();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use Blax\Shop\Models\ProductPrice;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PoolSeparateCartItemsTest extends TestCase
|
||||
{
|
||||
|
|
@ -65,7 +66,7 @@ class PoolSeparateCartItemsTest extends TestCase
|
|||
$this->pool->attachSingleItems([$spot1->id, $spot2->id]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_creates_separate_cart_items_for_different_dates()
|
||||
{
|
||||
$from1 = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -82,7 +83,7 @@ class PoolSeparateCartItemsTest extends TestCase
|
|||
$this->assertEquals(2, $this->cart->items()->count());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_merges_cart_items_with_same_dates_and_price()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -97,7 +98,7 @@ class PoolSeparateCartItemsTest extends TestCase
|
|||
$this->assertEquals(2, $item2->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_creates_separate_cart_items_when_price_changes()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
@ -129,7 +130,7 @@ class PoolSeparateCartItemsTest extends TestCase
|
|||
$this->assertNotEquals($price1, $item2->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_creates_separate_cart_items_for_different_date_lengths()
|
||||
{
|
||||
$from = Carbon::now()->addDays(1)->startOfDay();
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use Blax\Shop\Models\ProductPrice;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
/**
|
||||
* Tests for smart pool allocation and flexible cart behavior
|
||||
|
|
@ -83,7 +84,7 @@ class PoolSmartAllocationTest extends TestCase
|
|||
/**
|
||||
* Test: Items can be added to cart without dates
|
||||
*/
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function items_can_be_added_to_cart_without_dates()
|
||||
{
|
||||
$this->createPoolWithVaryingPrices();
|
||||
|
|
@ -100,7 +101,7 @@ class PoolSmartAllocationTest extends TestCase
|
|||
/**
|
||||
* Test: Items can be added even if currently claimed but will be available in future
|
||||
*/
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function items_can_be_added_even_if_currently_claimed_but_available_in_future()
|
||||
{
|
||||
$this->createPoolWithVaryingPrices();
|
||||
|
|
@ -131,7 +132,7 @@ class PoolSmartAllocationTest extends TestCase
|
|||
/**
|
||||
* Test: Cart is not ready for checkout if items added without dates
|
||||
*/
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_is_not_ready_for_checkout_without_dates_for_booking_products()
|
||||
{
|
||||
$this->createPoolWithVaryingPrices();
|
||||
|
|
@ -147,7 +148,7 @@ class PoolSmartAllocationTest extends TestCase
|
|||
/**
|
||||
* Test: Cart becomes ready after setting dates
|
||||
*/
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_becomes_ready_after_setting_valid_dates()
|
||||
{
|
||||
$this->createPoolWithVaryingPrices();
|
||||
|
|
@ -169,7 +170,7 @@ class PoolSmartAllocationTest extends TestCase
|
|||
/**
|
||||
* Test: User1 purchases items, User2 can add same items but only available ones get allocated
|
||||
*/
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user2_can_book_same_items_for_different_dates_after_user1_purchase()
|
||||
{
|
||||
$this->createPoolWithVaryingPrices();
|
||||
|
|
@ -216,7 +217,7 @@ class PoolSmartAllocationTest extends TestCase
|
|||
/**
|
||||
* Test: User2 can successfully book after setting different dates
|
||||
*/
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user2_can_successfully_book_after_setting_different_dates()
|
||||
{
|
||||
$this->createPoolWithVaryingPrices();
|
||||
|
|
@ -257,7 +258,7 @@ class PoolSmartAllocationTest extends TestCase
|
|||
* Scenario: 3 items claimed for future, 3 available now
|
||||
* When adding 3 items, should get the 3 currently available ones
|
||||
*/
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pool_prioritizes_currently_available_items_when_adding_to_cart()
|
||||
{
|
||||
$this->createPoolWithVaryingPrices();
|
||||
|
|
@ -291,7 +292,7 @@ class PoolSmartAllocationTest extends TestCase
|
|||
* - Change to different date when cheaper items become available
|
||||
* - Cart should reallocate to cheaper items
|
||||
*/
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_reallocates_to_cheaper_items_when_dates_change_with_lowest_strategy()
|
||||
{
|
||||
$this->createPoolWithVaryingPrices();
|
||||
|
|
@ -325,7 +326,7 @@ class PoolSmartAllocationTest extends TestCase
|
|||
/**
|
||||
* Test: Verify allocated items change when reallocating
|
||||
*/
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function allocated_single_items_change_when_reallocating_to_better_prices()
|
||||
{
|
||||
$this->createPoolWithVaryingPrices();
|
||||
|
|
|
|||
|
|
@ -4,16 +4,16 @@ namespace Blax\Shop\Tests\Feature;
|
|||
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductAction;
|
||||
use Blax\Shop\Models\ProductPurchase;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class ProductActionTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_a_product_action()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -32,7 +32,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertContains('refunded', $action->events ?? []);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function product_has_many_actions()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -52,7 +52,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertCount(2, $product->fresh()->actions);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function action_belongs_to_product()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -66,7 +66,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertEquals($product->id, $action->product->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_enable_and_disable_actions()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -86,7 +86,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertFalse($action->fresh()->active);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_store_action_parameters()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -109,7 +109,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertEquals('Welcome to our service', $action->parameters['subject']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_set_action_priority()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -134,7 +134,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertEquals($action2->id, $sorted[1]->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_different_events()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -157,7 +157,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertContains('refunded', $refundedAction->events);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_actions_for_specific_event()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -187,7 +187,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertCount(2, $purchaseActions);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_filter_enabled_actions()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -212,7 +212,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertCount(1, $enabledActions);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function multiple_products_can_have_same_action()
|
||||
{
|
||||
$product1 = Product::factory()->create();
|
||||
|
|
@ -234,7 +234,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertCount(1, $product2->actions);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_update_action_parameters()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -262,7 +262,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertEquals('another_value', $fresh->parameters['another_key']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function deleting_product_deletes_actions()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -281,7 +281,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertDatabaseMissing('product_actions', ['id' => $actionId]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function action_can_have_empty_parameters()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -295,7 +295,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertNull($action->parameters);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_query_actions_by_priority_order()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -333,7 +333,7 @@ class ProductActionTest extends TestCase
|
|||
$this->assertEquals($high->id, $ordered[2]->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_be_triggered_on_purchase()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@ use Blax\Shop\Models\Product;
|
|||
use Blax\Shop\Models\ProductAttribute;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class ProductAttributeTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_a_product_attribute()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -30,7 +31,7 @@ class ProductAttributeTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function attribute_belongs_to_product()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -45,7 +46,7 @@ class ProductAttributeTest extends TestCase
|
|||
$this->assertEquals($product->id, $attribute->product->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function product_can_have_multiple_attributes()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -71,7 +72,7 @@ class ProductAttributeTest extends TestCase
|
|||
$this->assertCount(3, $product->fresh()->attributes);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_a_sort_order()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -98,7 +99,7 @@ class ProductAttributeTest extends TestCase
|
|||
$this->assertEquals($attr2->id, $attributes[1]->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_store_metadata()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -120,7 +121,7 @@ class ProductAttributeTest extends TestCase
|
|||
$this->assertEquals('cm', $unitAttr->value);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_update_attribute_value()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -136,7 +137,7 @@ class ProductAttributeTest extends TestCase
|
|||
$this->assertEquals('Out of Stock', $attribute->fresh()->value);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function deleting_product_deletes_attributes()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -154,7 +155,7 @@ class ProductAttributeTest extends TestCase
|
|||
$this->assertDatabaseMissing('product_attributes', ['id' => $attributeId]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_filter_attributes_by_key()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -184,7 +185,7 @@ class ProductAttributeTest extends TestCase
|
|||
$this->assertCount(2, $colorAttributes);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function multiple_products_can_have_same_attribute_keys()
|
||||
{
|
||||
$product1 = Product::factory()->create();
|
||||
|
|
@ -208,7 +209,7 @@ class ProductAttributeTest extends TestCase
|
|||
$this->assertEquals('Brand B', $product2->attributes->first()->value);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function attributes_are_hidden_in_api_responses()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@ use Blax\Shop\Models\Product;
|
|||
use Blax\Shop\Models\ProductCategory;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class ProductCategoryTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_a_category()
|
||||
{
|
||||
$category = ProductCategory::factory()->create([
|
||||
|
|
@ -24,7 +25,7 @@ class ProductCategoryTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_automatically_generates_slug_from_name()
|
||||
{
|
||||
$category = ProductCategory::create([
|
||||
|
|
@ -34,7 +35,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertNotNull($category->slug);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_a_parent_category()
|
||||
{
|
||||
$parent = ProductCategory::factory()->create([
|
||||
|
|
@ -49,7 +50,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertEquals($parent->id, $child->parent->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_multiple_children()
|
||||
{
|
||||
$parent = ProductCategory::factory()->create();
|
||||
|
|
@ -61,7 +62,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertCount(3, $parent->fresh()->children);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_attach_products_to_category()
|
||||
{
|
||||
$category = ProductCategory::factory()->create();
|
||||
|
|
@ -75,7 +76,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertTrue($category->products->contains($product2));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_count_products_in_category()
|
||||
{
|
||||
$category = ProductCategory::factory()->create();
|
||||
|
|
@ -88,7 +89,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertEquals(3, $category->products()->count());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_visibility()
|
||||
{
|
||||
$visibleCategory = ProductCategory::factory()->create([
|
||||
|
|
@ -103,7 +104,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertFalse($hiddenCategory->is_visible);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_a_sort_order()
|
||||
{
|
||||
$category1 = ProductCategory::factory()->create(['sort_order' => 1]);
|
||||
|
|
@ -117,7 +118,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertEquals($category3->id, $sorted[2]->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_store_meta_data()
|
||||
{
|
||||
$category = ProductCategory::factory()->create([
|
||||
|
|
@ -131,7 +132,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertEquals(['test', 'category'], $category->meta->keywords);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function product_can_belong_to_multiple_categories()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -144,7 +145,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertCount(3, $product->fresh()->categories);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_all_products_from_category_hierarchy()
|
||||
{
|
||||
$parent = ProductCategory::factory()->create();
|
||||
|
|
@ -160,7 +161,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertCount(1, $child->products);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_detach_products_from_category()
|
||||
{
|
||||
$category = ProductCategory::factory()->create();
|
||||
|
|
@ -173,7 +174,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertCount(0, $category->fresh()->products);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function deleting_category_does_not_delete_products()
|
||||
{
|
||||
$category = ProductCategory::factory()->create();
|
||||
|
|
@ -187,7 +188,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertDatabaseHas('products', ['id' => $productId]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_visible_categories()
|
||||
{
|
||||
ProductCategory::factory()->create(['is_visible' => true]);
|
||||
|
|
@ -199,7 +200,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertCount(2, $visible);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_root_categories()
|
||||
{
|
||||
$root1 = ProductCategory::factory()->create(['parent_id' => null]);
|
||||
|
|
@ -214,7 +215,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertFalse($roots->contains($child));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_maintains_category_hierarchy_integrity()
|
||||
{
|
||||
$grandparent = ProductCategory::factory()->create();
|
||||
|
|
@ -226,7 +227,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertNull($grandparent->parent);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_filter_products_by_category_using_instance()
|
||||
{
|
||||
$category1 = ProductCategory::factory()->create();
|
||||
|
|
@ -248,7 +249,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertFalse($results->contains($product3));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_filter_products_by_category_using_id_string()
|
||||
{
|
||||
$category = ProductCategory::factory()->create();
|
||||
|
|
@ -268,7 +269,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertFalse($results->contains($product3));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_filter_products_by_multiple_categories()
|
||||
{
|
||||
$category1 = ProductCategory::factory()->create();
|
||||
|
|
@ -299,7 +300,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertFalse($results->contains($product4));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_filter_products_without_specific_category()
|
||||
{
|
||||
$category1 = ProductCategory::factory()->create();
|
||||
|
|
@ -321,7 +322,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertTrue($results->contains($product3));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_filter_products_without_category_using_instance()
|
||||
{
|
||||
$category = ProductCategory::factory()->create();
|
||||
|
|
@ -338,7 +339,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertTrue($results->contains($product2));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_filter_products_without_multiple_categories()
|
||||
{
|
||||
$category1 = ProductCategory::factory()->create();
|
||||
|
|
@ -368,7 +369,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertTrue($results->contains($product4));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_assign_a_category_to_product()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -380,7 +381,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertTrue($product->categories->contains($category));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_assign_multiple_categories_to_product()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -396,7 +397,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertTrue($product->categories->contains($category3));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_remove_a_category_from_product()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -413,7 +414,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertTrue($product->categories->contains($category2));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_remove_multiple_categories_from_product()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -432,7 +433,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertTrue($product->categories->contains($category3));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_sync_categories_on_product()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -453,7 +454,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertTrue($product->categories->contains($category3));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_assign_category_by_name()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -465,7 +466,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertEquals('Electronics', $category->name);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_assign_category_by_name_without_creating_duplicates()
|
||||
{
|
||||
$product1 = Product::factory()->create();
|
||||
|
|
@ -477,7 +478,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertCount(1, ProductCategory::where('name', 'Electronics')->get());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_assign_multiple_categories_by_names()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -491,7 +492,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertContains('Accessories', $categoryNames);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_assign_category_by_slug()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -503,7 +504,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertEquals('electronics', $category->slug);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_assign_category_by_slug_without_creating_duplicates()
|
||||
{
|
||||
$product1 = Product::factory()->create();
|
||||
|
|
@ -515,7 +516,7 @@ class ProductCategoryTest extends TestCase
|
|||
$this->assertCount(1, ProductCategory::where('slug', 'electronics')->get());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_assign_multiple_categories_by_slugs()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
|
|||
|
|
@ -11,12 +11,13 @@ use Blax\Shop\Models\ProductAttribute;
|
|||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class ProductManagementTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_a_product()
|
||||
{
|
||||
$product = Product::factory()
|
||||
|
|
@ -35,7 +36,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertEquals(99.99, $product->prices->first()->unit_amount);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_automatically_generates_slug_if_not_provided()
|
||||
{
|
||||
$product = Product::factory()->create(['slug' => null]);
|
||||
|
|
@ -44,7 +45,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertStringStartsWith('new-product-', $product->slug);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_manage_stock()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -58,7 +59,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertEquals(55, $product->AvailableStocks);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_cannot_decrease_stock_below_zero()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -70,7 +71,7 @@ class ProductManagementTest extends TestCase
|
|||
}, \Blax\Shop\Exceptions\NotEnoughStockException::class);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_available_stock()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -82,7 +83,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertEquals(20, $product->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_if_in_stock()
|
||||
{
|
||||
$productInStock = Product::factory()->create([
|
||||
|
|
@ -98,7 +99,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertFalse($productOutOfStock->isInStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_attach_categories()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -109,7 +110,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertTrue($product->categories->contains($category));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_attributes()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -125,7 +126,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertEquals('Blue', $product->attributes->first()->value);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_multiple_prices()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -152,7 +153,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertCount(2, $product->prices);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_related_products()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -165,7 +166,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertTrue($product->relatedProducts()->get()->contains($relatedProduct));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_upsell_products()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -178,7 +179,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertTrue($product->upsellProducts()->get()->contains($upsellProduct));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_cross_sell_products()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -191,7 +192,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertTrue($product->crossSellProducts()->get()->contains($crossSellProduct));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_published_products()
|
||||
{
|
||||
Product::factory()->create(['status' => 'published']);
|
||||
|
|
@ -203,7 +204,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertEquals(ProductStatus::PUBLISHED, $published->first()->status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_in_stock_products()
|
||||
{
|
||||
Product::factory()->create([
|
||||
|
|
@ -223,7 +224,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertTrue((bool) ($inStock->reverse()->first()->isInStock()));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_visible_products()
|
||||
{
|
||||
Product::factory()->create([
|
||||
|
|
@ -242,7 +243,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertTrue($visible->first()->is_visible);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_parent_child_relationships()
|
||||
{
|
||||
$parent = Product::factory()->create([
|
||||
|
|
@ -258,7 +259,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertEquals($parent->id, $child->parent->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_validates_virtual_and_downloadable_flags()
|
||||
{
|
||||
$virtualProduct = Product::factory()->create([
|
||||
|
|
@ -277,7 +278,7 @@ class ProductManagementTest extends TestCase
|
|||
$this->assertFalse($downloadableProduct->virtual);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_featured_status()
|
||||
{
|
||||
$featured = Product::factory()->create(['featured' => true]);
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@ use Blax\Shop\Models\Product;
|
|||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class ProductPriceTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_a_product_price()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -35,7 +36,7 @@ class ProductPriceTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function price_belongs_to_purchasable()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -51,7 +52,7 @@ class ProductPriceTest extends TestCase
|
|||
$this->assertEquals($product->id, $price->purchasable->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_set_default_price()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -77,7 +78,7 @@ class ProductPriceTest extends TestCase
|
|||
$this->assertEquals($price2->id, $product->defaultPrice()->first()->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_set_recurring_price()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -99,7 +100,7 @@ class ProductPriceTest extends TestCase
|
|||
$this->assertEquals(14, $price->trial_period_days);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_set_one_time_price()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -116,7 +117,7 @@ class ProductPriceTest extends TestCase
|
|||
$this->assertNull($price->interval);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_active_prices()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -143,7 +144,7 @@ class ProductPriceTest extends TestCase
|
|||
$this->assertTrue($activePrices->first()->active);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_current_price_based_on_sale()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -160,7 +161,7 @@ class ProductPriceTest extends TestCase
|
|||
$this->assertEquals(100.00, $price->getCurrentPrice(false));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_multiple_currencies()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -184,7 +185,7 @@ class ProductPriceTest extends TestCase
|
|||
$this->assertEquals('EUR', $eurPrice->currency);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_store_price_metadata()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -204,7 +205,7 @@ class ProductPriceTest extends TestCase
|
|||
$this->assertEquals(['feature1', 'feature2'], $price->meta->features);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_deactivate_price()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -224,7 +225,7 @@ class ProductPriceTest extends TestCase
|
|||
$this->assertFalse($price->fresh()->active);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function product_can_have_multiple_price_tiers()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -256,7 +257,7 @@ class ProductPriceTest extends TestCase
|
|||
$this->assertCount(3, $product->prices);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_set_billing_scheme()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use Blax\Shop\Models\ProductPrice;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class ProductPricingValidationTest extends TestCase
|
||||
{
|
||||
|
|
@ -25,7 +26,7 @@ class ProductPricingValidationTest extends TestCase
|
|||
auth()->login($this->user);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_product_has_no_prices()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -39,7 +40,7 @@ class ProductPricingValidationTest extends TestCase
|
|||
Cart::add($product, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_product_has_multiple_prices_but_no_default()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -68,7 +69,7 @@ class ProductPricingValidationTest extends TestCase
|
|||
Cart::add($product, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_product_has_single_price_not_marked_as_default()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -89,7 +90,7 @@ class ProductPricingValidationTest extends TestCase
|
|||
Cart::add($product, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_product_has_multiple_default_prices()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -125,7 +126,7 @@ class ProductPricingValidationTest extends TestCase
|
|||
Cart::add($product, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_allows_adding_product_with_valid_default_price()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -148,7 +149,7 @@ class ProductPricingValidationTest extends TestCase
|
|||
$this->assertEquals($product->id, $cartItem->purchasable_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_allows_product_with_one_default_and_multiple_non_default_prices()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -187,7 +188,7 @@ class ProductPricingValidationTest extends TestCase
|
|||
$this->assertEquals($product->id, $cartItem->purchasable_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_throws_exception_when_pool_has_no_price_and_single_items_have_no_prices()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
@ -213,7 +214,7 @@ class ProductPricingValidationTest extends TestCase
|
|||
Cart::add($pool, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_allows_pool_with_no_direct_price_but_single_items_have_prices()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
@ -246,7 +247,7 @@ class ProductPricingValidationTest extends TestCase
|
|||
$this->assertEquals($pool->id, $cartItem->purchasable_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_allows_pool_with_direct_price_even_if_single_items_have_no_prices()
|
||||
{
|
||||
$pool = Product::factory()->create([
|
||||
|
|
@ -279,7 +280,7 @@ class ProductPricingValidationTest extends TestCase
|
|||
$this->assertEquals($pool->id, $cartItem->purchasable_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_pricing_returns_errors_array_without_throwing()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -294,7 +295,7 @@ class ProductPricingValidationTest extends TestCase
|
|||
$this->assertStringContainsString('no prices', $result['errors'][0]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function validate_pricing_with_valid_price_returns_valid()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
|
|||
|
|
@ -8,12 +8,13 @@ use Blax\Shop\Models\ProductPurchase;
|
|||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class ProductPurchaseTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_create_a_purchase()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -38,7 +39,7 @@ class ProductPurchaseTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function purchase_belongs_to_purchaser()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -60,7 +61,7 @@ class ProductPurchaseTest extends TestCase
|
|||
$this->assertEquals($user->id, $purchase->purchaser->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function purchase_belongs_to_purchasable()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -82,7 +83,7 @@ class ProductPurchaseTest extends TestCase
|
|||
$this->assertEquals($product->id, $purchase->purchasable->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_have_different_statuses()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -114,7 +115,7 @@ class ProductPurchaseTest extends TestCase
|
|||
$this->assertEquals(PurchaseStatus::COMPLETED, $completedPurchase->status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_completed_purchases()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -148,7 +149,7 @@ class ProductPurchaseTest extends TestCase
|
|||
$this->assertEquals(PurchaseStatus::COMPLETED, $completed->first()->status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_cart_purchases()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -182,7 +183,7 @@ class ProductPurchaseTest extends TestCase
|
|||
$this->assertEquals(PurchaseStatus::CART, $inCart->first()->status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_store_purchase_metadata()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -208,7 +209,7 @@ class ProductPurchaseTest extends TestCase
|
|||
$this->assertEquals('Mozilla/5.0', $purchase->meta->user_agent);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_track_amount_paid()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -239,7 +240,7 @@ class ProductPurchaseTest extends TestCase
|
|||
$this->assertEquals(PurchaseStatus::COMPLETED, $purchase->fresh()->status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_store_charge_id()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -261,7 +262,7 @@ class ProductPurchaseTest extends TestCase
|
|||
$this->assertEquals('ch_123456789', $purchase->charge_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_tracks_purchase_quantity()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -283,7 +284,7 @@ class ProductPurchaseTest extends TestCase
|
|||
$this->assertEquals(25000, $purchase->amount);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_have_multiple_purchases()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -313,7 +314,7 @@ class ProductPurchaseTest extends TestCase
|
|||
$this->assertCount(2, $user->purchases);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function product_can_have_multiple_purchases()
|
||||
{
|
||||
$user1 = User::factory()->create();
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@ use Blax\Shop\Models\Product;
|
|||
use Blax\Shop\Models\ProductCategory;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class ProductScopeTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_by_category()
|
||||
{
|
||||
$category1 = ProductCategory::factory()->create();
|
||||
|
|
@ -33,7 +34,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertTrue($productsInCategory1->contains($product2));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_search_products_by_slug()
|
||||
{
|
||||
Product::factory()->create(['slug' => 'awesome-product']);
|
||||
|
|
@ -45,7 +46,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertCount(2, $results);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_search_products_by_sku()
|
||||
{
|
||||
Product::factory()->create(['sku' => 'SKU-001']);
|
||||
|
|
@ -57,7 +58,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertCount(2, $results);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_filter_by_price_range()
|
||||
{
|
||||
$product1 = Product::factory()->withPrices(1, 50)->create();
|
||||
|
|
@ -70,7 +71,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertTrue($inRange->contains($product2));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_filter_by_minimum_price_only()
|
||||
{
|
||||
$product1 = Product::factory()->withPrices(1, 50)->create();
|
||||
|
|
@ -84,7 +85,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertTrue($minPrice->contains($product3));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_filter_by_maximum_price_only()
|
||||
{
|
||||
$product1 = Product::factory()->withPrices(1, 50)->create();
|
||||
|
|
@ -98,7 +99,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertTrue($maxPrice->contains($product2));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_order_products_by_price_ascending()
|
||||
{
|
||||
$product1 = Product::factory()->withPrices(1, 150)->create(['name' => 'Expensive']);
|
||||
|
|
@ -111,7 +112,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertEquals($product1->id, $ordered->last()->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_order_products_by_price_descending()
|
||||
{
|
||||
$product1 = Product::factory()->withPrices(1, 150)->create(['name' => 'Expensive']);
|
||||
|
|
@ -124,7 +125,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertEquals($product2->id, $ordered->last()->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_combine_price_range_and_order_by_price()
|
||||
{
|
||||
$product1 = Product::factory()->withPrices(1, 50)->create();
|
||||
|
|
@ -139,7 +140,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertEquals($product3->id, $filtered->last()->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_low_stock_products()
|
||||
{
|
||||
$lowStockProduct = Product::factory()->create([
|
||||
|
|
@ -160,7 +161,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertFalse($lowStock->contains($normalStockProduct));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_featured_products()
|
||||
{
|
||||
Product::factory()->create(['featured' => true]);
|
||||
|
|
@ -173,7 +174,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertTrue($featured->every(fn($p) => $p->featured === true));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function visible_scope_excludes_unpublished_products()
|
||||
{
|
||||
Product::factory()->create([
|
||||
|
|
@ -196,7 +197,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertCount(1, $visible);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function visible_scope_respects_published_at_date()
|
||||
{
|
||||
Product::factory()->create([
|
||||
|
|
@ -216,7 +217,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertCount(1, $visible);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function in_stock_scope_includes_products_without_stock_management()
|
||||
{
|
||||
Product::factory()->create(['manage_stock' => false]);
|
||||
|
|
@ -229,7 +230,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertGreaterThanOrEqual(2, $inStock->count());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function in_stock_scope_excludes_out_of_stock_products()
|
||||
{
|
||||
$outOfStock = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -243,7 +244,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertTrue($products->contains($inStock));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_combine_multiple_scopes()
|
||||
{
|
||||
Product::factory()->create([
|
||||
|
|
@ -273,7 +274,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertCount(1, $products);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_products_by_type()
|
||||
{
|
||||
Product::factory()->create(['type' => ProductType::SIMPLE]);
|
||||
|
|
@ -286,7 +287,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertCount(2, $simpleProducts);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_downloadable_products()
|
||||
{
|
||||
Product::factory()->create(['downloadable' => true]);
|
||||
|
|
@ -298,7 +299,7 @@ class ProductScopeTest extends TestCase
|
|||
$this->assertCount(2, $downloadable);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_scope_virtual_products()
|
||||
{
|
||||
Product::factory()->create(['virtual' => true]);
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@ use Blax\Shop\Models\Product;
|
|||
use Blax\Shop\Models\ProductStock;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class ProductStockTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_creates_stock_record_on_increase()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -28,7 +29,7 @@ class ProductStockTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_creates_stock_record_on_decrease()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -43,7 +44,7 @@ class ProductStockTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function stock_belongs_to_product()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -55,7 +56,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals($product->id, $stock->product->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function product_has_many_stock_records()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -67,7 +68,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertCount(3, $product->stocks);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function available_stock_considers_all_records()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -79,7 +80,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(60, $product->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function claim_reduces_available_stock()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -90,7 +91,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertNotNull($claim);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function releasing_claim_increases_available_stock()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -103,7 +104,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(100, $product->refresh()->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function permanent_claim_has_no_expiry()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->create();
|
||||
|
|
@ -114,7 +115,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertTrue($claim->isPermanent());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function temporary_claim_has_expiry()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->create();
|
||||
|
|
@ -128,7 +129,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertTrue($claim->isTemporary());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function claim_can_have_note()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->create();
|
||||
|
|
@ -142,7 +143,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals($note, $claim->note);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cannot_claim_more_than_available()
|
||||
{
|
||||
$product = Product::factory()->withStocks(10)->create();
|
||||
|
|
@ -152,7 +153,7 @@ class ProductStockTest extends TestCase
|
|||
$product->claimStock(15);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function pending_scope_returns_unreleased_claims()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -167,7 +168,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertFalse($pendingClaims->contains($released));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function released_scope_returns_released_claims()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -182,7 +183,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertTrue($releasedClaims->contains($released));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function expired_claims_dont_affect_available_stock()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -198,7 +199,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(0, $available->count());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cannot_release_stock_twice()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->create();
|
||||
|
|
@ -209,7 +210,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertFalse($claim->release());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function stock_status_is_tracked()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -221,7 +222,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(StockStatus::COMPLETED, $stock->status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function product_without_stock_management_returns_max_stock()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => false]);
|
||||
|
|
@ -231,7 +232,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(PHP_INT_MAX, $available);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function product_without_stock_management_doesnt_create_records()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => false]);
|
||||
|
|
@ -242,7 +243,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertCount(0, $product->stocks);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function claim_without_stock_management_returns_null()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => false]);
|
||||
|
|
@ -252,7 +253,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertNull($claim);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function available_stocks_attribute_accessor_works()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -263,7 +264,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(40, $product->AvailableStocks);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function claims_method_filters_active_only()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -277,7 +278,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals($active->id, $claims->first()->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function can_adjust_stock()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -314,7 +315,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(25, $product->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_claim_stock_with_claimed_from_date()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -333,7 +334,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals($until->format('Y-m-d H:i:s'), $claim->expires_at->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_available_stock_on_a_date()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -358,7 +359,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(100, $availableOnDay12);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_handle_multiple_overlapping_claims_on_date()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -394,7 +395,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(100, $availableOnDay20);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_claims_without_claimed_from_as_immediately_claimed()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -418,7 +419,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(100, $availableOnDay12);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_permanent_claims_without_expires_at()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -442,7 +443,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(60, $availableOnDay100);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function available_on_date_scope_filters_correctly()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -483,7 +484,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals($claim2->id, $claimsOnDay12->first()->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_claimed_stock_amount()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -496,7 +497,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(40, $product->getCurrentlyClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_checks_if_claim_is_active()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -510,7 +511,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertFalse($claim->fresh()->isActive());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_releases_expired_claims()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -535,7 +536,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(StockStatus::PENDING, $activeClaim->fresh()->status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_has_reference_relationship()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -552,7 +553,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(get_class($user), $claim->reference_type);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_return_stock_type()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -578,7 +579,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(5, $returnEntry->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function temporary_scope_filters_correctly()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -595,7 +596,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertFalse($permanentStocks->contains($temporary));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_tracks_stock_with_custom_status()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -619,7 +620,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(50, $product->fresh()->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function backward_compatibility_accessors_work()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -643,7 +644,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals($claim->fresh()->updated_at->format('Y-m-d H:i:s'), $claim->fresh()->released_at->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_increase_type_affects_available_stock_correctly()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -667,7 +668,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(80, $product->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_decrease_type_affects_available_stock_correctly()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -691,7 +692,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(65, $product->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_return_type_affects_available_stock_correctly()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->create();
|
||||
|
|
@ -708,7 +709,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(48, $product->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_claimed_type_affects_available_and_claimed_stock_correctly()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -730,7 +731,7 @@ class ProductStockTest extends TestCase
|
|||
// Claimed stock shows the pending claim (always positive now)
|
||||
$this->assertEquals(25, $product->getCurrentlyClaimedStock());
|
||||
}
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_with_until_parameter_expires_correctly()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -752,7 +753,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(100, $product->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_claimed_with_from_and_until_affects_availability_by_date()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -779,7 +780,7 @@ class ProductStockTest extends TestCase
|
|||
$availableOnDay12 = $product->availableOnDate(now()->addDays(12));
|
||||
$this->assertEquals(100, $availableOnDay12); // After claim expires
|
||||
}
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_multiple_claimed_types_accumulate_in_claimed_stock()
|
||||
{
|
||||
$product = Product::factory()->withStocks(200)->create();
|
||||
|
|
@ -806,7 +807,7 @@ class ProductStockTest extends TestCase
|
|||
// Total claimed stock (always positive)
|
||||
$this->assertEquals(70, $product->getCurrentlyClaimedStock());
|
||||
}
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_claimed_with_completed_status_does_not_count_as_claimed()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -827,7 +828,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(0, $product->getCurrentlyClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_with_mixed_types_calculates_correctly()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => true]);
|
||||
|
|
@ -859,7 +860,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(85, $product->getAvailableStock());
|
||||
$this->assertEquals(30, $product->getCurrentlyClaimedStock());
|
||||
}
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_claimed_without_from_is_immediately_active()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -883,7 +884,7 @@ class ProductStockTest extends TestCase
|
|||
$availableAfter = $product->availableOnDate(now()->addDays(11));
|
||||
$this->assertEquals(100, $availableAfter);
|
||||
}
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_claimed_without_until_is_permanent_claim()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -907,7 +908,7 @@ class ProductStockTest extends TestCase
|
|||
$availableOnDay100 = $product->availableOnDate(now()->addDays(100));
|
||||
$this->assertEquals(65, $availableOnDay100);
|
||||
}
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_with_overlapping_claimed_periods_calculates_correctly()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -970,7 +971,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(50, $product->getActiveAndPlannedClaimedStock());
|
||||
$this->assertEquals(0, $product->getFutureClaimedStock());
|
||||
}
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_with_note_and_reference_tracks_correctly()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -996,7 +997,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(get_class($user), $claim->reference_type);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_expired_claims_dont_affect_current_availability()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -1020,7 +1021,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertCount(0, $activeClaims);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_releasing_claimed_updates_calculations()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -1049,7 +1050,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(100, $product->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function stock_claim_creates_correct_transactions()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -1083,7 +1084,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertNotNull($claimedEntry->expires_at);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function claimed_stock_reduces_available_and_increases_claimed()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -1111,7 +1112,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(50, $product->getCurrentlyClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function expired_claims_automatically_restore_available_stock()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -1141,7 +1142,7 @@ class ProductStockTest extends TestCase
|
|||
// No manual release() was called!
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function multiple_claims_with_different_expirations_restore_progressively()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -1169,7 +1170,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(0, $product->getCurrentlyClaimedStock()); // No claims
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function permanent_claims_without_expiration_never_auto_restore()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -1201,7 +1202,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(0, $product->getCurrentlyClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adjust_stock_claimed_also_auto_restores_after_expiration()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -1225,7 +1226,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(0, $product->getCurrentlyClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function claimed_stock_transactions_maintain_data_integrity()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -1270,7 +1271,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(35, $allClaimed);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function can_get_all_stocks_including_pending_and_expired()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -1314,7 +1315,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(0, $product->getCurrentlyClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function get_claimed_stock_returns_active_pending_claims_only()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -1340,7 +1341,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertCount(4, $allClaims);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function get_claimed_stock_excludes_released_claims()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -1364,7 +1365,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(0, $product->fresh()->getCurrentlyClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function get_claimed_stock_accounts_for_claim_expiration()
|
||||
{
|
||||
$product = Product::factory()->withStocks(200)->create();
|
||||
|
|
@ -1390,7 +1391,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(30, $product->fresh()->getCurrentlyClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function get_total_planned_claimed_stock_includes_future_claims()
|
||||
{
|
||||
$product = Product::factory()->withStocks(300)->create();
|
||||
|
|
@ -1413,7 +1414,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(25, $product->getCurrentlyClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function get_total_planned_claimed_stock_excludes_expired_claims()
|
||||
{
|
||||
$product = Product::factory()->withStocks(200)->create();
|
||||
|
|
@ -1427,7 +1428,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(90, $product->getActiveAndPlannedClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function get_total_planned_claimed_stock_excludes_released_claims()
|
||||
{
|
||||
$product = Product::factory()->withStocks(200)->create();
|
||||
|
|
@ -1452,7 +1453,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(25, $product->fresh()->getActiveAndPlannedClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function get_future_claimed_stock_without_from_date_parameter()
|
||||
{
|
||||
$product = Product::factory()->withStocks(300)->create();
|
||||
|
|
@ -1480,7 +1481,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(0, $product->fresh()->getFutureClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function get_future_claimed_stock_with_from_date_parameter()
|
||||
{
|
||||
$product = Product::factory()->withStocks(300)->create();
|
||||
|
|
@ -1504,7 +1505,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(0, $fromDay20);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function get_future_claimed_stock_excludes_expired_claims()
|
||||
{
|
||||
$product = Product::factory()->withStocks(300)->create();
|
||||
|
|
@ -1527,7 +1528,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(50, $product->fresh()->getFutureClaimedStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function claimed_stock_methods_work_together()
|
||||
{
|
||||
$product = Product::factory()->withStocks(500)->create();
|
||||
|
|
@ -1559,7 +1560,7 @@ class ProductStockTest extends TestCase
|
|||
$this->assertEquals(115, $product->fresh()->getFutureClaimedStock()); // future ones unchanged
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function claimed_stock_methods_return_zero_for_unmanaged_stock()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => false]);
|
||||
|
|
|
|||
|
|
@ -6,18 +6,18 @@ use Blax\Shop\Enums\PurchaseStatus;
|
|||
use Blax\Shop\Exceptions\NotEnoughStockException;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPurchase;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\CartItem;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class PurchaseFlowTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_purchase_a_product_directly()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -36,7 +36,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertEquals(PurchaseStatus::UNPAID, $purchase->status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_add_product_to_cart()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -51,7 +51,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertEquals($product->id, $cartItem->purchasable_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_get_cart_items()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -69,7 +69,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertCount(2, $cartItems);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_update_cart_item_quantity()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -82,7 +82,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertEquals(5, $cartItem->fresh()->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_remove_item_from_cart()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -97,7 +97,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertCount(0, $user->refresh()->cartItems);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_checkout_cart()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -126,7 +126,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertEquals(PurchaseStatus::UNPAID, $purchases[1]->status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_get_cart_total()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -144,7 +144,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertEquals(140.00, $total);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_get_cart_items_count()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -159,7 +159,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertEquals(5, $count);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_clear_cart()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -176,7 +176,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertCount(0, $user->fresh()->cartItems);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_check_if_product_was_purchased()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -191,7 +191,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertFalse($user->hasPurchased($notPurchasedProduct));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_get_completed_purchases()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -208,7 +208,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertCount(2, $completed);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function purchase_reduces_stock_when_managed()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -220,7 +220,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertEquals(7, $product->AvailableStocks);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cannot_purchase_more_than_available_stock()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -231,7 +231,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$user->purchase($product, quantity: 10);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function adding_to_cart_checks_stock_availability()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -240,7 +240,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertThrows(fn() => $user->addToCart($product, quantity: 5), NotEnoughStockException::class);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function purchase_can_store_metadata()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -254,7 +254,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertEquals('Happy Birthday!', $purchase->meta->gift_message ?? null);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function purchase_can_be_associated_with_cart()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -276,7 +276,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertTrue($cart->purchases->contains($purchase));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_marks_cart_as_converted()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -294,7 +294,7 @@ class PurchaseFlowTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_cannot_add_out_of_stock_product_to_cart()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -309,7 +309,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$user->addToCart($product, quantity: 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function purchase_stores_amount_correctly()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -324,7 +324,7 @@ class PurchaseFlowTest extends TestCase
|
|||
$this->assertGreaterThan(0, $purchase->amount);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_total_is_correct_after_checkout()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@ use Blax\Shop\Models\Product;
|
|||
use Blax\Shop\Models\ProductCategory;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class ShopFacadeTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_all_products()
|
||||
{
|
||||
Product::factory()->create();
|
||||
|
|
@ -24,7 +25,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertCount(3, $products);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_a_single_product_by_id()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -35,7 +36,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertEquals($product->id, $foundProduct->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_null_for_nonexistent_product()
|
||||
{
|
||||
$product = Shop::product(999);
|
||||
|
|
@ -43,7 +44,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertNull($product);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_all_categories()
|
||||
{
|
||||
ProductCategory::factory()->create();
|
||||
|
|
@ -54,7 +55,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertCount(2, $categories);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_in_stock_products()
|
||||
{
|
||||
Product::factory()->withStocks()->create();
|
||||
|
|
@ -66,7 +67,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertGreaterThanOrEqual(2, $inStockProducts->count());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_featured_products()
|
||||
{
|
||||
Product::factory()->create(['featured' => true]);
|
||||
|
|
@ -78,7 +79,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertCount(2, $featured);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_published_and_visible_products()
|
||||
{
|
||||
Product::factory()->create(['status' => 'published', 'is_visible' => true]);
|
||||
|
|
@ -90,7 +91,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertGreaterThanOrEqual(1, $published->count());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_search_products_by_name()
|
||||
{
|
||||
Product::factory()->create();
|
||||
|
|
@ -103,7 +104,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertGreaterThanOrEqual(1, $results->count());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_search_products_by_description()
|
||||
{
|
||||
Product::factory()->count(2)->create();
|
||||
|
|
@ -114,7 +115,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertIsObject($results);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_stock_availability_for_managed_stock_product()
|
||||
{
|
||||
$product = Product::factory()->withStocks(10)->create(['manage_stock' => true]);
|
||||
|
|
@ -124,7 +125,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertTrue($hasStock);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_false_when_not_enough_stock()
|
||||
{
|
||||
$product = Product::factory()->withStocks(5)->create(['manage_stock' => true]);
|
||||
|
|
@ -134,7 +135,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertFalse($hasStock);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_true_for_unmanaged_stock_products()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => false]);
|
||||
|
|
@ -144,7 +145,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertTrue($hasStock);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_available_stock()
|
||||
{
|
||||
$product = Product::factory()->withStocks(15)->create(['manage_stock' => true]);
|
||||
|
|
@ -154,7 +155,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertEquals(15, $available);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_max_int_for_unmanaged_stock_products()
|
||||
{
|
||||
$product = Product::factory()->create(['manage_stock' => false]);
|
||||
|
|
@ -164,7 +165,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertEquals(PHP_INT_MAX, $available);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_if_product_is_on_sale()
|
||||
{
|
||||
// Just verify the method exists and returns a boolean
|
||||
|
|
@ -175,7 +176,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertIsBool($isOnSale);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_shop_configuration()
|
||||
{
|
||||
$currency = Shop::config('currency', 'USD');
|
||||
|
|
@ -183,7 +184,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertIsString($currency);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_default_config_value_for_nonexistent_key()
|
||||
{
|
||||
$value = Shop::config('nonexistent.key', 'default');
|
||||
|
|
@ -191,7 +192,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertEquals('default', $value);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_default_currency()
|
||||
{
|
||||
$currency = Shop::currency();
|
||||
|
|
@ -200,7 +201,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertNotEmpty($currency);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_chain_query_builder_methods()
|
||||
{
|
||||
Product::factory()->create(['featured' => true, 'is_visible' => true]);
|
||||
|
|
@ -215,7 +216,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertCount(1, $products);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_paginate_products()
|
||||
{
|
||||
Product::factory()->count(15)->create();
|
||||
|
|
@ -226,7 +227,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertEquals(3, $page->lastPage());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_count_products()
|
||||
{
|
||||
Product::factory()->count(7)->create();
|
||||
|
|
@ -236,7 +237,7 @@ class ShopFacadeTest extends TestCase
|
|||
$this->assertEquals(7, $count);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_featured_and_in_stock_products()
|
||||
{
|
||||
Product::factory()->withStocks()->create(['featured' => true]);
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ use Blax\Shop\Exceptions\NotEnoughStockException;
|
|||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductStock;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class StockManagementTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_claim_stock_for_a_product()
|
||||
{
|
||||
$product = Product::factory()
|
||||
|
|
@ -30,7 +30,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals(90, $product->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_cannot_claim_more_stock_than_available()
|
||||
{
|
||||
$product = Product::factory()
|
||||
|
|
@ -45,7 +45,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals(5, $product->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_release_claimed_stock()
|
||||
{
|
||||
$product = Product::factory()
|
||||
|
|
@ -65,7 +65,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertNotNull($claim->fresh()->released_at);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_if_stock_is_pending()
|
||||
{
|
||||
$product = Product::factory()->withStocks(10)->create();
|
||||
|
|
@ -78,7 +78,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertNull($pending->released_at);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_check_if_stock_is_released()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->create();
|
||||
|
|
@ -93,7 +93,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertNotNull($released->released_at);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_distinguish_temporary_and_permanent_claims()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -114,7 +114,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertFalse($temporaryClaim->isPermanent());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_belongs_to_a_product()
|
||||
{
|
||||
$product = Product::factory()->withStocks(20)->create();
|
||||
|
|
@ -125,7 +125,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals($product->id, $claim->product->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function product_has_many_stock_records()
|
||||
{
|
||||
$product = Product::factory()->withStocks(30)->create();
|
||||
|
|
@ -139,7 +139,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals(30 + 10 + 10 + 50, $product->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_get_active_stock_claims()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -160,7 +160,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals($activeClaim->id, $activeClaims->first()->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_cannot_release_stock_twice()
|
||||
{
|
||||
$product = Product::factory()->withStocks()->create();
|
||||
|
|
@ -171,7 +171,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertFalse($claim->release());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_store_claim_note()
|
||||
{
|
||||
$product = Product::factory()->withStocks()->create();
|
||||
|
|
@ -186,7 +186,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals($note, $claim->note);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_calculates_available_stock_correctly()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -207,7 +207,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals(85, $product->refresh()->getAvailableStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function product_tracks_low_stock_threshold()
|
||||
{
|
||||
$product = Product::factory()
|
||||
|
|
@ -223,7 +223,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertTrue($product->fresh()->isLowStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_updates_in_stock_status_automatically()
|
||||
{
|
||||
$product = Product::factory()
|
||||
|
|
@ -235,7 +235,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertFalse($product->fresh()->isInStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_adjust_stock_with_from_parameter_for_claimed_type()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -265,7 +265,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals(-15, $decreaseStock->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_uses_now_as_default_from_date_for_claimed_type()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -283,7 +283,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertNull($claimedStock->claimed_from);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_does_not_set_claimed_from_for_non_claimed_types()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -298,7 +298,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertNull($stock->claimed_from);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_adjust_stock_with_note_parameter()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -317,7 +317,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals($note, $stock->note);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_adjust_stock_with_referencable_model()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -337,7 +337,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals($referencedProduct->id, $stock->reference_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_adjust_stock_with_all_parameters_combined()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -369,7 +369,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals($referencedProduct->id, $stock->reference_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_adjusts_stock_with_correct_quantity_signs_based_on_type()
|
||||
{
|
||||
$product = Product::factory()->withStocks(100)->create();
|
||||
|
|
@ -416,7 +416,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals(-5, $claimedDecrease->quantity);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_false_when_adjusting_stock_with_management_disabled()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
|
|||
|
|
@ -2,21 +2,16 @@
|
|||
|
||||
namespace Blax\Shop\Tests\Feature;
|
||||
|
||||
use Blax\Shop\Exceptions\NotEnoughStockException;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPurchase;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\CartItem;
|
||||
use Blax\Shop\Models\PaymentProviderIdentity;
|
||||
use Blax\Shop\Models\PaymentMethod as ShopPaymentMethod;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
use Laravel\Cashier\Cashier;
|
||||
use Stripe\PaymentMethod;
|
||||
use Stripe\Customer;
|
||||
use Stripe\Stripe;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class StripeChargeFlowTest extends TestCase
|
||||
{
|
||||
|
|
@ -45,7 +40,7 @@ class StripeChargeFlowTest extends TestCase
|
|||
Stripe::setApiKey(config('cashier.secret'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_be_created()
|
||||
{
|
||||
$user = User::factory()->create([
|
||||
|
|
@ -61,7 +56,7 @@ class StripeChargeFlowTest extends TestCase
|
|||
$this->assertInstanceOf(User::class, $user);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_have_stripe_account()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -80,7 +75,7 @@ class StripeChargeFlowTest extends TestCase
|
|||
$stripeCustomer->delete();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_has_stripe_account_trait()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -91,7 +86,7 @@ class StripeChargeFlowTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_update_billing_address()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -130,7 +125,7 @@ class StripeChargeFlowTest extends TestCase
|
|||
$stripeCustomer->delete();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function user_can_checkout_with_stripe()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -164,7 +159,7 @@ class StripeChargeFlowTest extends TestCase
|
|||
$this->assertSame('succeeded', $charge->status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function payment_method_model_can_store_stripe_details()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
|
@ -225,7 +220,7 @@ class StripeChargeFlowTest extends TestCase
|
|||
$stripeCustomer->delete();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function can_switch_default_payment_method_for_provider_identity()
|
||||
{
|
||||
// No need to hit Stripe here; use local records
|
||||
|
|
|
|||
|
|
@ -4,18 +4,19 @@ namespace Blax\Shop\Tests\Unit;
|
|||
|
||||
use Blax\Shop\Enums\ProductType;
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\CartItem;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
|
||||
class CartItemTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_stores_prices_as_integers_in_cents()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -37,7 +38,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEquals(3100, $cartItem->subtotal); // 1550 * 2
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_unit_amount_represents_base_price_per_day()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -51,7 +52,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEquals(5000, $cartItem->price); // Same as unit_amount for 1 day
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_calculates_price_correctly_for_booking_timespan()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -73,7 +74,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEquals(6000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_calculates_price_with_partial_days()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -93,7 +94,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEqualsWithDelta(2400, $cartItem->price, 1);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_handles_multiple_quantities_correctly()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -107,7 +108,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEquals(5000, $cartItem->subtotal); // 1000 * 5
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_updates_prices_when_dates_change()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -140,7 +141,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEquals(15000, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_handles_fractional_days_with_multiple_quantities()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -162,7 +163,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEqualsWithDelta(10800, $cartItem->subtotal, 3);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_subtotal_recalculates_on_quantity_change()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -179,7 +180,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEquals(7500, $cartItem->fresh()->subtotal); // 1500 * 5
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_stores_unit_amount_for_non_booking_products()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -194,7 +195,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEquals(9999, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_handles_sale_prices_in_cents()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -229,7 +230,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEquals(7500, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_rounds_prices_consistently()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -249,7 +250,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEquals(5000, $cartItem->price); // Rounded to 5000
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_unit_amount_remains_constant_across_date_updates()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -274,7 +275,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEquals(31500, $cartItem->price); // 4500 * 7
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_validates_database_storage_as_integer()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -293,7 +294,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertIsInt($dbItem->unit_amount);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_getSubtotal_method_returns_correct_value()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -307,7 +308,7 @@ class CartItemTest extends TestCase
|
|||
$this->assertEquals(3702, $cartItem->getSubtotal()); // 1234 * 3
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_handles_zero_prices()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -322,11 +323,14 @@ class CartItemTest extends TestCase
|
|||
$this->assertEquals(0, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_item_handles_very_long_booking_periods()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
$product = Product::factory()->withPrices(unit_amount: 500)->create(['type' => ProductType::BOOKING]); // $5.00 per day
|
||||
$product = Product::factory()
|
||||
->withPrices(unit_amount: 500)
|
||||
->create(['type' => ProductType::BOOKING]); // $5.00 per day
|
||||
|
||||
$price = $product->defaultPrice()->first();
|
||||
|
||||
// 365 days (1 year)
|
||||
|
|
|
|||
|
|
@ -8,12 +8,14 @@ use Blax\Shop\Models\Product;
|
|||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
|
||||
class CartTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_can_add_product_price_directly()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -27,7 +29,7 @@ class CartTest extends TestCase
|
|||
$this->assertEquals(100.00, $cartItem->price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_calculates_subtotal_automatically()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -39,7 +41,7 @@ class CartTest extends TestCase
|
|||
$this->assertEquals(150.00, $cartItem->subtotal);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_respects_sale_prices()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -72,7 +74,7 @@ class CartTest extends TestCase
|
|||
$this->assertEquals(100.00, $cartItem->regular_price);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_can_add_items_with_custom_parameters()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -92,7 +94,7 @@ class CartTest extends TestCase
|
|||
$this->assertEquals('Custom text', $cartItem->parameters['engraving']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_total_sums_all_items()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -111,7 +113,7 @@ class CartTest extends TestCase
|
|||
$this->assertEquals(200.00, $total);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_tracks_last_activity()
|
||||
{
|
||||
$cart = Cart::create([
|
||||
|
|
@ -122,7 +124,7 @@ class CartTest extends TestCase
|
|||
$this->assertTrue($cart->last_activity_at->isPast());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_can_be_converted()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -134,7 +136,7 @@ class CartTest extends TestCase
|
|||
$this->assertTrue($cart->fresh()->isConverted());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function active_scope_filters_correctly()
|
||||
{
|
||||
// Active cart (not expired, not converted)
|
||||
|
|
@ -166,7 +168,7 @@ class CartTest extends TestCase
|
|||
$this->assertCount(2, $active);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_deletes_items_on_deletion()
|
||||
{
|
||||
$cart = Cart::create();
|
||||
|
|
@ -183,7 +185,7 @@ class CartTest extends TestCase
|
|||
$this->assertDatabaseMissing('cart_items', ['id' => $cartItemId]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_can_have_currency()
|
||||
{
|
||||
$cart = Cart::create([
|
||||
|
|
@ -193,7 +195,7 @@ class CartTest extends TestCase
|
|||
$this->assertEquals('EUR', $cart->currency);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_can_have_status()
|
||||
{
|
||||
$cart = Cart::create([
|
||||
|
|
@ -207,7 +209,7 @@ class CartTest extends TestCase
|
|||
$this->assertEquals(CartStatus::CONVERTED, $cart->fresh()->status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_can_store_metadata()
|
||||
{
|
||||
$cart = Cart::create([
|
||||
|
|
@ -221,7 +223,7 @@ class CartTest extends TestCase
|
|||
$this->assertEquals('Gift wrapped', $cart->meta->notes);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function cart_can_have_session_id()
|
||||
{
|
||||
$sessionId = 'sess_' . str()->random(40);
|
||||
|
|
@ -233,7 +235,7 @@ class CartTest extends TestCase
|
|||
$this->assertEquals($sessionId, $cart->session_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_session_link_throws_when_stripe_disabled()
|
||||
{
|
||||
config(['shop.stripe.enabled' => false]);
|
||||
|
|
@ -245,7 +247,7 @@ class CartTest extends TestCase
|
|||
$cart->checkoutSessionLink();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_session_link_throws_when_cart_empty()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
@ -257,7 +259,7 @@ class CartTest extends TestCase
|
|||
$cart->checkoutSessionLink();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_session_link_throws_when_cart_empty_even_with_meta()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
@ -271,7 +273,7 @@ class CartTest extends TestCase
|
|||
$cart->checkoutSessionLink();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_session_link_returns_false_on_stripe_error()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
@ -292,7 +294,7 @@ class CartTest extends TestCase
|
|||
$this->assertNotNull($returnType);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_session_link_returns_null_when_session_not_found()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
@ -307,7 +309,7 @@ class CartTest extends TestCase
|
|||
$this->assertTrue(method_exists($cart, 'checkoutSessionLink'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_session_link_handles_meta_as_array()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
@ -320,7 +322,7 @@ class CartTest extends TestCase
|
|||
$this->assertEquals('cs_test_123', $cart->meta->stripe_session_id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function checkout_session_link_handles_meta_as_object()
|
||||
{
|
||||
config(['shop.stripe.enabled' => true]);
|
||||
|
|
|
|||
|
|
@ -3,14 +3,15 @@
|
|||
namespace Blax\Shop\Tests\Unit;
|
||||
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\CartItem;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Carbon\Carbon;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
|
||||
class HtmlDateTimeCastTest extends TestCase
|
||||
{
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_accepts_carbon_instance_and_stores_as_timestamp()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
@ -27,7 +28,7 @@ class HtmlDateTimeCastTest extends TestCase
|
|||
$this->assertEquals('2025-12-25 14:30:00', $cart->from->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_accepts_datetime_interface_and_stores_as_timestamp()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
@ -42,7 +43,7 @@ class HtmlDateTimeCastTest extends TestCase
|
|||
$this->assertEquals('2025-12-25 14:30:00', $cart->from->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_accepts_string_and_stores_as_timestamp()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
@ -57,7 +58,7 @@ class HtmlDateTimeCastTest extends TestCase
|
|||
$this->assertEquals('2025-12-25 14:30:00', $cart->from->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_accepts_html5_datetime_local_format()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
@ -72,7 +73,7 @@ class HtmlDateTimeCastTest extends TestCase
|
|||
$this->assertEquals('2025-12-25 14:30:00', $cart->from->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_format_for_html5_input()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
@ -86,7 +87,7 @@ class HtmlDateTimeCastTest extends TestCase
|
|||
$this->assertEquals('2025-12-25T14:30', $htmlFormat);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_handles_null_values()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
@ -98,7 +99,7 @@ class HtmlDateTimeCastTest extends TestCase
|
|||
$this->assertNull($cart->from);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_works_with_cart_items()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -122,7 +123,7 @@ class HtmlDateTimeCastTest extends TestCase
|
|||
$this->assertEquals('2025-12-27T10:00', $item->until->format('Y-m-d\TH:i'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_accepts_unix_timestamp()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
@ -137,7 +138,7 @@ class HtmlDateTimeCastTest extends TestCase
|
|||
$this->assertEquals('2025-12-25 14:30:00', $cart->from->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_maintains_carbon_methods()
|
||||
{
|
||||
$cart = Cart::factory()->create();
|
||||
|
|
|
|||
|
|
@ -5,12 +5,14 @@ namespace Blax\Shop\Tests\Unit;
|
|||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
|
||||
class ProductPricingTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_regular_price_when_not_on_sale()
|
||||
{
|
||||
$product = Product::factory()->withPrices(2, 100)->create();
|
||||
|
|
@ -21,7 +23,7 @@ class ProductPricingTest extends TestCase
|
|||
$this->assertEquals(100, $product->getCurrentPrice());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_sale_price_when_on_sale()
|
||||
{
|
||||
$product = Product::factory()
|
||||
|
|
@ -39,7 +41,7 @@ class ProductPricingTest extends TestCase
|
|||
$this->assertEquals(80, $product->getCurrentPrice());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_regular_price_when_sale_has_ended()
|
||||
{
|
||||
$product = Product::factory()->withPrices(1, 100)->create([
|
||||
|
|
@ -60,7 +62,7 @@ class ProductPricingTest extends TestCase
|
|||
$this->assertEquals(100, $product->getCurrentPrice());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_returns_regular_price_when_sale_hasnt_started()
|
||||
{
|
||||
$product = Product::factory()->withPrices(1, 100)->create([
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@ use Blax\Shop\Enums\ProductRelationType;
|
|||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class ProductRelationsTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_filters_relations_by_relation_type()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -41,7 +42,7 @@ class ProductRelationsTest extends TestCase
|
|||
$this->assertSame(1, $product->relatedProducts()->first()->pivot->sort_order);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function relations_by_type_accepts_enum_or_string()
|
||||
{
|
||||
$product = Product::factory()->create();
|
||||
|
|
@ -55,7 +56,7 @@ class ProductRelationsTest extends TestCase
|
|||
$this->assertTrue($product->relationsByType('related')->exists());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_can_be_queried_by_specific_relation_types()
|
||||
{
|
||||
$withUpsell = Product::factory()->create();
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ namespace Blax\Shop\Tests\Unit;
|
|||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
class StockManagementTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_detects_low_stock()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -22,7 +23,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertTrue($product->isLowStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_detects_sufficient_stock()
|
||||
{
|
||||
$product = Product::factory()->withStocks(50)->create([
|
||||
|
|
@ -32,7 +33,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertFalse($product->isLowStock());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function it_marks_product_as_out_of_stock()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
@ -46,7 +47,7 @@ class StockManagementTest extends TestCase
|
|||
$this->assertEquals('outofstock', $product->stock_status);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
#[Test]
|
||||
public function products_without_stock_management_are_always_in_stock()
|
||||
{
|
||||
$product = Product::factory()->create([
|
||||
|
|
|
|||
Loading…
Reference in New Issue