test(catalog): cover composed availability restrictions

This commit is contained in:
2026-08-24 14:33:01 -03:00
parent 2fd6851b40
commit a73b628bb4
6 changed files with 80 additions and 49 deletions

View File

@@ -246,7 +246,7 @@ class CartControllerTest extends TestCase
->assertJsonPath('code', 'purchase.limit_exceeded') ->assertJsonPath('code', 'purchase.limit_exceeded')
->assertJsonPath('catalog_item_id', $item->id) ->assertJsonPath('catalog_item_id', $item->id)
->assertJsonPath('catalog_item_name', $item->nombre) ->assertJsonPath('catalog_item_name', $item->nombre)
->assertJsonPath('maximum_addable_quantity', 1) ->assertJsonPath('availability.maximum_quantity', 1)
->assertJsonPath( ->assertJsonPath(
'message', 'message',
"Podés agregar hasta 1 unidad más de “{$item->nombre}”.", "Podés agregar hasta 1 unidad más de “{$item->nombre}”.",

View File

@@ -267,7 +267,7 @@ class BundleCatalogItemTest extends TestCase
$this->getJson("/api/tenants/{$this->tenant->codigo}/catalog-items/{$bundleId}") $this->getJson("/api/tenants/{$this->tenant->codigo}/catalog-items/{$bundleId}")
->assertOk() ->assertOk()
->assertJsonPath('data.type', CatalogItemType::Bundle->value) ->assertJsonPath('data.type', CatalogItemType::Bundle->value)
->assertJsonPath('data.maximum_addable_quantity', 4) ->assertJsonPath('data.availability.maximum_quantity', 4)
->assertJsonMissingPath('data.stock_tecnico') ->assertJsonMissingPath('data.stock_tecnico')
->assertJsonCount(1, 'data.components') ->assertJsonCount(1, 'data.components')
->assertJsonPath('data.components.0.catalog_item_id', $component->id) ->assertJsonPath('data.components.0.catalog_item_id', $component->id)

View File

@@ -72,18 +72,26 @@ class CatalogControllerTest extends TestCase
->assertJsonPath('0.items.0.nombre', 'Variants') ->assertJsonPath('0.items.0.nombre', 'Variants')
->assertJsonPath('0.items.0.descripcion', 'Variants description') ->assertJsonPath('0.items.0.descripcion', 'Variants description')
->assertJsonPath('0.items.0.precio', '100.00') ->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') ->assertJsonCount(3, '0.items.0.variants')
->assertJsonPath('0.items.0.variants.0.maximum_addable_quantity', 4) ->assertJsonPath('0.items.0.variants.0.availability.maximum_quantity', 4)
->assertJsonPath('0.items.0.variants.1.maximum_addable_quantity', 3) ->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.id', $unavailableVariant->id)
->assertJsonPath('0.items.0.variants.2.maximum_addable_quantity', 0) ->assertJsonPath('0.items.0.variants.2.availability.maximum_quantity', 0)
->assertJsonPath( ->assertJsonPath(
'0.items.0.variants.2.unavailable_message', '0.items.0.variants.2.availability.restrictions.0.message',
'Este producto no tiene stock disponible.', '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.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') ->assertJsonMissingPath('1.items.data.0.stock_tecnico')
->assertJsonCount(0, '1.items.data.0.variants'); ->assertJsonCount(0, '1.items.data.0.variants');
} }
@@ -119,16 +127,20 @@ class CatalogControllerTest extends TestCase
$this->actingAs($user, 'sanctum') $this->actingAs($user, 'sanctum')
->getJson("/api/tenants/{$tenant->codigo}/catalog") ->getJson("/api/tenants/{$tenant->codigo}/catalog")
->assertOk() ->assertOk()
->assertJsonPath('0.items.0.variants.0.maximum_addable_quantity', 0) ->assertJsonPath('0.items.0.variants.0.availability.maximum_quantity', 0)
->assertJsonPath('0.items.0.variants.1.maximum_addable_quantity', 0) ->assertJsonPath('0.items.0.variants.1.availability.maximum_quantity', 0)
->assertJsonPath( ->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.', 'Alcanzaste el cupo máximo permitido para este producto.',
) )
->assertJsonPath( ->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.', '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.0.stock_tecnico')
->assertJsonMissingPath('0.items.0.variants.1.stock_tecnico'); ->assertJsonMissingPath('0.items.0.variants.1.stock_tecnico');
} }
@@ -163,13 +175,13 @@ class CatalogControllerTest extends TestCase
->assertOk() ->assertOk()
->assertJsonCount(2, '0.items') ->assertJsonCount(2, '0.items')
->assertJsonPath('0.items.0.nombre', 'Unavailable') ->assertJsonPath('0.items.0.nombre', 'Unavailable')
->assertJsonPath('0.items.0.maximum_addable_quantity', 0) ->assertJsonPath('0.items.0.availability.maximum_quantity', 0)
->assertJsonPath( ->assertJsonPath(
'0.items.0.unavailable_message', '0.items.0.availability.restrictions.0.message',
'Este producto no tiene stock disponible.', 'Este producto no tiene stock disponible.',
) )
->assertJsonPath('0.items.1.nombre', 'Available') ->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 public function test_column_with_image_uses_item_image_then_variant_image_then_null(): void

View File

