Commit c4b415a7ce7 for woocommerce
commit c4b415a7ce712926380a06161948d1713b207ccf
Author: Tom Cafferkey <tjcafferkey@gmail.com>
Date: Tue Sep 29 10:14:07 2026 +0100
Add guidance after order withdrawal activation (#68687)
* Add enabled order withdrawal inbox guidance
* Add changelog entry for order withdrawal guidance
* Update plugins/woocommerce/src/Internal/OrderWithdrawal/OrderWithdrawalFeatureHighlightNotification.php
Co-authored-by: Jorge A. Torres <jorge.torres@automattic.com>
* Use controller for consts
* More useful messaging in note
* Order withdrawal endpoint class
* Convert to testwith
* Dismiss previous note
* Just rely on get_notes_with_name
* update get_url
---------
Co-authored-by: Jorge A. Torres <jorge.torres@automattic.com>
diff --git a/plugins/woocommerce/changelog/add-order-withdrawal-enabled-notification b/plugins/woocommerce/changelog/add-order-withdrawal-enabled-notification
new file mode 100644
index 00000000000..b36fafc5db8
--- /dev/null
+++ b/plugins/woocommerce/changelog/add-order-withdrawal-enabled-notification
@@ -0,0 +1,4 @@
+Significance: minor
+Type: add
+
+Add guidance after the order withdrawal feature is enabled.
diff --git a/plugins/woocommerce/src/Internal/OrderWithdrawal/OrderWithdrawalController.php b/plugins/woocommerce/src/Internal/OrderWithdrawal/OrderWithdrawalController.php
index 8cdab00f4ea..7bf27610d38 100644
--- a/plugins/woocommerce/src/Internal/OrderWithdrawal/OrderWithdrawalController.php
+++ b/plugins/woocommerce/src/Internal/OrderWithdrawal/OrderWithdrawalController.php
@@ -15,10 +15,7 @@ use Automattic\WooCommerce\Utilities\FeaturesUtil;
*/
final class OrderWithdrawalController implements RegisterHooksInterface {
- private const FEATURE_ID = 'order_withdrawal';
- private const ENDPOINT_KEY = 'order-withdrawal';
- private const ENDPOINT_SLUG = 'withdraw-order';
- private const ENDPOINT_OPTION = 'woocommerce_myaccount_order_withdrawal_endpoint';
+ private const FEATURE_ID = 'order_withdrawal';
/**
* Form processor.
@@ -48,6 +45,13 @@ final class OrderWithdrawalController implements RegisterHooksInterface {
*/
private OrderWithdrawalEmailPreview $email_preview;
+ /**
+ * Order withdrawal endpoint.
+ *
+ * @var OrderWithdrawalEndpoint
+ */
+ private OrderWithdrawalEndpoint $endpoint;
+
/**
* Initialize dependencies.
*
@@ -55,15 +59,17 @@ final class OrderWithdrawalController implements RegisterHooksInterface {
* @param OrderWithdrawalFormView $form_view Form view.
* @param OrderWithdrawalFeatureHighlightNotification $feature_highlight_notification Feature highlight notification.
* @param OrderWithdrawalEmailPreview $email_preview Email preview handler.
+ * @param OrderWithdrawalEndpoint $endpoint Order withdrawal endpoint.
* @internal
*
* @since 11.1.0
*/
- final public function init( OrderWithdrawalFormProcessor $form_processor, OrderWithdrawalFormView $form_view, OrderWithdrawalFeatureHighlightNotification $feature_highlight_notification, OrderWithdrawalEmailPreview $email_preview ): void { // phpcs:ignore Generic.CodeAnalysis.UnnecessaryFinalModifier.Found -- Required by WooCommerce injection method rules.
+ final public function init( OrderWithdrawalFormProcessor $form_processor, OrderWithdrawalFormView $form_view, OrderWithdrawalFeatureHighlightNotification $feature_highlight_notification, OrderWithdrawalEmailPreview $email_preview, OrderWithdrawalEndpoint $endpoint ): void { // phpcs:ignore Generic.CodeAnalysis.UnnecessaryFinalModifier.Found -- Required by WooCommerce injection method rules.
$this->form_processor = $form_processor;
$this->form_view = $form_view;
$this->feature_highlight_notification = $feature_highlight_notification;
$this->email_preview = $email_preview;
+ $this->endpoint = $endpoint;
}
/**
@@ -73,6 +79,7 @@ final class OrderWithdrawalController implements RegisterHooksInterface {
*/
public function register(): void {
add_action( FeaturesController::FEATURE_ENABLED_CHANGED_ACTION, array( $this, 'maybe_flush_rewrite_rules' ), 10, 1 );
+ add_action( FeaturesController::FEATURE_ENABLED_CHANGED_ACTION, array( $this->feature_highlight_notification, 'possibly_add_enabled_note' ), 10, 2 );
add_action( 'init', array( $this, 'register_feature_hooks' ), 0, 0 );
}
@@ -92,9 +99,9 @@ final class OrderWithdrawalController implements RegisterHooksInterface {
}
add_filter( 'woocommerce_get_query_vars', array( $this, 'add_query_var' ), 10, 1 );
- add_filter( 'woocommerce_endpoint_' . self::ENDPOINT_KEY . '_title', array( $this, 'get_endpoint_title' ), 10, 1 );
+ add_filter( 'woocommerce_endpoint_' . OrderWithdrawalEndpoint::ENDPOINT_KEY . '_title', array( $this, 'get_endpoint_title' ), 10, 1 );
add_filter( 'woocommerce_settings_pages', array( $this, 'add_endpoint_setting' ), 10, 1 );
- add_action( 'woocommerce_account_' . self::ENDPOINT_KEY . '_endpoint', array( $this, 'render_view' ) );
+ add_action( 'woocommerce_account_' . OrderWithdrawalEndpoint::ENDPOINT_KEY . '_endpoint', array( $this, 'render_view' ) );
$this->email_preview->register();
}
@@ -117,8 +124,8 @@ final class OrderWithdrawalController implements RegisterHooksInterface {
global $wp;
return $this->is_enabled()
- && isset( $wp->query_vars[ self::ENDPOINT_KEY ] )
- && self::ENDPOINT_KEY === WC()->query->get_current_endpoint();
+ && isset( $wp->query_vars[ OrderWithdrawalEndpoint::ENDPOINT_KEY ] )
+ && OrderWithdrawalEndpoint::ENDPOINT_KEY === WC()->query->get_current_endpoint();
}
/**
@@ -147,10 +154,10 @@ final class OrderWithdrawalController implements RegisterHooksInterface {
return array();
}
- $endpoint = (string) get_option( self::ENDPOINT_OPTION, self::ENDPOINT_SLUG );
+ $endpoint = $this->endpoint->get_slug();
if ( ! empty( $endpoint ) ) {
- $query_vars[ self::ENDPOINT_KEY ] = $endpoint;
+ $query_vars[ OrderWithdrawalEndpoint::ENDPOINT_KEY ] = $endpoint;
}
return $query_vars;
@@ -184,9 +191,9 @@ final class OrderWithdrawalController implements RegisterHooksInterface {
$endpoint_setting = array(
'title' => __( 'Order withdrawal', 'woocommerce' ),
'desc' => __( 'Endpoint for the order withdrawal page.', 'woocommerce' ),
- 'id' => self::ENDPOINT_OPTION,
+ 'id' => OrderWithdrawalEndpoint::ENDPOINT_OPTION,
'type' => 'text',
- 'default' => self::ENDPOINT_SLUG,
+ 'default' => OrderWithdrawalEndpoint::ENDPOINT_SLUG,
'desc_tip' => true,
);
@@ -194,7 +201,7 @@ final class OrderWithdrawalController implements RegisterHooksInterface {
$added = false;
foreach ( $settings as $key => $setting ) {
- if ( is_array( $setting ) && self::ENDPOINT_OPTION === ( $setting['id'] ?? '' ) ) {
+ if ( is_array( $setting ) && OrderWithdrawalEndpoint::ENDPOINT_OPTION === ( $setting['id'] ?? '' ) ) {
return $settings;
}
@@ -204,15 +211,15 @@ final class OrderWithdrawalController implements RegisterHooksInterface {
'sectionend' === ( $setting['type'] ?? '' ) &&
'account_endpoint_options' === ( $setting['id'] ?? '' )
) {
- $new_settings[ self::ENDPOINT_OPTION ] = $endpoint_setting;
- $added = true;
+ $new_settings[ OrderWithdrawalEndpoint::ENDPOINT_OPTION ] = $endpoint_setting;
+ $added = true;
}
$new_settings[ $key ] = $setting;
}
if ( ! $added ) {
- $new_settings[ self::ENDPOINT_OPTION ] = $endpoint_setting;
+ $new_settings[ OrderWithdrawalEndpoint::ENDPOINT_OPTION ] = $endpoint_setting;
}
return $new_settings;
@@ -238,7 +245,7 @@ final class OrderWithdrawalController implements RegisterHooksInterface {
private function get_template_args(): array {
return $this->form_view->get_template_args(
$this->form_processor->process_current_request(),
- $this->get_form_action_url(),
+ $this->endpoint->get_url(),
$this->get_shop_url()
);
}
@@ -251,13 +258,4 @@ final class OrderWithdrawalController implements RegisterHooksInterface {
return $shop_url ? $shop_url : home_url( '/' );
}
-
- /**
- * Get the form action URL.
- */
- private function get_form_action_url(): string {
- $account_url = wc_get_page_permalink( 'myaccount' );
-
- return wc_get_endpoint_url( self::ENDPOINT_KEY, '', $account_url ? $account_url : home_url( '/' ) );
- }
}
diff --git a/plugins/woocommerce/src/Internal/OrderWithdrawal/OrderWithdrawalEndpoint.php b/plugins/woocommerce/src/Internal/OrderWithdrawal/OrderWithdrawalEndpoint.php
new file mode 100644
index 00000000000..c0145191907
--- /dev/null
+++ b/plugins/woocommerce/src/Internal/OrderWithdrawal/OrderWithdrawalEndpoint.php
@@ -0,0 +1,51 @@
+<?php
+declare( strict_types = 1 );
+
+namespace Automattic\WooCommerce\Internal\OrderWithdrawal;
+
+/**
+ * Provides configuration and URLs for the order withdrawal endpoint.
+ *
+ * @internal Just for internal use.
+ *
+ * @since 11.3.0
+ */
+final class OrderWithdrawalEndpoint {
+
+ /**
+ * Internal endpoint key.
+ */
+ public const ENDPOINT_KEY = 'order-withdrawal';
+
+ /**
+ * Default endpoint slug.
+ */
+ public const ENDPOINT_SLUG = 'withdraw-order';
+
+ /**
+ * Option containing the configured endpoint slug.
+ */
+ public const ENDPOINT_OPTION = 'woocommerce_myaccount_order_withdrawal_endpoint';
+
+ /**
+ * Get the configured endpoint slug.
+ *
+ * @since 11.3.0
+ */
+ public function get_slug(): string {
+ return (string) get_option( self::ENDPOINT_OPTION, self::ENDPOINT_SLUG );
+ }
+
+ /**
+ * Get the configured public order withdrawal page URL.
+ *
+ * @since 11.3.0
+ */
+ public function get_url(): string {
+ $account_url = wc_get_page_permalink( 'myaccount' );
+ $query_vars = WC()->query->get_query_vars();
+ $endpoint = ! empty( $query_vars[ self::ENDPOINT_KEY ] ) ? self::ENDPOINT_KEY : $this->get_slug();
+
+ return wc_get_endpoint_url( $endpoint, '', $account_url ? $account_url : home_url( '/' ) );
+ }
+}
diff --git a/plugins/woocommerce/src/Internal/OrderWithdrawal/OrderWithdrawalFeatureHighlightNotification.php b/plugins/woocommerce/src/Internal/OrderWithdrawal/OrderWithdrawalFeatureHighlightNotification.php
index d563cce8f0e..62351e8c458 100644
--- a/plugins/woocommerce/src/Internal/OrderWithdrawal/OrderWithdrawalFeatureHighlightNotification.php
+++ b/plugins/woocommerce/src/Internal/OrderWithdrawal/OrderWithdrawalFeatureHighlightNotification.php
@@ -16,13 +16,30 @@ use Exception;
*/
final class OrderWithdrawalFeatureHighlightNotification implements RegisterHooksInterface {
- public const NOTE_NAME = 'wc-admin-order-withdrawal-feature';
- public const CREATED_OPTION = 'woocommerce_order_withdrawal_inbox_notification_created';
+ /**
+ * Order withdrawal endpoint.
+ *
+ * @var OrderWithdrawalEndpoint
+ */
+ private OrderWithdrawalEndpoint $endpoint;
+
+ public const NOTE_NAME = 'wc-admin-order-withdrawal-feature';
+ public const ENABLED_NOTE_NAME = 'wc-admin-order-withdrawal-enabled';
private const COMING_SOON_OPTION = 'woocommerce_coming_soon';
private const FEATURES_SETTINGS_URL = 'admin.php?page=wc-settings&tab=advanced§ion=features';
private const DOCUMENTATION_URL = 'https://woocommerce.com/document/customer-order-withdrawal/';
+ /**
+ * Initialize dependencies.
+ *
+ * @param OrderWithdrawalEndpoint $endpoint Order withdrawal endpoint.
+ * @internal
+ */
+ final public function init( OrderWithdrawalEndpoint $endpoint ): void { // phpcs:ignore Generic.CodeAnalysis.UnnecessaryFinalModifier.Found -- Required by WooCommerce injection method rules.
+ $this->endpoint = $endpoint;
+ }
+
/**
* Register hooks.
*
@@ -62,7 +79,7 @@ final class OrderWithdrawalFeatureHighlightNotification implements RegisterHooks
*/
public function possibly_add_note(): void {
try {
- if ( $this->has_note_been_created() ) {
+ if ( $this->note_exists( self::NOTE_NAME ) ) {
return;
}
@@ -70,15 +87,42 @@ final class OrderWithdrawalFeatureHighlightNotification implements RegisterHooks
return;
}
- if ( ! add_option( self::CREATED_OPTION, 'yes', '', false ) ) {
+ $this->get_feature_highlight_note()->save();
+ } catch ( Exception $exception ) {
+ wc_get_logger()->error(
+ 'Unable to create the order withdrawal inbox notification.',
+ array(
+ 'source' => 'order-withdrawal',
+ 'exception' => $exception,
+ )
+ );
+ }
+ }
+
+ /**
+ * Add a note when the order withdrawal feature is enabled.
+ *
+ * @param mixed $feature_id Feature being toggled.
+ * @param mixed $enabled Whether the feature was enabled.
+ *
+ * @since 11.3.0
+ */
+ public function possibly_add_enabled_note( $feature_id, $enabled ): void {
+ if ( 'order_withdrawal' !== $feature_id || true !== $enabled ) {
+ return;
+ }
+
+ try {
+ if ( $this->note_exists( self::ENABLED_NOTE_NAME ) ) {
+ $this->dismiss_note( self::NOTE_NAME );
return;
}
- $this->get_note()->save();
+ $this->get_enabled_note()->save();
+ $this->dismiss_note( self::NOTE_NAME );
} catch ( Exception $exception ) {
- delete_option( self::CREATED_OPTION );
wc_get_logger()->error(
- 'Unable to create the order withdrawal inbox notification.',
+ 'Unable to create the order withdrawal enabled inbox notification.',
array(
'source' => 'order-withdrawal',
'exception' => $exception,
@@ -87,6 +131,32 @@ final class OrderWithdrawalFeatureHighlightNotification implements RegisterHooks
}
}
+ /**
+ * Dismiss notes with the given name.
+ *
+ * @param string $note_name Note name stored in the data store.
+ */
+ private function dismiss_note( string $note_name ): void {
+ /**
+ * Data store instance.
+ *
+ * @var NotesDataStore $data_store
+ */
+ $data_store = Notes::load_data_store();
+ $note_ids = $data_store->get_notes_with_name( $note_name );
+
+ foreach ( $note_ids as $note_id ) {
+ $note = Notes::get_note( $note_id );
+
+ if ( ! $note instanceof Note || Note::E_WC_ADMIN_NOTE_ACTIONED === $note->get_status() ) {
+ continue;
+ }
+
+ $note->set_status( Note::E_WC_ADMIN_NOTE_ACTIONED );
+ $note->save();
+ }
+ }
+
/**
* Whether the notification is relevant for the current store settings.
*/
@@ -98,7 +168,7 @@ final class OrderWithdrawalFeatureHighlightNotification implements RegisterHooks
/**
* Get the inbox note.
*/
- private function get_note(): Note {
+ private function get_feature_highlight_note(): Note {
$note = new Note();
$note->set_title(
@@ -132,28 +202,51 @@ final class OrderWithdrawalFeatureHighlightNotification implements RegisterHooks
}
/**
- * Whether this note has already been created, including soft-deleted notes.
+ * Get the inbox note shown after the feature is enabled.
*/
- private function has_note_been_created(): bool {
- if ( 'yes' === get_option( self::CREATED_OPTION, 'no' ) ) {
- return true;
- }
+ private function get_enabled_note(): Note {
+ $note = new Note();
+ $note->set_title( __( 'The order withdrawal feature is enabled', 'woocommerce' ) );
+ $note->set_content(
+ __( 'Your order withdrawal page is ready. Share its URL wherever customers need access to the withdrawal form, such as your store\'s terms and conditions.', 'woocommerce' )
+ );
+ $note->set_content_data( (object) array() );
+ $note->set_type( Note::E_WC_ADMIN_NOTE_INFORMATIONAL );
+ $note->set_name( self::ENABLED_NOTE_NAME );
+ $note->set_source( 'woocommerce-admin' );
+ $note->add_action(
+ 'view-page',
+ __( 'View page', 'woocommerce' ),
+ $this->endpoint->get_url(),
+ Note::E_WC_ADMIN_NOTE_ACTIONED,
+ true
+ );
+ $note->add_action(
+ 'learn-more',
+ __( 'Learn more', 'woocommerce' ),
+ self::DOCUMENTATION_URL,
+ Note::E_WC_ADMIN_NOTE_UNACTIONED
+ );
+
+ return $note;
+ }
+
+ /**
+ * Whether a note exists, including soft-deleted notes.
+ *
+ * @param string $note_name Note name stored in the data store.
+ */
+ private function note_exists( string $note_name ): bool {
/**
* Data store instance.
*
* @var NotesDataStore $data_store
*/
$data_store = Notes::load_data_store();
- $note_ids = $data_store->get_notes_with_name( self::NOTE_NAME );
-
- if ( empty( $note_ids ) ) {
- return false;
- }
-
- update_option( self::CREATED_OPTION, 'yes', false );
+ $note_ids = $data_store->get_notes_with_name( $note_name );
- return true;
+ return ! empty( $note_ids );
}
/**
diff --git a/plugins/woocommerce/tests/php/src/Internal/OrderWithdrawal/OrderWithdrawalFeatureHighlightNotificationTest.php b/plugins/woocommerce/tests/php/src/Internal/OrderWithdrawal/OrderWithdrawalFeatureHighlightNotificationTest.php
index 5df32561c51..e05bc0a480d 100644
--- a/plugins/woocommerce/tests/php/src/Internal/OrderWithdrawal/OrderWithdrawalFeatureHighlightNotificationTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/OrderWithdrawal/OrderWithdrawalFeatureHighlightNotificationTest.php
@@ -5,6 +5,7 @@ namespace Automattic\WooCommerce\Tests\Internal\OrderWithdrawal;
use Automattic\WooCommerce\Admin\Notes\Note;
use Automattic\WooCommerce\Admin\Notes\Notes;
+use Automattic\WooCommerce\Internal\OrderWithdrawal\OrderWithdrawalEndpoint;
use Automattic\WooCommerce\Internal\OrderWithdrawal\OrderWithdrawalFeatureHighlightNotification;
use WC_Unit_Test_Case;
@@ -26,7 +27,7 @@ class OrderWithdrawalFeatureHighlightNotificationTest extends WC_Unit_Test_Case
self::ALLOWED_COUNTRIES_OPTION,
self::ALL_EXCEPT_COUNTRIES_OPTION,
self::SPECIFIC_COUNTRIES_OPTION,
- OrderWithdrawalFeatureHighlightNotification::CREATED_OPTION,
+ OrderWithdrawalEndpoint::ENDPOINT_OPTION,
);
/**
@@ -50,6 +51,7 @@ class OrderWithdrawalFeatureHighlightNotificationTest extends WC_Unit_Test_Case
parent::setUp();
$this->sut = new OrderWithdrawalFeatureHighlightNotification();
+ $this->sut->init( new OrderWithdrawalEndpoint() );
$this->store_original_options();
$this->delete_notification_state();
$this->set_live_eu_store_defaults();
@@ -78,11 +80,6 @@ class OrderWithdrawalFeatureHighlightNotificationTest extends WC_Unit_Test_Case
$note_ids,
'An eligible existing live store should receive the notification.'
);
- $this->assertSame(
- 'yes',
- get_option( OrderWithdrawalFeatureHighlightNotification::CREATED_OPTION ),
- 'Creating the note should persist the one-time creation flag.'
- );
}
/**
@@ -114,6 +111,74 @@ class OrderWithdrawalFeatureHighlightNotificationTest extends WC_Unit_Test_Case
);
}
+ /**
+ * @testdox Should add a notification with the configured withdrawal page when the feature is enabled.
+ */
+ public function test_possibly_add_enabled_note_adds_notification_with_configured_page_url(): void {
+ update_option( OrderWithdrawalEndpoint::ENDPOINT_OPTION, 'request-withdrawal' );
+
+ $this->sut->possibly_add_enabled_note( 'order_withdrawal', true );
+
+ $note = Notes::get_note_by_name( OrderWithdrawalFeatureHighlightNotification::ENABLED_NOTE_NAME );
+
+ $this->assertInstanceOf( Note::class, $note, 'Enabling order withdrawal should create an inbox notification.' );
+ $this->assertSame( 'The order withdrawal feature is enabled', $note->get_title(), 'The notification should have the expected title.' );
+ $this->assertSame( 'Your order withdrawal page is ready. Share its URL wherever customers need access to the withdrawal form, such as your store\'s terms and conditions.', $note->get_content(), 'The notification should explain how to share the withdrawal page.' );
+
+ $actions = $note->get_actions();
+
+ $this->assertCount( 2, $actions, 'The notification should include view page and learn more actions.' );
+ $this->assertSame( 'view-page', $actions[0]->name, 'The primary action should view the withdrawal page.' );
+ $this->assertSame( wc_get_endpoint_url( 'request-withdrawal', '', wc_get_page_permalink( 'myaccount' ) ), $actions[0]->query, 'The view page action should use the configured endpoint.' );
+ $this->assertSame( 'learn-more', $actions[1]->name, 'The secondary action should link to documentation.' );
+ $this->assertSame( 'https://woocommerce.com/document/customer-order-withdrawal/', $actions[1]->query, 'The learn more action should use the order withdrawal documentation URL.' );
+ }
+
+ /**
+ * @testdox Should only create the enabled notification once.
+ */
+ public function test_possibly_add_enabled_note_prevents_duplicates(): void {
+ $this->sut->possibly_add_enabled_note( 'order_withdrawal', true );
+ $this->sut->possibly_add_enabled_note( 'order_withdrawal', true );
+
+ $this->assertCount(
+ 1,
+ $this->get_enabled_notification_note_ids(),
+ 'Repeated enable events should not create duplicate notifications.'
+ );
+ }
+
+ /**
+ * @testdox Should dismiss the feature highlight notification when the enabled notification is created.
+ */
+ public function test_possibly_add_enabled_note_dismisses_feature_highlight_notification(): void {
+ $this->sut->possibly_add_note();
+
+ $this->sut->possibly_add_enabled_note( 'order_withdrawal', true );
+
+ $feature_highlight_note = Notes::get_note_by_name( OrderWithdrawalFeatureHighlightNotification::NOTE_NAME );
+ $enabled_note = Notes::get_note_by_name( OrderWithdrawalFeatureHighlightNotification::ENABLED_NOTE_NAME );
+
+ $this->assertInstanceOf( Note::class, $feature_highlight_note, 'The feature highlight notification should exist.' );
+ $this->assertSame( Note::E_WC_ADMIN_NOTE_ACTIONED, $feature_highlight_note->get_status(), 'The feature highlight notification should be dismissed.' );
+ $this->assertInstanceOf( Note::class, $enabled_note, 'The enabled notification should be created.' );
+ $this->assertSame( Note::E_WC_ADMIN_NOTE_UNACTIONED, $enabled_note->get_status(), 'The enabled notification should remain visible.' );
+ }
+
+ /**
+ * @testdox Should not add the enabled notification for unrelated or disabled features.
+ * @testWith ["order_withdrawal", false]
+ * ["other_feature", true]
+ *
+ * @param string $feature_id Feature being toggled.
+ * @param bool $enabled Whether the feature was enabled.
+ */
+ public function test_possibly_add_enabled_note_ignores_other_feature_changes( string $feature_id, bool $enabled ): void {
+ $this->sut->possibly_add_enabled_note( $feature_id, $enabled );
+
+ $this->assertFalse( Notes::get_note_by_name( OrderWithdrawalFeatureHighlightNotification::ENABLED_NOTE_NAME ), 'An irrelevant feature change should not create the notification.' );
+ }
+
/**
* @testdox Should match stores selling to EU countries.
* @dataProvider provide_country_settings
@@ -205,9 +270,12 @@ class OrderWithdrawalFeatureHighlightNotificationTest extends WC_Unit_Test_Case
* Delete notification state created by tests.
*/
private function delete_notification_state(): void {
- delete_option( OrderWithdrawalFeatureHighlightNotification::CREATED_OPTION );
+ $note_ids = array_merge(
+ $this->get_notification_note_ids(),
+ $this->get_enabled_notification_note_ids()
+ );
- foreach ( $this->get_notification_note_ids() as $note_id ) {
+ foreach ( $note_ids as $note_id ) {
$note = Notes::get_note( $note_id );
if ( $note instanceof Note ) {
@@ -230,6 +298,20 @@ class OrderWithdrawalFeatureHighlightNotificationTest extends WC_Unit_Test_Case
);
}
+ /**
+ * Get enabled notification note IDs.
+ *
+ * @return int[]
+ */
+ private function get_enabled_notification_note_ids(): array {
+ $data_store = Notes::load_data_store();
+
+ return array_map(
+ 'absint',
+ $data_store->get_notes_with_name( OrderWithdrawalFeatureHighlightNotification::ENABLED_NOTE_NAME )
+ );
+ }
+
/**
* Restore an option to its original state.
*
diff --git a/plugins/woocommerce/tests/php/src/Internal/OrderWithdrawal/OrderWithdrawalTest.php b/plugins/woocommerce/tests/php/src/Internal/OrderWithdrawal/OrderWithdrawalTest.php
index 6176add9230..a737b7c09e3 100644
--- a/plugins/woocommerce/tests/php/src/Internal/OrderWithdrawal/OrderWithdrawalTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/OrderWithdrawal/OrderWithdrawalTest.php
@@ -9,6 +9,7 @@ use Automattic\WooCommerce\Internal\Admin\EmailPreview\EmailPreview;
use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Internal\OrderWithdrawal\Emails\OrderWithdrawalEmailPreview;
use Automattic\WooCommerce\Internal\OrderWithdrawal\OrderWithdrawalController;
+use Automattic\WooCommerce\Internal\OrderWithdrawal\OrderWithdrawalEndpoint;
use Automattic\WooCommerce\Internal\OrderWithdrawal\OrderWithdrawalFormProcessor;
use Automattic\WooCommerce\Internal\OrderWithdrawal\OrderWithdrawalFormState;
use Automattic\WooCommerce\Internal\OrderWithdrawal\OrderWithdrawalFormView;
@@ -25,7 +26,6 @@ use WC_Unit_Test_Case;
class OrderWithdrawalTest extends WC_Unit_Test_Case {
private const FEATURE_OPTION = 'woocommerce_feature_order_withdrawal_enabled';
- private const ENDPOINT_OPTION = 'woocommerce_myaccount_order_withdrawal_endpoint';
private const FLUSH_QUEUE_OPTION = 'woocommerce_queue_flush_rewrite_rules';
private const MISSING_OPTION_MARK = '__woocommerce_order_withdrawal_missing_option__';
private const ORDER_WITHDRAWAL_REQUESTED_META_KEY = '_order_withdrawal_requested';
@@ -128,7 +128,7 @@ class OrderWithdrawalTest extends WC_Unit_Test_Case {
$this->original_remote_addr = $this->had_remote_addr ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : null;
$this->original_session = WC()->session;
$this->original_feature_option = get_option( self::FEATURE_OPTION, self::MISSING_OPTION_MARK );
- $this->original_endpoint_option = get_option( self::ENDPOINT_OPTION, self::MISSING_OPTION_MARK );
+ $this->original_endpoint_option = get_option( OrderWithdrawalEndpoint::ENDPOINT_OPTION, self::MISSING_OPTION_MARK );
$this->original_flush_queue_option = get_option( self::FLUSH_QUEUE_OPTION, self::MISSING_OPTION_MARK );
if ( ! WC()->session ) {
@@ -140,7 +140,7 @@ class OrderWithdrawalTest extends WC_Unit_Test_Case {
$_SERVER['REMOTE_ADDR'] = '203.0.113.10';
$this->clear_order_withdrawal_rate_limits();
$this->disable_feature();
- delete_option( self::ENDPOINT_OPTION );
+ delete_option( OrderWithdrawalEndpoint::ENDPOINT_OPTION );
delete_option( self::FLUSH_QUEUE_OPTION );
wc_clear_notices();
}
@@ -164,7 +164,7 @@ class OrderWithdrawalTest extends WC_Unit_Test_Case {
}
$this->restore_option( self::FEATURE_OPTION, $this->original_feature_option );
- $this->restore_option( self::ENDPOINT_OPTION, $this->original_endpoint_option );
+ $this->restore_option( OrderWithdrawalEndpoint::ENDPOINT_OPTION, $this->original_endpoint_option );
$this->restore_option( self::FLUSH_QUEUE_OPTION, $this->original_flush_queue_option );
wc_clear_notices();
$this->clear_order_withdrawal_rate_limits();
@@ -680,8 +680,11 @@ class OrderWithdrawalTest extends WC_Unit_Test_Case {
*/
public function test_controller_registers_order_deletion_cleanup_hooks(): void {
$controller = new OrderWithdrawalController();
+ $notification = new OrderWithdrawalFeatureHighlightNotification();
$email_preview = new OrderWithdrawalEmailPreview();
- $controller->init( $this->sut, new OrderWithdrawalFormView(), new OrderWithdrawalFeatureHighlightNotification(), $email_preview );
+ $endpoint = new OrderWithdrawalEndpoint();
+ $notification->init( $endpoint );
+ $controller->init( $this->sut, new OrderWithdrawalFormView(), $notification, $email_preview, $endpoint );
try {
$controller->register();
@@ -689,10 +692,12 @@ class OrderWithdrawalTest extends WC_Unit_Test_Case {
$this->assertNotFalse( has_action( 'woocommerce_before_delete_order', array( $this->sut, 'delete_order_withdrawal_inbox_note_for_order' ) ) );
$this->assertNotFalse( has_action( 'before_delete_post', array( $this->sut, 'delete_order_withdrawal_inbox_note_for_order' ) ) );
+ $this->assertNotFalse( has_action( FeaturesController::FEATURE_ENABLED_CHANGED_ACTION, array( $notification, 'possibly_add_enabled_note' ) ) );
$this->assertFalse( has_filter( 'woocommerce_prepare_email_for_preview', array( $email_preview, 'prepare_email_for_preview' ) ) );
} finally {
remove_action( 'init', array( $controller, 'register_feature_hooks' ), 0 );
remove_action( FeaturesController::FEATURE_ENABLED_CHANGED_ACTION, array( $controller, 'maybe_flush_rewrite_rules' ), 10 );
+ remove_action( FeaturesController::FEATURE_ENABLED_CHANGED_ACTION, array( $notification, 'possibly_add_enabled_note' ), 10 );
remove_filter( 'woocommerce_prepare_email_for_preview', array( $email_preview, 'prepare_email_for_preview' ), 10 );
remove_filter( 'woocommerce_get_query_vars', array( $controller, 'add_query_var' ), 10 );
remove_filter( 'woocommerce_endpoint_order-withdrawal_title', array( $controller, 'get_endpoint_title' ), 10 );
@@ -748,8 +753,10 @@ class OrderWithdrawalTest extends WC_Unit_Test_Case {
$controller = new OrderWithdrawalController();
$notification = new OrderWithdrawalFeatureHighlightNotification();
$email_preview = new OrderWithdrawalEmailPreview();
+ $endpoint = new OrderWithdrawalEndpoint();
- $controller->init( $this->sut, new OrderWithdrawalFormView(), $notification, $email_preview );
+ $notification->init( $endpoint );
+ $controller->init( $this->sut, new OrderWithdrawalFormView(), $notification, $email_preview, $endpoint );
try {
$controller->register();
@@ -764,6 +771,7 @@ class OrderWithdrawalTest extends WC_Unit_Test_Case {
} finally {
remove_action( 'init', array( $controller, 'register_feature_hooks' ), 0 );
remove_action( FeaturesController::FEATURE_ENABLED_CHANGED_ACTION, array( $controller, 'maybe_flush_rewrite_rules' ), 10 );
+ remove_action( FeaturesController::FEATURE_ENABLED_CHANGED_ACTION, array( $notification, 'possibly_add_enabled_note' ), 10 );
remove_filter( 'woocommerce_prepare_email_for_preview', array( $email_preview, 'prepare_email_for_preview' ), 10 );
remove_filter( 'woocommerce_get_query_vars', array( $controller, 'add_query_var' ), 10 );
remove_filter( 'woocommerce_endpoint_order-withdrawal_title', array( $controller, 'get_endpoint_title' ), 10 );
@@ -785,12 +793,15 @@ class OrderWithdrawalTest extends WC_Unit_Test_Case {
$controller = new OrderWithdrawalController();
$notification = new OrderWithdrawalFeatureHighlightNotification();
$email_preview = new OrderWithdrawalEmailPreview();
+ $endpoint = new OrderWithdrawalEndpoint();
+ $notification->init( $endpoint );
$controller->init(
$this->sut,
new OrderWithdrawalFormView(),
$notification,
- $email_preview
+ $email_preview,
+ $endpoint
);
try {
@@ -808,6 +819,7 @@ class OrderWithdrawalTest extends WC_Unit_Test_Case {
} finally {
remove_action( 'init', array( $controller, 'register_feature_hooks' ), 0 );
remove_action( FeaturesController::FEATURE_ENABLED_CHANGED_ACTION, array( $controller, 'maybe_flush_rewrite_rules' ), 10 );
+ remove_action( FeaturesController::FEATURE_ENABLED_CHANGED_ACTION, array( $notification, 'possibly_add_enabled_note' ), 10 );
remove_action( 'update_option_woocommerce_coming_soon', array( $notification, 'maybe_add_note_when_store_goes_live' ), 10 );
remove_action( 'wc_admin_daily', array( $notification, 'possibly_add_note' ), 10 );
remove_action( 'woocommerce_before_delete_order', array( $this->sut, 'delete_order_withdrawal_inbox_note_for_order' ), 10 );