Skip to content

Commit af2ec60

Browse files
authored
Merge pull request #2855 from magento-borg/MAGETWO-91528
[borg] MAGETWO-91528: Customizable options truncated when displaying ordered product in admin
2 parents 21990f7 + 74cac07 commit af2ec60

File tree

12 files changed

+446
-6
lines changed

12 files changed

+446
-6
lines changed

app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,10 @@
280280
<requiredEntity type="product_option">ProductOptionDateTime</requiredEntity>
281281
<requiredEntity type="product_option">ProductOptionTime</requiredEntity>
282282
</entity>
283+
<entity name="productWithOptions2" type="product">
284+
<var key="sku" entityType="product" entityKey="sku" />
285+
<requiredEntity type="product_option">ProductOptionDropDownWithLongValuesTitle</requiredEntity>
286+
</entity>
283287
<entity name="ApiVirtualProductWithDescription" type="product">
284288
<data key="sku" unique="suffix">api-virtual-product</data>
285289
<data key="type_id">virtual</data>

app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionData.xml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@
5959
<requiredEntity type="product_option_value">ProductOptionValueDropdown1</requiredEntity>
6060
<requiredEntity type="product_option_value">ProductOptionValueDropdown2</requiredEntity>
6161
</entity>
62+
<entity name="ProductOptionDropDownWithLongValuesTitle" type="product_option">
63+
<var key="product_sku" entityType="product" entityKey="sku" />
64+
<data key="title">OptionDropDownWithLongTitles</data>
65+
<data key="type">drop_down</data>
66+
<data key="sort_order">4</data>
67+
<data key="is_require">true</data>
68+
<requiredEntity type="product_option_value">ProductOptionValueDropdownLongTitle1</requiredEntity>
69+
<requiredEntity type="product_option_value">ProductOptionValueDropdownLongTitle2</requiredEntity>
70+
</entity>
6271
<entity name="ProductOptionRadiobutton" type="product_option">
6372
<var key="product_sku" entityType="product" entityKey="sku" />
6473
<data key="title">OptionRadioButtons</data>
@@ -112,4 +121,4 @@
112121
<data key="price">0.00</data>
113122
<data key="price_type">percent</data>
114123
</entity>
115-
</entities>
124+
</entities>

