Skip to content

Commit 952d3ab

Browse files
committed
MC-22569: Storefront: Check special/tier/group/rule/option price for product
1 parent 9a36b85 commit 952d3ab

19 files changed

+849
-0
lines changed
Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
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->create(PageFactory::class);
54+
$this->productRepository = $this->objectManager->create(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_without_price_configurations.php
63+
*
64+
* @return void
65+
*/
66+
public function testCheckProductPriceWithoutAdditionalPriceConfigurations(): void
67+
{
68+
$priceHtml = $this->getProductPriceHtml('simple_product');
69+
$this->assertFinalPrice($priceHtml, 50.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');
96+
$this->assertFinalPrice($priceHtml, 50.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');
110+
$this->assertFinalPrice($priceHtml, 50.00);
111+
$this->assertAsLowAsPrice($priceHtml, 25.00);
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');
124+
$this->assertFinalPrice($priceHtml, 30.00);
125+
$this->assertRegularPrice($priceHtml, 50.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');
142+
$this->assertFinalPrice($priceHtml, 50.00);
143+
$this->assertNotRegExp(
144+
'/\$10/',
145+
$priceHtml
146+
);
147+
$this->customerSession->setCustomerId(1);
148+
try {
149+
$priceHtml = $this->getProductPriceHtml('simple_product');
150+
$this->assertFinalPrice($priceHtml, 10.00);
151+
$this->assertRegularPrice($priceHtml, 50.00);
152+
} finally {
153+
$this->customerSession->setCustomerId(null);
154+
}
155+
}
156+
157+
/**
158+
* Assert that price of product with catalog rule with action equal to "Apply as percentage of original"
159+
* is renders correctly.
160+
*
161+
* @magentoDataFixture Magento/Catalog/_files/product_simple_without_price_configurations.php
162+
* @magentoDataFixture Magento/CatalogRule/_files/rule_apply_as_percentage_of_original_not_logged_user.php
163+
* @magentoDbIsolation disabled
164+
* @magentoAppArea frontend
165+
*
166+
* @return void
167+
*/
168+
public function testCheckPriceRendersCorrectlyWithApplyAsPercentageOfOriginalRule(): void
169+
{
170+
$priceHtml = $this->getProductPriceHtml('simple_product');
171+
$this->assertFinalPrice($priceHtml, 45.00);
172+
$this->assertRegularPrice($priceHtml, 50.00);
173+
}
174+
175+
/**
176+
* Assert that price of product with catalog rule with action equal to "Apply as fixed amount"
177+
* is renders correctly.
178+
*
179+
* @magentoDataFixture Magento/Catalog/_files/product_simple_without_price_configurations.php
180+
* @magentoDataFixture Magento/CatalogRule/_files/rule_apply_as_fixed_amount_not_logged_user.php
181+
* @magentoDbIsolation disabled
182+
* @magentoAppArea frontend
183+
*
184+
* @return void
185+
*/
186+
public function testCheckPriceRendersCorrectlyWithApplyAsFixedAmountRule(): void
187+
{
188+
$priceHtml = $this->getProductPriceHtml('simple_product');
189+
$this->assertFinalPrice($priceHtml, 40.00);
190+
$this->assertRegularPrice($priceHtml, 50.00);
191+
}
192+
193+
/**
194+
* Assert that price of product with catalog rule with action equal to "Adjust final price to this percentage"
195+
* is renders correctly.
196+
*
197+
* @magentoDataFixture Magento/Catalog/_files/product_simple_without_price_configurations.php
198+
* @magentoDataFixture Magento/CatalogRule/_files/rule_adjust_final_price_to_this_percentage_not_logged_user.php
199+
* @magentoDbIsolation disabled
200+
* @magentoAppArea frontend
201+
*
202+
* @return void
203+
*/
204+
public function testCheckPriceRendersCorrectlyWithAdjustFinalPriceToThisPercentageRule(): void
205+
{
206+
$priceHtml = $this->getProductPriceHtml('simple_product');
207+
$this->assertFinalPrice($priceHtml, 5.00);
208+
$this->assertRegularPrice($priceHtml, 50.00);
209+
}
210+
211+
/**
212+
* Assert that price of product with catalog rule with action equal to "Adjust final price to discount value"
213+
* is renders correctly.
214+
*
215+
* @magentoDataFixture Magento/Catalog/_files/product_simple_without_price_configurations.php
216+
* @magentoDataFixture Magento/CatalogRule/_files/rule_adjust_final_price_to_discount_value_not_logged_user.php
217+
* @magentoDbIsolation disabled
218+
* @magentoAppArea frontend
219+
*
220+
* @return void
221+
*/
222+
public function testCheckPriceRendersCorrectlyWithAdjustFinalPriceToDiscountValueRule(): void
223+
{
224+
$priceHtml = $this->getProductPriceHtml('simple_product');
225+
$this->assertFinalPrice($priceHtml, 10.00);
226+
$this->assertRegularPrice($priceHtml, 50.00);
227+
}
228+
229+
/**
230+
* Assert that price html contain "As low as" label and expected price amount.
231+
*
232+
* @param string $priceHtml
233+
* @param float $expectedPrice
234+
* @return void
235+
*/
236+
private function assertAsLowAsPrice(string $priceHtml, float $expectedPrice): void
237+
{
238+
$this->assertRegExp(
239+
sprintf(
240+
'/<span class="price-label">As low as<\/span> {1,}<span.*data-price-amount="%s".*>\$%01.2f<\/span>/',
241+
round($expectedPrice, 2),
242+
$expectedPrice
243+
),
244+
$priceHtml
245+
);
246+
}
247+
248+
/**
249+
* Assert that price html contain expected final price amount.
250+
*
251+
* @param string $priceHtml
252+
* @param float $expectedPrice
253+
* @return void
254+
*/
255+
private function assertFinalPrice(string $priceHtml, float $expectedPrice): void
256+
{
257+
$this->assertRegExp(
258+
sprintf(
259+
'/data-price-type="finalPrice".*<span class="price">\$%01.2f<\/span><\/span>/',
260+
$expectedPrice
261+
),
262+
$priceHtml
263+
);
264+
}
265+
266+
/**
267+
* Assert that price html contain "Regular price" label and expected price amount.
268+
*
269+
* @param string $priceHtml
270+
* @param float $expectedPrice
271+
* @return void
272+
*/
273+
private function assertRegularPrice(string $priceHtml, float $expectedPrice): void
274+
{
275+
$regex = '<span class="price-label">Regular Price<\/span> {1,}<span.*data-price-amount="%s".*>\$%01.2f<\/span>';
276+
$this->assertRegExp(
277+
sprintf("/{$regex}/", round($expectedPrice, 2), $expectedPrice),
278+
$priceHtml
279+
);
280+
}
281+
282+
/**
283+
* Return html of product price without new line characters.
284+
*
285+
* @param string $sku
286+
* @return string
287+
*/
288+
private function getProductPriceHtml(string $sku): string
289+
{
290+
$product = $this->productRepository->get($sku, false, null, true);
291+
292+
return preg_replace('/[\n\r]/', '', $this->getListProductBlock()->getProductPrice($product));
293+
}
294+
295+
/**
296+
* Get list product block from layout.
297+
*
298+
* @return ListProduct
299+
*/
300+
private function getListProductBlock(): ListProduct
301+
{
302+
$page = $this->pageFactory->create(PageFactory::class);
303+
$page->addHandle([
304+
'default',
305+
'catalog_category_view',
306+
]);
307+
$page->getLayout()->generateXml();
308+
/** @var Template $categoryProductsBlock */
309+
$categoryProductsBlock = $page->getLayout()->getBlock('category.products');
310+
311+
return $categoryProductsBlock->getChildBlock('product_list');
312+
}
313+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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_without_price_configurations.php';
14+
15+
/** @var WebsiteRepositoryInterface $websiteRepository */
16+
$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class);
17+
/** @var ProductTierPriceInterfaceFactory $tierPriceFactory */
18+
$tierPriceFactory = $objectManager->get(ProductTierPriceInterfaceFactory::class);
19+
/** @var ProductTierPriceExtensionFactory $tpExtensionAttributeFactory */
20+
$tpExtensionAttributeFactory = $objectManager->get(ProductTierPriceExtensionFactory::class);
21+
$adminWebsite = $websiteRepository->get('admin');
22+
$tierPriceExtensionAttribute = $tpExtensionAttributeFactory->create(
23+
[
24+
'data' => [
25+
'website_id' => $adminWebsite->getId(),
26+
]
27+
]
28+
);
29+
$tierPrices[] = $tierPriceFactory->create(
30+
[
31+
'data' => [
32+
'customer_group_id' => Group::CUST_GROUP_ALL,
33+
'qty' => 2,
34+
'value' => 40
35+
]
36+
]
37+
)->setExtensionAttributes($tierPriceExtensionAttribute);
38+
$product->setTierPrices($tierPrices);
39+
$productRepository->save($product);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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_without_price_configurations.php';
14+
15+
/** @var WebsiteRepositoryInterface $websiteRepository */
16+
$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class);
17+
/** @var ProductTierPriceInterfaceFactory $tierPriceFactory */
18+
$tierPriceFactory = $objectManager->get(ProductTierPriceInterfaceFactory::class);
19+
/** @var ProductTierPriceExtensionFactory $tpExtensionAttributeFactory */
20+
$tpExtensionAttributeFactory = $objectManager->get(ProductTierPriceExtensionFactory::class);
21+
$adminWebsite = $websiteRepository->get('admin');
22+
$tierPriceExtensionAttribute = $tpExtensionAttributeFactory->create(
23+
[
24+
'data' => [
25+
'website_id' => $adminWebsite->getId(),
26+
]
27+
]
28+
);
29+
$tierPrices[] = $tierPriceFactory->create(
30+
[
31+
'data' => [
32+
'customer_group_id' => 1,
33+
'qty' => 1,
34+
'value' => 10
35+
]
36+
]
37+
)->setExtensionAttributes($tierPriceExtensionAttribute);
38+
$product->setTierPrices($tierPrices);
39+
$productRepository->save($product);

0 commit comments

Comments
 (0)