You've already forked wc-composable-product
227 lines
7.2 KiB
PHP
227 lines
7.2 KiB
PHP
|
|
<?php
|
||
|
|
/**
|
||
|
|
* StockManager Tests
|
||
|
|
*
|
||
|
|
* @package Magdev\WcComposableProduct\Tests
|
||
|
|
*/
|
||
|
|
|
||
|
|
namespace Magdev\WcComposableProduct\Tests\Unit;
|
||
|
|
|
||
|
|
use Magdev\WcComposableProduct\Tests\TestCase;
|
||
|
|
use Magdev\WcComposableProduct\StockManager;
|
||
|
|
use Brain\Monkey\Functions;
|
||
|
|
|
||
|
|
class StockManagerTest extends TestCase
|
||
|
|
{
|
||
|
|
private StockManager $manager;
|
||
|
|
|
||
|
|
protected function setUp(): void
|
||
|
|
{
|
||
|
|
parent::setUp();
|
||
|
|
$this->manager = new StockManager();
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- validate_stock_availability ---
|
||
|
|
|
||
|
|
public function testValidateStock_ReturnsTrueWhenAllInStock(): void
|
||
|
|
{
|
||
|
|
$mock = $this->createProductMock([
|
||
|
|
'managing_stock' => false,
|
||
|
|
'is_in_stock' => true,
|
||
|
|
]);
|
||
|
|
|
||
|
|
Functions\expect('wc_get_product')->with(1)->andReturn($mock);
|
||
|
|
Functions\expect('wc_get_product')->with(2)->andReturn($mock);
|
||
|
|
|
||
|
|
$result = $this->manager->validate_stock_availability([1, 2]);
|
||
|
|
$this->assertTrue($result);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testValidateStock_ReturnsTrueWhenNotManagingStock(): void
|
||
|
|
{
|
||
|
|
$mock = $this->createProductMock(['managing_stock' => false]);
|
||
|
|
|
||
|
|
Functions\expect('wc_get_product')->with(1)->andReturn($mock);
|
||
|
|
|
||
|
|
$result = $this->manager->validate_stock_availability([1]);
|
||
|
|
$this->assertTrue($result);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testValidateStock_ReturnsErrorForOutOfStock(): void
|
||
|
|
{
|
||
|
|
$mock = $this->createProductMock([
|
||
|
|
'managing_stock' => true,
|
||
|
|
'is_in_stock' => false,
|
||
|
|
'get_name' => 'Widget',
|
||
|
|
]);
|
||
|
|
|
||
|
|
Functions\expect('wc_get_product')->with(1)->andReturn($mock);
|
||
|
|
|
||
|
|
$result = $this->manager->validate_stock_availability([1]);
|
||
|
|
$this->assertIsString($result);
|
||
|
|
$this->assertStringContainsString('Widget', $result);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testValidateStock_ReturnsErrorForInsufficientQuantity(): void
|
||
|
|
{
|
||
|
|
$mock = $this->createProductMock([
|
||
|
|
'managing_stock' => true,
|
||
|
|
'is_in_stock' => true,
|
||
|
|
'get_stock_quantity' => 1,
|
||
|
|
'get_name' => 'Widget',
|
||
|
|
'backorders_allowed' => false,
|
||
|
|
]);
|
||
|
|
|
||
|
|
Functions\expect('wc_get_product')->with(1)->andReturn($mock);
|
||
|
|
|
||
|
|
$result = $this->manager->validate_stock_availability([1], 5);
|
||
|
|
$this->assertIsString($result);
|
||
|
|
$this->assertStringContainsString('Widget', $result);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testValidateStock_PassesWhenBackordersAllowed(): void
|
||
|
|
{
|
||
|
|
// When stock_quantity is null the insufficient-stock check is skipped,
|
||
|
|
// and the backorders_allowed() branch is reached.
|
||
|
|
$mock = $this->createProductMock([
|
||
|
|
'managing_stock' => true,
|
||
|
|
'is_in_stock' => true,
|
||
|
|
'get_stock_quantity' => null,
|
||
|
|
'backorders_allowed' => true,
|
||
|
|
]);
|
||
|
|
|
||
|
|
Functions\expect('wc_get_product')->with(1)->andReturn($mock);
|
||
|
|
|
||
|
|
$result = $this->manager->validate_stock_availability([1], 5);
|
||
|
|
$this->assertTrue($result);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testValidateStock_SkipsNullProducts(): void
|
||
|
|
{
|
||
|
|
Functions\expect('wc_get_product')->with(999)->andReturn(false);
|
||
|
|
|
||
|
|
$result = $this->manager->validate_stock_availability([999]);
|
||
|
|
$this->assertTrue($result);
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- get_product_stock_info ---
|
||
|
|
|
||
|
|
public function testGetProductStockInfo_ReturnsCorrectStructure(): void
|
||
|
|
{
|
||
|
|
$mock = $this->createProductMock([
|
||
|
|
'is_in_stock' => true,
|
||
|
|
'get_stock_quantity' => 10,
|
||
|
|
'backorders_allowed' => false,
|
||
|
|
'get_stock_status' => 'instock',
|
||
|
|
'managing_stock' => true,
|
||
|
|
]);
|
||
|
|
|
||
|
|
Functions\expect('wc_get_product')->with(1)->andReturn($mock);
|
||
|
|
|
||
|
|
$info = $this->manager->get_product_stock_info(1);
|
||
|
|
|
||
|
|
$this->assertTrue($info['in_stock']);
|
||
|
|
$this->assertSame(10, $info['stock_quantity']);
|
||
|
|
$this->assertFalse($info['backorders_allowed']);
|
||
|
|
$this->assertSame('instock', $info['stock_status']);
|
||
|
|
$this->assertTrue($info['managing_stock']);
|
||
|
|
$this->assertTrue($info['has_enough_stock']);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testGetProductStockInfo_ReturnsFallbackForInvalidProduct(): void
|
||
|
|
{
|
||
|
|
Functions\expect('wc_get_product')->with(999)->andReturn(false);
|
||
|
|
|
||
|
|
$info = $this->manager->get_product_stock_info(999);
|
||
|
|
|
||
|
|
$this->assertFalse($info['in_stock']);
|
||
|
|
$this->assertSame(0, $info['stock_quantity']);
|
||
|
|
$this->assertFalse($info['backorders_allowed']);
|
||
|
|
$this->assertSame('outofstock', $info['stock_status']);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testGetProductStockInfo_HasEnoughStockTrueWhenNotManaging(): void
|
||
|
|
{
|
||
|
|
$mock = $this->createProductMock([
|
||
|
|
'managing_stock' => false,
|
||
|
|
'get_stock_quantity' => null,
|
||
|
|
]);
|
||
|
|
|
||
|
|
Functions\expect('wc_get_product')->with(1)->andReturn($mock);
|
||
|
|
|
||
|
|
$info = $this->manager->get_product_stock_info(1, 100);
|
||
|
|
$this->assertTrue($info['has_enough_stock']);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testGetProductStockInfo_HasEnoughStockFalseWhenInsufficient(): void
|
||
|
|
{
|
||
|
|
$mock = $this->createProductMock([
|
||
|
|
'managing_stock' => true,
|
||
|
|
'get_stock_quantity' => 2,
|
||
|
|
]);
|
||
|
|
|
||
|
|
Functions\expect('wc_get_product')->with(1)->andReturn($mock);
|
||
|
|
|
||
|
|
$info = $this->manager->get_product_stock_info(1, 5);
|
||
|
|
$this->assertFalse($info['has_enough_stock']);
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- prevent_composable_stock_reduction ---
|
||
|
|
|
||
|
|
public function testPreventStockReduction_ReturnsFalseForComposableItem(): void
|
||
|
|
{
|
||
|
|
$productMock = $this->createProductMock(['get_type' => 'composable']);
|
||
|
|
|
||
|
|
$itemMock = \Mockery::mock('WC_Order_Item_Product');
|
||
|
|
$itemMock->shouldReceive('get_product')->andReturn($productMock);
|
||
|
|
|
||
|
|
$orderMock = \Mockery::mock('WC_Order');
|
||
|
|
$orderMock->shouldReceive('get_items')->andReturn([$itemMock]);
|
||
|
|
|
||
|
|
$result = $this->manager->prevent_composable_stock_reduction(true, $orderMock);
|
||
|
|
$this->assertFalse($result);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testPreventStockReduction_PassesThroughForNonComposable(): void
|
||
|
|
{
|
||
|
|
$productMock = $this->createProductMock(['get_type' => 'simple']);
|
||
|
|
|
||
|
|
$itemMock = \Mockery::mock('WC_Order_Item_Product');
|
||
|
|
$itemMock->shouldReceive('get_product')->andReturn($productMock);
|
||
|
|
|
||
|
|
$orderMock = \Mockery::mock('WC_Order');
|
||
|
|
$orderMock->shouldReceive('get_items')->andReturn([$itemMock]);
|
||
|
|
|
||
|
|
$result = $this->manager->prevent_composable_stock_reduction(true, $orderMock);
|
||
|
|
$this->assertTrue($result);
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- store_selected_products_in_order ---
|
||
|
|
|
||
|
|
public function testStoreSelectedProducts_AddsMetaWhenPresent(): void
|
||
|
|
{
|
||
|
|
$itemMock = \Mockery::mock('WC_Order_Item_Product');
|
||
|
|
$itemMock->shouldReceive('add_meta_data')
|
||
|
|
->once()
|
||
|
|
->with('_composable_products', [1, 2], true);
|
||
|
|
|
||
|
|
$this->manager->store_selected_products_in_order(
|
||
|
|
$itemMock,
|
||
|
|
'cart_key',
|
||
|
|
['composable_products' => [1, 2]]
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testStoreSelectedProducts_DoesNothingWithoutData(): void
|
||
|
|
{
|
||
|
|
$itemMock = \Mockery::mock('WC_Order_Item_Product');
|
||
|
|
$itemMock->shouldNotReceive('add_meta_data');
|
||
|
|
|
||
|
|
$this->manager->store_selected_products_in_order(
|
||
|
|
$itemMock,
|
||
|
|
'cart_key',
|
||
|
|
[]
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|