From 1922484990f50060fd4376bfb2c6cc3f286a31ff Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov Date: Thu, 18 Dec 2014 12:51:27 +0200 Subject: [PATCH 01/23] MAGETWO-3387: 'Append Comments' is cleared on validation error during Order Submit --- .../Block/Adminhtml/Order/Create/Comment.php | 14 ---- .../Block/Adminhtml/Order/Create/Totals.php | 14 ++++ .../templates/order/create/totals.phtml | 2 +- .../Adminhtml/Order/Create/TotalsTest.php | 84 +++++++++++++++++++ 4 files changed, 99 insertions(+), 15 deletions(-) create mode 100644 dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/TotalsTest.php diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Comment.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Comment.php index 7ca3943d4ec36..6391503155d4c 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Comment.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Comment.php @@ -47,18 +47,4 @@ public function getCommentNote() { return $this->escapeHtml($this->getQuote()->getCustomerNote()); } - - /** - * Get note notification - * - * @return bool - */ - public function getNoteNotify() - { - $notify = $this->getQuote()->getCustomerNoteNotify(); - if (is_null($notify) || $notify) { - return true; - } - return false; - } } diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Totals.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Totals.php index 833932ae64b85..dedf8478a6d14 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Totals.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Totals.php @@ -181,4 +181,18 @@ public function canSendNewOrderConfirmationEmail() { return $this->_salesData->canSendNewOrderConfirmationEmail($this->getQuote()->getStoreId()); } + + /** + * Get note notification + * + * @return bool + */ + public function getNoteNotify() + { + $notify = $this->getQuote()->getCustomerNoteNotify(); + if (is_null($notify) || $notify) { + return true; + } + return false; + } } diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals.phtml index 31c3a50031389..2e104cccf9ef4 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/totals.phtml @@ -13,7 +13,7 @@
- getNoteNotify()): ?>checked="true"/> + getNoteNotify()): ?> checked="checked"/>
canSendNewOrderConfirmationEmail()): ?> diff --git a/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/TotalsTest.php b/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/TotalsTest.php new file mode 100644 index 0000000000000..79deefa5c8c79 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/TotalsTest.php @@ -0,0 +1,84 @@ +objectManager = new ObjectManager($this); + + $this->quoteMock = $this->getMock( + '\Magento\Sales\Model\Quote', ['getCustomerNoteNotify'], [], '', false + ); + $this->sessionQuoteMock = $this->getMock( + '\Magento\Backend\Model\Session\Quote', [], [], '', false + ); + + $this->sessionQuoteMock->expects($this->any()) + ->method('getQuote') + ->willReturn($this->quoteMock); + + $this->totals = $this->objectManager->getObject( + '\Magento\Sales\Block\Adminhtml\Order\Create\Totals', + [ + 'sessionQuote' => $this->sessionQuoteMock + ] + ); + } + + /** + * @param mixed $customerNoteNotify + * @param bool $expectedResult + * @dataProvider getNoteNotifyDataProvider + */ + public function testGetNoteNotify($customerNoteNotify, $expectedResult) + { + $this->quoteMock->expects($this->any()) + ->method('getCustomerNoteNotify') + ->willReturn($customerNoteNotify); + + $this->assertEquals($expectedResult, $this->totals->getNoteNotify()); + } + + /** + * @return array + */ + public function getNoteNotifyDataProvider() + { + return [ + [0, false], + [1, true], + ['0', false], + ['1', true], + [null, true] + ]; + } +} From f99d59c1730268afea9982e36047b7a8f33102cc Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov Date: Thu, 18 Dec 2014 14:27:45 +0200 Subject: [PATCH 02/23] MAGETWO-3387: 'Append Comments' is cleared on validation error during Order Submit --- .../Magento/Test/Legacy/_files/obsolete_methods.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php index 4ffcca5607537..4ee4d932893a4 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php @@ -2001,4 +2001,9 @@ ['getScriptTranslation', 'Magento\Framework\LocaleInterface'], ['getCountryTranslation', 'Magento\Framework\LocaleInterface'], ['getTerritoryTranslation', 'Magento\Framework\LocaleInterface'], + [ + 'getNoteNotify', + 'Magento\Sales\Block\Adminhtml\Order\Create\Comment', + 'Magento\Sales\Block\Adminhtml\Order\Create\Totals' + ], ]; From e4fcf91831bbbcc94c414171b0c8b9d7a88b6c9d Mon Sep 17 00:00:00 2001 From: agurzhyi Date: Thu, 18 Dec 2014 15:11:28 +0200 Subject: [PATCH 03/23] MAGETWO-31784: Tax class drop-down on New Customer Group page should not contain value 'none' --- .../Block/Adminhtml/Group/Edit/Form.php | 2 +- .../Tax/Model/TaxClass/Source/Customer.php | 19 +- .../Model/TaxClass/Source/CustomerTest.php | 2 +- .../Model/TaxClass/Source/CustomerTest.php | 177 ++++++++++++++++++ 4 files changed, 187 insertions(+), 13 deletions(-) create mode 100644 dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php diff --git a/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php b/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php index fbc41f25069e2..6c67a1f555ef1 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Group/Edit/Form.php @@ -115,7 +115,7 @@ protected function _prepareLayout() 'title' => __('Tax Class'), 'class' => 'required-entry', 'required' => true, - 'values' => $this->_taxCustomer->toOptionArray(true), + 'values' => $this->_taxCustomer->toOptionArray(), ] ); diff --git a/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php b/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php index 6d97a822c554c..fecd324706d2e 100644 --- a/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php +++ b/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php @@ -48,12 +48,12 @@ public function __construct( /** * Retrieve all customer tax classes as an options array. * - * @param bool $withEmpty * @return array */ - public function getAllOptions($withEmpty = true) + public function getAllOptions() { - if (!$this->_options) { + if (empty($this->_options)) { + $options = []; $filter = $this->filterBuilder ->setField(TaxClass::KEY_TYPE) ->setValue(TaxClassManagementInterface::TYPE_CUSTOMER) @@ -61,20 +61,17 @@ public function getAllOptions($withEmpty = true) $searchCriteria = $this->searchCriteriaBuilder->addFilter([$filter])->create(); $searchResults = $this->taxClassRepository->getList($searchCriteria); foreach ($searchResults->getItems() as $taxClass) { - $this->_options[] = [ + $options[] = [ 'value' => $taxClass->getClassId(), 'label' => $taxClass->getClassName(), ]; } - } - - if ($withEmpty) { - if (!$this->_options) { - return [['value' => '0', 'label' => __('None')]]; - } else { - return array_merge([['value' => '0', 'label' => __('None')]], $this->_options); + if (empty($options)) { + $options = [['value' => '0', 'label' => __('None')]]; } + $this->_options = $options; } + return $this->_options; } } diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php index 94bcf24352b16..aca4b4b4c5926 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php @@ -27,7 +27,7 @@ public function testGetAllOptions() $source = Bootstrap::getObjectManager()->get('Magento\Tax\Model\TaxClass\Source\Customer'); $this->assertEquals( $expectedResult, - $source->getAllOptions(false), + $source->getAllOptions(), 'Tax Class options are invalid.' ); } diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php new file mode 100644 index 0000000000000..182c1ddb283dc --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php @@ -0,0 +1,177 @@ +objectManager = new ObjectManager($this); + + $this->taxClassRepositoryMock = $this->getMockForAbstractClass( + 'Magento\Tax\Api\TaxClassRepositoryInterface', + ['getList'], + '', + false, + true, + true, + [] + ); + $this->searchCriteriaBuilderMock = $this->getMock( + 'Magento\Framework\Api\SearchCriteriaBuilder', + ['addFilter', 'create'], + [], + '', + false + ); + $this->filterBuilderMock = $this->getMock( + 'Magento\Framework\Api\FilterBuilder', + ['setField', 'setValue', 'create'], + [], + '', + false + ); + + $this->customer = $this->objectManager->getObject( + 'Magento\Tax\Model\TaxClass\Source\Customer', + [ + 'taxClassRepository' => $this->taxClassRepositoryMock, + 'searchCriteriaBuilder' => $this->searchCriteriaBuilderMock, + 'filterBuilder' => $this->filterBuilderMock + ] + ); + } + + /** + * Run test getAllOptions method + * + * @param bool $isEmpty + * @param array $expected + * @dataProvider dataProviderGetAllOptions + */ + public function testGetAllOptions($isEmpty, array $expected) + { + $filterMock = $this->getMock( + 'Magento\Framework\Api\Filter', + [], + [], + '', + false + ); + $searchCriteriaMock = $this->getMock( + 'Magento\Framework\Api\SearchCriteria', + [], + [], + '', + false + ); + $searchResultsMock = $this->getMockForAbstractClass( + 'Magento\Tax\Api\Data\TaxClassSearchResultsInterface', + [], + '', + false, + true, + true, + ['getItems'] + ); + $taxClassMock = $this->getMockForAbstractClass( + 'Magento\Tax\Api\Data\TaxClassInterface', + ['getClassId', 'getClassName'], + '', + false, + true, + true + ); + + $this->filterBuilderMock->expects($this->once()) + ->method('setField') + ->with(\Magento\Tax\Api\Data\TaxClassInterface::KEY_TYPE) + ->willReturnSelf(); + $this->filterBuilderMock->expects($this->once()) + ->method('setValue') + ->with(\Magento\Tax\Api\TaxClassManagementInterface::TYPE_CUSTOMER) + ->willReturnSelf(); + $this->filterBuilderMock->expects($this->once()) + ->method('create') + ->willReturn($filterMock); + $this->searchCriteriaBuilderMock->expects($this->once()) + ->method('addFilter') + ->with([$filterMock]) + ->willReturnSelf(); + $this->searchCriteriaBuilderMock->expects($this->once()) + ->method('create') + ->willReturn($searchCriteriaMock); + $this->taxClassRepositoryMock->expects($this->once()) + ->method('getList') + ->with($searchCriteriaMock) + ->willReturn($searchResultsMock); + + $items = []; + if (!$isEmpty) { + $taxClassMock->expects($this->once()) + ->method('getClassId') + ->willReturn(10); + $taxClassMock->expects($this->once()) + ->method('getClassName') + ->willReturn('class-name'); + $items = [$taxClassMock]; + } + + $searchResultsMock->expects($this->once()) + ->method('getItems') + ->willReturn($items); + + // checking of a lack of re-initialization + for ($i = 10; --$i;) { + $result = $this->customer->getAllOptions(); + $this->assertEquals($expected, $result); + } + } + + /** + * Data provider for testGetAllOptions + * + * @return array + */ + public function dataProviderGetAllOptions() + { + return [ + ['isEmpty' => false, 'expected' => [['value' => 10, 'label' => 'class-name']]], + ['isEmpty' => true, 'expected' => [['value' => '0', 'label' => __('None')]]] + ]; + } +} From b6d73d5bda49fbaa4b3432300e7eb45b983f1b02 Mon Sep 17 00:00:00 2001 From: agurzhyi Date: Fri, 19 Dec 2014 11:07:57 +0200 Subject: [PATCH 04/23] MAGETWO-31784: Tax class drop-down on New Customer Group page should not contain value 'none' --- app/code/Magento/Tax/Model/TaxClass/Source/Customer.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php b/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php index fecd324706d2e..3fd2d7ae6999e 100644 --- a/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php +++ b/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php @@ -5,8 +5,9 @@ namespace Magento\Tax\Model\TaxClass\Source; -use Magento\Tax\Api\Data\TaxClassInterface as TaxClass; +use Magento\Framework\Exception\StateException; use Magento\Tax\Api\TaxClassManagementInterface; +use Magento\Tax\Api\Data\TaxClassInterface as TaxClass; /** * Customer tax class source model. @@ -49,13 +50,13 @@ public function __construct( * Retrieve all customer tax classes as an options array. * * @return array + * @throws StateException */ public function getAllOptions() { if (empty($this->_options)) { $options = []; - $filter = $this->filterBuilder - ->setField(TaxClass::KEY_TYPE) + $filter = $this->filterBuilder->setField(TaxClass::KEY_TYPE) ->setValue(TaxClassManagementInterface::TYPE_CUSTOMER) ->create(); $searchCriteria = $this->searchCriteriaBuilder->addFilter([$filter])->create(); @@ -67,7 +68,7 @@ public function getAllOptions() ]; } if (empty($options)) { - $options = [['value' => '0', 'label' => __('None')]]; + throw new StateException('Customer tax class cannot does not exist.'); } $this->_options = $options; } From bd1301184813e6fb858fdb26e7b4d1fb6abdb652 Mon Sep 17 00:00:00 2001 From: agurzhyi Date: Fri, 19 Dec 2014 12:22:54 +0200 Subject: [PATCH 05/23] MAGETWO-31784: Tax class drop-down on New Customer Group page should not contain value 'none' --- .../Model/TaxClass/Source/CustomerTest.php | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php index 182c1ddb283dc..4ccee7bf5b7bf 100644 --- a/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php +++ b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php @@ -140,7 +140,6 @@ public function testGetAllOptions($isEmpty, array $expected) ->with($searchCriteriaMock) ->willReturn($searchResultsMock); - $items = []; if (!$isEmpty) { $taxClassMock->expects($this->once()) ->method('getClassId') @@ -148,17 +147,28 @@ public function testGetAllOptions($isEmpty, array $expected) $taxClassMock->expects($this->once()) ->method('getClassName') ->willReturn('class-name'); - $items = [$taxClassMock]; - } - $searchResultsMock->expects($this->once()) - ->method('getItems') - ->willReturn($items); + $items = [$taxClassMock]; + $searchResultsMock->expects($this->once()) + ->method('getItems') + ->willReturn($items); - // checking of a lack of re-initialization - for ($i = 10; --$i;) { - $result = $this->customer->getAllOptions(); - $this->assertEquals($expected, $result); + // checking of a lack of re-initialization + for ($i = 10; --$i;) { + $result = $this->customer->getAllOptions(); + $this->assertEquals($expected, $result); + } + } else { + $items = []; + $searchResultsMock->expects($this->once()) + ->method('getItems') + ->willReturn($items); + // checking exception + try { + $this->customer->getAllOptions(); + } catch (\Exception $e) { + $this->assertInstanceOf('Magento\Framework\Exception\StateException', $e); + } } } From d5bebc91925b93021103ddef91cc35d1f2f10be3 Mon Sep 17 00:00:00 2001 From: agurzhyi Date: Fri, 19 Dec 2014 15:20:57 +0200 Subject: [PATCH 06/23] MAGETWO-27636: Persistent Shopping Cart: 'Not %Username%?' link is displayed during page load for user logged in --- .../Magento/Persistent/Model/Observer.php | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/Persistent/Model/Observer.php b/app/code/Magento/Persistent/Model/Observer.php index d91abec454511..67d50e90ab4a7 100644 --- a/app/code/Magento/Persistent/Model/Observer.php +++ b/app/code/Magento/Persistent/Model/Observer.php @@ -92,23 +92,9 @@ public function emulateWelcomeBlock($block) null ); - $this->_applyAccountLinksPersistentData(); - $welcomeMessage = __('Welcome, %1!', $escapedName) - . ' ' . $this->_layout->getBlock('header.additional')->toHtml(); - $block->setWelcome($welcomeMessage); - return $this; - } + $block->setWelcome(__('Welcome, %1!', $escapedName)); - /** - * Emulate 'account links' block with persistent data - * - * @return void - */ - protected function _applyAccountLinksPersistentData() - { - if (!$this->_layout->getBlock('header.additional')) { - $this->_layout->addBlock('Magento\Persistent\Block\Header\Additional', 'header.additional'); - } + return $this; } /** @@ -119,7 +105,6 @@ protected function _applyAccountLinksPersistentData() */ public function emulateTopLinks($block) { - $this->_applyAccountLinksPersistentData(); $block->removeLinkByUrl($this->_url->getUrl('customer/account/login')); } } From 68ef14c5556e3ece0cc590428029354d5e3f8249 Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov Date: Fri, 19 Dec 2014 16:22:58 +0200 Subject: [PATCH 07/23] MAGETWO-30854: Unexpected
html element is present on 'View Return' Customer account frontend page --- app/code/Magento/Customer/etc/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/etc/config.xml b/app/code/Magento/Customer/etc/config.xml index 10a4fcbd2f672..521a80d8c306c 100644 --- a/app/code/Magento/Customer/etc/config.xml +++ b/app/code/Magento/Customer/etc/config.xml @@ -58,7 +58,7 @@ T: {{var telephone}} {{depend fax}}F: {{var fax}}{{/depend}} {{depend vat_id}}VAT: {{var vat_id}}{{/depend}} {{depend prefix}}{{var prefix}} {{/depend}}{{var firstname}} {{depend middlename}}{{var middlename}} {{/depend}}{{var lastname}}{{depend suffix}} {{var suffix}}{{/depend}}, {{var street}}, {{var city}}, {{var region}} {{var postcode}}, {{var country}} - + {{/depend}} {{depend company}}{{var company}}
{{/depend}} {{if street1}}{{var street1}}
{{/if}} {{depend street2}}{{var street2}}
{{/depend}} From 7009abff583f7e7a807a1e7e798424e54f82492a Mon Sep 17 00:00:00 2001 From: Vladyslav Shcherbyna Date: Mon, 22 Dec 2014 12:22:52 +0200 Subject: [PATCH 08/23] MAGETWO-7359: Incorrect totals shown on coupon usage report --- .../Model/Resource/Report/Rule/Createdat.php | 12 ++- .../Resource/Report/Rule/CreatedatTest.php | 102 ++++++++++++++++++ 2 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/SalesRule/Model/Resource/Report/Rule/CreatedatTest.php diff --git a/app/code/Magento/SalesRule/Model/Resource/Report/Rule/Createdat.php b/app/code/Magento/SalesRule/Model/Resource/Report/Rule/Createdat.php index 9e3ec5c040336..63bd5a0554ec1 100644 --- a/app/code/Magento/SalesRule/Model/Resource/Report/Rule/Createdat.php +++ b/app/code/Magento/SalesRule/Model/Resource/Report/Rule/Createdat.php @@ -94,7 +94,10 @@ protected function _aggregateByOrder($aggregationField, $from, $to) 'base_subtotal_canceled', 0 ) . ' - ' . $adapter->getIfNullSql( - 'ABS(base_discount_amount) - ' . $adapter->getIfNullSql('base_discount_canceled', 0), + 'ABS(base_discount_amount) - ABS(' . $adapter->getIfNullSql('base_discount_canceled', 0) . ')', + 0 + ) . ' + ' . $adapter->getIfNullSql( + 'base_tax_amount - ' . $adapter->getIfNullSql('base_tax_canceled', 0), 0 ) . ') * base_to_global_rate)', @@ -120,9 +123,12 @@ protected function _aggregateByOrder($aggregationField, $from, $to) 'base_subtotal_refunded', 0 ) . ' - ' . $adapter->getIfNullSql( - 'base_discount_invoiced - ' . $adapter->getIfNullSql('base_discount_refunded', 0), + 'ABS(base_discount_invoiced) - ABS(' . $adapter->getIfNullSql('base_discount_refunded', 0) . ')', 0 - ) . ') * base_to_global_rate)', + ) . ' + ' . $adapter->getIfNullSql( + 'base_tax_invoiced - ' . $adapter->getIfNullSql('base_tax_refunded', 0), + 0 + ) . ') * base_to_global_rate)', 0 ), ]; diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Resource/Report/Rule/CreatedatTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Resource/Report/Rule/CreatedatTest.php new file mode 100644 index 0000000000000..aabe4d1790ba1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Resource/Report/Rule/CreatedatTest.php @@ -0,0 +1,102 @@ +create('Magento\Sales\Model\Order'); + $order->loadByIncrementId('100000001') + ->setBaseGrandTotal($orderParams['base_subtotal']) + ->setSubtotal($orderParams['base_subtotal']) + ->setBaseSubtotal($orderParams['base_subtotal']) + ->setBaseDiscountAmount($orderParams['base_discount_amount']) + ->setBaseTaxAmount($orderParams['base_tax_amount']) + ->setBaseSubtotalInvoiced($orderParams['base_subtotal_invoiced']) + ->setBaseDiscountInvoiced($orderParams['base_discount_invoiced']) + ->setBaseTaxInvoiced($orderParams['base_tax_invoiced']) + ->setBaseShippingAmount(0) + ->setBaseToGlobalRate(1) + ->setCouponCode('1234567890') + ->setCreatedAt('2014-10-25 10:10:10') + ->save(); + // refresh report statistics + /** @var \Magento\SalesRule\Model\Resource\Report\Rule $reportResource */ + $reportResource = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + 'Magento\SalesRule\Model\Resource\Report\Rule' + ); + $reportResource->aggregate(); + /** @var \Magento\SalesRule\Model\Resource\Report\Collection $reportCollection */ + $reportCollection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + 'Magento\SalesRule\Model\Resource\Report\Collection' + ); + $salesRuleReportItem = $reportCollection->getFirstItem(); + $this->assertEquals($this->getTotalAmount($order), $salesRuleReportItem['total_amount']); + $this->assertEquals($this->getTotalAmountActual($order), $salesRuleReportItem['total_amount_actual']); + } + + /** + * Repeat sql formula from \Magento\SalesRule\Model\Resource\Report\Rule\Createdat::_aggregateByOrder + * + * @param \Magento\Sales\Model\Order $order + * @return float + */ + private function getTotalAmount(\Magento\Sales\Model\Order $order) + { + return ( + $order->getBaseSubtotal() - $order->getBaseSubtotalCanceled() + - (abs($order->getBaseDiscountAmount()) - abs($order->getBaseDiscountCanceled())) + + ($order->getBaseTaxAmount() - $order->getBaseTaxCanceled()) + ) * $order->getBaseToGlobalRate(); + } + + /** + * Repeat sql formula from \Magento\SalesRule\Model\Resource\Report\Rule\Createdat::_aggregateByOrder + * + * @param \Magento\Sales\Model\Order $order + * @return float + */ + private function getTotalAmountActual(\Magento\Sales\Model\Order $order) + { + return ( + $order->getBaseSubtotalInvoiced() - $order->getSubtotalRefunded() + - abs($order->getBaseDiscountInvoiced()) - abs($order->getBaseDiscountRefunded()) + + $order->getBaseTaxInvoiced() - $order->getBaseTaxRefunded() + ) * $order->getBaseToGlobalRate(); + } + + /** + * @return array + */ + public function orderParamsDataProvider() + { + return [ + [ + [ + 'base_discount_amount' => 98.80, + 'base_subtotal' => 494, + 'base_tax_amount' => 8.8, + 'base_subtotal_invoiced' => 494, + 'base_discount_invoiced' => 98.80, + 'base_tax_invoiced' => 8.8 + ] + ] + ]; + } +} From bc445afbcae98d1f59f2a22b63386c99cab49402 Mon Sep 17 00:00:00 2001 From: agurzhyi Date: Mon, 22 Dec 2014 21:23:17 +0200 Subject: [PATCH 09/23] MAGETWO-27636: Persistent Shopping Cart: 'Not %Username%?' link is displayed during page load for user logged in --- .../Persistent/Block/Header/Additional.php | 19 +- .../Model/Layout/DepersonalizePlugin.php | 73 ++++ .../Magento/Persistent/Model/Observer.php | 19 +- .../Magento/Persistent/etc/frontend/di.xml | 6 + .../Block/Header/AdditionalTest.php | 356 ++++++++++++++++++ .../Model/Layout/DepersonalizePluginTest.php | 163 ++++++++ 6 files changed, 627 insertions(+), 9 deletions(-) create mode 100644 app/code/Magento/Persistent/Model/Layout/DepersonalizePlugin.php create mode 100644 dev/tests/unit/testsuite/Magento/Persistent/Block/Header/AdditionalTest.php create mode 100644 dev/tests/unit/testsuite/Magento/Persistent/Model/Layout/DepersonalizePluginTest.php diff --git a/app/code/Magento/Persistent/Block/Header/Additional.php b/app/code/Magento/Persistent/Block/Header/Additional.php index 298052731e37a..4b7f83d2e2335 100644 --- a/app/code/Magento/Persistent/Block/Header/Additional.php +++ b/app/code/Magento/Persistent/Block/Header/Additional.php @@ -44,6 +44,7 @@ public function __construct( \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository, array $data = [] ) { + $this->isScopePrivate = true; $this->_customerViewHelper = $customerViewHelper; $this->_persistentSessionHelper = $persistentSessionHelper; $this->customerRepository = $customerRepository; @@ -68,12 +69,16 @@ public function getHref() */ protected function _toHtml() { - $persistentName = $this->_escaper->escapeHtml( - $this->_customerViewHelper->getCustomerName( - $this->customerRepository->getById($this->_persistentSessionHelper->getSession()->getCustomerId()) - ) - ); - return 'getLinkAttributes() . ' >' . $this->escapeHtml(__('(Not %1?)', $persistentName)) - . ''; + if ($this->_persistentSessionHelper->getSession()->getCustomerId()) { + $persistentName = $this->escapeHtml( + $this->_customerViewHelper->getCustomerName( + $this->customerRepository->getById($this->_persistentSessionHelper->getSession()->getCustomerId()) + ) + ); + return 'getLinkAttributes() . ' >' . __('(Not %1?)', $persistentName) + . ''; + } + + return ''; } } diff --git a/app/code/Magento/Persistent/Model/Layout/DepersonalizePlugin.php b/app/code/Magento/Persistent/Model/Layout/DepersonalizePlugin.php new file mode 100644 index 0000000000000..46bf6df521289 --- /dev/null +++ b/app/code/Magento/Persistent/Model/Layout/DepersonalizePlugin.php @@ -0,0 +1,73 @@ +persistentSession = $persistentSession; + $this->request = $request; + $this->moduleManager = $moduleManager; + $this->cacheConfig = $cacheConfig; + } + + /** + * After generate Xml + * + * @param \Magento\Framework\View\LayoutInterface $subject + * @param \Magento\Framework\View\LayoutInterface $result + * @return \Magento\Framework\View\LayoutInterface + */ + public function afterGenerateXml( + \Magento\Framework\View\LayoutInterface $subject, + \Magento\Framework\View\LayoutInterface $result + ) { + if ($this->moduleManager->isEnabled('Magento_PageCache') + && $this->cacheConfig->isEnabled() + && !$this->request->isAjax() + && $subject->isCacheable() + ) { + $this->persistentSession->setCustomerId(null); + } + + return $result; + } +} diff --git a/app/code/Magento/Persistent/Model/Observer.php b/app/code/Magento/Persistent/Model/Observer.php index 67d50e90ab4a7..d91abec454511 100644 --- a/app/code/Magento/Persistent/Model/Observer.php +++ b/app/code/Magento/Persistent/Model/Observer.php @@ -92,11 +92,25 @@ public function emulateWelcomeBlock($block) null ); - $block->setWelcome(__('Welcome, %1!', $escapedName)); - + $this->_applyAccountLinksPersistentData(); + $welcomeMessage = __('Welcome, %1!', $escapedName) + . ' ' . $this->_layout->getBlock('header.additional')->toHtml(); + $block->setWelcome($welcomeMessage); return $this; } + /** + * Emulate 'account links' block with persistent data + * + * @return void + */ + protected function _applyAccountLinksPersistentData() + { + if (!$this->_layout->getBlock('header.additional')) { + $this->_layout->addBlock('Magento\Persistent\Block\Header\Additional', 'header.additional'); + } + } + /** * Emulate 'top links' block with persistent data * @@ -105,6 +119,7 @@ public function emulateWelcomeBlock($block) */ public function emulateTopLinks($block) { + $this->_applyAccountLinksPersistentData(); $block->removeLinkByUrl($this->_url->getUrl('customer/account/login')); } } diff --git a/app/code/Magento/Persistent/etc/frontend/di.xml b/app/code/Magento/Persistent/etc/frontend/di.xml index 08f489c246990..a3d5a161a1746 100644 --- a/app/code/Magento/Persistent/etc/frontend/di.xml +++ b/app/code/Magento/Persistent/etc/frontend/di.xml @@ -12,4 +12,10 @@ + + + diff --git a/dev/tests/unit/testsuite/Magento/Persistent/Block/Header/AdditionalTest.php b/dev/tests/unit/testsuite/Magento/Persistent/Block/Header/AdditionalTest.php new file mode 100644 index 0000000000000..9237b9f7ff895 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Persistent/Block/Header/AdditionalTest.php @@ -0,0 +1,356 @@ +objectManager = new \Magento\TestFramework\Helper\ObjectManager($this); + + $this->contextMock = $this->getMock( + 'Magento\Framework\View\Element\Template\Context', + [ + 'getEventManager', + 'getScopeConfig', + 'getCacheState', + 'getCache', + 'getInlineTranslation', + 'getSidResolver', + 'getSession', + 'getEscaper', + 'getUrlBuilder' + ], + [], + '', + false + ); + $this->customerViewHelperMock = $this->getMock( + 'Magento\Customer\Helper\View', + [], + [], + '', + false + ); + $this->persistentSessionHelperMock = $this->getMock( + 'Magento\Persistent\Helper\Session', + ['getSession'], + [], + '', + false + ); + $this->customerRepositoryMock = $this->getMockForAbstractClass( + 'Magento\Customer\Api\CustomerRepositoryInterface', + [], + '', + false, + true, + true, + ['getById'] + ); + + $this->eventManagerMock = $this->getMockForAbstractClass( + 'Magento\Framework\Event\ManagerInterface', + [], + '', + false, + true, + true, + ['dispatch'] + ); + $this->scopeConfigMock = $this->getMockForAbstractClass( + 'Magento\Framework\App\Config\ScopeConfigInterface', + [], + '', + false, + true, + true, + ['getValue'] + ); + $this->cacheStateMock = $this->getMockForAbstractClass( + 'Magento\Framework\App\Cache\StateInterface', + [], + '', + false, + true, + true, + ['isEnabled'] + ); + $this->cacheMock = $this->getMockForAbstractClass( + 'Magento\Framework\App\CacheInterface', + [], + '', + false, + true, + true, + ['load'] + ); + $this->sidResolverMock = $this->getMockForAbstractClass( + 'Magento\Framework\Session\SidResolverInterface', + [], + '', + false, + true, + true, + ['getSessionIdQueryParam'] + ); + $this->sessionMock = $this->getMockForAbstractClass( + 'Magento\Framework\Session\SessionManagerInterface', + [], + '', + false, + true, + true, + ['getSessionId'] + ); + $this->escaperMock = $this->getMockForAbstractClass( + 'Magento\Framework\Escaper', + [], + '', + false, + true, + true, + ['escapeHtml'] + ); + $this->urlBuilderMock = $this->getMockForAbstractClass( + 'Magento\Framework\UrlInterface', + [], + '', + false, + true, + true, + ['getUrl'] + ); + + $this->contextMock->expects($this->once()) + ->method('getEventManager') + ->willReturn($this->eventManagerMock); + $this->contextMock->expects($this->once()) + ->method('getScopeConfig') + ->willReturn($this->scopeConfigMock); + $this->contextMock->expects($this->once()) + ->method('getCacheState') + ->willReturn($this->cacheStateMock); + $this->contextMock->expects($this->once()) + ->method('getCache') + ->willReturn($this->cacheMock); + $this->contextMock->expects($this->once()) + ->method('getSidResolver') + ->willReturn($this->sidResolverMock); + $this->contextMock->expects($this->once()) + ->method('getSession') + ->willReturn($this->sessionMock); + $this->contextMock->expects($this->once()) + ->method('getEscaper') + ->willReturn($this->escaperMock); + $this->contextMock->expects($this->once()) + ->method('getUrlBuilder') + ->willReturn($this->urlBuilderMock); + + $this->additional = $this->objectManager->getObject( + 'Magento\Persistent\Block\Header\Additional', + [ + 'context' => $this->contextMock, + 'customerViewHelper' => $this->customerViewHelperMock, + 'persistentSessionHelper' => $this->persistentSessionHelperMock, + 'customerRepository' => $this->customerRepositoryMock, + 'data' => [] + ] + ); + } + + /** + * Run test toHtml method + * + * @param bool $customerId + * @return void + * + * @dataProvider dataProviderToHtml + */ + public function testToHtml($customerId) + { + $cacheData = false; + $idQueryParam = 'id-query-param'; + $sessionId = 'session-id'; + $customerName = 'customer-name'; + + $this->additional->setData('cache_lifetime', 789); + $this->additional->setData('cache_key', 'cache-key'); + + $this->eventManagerMock->expects($this->once()) + ->method('dispatch') + ->with('view_block_abstract_to_html_before', ['block' => $this->additional]); + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->with( + 'advanced/modules_disable_output/Magento_Persistent', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE + )->willReturn(false); + + // get cache + $this->cacheStateMock->expects($this->at(0)) + ->method('isEnabled') + ->with(\Magento\Persistent\Block\Header\Additional::CACHE_GROUP) + ->willReturn(true); + // save cache + $this->cacheStateMock->expects($this->at(1)) + ->method('isEnabled') + ->with(\Magento\Persistent\Block\Header\Additional::CACHE_GROUP) + ->willReturn(false); + + $this->cacheMock->expects($this->once()) + ->method('load') + ->willReturn($cacheData); + $this->sidResolverMock->expects($this->never()) + ->method('getSessionIdQueryParam') + ->with($this->sessionMock) + ->willReturn($idQueryParam); + $this->sessionMock->expects($this->never()) + ->method('getSessionId') + ->willReturn($sessionId); + + // call protected _toHtml method + $sessionMock = $this->getMock( + 'Magento\Persistent\Model\Session', + ['getCustomerId'], + [], + '', + false + ); + + $this->persistentSessionHelperMock->expects($this->atLeastOnce()) + ->method('getSession') + ->willReturn($sessionMock); + + $sessionMock->expects($this->atLeastOnce()) + ->method('getCustomerId') + ->willReturn($customerId); + + if ($customerId) { + + $customerMock = $this->getMockForAbstractClass( + 'Magento\Customer\Api\Data\CustomerInterface', + [], + '', + false, + true, + true, + [] + ); + + $this->customerRepositoryMock->expects($this->once()) + ->method('getById') + ->with($customerId) + ->willReturn($customerMock); + + $this->customerViewHelperMock->expects($this->once()) + ->method('getCustomerName') + ->with($customerMock) + ->willReturn($customerName); + + $this->escaperMock->expects($this->at(0)) + ->method('escapeHtml') + ->with($customerName) + ->willReturn($customerName); + + $this->assertEquals('(Not customer-name?)', $this->additional->toHtml()); + } else { + $this->assertEquals('', $this->additional->toHtml()); + } + } + + /** + * Data provider for dataProviderToHtml method + * + * @return array + */ + public function dataProviderToHtml() + { + return [ + ['customerId' => 2], + ['customerId' => null], + ]; + } +} diff --git a/dev/tests/unit/testsuite/Magento/Persistent/Model/Layout/DepersonalizePluginTest.php b/dev/tests/unit/testsuite/Magento/Persistent/Model/Layout/DepersonalizePluginTest.php new file mode 100644 index 0000000000000..4e92b86b297d7 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Persistent/Model/Layout/DepersonalizePluginTest.php @@ -0,0 +1,163 @@ +objectManager = new \Magento\TestFramework\Helper\ObjectManager($this); + + $this->persistentSessionMock = $this->getMock( + 'Magento\Persistent\Model\Session', + ['setCustomerId'], + [], + '', + false + ); + + $this->requestMock = $this->getMockForAbstractClass( + 'Magento\Framework\App\RequestInterface', + [], + '', + false, + true, + true, + ['isAjax'] + ); + $this->moduleManagerMock = $this->getMock( + 'Magento\Framework\Module\Manager', + ['isEnabled'], + [], + '', + false + ); + $this->cacheConfigMock = $this->getMock( + 'Magento\PageCache\Model\Config', + ['isEnabled'], + [], + '', + false + ); + + $this->plugin = $this->objectManager->getObject( + 'Magento\Persistent\Model\Layout\DepersonalizePlugin', + [ + 'persistentSession' => $this->persistentSessionMock, + 'request' => $this->requestMock, + 'moduleManager' => $this->moduleManagerMock, + 'cacheConfig' => $this->cacheConfigMock + ] + ); + } + + /** + * Run test afterGenerateXml method + * + * @param bool $result + * + * @dataProvider dataProviderAfterGenerateXml + */ + public function testAfterGenerateXml($result) + { + /** @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject $subjectMock */ + $subjectMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\LayoutInterface', + [], + '', + false, + true, + true, + ['isCacheable'] + ); + /** @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject $resultMock */ + $resultMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\LayoutInterface', + [], + '', + false, + true, + true, + [] + ); + + $this->moduleManagerMock->expects($this->once()) + ->method('isEnabled') + ->with('Magento_PageCache') + ->willReturn($result); + $this->cacheConfigMock->expects($this->any()) + ->method('isEnabled') + ->willReturn($result); + $this->requestMock->expects($this->any()) + ->method('isAjax') + ->willReturn(!$result); + $subjectMock->expects($this->any()) + ->method('isCacheable') + ->willReturn($result); + + if ($result) { + $this->persistentSessionMock->expects($this->once()) + ->method('setCustomerId') + ->with(null); + } else { + $this->persistentSessionMock->expects($this->never()) + ->method('setCustomerId') + ->with(null); + } + + $this->assertEquals($resultMock, $this->plugin->afterGenerateXml($subjectMock, $resultMock)); + } + + /** + * Data provider for testAfterGenerateXml + * + * @return array + */ + public function dataProviderAfterGenerateXml() + { + return [ + ['result' => true], + ['result' => false] + ]; + } +} From 2150d5f5850ee0de711962bbd60b6f9b161b5591 Mon Sep 17 00:00:00 2001 From: agurzhyi Date: Tue, 23 Dec 2014 10:33:18 +0200 Subject: [PATCH 10/23] MAGETWO-31784: Tax class drop-down on New Customer Group page should not contain value 'none' --- app/code/Magento/Tax/Model/TaxClass/Source/Customer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php b/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php index 3fd2d7ae6999e..e01a192bb2a7d 100644 --- a/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php +++ b/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php @@ -68,7 +68,7 @@ public function getAllOptions() ]; } if (empty($options)) { - throw new StateException('Customer tax class cannot does not exist.'); + throw new StateException('At least one customer tax class should be present.'); } $this->_options = $options; } From 4463990fb7d55020e82c1b62e0325f7306af62dd Mon Sep 17 00:00:00 2001 From: agurzhyi Date: Tue, 23 Dec 2014 11:09:51 +0200 Subject: [PATCH 11/23] MAGETWO-5713: Shopping Cart Price Rules not applying to configurable products based on product attributes --- .../Model/Rule/Condition/Product.php | 56 +++++++------- .../Model/Condition/AbstractCondition.php | 11 ++- .../Magento/Rule/Model/Condition/Combine.php | 10 +-- .../Condition/Product/AbstractProduct.php | 32 ++++---- .../Model/Rule/Condition/Address.php | 14 ++-- .../Model/Rule/Condition/Product.php | 14 ++-- .../Model/Rule/Condition/Product/Found.php | 6 +- .../Rule/Condition/Product/Subselect.php | 6 +- .../Magento/SalesRule/Model/RulesApplier.php | 13 +++- .../Model/Condition/AbstractConditionTest.php | 42 +++++++++++ .../Condition/Product/AbstractProductTest.php | 49 ++++++++++-- .../SalesRule/Model/RulesApplierTest.php | 75 +++++++++++++++---- 12 files changed, 236 insertions(+), 92 deletions(-) diff --git a/app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php b/app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php index 7511d2f5c0bf0..cb8b7786232a3 100644 --- a/app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php +++ b/app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php @@ -8,26 +8,29 @@ */ namespace Magento\CatalogRule\Model\Rule\Condition; +/** + * Class Product + */ class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct { /** * Validate product attribute value for condition * - * @param \Magento\Framework\Object $object + * @param \Magento\Framework\Model\AbstractModel $model * @return bool */ - public function validate(\Magento\Framework\Object $object) + public function validate(\Magento\Framework\Model\AbstractModel $model) { $attrCode = $this->getAttribute(); if ('category_ids' == $attrCode) { - return $this->validateAttribute($object->getAvailableInCategories()); + return $this->validateAttribute($model->getAvailableInCategories()); } - $oldAttrValue = $object->hasData($attrCode) ? $object->getData($attrCode) : null; - $this->_setAttributeValue($object); + $oldAttrValue = $model->hasData($attrCode) ? $model->getData($attrCode) : null; + $this->_setAttributeValue($model); - $result = $this->validateAttribute($object->getData($this->getAttribute())); - $this->_restoreOldAttrValue($object, $oldAttrValue); + $result = $this->validateAttribute($model->getData($this->getAttribute())); + $this->_restoreOldAttrValue($model, $oldAttrValue); return (bool)$result; } @@ -35,36 +38,36 @@ public function validate(\Magento\Framework\Object $object) /** * Restore old attribute value * - * @param \Magento\Framework\Object $object + * @param \Magento\Framework\Model\AbstractModel $model * @param mixed $oldAttrValue * @return void */ - protected function _restoreOldAttrValue($object, $oldAttrValue) + protected function _restoreOldAttrValue(\Magento\Framework\Model\AbstractModel $model, $oldAttrValue) { $attrCode = $this->getAttribute(); if (is_null($oldAttrValue)) { - $object->unsetData($attrCode); + $model->unsetData($attrCode); } else { - $object->setData($attrCode, $oldAttrValue); + $model->setData($attrCode, $oldAttrValue); } } /** * Set attribute value * - * @param \Magento\Framework\Object $object + * @param \Magento\Framework\Model\AbstractModel $model * @return $this */ - protected function _setAttributeValue($object) + protected function _setAttributeValue(\Magento\Framework\Model\AbstractModel $model) { - $storeId = $object->getStoreId(); + $storeId = $model->getStoreId(); $defaultStoreId = \Magento\Store\Model\Store::DEFAULT_STORE_ID; - if (!isset($this->_entityAttributeValues[$object->getId()])) { + if (!isset($this->_entityAttributeValues[$model->getId()])) { return $this; } - $productValues = $this->_entityAttributeValues[$object->getId()]; + $productValues = $this->_entityAttributeValues[$model->getId()]; if (!isset($productValues[$storeId]) && !isset($productValues[$defaultStoreId])) { return $this; @@ -72,10 +75,11 @@ protected function _setAttributeValue($object) $value = isset($productValues[$storeId]) ? $productValues[$storeId] : $productValues[$defaultStoreId]; - $value = $this->_prepareDatetimeValue($value, $object); - $value = $this->_prepareMultiselectValue($value, $object); + $value = $this->_prepareDatetimeValue($value, $model); + $value = $this->_prepareMultiselectValue($value, $model); + + $model->setData($this->getAttribute(), $value); - $object->setData($this->getAttribute(), $value); return $this; } @@ -83,15 +87,16 @@ protected function _setAttributeValue($object) * Prepare datetime attribute value * * @param mixed $value - * @param \Magento\Framework\Object $object + * @param \Magento\Framework\Model\AbstractModel $model * @return mixed */ - protected function _prepareDatetimeValue($value, $object) + protected function _prepareDatetimeValue($value, \Magento\Framework\Model\AbstractModel $model) { - $attribute = $object->getResource()->getAttribute($this->getAttribute()); + $attribute = $model->getResource()->getAttribute($this->getAttribute()); if ($attribute && $attribute->getBackendType() == 'datetime') { $value = strtotime($value); } + return $value; } @@ -99,15 +104,16 @@ protected function _prepareDatetimeValue($value, $object) * Prepare multiselect attribute value * * @param mixed $value - * @param \Magento\Framework\Object $object + * @param \Magento\Framework\Model\AbstractModel $model * @return mixed */ - protected function _prepareMultiselectValue($value, $object) + protected function _prepareMultiselectValue($value, \Magento\Framework\Model\AbstractModel $model) { - $attribute = $object->getResource()->getAttribute($this->getAttribute()); + $attribute = $model->getResource()->getAttribute($this->getAttribute()); if ($attribute && $attribute->getFrontendInput() == 'multiselect') { $value = strlen($value) ? explode(',', $value) : []; } + return $value; } } diff --git a/app/code/Magento/Rule/Model/Condition/AbstractCondition.php b/app/code/Magento/Rule/Model/Condition/AbstractCondition.php index 9c2987de3a34d..916a1404540f9 100644 --- a/app/code/Magento/Rule/Model/Condition/AbstractCondition.php +++ b/app/code/Magento/Rule/Model/Condition/AbstractCondition.php @@ -832,12 +832,17 @@ protected function _compareValues($validatedValue, $value, $strict = true) } /** - * @param \Magento\Framework\Object $object + * @param \Magento\Framework\Model\AbstractModel $model * @return bool */ - public function validate(\Magento\Framework\Object $object) + public function validate(\Magento\Framework\Model\AbstractModel $model) { - return $this->validateAttribute($object->getData($this->getAttribute())); + if (!$model->hasData($this->getAttribute())) { + $model->load($model->getId()); + } + $attributeValue = $model->getData($this->getAttribute()); + + return $this->validateAttribute($attributeValue); } /** diff --git a/app/code/Magento/Rule/Model/Condition/Combine.php b/app/code/Magento/Rule/Model/Condition/Combine.php index 8e9355a4957b2..f565e98b548d9 100644 --- a/app/code/Magento/Rule/Model/Condition/Combine.php +++ b/app/code/Magento/Rule/Model/Condition/Combine.php @@ -316,12 +316,12 @@ public function asStringRecursive($level = 0) } /** - * @param \Magento\Framework\Object $object + * @param \Magento\Framework\Model\AbstractModel $model * @return bool */ - public function validate(\Magento\Framework\Object $object) + public function validate(\Magento\Framework\Model\AbstractModel $model) { - return $this->_isValid($object); + return $this->_isValid($model); } /** @@ -338,7 +338,7 @@ public function validateByEntityId($entityId) /** * Is entity valid * - * @param int|\Magento\Framework\Object $entity + * @param int|\Magento\Framework\Model\AbstractModel $entity * @return bool */ protected function _isValid($entity) @@ -351,7 +351,7 @@ protected function _isValid($entity) $true = (bool)$this->getValue(); foreach ($this->getConditions() as $cond) { - if ($entity instanceof \Magento\Framework\Object) { + if ($entity instanceof \Magento\Framework\Model\AbstractModel) { $validated = $cond->validate($entity); } else { $validated = $cond->validateByEntityId($entity); diff --git a/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php b/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php index 00034cf90ae76..f0d4de7d40fb9 100644 --- a/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php +++ b/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php @@ -523,50 +523,50 @@ public function loadArray($arr) /** * Validate product attribute value for condition * - * @param \Magento\Framework\Object $object + * @param \Magento\Framework\Model\AbstractModel $model * @return bool */ - public function validate(\Magento\Framework\Object $object) + public function validate(\Magento\Framework\Model\AbstractModel $model) { $attrCode = $this->getAttribute(); if ('category_ids' == $attrCode) { - return $this->validateAttribute($object->getAvailableInCategories()); - } elseif (!isset($this->_entityAttributeValues[$object->getId()])) { - if (!$object->getResource()) { + return $this->validateAttribute($model->getAvailableInCategories()); + } elseif (!isset($this->_entityAttributeValues[$model->getId()])) { + if (!$model->getResource()) { return false; } - $attr = $object->getResource()->getAttribute($attrCode); + $attr = $model->getResource()->getAttribute($attrCode); if ($attr && $attr->getBackendType() == 'datetime' && !is_int($this->getValue())) { $this->setValue(strtotime($this->getValue())); - $value = strtotime($object->getData($attrCode)); + $value = strtotime($model->getData($attrCode)); return $this->validateAttribute($value); } if ($attr && $attr->getFrontendInput() == 'multiselect') { - $value = $object->getData($attrCode); + $value = $model->getData($attrCode); $value = strlen($value) ? explode(',', $value) : []; return $this->validateAttribute($value); } - return parent::validate($object); + return parent::validate($model); } else { $result = false; // any valid value will set it to TRUE // remember old attribute state - $oldAttrValue = $object->hasData($attrCode) ? $object->getData($attrCode) : null; + $oldAttrValue = $model->hasData($attrCode) ? $model->getData($attrCode) : null; - foreach ($this->_entityAttributeValues[$object->getId()] as $value) { - $attr = $object->getResource()->getAttribute($attrCode); + foreach ($this->_entityAttributeValues[$model->getId()] as $value) { + $attr = $model->getResource()->getAttribute($attrCode); if ($attr && $attr->getBackendType() == 'datetime') { $value = strtotime($value); } elseif ($attr && $attr->getFrontendInput() == 'multiselect') { $value = strlen($value) ? explode(',', $value) : []; } - $object->setData($attrCode, $value); - $result |= parent::validate($object); + $model->setData($attrCode, $value); + $result |= parent::validate($model); if ($result) { break; @@ -574,9 +574,9 @@ public function validate(\Magento\Framework\Object $object) } if (is_null($oldAttrValue)) { - $object->unsetData($attrCode); + $model->unsetData($attrCode); } else { - $object->setData($attrCode, $oldAttrValue); + $model->setData($attrCode, $oldAttrValue); } return (bool)$result; diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Address.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Address.php index 49983011229bb..5589be55402fc 100644 --- a/app/code/Magento/SalesRule/Model/Rule/Condition/Address.php +++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Address.php @@ -160,22 +160,22 @@ public function getValueSelectOptions() /** * Validate Address Rule Condition * - * @param \Magento\Framework\Object $object + * @param \Magento\Framework\Model\AbstractModel $model * @return bool */ - public function validate(\Magento\Framework\Object $object) + public function validate(\Magento\Framework\Model\AbstractModel $model) { - $address = $object; + $address = $model; if (!$address instanceof \Magento\Sales\Model\Quote\Address) { - if ($object->getQuote()->isVirtual()) { - $address = $object->getQuote()->getBillingAddress(); + if ($model->getQuote()->isVirtual()) { + $address = $model->getQuote()->getBillingAddress(); } else { - $address = $object->getQuote()->getShippingAddress(); + $address = $model->getQuote()->getShippingAddress(); } } if ('payment_method' == $this->getAttribute() && !$address->hasPaymentMethod()) { - $address->setPaymentMethod($object->getQuote()->getPayment()->getMethod()); + $address->setPaymentMethod($model->getQuote()->getPayment()->getMethod()); } return parent::validate($address); diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php index 9b614b59ae334..2f4fcbf7c0af2 100644 --- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php +++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php @@ -28,24 +28,24 @@ protected function _addSpecialAttributes(array &$attributes) /** * Validate Product Rule Condition * - * @param \Magento\Framework\Object $object + * @param \Magento\Framework\Model\AbstractModel $model * @return bool */ - public function validate(\Magento\Framework\Object $object) + public function validate(\Magento\Framework\Model\AbstractModel $model) { //@todo reimplement this method when is fixed MAGETWO-5713 /** @var \Magento\Catalog\Model\Product $product */ - $product = $object->getProduct(); + $product = $model->getProduct(); if (!$product instanceof \Magento\Catalog\Model\Product) { - $product = $this->productRepository->getById($object->getProductId()); + $product = $this->productRepository->getById($model->getProductId()); } $product->setQuoteItemQty( - $object->getQty() + $model->getQty() )->setQuoteItemPrice( - $object->getPrice() // possible bug: need to use $object->getBasePrice() + $model->getPrice() // possible bug: need to use $model->getBasePrice() )->setQuoteItemRowTotal( - $object->getBaseRowTotal() + $model->getBaseRowTotal() ); return parent::validate($product); diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Found.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Found.php index c36ee4671e1d4..bea0defa401eb 100644 --- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Found.php +++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Found.php @@ -52,15 +52,15 @@ public function asHtml() /** * Validate * - * @param \Magento\Framework\Object $object Quote + * @param \Magento\Framework\Model\AbstractModel $model * @return bool */ - public function validate(\Magento\Framework\Object $object) + public function validate(\Magento\Framework\Model\AbstractModel $model) { $all = $this->getAggregator() === 'all'; $true = (bool)$this->getValue(); $found = false; - foreach ($object->getAllItems() as $item) { + foreach ($model->getAllItems() as $item) { $found = $all; foreach ($this->getConditions() as $cond) { $validated = $cond->validate($item); diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Subselect.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Subselect.php index 59a5455e96b91..08f7503259808 100644 --- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Subselect.php +++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Subselect.php @@ -133,17 +133,17 @@ public function asHtml() /** * Validate * - * @param \Magento\Framework\Object $object Quote + * @param \Magento\Framework\Model\AbstractModel $model * @return bool */ - public function validate(\Magento\Framework\Object $object) + public function validate(\Magento\Framework\Model\AbstractModel $model) { if (!$this->getConditions()) { return false; } $attr = $this->getAttribute(); $total = 0; - foreach ($object->getQuote()->getAllVisibleItems() as $item) { + foreach ($model->getQuote()->getAllVisibleItems() as $item) { if (parent::validate($item)) { $total += $item->getData($attr); } diff --git a/app/code/Magento/SalesRule/Model/RulesApplier.php b/app/code/Magento/SalesRule/Model/RulesApplier.php index f7bde08d44e73..4dace1d8f8df7 100644 --- a/app/code/Magento/SalesRule/Model/RulesApplier.php +++ b/app/code/Magento/SalesRule/Model/RulesApplier.php @@ -59,7 +59,18 @@ public function applyRules($item, $rules, $skipValidation, $couponCode) } if (!$skipValidation && !$rule->getActions()->validate($item)) { - continue; + $childItems = $item->getChildren(); + $isContinue = true; + if (!empty($childItems)) { + foreach ($childItems as $childItem) { + if ($rule->getActions()->validate($childItem)) { + $isContinue = false; + } + } + } + if ($isContinue) { + continue; + } } $this->applyRule($item, $rule, $address, $couponCode); diff --git a/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/AbstractConditionTest.php b/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/AbstractConditionTest.php index ba41ccae4d43e..9d1f9f3ac6f0a 100644 --- a/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/AbstractConditionTest.php +++ b/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/AbstractConditionTest.php @@ -106,6 +106,48 @@ public function testValidateAttribute($existingValue, $operator, $valueForValida ); } + /** + * @param $existingValue + * @param $operator + * @param $valueForValidate + * @param $expectedResult + * + * @dataProvider validateAttributeDataProvider + */ + public function testValidate($existingValue, $operator, $valueForValidate, $expectedResult) + { + $objectMock = $this->getMock( + 'Magento\Framework\Model\AbstractModel', + ['hasData', 'load', 'getId', 'getData'], + [], + '', + false + ); + $objectMock->expects($this->once()) + ->method('hasData') + ->willReturn(false); + $objectMock->expects($this->once()) + ->method('getId') + ->willReturn(7); + $objectMock->expects($this->once()) + ->method('load') + ->with(7); + $objectMock->expects($this->once()) + ->method('getData') + ->willReturn($valueForValidate); + + $this->_condition->setOperator($operator); + $this->_condition->setData('value_parsed', $existingValue); + $this->assertEquals( + $expectedResult, + $this->_condition->validate($objectMock), + "Failed asserting that " + . var_export($existingValue, true) + . $operator + . var_export($valueForValidate, true) + ); + } + public function validateAttributeArrayInputTypeDataProvider() { return [ diff --git a/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/Product/AbstractProductTest.php b/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/Product/AbstractProductTest.php index 97289d77f0598..93ad5f6f97d44 100644 --- a/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/Product/AbstractProductTest.php +++ b/dev/tests/unit/testsuite/Magento/Rule/Model/Condition/Product/AbstractProductTest.php @@ -55,7 +55,7 @@ public function setUp() public function testValidateAttributeEqualCategoryId() { - $product = $this->getMock('\Magento\Framework\Object', ["getAttribute"], [], '', false); + $product = $this->getMock('Magento\Framework\Model\AbstractModel', ["getAttribute"], [], '', false); $this->_condition->setAttribute('category_ids'); $product->setAvailableInCategories(new \Magento\Framework\Object()); $this->assertFalse($this->_condition->validate($product)); @@ -63,7 +63,16 @@ public function testValidateAttributeEqualCategoryId() public function testValidateEmptyEntityAttributeValues() { - $product = $this->getMock('\Magento\Framework\Object', ["getAttribute"], [], '', false); + $product = $this->getMock( + 'Magento\Framework\Model\AbstractModel', + ["getAttribute", 'getResource'], + [], + '', + false + ); + $product->expects($this->once()) + ->method('getResource') + ->willReturn(null); $product->setId(1); $configProperty = new \ReflectionProperty( 'Magento\Rule\Model\Condition\Product\AbstractProduct', @@ -76,7 +85,13 @@ public function testValidateEmptyEntityAttributeValues() public function testValidateEmptyEntityAttributeValuesWithResource() { - $product = $this->getMock('\Magento\Framework\Object', ["getAttribute"], [], '', false); + $product = $this->getMock( + 'Magento\Framework\Model\AbstractModel', + ["getAttribute", 'getResource'], + [], + '', + false + ); $product->setId(1); $time = '04/19/2012 11:59 am'; $product->setData('someAttribute', $time); @@ -103,8 +118,10 @@ public function testValidateEmptyEntityAttributeValuesWithResource() ->with('someAttribute') ->will($this->returnValue($attribute)); $newResource->_config = $this->getMock('Magento\Eav\Model\Config', [], [], '', false); + $product->expects($this->atLeastOnce()) + ->method('getResource') + ->willReturn($newResource); - $product->setResource($newResource); $this->assertFalse($this->_condition->validate($product)); $product->setData('someAttribute', 'option1,option2,option3'); @@ -125,7 +142,13 @@ public function testValidateEmptyEntityAttributeValuesWithResource() public function testValidateSetEntityAttributeValuesWithResource() { $this->_condition->setAttribute('someAttribute'); - $product = $this->getMock('\Magento\Framework\Object', ['getAttribute'], [], '', false); + $product = $this->getMock( + 'Magento\Framework\Model\AbstractModel', + ['getAttribute', 'getResource'], + [], + '', + false + ); $product->setAtribute('attribute'); $product->setId(12); @@ -146,7 +169,9 @@ public function testValidateSetEntityAttributeValuesWithResource() ->will($this->returnValue($attribute)); $newResource->_config = $this->getMock('Magento\Eav\Model\Config', [], [], '', false); - $product->setResource($newResource); + $product->expects($this->atLeastOnce()) + ->method('getResource') + ->willReturn($newResource); $this->_entityAttributeValuesProperty->setValue( $this->_condition, @@ -161,7 +186,13 @@ public function testValidateSetEntityAttributeValuesWithResource() public function testValidateSetEntityAttributeValuesWithoutResource() { - $product = $this->getMock('\Magento\Framework\Object', ['someMethod'], [], '', false); + $product = $this->getMock( + 'Magento\Framework\Model\AbstractModel', + ['someMethod', 'getResource', 'load'], + [], + '', + false + ); $this->_condition->setAttribute('someAttribute'); $product->setAtribute('attribute'); $product->setId(12); @@ -198,7 +229,9 @@ public function testValidateSetEntityAttributeValuesWithoutResource() ->will($this->returnValue($attribute)); $newResource->_config = $this->getMock('Magento\Eav\Model\Config', [], [], '', false); - $product->setResource($newResource); + $product->expects($this->atLeastOnce()) + ->method('getResource') + ->willReturn($newResource); $this->_entityAttributeValuesProperty->setValue( $this->_condition, diff --git a/dev/tests/unit/testsuite/Magento/SalesRule/Model/RulesApplierTest.php b/dev/tests/unit/testsuite/Magento/SalesRule/Model/RulesApplierTest.php index bc875f4835b17..200e619dbfcbe 100644 --- a/dev/tests/unit/testsuite/Magento/SalesRule/Model/RulesApplierTest.php +++ b/dev/tests/unit/testsuite/Magento/SalesRule/Model/RulesApplierTest.php @@ -58,10 +58,16 @@ public function setUp() ); } - public function testApplyRulesWhenRuleWithStopRulesProcessingIsUsed() + /** + * @param bool $isChildren + * @param bool $isContinue + * + * @dataProvider dataProviderChildren + */ + public function testApplyRulesWhenRuleWithStopRulesProcessingIsUsed($isChildren, $isContinue) { $positivePrice = 1; - $skipValidation = true; + $skipValidation = false; $item = $this->getPreparedItem(); $couponCode = 111; @@ -73,7 +79,7 @@ public function testApplyRulesWhenRuleWithStopRulesProcessingIsUsed() */ $ruleWithStopFurtherProcessing = $this->getMock( 'Magento\SalesRule\Model\Rule', - ['getStoreLabel', 'getCouponType', 'getRuleId', '__wakeup'], + ['getStoreLabel', 'getCouponType', 'getRuleId', '__wakeup', 'getActions'], [], '', false @@ -87,6 +93,14 @@ public function testApplyRulesWhenRuleWithStopRulesProcessingIsUsed() false ); + $actionMock = $this->getMock( + 'Magento\Rule\Model\Action\Collection', + ['validate'], + [], + '', + false + ); + $ruleWithStopFurtherProcessing->setName('ruleWithStopFurtherProcessing'); $ruleThatShouldNotBeRun->setName('ruleThatShouldNotBeRun'); $rules = [$ruleWithStopFurtherProcessing, $ruleThatShouldNotBeRun]; @@ -96,20 +110,52 @@ public function testApplyRulesWhenRuleWithStopRulesProcessingIsUsed() $this->validatorUtility->expects($this->atLeastOnce()) ->method('canProcessRule') - ->will( - $this->returnValue(true) - ); - $ruleWithStopFurtherProcessing->expects($this->any()) - ->method('getRuleId') - ->will($this->returnValue($ruleId)); - $this->applyRule($item, $ruleWithStopFurtherProcessing); - $ruleWithStopFurtherProcessing->setStopRulesProcessing(true); - $ruleThatShouldNotBeRun->expects($this->never()) - ->method('getStopRulesProcessing'); + ->will($this->returnValue(true)); + + $ruleWithStopFurtherProcessing->expects($this->atLeastOnce()) + ->method('getActions') + ->willReturn($actionMock); + $actionMock->expects($this->at(0)) + ->method('validate') + ->with($item) + ->willReturn(!$isChildren); + + // if there are child elements, check them + if ($isChildren) { + $item->expects($this->atLeastOnce()) + ->method('getChildren') + ->willReturn([$item]); + $actionMock->expects($this->at(1)) + ->method('validate') + ->with($item) + ->willReturn(!$isContinue); + } + + // + if (!$isContinue || !$isChildren) { + $ruleWithStopFurtherProcessing->expects($this->any()) + ->method('getRuleId') + ->will($this->returnValue($ruleId)); + + $this->applyRule($item, $ruleWithStopFurtherProcessing); + + $ruleWithStopFurtherProcessing->setStopRulesProcessing(true); + $ruleThatShouldNotBeRun->expects($this->never()) + ->method('getStopRulesProcessing'); + } + $result = $this->rulesApplier->applyRules($item, $rules, $skipValidation, $couponCode); $this->assertEquals($appliedRuleIds, $result); } + public function dataProviderChildren() + { + return [ + ['isChildren' => true, 'isContinue' => false], + ['isChildren' => false, 'isContinue' => true], + ]; + } + /** * @return \Magento\Sales\Model\Quote\Item\AbstractItem|\PHPUnit_Framework_MockObject_MockObject */ @@ -137,7 +183,8 @@ protected function getPreparedItem() 'setDiscountPercent', 'getAddress', 'setAppliedRuleIds', - '__wakeup' + '__wakeup', + 'getChildren' ], [], '', From a32b444c9d02ab8f3985ff266ccfe9432756a848 Mon Sep 17 00:00:00 2001 From: agurzhyi Date: Tue, 23 Dec 2014 15:59:47 +0200 Subject: [PATCH 12/23] MAGETWO-27636: Persistent Shopping Cart: 'Not %Username%?' link is displayed during page load for user logged in --- app/code/Magento/Persistent/etc/module.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Persistent/etc/module.xml b/app/code/Magento/Persistent/etc/module.xml index 0a201d7d4ef6e..bc37874917dcf 100644 --- a/app/code/Magento/Persistent/etc/module.xml +++ b/app/code/Magento/Persistent/etc/module.xml @@ -7,6 +7,7 @@ + From a6a3417a85b831e5db1d6c8316202541f3c951ee Mon Sep 17 00:00:00 2001 From: agurzhyi Date: Tue, 23 Dec 2014 16:36:16 +0200 Subject: [PATCH 13/23] MAGETWO-31784: Tax class drop-down on New Customer Group page should not contain value 'none' --- app/code/Magento/Tax/Model/TaxClass/Source/Customer.php | 3 --- .../Magento/Tax/Model/TaxClass/Source/CustomerTest.php | 8 ++------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php b/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php index e01a192bb2a7d..7033763324eb5 100644 --- a/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php +++ b/app/code/Magento/Tax/Model/TaxClass/Source/Customer.php @@ -67,9 +67,6 @@ public function getAllOptions() 'label' => $taxClass->getClassName(), ]; } - if (empty($options)) { - throw new StateException('At least one customer tax class should be present.'); - } $this->_options = $options; } diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php index 4ccee7bf5b7bf..2787e1c44c582 100644 --- a/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php +++ b/dev/tests/unit/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php @@ -164,11 +164,7 @@ public function testGetAllOptions($isEmpty, array $expected) ->method('getItems') ->willReturn($items); // checking exception - try { - $this->customer->getAllOptions(); - } catch (\Exception $e) { - $this->assertInstanceOf('Magento\Framework\Exception\StateException', $e); - } + $this->assertEmpty($this->customer->getAllOptions()); } } @@ -181,7 +177,7 @@ public function dataProviderGetAllOptions() { return [ ['isEmpty' => false, 'expected' => [['value' => 10, 'label' => 'class-name']]], - ['isEmpty' => true, 'expected' => [['value' => '0', 'label' => __('None')]]] + ['isEmpty' => true, 'expected' => []] ]; } } From 0ecb9168718fd74db5e6dcdff5e4e8cb54ef4988 Mon Sep 17 00:00:00 2001 From: agurzhyi Date: Tue, 23 Dec 2014 16:39:36 +0200 Subject: [PATCH 14/23] MAGETWO-27636: Persistent Shopping Cart: 'Not %Username%?' link is displayed during page load for user logged in --- app/code/Magento/Persistent/etc/module.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Persistent/etc/module.xml b/app/code/Magento/Persistent/etc/module.xml index bc37874917dcf..0a201d7d4ef6e 100644 --- a/app/code/Magento/Persistent/etc/module.xml +++ b/app/code/Magento/Persistent/etc/module.xml @@ -7,7 +7,6 @@ - From c9a320b9e938a8ffe7419a7eaa111953d81284ad Mon Sep 17 00:00:00 2001 From: agurzhyi Date: Tue, 23 Dec 2014 16:58:51 +0200 Subject: [PATCH 15/23] MAGETWO-31634: 'Credit Memo' button is absent on Invoice page for Authorize.net --- app/code/Magento/Sales/Model/Order.php | 2 +- .../Magento/Sales/Model/OrderTest.php | 83 ++++++++++++++++++- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 540409a35baf4..89e8ca8befbd5 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -3389,7 +3389,7 @@ public function getStatusHistories() if ($this->getData(ApiOrderInterface::STATUS_HISTORIES) == null) { $this->setData( ApiOrderInterface::STATUS_HISTORIES, - $this->getPaymentsCollection()->getItems() + $this->getStatusHistoryCollection()->getItems() ); } return $this->getData(ApiOrderInterface::STATUS_HISTORIES); diff --git a/dev/tests/unit/testsuite/Magento/Sales/Model/OrderTest.php b/dev/tests/unit/testsuite/Magento/Sales/Model/OrderTest.php index 17e91454fa8cd..6af26f5a8165f 100644 --- a/dev/tests/unit/testsuite/Magento/Sales/Model/OrderTest.php +++ b/dev/tests/unit/testsuite/Magento/Sales/Model/OrderTest.php @@ -4,6 +4,8 @@ */ namespace Magento\Sales\Model; +use Magento\Sales\Model\Resource\Order\Status\History\CollectionFactory as HistoryCollectionFactory; + /** * Test class for \Magento\Sales\Model\Order */ @@ -39,6 +41,11 @@ class OrderTest extends \PHPUnit_Framework_TestCase */ protected $item; + /** + * @var HistoryCollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $historyCollectionFactoryMock; + protected function setUp() { $helper = new \Magento\TestFramework\Helper\ObjectManager($this); @@ -56,6 +63,13 @@ protected function setUp() '', false ); + $this->historyCollectionFactoryMock = $this->getMock( + 'Magento\Sales\Model\Resource\Order\Status\History\CollectionFactory', + ['create'], + [], + '', + false + ); $this->item = $this->getMock( 'Magento\Sales\Model\Resource\Order\Item', ['isDeleted', 'getQtyToInvoice', 'getParentItemId', 'getQuoteItemId'], @@ -87,7 +101,8 @@ protected function setUp() 'paymentCollectionFactory' => $this->paymentCollectionFactoryMock, 'orderItemCollectionFactory' => $this->orderItemCollectionFactoryMock, 'data' => ['increment_id' => $this->incrementId], - 'context' => $context + 'context' => $context, + 'historyCollectionFactory' => $this->historyCollectionFactoryMock ] ); } @@ -484,4 +499,70 @@ public function testGetEntityType() { $this->assertEquals('order', $this->order->getEntityType()); } + + /** + * Run test getStatusHistories method + * + * @return void + */ + public function testGetStatusHistories() + { + $itemMock = $this->getMockForAbstractClass( + 'Magento\Sales\Api\Data\OrderStatusHistoryInterface', + [], + '', + false, + true, + true, + ['setOrder'] + ); + $dbMock = $this->getMock( + 'Magento\Framework\Data\Collection\Db', + ['setOrder'], + [], + '', + false + ); + $collectionMock = $this->getMock( + 'Magento\Sales\Model\Resource\Order\Status\History\Collection', + [ + 'setOrderFilter', + 'setOrder', + 'getItems', + 'getIterator', + 'toOptionArray', + 'count', + 'load' + ], + [], + '', + false + ); + + $collectionItems = [$itemMock]; + + $collectionMock->expects($this->once()) + ->method('setOrderFilter') + ->with($this->order) + ->willReturnSelf(); + $collectionMock->expects($this->once()) + ->method('setOrder') + ->with('created_at', 'desc') + ->willReturn($dbMock); + $dbMock->expects($this->once()) + ->method('setOrder') + ->with('entity_id', 'desc') + ->willReturn($collectionMock); + $collectionMock->expects($this->once()) + ->method('getItems') + ->willReturn($collectionItems); + + $this->historyCollectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($collectionMock); + + for ($i = 10; --$i;) { + $this->assertEquals($collectionItems, $this->order->getStatusHistories()); + } + } } From d3d2de734ca92818f831d2206ef68349137b89c0 Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov Date: Mon, 15 Dec 2014 17:40:24 +0200 Subject: [PATCH 16/23] MAGETWO-3404: Transactions Tab on Order page in Admin Signed-off-by: Dmytro Voskoboinikov --- .../OfflinePayments/Model/Banktransfer.php | 7 + .../OfflinePayments/Model/Cashondelivery.php | 7 + .../Magento/OfflinePayments/Model/Checkmo.php | 7 + .../OfflinePayments/Model/Purchaseorder.php | 7 + .../Payment/Model/Method/AbstractMethod.php | 17 +++ .../Adminhtml/Order/View/Tab/Transactions.php | 24 +++- .../Order/View/Tab/TransactionsTest.php | 128 ++++++++++++++++++ 7 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/TransactionsTest.php diff --git a/app/code/Magento/OfflinePayments/Model/Banktransfer.php b/app/code/Magento/OfflinePayments/Model/Banktransfer.php index fb8d31b9c90f3..858f68ddc21c5 100644 --- a/app/code/Magento/OfflinePayments/Model/Banktransfer.php +++ b/app/code/Magento/OfflinePayments/Model/Banktransfer.php @@ -32,6 +32,13 @@ class Banktransfer extends \Magento\Payment\Model\Method\AbstractMethod */ protected $_infoBlockType = 'Magento\Payment\Block\Info\Instructions'; + /** + * Availability option + * + * @var bool + */ + protected $_isOffline = true; + /** * Get instructions text from config * diff --git a/app/code/Magento/OfflinePayments/Model/Cashondelivery.php b/app/code/Magento/OfflinePayments/Model/Cashondelivery.php index 74097a8272868..07ca59f6ac748 100644 --- a/app/code/Magento/OfflinePayments/Model/Cashondelivery.php +++ b/app/code/Magento/OfflinePayments/Model/Cashondelivery.php @@ -30,6 +30,13 @@ class Cashondelivery extends \Magento\Payment\Model\Method\AbstractMethod */ protected $_infoBlockType = 'Magento\Payment\Block\Info\Instructions'; + /** + * Availability option + * + * @var bool + */ + protected $_isOffline = true; + /** * Get instructions text from config * diff --git a/app/code/Magento/OfflinePayments/Model/Checkmo.php b/app/code/Magento/OfflinePayments/Model/Checkmo.php index 4b1bc2b055842..37a8e7a3e20cc 100644 --- a/app/code/Magento/OfflinePayments/Model/Checkmo.php +++ b/app/code/Magento/OfflinePayments/Model/Checkmo.php @@ -21,6 +21,13 @@ class Checkmo extends \Magento\Payment\Model\Method\AbstractMethod */ protected $_infoBlockType = 'Magento\OfflinePayments\Block\Info\Checkmo'; + /** + * Availability option + * + * @var bool + */ + protected $_isOffline = true; + /** * Assign data to info model instance * diff --git a/app/code/Magento/OfflinePayments/Model/Purchaseorder.php b/app/code/Magento/OfflinePayments/Model/Purchaseorder.php index d41a3cdbf77cc..0c82a6352f44a 100644 --- a/app/code/Magento/OfflinePayments/Model/Purchaseorder.php +++ b/app/code/Magento/OfflinePayments/Model/Purchaseorder.php @@ -21,6 +21,13 @@ class Purchaseorder extends \Magento\Payment\Model\Method\AbstractMethod */ protected $_infoBlockType = 'Magento\OfflinePayments\Block\Info\Purchaseorder'; + /** + * Availability option + * + * @var bool + */ + protected $_isOffline = true; + /** * Assign data to info model instance * diff --git a/app/code/Magento/Payment/Model/Method/AbstractMethod.php b/app/code/Magento/Payment/Model/Method/AbstractMethod.php index 993666627b4ea..cbeea1302ecac 100644 --- a/app/code/Magento/Payment/Model/Method/AbstractMethod.php +++ b/app/code/Magento/Payment/Model/Method/AbstractMethod.php @@ -70,6 +70,13 @@ abstract class AbstractMethod extends \Magento\Framework\Object implements Metho */ protected $_isGateway = false; + /** + * Payment Method feature + * + * @var bool + */ + protected $_isOffline = false; + /** * Payment Method feature * @@ -370,6 +377,16 @@ public function isGateway() return $this->_isGateway; } + /** + * Retrieve payment method online/offline flag + * + * @return bool + */ + public function isOffline() + { + return $this->_isOffline; + } + /** * Flag if we need to run payment initialize while order place * diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/Transactions.php b/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/Transactions.php index c807707f19da4..cdddae0d54fe9 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/Transactions.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/Transactions.php @@ -17,20 +17,40 @@ class Transactions extends \Magento\Framework\View\Element\Text\ListText impleme */ protected $_authorization; + /** + * Core registry + * + * @var \Magento\Framework\Registry + */ + protected $_coreRegistry = null; + /** * @param \Magento\Framework\View\Element\Context $context * @param \Magento\Framework\AuthorizationInterface $authorization + * @param \Magento\Framework\Registry $registry * @param array $data */ public function __construct( \Magento\Framework\View\Element\Context $context, \Magento\Framework\AuthorizationInterface $authorization, - array $data = [] + \Magento\Framework\Registry $registry, + array $data = array() ) { $this->_authorization = $authorization; + $this->_coreRegistry = $registry; parent::__construct($context, $data); } + /** + * Retrieve order model instance + * + * @return \Magento\Sales\Model\Order + */ + public function getOrder() + { + return $this->_coreRegistry->registry('current_order'); + } + /** * {@inheritdoc} */ @@ -52,7 +72,7 @@ public function getTabTitle() */ public function canShowTab() { - return true; + return !$this->getOrder()->getPayment()->getMethodInstance()->isOffline(); } /** diff --git a/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/TransactionsTest.php b/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/TransactionsTest.php new file mode 100644 index 0000000000000..c006dbd646ef7 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/TransactionsTest.php @@ -0,0 +1,128 @@ +objectManager = new \Magento\TestFramework\Helper\ObjectManager($this); + + $this->authorizationMock = $this->getMock('\Magento\Framework\Authorization', [], [], '', false); + $this->coreRegistryMock = $this->getMock('Magento\Framework\Registry', [], [], '', false); + $this->orderMock = $this->getMock('\Magento\Sales\Model\Order', [], [], '', false); + $this->paymentMock = $this->getMock('\Magento\Sales\Model\Order\Payment', [], [], '', false); + + $this->coreRegistryMock->expects($this->any()) + ->method('registry') + ->with('current_order') + ->willReturn($this->orderMock); + + $this->orderMock->expects($this->any()) + ->method('getPayment') + ->willReturn($this->paymentMock); + + $this->transactionsTab = $this->objectManager->getObject( + 'Magento\Sales\Block\Adminhtml\Order\View\Tab\Transactions', + [ + 'authorization' => $this->authorizationMock, + 'registry' => $this->coreRegistryMock + ] + ); + } + + public function testGetOrder() + { + $this->assertInstanceOf('\Magento\Sales\Model\Order', $this->transactionsTab->getOrder()); + } + + /** + * @param string $methodClass + * @param bool $expectedResult + * @depends testGetOrder + * @dataProvider canShowTabDataProvider + */ + public function testCanShowTab($methodClass, $expectedResult) + { + $methodInstance = $this->objectManager->getObject($methodClass); + $this->paymentMock->expects($this->any()) + ->method('getMethodInstance') + ->willReturn($methodInstance); + + $this->assertEquals($expectedResult, $this->transactionsTab->canShowTab()); + } + + /** + * @return array + */ + public function canShowTabDataProvider() + { + return [ + ['\Magento\Pbridge\Model\Payment\Method\Authorizenet', true], + ['\Magento\Authorizenet\Model\Authorizenet', true], + ['\Magento\OfflinePayments\Model\Cashondelivery', false], + ['\Magento\OfflinePayments\Model\Checkmo', false] + ]; + } + + /** + * @param bool $isAllowed + * @param bool $expectedResult + * @dataProvider isHiddenDataProvider + */ + public function testIsHidden($isAllowed, $expectedResult) + { + $this->authorizationMock->expects($this->any()) + ->method('isAllowed') + ->with('Magento_Sales::transactions_fetch') + ->willReturn($isAllowed); + + $this->assertEquals($expectedResult, $this->transactionsTab->isHidden()); + } + + /** + * @return array + */ + public function isHiddenDataProvider() + { + return [ + [true, false], + [false, true] + ]; + } +} From 2f99c7cb26f33f2e1a0c577360b91865605b5c5e Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov Date: Tue, 16 Dec 2014 11:27:00 +0200 Subject: [PATCH 17/23] MAGETWO-3404: Transactions Tab on Order page in Admin - Unit tests were updated. Signed-off-by: Dmytro Voskoboinikov --- .../Order/View/Tab/Stub/OnlineMethod.php | 18 ++++++++++++++++++ .../Order/View/Tab/TransactionsTest.php | 7 ++++--- 2 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/Stub/OnlineMethod.php diff --git a/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/Stub/OnlineMethod.php b/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/Stub/OnlineMethod.php new file mode 100644 index 0000000000000..28818895ef30c --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Sales/Block/Adminhtml/Order/View/Tab/Stub/OnlineMethod.php @@ -0,0 +1,18 @@ + Date: Tue, 16 Dec 2014 13:32:00 +0200 Subject: [PATCH 18/23] MAGETWO-3404: Transactions Tab on Order page in Admin - Changes according to Bamboo tests results. Signed-off-by: Dmytro Voskoboinikov --- .../Sales/Block/Adminhtml/Order/View/Tab/Transactions.php | 2 +- .../Magento/Test/Php/_files/phpcpd/blacklist/common.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/Transactions.php b/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/Transactions.php index cdddae0d54fe9..a39f367057dc0 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/Transactions.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/Transactions.php @@ -34,7 +34,7 @@ public function __construct( \Magento\Framework\View\Element\Context $context, \Magento\Framework\AuthorizationInterface $authorization, \Magento\Framework\Registry $registry, - array $data = array() + array $data = [] ) { $this->_authorization = $authorization; $this->_coreRegistry = $registry; diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt index 89690a5dd6300..083fbe5c84c2f 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt +++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt @@ -144,3 +144,4 @@ app/code/Magento/Sales/Model/Spi Magento/Catalog/Model/ProductLink Magento/GroupedProduct/Model/Resource/Product/Type/Grouped lib/internal/Magento/Framework/Interception/ObjectManager/Config +app/code/Magento/OfflinePayments/Model \ No newline at end of file From f1b21e05c9fcaaafd5753098ed0570979b8331b1 Mon Sep 17 00:00:00 2001 From: Sergey Ivashchenko Date: Wed, 24 Dec 2014 14:29:15 +0200 Subject: [PATCH 19/23] MAGETWO-7359: Incorrect totals shown on coupon usage report --- .../SalesRule/Model/Resource/Report/Rule/CreatedatTest.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Resource/Report/Rule/CreatedatTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Resource/Report/Rule/CreatedatTest.php index aabe4d1790ba1..2d14ae963cee1 100644 --- a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Resource/Report/Rule/CreatedatTest.php +++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Resource/Report/Rule/CreatedatTest.php @@ -1,9 +1,6 @@ Date: Wed, 24 Dec 2014 14:29:50 +0200 Subject: [PATCH 20/23] MAGETWO-31784: Tax class drop-down on New Customer Group page should not contain None value --- .../testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php index aca4b4b4c5926..f6ef2eced2db7 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/Source/CustomerTest.php @@ -46,7 +46,6 @@ public function testGetAllOptionsWithDefaultValues() if (empty($expectedResult)) { $this->fail('Preconditions failed: At least one tax class should be available.'); } - $expectedResult = array_merge([['value' => '0', 'label' => __('None')]], $expectedResult); /** @var \Magento\Tax\Model\TaxClass\Source\Product $source */ $source = Bootstrap::getObjectManager()->get('Magento\Tax\Model\TaxClass\Source\Customer'); $this->assertEquals( From f2c827ddeab2f1377ba832aa4a4581afeecb077e Mon Sep 17 00:00:00 2001 From: Sergey Ivashchenko Date: Wed, 24 Dec 2014 15:36:13 +0200 Subject: [PATCH 21/23] MAGETWO-27636: Persistent Shopping Cart: Not Username? link is displayed during page load for user logged in --- app/code/Magento/Persistent/etc/frontend/di.xml | 2 +- app/code/Magento/Persistent/etc/module.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Persistent/etc/frontend/di.xml b/app/code/Magento/Persistent/etc/frontend/di.xml index a3d5a161a1746..d35e4c3dc204c 100644 --- a/app/code/Magento/Persistent/etc/frontend/di.xml +++ b/app/code/Magento/Persistent/etc/frontend/di.xml @@ -13,7 +13,7 @@ - diff --git a/app/code/Magento/Persistent/etc/module.xml b/app/code/Magento/Persistent/etc/module.xml index 0a201d7d4ef6e..c71ae0efdf486 100644 --- a/app/code/Magento/Persistent/etc/module.xml +++ b/app/code/Magento/Persistent/etc/module.xml @@ -8,6 +8,7 @@ + From 33dc4a840ea7b586d6569f392dba36589e62eb2b Mon Sep 17 00:00:00 2001 From: Sergey Ivashchenko Date: Wed, 24 Dec 2014 15:52:02 +0200 Subject: [PATCH 22/23] MAGETWO-32110: Create pull request for all bugfixes made while code freeze --- .../functional/testsuites/Mtf/TestSuite/EndToEndCETests.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/functional/testsuites/Mtf/TestSuite/EndToEndCETests.php b/dev/tests/functional/testsuites/Mtf/TestSuite/EndToEndCETests.php index a02b42d41eaf6..42243f0d1d784 100755 --- a/dev/tests/functional/testsuites/Mtf/TestSuite/EndToEndCETests.php +++ b/dev/tests/functional/testsuites/Mtf/TestSuite/EndToEndCETests.php @@ -39,8 +39,8 @@ public static function suite() $suite->addTestSuite('Magento\CatalogSearch\Test\TestCase\AdvancedSearchTest'); // Url rewrites - $suite->addTestSuite('Magento\Urlrewrite\Test\TestCase\ProductTest'); - $suite->addTestSuite('Magento\Urlrewrite\Test\TestCase\CategoryTest'); + $suite->addTestSuite('Magento\UrlRewrite\Test\TestCase\ProductTest'); + $suite->addTestSuite('Magento\UrlRewrite\Test\TestCase\CategoryTest'); // Customer $suite->addTestSuite('Magento\Customer\Test\TestCase\BackendCustomerCreateTest'); From 5e4be3b532b7027fbe8bab04034859057cfd9550 Mon Sep 17 00:00:00 2001 From: Sergey Ivashchenko Date: Wed, 24 Dec 2014 16:57:39 +0200 Subject: [PATCH 23/23] MAGETWO-32110: Create pull request for all bugfixes made while code freeze --- app/code/Magento/Persistent/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Persistent/composer.json b/app/code/Magento/Persistent/composer.json index f875228c95812..b09817d8ff101 100644 --- a/app/code/Magento/Persistent/composer.json +++ b/app/code/Magento/Persistent/composer.json @@ -9,6 +9,7 @@ "magento/module-customer": "0.42.0-beta1", "magento/module-sales": "0.42.0-beta1", "magento/module-cron": "0.42.0-beta1", + "magento/module-page-cache": "0.42.0-beta1", "magento/framework": "0.42.0-beta1", "magento/magento-composer-installer": "*" },