greys / wc-subscriptions-tests
PHPUnit test framework and helpers for WooCommerce Subscriptions extensions
Installs: 11
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/greys/wc-subscriptions-tests
Requires
- php: >=7.4
- greys/woocommerce-phpunit-framework: ^5.0
Requires (Dev)
- phpunit/phpunit: ^9.6
- yoast/phpunit-polyfills: ^1.0
README
A comprehensive PHPUnit testing framework for WooCommerce Subscriptions extensions. This package provides test helpers, mock classes, and assertion traits to make testing WooCommerce Subscriptions functionality easier and more reliable.
Features
- 🎯 Complete Test Suite: Base test case class with subscription-specific functionality
- 🛠️ Helper Classes: Create subscriptions, renewal orders, and recurring carts easily
- 🎭 Mock Objects: Full mock implementations when WC Subscriptions isn't available
- ✅ Custom Assertions: Subscription-specific assertion methods
- 📦 Easy Integration: Works seamlessly with existing WooCommerce test setups
Requirements
- PHP >= 7.4
- PHPUnit ^9.6
- WooCommerce PHPUnit Framework (
greys/woocommerce-phpunit-framework
) - WordPress Test Suite
Installation
composer require --dev greys/woocommerce-subscriptions-phpunit-framework
Quick Start
1. Extend the Base Test Case
<?php use Greys\WooCommerce\Subscriptions\Tests\UnitTestCase; use Greys\WooCommerce\Subscriptions\Tests\Helpers\Subscription; class My_Subscription_Test extends UnitTestCase { public function test_subscription_creation() { // Arrange - Create a subscription using helper. $subscription = Subscription::create_subscription( array( 'status' => 'active', 'billing_period' => 'month', 'billing_interval' => 1, ) ); // Act - Add to tracked subscriptions for cleanup. $this->subscription_ids[] = $subscription->get_id(); // Assert - Use custom assertions. $this->assertSubscriptionActive( $subscription ); $this->assertSubscriptionSchedule( 'month', 1, $subscription ); } }
2. Create Test Subscriptions
// Simple subscription $subscription = Subscription::create_subscription(); // Subscription with trial $subscription = Subscription::create_subscription( array( 'trial_end' => gmdate( 'Y-m-d H:i:s', strtotime( '+7 days' ) ), ) ); // Add products $product = Subscription::create_subscription_product( array( 'name' => 'Monthly Plan', 'regular_price' => '29.99', ) ); Subscription::add_product( $subscription, $product->get_id() );
3. Test Renewal Orders
use Greys\WooCommerce\Subscriptions\Tests\Helpers\Renewal; public function test_renewal_order_creation() { // Arrange. $subscription = Subscription::create_subscription(); // Act. $renewal_order = Renewal::create_renewal_order( $subscription ); // Assert. $this->assertRenewalOrderCreated( $subscription ); $this->assertEquals( 'pending', $renewal_order->get_status() ); }
4. Test Recurring Cart
use Greys\WooCommerce\Subscriptions\Tests\Helpers\RecurringCart; public function test_recurring_cart() { // Arrange. $product = Subscription::create_subscription_product(); // Act. $cart_key = RecurringCart::add_subscription_to_cart( $product->get_id(), 2 // quantity ); // Assert. $this->assertNotEmpty( $cart_key ); $this->assertEquals( 2, WC()->cart->get_cart_contents_count() ); }
Available Helpers
Subscription
create_subscription( $args )
- Create a test subscriptioncreate_subscription_product( $args )
- Create a subscription productadd_product( $subscription, $product_id, $args )
- Add product to subscriptionupdate_status( $subscription, $new_status )
- Update subscription statusprocess_payment( $subscription, $success )
- Process subscription paymentcreate_customer( $args )
- Create a customer with subscription capabilities
Renewal
create_renewal_order( $subscription, $args )
- Create renewal orderprocess_renewal_payment( $renewal_order, $success )
- Process renewal paymentcreate_failed_renewal_order( $subscription, $reason )
- Create failed renewalget_renewal_orders( $subscription )
- Get all renewal ordersschedule_renewal( $subscription, $date )
- Schedule renewal paymenttrigger_renewal_retry( $renewal_order, $retry_count )
- Trigger payment retry
RecurringCart
add_subscription_to_cart( $product_id, $quantity, $cart_data )
- Add subscription to cartcreate_recurring_cart( $args )
- Create mock recurring cartadd_item_to_recurring_cart( $cart, $product_id, $quantity, $total )
- Add item to recurring cartcalculate_recurring_totals( $cart )
- Calculate cart totalsclear_recurring_carts()
- Clear all recurring cartscreate_mixed_cart( $products )
- Create cart with mixed products
Custom Assertions
The framework provides subscription-specific assertions via traits:
// Status assertions $this->assertSubscriptionActive( $subscription ); $this->assertSubscriptionOnHold( $subscription ); $this->assertSubscriptionCancelled( $subscription ); // Schedule assertions $this->assertSubscriptionSchedule( 'month', 1, $subscription ); $this->assertSubscriptionDate( 'next_payment', '2024-02-01', $subscription ); // Content assertions $this->assertSubscriptionContainsProduct( $product_id, $subscription ); $this->assertSubscriptionItemCount( 3, $subscription ); $this->assertSubscriptionTotal( 99.99, $subscription ); // Trial assertions $this->assertSubscriptionHasTrial( $subscription ); $this->assertSubscriptionNoTrial( $subscription ); // Payment assertions $this->assertSubscriptionPaymentMethod( 'stripe', $subscription ); $this->assertSubscriptionManual( $subscription ); $this->assertSubscriptionFailedPaymentCount( 2, $subscription ); // Relationship assertions $this->assertSubscriptionHasParentOrder( $subscription ); $this->assertSubscriptionHasRenewalOrders( $subscription, 3 ); $this->assertRenewalOrderCreated( $subscription );
Mock Classes
When WooCommerce Subscriptions is not available, the framework provides mock classes:
WC_Subscription_Mock
A full mock implementation of WC_Subscription that extends WC_Order:
$mock_subscription = new \WCS\Testing\Mocks\WC_Subscription_Mock(); $mock_subscription->set_billing_period( 'month' ); $mock_subscription->set_billing_interval( 1 ); $mock_subscription->update_dates( array( 'start' => gmdate( 'Y-m-d H:i:s' ), 'next_payment' => gmdate( 'Y-m-d H:i:s', strtotime( '+1 month' ) ), ) );
Advanced Usage
Testing Payment Failures
public function test_payment_failure_handling() { // Arrange. $subscription = Subscription::create_subscription( array( 'status' => 'active', ) ); // Act. Subscription::process_payment( $subscription, false ); // Assert. $this->assertSubscriptionOnHold( $subscription ); $this->assertSubscriptionFailedPaymentCount( 1, $subscription ); }
Testing Subscription Trials
public function test_trial_period() { // Arrange. $trial_end = gmdate( 'Y-m-d H:i:s', strtotime( '+14 days' ) ); $subscription = Subscription::create_subscription( array( 'trial_end' => $trial_end, ) ); // Assert. $this->assertSubscriptionHasTrial( $subscription ); $this->assertSubscriptionDate( 'trial_end', $trial_end, $subscription ); }
Testing Renewal Retries
public function test_renewal_retry_mechanism() { // Arrange. $subscription = Subscription::create_subscription(); $failed_renewal = Renewal::create_failed_renewal_order( $subscription, 'Insufficient funds' ); // Act. Renewal::trigger_renewal_retry( $failed_renewal, 1 ); // Assert. $this->assertSubscriptionOnHold( $subscription ); $retry_scheduled = as_next_scheduled_action( 'woocommerce_subscription_payment_retry', array( $failed_renewal->get_id() ) ); $this->assertNotFalse( $retry_scheduled ); }
Testing Mixed Cart (Subscription + Regular Products)
public function test_mixed_cart_checkout() { // Arrange. $regular_product = WC_Helper_Product::create_simple_product(); $subscription_product = Subscription::create_subscription_product(); // Act. $cart = RecurringCart::create_mixed_cart( array( array( 'id' => $regular_product->get_id(), 'quantity' => 1 ), array( 'id' => $subscription_product->get_id(), 'quantity' => 1, 'is_subscription' => true ), ) ); // Assert. $this->assertCount( 2, $cart ); $this->assertTrue( WC()->cart->contains_subscription() ); }
Bootstrap Configuration
Add to your test bootstrap file:
// Load WC Subscriptions mock if not available if ( ! class_exists( 'WC_Subscription' ) ) { require_once __DIR__ . '/vendor/greys/woocommerce-subscriptions-phpunit-framework/src/mocks/class-wc-subscription-mock.php'; } // Define WCS constants if needed if ( ! defined( 'WCS_INIT_TIMESTAMP' ) ) { define( 'WCS_INIT_TIMESTAMP', time() ); }
Best Practices
- Always track subscription IDs for cleanup in
tearDown()
- Use helpers instead of direct database manipulation
- Clear scheduled actions after each test
- Mock external payment gateways to avoid API calls
- Test both success and failure scenarios
- Use realistic test data (proper date formats, valid amounts)
Troubleshooting
"Class WC_Subscription not found"
The framework automatically loads mock classes when WC Subscriptions isn't available. Ensure the mock is loaded in your bootstrap file.
Scheduled actions not clearing
Use the base test case which automatically clears subscription-related scheduled actions:
class MyTest extends UnitTestCase { // Scheduled actions are automatically cleared }
Payment gateway errors
Mock payment gateways to avoid external dependencies:
PaymentGateway::mock_gateway( 'stripe', array( 'supports' => array( 'subscriptions', 'subscription_cancellation' ), ) );
Contributing
Contributions are welcome! Please:
- Write tests for new features
- Follow WordPress coding standards
- Update documentation for API changes
- Add examples for complex features
License
GPL-3.0-or-later
Credits
Built with ❤️ for the WooCommerce community by Greys.
Inspired by and built upon:
- WooCommerce Core Testing Framework
- WordPress Testing Suite
- PHPUnit best practices
Support
For issues, questions, or feature requests, please open an issue on GitHub.