-
-
Notifications
You must be signed in to change notification settings - Fork 73
Fix: free trial lost on abandoned WooCommerce checkout #360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
6172a05
a4592bb
bd5f1a7
a912cac
3da7e7a
d5bc1b0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,219 @@ | ||
| <?php | ||
| /** | ||
| * Regression tests for Payment_Manager pending-payment popup behaviour. | ||
| * | ||
| * @package WP_Ultimo | ||
| */ | ||
|
|
||
| namespace WP_Ultimo\Managers; | ||
|
|
||
| use WP_UnitTestCase; | ||
| use WP_Ultimo\Models\Customer; | ||
|
|
||
| /** | ||
| * Regression tests for Payment_Manager::check_pending_payments() and | ||
| * render_pending_payments(). | ||
| * | ||
| * Ensures that pending and cancelled memberships (from abandoned checkouts) | ||
| * do not trigger the "pending payment" popup on user login, which previously | ||
| * pointed users at WC orders that may no longer exist. | ||
| * | ||
| * @see https://github.com/Ultimate-Multisite/ultimate-multisite/pull/360 | ||
| */ | ||
| class Payment_Manager_Pending_Popup_Test extends WP_UnitTestCase { | ||
|
|
||
| private Payment_Manager $manager; | ||
| private Customer $customer; | ||
| private \WP_User $wp_user; | ||
|
|
||
| /** | ||
| * Set up a fresh customer and payment manager instance before each test. | ||
| */ | ||
| public function setUp(): void { | ||
|
|
||
| parent::setUp(); | ||
|
|
||
| $uid = uniqid('popup_'); | ||
|
|
||
| $this->customer = wu_create_customer( | ||
| [ | ||
| 'username' => $uid, | ||
| 'email' => $uid . '@example.com', | ||
| 'password' => 'password123', | ||
| ] | ||
| ); | ||
|
|
||
| $this->wp_user = $this->customer->get_user(); | ||
|
|
||
| $this->manager = Payment_Manager::get_instance(); | ||
|
|
||
| delete_user_meta($this->wp_user->ID, 'wu_show_pending_payment_popup'); | ||
| } | ||
|
|
||
| /** | ||
| * A pending membership (abandoned checkout) must NOT trigger the popup. | ||
| * | ||
| * Before the fix the loop did not skip pending memberships, so any | ||
| * abandoned checkout with a linked WU payment would silently set the meta | ||
| * on every subsequent login. | ||
| */ | ||
| public function test_pending_membership_does_not_trigger_popup(): void { | ||
|
|
||
| $product = wu_create_product( | ||
| [ | ||
| 'name' => 'Plan', | ||
| 'slug' => 'plan-popup-pending-' . uniqid(), | ||
| 'amount' => 50.00, | ||
| 'type' => 'plan', | ||
| 'active' => true, | ||
| 'pricing_type' => 'paid', | ||
| 'recurring' => true, | ||
| 'duration' => 1, | ||
| 'duration_unit' => 'month', | ||
| ] | ||
| ); | ||
|
|
||
| $membership = wu_create_membership( | ||
| [ | ||
| 'customer_id' => $this->customer->get_id(), | ||
| 'plan_id' => $product->get_id(), | ||
| 'status' => 'pending', | ||
| 'recurring' => true, | ||
| ] | ||
| ); | ||
|
|
||
| wu_create_payment( | ||
| [ | ||
| 'customer_id' => $this->customer->get_id(), | ||
| 'membership_id' => $membership->get_id(), | ||
| 'status' => 'pending', | ||
| 'total' => 50.00, | ||
| 'gateway' => 'woocommerce', | ||
| ] | ||
| ); | ||
|
Comment on lines
+85
to
+93
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assert the pending payment fixture was created. The pending/cancelled cases pass trivially if Suggested guard- wu_create_payment(
+ $payment = wu_create_payment(
[
'customer_id' => $this->customer->get_id(),
'membership_id' => $membership->get_id(),
'status' => 'pending',
'total' => 50.00,
'gateway' => 'woocommerce',
]
);
+ $this->assertNotEmpty($payment, 'Failed to create the pending payment fixture.');Also applies to: 134-142, 185-193 🤖 Prompt for AI Agents |
||
|
|
||
| $this->manager->check_pending_payments($this->wp_user); | ||
|
|
||
| $this->assertEmpty( | ||
| get_user_meta($this->wp_user->ID, 'wu_show_pending_payment_popup', true), | ||
| 'A pending membership must not trigger the pending payment popup.' | ||
| ); | ||
|
|
||
| $membership->delete(); | ||
| $product->delete(); | ||
| } | ||
|
|
||
| /** | ||
| * A cancelled membership must NOT trigger the popup. | ||
| */ | ||
| public function test_cancelled_membership_does_not_trigger_popup(): void { | ||
|
|
||
| $product = wu_create_product( | ||
| [ | ||
| 'name' => 'Plan', | ||
| 'slug' => 'plan-popup-cancelled-' . uniqid(), | ||
| 'amount' => 50.00, | ||
| 'type' => 'plan', | ||
| 'active' => true, | ||
| 'pricing_type' => 'paid', | ||
| 'recurring' => true, | ||
| 'duration' => 1, | ||
| 'duration_unit' => 'month', | ||
| ] | ||
| ); | ||
|
|
||
| $membership = wu_create_membership( | ||
| [ | ||
| 'customer_id' => $this->customer->get_id(), | ||
| 'plan_id' => $product->get_id(), | ||
| 'status' => 'cancelled', | ||
| 'recurring' => true, | ||
| ] | ||
| ); | ||
|
|
||
| wu_create_payment( | ||
| [ | ||
| 'customer_id' => $this->customer->get_id(), | ||
| 'membership_id' => $membership->get_id(), | ||
| 'status' => 'pending', | ||
| 'total' => 50.00, | ||
| 'gateway' => 'woocommerce', | ||
| ] | ||
| ); | ||
|
|
||
| $this->manager->check_pending_payments($this->wp_user); | ||
|
|
||
| $this->assertEmpty( | ||
| get_user_meta($this->wp_user->ID, 'wu_show_pending_payment_popup', true), | ||
| 'A cancelled membership must not trigger the pending payment popup.' | ||
| ); | ||
|
|
||
| $membership->delete(); | ||
| $product->delete(); | ||
| } | ||
|
|
||
| /** | ||
| * An active membership with a genuine pending payment MUST trigger the popup. | ||
| * Validates that the skip only applies to pending/cancelled memberships and | ||
| * does not suppress legitimate payment reminders. | ||
| */ | ||
| public function test_active_membership_with_pending_payment_triggers_popup(): void { | ||
|
|
||
| $product = wu_create_product( | ||
| [ | ||
| 'name' => 'Plan', | ||
| 'slug' => 'plan-popup-active-' . uniqid(), | ||
| 'amount' => 50.00, | ||
| 'type' => 'plan', | ||
| 'active' => true, | ||
| 'pricing_type' => 'paid', | ||
| 'recurring' => true, | ||
| 'duration' => 1, | ||
| 'duration_unit' => 'month', | ||
| ] | ||
| ); | ||
|
|
||
| $membership = wu_create_membership( | ||
| [ | ||
| 'customer_id' => $this->customer->get_id(), | ||
| 'plan_id' => $product->get_id(), | ||
| 'status' => 'active', | ||
| 'recurring' => true, | ||
| ] | ||
| ); | ||
|
|
||
| wu_create_payment( | ||
| [ | ||
| 'customer_id' => $this->customer->get_id(), | ||
| 'membership_id' => $membership->get_id(), | ||
| 'status' => 'pending', | ||
| 'total' => 50.00, | ||
| 'gateway' => 'woocommerce', | ||
| ] | ||
| ); | ||
|
|
||
| $this->manager->check_pending_payments($this->wp_user); | ||
|
|
||
| $this->assertNotEmpty( | ||
| get_user_meta($this->wp_user->ID, 'wu_show_pending_payment_popup', true), | ||
| 'An active membership with a pending payment must trigger the popup.' | ||
| ); | ||
|
|
||
| $membership->delete(); | ||
| $product->delete(); | ||
| } | ||
|
|
||
| /** | ||
| * Delete test data and reset state after each test. | ||
| */ | ||
| public function tearDown(): void { | ||
|
|
||
| global $wpdb; | ||
| $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}wu_memberships WHERE customer_id = %d", $this->customer->get_id())); | ||
| $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}wu_payments WHERE customer_id = %d", $this->customer->get_id())); | ||
| delete_user_meta($this->wp_user->ID, 'wu_show_pending_payment_popup'); | ||
| $this->customer->delete(); | ||
|
|
||
| parent::tearDown(); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
render_pending_payments()is still untested.All three methods only exercise
check_pending_payments(), but the production fix also added the same status guard ininc/managers/class-payment-manager.php:232-309. Without a render assertion, that second half of the fix can regress independently.Also applies to: 60-204
🤖 Prompt for AI Agents