From a73b628bb4dd48ccbf180a4fe44732db7855d397 Mon Sep 17 00:00:00 2001 From: ncoronel Date: Mon, 24 Aug 2026 14:33:01 -0300 Subject: [PATCH] test(catalog): cover composed availability restrictions --- tests/Feature/Cart/CartControllerTest.php | 2 +- .../Feature/Catalog/BundleCatalogItemTest.php | 2 +- .../Feature/Catalog/CatalogControllerTest.php | 38 +++++++---- .../CatalogItemDetailControllerTest.php | 18 ++--- tests/Feature/Purchase/StorePurchaseTest.php | 2 +- .../CatalogItemAllowanceServiceTest.php | 67 ++++++++++++------- 6 files changed, 80 insertions(+), 49 deletions(-) diff --git a/tests/Feature/Cart/CartControllerTest.php b/tests/Feature/Cart/CartControllerTest.php index 69e738d..24eb0f4 100644 --- a/tests/Feature/Cart/CartControllerTest.php +++ b/tests/Feature/Cart/CartControllerTest.php @@ -246,7 +246,7 @@ class CartControllerTest extends TestCase ->assertJsonPath('code', 'purchase.limit_exceeded') ->assertJsonPath('catalog_item_id', $item->id) ->assertJsonPath('catalog_item_name', $item->nombre) - ->assertJsonPath('maximum_addable_quantity', 1) + ->assertJsonPath('availability.maximum_quantity', 1) ->assertJsonPath( 'message', "Podés agregar hasta 1 unidad más de “{$item->nombre}”.", diff --git a/tests/Feature/Catalog/BundleCatalogItemTest.php b/tests/Feature/Catalog/BundleCatalogItemTest.php index e1e80c5..a728408 100644 --- a/tests/Feature/Catalog/BundleCatalogItemTest.php +++ b/tests/Feature/Catalog/BundleCatalogItemTest.php @@ -267,7 +267,7 @@ class BundleCatalogItemTest extends TestCase $this->getJson("/api/tenants/{$this->tenant->codigo}/catalog-items/{$bundleId}") ->assertOk() ->assertJsonPath('data.type', CatalogItemType::Bundle->value) - ->assertJsonPath('data.maximum_addable_quantity', 4) + ->assertJsonPath('data.availability.maximum_quantity', 4) ->assertJsonMissingPath('data.stock_tecnico') ->assertJsonCount(1, 'data.components') ->assertJsonPath('data.components.0.catalog_item_id', $component->id) diff --git a/tests/Feature/Catalog/CatalogControllerTest.php b/tests/Feature/Catalog/CatalogControllerTest.php index cdc98d2..847bd86 100644 --- a/tests/Feature/Catalog/CatalogControllerTest.php +++ b/tests/Feature/Catalog/CatalogControllerTest.php @@ -72,18 +72,26 @@ class CatalogControllerTest extends TestCase ->assertJsonPath('0.items.0.nombre', 'Variants') ->assertJsonPath('0.items.0.descripcion', 'Variants description') ->assertJsonPath('0.items.0.precio', '100.00') - ->assertJsonPath('0.items.0.maximum_addable_quantity', 7) + ->assertJsonPath('0.items.0.availability.maximum_quantity', 7) ->assertJsonCount(3, '0.items.0.variants') - ->assertJsonPath('0.items.0.variants.0.maximum_addable_quantity', 4) - ->assertJsonPath('0.items.0.variants.1.maximum_addable_quantity', 3) + ->assertJsonPath('0.items.0.variants.0.availability.maximum_quantity', 4) + ->assertJsonPath('0.items.0.variants.1.availability.maximum_quantity', 3) ->assertJsonPath('0.items.0.variants.2.id', $unavailableVariant->id) - ->assertJsonPath('0.items.0.variants.2.maximum_addable_quantity', 0) + ->assertJsonPath('0.items.0.variants.2.availability.maximum_quantity', 0) ->assertJsonPath( - '0.items.0.variants.2.unavailable_message', + '0.items.0.variants.2.availability.restrictions.0.message', 'Este producto no tiene stock disponible.', ) + ->assertJsonPath( + '0.items.0.variants.2.availability.capabilities.select_variant', + false, + ) + ->assertJsonPath( + '0.items.0.variants.2.availability.capabilities.add_to_cart', + false, + ) ->assertJsonPath('1.title', 'Row') - ->assertJsonPath('1.items.data.0.maximum_addable_quantity', 8) + ->assertJsonPath('1.items.data.0.availability.maximum_quantity', 8) ->assertJsonMissingPath('1.items.data.0.stock_tecnico') ->assertJsonCount(0, '1.items.data.0.variants'); } @@ -119,16 +127,20 @@ class CatalogControllerTest extends TestCase $this->actingAs($user, 'sanctum') ->getJson("/api/tenants/{$tenant->codigo}/catalog") ->assertOk() - ->assertJsonPath('0.items.0.variants.0.maximum_addable_quantity', 0) - ->assertJsonPath('0.items.0.variants.1.maximum_addable_quantity', 0) + ->assertJsonPath('0.items.0.variants.0.availability.maximum_quantity', 0) + ->assertJsonPath('0.items.0.variants.1.availability.maximum_quantity', 0) ->assertJsonPath( - '0.items.0.variants.0.unavailable_message', + '0.items.0.variants.0.availability.restrictions.0.message', 'Alcanzaste el cupo máximo permitido para este producto.', ) ->assertJsonPath( - '0.items.0.variants.1.unavailable_message', + '0.items.0.variants.1.availability.restrictions.0.message', 'Alcanzaste el cupo máximo permitido para este producto.', ) + ->assertJsonPath( + '0.items.0.variants.1.availability.capabilities.buy_now', + false, + ) ->assertJsonMissingPath('0.items.0.variants.0.stock_tecnico') ->assertJsonMissingPath('0.items.0.variants.1.stock_tecnico'); } @@ -163,13 +175,13 @@ class CatalogControllerTest extends TestCase ->assertOk() ->assertJsonCount(2, '0.items') ->assertJsonPath('0.items.0.nombre', 'Unavailable') - ->assertJsonPath('0.items.0.maximum_addable_quantity', 0) + ->assertJsonPath('0.items.0.availability.maximum_quantity', 0) ->assertJsonPath( - '0.items.0.unavailable_message', + '0.items.0.availability.restrictions.0.message', 'Este producto no tiene stock disponible.', ) ->assertJsonPath('0.items.1.nombre', 'Available') - ->assertJsonPath('0.items.1.unavailable_message', null); + ->assertJsonCount(0, '0.items.1.availability.restrictions'); } public function test_column_with_image_uses_item_image_then_variant_image_then_null(): void diff --git a/tests/Feature/Catalog/CatalogItemDetailControllerTest.php b/tests/Feature/Catalog/CatalogItemDetailControllerTest.php index 816cd99..40ca24e 100644 --- a/tests/Feature/Catalog/CatalogItemDetailControllerTest.php +++ b/tests/Feature/Catalog/CatalogItemDetailControllerTest.php @@ -40,7 +40,7 @@ class CatalogItemDetailControllerTest extends TestCase $response ->assertOk() - ->assertJsonPath('data.maximum_addable_quantity', 7) + ->assertJsonPath('data.availability.maximum_quantity', 7) ->assertJsonMissingPath('data.stock_tecnico') ->assertJsonCount(0, 'data.variants') ->assertJsonCount(1, 'data.images'); @@ -71,14 +71,14 @@ class CatalogItemDetailControllerTest extends TestCase ->assertOk() ->assertJsonCount(2, 'data.variants') ->assertJsonPath('data.variants.0.id', $firstVariant->id) - ->assertJsonPath('data.variants.0.maximum_addable_quantity', 0) + ->assertJsonPath('data.variants.0.availability.maximum_quantity', 0) ->assertJsonPath( - 'data.variants.0.unavailable_message', + 'data.variants.0.availability.restrictions.0.message', 'Este producto no tiene stock disponible.', ) ->assertJsonPath('data.variants.1.id', $secondVariant->id) ->assertJsonPath('data.selected_variant.id', $secondVariant->id) - ->assertJsonPath('data.selected_variant.maximum_addable_quantity', 6) + ->assertJsonPath('data.selected_variant.availability.maximum_quantity', 6) ->assertJsonMissingPath('data.selected_variant.stock_tecnico') ->assertJsonCount(1, 'data.selected_variant.images'); $response @@ -133,11 +133,11 @@ class CatalogItemDetailControllerTest extends TestCase $response ->assertOk() ->assertJsonPath('data.variants.0.id', $firstVariant->id) - ->assertJsonPath('data.variants.0.maximum_addable_quantity', 4) + ->assertJsonPath('data.variants.0.availability.maximum_quantity', 4) ->assertJsonPath('data.variants.0.values.size.value', 'S') ->assertJsonPath('data.variants.0.values.size.label', 'Small') ->assertJsonPath('data.variants.1.id', $secondVariant->id) - ->assertJsonPath('data.variants.1.maximum_addable_quantity', 7) + ->assertJsonPath('data.variants.1.availability.maximum_quantity', 7) ->assertJsonPath('data.variants.1.values.size.value', 'M') ->assertJsonPath('data.variants.1.values.size.label', 'Medium') ->assertJsonPath('data.attributes.0.codigo', 'size') @@ -145,7 +145,7 @@ class CatalogItemDetailControllerTest extends TestCase ->assertJsonPath('data.attributes.0.options.1.value', 'M') ->assertJsonCount(2, 'data.attributes.0.options') ->assertJsonPath('data.selected_variant.id', $secondVariant->id) - ->assertJsonPath('data.selected_variant.maximum_addable_quantity', 7) + ->assertJsonPath('data.selected_variant.availability.maximum_quantity', 7) ->assertJsonPath('data.selected_variant.values.size.value', 'M') ->assertJsonPath('data.selected_variant.values.size.label', 'Medium') ->assertJsonCount(1, 'data.selected_variant.images'); @@ -185,9 +185,9 @@ class CatalogItemDetailControllerTest extends TestCase $this->getJson("/api/tenants/{$tenant->codigo}/catalog-items/{$item->id}") ->assertOk() ->assertJsonPath('data.selected_variant.id', $variant->id) - ->assertJsonPath('data.selected_variant.maximum_addable_quantity', null) + ->assertJsonPath('data.selected_variant.availability.maximum_quantity', null) ->assertJsonMissingPath('data.stock_tecnico') - ->assertJsonPath('data.variants.0.maximum_addable_quantity', null) + ->assertJsonPath('data.variants.0.availability.maximum_quantity', null) ->assertJsonMissingPath('data.selected_variant.stock_tecnico') ->assertJsonMissingPath('data.variants.0.stock_tecnico'); } diff --git a/tests/Feature/Purchase/StorePurchaseTest.php b/tests/Feature/Purchase/StorePurchaseTest.php index 91f521a..ee82511 100644 --- a/tests/Feature/Purchase/StorePurchaseTest.php +++ b/tests/Feature/Purchase/StorePurchaseTest.php @@ -394,7 +394,7 @@ class StorePurchaseTest extends TestCase ->assertJsonPath('code', 'purchase.limit_exceeded') ->assertJsonPath('catalog_item_id', $variant->catalog_item_id) ->assertJsonPath('catalog_item_name', $variant->catalogItem->nombre) - ->assertJsonPath('maximum_addable_quantity', 1); + ->assertJsonPath('availability.maximum_quantity', 1); $this->actingAs($otherUser, 'sanctum') ->postJson('/api/tenants/sonder/compras/start-checkout', [ diff --git a/tests/Unit/Catalog/CatalogItemAllowanceServiceTest.php b/tests/Unit/Catalog/CatalogItemAllowanceServiceTest.php index 4d882aa..104966f 100644 --- a/tests/Unit/Catalog/CatalogItemAllowanceServiceTest.php +++ b/tests/Unit/Catalog/CatalogItemAllowanceServiceTest.php @@ -3,41 +3,60 @@ namespace Tests\Unit\Catalog; use App\Domains\Catalog\Services\CatalogItemAllowanceService; -use ReflectionClass; +use App\Domains\Purchase\Services\UserPurchaseLimitService; +use Mockery; use Tests\TestCase; class CatalogItemAllowanceServiceTest extends TestCase { - private CatalogItemAllowanceService $service; - - protected function setUp(): void + public function test_it_composes_stock_and_quota_into_restrictions_and_capabilities(): void { - parent::setUp(); - - $this->service = (new ReflectionClass(CatalogItemAllowanceService::class)) - ->newInstanceWithoutConstructor(); - } - - public function test_it_returns_the_user_quota_message_with_priority_over_stock(): void - { - $this->assertSame( - 'Alcanzaste el cupo máximo permitido para este producto.', - $this->service->unavailableMessage(0, 0), + $service = new CatalogItemAllowanceService( + Mockery::mock(UserPurchaseLimitService::class), ); - } - public function test_it_returns_the_out_of_stock_message(): void - { + $availability = $service->availability(0, 0, 'variant'); + + $this->assertSame(0, $availability['maximum_quantity']); $this->assertSame( - 'Este producto no tiene stock disponible.', - $this->service->unavailableMessage(0, null), + ['user_quota_reached', 'out_of_stock'], + array_column($availability['restrictions'], 'code'), ); + $this->assertSame(['variant', 'variant'], array_column($availability['restrictions'], 'scope')); + $this->assertSame([ + 'select_variant' => false, + 'change_quantity' => false, + 'add_to_cart' => false, + 'buy_now' => false, + ], $availability['capabilities']); } - public function test_it_returns_no_message_when_the_item_is_available(): void + public function test_it_keeps_all_capabilities_when_no_restriction_applies(): void { - $this->assertNull($this->service->unavailableMessage(1, null)); - $this->assertNull($this->service->unavailableMessage(null, 1)); - $this->assertNull($this->service->unavailableMessage(null, null)); + $service = new CatalogItemAllowanceService( + Mockery::mock(UserPurchaseLimitService::class), + ); + + $availability = $service->availability(5, 3); + + $this->assertSame(3, $availability['maximum_quantity']); + $this->assertSame([], $availability['restrictions']); + $this->assertNotContains(false, $availability['capabilities'], true); + } + + public function test_it_describes_a_requested_quantity_that_exceeds_the_remaining_quota(): void + { + $service = new CatalogItemAllowanceService( + Mockery::mock(UserPurchaseLimitService::class), + ); + + $availability = $service->purchaseLimitExceededAvailability(1, 'Solo podés agregar una unidad.'); + + $this->assertSame(1, $availability['maximum_quantity']); + $this->assertSame( + 'requested_quantity_exceeds_user_quota', + $availability['restrictions'][0]['code'], + ); + $this->assertTrue($availability['capabilities']['change_quantity']); } }