Skip to content
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

fix(checkout): use show delivery options on backorders setting #1136

Merged
merged 11 commits into from
Aug 5, 2024
10 changes: 9 additions & 1 deletion src/Hooks/CheckoutScriptHooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,19 @@ private function shouldShowDeliveryOptions(): bool

$showDeliveryOptions = false;

$deliveryOptionsEnabledWhenOnBackorder = Settings::get(
CheckoutSettings::ENABLE_DELIVERY_OPTIONS_WHEN_NOT_IN_STOCK,
CheckoutSettings::ID
);

foreach (WC()->cart->get_cart() as $cartItem) {
/** @var WC_Product $product */
$product = $cartItem['data'];

if (! $product->is_virtual() && ! $product->is_on_backorder($cartItem['quantity'])) {
$productIsVirtual = $product->is_virtual();
$productOnBackorder = $product->is_on_backorder($cartItem['quantity']);

if (! $productIsVirtual && (! $productOnBackorder || $deliveryOptionsEnabledWhenOnBackorder)) {
$showDeliveryOptions = true;
break;
}
Expand Down
98 changes: 89 additions & 9 deletions tests/Mock/MockWcCart.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,24 @@
array $variation = [],
array $cartItemData = []
): void {
for ($i = 0; $i < $quantity; $i++) {
$this->items[] = new WC_Product($productId);
$cartId = $this->generate_cart_id($productId, $variationId, $variation, $cartItemData);
$cartItemKey = $this->find_product_in_cart($cartId);

if ($cartItemKey) {
$this->items[$cartItemKey]['quantity'] += $quantity;
} else {
$this->items[] = [
'data' => new WC_Product($productId),
'quantity' => $quantity,
];
}
}

public function get_cart()

Check notice on line 50 in tests/Mock/MockWcCart.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/Mock/MockWcCart.php#L50

The method get_cart is not named in camelCase.
{
return $this->items;
}

/**
* @return void
*/
Expand All @@ -53,13 +66,12 @@
public function get_shipping_packages(): array
{
// calculate weight of all products in cart
$weight = array_reduce(
$this->items,
static function (float $carry, WC_Product $item) {
return $carry + (float) $item->get_weight();
},
0
);
$weight = 0;
foreach ($this->items as $item) {
/** @var \WC_Product $wcProduct */
$wcProduct = $item['data'];
$weight += $wcProduct->get_weight() * $item['quantity'];
}

if ($weight > 10) {
return [];
Expand All @@ -69,4 +81,72 @@
'flat_rate:0' => [],
];
}

/**
* Generate a unique ID for the cart item being added.
*
* @param int $productId - id of the product the key is being generated for.
* @param int $variationId of the product the key is being generated for.
* @param array $variation data for the cart item.
* @param array $cartItemData other cart item data passed which affects this items uniqueness in the cart.
*
* @return string cart item key
*/
public function generate_cart_id(

Check notice on line 95 in tests/Mock/MockWcCart.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/Mock/MockWcCart.php#L95

The method generate_cart_id is not named in camelCase.
int $productId,
int $variationId = 0,
array $variation = [],
array $cartItemData = []
): string {
$idParts = [$productId];

if ($variationId && 0 !== $variationId) {
$idParts[] = $variationId;
}

if (is_array($variation) && ! empty($variation)) {
$variationKey = '';
foreach ($variation as $key => $value) {
$variationKey .= trim($key) . trim($value);
}
$idParts[] = $variationKey;
}

if (is_array($cartItemData) && ! empty($cartItemData)) {
$cartItemDataKey = '';
foreach ($cartItemData as $key => $value) {
if (is_array($value) || is_object($value)) {
$value = http_build_query($value);
}
$cartItemDataKey .= trim($key) . trim($value);
}
$idParts[] = $cartItemDataKey;
}

return apply_filters(
'woocommerce_cart_id',
md5(implode('_', $idParts))
);
}

/**
* Check if product is in the cart and return cart item key.
* Cart item key will be unique based on the item and its properties, such as variations.
* ONLY RETURNS A KEY! DOES NOT RETURN THE ITEM!
*
* @param mixed $cartId id of product to find in the cart.
*
* @return string cart item key
*/
public function find_product_in_cart($cartId = false): string

Check notice on line 141 in tests/Mock/MockWcCart.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/Mock/MockWcCart.php#L141

The method find_product_in_cart is not named in camelCase.
{
$thisItemsIsArray = is_array($this->items);
$itemAlreadyExists = isset($this->items[$cartId]);

if ($cartId !== false && $thisItemsIsArray && $itemAlreadyExists) {
return $cartId;
}

return '';
}
}
93 changes: 93 additions & 0 deletions tests/Mock/MockWpEnqueue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

declare(strict_types=1);

namespace MyParcelNL\WooCommerce\Tests\Mock;

use MyParcelNL\Pdk\Base\Support\Arr;
use MyParcelNL\Pdk\Base\Support\Collection;

final class MockWpEnqueue implements StaticMockInterface
{
/**
* @var \MyParcelNL\Pdk\Base\Support\Collection
*/
private static $queuedItems;

/**
* @param $handle
* @param $src
* @param $deps
* @param $ver
* @param $in_footer
*
* @return void
*/
public static function add($handle, $src, $deps, $ver, $in_footer): void

Check notice on line 26 in tests/Mock/MockWpEnqueue.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/Mock/MockWpEnqueue.php#L26

The parameter $in_footer is not named in camelCase.
{
$existing = array_filter(Arr::wrap(self::get($handle)));

self::$queuedItems->put(
$handle,
array_merge($existing, [
[
'src' => $src,
'deps' => $deps,
'ver' => $ver,
'in_footer' => $in_footer,

Check warning on line 37 in tests/Mock/MockWpEnqueue.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/Mock/MockWpEnqueue.php#L37

The variable $in_footer is not named in camelCase.
],
])
);
}

/**
* @return \MyParcelNL\Pdk\Base\Support\Collection
*/
public static function all(): Collection
{
return self::getQueuedItems();
}

/**
* @param string $tag
*
* @return array
*/
public static function get(string $tag): array
{
return self::getQueuedItems()
->get($tag, []);
}

public static function reset(): void
{
self::$queuedItems = new Collection();
}

public static function toArray(): array
{
return self::getQueuedItems()
->map(static function (array $actions) {
return (new Collection(Arr::pluck($actions, 'function')))->map(static function ($function) {
if (! is_array($function)) {
return $function;
}

return implode('::', [get_class($function[0]), $function[1]]);
});
})
->toArray();
}

/**
* @return \MyParcelNL\Pdk\Base\Support\Collection
*/
private static function getQueuedItems(): Collection
{
if (null === self::$queuedItems) {
self::reset();
}

return self::$queuedItems;
}
}
83 changes: 83 additions & 0 deletions tests/Unit/Hooks/CheckoutScriptHooksTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php
/** @noinspection StaticClosureCanBeUsedInspection */

declare(strict_types=1);

namespace MyParcelNL\WooCommerce\Hooks;

use MyParcelNL\Pdk\Facade\Pdk;
use MyParcelNL\Pdk\Settings\Model\CheckoutSettings;
use MyParcelNL\WooCommerce\Tests\Mock\MockWpEnqueue;
use MyParcelNL\WooCommerce\Tests\Uses\UsesMockWcPdkInstance;
use WC_Product;
use function MyParcelNL\Pdk\Tests\factory;
use function MyParcelNL\Pdk\Tests\usesShared;
use function MyParcelNL\WooCommerce\Tests\wpFactory;

usesShared(new UsesMockWcPdkInstance());

it(
'enqueues frontend scripts',
function (
bool $enableDeliveryOptions,
bool $enableDeliveryOptionsWhenNotInStock,
array $productData,
array $expected
) {
factory(CheckoutSettings::class)
->withEnableDeliveryOptions($enableDeliveryOptions)
->withEnableDeliveryOptionsWhenNotInStock($enableDeliveryOptionsWhenNotInStock)
->store();

$product = wpFactory(WC_Product::class)
->with($productData)
->make();

WC()->cart->add_to_cart($product->get_id(), 2);

/** @var \MyParcelNL\WooCommerce\Hooks\CheckoutScriptHooks $class */
$class = Pdk::get(CheckoutScriptHooks::class);

$class->enqueueFrontendScripts();

$all =
MockWpEnqueue::all()
->all();

expect($all)
->toHaveKeys($expected['toContain'])
->and($all)->not->toHaveKeys($expected['notToContain']);

MockWpEnqueue::reset();
WC()->cart->empty_cart();
}
)
->with([
'enable all, in stock' => [
'enableDeliveryOptions' => true,
'enableDeliveryOptionsWhenNotInStock' => true,
'productData' => ['id' => 1, 'is_on_backorder' => false],
'expected' => [
'toContain' => ['myparcelnl-delivery-options'],
'notToContain' => [],
],
],
'enable delivery options, on backorder' => [
'enableDeliveryOptions' => true,
'enableDeliveryOptionsWhenNotInStock' => false,
'productData' => ['id' => 1, 'is_on_backorder' => true],
'expected' => [
'toContain' => [],
FlorianSDV marked this conversation as resolved.
Show resolved Hide resolved
'notToContain' => ['myparcelnl-delivery-options'],
],
],
'enable all, on backorder' => [
'enableDeliveryOptions' => true,
'enableDeliveryOptionsWhenNotInStock' => true,
'productData' => ['id' => 1, 'is_on_backorder' => true],
'expected' => [
'toContain' => ['myparcelnl-delivery-options'],
'notToContain' => [],
],
],
]);
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
"value": ["5.0.0-alpha.1"]
}
],
"parentProduct": null,
"product": {
"id": "product",
"countryOfOrigin": "BB",
"customsCode": "1234",
"disableDeliveryOptions": -1,
Expand All @@ -66,7 +66,7 @@
"exportSignature": -1,
"fitInDigitalStamp": 7,
"fitInMailbox": 7,
"id": "product",
"packageType": "digital_stamp"
},
"parentProduct": null
}
}
11 changes: 11 additions & 0 deletions tests/mock_wp_functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use MyParcelNL\Pdk\Facade\Pdk;
use MyParcelNL\WooCommerce\Tests\Exception\DieException;
use MyParcelNL\WooCommerce\Tests\Mock\MockWpActions;
use MyParcelNL\WooCommerce\Tests\Mock\MockWpEnqueue;
use MyParcelNL\WooCommerce\Tests\Mock\MockWpMeta;
use MyParcelNL\WooCommerce\Tests\Mock\MockWpUser;
use MyParcelNL\WooCommerce\Tests\Mock\WordPressOptions;
Expand Down Expand Up @@ -151,3 +152,13 @@
{
return $value;
}

function wp_enqueue_script($handle, $src = '', $deps = [], $ver = false, $in_footer = false)

Check notice on line 156 in tests/mock_wp_functions.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/mock_wp_functions.php#L156

The parameter $in_footer is not named in camelCase.
{
MockWpEnqueue::add($handle, $src, $deps, $ver, $in_footer);

Check warning on line 158 in tests/mock_wp_functions.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/mock_wp_functions.php#L158

The variable $in_footer is not named in camelCase.
}

function wp_enqueue_style($handle, $src, $deps, $version, $media)
{
MockWpEnqueue::add($handle, $src, $deps, $version, $media);
}

Check notice on line 164 in tests/mock_wp_functions.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/mock_wp_functions.php#L164

Expected 1 newline at end of file; 0 found

Check notice on line 164 in tests/mock_wp_functions.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/mock_wp_functions.php#L164

File must end with a newline character
Loading