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); } }