mirror of
https://github.com/wp-graphql/wp-graphql-woocommerce.git
synced 2026-08-14 12:53:44 +02:00
* fix: downloadsRemaining returns null for valid numeric string values Use is_numeric() + intval() instead of 'integer' === gettype() to handle cases where WooCommerce stores downloads_remaining as a numeric string. Mirrors WooCommerce's own approach in its download templates. Co-authored-by: Nestor Vera <hacknug@users.noreply.github.com> Closes #937 * fix: Match CI phpcov php-code-coverage version to Docker container The Docker container uses php-code-coverage 9.2.x which serializes coverage with v9 classes (e.g. Xdebug3Driver). phpcov v9 bundles php-code-coverage v11 with different classes, causing __PHP_Incomplete_Class errors. Pin to phpcov v8 + php-code-coverage v9 to match the Docker environment. --------- Co-authored-by: Nestor Vera <hacknug@users.noreply.github.com>
454 lines
12 KiB
PHP
454 lines
12 KiB
PHP
<?php
|
|
|
|
class DownloadableItemQueriesTest extends \Tests\WPGraphQL\WooCommerce\TestCase\WooGraphQLTestCase {
|
|
public function setUp(): void {
|
|
// before
|
|
parent::setUp();
|
|
|
|
update_option( 'woocommerce_downloads_grant_access_after_payment', 'yes' );
|
|
}
|
|
|
|
// tests
|
|
public function testOrderToDownloadableItemsQuery() {
|
|
$downloadable_product = $this->factory->product->createSimple(
|
|
[
|
|
'downloadable' => true,
|
|
'downloads' => [ $this->factory->product->createDownload() ],
|
|
]
|
|
);
|
|
$order_id = $this->factory->order->createNew(
|
|
[
|
|
'status' => 'completed',
|
|
'customer_id' => $this->customer,
|
|
],
|
|
[
|
|
'line_items' => [
|
|
[
|
|
'product' => $downloadable_product,
|
|
'qty' => 1,
|
|
],
|
|
],
|
|
]
|
|
);
|
|
|
|
// Force download permission updated.
|
|
wc_downloadable_product_permissions( $order_id, true );
|
|
|
|
$order = wc_get_order( $order_id );
|
|
$downloadable_items = $order->get_downloadable_items();
|
|
|
|
$query = '
|
|
query {
|
|
customer {
|
|
orders {
|
|
nodes {
|
|
downloadableItems(first: 1) {
|
|
nodes {
|
|
url
|
|
accessExpires
|
|
downloadId
|
|
downloadsRemaining
|
|
name
|
|
product {
|
|
databaseId
|
|
}
|
|
download {
|
|
downloadId
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
';
|
|
|
|
/**
|
|
* Assertion One
|
|
*
|
|
* Tests query results
|
|
*/
|
|
$this->loginAsCustomer();
|
|
$response = $this->graphql( compact( 'query' ) );
|
|
$expected = array_map(
|
|
function ( $item ) {
|
|
return $this->expectedNode(
|
|
'customer.orders.nodes',
|
|
[
|
|
$this->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[
|
|
$this->expectedField( 'url', $item['download_url'] ),
|
|
$this->expectedField( 'accessExpires', $item['access_expires'] ),
|
|
$this->expectedField( 'downloadId', $item['download_id'] ),
|
|
$this->expectedField(
|
|
'downloadsRemaining',
|
|
isset( $item['downloads_remaining'] ) && is_numeric( $item['downloads_remaining'] )
|
|
? intval( $item['downloads_remaining'] )
|
|
: static::IS_NULL
|
|
),
|
|
$this->expectedField( 'name', $item['download_name'] ),
|
|
$this->expectedField( 'product.databaseId', $item['product_id'] ),
|
|
$this->expectedField( 'download.downloadId', $item['download_id'] ),
|
|
]
|
|
),
|
|
],
|
|
0
|
|
);
|
|
},
|
|
$downloadable_items
|
|
);
|
|
|
|
$this->assertQuerySuccessful( $response, $expected );
|
|
}
|
|
|
|
public function testOrderToDownloadableItemsQueryArgs() {
|
|
$valid_product = $this->factory->product->createSimple(
|
|
[
|
|
'downloadable' => true,
|
|
'downloads' => [ $this->factory->product->createDownload() ],
|
|
]
|
|
);
|
|
$downloadable_product = $this->factory->product->createSimple(
|
|
[
|
|
'download_expiry' => 5,
|
|
'download_limit' => 3,
|
|
'downloadable' => true,
|
|
'downloads' => [ $this->factory->product->createDownload() ],
|
|
]
|
|
);
|
|
$downloaded_product = $this->factory->product->createSimple(
|
|
[
|
|
'download_limit' => 0,
|
|
'downloadable' => true,
|
|
'downloads' => [ $this->factory->product->createDownload() ],
|
|
]
|
|
);
|
|
|
|
$order_id = $this->factory->order->createNew(
|
|
[
|
|
'status' => 'completed',
|
|
'customer_id' => $this->customer,
|
|
],
|
|
[
|
|
'line_items' => [
|
|
[
|
|
'product' => $valid_product,
|
|
'qty' => 1,
|
|
],
|
|
[
|
|
'product' => $downloadable_product,
|
|
'qty' => 1,
|
|
],
|
|
[
|
|
'product' => $downloaded_product,
|
|
'qty' => 1,
|
|
],
|
|
],
|
|
]
|
|
);
|
|
|
|
// Force download permission updated.
|
|
wc_downloadable_product_permissions( $order_id, true );
|
|
|
|
$query = '
|
|
query($active: Boolean, $hasDownloadsRemaining: Boolean) {
|
|
customer {
|
|
orders {
|
|
nodes {
|
|
downloadableItems(where: { active: $active, hasDownloadsRemaining: $hasDownloadsRemaining }) {
|
|
nodes {
|
|
product {
|
|
databaseId
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
';
|
|
|
|
/**
|
|
* Assertion One
|
|
*
|
|
* Tests "active" whereArg
|
|
*/
|
|
$this->loginAsCustomer();
|
|
$variables = [ 'active' => true ];
|
|
$response = $this->graphql( compact( 'query', 'variables' ) );
|
|
$expected = [
|
|
$this->expectedNode(
|
|
'customer.orders.nodes',
|
|
[
|
|
$this->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[ $this->expectedField( 'product.databaseId', $valid_product ) ]
|
|
),
|
|
$this->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[ $this->expectedField( 'product.databaseId', $downloadable_product ) ]
|
|
),
|
|
$this->not()->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[ $this->expectedField( 'product.databaseId', $downloaded_product ) ]
|
|
),
|
|
],
|
|
0
|
|
),
|
|
];
|
|
|
|
$this->assertQuerySuccessful( $response, $expected );
|
|
|
|
/**
|
|
* Assertion Two
|
|
*
|
|
* Tests "active" whereArg reversed
|
|
*/
|
|
$variables = [ 'active' => false ];
|
|
$response = $this->graphql( compact( 'query', 'variables' ) );
|
|
$expected = [
|
|
$this->expectedNode(
|
|
'customer.orders.nodes',
|
|
[
|
|
$this->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[ $this->expectedField( 'product.databaseId', $downloaded_product ) ]
|
|
),
|
|
$this->not()->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[ $this->expectedField( 'product.databaseId', $valid_product ) ]
|
|
),
|
|
$this->not()->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[ $this->expectedField( 'product.databaseId', $downloadable_product ) ]
|
|
),
|
|
],
|
|
0
|
|
),
|
|
];
|
|
|
|
$this->assertQuerySuccessful( $response, $expected );
|
|
|
|
/**
|
|
* Assertion Three
|
|
*
|
|
* Tests "hasDownloadsRemaining" whereArg
|
|
*/
|
|
$variables = [ 'hasDownloadsRemaining' => true ];
|
|
$response = $this->graphql( compact( 'query', 'variables' ) );
|
|
$expected = [
|
|
$this->expectedNode(
|
|
'customer.orders.nodes',
|
|
[
|
|
$this->not()->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[ $this->expectedField( 'product.databaseId', $downloaded_product ) ]
|
|
),
|
|
$this->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[ $this->expectedField( 'product.databaseId', $valid_product ) ]
|
|
),
|
|
$this->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[ $this->expectedField( 'product.databaseId', $downloadable_product ) ]
|
|
),
|
|
],
|
|
0
|
|
),
|
|
];
|
|
|
|
$this->assertQuerySuccessful( $response, $expected );
|
|
|
|
/**
|
|
* Assertion Four
|
|
*
|
|
* Tests "hasDownloadsRemaining" whereArg reversed
|
|
*/
|
|
$variables = [ 'hasDownloadsRemaining' => false ];
|
|
$response = $this->graphql( compact( 'query', 'variables' ) );
|
|
$expected = [
|
|
$this->expectedNode(
|
|
'customer.orders.nodes',
|
|
[
|
|
$this->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[ $this->expectedField( 'product.databaseId', $downloaded_product ) ]
|
|
),
|
|
$this->not()->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[ $this->expectedField( 'product.databaseId', $valid_product ) ]
|
|
),
|
|
$this->not()->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[ $this->expectedField( 'product.databaseId', $downloadable_product ) ]
|
|
),
|
|
],
|
|
0
|
|
),
|
|
];
|
|
|
|
$this->assertQuerySuccessful( $response, $expected );
|
|
}
|
|
|
|
public function testCustomerToDownloadableItemsQuery() {
|
|
$downloadable_product = $this->factory->product->createSimple(
|
|
[
|
|
'downloadable' => true,
|
|
'downloads' => [ $this->factory->product->createDownload() ],
|
|
]
|
|
);
|
|
$order_id = $this->factory->order->createNew(
|
|
[
|
|
'status' => 'completed',
|
|
'customer_id' => $this->customer,
|
|
],
|
|
[
|
|
'line_items' => [
|
|
[
|
|
'product' => $downloadable_product,
|
|
'qty' => 1,
|
|
],
|
|
],
|
|
]
|
|
);
|
|
|
|
// Force download permission updated.
|
|
wc_downloadable_product_permissions( $order_id, true );
|
|
|
|
$downloadable_items = \wc_get_customer_available_downloads( $this->customer );
|
|
|
|
$query = '
|
|
query {
|
|
customer {
|
|
downloadableItems(first: 1) {
|
|
nodes {
|
|
url
|
|
accessExpires
|
|
downloadId
|
|
downloadsRemaining
|
|
name
|
|
product {
|
|
databaseId
|
|
}
|
|
download {
|
|
downloadId
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
';
|
|
|
|
/**
|
|
* Assertion One
|
|
*
|
|
* Tests query results
|
|
*/
|
|
$this->loginAsCustomer();
|
|
$response = $this->graphql( compact( 'query' ) );
|
|
$expected = array_map(
|
|
function ( $item ) {
|
|
return $this->expectedNode(
|
|
'customer.downloadableItems.nodes',
|
|
[
|
|
$this->expectedField( 'url', $item['download_url'] ),
|
|
$this->expectedField(
|
|
'accessExpires',
|
|
! empty( $item['access_expires'] ) ? $item['access_expires'] : static::IS_NULL
|
|
),
|
|
$this->expectedField( 'downloadId', $item['download_id'] ),
|
|
$this->expectedField(
|
|
'downloadsRemaining',
|
|
isset( $item['downloads_remaining'] ) && is_numeric( $item['downloads_remaining'] )
|
|
? intval( $item['downloads_remaining'] )
|
|
: static::IS_NULL
|
|
),
|
|
$this->expectedField( 'name', $item['download_name'] ),
|
|
$this->expectedField( 'product.databaseId', $item['product_id'] ),
|
|
$this->expectedField( 'download.downloadId', $item['download_id'] ),
|
|
],
|
|
0
|
|
);
|
|
},
|
|
$downloadable_items
|
|
);
|
|
|
|
$this->assertQuerySuccessful( $response, $expected );
|
|
}
|
|
|
|
public function testDownloadsRemainingHandlesNumericString() {
|
|
$downloadable_product = $this->factory->product->createSimple(
|
|
[
|
|
'download_limit' => 5,
|
|
'downloadable' => true,
|
|
'downloads' => [ $this->factory->product->createDownload() ],
|
|
]
|
|
);
|
|
|
|
$order_id = $this->factory->order->createNew(
|
|
[
|
|
'status' => 'completed',
|
|
'customer_id' => $this->customer,
|
|
],
|
|
[
|
|
'line_items' => [
|
|
[
|
|
'product' => $downloadable_product,
|
|
'qty' => 1,
|
|
],
|
|
],
|
|
]
|
|
);
|
|
|
|
wc_downloadable_product_permissions( $order_id, true );
|
|
|
|
// Force downloads_remaining to a numeric string as WooCommerce sometimes stores it.
|
|
global $wpdb;
|
|
$wpdb->update(
|
|
"{$wpdb->prefix}woocommerce_downloadable_product_permissions",
|
|
[ 'downloads_remaining' => '3' ],
|
|
[
|
|
'order_id' => $order_id,
|
|
'product_id' => $downloadable_product,
|
|
]
|
|
);
|
|
|
|
$this->loginAsCustomer();
|
|
|
|
$query = '
|
|
query {
|
|
customer {
|
|
orders {
|
|
nodes {
|
|
downloadableItems(first: 1) {
|
|
nodes {
|
|
downloadsRemaining
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
';
|
|
|
|
$response = $this->graphql( compact( 'query' ) );
|
|
$expected = [
|
|
$this->expectedNode(
|
|
'customer.orders.nodes',
|
|
[
|
|
$this->expectedNode(
|
|
'downloadableItems.nodes',
|
|
[
|
|
$this->expectedField( 'downloadsRemaining', 3 ),
|
|
]
|
|
),
|
|
],
|
|
0
|
|
),
|
|
];
|
|
|
|
$this->assertQuerySuccessful( $response, $expected );
|
|
}
|
|
}
|