Skip to content

Commit b8a23bd

Browse files
committed
MC-25073: Storefront: Check special/tier/group/rule/option price for product
1 parent 18c339e commit b8a23bd

18 files changed

+793
-7
lines changed
Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Catalog\Block\Product\ListProduct;
9+
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Catalog\Block\Product\ListProduct;
12+
use Magento\Customer\Model\Session;
13+
use Magento\Framework\View\Element\Template;
14+
use Magento\Framework\View\Result\PageFactory;
15+
use Magento\TestFramework\Helper\Bootstrap;
16+
use Magento\TestFramework\ObjectManager;
17+
use PHPUnit\Framework\TestCase;
18+
19+
/**
20+
* Check that product price render correctly on category page.
21+
*
22+
* @magentoDbIsolation enabled
23+
* @magentoAppArea frontend
24+
*/
25+
class CheckProductPriceTest extends TestCase
26+
{
27+
/**
28+
* @var ObjectManager
29+
*/
30+
private $objectManager;
31+
32+
/**
33+
* @var PageFactory
34+
*/
35+
private $pageFactory;
36+
37+
/**
38+
* @var ProductRepositoryInterface
39+
*/
40+
private $productRepository;
41+
42+
/**
43+
* @var Session
44+
*/
45+
private $customerSession;
46+
47+
/**
48+
* @inheritdoc
49+
*/
50+
protected function setUp()
51+
{
52+
$this->objectManager = Bootstrap::getObjectManager();
53+
$this->pageFactory = $this->objectManager->get(PageFactory::class);
54+
$this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
55+
$this->customerSession = $this->objectManager->create(Session::class);
56+
parent::setUp();
57+
}
58+
59+
/**
60+
* Assert that product price without additional price configurations will render as expected.
61+
*
62+
* @magentoDataFixture Magento/Catalog/_files/product_simple_tax_none.php
63+
*
64+
* @return void
65+
*/
66+
public function testCheckProductPriceWithoutAdditionalPriceConfigurations(): void
67+
{
68+
$priceHtml = $this->getProductPriceHtml('simple-product-tax-none');
69+
$this->assertFinalPrice($priceHtml, 205.00);
70+
}
71+
72+
/**
73+
* Assert that product special price rendered correctly.
74+
*
75+
* @magentoDataFixture Magento/Catalog/_files/product_special_price.php
76+
*
77+
* @return void
78+
*/
79+
public function testCheckSpecialPrice(): void
80+
{
81+
$priceHtml = $this->getProductPriceHtml('simple');
82+
$this->assertFinalPrice($priceHtml, 5.99);
83+
$this->assertRegularPrice($priceHtml, 10.00);
84+
}
85+
86+
/**
87+
* Assert that product with fixed tier price is renders correctly.
88+
*
89+
* @magentoDataFixture Magento/Catalog/_files/product_simple_with_fixed_tier_price.php
90+
*
91+
* @return void
92+
*/
93+
public function testCheckFixedTierPrice(): void
94+
{
95+
$priceHtml = $this->getProductPriceHtml('simple-product-tax-none');
96+
$this->assertFinalPrice($priceHtml, 205.00);
97+
$this->assertAsLowAsPrice($priceHtml, 40.00);
98+
}
99+
100+
/**
101+
* Assert that price of product with percent tier price rendered correctly.
102+
*
103+
* @magentoDataFixture Magento/Catalog/_files/product_simple_with_percent_tier_price.php
104+
*
105+
* @return void
106+
*/
107+
public function testCheckPercentTierPrice(): void
108+
{
109+
$priceHtml = $this->getProductPriceHtml('simple-product-tax-none');
110+
$this->assertFinalPrice($priceHtml, 205.00);
111+
$this->assertAsLowAsPrice($priceHtml, 102.50);
112+
}
113+
114+
/**
115+
* Assert that price of product with fixed tier price for not logged user is renders correctly.
116+
*
117+
* @magentoDataFixture Magento/Catalog/_files/product_simple_with_fixed_tier_price_for_not_logged_user.php
118+
*
119+
* @return void
120+
*/
121+
public function testCheckFixedTierPriceForNotLoggedUser(): void
122+
{
123+
$priceHtml = $this->getProductPriceHtml('simple-product-tax-none');
124+
$this->assertFinalPrice($priceHtml, 30.00);
125+
$this->assertRegularPrice($priceHtml, 205.00);
126+
}
127+
128+
/**
129+
* Assert that price of product with fixed tier price for logged user is renders correctly.
130+
*
131+
* @magentoDataFixture Magento/Catalog/_files/product_simple_with_fixed_tier_price_for_logged_user.php
132+
* @magentoDataFixture Magento/Customer/_files/customer.php
133+
* @magentoDbIsolation disabled
134+
* @magentoAppArea frontend
135+
* @magentoAppIsolation enabled
136+
*
137+
* @return void
138+
*/
139+
public function testCheckFixedTierPriceForLoggedUser(): void
140+
{
141+
$priceHtml = $this->getProductPriceHtml('simple-product-tax-none');
142+
$this->assertFinalPrice($priceHtml, 205.00);
143+
$this->assertNotRegExp('/\$10/', $priceHtml);
144+
$this->customerSession->setCustomerId(1);
145+
try {
146+
$priceHtml = $this->getProductPriceHtml('simple-product-tax-none');
147+
$this->assertFinalPrice($priceHtml, 10.00);
148+
$this->assertRegularPrice($priceHtml, 205.00);
149+
} finally {
150+
$this->customerSession->setCustomerId(null);
151+
}
152+
}
153+
154+
/**
155+
* Assert that price of product with catalog rule with action equal to "Apply as percentage of original"
156+
* is renders correctly.
157+
*
158+
* @magentoDataFixture Magento/Catalog/_files/product_simple_tax_none.php
159+
* @magentoDataFixture Magento/CatalogRule/_files/rule_apply_as_percentage_of_original_not_logged_user.php
160+
* @magentoDbIsolation disabled
161+
* @magentoAppArea frontend
162+
*
163+
* @return void
164+
*/
165+
public function testCheckPriceRendersCorrectlyWithApplyAsPercentageOfOriginalRule(): void
166+
{
167+
$priceHtml = $this->getProductPriceHtml('simple-product-tax-none');
168+
$this->assertFinalPrice($priceHtml, 184.50);
169+
$this->assertRegularPrice($priceHtml, 205.00);
170+
}
171+
172+
/**
173+
* Assert that price of product with catalog rule with action equal to "Apply as fixed amount"
174+
* is renders correctly.
175+
*
176+
* @magentoDataFixture Magento/Catalog/_files/product_simple_tax_none.php
177+
* @magentoDataFixture Magento/CatalogRule/_files/rule_apply_as_fixed_amount_not_logged_user.php
178+
* @magentoDbIsolation disabled
179+
* @magentoAppArea frontend
180+
*
181+
* @return void
182+
*/
183+
public function testCheckPriceRendersCorrectlyWithApplyAsFixedAmountRule(): void
184+
{
185+
$priceHtml = $this->getProductPriceHtml('simple-product-tax-none');
186+
$this->assertFinalPrice($priceHtml, 195.00);
187+
$this->assertRegularPrice($priceHtml, 205.00);
188+
}
189+
190+
/**
191+
* Assert that price of product with catalog rule with action equal to "Adjust final price to this percentage"
192+
* is renders correctly.
193+
*
194+
* @magentoDataFixture Magento/Catalog/_files/product_simple_tax_none.php
195+
* @magentoDataFixture Magento/CatalogRule/_files/rule_adjust_final_price_to_this_percentage_not_logged_user.php
196+
* @magentoDbIsolation disabled
197+
* @magentoAppArea frontend
198+
*
199+
* @return void
200+
*/
201+
public function testCheckPriceRendersCorrectlyWithAdjustFinalPriceToThisPercentageRule(): void
202+
{
203+
$priceHtml = $this->getProductPriceHtml('simple-product-tax-none');
204+
$this->assertFinalPrice($priceHtml, 20.50);
205+
$this->assertRegularPrice($priceHtml, 205.00);
206+
}
207+
208+
/**
209+
* Assert that price of product with catalog rule with action equal to "Adjust final price to discount value"
210+
* is renders correctly.
211+
*
212+
* @magentoDataFixture Magento/Catalog/_files/product_simple_tax_none.php
213+
* @magentoDataFixture Magento/CatalogRule/_files/rule_adjust_final_price_to_discount_value_not_logged_user.php
214+
* @magentoDbIsolation disabled
215+
* @magentoAppArea frontend
216+
*
217+
* @return void
218+
*/
219+
public function testCheckPriceRendersCorrectlyWithAdjustFinalPriceToDiscountValueRule(): void
220+
{
221+
$priceHtml = $this->getProductPriceHtml('simple-product-tax-none');
222+
$this->assertFinalPrice($priceHtml, 10.00);
223+
$this->assertRegularPrice($priceHtml, 205.00);
224+
}
225+
226+
/**
227+
* Assert that price html contain "As low as" label and expected price amount.
228+
*
229+
* @param string $priceHtml
230+
* @param float $expectedPrice
231+
* @return void
232+
*/
233+
private function assertAsLowAsPrice(string $priceHtml, float $expectedPrice): void
234+
{
235+
$this->assertRegExp(
236+
sprintf(
237+
'/<span class="price-label">As low as<\/span> {1,}<span.*data-price-amount="%s".*>\$%01.2f<\/span>/',
238+
round($expectedPrice, 2),
239+
$expectedPrice
240+
),
241+
$priceHtml
242+
);
243+
}
244+
245+
/**
246+
* Assert that price html contain expected final price amount.
247+
*
248+
* @param string $priceHtml
249+
* @param float $expectedPrice
250+
* @return void
251+
*/
252+
private function assertFinalPrice(string $priceHtml, float $expectedPrice): void
253+
{
254+
$this->assertRegExp(
255+
sprintf(
256+
'/data-price-type="finalPrice".*<span class="price">\$%01.2f<\/span><\/span>/',
257+
$expectedPrice
258+
),
259+
$priceHtml
260+
);
261+
}
262+
263+
/**
264+
* Assert that price html contain "Regular price" label and expected price amount.
265+
*
266+
* @param string $priceHtml
267+
* @param float $expectedPrice
268+
* @return void
269+
*/
270+
private function assertRegularPrice(string $priceHtml, float $expectedPrice): void
271+
{
272+
$regex = '<span class="price-label">Regular Price<\/span> {1,}<span.*data-price-amount="%s".*>\$%01.2f<\/span>';
273+
$this->assertRegExp(
274+
sprintf("/{$regex}/", round($expectedPrice, 2), $expectedPrice),
275+
$priceHtml
276+
);
277+
}
278+
279+
/**
280+
* Return html of product price without new line characters.
281+
*
282+
* @param string $sku
283+
* @return string
284+
*/
285+
private function getProductPriceHtml(string $sku): string
286+
{
287+
$product = $this->productRepository->get($sku, false, null, true);
288+
289+
return preg_replace('/[\n\r]/', '', $this->getListProductBlock()->getProductPrice($product));
290+
}
291+
292+
/**
293+
* Get list product block from layout.
294+
*
295+
* @return ListProduct
296+
*/
297+
private function getListProductBlock(): ListProduct
298+
{
299+
$page = $this->pageFactory->create();
300+
$page->addHandle([
301+
'default',
302+
'catalog_category_view',
303+
]);
304+
$page->getLayout()->generateXml();
305+
/** @var Template $categoryProductsBlock */
306+
$categoryProductsBlock = $page->getLayout()->getBlock('category.products');
307+
308+
return $categoryProductsBlock->getChildBlock('product_list');
309+
}
310+
}

dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_tax_none_rollback.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,26 @@
55
*/
66
declare(strict_types=1);
77

8-
use Magento\Catalog\Api\Data\ProductInterface;
98
use Magento\Catalog\Api\ProductRepositoryInterface;
109
use Magento\Framework\Exception\NoSuchEntityException;
10+
use Magento\Framework\Registry;
1111
use Magento\TestFramework\Helper\Bootstrap;
1212
use Magento\TestFramework\ObjectManager;
1313

1414
/** @var ObjectManager $objectManager */
1515
$objectManager = Bootstrap::getObjectManager();
1616
/** @var ProductRepositoryInterface $productRepository */
1717
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
18-
/** @var \Magento\Framework\Registry $registry */
19-
$registry =$objectManager->get(\Magento\Framework\Registry::class);
20-
18+
/** @var Registry $registry */
19+
$registry = $objectManager->get(Registry::class);
2120
$registry->unregister('isSecureArea');
2221
$registry->register('isSecureArea', true);
23-
2422
try {
25-
/** @var ProductInterface $product */
2623
$product = $productRepository->get('simple-product-tax-none', false, null, true);
2724
$productRepository->delete($product);
2825
} catch (NoSuchEntityException $e) {
2926
// isolation on
3027
}
31-
28+
$productRepository->cleanCache();
3229
$registry->unregister('isSecureArea');
3330
$registry->register('isSecureArea', false);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
use Magento\Catalog\Api\Data\ProductTierPriceExtensionFactory;
9+
use Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory;
10+
use Magento\Customer\Model\Group;
11+
use Magento\Store\Api\WebsiteRepositoryInterface;
12+
13+
require __DIR__ . '/product_simple_tax_none.php';
14+
15+
$product = $productRepository->get('simple-product-tax-none');
16+
/** @var WebsiteRepositoryInterface $websiteRepository */
17+
$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class);
18+
/** @var ProductTierPriceInterfaceFactory $tierPriceFactory */
19+
$tierPriceFactory = $objectManager->get(ProductTierPriceInterfaceFactory::class);
20+
/** @var ProductTierPriceExtensionFactory $tpExtensionAttributeFactory */
21+
$tpExtensionAttributeFactory = $objectManager->get(ProductTierPriceExtensionFactory::class);
22+
$adminWebsite = $websiteRepository->get('admin');
23+
$tierPriceExtensionAttribute = $tpExtensionAttributeFactory->create(
24+
[
25+
'data' => [
26+
'website_id' => $adminWebsite->getId(),
27+
]
28+
]
29+
);
30+
$tierPrices[] = $tierPriceFactory->create(
31+
[
32+
'data' => [
33+
'customer_group_id' => Group::CUST_GROUP_ALL,
34+
'qty' => 2,
35+
'value' => 40
36+
]
37+
]
38+
)->setExtensionAttributes($tierPriceExtensionAttribute);
39+
$product->setTierPrices($tierPrices);
40+
$productRepository->save($product);

0 commit comments

Comments
 (0)