app/code/Magento/Catalog/Test/Mftf/Data/ProductOptionValueData.xml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,16 @@
5050
<data key="price">2</data>
5151
<data key="price_type">fixed</data>
5252
</entity>
53-
</entities>
53+
<entity name="ProductOptionValueDropdownLongTitle1" type="product_option_value">
54+
<data key="title">Optisfvdklvfnkljvnfdklpvnfdjklfdvnjkvfdkjnvfdjkfvndj11111Optisfvdklvfnkljvnfdklpvnfdjklfdvnjkvfdkjnvfdjkfvndj11111</data>
55+
<data key="sort_order">1</data>
56+
<data key="price">10</data>
57+
<data key="price_type">fixed</data>
58+
</entity>
59+
<entity name="ProductOptionValueDropdownLongTitle2" type="product_option_value">
60+
<data key="title">Optisfvdklvfnkljvnfdklpvnfdjklfdvnjkvfdkjnvfdjkfvndj22222Optisfvdklvfnkljvnfdklpvnfdjklfdvnjkvfdkjnvfdjkfvndj22222</data>
61+
<data key="sort_order">2</data>
62+
<data key="price">20</data>
63+
<data key="price_type">percent</data>
64+
</entity>
65+
</entities>
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd">
11+
<test name="StorefrontPurchaseProductWithCustomOptionsWithLongValuesTitle">
12+
<annotations>
13+
<group value="Catalog"/>
14+
<title value="Admin should be able to see the full title of the selected custom option value in the order"/>
15+
<description value="Admin should be able to see the full title of the selected custom option value in the order"/>
16+
<severity value="MAJOR"/>
17+
<testCaseId value="MC-3043"/>
18+
<group value="skip"/>
19+
<!-- Skip due to MQE-1128 -->
20+
</annotations>
21+
<before>
22+
<!--Create Simple Product with Custom Options-->
23+
<createData entity="_defaultCategory" stepKey="createCategory"/>
24+
<createData entity="_defaultProduct" stepKey="createProduct">
25+
<requiredEntity createDataKey="createCategory"/>
26+
<field key="price">17</field>
27+
</createData>
28+
<updateData createDataKey="createProduct" entity="productWithOptions2" stepKey="updateProductWithOptions"/>
29+
30+
<createData entity="Simple_US_Customer" stepKey="createCustomer"/>
31+
</before>
32+
<after>
33+
<deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/>
34+
<deleteData createDataKey="createProduct" stepKey="deleteProduct"/>
35+
<deleteData createDataKey="createCategory" stepKey="deleteCategory"/>
36+
</after>
37+
38+
<!-- Login Customer Storefront -->
39+
40+
<amOnPage url="{{StorefrontCustomerSignInPage.url}}" stepKey="amOnSignInPage"/>
41+
<fillField userInput="$$createCustomer.email$$" selector="{{StorefrontCustomerSignInFormSection.emailField}}" stepKey="fillEmail"/>
42+
<fillField userInput="$$createCustomer.password$$" selector="{{StorefrontCustomerSignInFormSection.passwordField}}" stepKey="fillPassword"/>
43+
<click selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}" stepKey="clickSignInAccountButton"/>
44+
45+
<!-- Checking the correctness of displayed prices for user parameters -->
46+
47+
<amOnPage url="{{StorefrontHomePage.url}}$$createProduct.custom_attributes[url_key]$$.html" stepKey="amOnProductPage"/>
48+
<seeElement selector="{{StorefrontProductInfoMainSection.productAttributeOptionsDropDown(ProductOptionDropDownWithLongValuesTitle.title, ProductOptionValueDropdownLongTitle1.price)}}" stepKey="checkDropDownProductOption"/>
49+
50+
<!-- Adding items to the checkout -->
51+
52+
<selectOption userInput="{{ProductOptionValueDropdownLongTitle1.price}}" selector="{{StorefrontProductInfoMainSection.productOptionSelect(ProductOptionDropDownWithLongValuesTitle.title)}}" stepKey="seeProductOptionDropDown"/>
53+
<grabTextFrom selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="finalProductPrice"/>
54+
55+
<actionGroup ref="StorefrontAddToCartCustomOptionsProductPageActionGroup" stepKey="addToCartFromStorefrontProductPage">
56+
<argument name="productName" value="$$createProduct.name$$"/>
57+
</actionGroup>
58+
59+
<!-- Checking the correctness of displayed custom options for user parameters on checkout -->
60+
61+
<actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart" />
62+
63+
<conditionalClick selector="{{CheckoutPaymentSection.cartItemsArea}}" dependentSelector="{{CheckoutPaymentSection.cartItemsArea}}" visible="true" stepKey="exposeMiniCart"/>
64+
65+
<waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskForCartItem"/>
66+
<waitForElement selector="{{CheckoutPaymentSection.cartItemsAreaActive}}" time="30" stepKey="waitForCartItemsAreaActive"/>
67+
68+
<see selector="{{CheckoutPaymentSection.cartItems}}" userInput="$$createProduct.name$$" stepKey="seeProductInCart"/>
69+
70+
<conditionalClick selector="{{CheckoutPaymentSection.ProductOptionsByProductItemName($$createProduct.name$$)}}" dependentSelector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" visible="false" stepKey="exposeProductOptions"/>
71+
72+
<see selector="{{CheckoutPaymentSection.ProductOptionsActiveByProductItemName($$createProduct.name$$)}}" userInput="{{ProductOptionValueDropdownLongTitle1.title}}" stepKey="seeProductOptionValueDropdown1Input1"/>
73+
74+
<click selector="{{CheckoutShippingSection.next}}" stepKey="clickNext"/>
75+
76+
<!-- Place Order -->
77+
78+
<waitForElement selector="{{CheckoutPaymentSection.placeOrder}}" time="30" stepKey="waitForPlaceOrderButton"/>
79+
<click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrder"/>
80+
81+
<grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/>
82+
83+
<!-- Login to Admin and open Order -->
84+
85+
<actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/>
86+
87+
<amOnPage url="{{AdminOrdersPage.url}}" stepKey="onOrdersPage"/>
88+
<waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappearOnOrdersPage"/>
89+
<fillField selector="{{AdminOrdersGridSection.search}}" userInput="{$grabOrderNumber}" stepKey="fillOrderNum"/>
90+
<click selector="{{AdminOrdersGridSection.submitSearch}}" stepKey="submitSearchOrderNum"/>
91+
<waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappearOnSearch"/>
92+
<click selector="{{AdminOrdersGridSection.firstRow}}" stepKey="clickOrderRow"/>
93+
94+
<!-- Checking the correctness of displayed custom options for user parameters on Order -->
95+
96+
<dontSee selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueDropdownLongTitle1.title}}" stepKey="dontSeeAdminOrderProductOptionValueDropdown1"/>
97+
<grabTextFrom selector="{{AdminOrderItemsOrderedSection.productNameOptions}} dd" stepKey="productOptionValueText"/>
98+
<assertEquals stepKey="checkProductOptionValue">
99+
<actualResult type="variable">productOptionValueText</actualResult>
100+
<expectedResult type="string">Optisfvdklvfnkljvnfdklpvnfdjklfdvnjkvfdkjnvfdjkfvndj111 ...</expectedResult>
101+
</assertEquals>
102+
<moveMouseOver selector="{{AdminOrderItemsOrderedSection.productNameOptions}} dd" stepKey="hoverProduct"/>
103+
<waitForElementVisible selector="{{AdminOrderItemsOrderedSection.productNameOptions}} dd:nth-child(2)" stepKey="waitForCustomOptionValueFullName"/>
104+
<see selector="{{AdminOrderItemsOrderedSection.productNameOptions}}" userInput="{{ProductOptionValueDropdownLongTitle1.title}}" stepKey="seeAdminOrderProductOptionValueDropdown1"/>
105+
</test>
106+
</tests>

