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:
108
tests/Unit/Admin/ProductDataTest.php
Normal file
108
tests/Unit/Admin/ProductDataTest.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* Admin ProductData Tests
|
||||
*
|
||||
* @package Magdev\WcComposableProduct\Tests
|
||||
*/
|
||||
|
||||
namespace Magdev\WcComposableProduct\Tests\Unit\Admin;
|
||||
|
||||
use Magdev\WcComposableProduct\Tests\TestCase;
|
||||
use Magdev\WcComposableProduct\Admin\ProductData;
|
||||
use Brain\Monkey\Functions;
|
||||
|
||||
class ProductDataTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$_POST = [];
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$_POST = [];
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function testConstructor_RegistersExpectedHooks(): void
|
||||
{
|
||||
$productData = new ProductData();
|
||||
|
||||
self::assertNotFalse(has_filter('woocommerce_product_data_tabs', 'Magdev\WcComposableProduct\Admin\ProductData->add_product_data_tab()'));
|
||||
self::assertNotFalse(has_action('woocommerce_product_data_panels', 'Magdev\WcComposableProduct\Admin\ProductData->add_product_data_panel()'));
|
||||
self::assertNotFalse(has_action('woocommerce_process_product_meta_composable', 'Magdev\WcComposableProduct\Admin\ProductData->save_product_data()'));
|
||||
self::assertNotFalse(has_action('woocommerce_product_options_general_product_data', 'Magdev\WcComposableProduct\Admin\ProductData->add_general_fields()'));
|
||||
}
|
||||
|
||||
public function testAddProductDataTab_AddsComposableTab(): void
|
||||
{
|
||||
$productData = new ProductData();
|
||||
$tabs = $productData->add_product_data_tab([]);
|
||||
|
||||
$this->assertArrayHasKey('composable', $tabs);
|
||||
$this->assertSame('composable_product_data', $tabs['composable']['target']);
|
||||
$this->assertContains('show_if_composable', $tabs['composable']['class']);
|
||||
$this->assertSame(21, $tabs['composable']['priority']);
|
||||
}
|
||||
|
||||
public function testSaveProductData_SavesAllFields(): void
|
||||
{
|
||||
$_POST = [
|
||||
'_composable_selection_limit' => '5',
|
||||
'_composable_pricing_mode' => 'fixed',
|
||||
'_composable_include_unpublished' => 'yes',
|
||||
'_composable_criteria_type' => 'tag',
|
||||
'_composable_categories' => ['1', '2'],
|
||||
'_composable_tags' => ['3', '4'],
|
||||
'_composable_skus' => 'SKU-1, SKU-2',
|
||||
];
|
||||
|
||||
Functions\expect('absint')->andReturnUsing(function ($val) {
|
||||
return abs((int) $val);
|
||||
});
|
||||
Functions\expect('sanitize_text_field')->andReturnUsing(function ($val) {
|
||||
return $val;
|
||||
});
|
||||
Functions\expect('sanitize_textarea_field')->andReturnUsing(function ($val) {
|
||||
return $val;
|
||||
});
|
||||
|
||||
Functions\expect('update_post_meta')->times(7);
|
||||
|
||||
$productData = new ProductData();
|
||||
$productData->save_product_data(42);
|
||||
}
|
||||
|
||||
public function testSaveProductData_DefaultsWhenPostEmpty(): void
|
||||
{
|
||||
// No POST data at all
|
||||
Functions\expect('absint')->andReturnUsing(function ($val) {
|
||||
return abs((int) $val);
|
||||
});
|
||||
Functions\expect('sanitize_text_field')->andReturnUsing(function ($val) {
|
||||
return $val;
|
||||
});
|
||||
Functions\expect('sanitize_textarea_field')->andReturnUsing(function ($val) {
|
||||
return $val;
|
||||
});
|
||||
|
||||
Functions\expect('update_post_meta')
|
||||
->with(42, '_composable_selection_limit', \Mockery::any())->once();
|
||||
Functions\expect('update_post_meta')
|
||||
->with(42, '_composable_pricing_mode', '')->once();
|
||||
Functions\expect('update_post_meta')
|
||||
->with(42, '_composable_include_unpublished', '')->once();
|
||||
Functions\expect('update_post_meta')
|
||||
->with(42, '_composable_criteria_type', 'category')->once();
|
||||
Functions\expect('update_post_meta')
|
||||
->with(42, '_composable_categories', [])->once();
|
||||
Functions\expect('update_post_meta')
|
||||
->with(42, '_composable_tags', [])->once();
|
||||
Functions\expect('update_post_meta')
|
||||
->with(42, '_composable_skus', '')->once();
|
||||
|
||||
$productData = new ProductData();
|
||||
$productData->save_product_data(42);
|
||||
}
|
||||
}
|
||||
84
tests/Unit/Admin/SettingsTest.php
Normal file
84
tests/Unit/Admin/SettingsTest.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/**
|
||||
* Admin Settings Tests
|
||||
*
|
||||
* @package Magdev\WcComposableProduct\Tests
|
||||
*/
|
||||
|
||||
namespace Magdev\WcComposableProduct\Tests\Unit\Admin;
|
||||
|
||||
use Magdev\WcComposableProduct\Tests\TestCase;
|
||||
use Magdev\WcComposableProduct\Admin\Settings;
|
||||
use Brain\Monkey\Functions;
|
||||
|
||||
class SettingsTest extends TestCase
|
||||
{
|
||||
public function testConstructor_SetsIdAndLabel(): void
|
||||
{
|
||||
$settings = new Settings();
|
||||
|
||||
$this->assertSame('composable_products', $settings->get_id());
|
||||
}
|
||||
|
||||
public function testGetSettings_ReturnsExpectedFieldIds(): void
|
||||
{
|
||||
Functions\expect('apply_filters')
|
||||
->once()
|
||||
->with('wc_composable_settings', \Mockery::type('array'))
|
||||
->andReturnUsing(function ($hook, $settings) {
|
||||
return $settings;
|
||||
});
|
||||
|
||||
$settings = new Settings();
|
||||
$fields = $settings->get_settings();
|
||||
|
||||
// Extract all field IDs
|
||||
$ids = array_column($fields, 'id');
|
||||
|
||||
$this->assertContains('wc_composable_settings', $ids);
|
||||
$this->assertContains('wc_composable_default_limit', $ids);
|
||||
$this->assertContains('wc_composable_default_pricing', $ids);
|
||||
$this->assertContains('wc_composable_include_unpublished', $ids);
|
||||
$this->assertContains('wc_composable_show_images', $ids);
|
||||
$this->assertContains('wc_composable_show_prices', $ids);
|
||||
$this->assertContains('wc_composable_show_total', $ids);
|
||||
}
|
||||
|
||||
public function testGetSettings_HasCorrectFieldTypes(): void
|
||||
{
|
||||
Functions\expect('apply_filters')
|
||||
->once()
|
||||
->andReturnUsing(function ($hook, $settings) {
|
||||
return $settings;
|
||||
});
|
||||
|
||||
$settings = new Settings();
|
||||
$fields = $settings->get_settings();
|
||||
|
||||
// Index fields by ID for easy lookup
|
||||
$indexed = [];
|
||||
foreach ($fields as $field) {
|
||||
if (isset($field['id'])) {
|
||||
$indexed[$field['id']] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertSame('number', $indexed['wc_composable_default_limit']['type']);
|
||||
$this->assertSame('select', $indexed['wc_composable_default_pricing']['type']);
|
||||
$this->assertSame('checkbox', $indexed['wc_composable_include_unpublished']['type']);
|
||||
$this->assertSame('checkbox', $indexed['wc_composable_show_images']['type']);
|
||||
}
|
||||
|
||||
public function testGetSettings_AppliesFilter(): void
|
||||
{
|
||||
Functions\expect('apply_filters')
|
||||
->once()
|
||||
->with('wc_composable_settings', \Mockery::type('array'))
|
||||
->andReturnUsing(function ($hook, $settings) {
|
||||
return $settings;
|
||||
});
|
||||
|
||||
$settings = new Settings();
|
||||
$settings->get_settings();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user