Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public static function sanitize_subscription( $subscription ) {
}

/**
* Get the user's subscription within a grouped or variable subscription product.
* Get the user's active subscription for a product (simple, grouped, or variable).
*
* @param \WC_Product $product Product.
* @param int|null $user_id User ID. Defaults to the current user.
Expand All @@ -161,16 +161,19 @@ public static function get_user_subscription( $product, $user_id = null ) {
return null;
}

$products = $product->get_children();
$children = $product->get_children();
$user_subscriptions = wcs_get_users_subscriptions( $user_id );

foreach ( $products as $product ) {
$product = wc_get_product( $product );
if ( ! $product ) {
// Simple products have no children; check their status directly.
$product_ids = ! empty( $children ) ? $children : [ $product->get_id() ];
Comment thread
jason10lee marked this conversation as resolved.

foreach ( $product_ids as $product_id ) {
Comment thread
jason10lee marked this conversation as resolved.
$product_to_check = wc_get_product( $product_id );
if ( ! $product_to_check ) {
continue;
}
foreach ( $user_subscriptions as $subscription ) {
if ( $subscription->has_product( $product->get_id() ) && $subscription->has_status( 'active' ) ) {
if ( $subscription->has_product( $product_to_check->get_id() ) && $subscription->has_status( WooCommerce_Connection::ACTIVE_SUBSCRIPTION_STATUSES ) ) {
return $subscription;
Comment thread
jason10lee marked this conversation as resolved.
}
}
Expand Down
44 changes: 44 additions & 0 deletions tests/mocks/wc-mocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,50 @@ public function save() {}

$orders_database = [];
$subscriptions_database = [];
$products_database = [];

class WC_Product {
protected $data = [];
public function __construct( $data = [] ) {
$this->data = $data;
}
public function get_id() {
return $this->data['id'] ?? 0;
}
public function get_children() {
return $this->data['children'] ?? [];
}
public function get_type() {
return $this->data['type'] ?? 'simple';
}
public function get_name() {
return $this->data['name'] ?? '';
}
public function get_price() {
return $this->data['price'] ?? '0';
}
}

/**
* Register a mock product in the global products database.
*
* @param array $data Product data including 'id', 'children', 'type', 'name', 'price'.
* @return WC_Product
*/
function wc_create_mock_product( $data = [] ) {
global $products_database;
$product = new WC_Product( $data );
$products_database[ $product->get_id() ] = $product;
return $product;
}

function wc_get_product( $product_id ) {
global $products_database;
if ( $product_id instanceof WC_Product ) {
return $product_id;
}
return $products_database[ $product_id ] ?? null;
}

class WC_Order {
public $data = [ 'items' => [] ];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,24 @@
use Newspack\WooCommerce_Subscriptions;
use Newspack\Reader_Activation;

require_once __DIR__ . '/../../../mocks/wc-mocks.php';

/**
* Test WooCommerce Subscriptions integration functionality.
*
* @group WooCommerce_Subscriptions_Integration
*/
class Newspack_Test_WooCommerce_Subscriptions extends WP_UnitTestCase {
/**
* Reset the global mock databases before each test.
*/
public function set_up() {
parent::set_up();
global $subscriptions_database, $products_database;
$subscriptions_database = [];
$products_database = [];
}

/**
* Test WooCommerce_Subscriptions::is_active.
*/
Expand All @@ -29,4 +41,123 @@ public function test_is_enabled() {
$is_enabled = WooCommerce_Subscriptions::is_enabled();
$this->assertFalse( $is_enabled, 'WooCommerce Subscriptions integration should not be active if the main WooCommerce plugin is not available.' );
}

/**
* Test get_user_subscription returns an active subscription for a simple product.
*/
public function test_get_user_subscription_simple_product_active() {
$user_id = $this->factory->user->create();
$product_id = 100;
$product = wc_create_mock_product( [ 'id' => $product_id ] );

wcs_create_subscription(
[
'customer_id' => $user_id,
'status' => 'active',
'products' => [ $product_id ],
]
);

$result = WooCommerce_Subscriptions::get_user_subscription( $product, $user_id );
$this->assertInstanceOf( WC_Subscription::class, $result, 'Should find active subscription for a simple product.' );
}

/**
* Test get_user_subscription returns null for a simple product with no subscription.
*/
public function test_get_user_subscription_simple_product_none() {
$user_id = $this->factory->user->create();
$product = wc_create_mock_product( [ 'id' => 200 ] );

$result = WooCommerce_Subscriptions::get_user_subscription( $product, $user_id );
$this->assertNull( $result, 'Should return null when the user has no subscription for the product.' );
}

/**
* Test get_user_subscription finds an active subscription on a child product.
*/
public function test_get_user_subscription_variable_product() {
$user_id = $this->factory->user->create();
$child_id = 301;

wc_create_mock_product( [ 'id' => $child_id ] );
$parent = wc_create_mock_product(
[
'id' => 300,
'type' => 'variable',
'children' => [ $child_id ],
]
);

wcs_create_subscription(
[
'customer_id' => $user_id,
'status' => 'active',
'products' => [ $child_id ],
]
);

$result = WooCommerce_Subscriptions::get_user_subscription( $parent, $user_id );
$this->assertInstanceOf( WC_Subscription::class, $result, 'Should find active subscription on a child/variation product.' );
}

/**
* Test get_user_subscription treats pending-cancel as active.
*/
public function test_get_user_subscription_pending_cancel_is_active() {
$user_id = $this->factory->user->create();
$product_id = 400;
$product = wc_create_mock_product( [ 'id' => $product_id ] );

wcs_create_subscription(
[
'customer_id' => $user_id,
'status' => 'pending-cancel',
'products' => [ $product_id ],
]
);

$result = WooCommerce_Subscriptions::get_user_subscription( $product, $user_id );
$this->assertInstanceOf( WC_Subscription::class, $result, 'Should treat pending-cancel subscriptions as active.' );
}

/**
* Test get_user_subscription returns null for an expired subscription.
*/
public function test_get_user_subscription_expired_returns_null() {
$user_id = $this->factory->user->create();
$product_id = 500;
$product = wc_create_mock_product( [ 'id' => $product_id ] );

wcs_create_subscription(
[
'customer_id' => $user_id,
'status' => 'expired',
'products' => [ $product_id ],
]
);

$result = WooCommerce_Subscriptions::get_user_subscription( $product, $user_id );
$this->assertNull( $result, 'Should return null for an expired subscription.' );
}

/**
* Test get_user_subscription returns null for a cancelled subscription.
*/
public function test_get_user_subscription_cancelled_returns_null() {
$user_id = $this->factory->user->create();
$product_id = 600;
$product = wc_create_mock_product( [ 'id' => $product_id ] );

wcs_create_subscription(
[
'customer_id' => $user_id,
'status' => 'cancelled',
'products' => [ $product_id ],
]
);

$result = WooCommerce_Subscriptions::get_user_subscription( $product, $user_id );
$this->assertNull( $result, 'Should return null for a cancelled subscription.' );
}
}
Loading