You've already forked wc-composable-product
Add PHPUnit test suite, PSR-4 refactor, lint+test CI jobs (v1.3.1)
- 57 unit tests covering ProductType, StockManager, CartHandler, Plugin, Admin/ProductData, Admin/Settings using Brain Monkey + Mockery - WooCommerce class stubs for testing without WP installation - PHP lint and test jobs in release workflow (test gate blocks release) - PSR-4 namespace change: WC_Composable_Product -> Magdev\WcComposableProduct - PascalCase filenames for all classes under includes/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
226
tests/Unit/StockManagerTest.php
Normal file
226
tests/Unit/StockManagerTest.php
Normal file
@@ -0,0 +1,226 @@
|
||||
<?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',
|
||||
[]
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user