@@ -40,7 +40,7 @@ class CatalogItemDetailControllerTest extends TestCase
$response $response
->assertOk() ->assertOk()
->assertJsonPath('data.maximum_addable_quantity', 7) ->assertJsonPath('data.availability.maximum_quantity', 7)
->assertJsonMissingPath('data.stock_tecnico') ->assertJsonMissingPath('data.stock_tecnico')
->assertJsonCount(0, 'data.variants') ->assertJsonCount(0, 'data.variants')
->assertJsonCount(1, 'data.images'); ->assertJsonCount(1, 'data.images');
@@ -71,14 +71,14 @@ class CatalogItemDetailControllerTest extends TestCase
->assertOk() ->assertOk()
->assertJsonCount(2, 'data.variants') ->assertJsonCount(2, 'data.variants')
->assertJsonPath('data.variants.0.id', $firstVariant->id) ->assertJsonPath('data.variants.0.id', $firstVariant->id)
->assertJsonPath('data.variants.0.maximum_addable_quantity', 0) ->assertJsonPath('data.variants.0.availability.maximum_quantity', 0)
->assertJsonPath( ->assertJsonPath(
'data.variants.0.unavailable_message', 'data.variants.0.availability.restrictions.0.message',
'Este producto no tiene stock disponible.', 'Este producto no tiene stock disponible.',
) )
->assertJsonPath('data.variants.1.id', $secondVariant->id) ->assertJsonPath('data.variants.1.id', $secondVariant->id)
->assertJsonPath('data.selected_variant.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') ->assertJsonMissingPath('data.selected_variant.stock_tecnico')
->assertJsonCount(1, 'data.selected_variant.images'); ->assertJsonCount(1, 'data.selected_variant.images');
$response $response
@@ -133,11 +133,11 @@ class CatalogItemDetailControllerTest extends TestCase
$response $response
->assertOk() ->assertOk()
->assertJsonPath('data.variants.0.id', $firstVariant->id) ->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.value', 'S')
->assertJsonPath('data.variants.0.values.size.label', 'Small') ->assertJsonPath('data.variants.0.values.size.label', 'Small')
->assertJsonPath('data.variants.1.id', $secondVariant->id) ->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.value', 'M')
->assertJsonPath('data.variants.1.values.size.label', 'Medium') ->assertJsonPath('data.variants.1.values.size.label', 'Medium')
->assertJsonPath('data.attributes.0.codigo', 'size') ->assertJsonPath('data.attributes.0.codigo', 'size')
@@ -145,7 +145,7 @@ class CatalogItemDetailControllerTest extends TestCase
->assertJsonPath('data.attributes.0.options.1.value', 'M') ->assertJsonPath('data.attributes.0.options.1.value', 'M')
->assertJsonCount(2, 'data.attributes.0.options') ->assertJsonCount(2, 'data.attributes.0.options')
->assertJsonPath('data.selected_variant.id', $secondVariant->id) ->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.value', 'M')
->assertJsonPath('data.selected_variant.values.size.label', 'Medium') ->assertJsonPath('data.selected_variant.values.size.label', 'Medium')
->assertJsonCount(1, 'data.selected_variant.images'); ->assertJsonCount(1, 'data.selected_variant.images');
@@ -185,9 +185,9 @@ class CatalogItemDetailControllerTest extends TestCase
$this->getJson("/api/tenants/{$tenant->codigo}/catalog-items/{$item->id}") $this->getJson("/api/tenants/{$tenant->codigo}/catalog-items/{$item->id}")
->assertOk() ->assertOk()
->assertJsonPath('data.selected_variant.id', $variant->id) ->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') ->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.selected_variant.stock_tecnico')
->assertJsonMissingPath('data.variants.0.stock_tecnico'); ->assertJsonMissingPath('data.variants.0.stock_tecnico');
} }

View File

@@ -394,7 +394,7 @@ class StorePurchaseTest extends TestCase
->assertJsonPath('code', 'purchase.limit_exceeded') ->assertJsonPath('code', 'purchase.limit_exceeded')
->assertJsonPath('catalog_item_id', $variant->catalog_item_id) ->assertJsonPath('catalog_item_id', $variant->catalog_item_id)
->assertJsonPath('catalog_item_name', $variant->catalogItem->nombre) ->assertJsonPath('catalog_item_name', $variant->catalogItem->nombre)
->assertJsonPath('maximum_addable_quantity', 1); ->assertJsonPath('availability.maximum_quantity', 1);
$this->actingAs($otherUser, 'sanctum') $this->actingAs($otherUser, 'sanctum')
->postJson('/api/tenants/sonder/compras/start-checkout', [ ->postJson('/api/tenants/sonder/compras/start-checkout', [

View File

@@ -3,41 +3,60 @@
namespace Tests\Unit\Catalog; namespace Tests\Unit\Catalog;
use App\Domains\Catalog\Services\CatalogItemAllowanceService; use App\Domains\Catalog\Services\CatalogItemAllowanceService;
use ReflectionClass; use App\Domains\Purchase\Services\UserPurchaseLimitService;
use Mockery;
use Tests\TestCase; use Tests\TestCase;
class CatalogItemAllowanceServiceTest extends TestCase class CatalogItemAllowanceServiceTest extends TestCase
{ {
private CatalogItemAllowanceService $service; public function test_it_composes_stock_and_quota_into_restrictions_and_capabilities(): void
protected function setUp(): void
{ {
parent::setUp(); $service = new CatalogItemAllowanceService(
Mockery::mock(UserPurchaseLimitService::class),
$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),
); );
}
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( $this->assertSame(
'Este producto no tiene stock disponible.', ['user_quota_reached', 'out_of_stock'],
$this->service->unavailableMessage(0, null), 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)); $service = new CatalogItemAllowanceService(
$this->assertNull($this->service->unavailableMessage(null, 1)); Mockery::mock(UserPurchaseLimitService::class),
$this->assertNull($this->service->unavailableMessage(null, null)); );
$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']);
} }
} }