Skip to content

Commit c5e95c6

Browse files
author
Magento CICD
authored
merge magento/2.3-develop into magento-earl-grey/MAGETWO-67627
2 parents 0b3ab15 + af2ec60 commit c5e95c6

File tree

78 files changed

+2079
-676
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+2079
-676
lines changed

app/code/Magento/Authorizenet/Model/Directpost.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -814,10 +814,14 @@ protected function declineOrder(\Magento\Sales\Model\Order $order, $message = ''
814814
{
815815
try {
816816
$response = $this->getResponse();
817-
if ($voidPayment && $response->getXTransId() && strtoupper($response->getXType())
818-
== self::REQUEST_TYPE_AUTH_ONLY
817+
if ($voidPayment
818+
&& $response->getXTransId()
819+
&& strtoupper($response->getXType()) == self::REQUEST_TYPE_AUTH_ONLY
819820
) {
820-
$order->getPayment()->setTransactionId(null)->setParentTransactionId($response->getXTransId())->void();
821+
$order->getPayment()
822+
->setTransactionId(null)
823+
->setParentTransactionId($response->getXTransId())
824+
->void($response);
821825
}
822826
$order->registerCancellation($message)->save();
823827
} catch (\Exception $e) {
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
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\Captcha\Test\Unit\Observer;
9+
10+
use Magento\Captcha\Model\DefaultModel as CaptchaModel;
11+
use Magento\Captcha\Observer\CheckGuestCheckoutObserver;
12+
use Magento\Captcha\Helper\Data as CaptchaDataHelper;
13+
use Magento\Framework\App\Action\Action;
14+
use Magento\Framework\App\ActionFlag;
15+
use Magento\Captcha\Observer\CaptchaStringResolver;
16+
use Magento\Checkout\Model\Type\Onepage;
17+
use Magento\Framework\App\Request\Http;
18+
use Magento\Framework\App\Response\Http as HttpResponse;
19+
use Magento\Framework\Event\Observer;
20+
use Magento\Framework\Json\Helper\Data as JsonHelper;
21+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
22+
use Magento\Quote\Model\Quote;
23+
24+
/**
25+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
26+
*/
27+
class CheckGuestCheckoutObserverTest extends \PHPUnit\Framework\TestCase
28+
{
29+
const FORM_ID = 'guest_checkout';
30+
31+
/**
32+
* @var CheckGuestCheckoutObserver
33+
*/
34+
private $checkGuestCheckoutObserver;
35+
36+
/**
37+
* @var ObjectManager
38+
*/
39+
private $objectManager;
40+
41+
/**
42+
* @var Observer
43+
*/
44+
private $observer;
45+
46+
/**
47+
* @var HttpResponse|\PHPUnit_Framework_MockObject_MockObject
48+
*/
49+
private $responseMock;
50+
51+
/**
52+
* @var HttpResponse|\PHPUnit_Framework_MockObject_MockObject
53+
*/
54+
private $requestMock;
55+
56+
/**
57+
* @var ActionFlag|\PHPUnit_Framework_MockObject_MockObject
58+
*/
59+
private $actionFlagMock;
60+
61+
/**
62+
* @var CaptchaStringResolver|\PHPUnit_Framework_MockObject_MockObject
63+
*/
64+
private $captchaStringResolverMock;
65+
66+
/**
67+
* @var JsonHelper|\PHPUnit_Framework_MockObject_MockObject
68+
*/
69+
private $jsonHelperMock;
70+
71+
/**
72+
* @var CaptchaModel|\PHPUnit_Framework_MockObject_MockObject
73+
*/
74+
private $captchaModelMock;
75+
76+
/**
77+
* @var Quote|\PHPUnit_Framework_MockObject_MockObject
78+
*/
79+
private $quoteModelMock;
80+
81+
/**
82+
* @var Action|\PHPUnit_Framework_MockObject_MockObject
83+
*/
84+
private $controllerMock;
85+
86+
protected function setUp()
87+
{
88+
$onepageModelTypeMock = $this->createMock(Onepage::class);
89+
$captchaHelperMock = $this->createMock(CaptchaDataHelper::class);
90+
$this->objectManager = new ObjectManager($this);
91+
$this->actionFlagMock = $this->createMock(ActionFlag::class);
92+
$this->captchaStringResolverMock = $this->createMock(CaptchaStringResolver::class);
93+
$this->captchaModelMock = $this->createMock(CaptchaModel::class);
94+
$this->quoteModelMock = $this->createMock(Quote::class);
95+
$this->controllerMock = $this->createMock(Action::class);
96+
$this->requestMock = $this->createMock(Http::class);
97+
$this->responseMock = $this->createMock(HttpResponse::class);
98+
$this->observer = new Observer(['controller_action' => $this->controllerMock]);
99+
$this->jsonHelperMock = $this->createMock(JsonHelper::class);
100+
101+
$this->checkGuestCheckoutObserver = $this->objectManager->getObject(
102+
CheckGuestCheckoutObserver::class,
103+
[
104+
'helper' => $captchaHelperMock,
105+
'actionFlag' => $this->actionFlagMock,
106+
'captchaStringResolver' => $this->captchaStringResolverMock,
107+
'typeOnepage' => $onepageModelTypeMock,
108+
'jsonHelper' => $this->jsonHelperMock
109+
]
110+
);
111+
112+
$captchaHelperMock->expects($this->once())
113+
->method('getCaptcha')
114+
->with(self::FORM_ID)
115+
->willReturn($this->captchaModelMock);
116+
$onepageModelTypeMock->expects($this->once())
117+
->method('getQuote')
118+
->willReturn($this->quoteModelMock);
119+
}
120+
121+
public function testCheckGuestCheckoutForRegister()
122+
{
123+
$this->quoteModelMock->expects($this->once())
124+
->method('getCheckoutMethod')
125+
->willReturn(Onepage::METHOD_REGISTER);
126+
$this->captchaModelMock->expects($this->never())
127+
->method('isRequired');
128+
129+
$this->checkGuestCheckoutObserver->execute($this->observer);
130+
}
131+
132+
public function testCheckGuestCheckoutWithNoCaptchaRequired()
133+
{
134+
$this->quoteModelMock->expects($this->once())
135+
->method('getCheckoutMethod')
136+
->willReturn(Onepage::METHOD_GUEST);
137+
$this->captchaModelMock->expects($this->once())
138+
->method('isRequired')
139+
->willReturn(false);
140+
$this->captchaModelMock->expects($this->never())
141+
->method('isCorrect');
142+
143+
$this->checkGuestCheckoutObserver->execute($this->observer);
144+
}
145+
146+
public function testCheckGuestCheckoutWithIncorrectCaptcha()
147+
{
148+
$captchaValue = 'some_word';
149+
$encodedJsonValue = '{}';
150+
151+
$this->quoteModelMock->expects($this->once())
152+
->method('getCheckoutMethod')
153+
->willReturn(Onepage::METHOD_GUEST);
154+
$this->captchaModelMock->expects($this->once())
155+
->method('isRequired')
156+
->willReturn(true);
157+
$this->controllerMock->expects($this->once())
158+
->method('getRequest')
159+
->willReturn($this->requestMock);
160+
$this->controllerMock->expects($this->once())
161+
->method('getResponse')
162+
->willReturn($this->responseMock);
163+
$this->controllerMock->expects($this->once())
164+
->method('getResponse')
165+
->willReturn($this->responseMock);
166+
$this->captchaStringResolverMock->expects($this->once())
167+
->method('resolve')
168+
->with($this->requestMock, self::FORM_ID)
169+
->willReturn($captchaValue);
170+
$this->captchaModelMock->expects($this->once())
171+
->method('isCorrect')
172+
->with($captchaValue)
173+
->willReturn(false);
174+
$this->actionFlagMock->expects($this->once())
175+
->method('set')
176+
->with('', Action::FLAG_NO_DISPATCH, true);
177+
$this->jsonHelperMock->expects($this->once())
178+
->method('jsonEncode')
179+
->willReturn($encodedJsonValue);
180+
$this->responseMock->expects($this->once())
181+
->method('representJson')
182+
->with($encodedJsonValue);
183+
184+
$this->checkGuestCheckoutObserver->execute($this->observer);
185+
}
186+
187+
public function testCheckGuestCheckoutWithCorrectCaptcha()
188+
{
189+
$this->quoteModelMock->expects($this->once())
190+
->method('getCheckoutMethod')
191+
->willReturn(Onepage::METHOD_GUEST);
192+
$this->captchaModelMock->expects($this->once())
193+
->method('isRequired')
194+
->willReturn(true);
195+
$this->controllerMock->expects($this->once())
196+
->method('getRequest')
197+
->willReturn($this->requestMock);
198+
$this->captchaStringResolverMock->expects($this->once())
199+
->method('resolve')
200+
->with($this->requestMock, self::FORM_ID)
201+
->willReturn('some_word');
202+
$this->captchaModelMock->expects($this->once())
203+
->method('isCorrect')
204+
->with('some_word')
205+
->willReturn(true);
206+
$this->actionFlagMock->expects($this->never())
207+
->method('set');
208+
209+
$this->checkGuestCheckoutObserver->execute($this->observer);
210+
}
211+
}

app/code/Magento/Catalog/Setup/Patch/Data/UpgradeWebsiteAttributes.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,21 @@ private function processAttributeValues(array $attributeValueItems, $tableName)
156156
*/
157157
private function fetchAttributeValues($tableName)
158158
{
159+
//filter store groups which have more than 1 store
160+
$multipleStoresInWebsite = array_values(
161+
array_reduce(
162+
array_filter($this->getGroupedStoreViews(), function ($storeViews) {
163+
return is_array($storeViews) && count($storeViews) > 1;
164+
}),
165+
'array_merge',
166+
[]
167+
)
168+
);
169+
170+
if (count($multipleStoresInWebsite) < 1) {
171+
return [];
172+
}
173+
159174
$connection = $this->moduleDataSetup->getConnection();
160175
$batchSelectIterator = $this->batchQueryGenerator->generate(
161176
'value_id',
@@ -184,9 +199,10 @@ private function fetchAttributeValues($tableName)
184199
self::ATTRIBUTE_WEBSITE
185200
)
186201
->where(
187-
'cpei.store_id <> ?',
188-
self::GLOBAL_STORE_VIEW_ID
189-
)
202+
'cpei.store_id IN (?)',
203+
$multipleStoresInWebsite
204+
),
205+
1000
190206
);
191207

192208
foreach ($batchSelectIterator as $select) {

app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@
157157
<click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="openSeoSection"/>
158158
<fillField userInput="{{simpleProduct.urlKey}}" selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="fillUrlKey"/>
159159

160-
<click selector="{{AdminProductCustomizableOptionsSection.customezableOptions}}" stepKey="openCustomOptionsSection"/>
160+
<click selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" stepKey="openCustomOptionsSection"/>
161161
<click selector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" stepKey="clickAddOption"/>
162162
<fillField userInput="option1" selector="{{AdminProductCustomizableOptionsSection.optionTitleInput}}" stepKey="fillOptionTitle"/>
163163
<click selector="{{AdminProductCustomizableOptionsSection.optionTypeOpenDropDown}}" stepKey="openTypeDropDown"/>

app/code/Magento/Catalog/Test/Mftf/ActionGroup/CustomOptionsActionGroup.xml

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,8 @@
66
*/
77
-->
88

9-
<actionGroups 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/actionGroupSchema.xsd">
11-
12-
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd">
1310
<actionGroup name="CreateCustomRadioOptions">
14-
1511
<!-- ActionGroup will add a single custom option to a product -->
1612
<!-- You must already be on the product creation page -->
1713
<arguments>
@@ -39,8 +35,23 @@
3935

4036
<fillField stepKey="fillInValueTitle2" selector="{{AdminProductCustomizableOptionsSection.valueTitle}}" userInput="{{productOption2.title}}"/>
4137
<fillField stepKey="fillInValuePrice2" selector="{{AdminProductCustomizableOptionsSection.valuePrice}}" userInput="{{productOption2.price}}"/>
38+
</actionGroup>
4239

43-
40+
<!--Add a custom option of type "file" to a product-->
41+
<actionGroup name="AddProductCustomOptionFile">
42+
<arguments>
43+
<argument name="option" defaultValue="ProductOptionFile"/>
44+
</arguments>
45+
<conditionalClick selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" dependentSelector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" visible="false" stepKey="openCustomOptionSection"/>
46+
<click selector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" stepKey="clickAddOption"/>
47+
<waitForElementVisible selector="{{AdminProductCustomizableOptionsSection.lastOptionTitle}}" stepKey="waitForOption"/>
48+
<fillField selector="{{AdminProductCustomizableOptionsSection.lastOptionTitle}}" userInput="{{option.title}}" stepKey="fillTitle"/>
49+
<click selector="{{AdminProductCustomizableOptionsSection.lastOptionTypeParent}}" stepKey="openTypeSelect"/>
50+
<click selector="{{AdminProductCustomizableOptionsSection.optionType('File')}}" stepKey="selectTypeFile"/>
51+
<waitForElementVisible selector="{{AdminProductCustomizableOptionsSection.optionPrice}}" stepKey="waitForElements"/>
52+
<fillField selector="{{AdminProductCustomizableOptionsSection.optionPrice}}" userInput="{{option.price}}" stepKey="fillPrice"/>
53+
<selectOption selector="{{AdminProductCustomizableOptionsSection.optionPriceType}}" userInput="{{option.price_type}}" stepKey="selectPriceType"/>
54+
<fillField selector="{{AdminProductCustomizableOptionsSection.optionFileExtensions}}" userInput="{{option.file_extension}}" stepKey="fillCompatibleExtensions"/>
4455
</actionGroup>
4556

4657
</actionGroups>

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>

app/code/Magento/Catalog/Test/Mftf/Section/AdminProductCustomizableOptionsSection.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd">
1111
<section name="AdminProductCustomizableOptionsSection">
1212
<element name="checkIfCustomizableOptionsTabOpen" type="text" selector="//span[text()='Customizable Options']/parent::strong/parent::*[@data-state-collapsible='closed']"/>
13-
<element name="customezableOptions" type="text" selector="//strong[contains(@class, 'admin__collapsible-title')]/span[text()='Customizable Options']"/>
13+
<element name="customizableOptions" type="text" selector="//strong[contains(@class, 'admin__collapsible-title')]/span[text()='Customizable Options']"/>
1414
<element name="useDefaultOptionTitle" type="text" selector="[data-index='options'] tr.data-row [data-index='title'] [name^='options_use_default']"/>
1515
<element name="useDefaultOptionTitleByIndex" type="text" selector="[data-index='options'] [data-index='values'] tr[data-repeat-index='{{var1}}'] [name^='options_use_default']" parameterized="true"/>
1616
<element name="addOptionBtn" type="button" selector="button[data-index='button_add']"/>
@@ -20,7 +20,6 @@
2020
<element name="optionTypeTextField" type="button" selector=".admin__dynamic-rows[data-index='options'] .action-menu._active li li"/>
2121
<element name="maxCharactersInput" type="input" selector="input[name='product[options][0][max_characters]']"/>
2222

23-
2423
<element name="checkSelect" type="select" selector="//span[text()='{{var1}}']/parent::div/parent::div/parent::div//span[text()='Option Type']/parent::label/parent::div//div[@data-role='selected-option']" parameterized="true"/>
2524
<element name="checkDropDown" type="select" selector="//span[text()='{{var1}}']/parent::div/parent::div/parent::div//parent::label/parent::div//li[@class='admin__action-multiselect-menu-inner-item']//label[text()='Drop-down']" parameterized="true"/>
2625
<element name="clickAddValue" type="button" selector="//span[text()='{{var1}}']/parent::div/parent::div/parent::div//tfoot//button" parameterized="true"/>
@@ -38,5 +37,10 @@
3837
<element name="addValue" type="button" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr[last()]//*[@data-action='add_new_row']" />
3938
<element name="valueTitle" type="input" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr[last()]//*[contains(@class, 'admin__control-table')]//tbody/tr[last()]//*[@data-index='title']//input" />
4039
<element name="valuePrice" type="input" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr[last()]//*[contains(@class, 'admin__control-table')]//tbody/tr[last()]//*[@data-index='price']//input" />
40+
41+
<element name="optionPrice" type="input" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr[last()]//*[@name='product[options][0][price]']"/>
42+
<element name="optionPriceType" type="select" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr[last()]//*[@name='product[options][0][price_type]']"/>
43+
<element name="optionSku" type="input" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr[last()]//*[@name='product[options][0][sku]']"/>
44+
<element name="optionFileExtensions" type="input" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr[last()]//*[@name='product[options][0][file_extension]']"/>
4145
</section>
4246
</sections>

0 commit comments

Comments
 (0)