diff --git a/includes/Admin.php b/includes/Admin.php
index 613ac5d61..e2cc7ba20 100644
--- a/includes/Admin.php
+++ b/includes/Admin.php
@@ -1157,25 +1157,25 @@ public function add_product_settings_tab_content() {
global $post;
// all products have sync enabled unless explicitly disabled
- $sync_enabled = 'no' !== get_post_meta( $post->ID, Products::SYNC_ENABLED_META_KEY, true );
- $visibility = get_post_meta( $post->ID, Products::VISIBILITY_META_KEY, true );
- $is_visible = $visibility ? wc_string_to_bool( $visibility ) : true;
- $product = wc_get_product( $post );
-
- $rich_text_description = get_post_meta( $post->ID, \WC_Facebookcommerce_Integration::FB_RICH_TEXT_DESCRIPTION, true );
- $price = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PRODUCT_PRICE, true );
- $image_source = get_post_meta( $post->ID, Products::PRODUCT_IMAGE_SOURCE_META_KEY, true );
- $image = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PRODUCT_IMAGE, true );
- $video_urls = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PRODUCT_VIDEO, true );
- $fb_brand = get_post_meta( $post->ID, \WC_Facebook_Product::FB_BRAND, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_BRAND, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_brand', true );
- $fb_mpn = get_post_meta( $post->ID, \WC_Facebook_Product::FB_MPN, true );
- $fb_condition = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PRODUCT_CONDITION, true );
- $fb_age_group = get_post_meta( $post->ID, \WC_Facebook_Product::FB_AGE_GROUP, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_AGE_GROUP, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_age_group', true );
- $fb_gender = get_post_meta( $post->ID, \WC_Facebook_Product::FB_GENDER, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_GENDER, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_gender', true );
- $fb_size = get_post_meta( $post->ID, \WC_Facebook_Product::FB_SIZE, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_SIZE, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_size', true );
- $fb_color = get_post_meta( $post->ID, \WC_Facebook_Product::FB_COLOR, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_COLOR, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_color', true );
- $fb_material = get_post_meta( $post->ID, \WC_Facebook_Product::FB_MATERIAL, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_MATERIAL, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_material', true );
- $fb_pattern = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PATTERN, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_PATTERN, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_pattern', true );
+ $sync_enabled = 'no' !== get_post_meta( $post->ID, Products::SYNC_ENABLED_META_KEY, true );
+ $visibility = get_post_meta( $post->ID, Products::VISIBILITY_META_KEY, true );
+ $is_visible = $visibility ? wc_string_to_bool( $visibility ) : true;
+ $product = wc_get_product( $post );
+ $fb_product_description = get_post_meta( $post->ID, \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION, true );
+ $fb_mpn = get_post_meta( $post->ID, \WC_Facebook_Product::FB_MPN, true );
+ $rich_text_description = get_post_meta( $post->ID, \WC_Facebookcommerce_Integration::FB_RICH_TEXT_DESCRIPTION, true );
+ $price = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PRODUCT_PRICE, true );
+ $image_source = get_post_meta( $post->ID, Products::PRODUCT_IMAGE_SOURCE_META_KEY, true );
+ $image = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PRODUCT_IMAGE, true );
+ $video_urls = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PRODUCT_VIDEO, true );
+ $fb_brand = get_post_meta( $post->ID, \WC_Facebook_Product::FB_BRAND, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_BRAND, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_brand', true );
+ $fb_condition = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PRODUCT_CONDITION, true );
+ $fb_age_group = get_post_meta( $post->ID, \WC_Facebook_Product::FB_AGE_GROUP, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_AGE_GROUP, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_age_group', true );
+ $fb_gender = get_post_meta( $post->ID, \WC_Facebook_Product::FB_GENDER, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_GENDER, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_gender', true );
+ $fb_size = get_post_meta( $post->ID, \WC_Facebook_Product::FB_SIZE, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_SIZE, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_size', true );
+ $fb_color = get_post_meta( $post->ID, \WC_Facebook_Product::FB_COLOR, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_COLOR, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_color', true );
+ $fb_material = get_post_meta( $post->ID, \WC_Facebook_Product::FB_MATERIAL, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_MATERIAL, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_material', true );
+ $fb_pattern = get_post_meta( $post->ID, \WC_Facebook_Product::FB_PATTERN, true ) ? get_post_meta( $post->ID, \WC_Facebook_Product::FB_PATTERN, true ) : get_post_meta( $post->ID, '_wc_facebook_enhanced_catalog_attributes_pattern', true );
if ( $sync_enabled ) {
$sync_mode = $is_visible ? self::SYNC_MODE_SYNC_AND_SHOW : self::SYNC_MODE_SYNC_AND_HIDE;
@@ -1189,6 +1189,29 @@ public function add_product_settings_tab_content() {
ID && ( $fb_product_description || $image || $price ) ) {
+ ?>
+
+
+ 'wc_facebook_sync_mode',
@@ -1204,72 +1227,78 @@ public function add_product_settings_tab_content() {
)
);
- echo '
';
- echo '';
- wp_editor(
- $rich_text_description,
- \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION,
- array(
- 'id' => 'wc_facebook_sync_mode',
- 'textarea_name' => \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION,
- 'textarea_rows' => 10,
- 'media_buttons' => true,
- 'teeny' => true,
- 'quicktags' => false,
- 'tinymce' => array(
- 'toolbar1' => 'bold,italic,bullist,spellchecker,fullscreen',
- ),
- )
- );
- echo '
';
-
- woocommerce_wp_radio(
- array(
- 'id' => 'fb_product_image_source',
- 'label' => __( 'Facebook Product Image', 'facebook-for-woocommerce' ),
- 'desc_tip' => true,
- 'description' => __( 'Choose the product image that should be synced to the Facebook catalog and displayed for this product.', 'facebook-for-woocommerce' ),
- 'options' => array(
- Products::PRODUCT_IMAGE_SOURCE_PRODUCT => __( 'Use WooCommerce image', 'facebook-for-woocommerce' ),
- Products::PRODUCT_IMAGE_SOURCE_CUSTOM => __( 'Use custom image', 'facebook-for-woocommerce' ),
- ),
- 'value' => $image_source ? $image_source : Products::PRODUCT_IMAGE_SOURCE_PRODUCT,
- 'class' => 'short enable-if-sync-enabled js-fb-product-image-source',
- 'wrapper_class' => 'fb-product-image-source-field',
- )
- );
+ // Check if this is an existing product with a Facebook description
+ if ( $post->ID && $fb_product_description ) {
+ echo '
';
+ echo '';
+ wp_editor(
+ $rich_text_description,
+ \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION,
+ array(
+ 'id' => 'wc_facebook_sync_mode',
+ 'textarea_name' => \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION,
+ 'textarea_rows' => 10,
+ 'media_buttons' => true,
+ 'teeny' => true,
+ 'quicktags' => false,
+ 'tinymce' => array(
+ 'toolbar1' => 'bold,italic,bullist,spellchecker,fullscreen',
+ ),
+ )
+ );
+ echo '
';
+ }
+ if ( $post->ID && $image ) {
+ woocommerce_wp_radio(
+ array(
+ 'id' => 'fb_product_image_source',
+ 'label' => __( 'Facebook Product Image', 'facebook-for-woocommerce' ),
+ 'desc_tip' => true,
+ 'description' => __( 'Choose the product image that should be synced to the Facebook catalog and displayed for this product.', 'facebook-for-woocommerce' ),
+ 'options' => array(
+ Products::PRODUCT_IMAGE_SOURCE_PRODUCT => __( 'Use WooCommerce image', 'facebook-for-woocommerce' ),
+ Products::PRODUCT_IMAGE_SOURCE_CUSTOM => __( 'Use custom image', 'facebook-for-woocommerce' ),
+ ),
+ 'value' => $image_source ? $image_source : Products::PRODUCT_IMAGE_SOURCE_PRODUCT,
+ 'class' => 'short enable-if-sync-enabled js-fb-product-image-source',
+ 'wrapper_class' => 'fb-product-image-source-field',
+ )
+ );
- woocommerce_wp_text_input(
- array(
- 'id' => \WC_Facebook_Product::FB_PRODUCT_IMAGE,
- 'label' => __( 'Custom Image URL', 'facebook-for-woocommerce' ),
- 'value' => $image,
- 'class' => sprintf( 'enable-if-sync-enabled product-image-source-field show-if-product-image-source-%s', Products::PRODUCT_IMAGE_SOURCE_CUSTOM ),
- 'desc_tip' => true,
- 'description' => __( 'Please enter an absolute URL (e.g. https://domain.com/image.jpg).', 'facebook-for-woocommerce' ),
- )
- );
+ woocommerce_wp_text_input(
+ array(
+ 'id' => \WC_Facebook_Product::FB_PRODUCT_IMAGE,
+ 'label' => __( 'Custom Image URL', 'facebook-for-woocommerce' ),
+ 'value' => $image,
+ 'class' => sprintf( 'enable-if-sync-enabled product-image-source-field show-if-product-image-source-%s', Products::PRODUCT_IMAGE_SOURCE_CUSTOM ),
+ 'desc_tip' => true,
+ 'description' => __( 'Please enter an absolute URL (e.g. https://domain.com/image.jpg).', 'facebook-for-woocommerce' ),
+ )
+ );
+ }
$this->render_facebook_product_video_field( $video_urls );
- woocommerce_wp_text_input(
- array(
- 'id' => \WC_Facebook_Product::FB_PRODUCT_PRICE,
- 'label' => sprintf(
- /* translators: Placeholders %1$s - WC currency symbol */
- __( 'Facebook Price (%1$s)', 'facebook-for-woocommerce' ),
- get_woocommerce_currency_symbol()
- ),
- 'desc_tip' => true,
- 'description' => __( 'Custom price for product on Facebook. Please enter in monetary decimal (.) format without thousand separators and currency symbols. If blank, product price will be used.', 'facebook-for-woocommerce' ),
- 'cols' => 40,
- 'rows' => 60,
- 'value' => $price,
- 'class' => 'enable-if-sync-enabled',
- )
- );
+ if ( $post->ID && $price ) {
+ woocommerce_wp_text_input(
+ array(
+ 'id' => \WC_Facebook_Product::FB_PRODUCT_PRICE,
+ 'label' => sprintf(
+ /* translators: Placeholders %1$s - WC currency symbol */
+ __( 'Facebook Price (%1$s)', 'facebook-for-woocommerce' ),
+ get_woocommerce_currency_symbol()
+ ),
+ 'desc_tip' => true,
+ 'description' => __( 'Custom price for product on Facebook. Please enter in monetary decimal (.) format without thousand separators and currency symbols. If blank, product price will be used.', 'facebook-for-woocommerce' ),
+ 'cols' => 40,
+ 'rows' => 60,
+ 'value' => $price,
+ 'class' => 'enable-if-sync-enabled',
+ )
+ );
+ }
woocommerce_wp_hidden_input(
array(
@@ -1277,7 +1306,7 @@ public function add_product_settings_tab_content() {
'value' => '',
)
);
- ?>
+ ?>
@@ -1480,6 +1509,8 @@ public function add_product_variation_edit_fields( $index, $variation_data, $pos
$image_source = $variation->get_meta( Products::PRODUCT_IMAGE_SOURCE_META_KEY );
$fb_mpn = $this->get_product_variation_meta( $variation, \WC_Facebook_Product::FB_MPN, $parent );
+ $has_fb_specific_variation_fields = ! empty( $description ) || ! empty( $image_url ) || ! empty( $price );
+
if ( $sync_enabled ) {
$sync_mode = $is_visible ? self::SYNC_MODE_SYNC_AND_SHOW : self::SYNC_MODE_SYNC_AND_HIDE;
} else {
@@ -1494,6 +1525,28 @@ public function add_product_variation_edit_fields( $index, $variation_data, $pos
get_id() && $has_fb_specific_variation_fields ) {
+ ?>
+
+
+ get_id() && $has_fb_specific_variation_fields ) {
+ if ( ! empty( $description ) ) {
woocommerce_wp_textarea_input(
array(
'id' => sprintf( 'variable_%s%s', \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION, $index ),
@@ -1525,7 +1581,9 @@ public function add_product_variation_edit_fields( $index, $variation_data, $pos
'wrapper_class' => 'form-row form-row-full',
)
);
+ }
+ if ( ! empty( $image_url ) ) {
woocommerce_wp_radio(
array(
'id' => "variable_fb_product_image_source$index",
@@ -1556,13 +1614,15 @@ public function add_product_variation_edit_fields( $index, $variation_data, $pos
'description' => __( 'Please enter an absolute URL (e.g. https://domain.com/image.jpg).', 'facebook-for-woocommerce' ),
)
);
+ }
+ if ( ! empty( $price ) ) {
woocommerce_wp_text_input(
array(
'id' => sprintf( 'variable_%s%s', \WC_Facebook_Product::FB_PRODUCT_PRICE, $index ),
'name' => sprintf( "variable_%s[$index]", \WC_Facebook_Product::FB_PRODUCT_PRICE ),
'label' => sprintf(
- /* translators: Placeholders %1$s - WC currency symbol */
+ /* translators: Placeholders %1$s - WC currency symbol */
__( 'Facebook Price (%1$s)', 'facebook-for-woocommerce' ),
get_woocommerce_currency_symbol()
),
@@ -1573,20 +1633,23 @@ public function add_product_variation_edit_fields( $index, $variation_data, $pos
'wrapper_class' => 'form-row form-full',
)
);
+ }
+ }
+ // Always show MPN field as it's not deprecated
woocommerce_wp_text_input(
array(
'id' => sprintf( 'variable_%s%s', \WC_Facebook_Product::FB_MPN, $index ),
'name' => sprintf( "variable_%s[$index]", \WC_Facebook_Product::FB_MPN ),
- 'label' => __( 'Manufacturer Parts Number (MPN)', 'facebook-for-woocommerce' ),
+ 'label' => __( 'Manufacturer Part Number (MPN)', 'facebook-for-woocommerce' ),
'desc_tip' => true,
- 'description' => __( 'Manufacturer Parts Number', 'facebook-for-woocommerce' ),
- 'value' => wc_format_decimal( $fb_mpn ),
+ 'description' => __( 'Manufacturer Part Number', 'facebook-for-woocommerce' ),
+ 'value' => $fb_mpn,
'class' => 'enable-if-sync-enabled',
'wrapper_class' => 'form-row form-full',
)
);
- ?>
+ ?>
@@ -1611,10 +1674,9 @@ public function add_product_variation_edit_fields( $index, $variation_data, $pos
.hide();
});
- wc_plugin_dir = WP_PLUGIN_DIR . '/woocommerce';
+ if (!file_exists($this->wc_plugin_dir)) {
+ $this->wc_plugin_dir = dirname(dirname(dirname(__DIR__))) . '/woocommerce';
+ }
+
+ if (!file_exists($this->wc_plugin_dir)) {
+ $this->markTestSkipped('WooCommerce plugin is required for this test.');
+ return;
+ }
+
+ // Include WooCommerce admin functions if not already included
+ if (!function_exists('woocommerce_wp_select')) {
+ require_once $this->wc_plugin_dir . '/includes/admin/wc-admin-functions.php';
+ require_once $this->wc_plugin_dir . '/includes/admin/wc-meta-box-functions.php';
+ }
+
+ // Set up WordPress admin environment
+ set_current_screen('edit-post');
+
+ // Create real Admin instance
+ $this->admin = new Admin();
+
+ // Create a test product
+ $this->product = new \WC_Product_Simple();
+ $this->product->save();
+
+ // Set up the global post
+ $GLOBALS['post'] = get_post($this->product->get_id());
+ }
+
+ public function tearDown(): void {
+ parent::tearDown();
+
+ // Clean up WordPress admin environment
+ set_current_screen('front');
+
+ // Clean up
+ if ($this->product) {
+ $this->product->delete(true);
+ }
+ }
+
+ /**
+ * Test that deprecation notice is not shown for new products
+ */
+ public function test_deprecation_notice_not_shown_for_new_products() {
+ ob_start();
+ $this->admin->add_product_settings_tab_content();
+ $content = ob_get_clean();
+
+ $this->assertStringNotContainsString('notice notice-warning inline is-dismissible', $content);
+ $this->assertStringNotContainsString('Some attributes are no longer supported', $content);
+ }
+
+ /**
+ * Test that deprecation notice is shown when product has Facebook description
+ */
+ public function test_deprecation_notice_shown_with_fb_description() {
+ $this->product->update_meta_data('fb_product_description', 'Test description');
+ $this->product->save();
+
+ ob_start();
+ $this->admin->add_product_settings_tab_content();
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('notice notice-warning inline is-dismissible', $content);
+ $this->assertStringContainsString('Some attributes are no longer supported', $content);
+ $this->assertStringContainsString('Facebook Description, Custom Image URL, and Facebook Price are no longer supported', $content);
+ }
+
+ /**
+ * Test that deprecation notice is shown when product has custom image URL
+ */
+ public function test_deprecation_notice_shown_with_custom_image() {
+ $this->product->update_meta_data('fb_product_image', 'https://example.com/image.jpg');
+ $this->product->save();
+
+ ob_start();
+ $this->admin->add_product_settings_tab_content();
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('notice notice-warning inline is-dismissible', $content);
+ $this->assertStringContainsString('Some attributes are no longer supported', $content);
+ }
+
+ /**
+ * Test that deprecation notice is shown when product has custom price
+ */
+ public function test_deprecation_notice_shown_with_custom_price() {
+ $this->product->update_meta_data('fb_product_price', '99.99');
+ $this->product->save();
+
+ ob_start();
+ $this->admin->add_product_settings_tab_content();
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('notice notice-warning inline is-dismissible', $content);
+ $this->assertStringContainsString('Some attributes are no longer supported', $content);
+ }
+
+ /**
+ * Test that notice dismiss button exists and has correct structure
+ */
+ public function test_deprecation_notice_has_dismiss_button() {
+ $this->product->update_meta_data('fb_product_description', 'Test description');
+ $this->product->save();
+
+ ob_start();
+ $this->admin->add_product_settings_tab_content();
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('button type="button" class="notice-dismiss"', $content);
+ $this->assertStringContainsString('Dismiss this notice', $content);
+ }
+
+ /**
+ * Test that deprecation notice has correct styling
+ */
+ public function test_deprecation_notice_has_correct_styling() {
+ $this->product->update_meta_data('fb_product_description', 'Test description');
+ $this->product->save();
+
+ ob_start();
+ $this->admin->add_product_settings_tab_content();
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('style="padding: 1px 12px; margin: 10px 10px 0; border-left: 4px solid #dba617; background-color: #fff;"', $content);
+ }
+
+ /**
+ * Test that variation notice is not shown when no deprecated fields exist
+ */
+ public function test_variation_notice_not_shown_without_deprecated_fields() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringNotContainsString('notice notice-warning', $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation notice is shown when deprecated fields exist
+ */
+ public function test_variation_notice_shown_with_deprecated_fields() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->update_meta_data('fb_product_description', 'Test description');
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('notice notice-warning', $content);
+ $this->assertStringContainsString('Some attributes are no longer supported', $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation notice has correct styling
+ */
+ public function test_variation_notice_has_correct_styling() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->update_meta_data('fb_product_description', 'Test description');
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('style="padding: 1px 12px; margin: 10px 10px 0; border-left: 4px solid #dba617; background-color: #fff;"', $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation notice has dismiss button
+ */
+ public function test_variation_notice_has_dismiss_button() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->update_meta_data('fb_product_description', 'Test description');
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('button type="button" class="notice-dismiss"', $content);
+ $this->assertStringContainsString('Dismiss this notice', $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation fields are not shown when no deprecated fields exist
+ */
+ public function test_variation_fields_not_shown_without_deprecated_fields() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringNotContainsString('Facebook Description', $content);
+ $this->assertStringNotContainsString('Custom Image URL', $content);
+ $this->assertStringNotContainsString('Facebook Price', $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation fields are shown when deprecated fields exist
+ */
+ public function test_variation_fields_shown_with_deprecated_fields() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->update_meta_data('fb_product_description', 'Test description');
+ $variation->update_meta_data('fb_product_image', 'https://example.com/image.jpg');
+ $variation->update_meta_data('fb_product_price', '99.99');
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('Facebook Description', $content);
+ $this->assertStringContainsString('Custom Image URL', $content);
+ $this->assertStringContainsString('Facebook Price', $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation fields show correct values
+ */
+ public function test_variation_fields_show_correct_values() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->update_meta_data('fb_product_description', 'Test description content');
+ $variation->update_meta_data('fb_product_image', 'https://example.com/test-image.jpg');
+ $variation->update_meta_data('fb_product_price', '99.99');
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('Test description content', $content);
+ $this->assertStringContainsString('https://example.com/test-image.jpg', $content);
+ $this->assertStringContainsString('99.99', $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation fields inherit parent values when not set
+ */
+ public function test_variation_fields_inherit_parent_values() {
+ $product = new \WC_Product_Variable();
+ $product->update_meta_data('fb_product_description', 'Parent description');
+ $product->update_meta_data('fb_product_image', 'https://example.com/parent-image.jpg');
+ $product->update_meta_data('fb_product_price', '199.99');
+ $product->save();
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('Parent description', $content);
+ $this->assertStringContainsString('https://example.com/parent-image.jpg', $content);
+ $this->assertStringContainsString('199.99', $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation fields handle empty values correctly
+ */
+ public function test_variation_fields_handle_empty_values() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->update_meta_data('fb_product_description', '');
+ $variation->update_meta_data('fb_product_image', '');
+ $variation->update_meta_data('fb_product_price', '');
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('value=""', $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation fields handle special characters correctly
+ */
+ public function test_variation_fields_handle_special_characters() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->update_meta_data('fb_product_description', 'Test & description with "characters"');
+ $variation->update_meta_data('fb_product_image', 'https://example.com/image?param=value&special=true');
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString('Test & description with <special> "characters"', $content);
+ $this->assertStringContainsString('https://example.com/image?param=value&special=true', $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation fields handle long text values correctly
+ */
+ public function test_variation_fields_handle_long_text() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $long_description = str_repeat('This is a very long description. ', 50);
+ $long_image_url = 'https://example.com/image/' . str_repeat('very-long-path-segment-', 10) . '.jpg';
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->update_meta_data('fb_product_description', $long_description);
+ $variation->update_meta_data('fb_product_image', $long_image_url);
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString($long_description, $content);
+ $this->assertStringContainsString($long_image_url, $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation fields handle multiple variations correctly
+ */
+ public function test_variation_fields_handle_multiple_variations() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ // Create multiple variations
+ $variations = [];
+ for ($i = 1; $i <= 3; $i++) {
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->update_meta_data('fb_product_description', "Description {$i}");
+ $variation->update_meta_data('fb_product_image', "https://example.com/image-{$i}.jpg");
+ $variation->update_meta_data('fb_product_price', "99.{$i}9");
+ $variation->save();
+ $variations[] = $variation;
+ }
+
+ // Test each variation
+ foreach ($variations as $index => $variation) {
+ ob_start();
+ $this->admin->add_product_variation_edit_fields($index, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString("Description " . ($index + 1), $content);
+ $this->assertStringContainsString("image-" . ($index + 1), $content);
+ $this->assertStringContainsString("99." . ($index + 1) . "9", $content);
+ }
+
+ // Clean up
+ foreach ($variations as $variation) {
+ $variation->delete(true);
+ }
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation fields handle HTML content correctly
+ */
+ public function test_variation_fields_handle_html_content() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $html_description = 'This is a bold description with link
';
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->update_meta_data('fb_product_description', $html_description);
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString(htmlspecialchars($html_description, ENT_QUOTES), $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation fields handle Unicode characters correctly
+ */
+ public function test_variation_fields_handle_unicode_characters() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $unicode_description = 'Description with Unicode: 🚀 emoji, æ±‰å— Chinese, Español Spanish';
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->update_meta_data('fb_product_description', $unicode_description);
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString($unicode_description, $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation fields handle price formatting correctly
+ */
+ public function test_variation_fields_handle_price_formatting() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $test_prices = [
+ '99.99',
+ '1234.56',
+ '0.99',
+ '1000000.00',
+ '.99'
+ ];
+
+ foreach ($test_prices as $index => $price) {
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ $variation->update_meta_data('fb_product_price', $price);
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields($index, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ $this->assertStringContainsString(wc_format_decimal($price), $content);
+
+ $variation->delete(true);
+ }
+
+ // Clean up
+ $product->delete(true);
+ }
+
+ /**
+ * Test that variation fields handle invalid values correctly
+ */
+ public function test_variation_fields_handle_invalid_values() {
+ $product = new \WC_Product_Variable();
+ $product->save();
+
+ $invalid_values = [
+ 'fb_product_image' => 'not-a-valid-url',
+ 'fb_product_price' => 'not-a-number',
+ 'fb_product_description' => null
+ ];
+
+ $variation = new \WC_Product_Variation();
+ $variation->set_parent_id($product->get_id());
+ foreach ($invalid_values as $key => $value) {
+ $variation->update_meta_data($key, $value);
+ }
+ $variation->save();
+
+ ob_start();
+ $this->admin->add_product_variation_edit_fields(0, [], get_post($variation->get_id()));
+ $content = ob_get_clean();
+
+ // Verify that invalid values are handled gracefully
+ $this->assertStringContainsString('value=""', $content);
+
+ // Clean up
+ $variation->delete(true);
+ $product->delete(true);
+ }
+}
\ No newline at end of file