app/code/Magento/Sales/Block/Adminhtml/Items/Column/Name.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
*/
66
namespace Magento\Sales\Block\Adminhtml\Items\Column;
77

8+
use Magento\Framework\Filter\TruncateFilter\Result;
9+
810
/**
911
* Sales Order items name column renderer
1012
*
@@ -13,6 +15,11 @@
1315
*/
1416
class Name extends \Magento\Sales\Block\Adminhtml\Items\Column\DefaultColumn
1517
{
18+
/**
19+
* @var Result
20+
*/
21+
private $truncateResult = null;
22+
1623
/**
1724
* Truncate string
1825
*
@@ -22,13 +29,15 @@ class Name extends \Magento\Sales\Block\Adminhtml\Items\Column\DefaultColumn
2229
* @param string &$remainder
2330
* @param bool $breakWords
2431
* @return string
32+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
2533
*/
2634
public function truncateString($value, $length = 80, $etc = '...', &$remainder = '', $breakWords = true)
2735
{
28-
return $this->filterManager->truncate(
36+
$this->truncateResult = $this->filterManager->truncateFilter(
2937
$value,
30-
['length' => $length, 'etc' => $etc, 'remainder' => $remainder, 'breakWords' => $breakWords]
38+
['length' => $length, 'etc' => $etc, 'breakWords' => $breakWords]
3139
);
40+
return $this->truncateResult->getValue();
3241
}
3342

3443
/**
@@ -40,8 +49,11 @@ public function truncateString($value, $length = 80, $etc = '...', &$remainder =
4049
public function getFormattedOption($value)
4150
{
4251
$remainder = '';
43-
$value = $this->truncateString($value, 55, '', $remainder);
44-
$result = ['value' => nl2br($value), 'remainder' => nl2br($remainder)];
52+
$this->truncateString($value, 55, '', $remainder);
53+
$result = [
54+
'value' => nl2br($this->truncateResult->getValue()),
55+
'remainder' => nl2br($this->truncateResult->getRemainder())
56+
];
4557

4658
return $result;
4759
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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\Framework\Filter;
9+
10+
class TruncateFilterTest extends \PHPUnit\Framework\TestCase
11+
{
12+
/**
13+
* @param string $expectedValue
14+
* @param string $expectedRemainder
15+
* @param string $string
16+
* @param int $length
17+
* @param string $etc
18+
* @param bool $breakWords
19+
* @dataProvider truncateDataProvider
20+
*/
21+
public function testFilter(
22+
$expectedValue,
23+
$expectedRemainder,
24+
$string,
25+
$length = 5,
26+
$etc = '...',
27+
$breakWords = true
28+
) {
29+
/** @var TruncateFilter $truncateFilter */
30+
$truncateFilter = \Magento\TestFramework\ObjectManager::getInstance()->create(
31+
TruncateFilter::class,
32+
[
33+
'length' => $length,
34+
'etc' => $etc,
35+
'breakWords' => $breakWords,
36+
]
37+
);
38+
$result = $truncateFilter->filter($string);
39+
$this->assertEquals($expectedValue, $result->getValue());
40+
$this->assertEquals($expectedRemainder, $result->getRemainder());
41+
}
42+
43+
public function truncateDataProvider() : array
44+
{
45+
return [
46+
'1' => [
47+
'12...',
48+
'34567890',
49+
'1234567890',
50+
],
51+
'2' => [
52+
'123..',
53+
' 456 789',
54+
'123 456 789',
55+
8,
56+
'..',
57+
false
58+
]
59+
];
60+
}
61+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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\Sales\Block\Adminhtml\Items\Column;
9+
10+
/**
11+
* @magentoAppArea adminhtml
12+
*/
13+
class NameTest extends \PHPUnit\Framework\TestCase
14+
{
15+
/**
16+
* @var Name
17+
*/
18+
private $block;
19+
20+
protected function setUp()
21+
{
22+
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
23+
/** @var $layout \Magento\Framework\View\Layout */
24+
$layout = $objectManager->create(\Magento\Framework\View\LayoutInterface::class);
25+
/** @var $block \Magento\Sales\Block\Adminhtml\Items\AbstractItems */
26+
$this->block = $layout->createBlock(Name::class, 'block');
27+
}
28+
29+
public function testTruncateString() : void
30+
{
31+
$remainder = '';
32+
$this->assertEquals(
33+
'12345',
34+
$this->block->truncateString('1234567890', 5, '', $remainder)
35+
);
36+
}
37+
38+
public function testGetFormattedOptiong() : void
39+
{
40+
$this->assertEquals(
41+
[
42+
'value' => '1234567890123456789012345678901234567890123456789012345',
43+
'remainder' => '67890',
44+
],
45+
$this->block->getFormattedOption(
46+
'123456789012345678901234567890123456789012345678901234567890'
47+
)
48+
);
49+
}
50+
}

lib/internal/Magento/Framework/Filter/Factory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class Factory extends AbstractFactory
3232
'decrypt' => \Magento\Framework\Filter\Decrypt::class,
3333
'translit' => \Magento\Framework\Filter\Translit::class,
3434
'translitUrl' => \Magento\Framework\Filter\TranslitUrl::class,
35+
'truncateFilter' => \Magento\Framework\Filter\TruncateFilter::class,
3536
];
3637

3738
/**

lib/internal/Magento/Framework/Filter/FilterManager.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
* @method string removeTags(string $value, $params = array())
2222
* @method string stripTags(string $value, $params = array())
2323
* @method string truncate(string $value, $params = array())
24+
* @method string truncateFilter(string $value, $params = array())
2425
* @method string encrypt(string $value, $params = array())
2526
* @method string decrypt(string $value, $params = array())
2627
* @method string translit(string $value)

lib/internal/Magento/Framework/Filter/Truncate.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
*
1111
* Truncate a string to a certain length if necessary, appending the $etc string.
1212
* $remainder will contain the string that has been replaced with $etc.
13+
*
14+
* @deprecated
15+
* @see \Magento\Framework\Filter\TruncateFilter
1316
*/
1417
class Truncate implements \Zend_Filter_Interface
1518
{

0 commit comments

Comments
 (0)