From 01307c702546605cc7d1679261404665d92e84a1 Mon Sep 17 00:00:00 2001 From: DmytroPaidych Date: Tue, 24 Mar 2020 17:24:20 +0200 Subject: [PATCH 1/6] MC-32709: Customer configuration: Account sharing options --- .../AccountManagement/CreateAccountTest.php | 29 ++- .../Customer/Model/Config/ShareTest.php | 73 +++++-- .../Customer/Model/CustomerRegistryTest.php | 192 ++++++++++++------ .../_files/customer_for_second_website.php | 40 ++++ .../customer_for_second_website_rollback.php | 28 +++ 5 files changed, 280 insertions(+), 82 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/customer_for_second_website.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/customer_for_second_website_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php index 8be3dfc10d86e..28fefd0bc4e1b 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php @@ -19,6 +19,7 @@ use Magento\Framework\Encryption\EncryptorInterface; use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\State\InputMismatchException; use Magento\Framework\Math\Random; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Validator\Exception; @@ -496,9 +497,33 @@ public function testCreateNewCustomerFromClone(): void $this->assertCustomerData($customer, $expectedCustomerData); $this->accountManagement->authenticate( $customer->getEmail(), - '_aPassword1', - true + '_aPassword1' + ); + } + + /** + * Test for create customer account for second website (with existing email for default website) + * with global account scope config. + * + * @magentoConfigFixture current_store customer/account_share/scope 0 + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * + * @return void + */ + public function testCreateAccountInGlobalScope(): void + { + $customerEntity = $this->customerFactory->create(); + $this->dataObjectHelper->populateWithArray( + $customerEntity, + $this->defaultCustomerData, + CustomerInterface::class ); + $storeId = $this->storeManager->getStore('fixture_second_store')->getStoreId(); + $customerEntity->setStoreId($storeId); + $message = 'A customer with the same email address already exists in an associated website.'; + $this->expectExceptionObject(new InputMismatchException(__($message))); + $this->accountManagement->createAccount($customerEntity, '_aPassword1'); } /** diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Config/ShareTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Config/ShareTest.php index 0c35155e5f213..f8371ee959bae 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Config/ShareTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Config/ShareTest.php @@ -3,43 +3,80 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Customer\Model\Config; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\ObjectManagerInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; /** * Test \Magento\Customer\Model\Config\Share */ -class ShareTest extends \PHPUnit\Framework\TestCase +class ShareTest extends TestCase { - public function testGetSharedWebsiteIds() + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Share */ + private $share; + + /** @var WebsiteRepositoryInterface */ + private $websiteRepository; + + /** + * @inheritdoc + */ + protected function setUp() { - /** @var Share $share */ - $share = Bootstrap::getObjectManager()->get(\Magento\Customer\Model\Config\Share::class); + parent::setUp(); - $websiteIds = $share->getSharedWebsiteIds(42); + $this->objectManager = Bootstrap::getObjectManager(); + $this->share = $this->objectManager->get(Share::class); + $this->websiteRepository = $this->objectManager->create(WebsiteRepositoryInterface::class); + } + /** + * @return void + */ + public function testGetSharedWebsiteIds(): void + { + $websiteIds = $this->share->getSharedWebsiteIds(42); $this->assertEquals([42], $websiteIds); } /** * @magentoDataFixture Magento/Store/_files/core_second_third_fixturestore.php * @magentoConfigFixture current_store customer/account_share/scope 0 + * + * @return void */ - public function testGetSharedWebsiteIdsMultipleSites() + public function testGetSharedWebsiteIdsMultipleSites(): void { - /** @var Share $share */ - $share = Bootstrap::getObjectManager()->get(\Magento\Customer\Model\Config\Share::class); - $expectedIds = [1]; - /** @var \Magento\Store\Model\Website $website */ - $website = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Store\Model\Website::class - ); - $expectedIds[] = $website->load('secondwebsite')->getId(); - $expectedIds[] = $website->load('thirdwebsite')->getId(); - - $websiteIds = $share->getSharedWebsiteIds(42); - + $expectedIds[] = $this->websiteRepository->get('base')->getId(); + $expectedIds[] = $this->websiteRepository->get('secondwebsite')->getId(); + $expectedIds[] = $this->websiteRepository->get('thirdwebsite')->getId(); + $websiteIds = $this->share->getSharedWebsiteIds(42); $this->assertEquals($expectedIds, $websiteIds); } + + /** + * @magentoConfigFixture current_store customer/account_share/scope 1 + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_for_second_website.php + * @magentoDbIsolation enabled + * + * @return void + */ + public function testEnableGlobalAccountShareScope(): void + { + $message = 'We can\'t share customer accounts globally when the accounts share' + . ' identical email addresses on more than one website.'; + $this->expectExceptionObject(new LocalizedException(__($message))); + $this->share->setPath(Share::XML_PATH_CUSTOMER_ACCOUNT_SHARE)->setValue((string)Share::SHARE_GLOBAL) + ->beforeSave(); + } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerRegistryTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerRegistryTest.php index d885d7c6f36e0..7bff71bb85bf8 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerRegistryTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerRegistryTest.php @@ -3,127 +3,195 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Customer\Model; +use Magento\Customer\Model\ResourceModel\Customer as CustomerResourceModel; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\ObjectManagerInterface; +use Magento\Store\Model\StoreManagerInterface; use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; /** * Test for \Magento\Customer\Model\CustomerRegistry + * + * @magentoDbIsolation enabled */ -class CustomerRegistryTest extends \PHPUnit\Framework\TestCase +class CustomerRegistryTest extends TestCase { /** - * @var \Magento\Customer\Model\CustomerRegistry + * @var ObjectManagerInterface */ - protected $_model; + private $objectManager; - /**#@+ - * Data set in customer fixture + /** + * @var CustomerRegistry + */ + private $model; + + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var CustomerResourceModel */ - const CUSTOMER_ID = 1; - const CUSTOMER_EMAIL = 'customer@example.com'; - const WEBSITE_ID = 1; + private $customerResourceModel; /** - * Initialize SUT + * @var int + */ + private $defaultWebsiteId; + + /** + * @inheritdoc */ protected function setUp() { - $this->_model = Bootstrap::getObjectManager() - ->create(\Magento\Customer\Model\CustomerRegistry::class); + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->model = $this->objectManager->get(CustomerRegistry::class); + $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); + $this->customerResourceModel = $this->objectManager->get(CustomerResourceModel::class); + $this->defaultWebsiteId = $this->storeManager->getWebsite('base')->getWebsiteId(); } /** * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void */ - public function testRetrieve() + public function testRetrieve(): void { - $customer = $this->_model->retrieve(self::CUSTOMER_ID); - $this->assertInstanceOf(\Magento\Customer\Model\Customer::class, $customer); - $this->assertEquals(self::CUSTOMER_ID, $customer->getId()); + $customer = $this->model->retrieve(1); + $this->assertInstanceOf(Customer::class, $customer); + $this->assertEquals(1, $customer->getId()); } /** * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void */ - public function testRetrieveByEmail() + public function testRetrieveByEmail(): void { - $customer = $this->_model->retrieveByEmail('customer@example.com', self::WEBSITE_ID); - $this->assertInstanceOf(\Magento\Customer\Model\Customer::class, $customer); - $this->assertEquals(self::CUSTOMER_EMAIL, $customer->getEmail()); + $email = 'customer@example.com'; + $customer = $this->model->retrieveByEmail($email, $this->defaultWebsiteId); + $this->assertInstanceOf(Customer::class, $customer); + $this->assertEquals($email, $customer->getEmail()); } /** * @magentoDataFixture Magento/Customer/_files/customer.php * @magentoAppArea adminhtml + * + * @return void */ - public function testRetrieveCached() + public function testRetrieveCached(): void { - //Setup customer in the id and email registries - $customerBeforeDeletion = $this->_model->retrieve(self::CUSTOMER_ID); - //Delete the customer from db - Bootstrap::getObjectManager()->create( - \Magento\Customer\Model\Customer::class - )->load(self::CUSTOMER_ID)->delete(); - //Verify presence of Customer in registry - $this->assertEquals($customerBeforeDeletion, $this->_model->retrieve(self::CUSTOMER_ID)); - //Verify presence of Customer in email registry - $this->assertEquals($customerBeforeDeletion, $this->_model - ->retrieveByEmail(self::CUSTOMER_EMAIL, self::WEBSITE_ID)); + $customerId = 1; + $customerBeforeDeletion = $this->model->retrieve($customerId); + $this->customerResourceModel->load($customerBeforeDeletion, $customerBeforeDeletion->getId()); + $this->customerResourceModel->delete($customerBeforeDeletion); + $this->assertEquals($customerBeforeDeletion, $this->model->retrieve($customerId)); + $this->assertEquals($customerBeforeDeletion, $this->model + ->retrieveByEmail('customer@example.com', $this->defaultWebsiteId)); } /** - * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage No such entity with customerId = 1 + * @return void */ - public function testRetrieveException() + public function testRetrieveException(): void { - $this->_model->retrieve(self::CUSTOMER_ID); + $customerId = 1; + $this->expectException(NoSuchEntityException::class); + $this->expectExceptionMessage(sprintf('No such entity with customerId = %s', $customerId)); + $this->model->retrieve($customerId); } - public function testRetrieveEmailException() + /** + * @return void + */ + public function testRetrieveEmailException(): void { - try { - $this->_model->retrieveByEmail(self::CUSTOMER_EMAIL, self::WEBSITE_ID); - $this->fail("NoSuchEntityException was not thrown as expected."); - } catch (NoSuchEntityException $e) { - $expectedParams = [ - 'fieldName' => 'email', - 'fieldValue' => 'customer@example.com', - 'field2Name' => 'websiteId', - 'field2Value' => 1, - ]; - $this->assertEquals($expectedParams, $e->getParameters()); - } + $email = 'customer@example.com'; + $this->expectExceptionObject( + NoSuchEntityException::doubleField('email', $email, 'websiteId', $this->defaultWebsiteId) + ); + $this->model->retrieveByEmail($email, $this->defaultWebsiteId); } /** * @magentoDataFixture Magento/Customer/_files/customer.php - * @expectedException \Magento\Framework\Exception\NoSuchEntityException * @magentoAppArea adminhtml + * + * @return void */ - public function testRemove() + public function testRemove(): void { - $customer = $this->_model->retrieve(self::CUSTOMER_ID); - $this->assertInstanceOf(\Magento\Customer\Model\Customer::class, $customer); - $customer->delete(); - $this->_model->remove(self::CUSTOMER_ID); - $this->_model->retrieve(self::CUSTOMER_ID); + $customerId = 1; + $customer = $this->model->retrieve($customerId); + $this->assertInstanceOf(Customer::class, $customer); + $this->customerResourceModel->delete($customer); + $this->model->remove($customerId); + $this->expectException(NoSuchEntityException::class); + $this->model->retrieve($customerId); } /** * @magentoDataFixture Magento/Customer/_files/customer.php - * @expectedException \Magento\Framework\Exception\NoSuchEntityException * @magentoAppArea adminhtml + * + * @return void + */ + public function testRemoveByEmail(): void + { + $email = 'customer@example.com'; + $customer = $this->model->retrieve(1); + $this->assertInstanceOf(Customer::class, $customer); + $this->customerResourceModel->delete($customer); + $this->model->removeByEmail($email, $this->defaultWebsiteId); + $this->expectException(NoSuchEntityException::class); + $this->model->retrieveByEmail($email, $customer->getWebsiteId()); + } + + /** + * Test customer is available for all websites with global account scope config. + * + * @magentoConfigFixture current_store customer/account_share/scope 0 + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * + * @return void + */ + public function testRetrieveAccountInGlobalScope(): void + { + $email = 'customer@example.com'; + $websiteId = $this->storeManager->getWebsite('test')->getWebsiteId(); + $customer = $this->model->retrieveByEmail($email, $websiteId); + $this->assertEquals($email, $customer->getEmail()); + } + + /** + * Test customer is not available for second website with account scope config per websites. + * + * @magentoConfigFixture current_store customer/account_share/scope 1 + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * + * @return void */ - public function testRemoveByEmail() + public function testRetrieveAccountInWebsiteScope(): void { - $customer = $this->_model->retrieve(self::CUSTOMER_ID); - $this->assertInstanceOf(\Magento\Customer\Model\Customer::class, $customer); - $customer->delete(); - $this->_model->removeByEmail(self::CUSTOMER_EMAIL, self::WEBSITE_ID); - $this->_model->retrieveByEmail(self::CUSTOMER_EMAIL, $customer->getWebsiteId()); + $email = 'customer@example.com'; + $websiteId = $this->storeManager->getWebsite('test')->getWebsiteId(); + $this->expectExceptionObject( + NoSuchEntityException::doubleField('email', $email, 'websiteId', $websiteId) + ); + $this->model->retrieveByEmail($email, $websiteId); } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_for_second_website.php b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_for_second_website.php new file mode 100644 index 0000000000000..c4df3e9fc8137 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_for_second_website.php @@ -0,0 +1,40 @@ +get(AccountManagementInterface::class); +/** @var CustomerFactory $customerFactory */ +$customerFactory = $objectManager->get(CustomerFactory::class); +/** @var AttributeRepository $attributeRepository */ +$attributeRepository = $objectManager->get(AttributeRepository::class); +$gender = $attributeRepository->get(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, CustomerInterface::GENDER) + ->getSource()->getOptionId('Male'); +$defaultGroupId = $objectManager->get(GroupManagement::class)->getDefaultGroup($store->getStoreId())->getId(); + +$customer = $customerFactory->create(); +$customer->setWebsiteId($websiteId) + ->setEmail('customer@example.com') + ->setGroupId($defaultGroupId) + ->setStoreId($store->getStoreId()) + ->setFirstname('John') + ->setLastname('Smith') + ->setDefaultBilling(1) + ->setDefaultShipping(1) + ->setGender($gender); + +$accountManagment->createAccount($customer, 'Apassword1'); diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_for_second_website_rollback.php b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_for_second_website_rollback.php new file mode 100644 index 0000000000000..2d2bd7b4587d3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_for_second_website_rollback.php @@ -0,0 +1,28 @@ +get(CustomerRepositoryInterface::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $customer = $customerRepository->get('customer@example.com', $websiteId); + $customerRepository->delete($customer); +} catch (NoSuchEntityException $e) { + //customer already deleted +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); From 7be2671585e2d294c2a2f6027f0bbee8f2e6a8d2 Mon Sep 17 00:00:00 2001 From: DmytroPaidych Date: Tue, 24 Mar 2020 17:31:19 +0200 Subject: [PATCH 2/6] MC-32713: Admin: Customer force sign in --- .../Customer/InvalidateTokenTest.php | 79 +++++++++++++++++++ .../customer_with_integration_token.php | 15 ++++ ...stomer_with_integration_token_rollback.php | 8 ++ 3 files changed, 102 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Customer/InvalidateTokenTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Integration/_files/customer_with_integration_token.php create mode 100644 dev/tests/integration/testsuite/Magento/Integration/_files/customer_with_integration_token_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Customer/InvalidateTokenTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Customer/InvalidateTokenTest.php new file mode 100644 index 0000000000000..396824b44304d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Customer/InvalidateTokenTest.php @@ -0,0 +1,79 @@ +escaper = $this->_objectManager->get(Escaper::class); + } + + /** + * @magentoDataFixture Magento/Integration/_files/customer_with_integration_token.php + * + * @return void + */ + public function testInvalidateCustomerToken(): void + { + $customerId = 1; + $this->getRequest()->setParam('customer_id', $customerId)->setMethod(HttpRequest::METHOD_GET); + $this->dispatch('backend/customer/customer/invalidateToken'); + $this->assertRedirect($this->stringContains('backend/customer/index/edit/id/' . $customerId)); + $message = $this->escaper->escapeHtml('You have revoked the customer\'s tokens.'); + $this->assertSessionMessages($this->equalTo([(string)__($message)]), MessageInterface::TYPE_SUCCESS); + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testInvalidateCustomerWithoutToken(): void + { + $customerId = 1; + $this->getRequest()->setParam('customer_id', $customerId)->setMethod(HttpRequest::METHOD_GET); + $this->dispatch('backend/customer/customer/invalidateToken'); + $this->assertRedirect($this->stringContains('backend/customer/index/edit/id/' . $customerId)); + $this->assertSessionMessages( + $this->equalTo([(string)__('This customer has no tokens.')]), + MessageInterface::TYPE_ERROR + ); + } + + /** + * @return void + */ + public function testInvalidateCustomerTokenWithoutParams(): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_GET); + $this->dispatch('backend/customer/customer/invalidateToken'); + $this->assertRedirect($this->stringContains('backend/customer/index/index')); + $message = $this->escaper->escapeHtml('We can\'t find a customer to revoke.'); + $this->assertSessionMessages($this->equalTo([(string)__($message)]), MessageInterface::TYPE_ERROR); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Integration/_files/customer_with_integration_token.php b/dev/tests/integration/testsuite/Magento/Integration/_files/customer_with_integration_token.php new file mode 100644 index 0000000000000..68b9a72759d3f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Integration/_files/customer_with_integration_token.php @@ -0,0 +1,15 @@ +get(CustomerTokenServiceInterface::class); + +$customerTokenService->createCustomerAccessToken($customer->getEmail(), $customer->getPassword()); diff --git a/dev/tests/integration/testsuite/Magento/Integration/_files/customer_with_integration_token_rollback.php b/dev/tests/integration/testsuite/Magento/Integration/_files/customer_with_integration_token_rollback.php new file mode 100644 index 0000000000000..768b6f25cb747 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Integration/_files/customer_with_integration_token_rollback.php @@ -0,0 +1,8 @@ + Date: Wed, 25 Mar 2020 10:31:59 +0200 Subject: [PATCH 3/6] MC-32700: Storefront: Order view in customer profile --- .../Block/Order/Creditmemo/ItemsTest.php | 243 +++++++++++++++--- .../Block/Order/Creditmemo/TotalsTest.php | 97 +++++++ .../Magento/Sales/Block/Order/HistoryTest.php | 177 +++++++++++++ .../Sales/Block/Order/Info/ButtonsTest.php | 115 +++++++++ .../Magento/Sales/Block/Order/InfoTest.php | 172 +++++++++++++ .../Sales/Block/Order/Invoice/ItemsTest.php | 239 ++++++++++++++--- .../Sales/Block/Order/Invoice/TotalsTest.php | 97 +++++++ .../Item/Renderer/DefaultRendererTest.php | 111 ++++++++ .../Magento/Sales/Block/Order/ItemsTest.php | 221 +++++++++++----- .../Magento/Sales/Block/Order/TotalsTest.php | 129 ++++++++-- .../_files/customer_order_with_two_items.php | 96 +++++++ ...customer_order_with_two_items_rollback.php | 29 +++ .../Sales/_files/invoices_for_items.php | 23 ++ .../_files/invoices_for_items_rollback.php | 8 + .../Sales/_files/refunds_for_items.php | 23 ++ .../_files/refunds_for_items_rollback.php | 8 + 16 files changed, 1631 insertions(+), 157 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Block/Order/Creditmemo/TotalsTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Block/Order/HistoryTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Block/Order/Info/ButtonsTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Block/Order/InfoTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Block/Order/Invoice/TotalsTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Block/Order/Item/Renderer/DefaultRendererTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/customer_order_with_two_items.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/customer_order_with_two_items_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/invoices_for_items.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/invoices_for_items_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/refunds_for_items.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/refunds_for_items_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Creditmemo/ItemsTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Creditmemo/ItemsTest.php index f130c788a65db..318a07127767d 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Creditmemo/ItemsTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Creditmemo/ItemsTest.php @@ -3,74 +3,249 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Sales\Block\Order\Creditmemo; -class ItemsTest extends \PHPUnit\Framework\TestCase +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Framework\View\Element\Text; +use Magento\Framework\View\LayoutInterface; +use Magento\Framework\View\Result\PageFactory; +use Magento\Sales\Api\Data\CreditmemoInterface; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\Data\OrderInterfaceFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Tests for view creditmemo items block. + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ItemsTest extends TestCase { - /** - * @var \Magento\Framework\View\LayoutInterface - */ - protected $_layout; + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var LayoutInterface */ + private $layout; + + /** @var Items */ + private $block; + + /** @var CreditmemoInterface */ + private $creditmemo; + + /** @var Registry */ + private $registry; + + /** @var OrderInterfaceFactory */ + private $orderFactory; + + /** @var PageFactory */ + private $pageFactory; /** - * @var \Magento\Sales\Block\Order\Creditmemo\Items + * @inheritdoc */ - protected $_block; + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->block = $this->layout->createBlock(Items::class, 'block'); + $this->creditmemo = $this->objectManager->get(CreditmemoInterface::class); + $this->registry = $this->objectManager->get(Registry::class); + $this->orderFactory = $this->objectManager->get(OrderInterfaceFactory::class); + $this->pageFactory = $this->objectManager->get(PageFactory::class); + } /** - * @var \Magento\Sales\Model\Order\Creditmemo + * @inheritdoc */ - protected $_creditmemo; - - protected function setUp() + protected function tearDown() { - $this->_layout = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Framework\View\LayoutInterface::class - ); - $this->_block = $this->_layout->createBlock(\Magento\Sales\Block\Order\Creditmemo\Items::class, 'block'); - $this->_creditmemo = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Sales\Model\Order\Creditmemo::class - ); + $this->registry->unregister('current_order'); + + parent::tearDown(); } /** * @magentoAppIsolation enabled + * + * @return void */ - public function testGetTotalsHtml() + public function testGetTotalsHtml(): void { - $childBlock = $this->_layout->addBlock( - \Magento\Framework\View\Element\Text::class, + $childBlock = $this->layout->addBlock( + Text::class, 'creditmemo_totals', 'block' ); - $expectedHtml = 'Any html'; $this->assertEmpty($childBlock->getCreditmemo()); - $this->assertNotEquals($expectedHtml, $this->_block->getTotalsHtml($this->_creditmemo)); - + $this->assertNotEquals($expectedHtml, $this->block->getTotalsHtml($this->creditmemo)); $childBlock->setText($expectedHtml); - $actualHtml = $this->_block->getTotalsHtml($this->_creditmemo); - $this->assertSame($this->_creditmemo, $childBlock->getCreditmemo()); + $actualHtml = $this->block->getTotalsHtml($this->creditmemo); + $this->assertSame($this->creditmemo, $childBlock->getCreditmemo()); $this->assertEquals($expectedHtml, $actualHtml); } - public function testGetCommentsHtml() + /** + * @magentoAppIsolation enabled + * + * @return void + */ + public function testGetCommentsHtml(): void { - $childBlock = $this->_layout->addBlock( - \Magento\Framework\View\Element\Text::class, + $childBlock = $this->layout->addBlock( + Text::class, 'creditmemo_comments', 'block' ); - $expectedHtml = 'Any html'; $this->assertEmpty($childBlock->getEntity()); $this->assertEmpty($childBlock->getTitle()); - $this->assertNotEquals($expectedHtml, $this->_block->getCommentsHtml($this->_creditmemo)); - + $this->assertNotEquals($expectedHtml, $this->block->getCommentsHtml($this->creditmemo)); $childBlock->setText($expectedHtml); - $actualHtml = $this->_block->getCommentsHtml($this->_creditmemo); - $this->assertSame($this->_creditmemo, $childBlock->getEntity()); + $actualHtml = $this->block->getCommentsHtml($this->creditmemo); + $this->assertSame($this->creditmemo, $childBlock->getEntity()); $this->assertNotEmpty($childBlock->getTitle()); $this->assertEquals($expectedHtml, $actualHtml); } + + /** + * @magentoDataFixture Magento/Sales/_files/refunds_for_items.php + * + * @return void + */ + public function testDisplayingCreditmemos(): void + { + $order = $this->orderFactory->create()->loadByIncrementId('100000555'); + $this->registerOrder($order); + $blockHtml = $this->renderCreditmemoItemsBlock(); + $this->assertCreditmemosBlock($order, $blockHtml); + } + + /** + * Assert creditmemos block. + * + * @param OrderInterface $order + * @param string $blockHtml + * @return void + */ + private function assertCreditmemosBlock(OrderInterface $order, string $blockHtml): void + { + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//a[contains(@href, 'sales/order/printCreditmemo/order_id/%s')]/span[contains(text(), '%s')]", + $order->getId(), + __('Print All Refunds') + ), + $blockHtml + ), + sprintf('%s button was not found.', __('Print All Refunds')) + ); + $this->assertNotCount(0, $order->getCreditmemosCollection(), 'Creditmemos collection is empty'); + foreach ($order->getCreditmemosCollection() as $creditmemo) { + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//div[contains(@class, 'order-title')]/strong[contains(text(), '%s')]", + __('Refund #') . $creditmemo->getIncrementId() + ), + $blockHtml + ), + sprintf('Title for %s was not found.', __('Refund #') . $creditmemo->getIncrementId()) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//a[contains(@href, 'sales/order/printCreditmemo/creditmemo_id/%s')]" + . "/span[contains(text(), '%s')]", + $creditmemo->getId(), + __('Print Refund') + ), + $blockHtml + ), + sprintf('%s button for #%s was not found.', __('Print Refund'), $creditmemo->getIncrementId()) + ); + $this->assertCreditmemoItems($creditmemo, $blockHtml); + } + } + + /** + * Assert creditmemo items list. + * + * @param CreditmemoInterface $creditmemo + * @param string $html + * @return void + */ + private function assertCreditmemoItems(CreditmemoInterface $creditmemo, string $html): void + { + $this->assertNotCount(0, $creditmemo->getItemsCollection(), 'Creditmemo items collection is empty'); + $fieldsToCheck = [ + 'name' => "/td[contains(@class, 'name')]/strong[contains(text(), '%s')]", + 'sku' => "/td[contains(@class, 'sku') and contains(text(), '%s')]", + 'price' => "/td[contains(@class, 'price')]//span[contains(text(), '%01.2f')]", + 'qty' => "/td[contains(@class, 'qty') and contains(text(), '%d')]", + 'row_total' => "/td[contains(@class, 'subtotal')]//span[contains(text(), '%01.2f')]", + 'discount_amount' => "/td[contains(@class, 'discount')]/span[contains(text(), '%01.2f')]", + ]; + foreach ($creditmemo->getItemsCollection() as $item) { + $rowXpath = sprintf( + "//table[@id='my-refund-table-%s']//tr[@id='order-item-row-%s']", + $creditmemo->getId(), + $item->getId() + ); + foreach ($fieldsToCheck as $key => $xpath) { + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($rowXpath . $xpath, $item->getData($key)), $html), + sprintf('Item %s wasn\'t found or not equals to %s.', $key, $item->getData($key)) + ); + } + } + } + + /** + * Render creditmemo items block. + * + * @return string + */ + private function renderCreditmemoItemsBlock(): string + { + $page = $this->pageFactory->create(); + $page->addHandle([ + 'default', + 'sales_order_creditmemo', + ]); + $page->getLayout()->generateXml(); + $creditmemoItemsBlock = $page->getLayout()->getBlock('creditmemo_items')->unsetChild('creditmemo_totals'); + $creditmemoItemsBlock->getRequest()->setRouteName('sales')->setControllerName('order') + ->setActionName('creditmemo'); + + return $creditmemoItemsBlock->toHtml(); + } + + /** + * Register order in registry. + * + * @param OrderInterface $order + * @return void + */ + private function registerOrder(OrderInterface $order): void + { + $this->registry->unregister('current_order'); + $this->registry->register('current_order', $order); + } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Creditmemo/TotalsTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Creditmemo/TotalsTest.php new file mode 100644 index 0000000000000..a88b2d3a5f0df --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Creditmemo/TotalsTest.php @@ -0,0 +1,97 @@ +objectManager = Bootstrap::getObjectManager(); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Totals::class) + ->setTemplate('Magento_Sales::order/totals.phtml'); + $this->orderFactory = $this->objectManager->get(OrderInterfaceFactory::class); + } + + /** + * @magentoDataFixture Magento/Sales/_files/refunds_for_items.php + * + * @return void + */ + public function testCreditmemoTotalsBlock(): void + { + $order = $this->orderFactory->create()->loadByIncrementId('100000555'); + $creditmemo = $order->getCreditmemosCollection()->getFirstItem(); + $this->assertNotNull($creditmemo->getId()); + $blockHtml = $this->block->setOrder($order)->setCreditmemo($creditmemo)->toHtml(); + $message = '"%s" for creditmemo wasn\'t found or not equals to %01.2f'; + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//th[contains(text(), '%s')]/following-sibling::td/span[contains(text(), '%01.2f')]", + __('Subtotal'), + $creditmemo->getSubtotal() + ), + $blockHtml + ), + sprintf($message, __('Subtotal'), $creditmemo->getSubtotal()) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//th[contains(text(), '%s')]/following-sibling::td/span[contains(text(), '%01.2f')]", + __('Shipping & Handling'), + $creditmemo->getShippingAmount() + ), + $blockHtml + ), + sprintf($message, __('Shipping & Handling'), $creditmemo->getShippingAmount()) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//tr[contains(@class, 'grand_total') and contains(.//strong, '%s')]" + . "//span[contains(text(), '%01.2f')]", + __('Grand Total'), + $creditmemo->getGrandTotal() + ), + $blockHtml + ), + sprintf($message, __('Grand Total'), $creditmemo->getGrandTotal()) + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/HistoryTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/HistoryTest.php new file mode 100644 index 0000000000000..d7e342c096dc9 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/HistoryTest.php @@ -0,0 +1,177 @@ +objectManager = Bootstrap::getObjectManager(); + $this->customerSession = $this->objectManager->get(Session::class); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(History::class); + $this->orderFactory = $this->objectManager->get(OrderInterfaceFactory::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->customerSession->logout(); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testCustomerOrderGridWithoutOrders(): void + { + $this->customerSession->loginById(1); + $this->assertContains((string)$this->block->getEmptyOrdersMessage(), strip_tags($this->block->toHtml())); + } + + /** + * @magentoDataFixture Magento/Sales/_files/order_with_customer.php + * + * @return void + */ + public function testCustomerOrderGridWithOrder(): void + { + $this->customerSession->loginById(1); + $this->assertCustomerOrderGrid(['100000001'], $this->block->toHtml()); + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Sales/_files/orders_with_customer.php + * + * @return void + */ + public function testCustomerOrderGridWithSomeOrders(): void + { + $this->customerSession->loginById(1); + $ordersToCheck = ['100000002', '100000003', '100000004', '100000005', '100000006']; + $this->assertCustomerOrderGrid($ordersToCheck, $this->block->toHtml()); + } + + /** + * Assert customer order grid. + * + * @param array $ordersToCheck + * @param string $blockHtml + * @return void + */ + private function assertCustomerOrderGrid(array $ordersToCheck, string $blockHtml): void + { + foreach ($ordersToCheck as $orderIncrementId) { + $order = $this->orderFactory->create()->loadByIncrementId($orderIncrementId); + $rowXpath = sprintf("//td[contains(@class,'id') and contains(text(), '%s')]", $order->getRealOrderId()); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + $rowXpath . "/following-sibling::td[contains(@class, 'date') and contains(text(), '%s')]", + $this->block->formatDate($order->getCreatedAt()) + ), + $blockHtml + ), + sprintf('Created date for order #%s wasn\'t found in row.', $orderIncrementId) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + $rowXpath . "/following-sibling::td[contains(@class, 'total')]/span[contains(text(), '%s')]", + $order->getTotal() + ), + $blockHtml + ), + sprintf( + 'Order Totals for order #%s wasn\'t found or not equal to "%s" in row.', + $orderIncrementId, + $order->getTotal() + ) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + $rowXpath . "/following-sibling::td[contains(@class, 'status') and contains(text(), '%s')]", + $order->getStatusLabel() + ), + $blockHtml + ), + sprintf( + 'Order status for order #%s wasn\'t found or not equal to "%s" in row.', + $orderIncrementId, + $order->getStatusLabel() + ) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + $rowXpath . "/following-sibling::td/a[contains(@href, 'sales/order/view/order_id/%s')]" + . "/span[contains(text(), '%s')]", + $order->getId(), + __('View Order') + ), + $blockHtml + ), + sprintf('View order button for order #%s wasn\'t found.', $orderIncrementId) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + $rowXpath . "/following-sibling::td/a[contains(@data-post," + . "'sales\/order\/reorder\/order_id\/%s')]/span[contains(text(), '%s')]", + $order->getId(), + __('Reorder') + ), + $blockHtml + ), + sprintf('Reorder button for order #%s wasn\'t found.', $orderIncrementId) + ); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Info/ButtonsTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Info/ButtonsTest.php new file mode 100644 index 0000000000000..676415629fdc9 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Info/ButtonsTest.php @@ -0,0 +1,115 @@ +objectManager = Bootstrap::getObjectManager(); + $this->registry = $this->objectManager->get(Registry::class); + $this->customerSession = $this->objectManager->get(Session::class); + $this->order = $this->objectManager->get(OrderInterface::class); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Buttons::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister('current_order'); + $this->customerSession->logout(); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Sales/_files/order_with_customer.php + * + * @return void + */ + public function testDisplayingOrderActionButtons(): void + { + $this->customerSession->loginById(1); + $order = $this->order->loadByIncrementId('100000001'); + $this->registerOrder($order); + $blockHtml = $this->block->toHtml(); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//a[contains(@data-post, 'sales\/order\/reorder\/order_id\/%s')]/span[contains(text(), '%s')]", + $order->getId(), + __('Reorder') + ), + $blockHtml + ), + sprintf('%s button wasn\'t found.', __('Reorder')) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//a[contains(@href, 'sales/order/print/order_id/%s')]/span[contains(text(), '%s')]", + $order->getId(), + __('Print Order') + ), + $blockHtml + ), + sprintf('%s button wasn\'t found.', __('Print Order')) + ); + } + + /** + * Register order in registry. + * + * @param OrderInterface $order + * @return void + */ + private function registerOrder(OrderInterface $order): void + { + $this->registry->unregister('current_order'); + $this->registry->register('current_order', $order); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/InfoTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/InfoTest.php new file mode 100644 index 0000000000000..1b84db76869e3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/InfoTest.php @@ -0,0 +1,172 @@ +objectManager = Bootstrap::getObjectManager(); + $this->registry = $this->objectManager->get(Registry::class); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->orderFactory = $this->objectManager->get(OrderInterfaceFactory::class); + $this->countryFactory = $this->objectManager->get(CountryFactory::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister('current_order'); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Sales/_files/order_with_customer.php + * + * @return void + */ + public function testOrderStatus(): void + { + $order = $this->orderFactory->create()->loadByIncrementId('100000001'); + $this->registerOrder($order); + $block = $this->layout->createBlock(Info::class)->setTemplate('Magento_Sales::order/order_status.phtml'); + $this->assertContains((string)__($order->getStatusLabel()), strip_tags($block->toHtml())); + } + + /** + * @magentoDataFixture Magento/Sales/_files/order_with_customer.php + * + * @return void + */ + public function testOrderDate(): void + { + $order = $this->orderFactory->create()->loadByIncrementId('100000001'); + $this->registerOrder($order); + $block = $this->layout->createBlock(Info::class)->setTemplate('Magento_Sales::order/order_date.phtml'); + $this->assertContains( + (string)__('Order Date: %1', $block->formatDate($order->getCreatedAt(), \IntlDateFormatter::LONG)), + strip_tags($block->toHtml()) + ); + } + + /** + * @magentoDataFixture Magento/Sales/_files/customer_order_with_two_items.php + * + * @return void + */ + public function testOrderInformation(): void + { + $order = $this->orderFactory->create()->loadByIncrementId('100000555'); + $this->registerOrder($order); + $blockHtml = $this->layout->createBlock(Info::class)->toHtml(); + $this->assertOrderAddress($order->getShippingAddress(), $blockHtml); + $this->assertOrderAddress($order->getBillingAddress(), $blockHtml); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//div[contains(@class, 'box-order-shipping-method') and contains(.//span, '%s')]" + . "//div[contains(text(), '%s')]", + __('Shipping Method'), + $order->getShippingDescription() + ), + $blockHtml + ), + 'Shipping method for order wasn\'t found.' + ); + } + + /** + * Assert order address. + * + * @param OrderAddressInterface $address + * @param string $html + * @return void + */ + private function assertOrderAddress(OrderAddressInterface $address, string $html): void + { + $addressBoxXpath = sprintf("//div[contains(@class, 'box-order-%s-address')]", $address->getAddressType()) + . "//address[contains(., '%s')]"; + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($addressBoxXpath, $address->getName()), $html), + sprintf('Customer name for %s address wasn\'t found.', $address->getAddressType()) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + $addressBoxXpath, + $this->countryFactory->create()->loadByCode($address->getData('country_id'))->getName() + ), + $html + ), + sprintf('Country for %s address wasn\'t found.', $address->getAddressType()) + ); + $attributes = ['company', 'street', 'city', 'region', 'postcode', 'telephone']; + foreach ($attributes as $key) { + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($addressBoxXpath, $address->getData($key)), $html), + sprintf('%s for %s address wasn\'t found.', $key, $address->getAddressType()) + ); + } + } + + /** + * Register order in registry. + * + * @param OrderInterface $order + * @return void + */ + private function registerOrder(OrderInterface $order): void + { + $this->registry->unregister('current_order'); + $this->registry->register('current_order', $order); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Invoice/ItemsTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Invoice/ItemsTest.php index cfb97ee4298ec..bf13d5a296eee 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Invoice/ItemsTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Invoice/ItemsTest.php @@ -3,70 +3,243 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Sales\Block\Order\Invoice; -class ItemsTest extends \PHPUnit\Framework\TestCase +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Framework\View\Element\Text; +use Magento\Framework\View\LayoutInterface; +use Magento\Framework\View\Result\PageFactory; +use Magento\Sales\Api\Data\InvoiceInterface; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\Data\OrderInterfaceFactory; +use Magento\Sales\Api\Data\InvoiceInterfaceFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Tests for view invoice items block. + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ItemsTest extends TestCase { - /** - * @var \Magento\Framework\View\LayoutInterface - */ - protected $_layout; + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Registry */ + private $registry; + + /** @var LayoutInterface */ + private $layout; + + /** @var Items */ + private $block; + + /** @var InvoiceInterfaceFactory */ + private $invoiceFactory; + + /** @var OrderInterfaceFactory */ + private $orderFactory; + + /** @var PageFactory */ + private $pageFactory; /** - * @var \Magento\Sales\Block\Order\Invoice\Items + * @inheritdoc */ - protected $_block; + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->registry = $this->objectManager->get(Registry::class); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->block = $this->layout->createBlock(Items::class, 'block'); + $this->invoiceFactory = $this->objectManager->get(InvoiceInterfaceFactory::class); + $this->orderFactory = $this->objectManager->get(OrderInterfaceFactory::class); + $this->pageFactory = $this->objectManager->get(PageFactory::class); + } /** - * @var \Magento\Sales\Model\Order\Invoice + * @inheritdoc */ - protected $_invoice; - - protected function setUp() + protected function tearDown() { - $this->_layout = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Framework\View\LayoutInterface::class - ); - $this->_block = $this->_layout->createBlock(\Magento\Sales\Block\Order\Invoice\Items::class, 'block'); - $this->_invoice = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Sales\Model\Order\Invoice::class - ); + $this->registry->unregister('current_order'); + + parent::tearDown(); } /** * @magentoAppIsolation enabled + * + * @return void */ - public function testGetInvoiceTotalsHtml() + public function testGetInvoiceTotalsHtml(): void { - $childBlock = $this->_layout->addBlock(\Magento\Framework\View\Element\Text::class, 'invoice_totals', 'block'); - + $childBlock = $this->layout->addBlock(Text::class, 'invoice_totals', 'block'); $expectedHtml = 'Any html'; $this->assertEmpty($childBlock->getInvoice()); - $this->assertNotEquals($expectedHtml, $this->_block->getInvoiceTotalsHtml($this->_invoice)); - + $invoice = $this->invoiceFactory->create(); + $this->assertNotEquals($expectedHtml, $this->block->getInvoiceTotalsHtml($invoice)); $childBlock->setText($expectedHtml); - $actualHtml = $this->_block->getInvoiceTotalsHtml($this->_invoice); - $this->assertSame($this->_invoice, $childBlock->getInvoice()); + $actualHtml = $this->block->getInvoiceTotalsHtml($invoice); + $this->assertSame($invoice, $childBlock->getInvoice()); $this->assertEquals($expectedHtml, $actualHtml); } - public function testGetInvoiceCommentsHtml() + /** + * @magentoAppIsolation enabled + * + * @return void + */ + public function testGetInvoiceCommentsHtml(): void { - $childBlock = $this->_layout->addBlock( - \Magento\Framework\View\Element\Text::class, + $childBlock = $this->layout->addBlock( + Text::class, 'invoice_comments', 'block' ); - $expectedHtml = 'Any html'; $this->assertEmpty($childBlock->getEntity()); $this->assertEmpty($childBlock->getTitle()); - $this->assertNotEquals($expectedHtml, $this->_block->getInvoiceCommentsHtml($this->_invoice)); - + $invoice = $this->invoiceFactory->create(); + $this->assertNotEquals($expectedHtml, $this->block->getInvoiceCommentsHtml($invoice)); $childBlock->setText($expectedHtml); - $actualHtml = $this->_block->getInvoiceCommentsHtml($this->_invoice); - $this->assertSame($this->_invoice, $childBlock->getEntity()); + $actualHtml = $this->block->getInvoiceCommentsHtml($invoice); + $this->assertSame($invoice, $childBlock->getEntity()); $this->assertNotEmpty($childBlock->getTitle()); $this->assertEquals($expectedHtml, $actualHtml); } + + /** + * @magentoDataFixture Magento/Sales/_files/invoices_for_items.php + * + * @return void + */ + public function testDisplayingInvoices(): void + { + $order = $this->orderFactory->create()->loadByIncrementId('100000555'); + $this->registerOrder($order); + $blockHtml = $this->renderInvoiceItemsBlock(); + $this->assertInvoicesBlock($order, $blockHtml); + } + + /** + * Assert invoices block. + * + * @param OrderInterface $order + * @param string $blockHtml + * @return void + */ + private function assertInvoicesBlock(OrderInterface $order, string $blockHtml): void + { + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//a[contains(@href, 'sales/order/printInvoice/order_id/%s')]/span[contains(text(), '%s')]", + $order->getId(), + __('Print All Invoices') + ), + $blockHtml + ), + sprintf('%s button was not found.', __('Print All Invoices')) + ); + $this->assertNotCount(0, $order->getInvoiceCollection(), 'Invoice collection is empty'); + foreach ($order->getInvoiceCollection() as $invoice) { + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//div[contains(@class, 'order-title')]/strong[contains(text(), '%s')]", + __('Invoice #') . $invoice->getIncrementId() + ), + $blockHtml + ), + sprintf('Title for %s was not found.', __('Invoice #') . $invoice->getIncrementId()) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//a[contains(@href, 'sales/order/printInvoice/invoice_id/%s')]/span[contains(text(), '%s')]", + $invoice->getId(), + __('Print Invoice') + ), + $blockHtml + ), + sprintf('%s button for #%s was not found.', __('Print Invoice'), $invoice->getIncrementId()) + ); + $this->assertInvoiceItems($invoice, $blockHtml); + } + } + + /** + * Assert invoice items list. + * + * @param InvoiceInterface $invoice + * @param string $blockHtml + * @return void + */ + private function assertInvoiceItems(InvoiceInterface $invoice, string $blockHtml): void + { + $this->assertNotCount(0, $invoice->getItemsCollection(), 'Invoice items collection is empty'); + $fieldsToCheck = [ + 'name' => "/td[contains(@class, 'name')]/strong[contains(text(), '%s')]", + 'sku' => "/td[contains(@class, 'sku') and contains(text(), '%s')]", + 'price' => "/td[contains(@class, 'price')]//span[contains(text(), '%01.2f')]", + 'qty' => "/td[contains(@class, 'qty')]/span[contains(text(), '%d')]", + 'row_total' => "/td[contains(@class, 'subtotal')]//span[contains(text(), '%01.2f')]", + ]; + foreach ($invoice->getItemsCollection() as $item) { + $itemRowXpath = sprintf( + "//table[@id='my-invoice-table-%s']//tr[@id='order-item-row-%s']", + $invoice->getId(), + $item->getId() + ); + foreach ($fieldsToCheck as $key => $xpath) { + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($itemRowXpath . $xpath, $item->getData($key)), $blockHtml), + sprintf('Item %s wasn\'t found or not equals to %s.', $key, $item->getData($key)) + ); + } + } + } + + /** + * Render invoice items block. + * + * @return string + */ + private function renderInvoiceItemsBlock(): string + { + $page = $this->pageFactory->create(); + $page->addHandle([ + 'default', + 'sales_order_invoice', + ]); + $page->getLayout()->generateXml(); + $invoiceItemsBlock = $page->getLayout()->getBlock('invoice_items')->unsetChild('invoice_totals'); + $invoiceItemsBlock->getRequest()->setRouteName('sales')->setControllerName('order')->setActionName('invoice'); + + return $invoiceItemsBlock->toHtml(); + } + + /** + * Register order in registry. + * + * @param OrderInterface $order + * @return void + */ + private function registerOrder(OrderInterface $order): void + { + $this->registry->unregister('current_order'); + $this->registry->register('current_order', $order); + } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Invoice/TotalsTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Invoice/TotalsTest.php new file mode 100644 index 0000000000000..1fe7e02833a2f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Invoice/TotalsTest.php @@ -0,0 +1,97 @@ +objectManager = Bootstrap::getObjectManager(); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Totals::class) + ->setTemplate('Magento_Sales::order/totals.phtml'); + $this->orderFactory = $this->objectManager->get(OrderInterfaceFactory::class); + } + + /** + * @magentoDataFixture Magento/Sales/_files/invoices_for_items.php + * + * @return void + */ + public function testInvoiceTotalsBlock(): void + { + $order = $this->orderFactory->create()->loadByIncrementId('100000555'); + $invoice = $order->getInvoiceCollection()->getFirstItem(); + $this->assertNotNull($invoice->getId()); + $blockHtml = $this->block->setOrder($order)->setInvoice($invoice)->toHtml(); + $message = '"%s" for invoice wasn\'t found or not equals to %01.2f'; + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//th[contains(text(), '%s')]/following-sibling::td/span[contains(text(), '%01.2f')]", + __('Subtotal'), + $invoice->getSubtotal() + ), + $blockHtml + ), + sprintf($message, __('Subtotal'), $invoice->getSubtotal()) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//th[contains(text(), '%s')]/following-sibling::td/span[contains(text(), '%01.2f')]", + __('Shipping & Handling'), + $invoice->getShippingAmount() + ), + $blockHtml + ), + sprintf($message, __('Shipping & Handling'), $invoice->getShippingAmount()) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//tr[contains(@class, 'grand_total') and contains(.//strong, '%s')]" + . "//span[contains(text(), '%01.2f')]", + __('Grand Total'), + $invoice->getGrandTotal() + ), + $blockHtml + ), + sprintf($message, __('Grand Total'), $invoice->getGrandTotal()) + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Item/Renderer/DefaultRendererTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Item/Renderer/DefaultRendererTest.php new file mode 100644 index 0000000000000..147efc2cd6c78 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/Item/Renderer/DefaultRendererTest.php @@ -0,0 +1,111 @@ +objectManager = Bootstrap::getObjectManager(); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(DefaultRenderer::class); + $this->orderFactory = $this->objectManager->get(OrderInterfaceFactory::class); + } + + /** + * @magentoDataFixture Magento/Sales/_files/shipment_for_order_with_customer.php + * + * @return void + */ + public function testDisplayingShipmentItem(): void + { + $order = $this->orderFactory->create()->loadByIncrementId('100000001'); + $shipment = $order->getShipmentsCollection()->getFirstItem(); + $this->assertNotNull($shipment->getId()); + $item = $shipment->getAllItems()[0] ?? null; + $this->assertNotNull($item); + $blockHtml = $this->block->setTemplate('Magento_Sales::order/shipment/items/renderer/default.phtml') + ->setItem($item)->toHtml(); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//td[contains(@class, 'name')]/strong[contains(text(), '%s')]", + $item->getName() + ), + $blockHtml + ), + sprintf('Item with name %s wasn\'t found.', $item->getName()) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//td[contains(@class, 'sku') and contains(text(), '%s')]", + $item->getSku() + ), + $blockHtml + ), + sprintf('Item with sku %s wasn\'t found.', $item->getSku()) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//td[contains(@class, 'qty') and contains(text(), '%d')]", + $item->getQty() + ), + $blockHtml + ), + sprintf( + 'Qty for item %s wasn\'t found or not equals to %s.', + $item->getName(), + $item->getQty() + ) + ); + } + + /** + * @magentoDataFixture Magento/Sales/_files/refunds_for_items.php + * + * @return void + */ + public function testCreditmemoItemTotalAmount(): void + { + $order = $this->orderFactory->create()->loadByIncrementId('100000555'); + $creditmemo = $order->getCreditmemosCollection()->getFirstItem(); + $this->assertNotNull($creditmemo->getId()); + $item = $creditmemo->getItemsCollection()->getFirstItem(); + $this->assertNotNull($item->getId()); + $this->assertEquals(10.00, $this->block->getTotalAmount($item)); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/ItemsTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/ItemsTest.php index 4c7b202fc1351..cb211b343cf0d 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/ItemsTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/ItemsTest.php @@ -3,133 +3,228 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Sales\Block\Order; -class ItemsTest extends \PHPUnit\Framework\TestCase +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Framework\View\LayoutInterface; +use Magento\Framework\View\Result\PageFactory; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\Data\OrderInterfaceFactory; +use Magento\Sales\Model\ResourceModel\Order\Item\Collection; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use Magento\Theme\Block\Html\Pager; +use PHPUnit\Framework\TestCase; + +/** + * Tests order items block. + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ItemsTest extends TestCase { - /** - * @var \Magento\Sales\Block\Order\Items - */ - private $model; + /** @var Items */ + private $block; - /** - * @var \Magento\Framework\View\LayoutInterface - */ + /** @var LayoutInterface */ private $layout; - /** - * @var \Magento\Framework\ObjectManagerInterface - */ + /** @var ObjectManagerInterface */ private $objectManager; - /** - * @var \Magento\Framework\Registry - */ + /** @var Registry */ private $registry; + /** @var OrderInterfaceFactory */ + private $orderFactory; + + /** @var PageFactory */ + private $pageFactory; + + /** + * @inheritdoc + */ protected function setUp() { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->layout = $this->objectManager->get(\Magento\Framework\View\LayoutInterface::class); - $this->registry = $this->objectManager->get(\Magento\Framework\Registry::class); + $this->objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->registry = $this->objectManager->get(Registry::class); + $this->orderFactory = $this->objectManager->get(OrderInterfaceFactory::class); + $this->pageFactory = $this->objectManager->get(PageFactory::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister('current_order'); + + parent::tearDown(); } /** * @magentoDataFixture Magento/Sales/_files/order.php + * + * @return void */ - public function testGetOrderItems() + public function testGetOrderItems(): void { - $this->registerOrder(); - $this->model = $this->layout->createBlock(\Magento\Sales\Block\Order\Items::class); - $this->assertTrue(count($this->model->getItems()) > 0); + $order = $this->orderFactory->create()->loadByIncrementId('100000001'); + $this->registerOrder($order); + $this->block = $this->layout->createBlock(Items::class); + $this->assertCount(1, $this->block->getItems()); } /** - * @magentoAppIsolation enabled * @magentoConfigFixture default/sales/orders/items_per_page 3 * @magentoDataFixture Magento/Sales/_files/order_item_list.php + * + * @return void */ - public function testPagerIsDisplayed() + public function testPagerIsDisplayed(): void { - $this->registerOrder(); - - /** @var \Magento\Sales\Block\Order\Items model */ - $this->model = $this->layout->createBlock(\Magento\Sales\Block\Order\Items::class, 'items_block'); + $order = $this->orderFactory->create()->loadByIncrementId('100000001'); + $this->registerOrder($order); + $this->block = $this->layout->createBlock(Items::class, 'items_block'); $this->layout->addBlock( - $this->objectManager->get(\Magento\Theme\Block\Html\Pager::class), + $this->objectManager->get(Pager::class), 'sales_order_item_pager', 'items_block' ); - $this->model->setLayout($this->layout); - - $this->assertTrue($this->model->isPagerDisplayed()); + $this->block->setLayout($this->layout); + $this->assertTrue($this->block->isPagerDisplayed()); } /** * @magentoDataFixture Magento/Sales/_files/order_item_list.php + * + * @return void */ - public function testPagerIsNotDisplayed() + public function testPagerIsNotDisplayed(): void { - $this->registerOrder(); - - /** @var \Magento\Sales\Block\Order\Items model */ - $this->model = $this->layout->createBlock(\Magento\Sales\Block\Order\Items::class, 'items_block'); + $order = $this->orderFactory->create()->loadByIncrementId('100000001'); + $this->registerOrder($order); + $this->block = $this->layout->createBlock(Items::class, 'items_block'); $this->layout->addBlock( - $this->objectManager->get(\Magento\Theme\Block\Html\Pager::class), + $this->objectManager->get(Pager::class), 'sales_order_item_pager', 'items_block' ); - $this->model->setLayout($this->layout); - - $this->assertFalse($this->model->isPagerDisplayed()); + $this->block->setLayout($this->layout); + $this->assertFalse($this->block->isPagerDisplayed()); + $this->assertEmpty(preg_replace('/\s+/', '', strip_tags($this->block->getPagerHtml()))); } /** - * @magentoAppIsolation enabled - * @magentoAppArea frontend * @magentoConfigFixture default/sales/orders/items_per_page 3 * @magentoDataFixture Magento/Sales/_files/order_item_list.php + * + * @return void */ - public function testGetPagerHtml() + public function testGetPagerHtml(): void { - $this->registerOrder(); - - /** @var \Magento\Sales\Block\Order\Items model */ - $this->model = $this->layout->createBlock(\Magento\Sales\Block\Order\Items::class, 'items_block'); + $order = $this->orderFactory->create()->loadByIncrementId('100000001'); + $this->registerOrder($order); + $this->block = $this->layout->createBlock(Items::class, 'items_block'); $this->layout->addBlock( - $this->objectManager->get(\Magento\Theme\Block\Html\Pager::class), + $this->objectManager->get(Pager::class), 'sales_order_item_pager', 'items_block' ); - $this->model->setLayout($this->layout); - - $this->assertNotEmpty($this->model->getPagerHtml()); + $this->block->setLayout($this->layout); + $this->assertNotEmpty(preg_replace('/\s+/', '', strip_tags($this->block->getPagerHtml()))); + $this->assertTrue($this->block->isPagerDisplayed()); } /** * @magentoDataFixture Magento/Sales/_files/order.php + * + * @return void + */ + public function testGetOrder(): void + { + $order = $this->orderFactory->create()->loadByIncrementId('100000001'); + $this->registerOrder($order); + $this->block = $this->layout->createBlock(Items::class, 'items_block'); + $this->assertEquals($order, $this->block->getOrder()); + } + + /** + * @magentoDataFixture Magento/Sales/_files/customer_order_with_two_items.php + * + * @return void + */ + public function testDisplayingOrderItems(): void + { + $order = $this->orderFactory->create()->loadByIncrementId('100000555'); + $this->registerOrder($order); + $blockHtml = $this->renderOrderItemsBlock(); + $this->assertOrderItems($order->getItemsCollection(), $blockHtml); + } + + /** + * Render order items block. + * + * @return string */ - public function testGetOrder() + private function renderOrderItemsBlock(): string { - $order = $this->registerOrder(); + $page = $this->pageFactory->create(); + $page->addHandle([ + 'default', + 'sales_order_view', + ]); + $page->getLayout()->generateXml(); + $orderItemsBlock = $page->getLayout()->getBlock('order_items')->unsetChild('order_totals'); + + return $orderItemsBlock->toHtml(); + } - /** @var \Magento\Sales\Block\Order\Items model */ - $this->model = $this->layout->createBlock(\Magento\Sales\Block\Order\Items::class, 'items_block'); - $this->assertEquals($order, $this->model->getOrder()); + /** + * Assert order items list. + * + * @param Collection $orderItems + * @param string $blockHtml + * @return void + */ + private function assertOrderItems(Collection $orderItems, string $blockHtml): void + { + $this->assertNotCount(0, $orderItems, 'Order items collection is empty'); + $fieldsToCheck = [ + 'name' => "/td[contains(@class, 'name')]/strong[contains(text(), '%s')]", + 'sku' => "/td[contains(@class, 'sku') and contains(text(), '%s')]", + 'price' => "/td[contains(@class, 'price')]//span[contains(text(), '%01.2f')]", + 'qty_ordered' => "/td[contains(@class, 'qty')]//span[contains(text(), '" . __('Ordered') + . "')]/following-sibling::span[contains(text(), '%d')]", + 'row_total' => "/td[contains(@class, 'subtotal')]//span[contains(text(), '%01.2f')]", + ]; + foreach ($orderItems as $item) { + $itemRowXpath = sprintf("//tr[@id='order-item-row-%s']", $item->getItemId()); + foreach ($fieldsToCheck as $key => $xpath) { + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($itemRowXpath . $xpath, $item->getData($key)), $blockHtml), + sprintf('Item %s wasn\'t found or not equals to %s.', $key, $item->getData($key)) + ); + } + } } /** - * Register order in registry + * Register order in registry. * - * @return \Magento\Sales\Model\Order + * @param OrderInterface $order + * @return void */ - private function registerOrder() + private function registerOrder(OrderInterface $order): void { - /** @var \Magento\Sales\Model\Order $order */ - $order = $this->objectManager->get(\Magento\Sales\Model\Order::class); - $order->loadByIncrementId('100000001'); + $this->registry->unregister('current_order'); $this->registry->register('current_order', $order); - return $order; } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/TotalsTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/TotalsTest.php index b23e7bcc140d4..7361ddc985b21 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/TotalsTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/TotalsTest.php @@ -3,54 +3,129 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Sales\Block\Order; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\Element\Context; +use Magento\Framework\View\Element\Text; +use Magento\Framework\View\Layout; +use Magento\Framework\View\LayoutInterface; +use Magento\Sales\Api\Data\OrderInterfaceFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + /** + * Tests for order totals block. + * * @magentoAppArea frontend + * @magentoDbIsolation enabled */ -class TotalsTest extends \PHPUnit\Framework\TestCase +class TotalsTest extends TestCase { - public function testToHtmlChildrenInitialized() + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Layout */ + private $layout; + + /** @var Totals */ + private $block; + + /** @var OrderInterfaceFactory */ + private $orderFactory; + + /** + * @inheritdoc + */ + protected function setUp() { - \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\App\State::class) - ->setAreaCode('frontend'); + parent::setUp(); - /** @var $layout \Magento\Framework\View\Layout */ - $layout = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Framework\View\LayoutInterface::class - ); - /** @var \Magento\Sales\Block\Order\Totals $block */ - $block = $layout->createBlock(\Magento\Sales\Block\Order\Totals::class, 'block'); - $block->setOrder( - \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Sales\Model\Order::class) - )->setTemplate( - 'order/totals.phtml' - ); + $this->objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->block = $this->layout->createBlock(Totals::class, 'block'); + $this->orderFactory = $this->objectManager->get(OrderInterfaceFactory::class); + } - $context = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Framework\View\Element\Context::class - ); - $childOne = $this->getMockBuilder(\Magento\Framework\View\Element\Text::class) + /** + * @magentoAppIsolation enabled + * + * @return void + */ + public function testToHtmlChildrenInitialized(): void + { + $this->block->setOrder($this->orderFactory->create())->setTemplate('order/totals.phtml'); + $context = $this->objectManager->get(Context::class); + $childOne = $this->getMockBuilder(Text::class) ->setMethods(['initTotals']) ->setConstructorArgs([$context]) ->getMock(); $childOne->expects($this->once())->method('initTotals'); - $layout->addBlock($childOne, 'child1', 'block'); - - $childTwo = $this->getMockBuilder(\Magento\Framework\View\Element\Text::class) + $this->layout->addBlock($childOne, 'child1', 'block'); + $childTwo = $this->getMockBuilder(Text::class) ->setMethods(['initTotals']) ->setConstructorArgs([$context]) ->getMock(); $childTwo->expects($this->once())->method('initTotals'); - $layout->addBlock($childTwo, 'child2', 'block'); - - $childThree = $this->getMockBuilder(\Magento\Framework\View\Element\Text::class) + $this->layout->addBlock($childTwo, 'child2', 'block'); + $childThree = $this->getMockBuilder(Text::class) ->setMethods(['initTotals']) ->setConstructorArgs([$context]) ->getMock(); $childThree->expects($this->once())->method('initTotals'); - $layout->addBlock($childThree, 'child3', 'block'); + $this->layout->addBlock($childThree, 'child3', 'block'); + $this->block->toHtml(); + } - $block->toHtml(); + /** + * @magentoDataFixture Magento/Sales/_files/customer_order_with_two_items.php + * + * @return void + */ + public function testOrderTotalsBlock(): void + { + $order = $this->orderFactory->create()->loadByIncrementId('100000555'); + $blockHtml = $this->block->setTemplate('Magento_Sales::order/totals.phtml')->setOrder($order)->toHtml(); + $message = '"%s" for order wasn\'t found or not equals to %01.2f'; + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//th[contains(text(), '%s')]/following-sibling::td/span[contains(text(), '%01.2f')]", + __('Subtotal'), + $order->getSubtotal() + ), + $blockHtml + ), + sprintf($message, __('Subtotal'), $order->getSubtotal()) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//th[contains(text(), '%s')]/following-sibling::td/span[contains(text(), '%01.2f')]", + __('Shipping & Handling'), + $order->getShippingAmount() + ), + $blockHtml + ), + sprintf($message, __('Shipping & Handling'), $order->getShippingAmount()) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//tr[contains(@class, 'grand_total') and contains(.//strong, '%s')]" + . "//span[contains(text(), '%01.2f')]", + __('Grand Total'), + $order->getGrandTotal() + ), + $blockHtml + ), + sprintf($message, __('Grand Total'), $order->getGrandTotal()) + ); } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/customer_order_with_two_items.php b/dev/tests/integration/testsuite/Magento/Sales/_files/customer_order_with_two_items.php new file mode 100644 index 0000000000000..5270b291a56d4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/customer_order_with_two_items.php @@ -0,0 +1,96 @@ +get(OrderInterfaceFactory::class); +/** @var OrderItemInterfaceFactory $orderItemFactory */ +$orderItemFactory = $objectManager->get(OrderItemInterfaceFactory::class); +/** @var OrderRepositoryInterface $orderRepository */ +$orderRepository = $objectManager->get(OrderRepositoryInterface::class); +/** @var OrderAddressInterfaceFactory $orderAddressFactory */ +$orderAddressFactory = $objectManager->get(OrderAddressInterfaceFactory::class); +/** @var OrderPaymentInterfaceFactory $orderPaymentFactory */ +$orderPaymentFactory = $objectManager->get(OrderPaymentInterfaceFactory::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); + +$billingAddress = $orderAddressFactory->create(['data' => $customerAddress->getData()]); +$billingAddress->setAddressType(Address::TYPE_BILLING); + +$shippingAddress = $orderAddressFactory->create(['data' => $customerAddress->getData()]); +$shippingAddress->setAddressType(Address::TYPE_SHIPPING) + ->setStreet('street for shipping') + ->setRegion('North West') + ->setPostcode('GU16 7HF') + ->setShippingMethod('flatrate_flatrate'); + +$orderPayment = $orderPaymentFactory->create(); +$orderPayment->setMethod('checkmo') + ->setAdditionalInformation('last_trans_id', '11122') + ->setAdditionalInformation( + 'metadata', + ['type' => 'free', 'fraudulent' => false] + ); + +$firstProduct = $productRepository->get('simple-1'); +$firstOrderItem = $orderItemFactory->create(); +$firstOrderItem->setProductId($firstProduct->getId()) + ->setQtyOrdered(1) + ->setBasePrice($firstProduct->getPrice()) + ->setPrice($firstProduct->getPrice()) + ->setRowTotal($firstProduct->getPrice()) + ->setProductType(Type::TYPE_SIMPLE) + ->setName($firstProduct->getName()) + ->setSku($firstProduct->getSku()); + +$secondProduct = $productRepository->get('simple'); +$secondOrderItem = $orderItemFactory->create(); +$secondOrderItem->setProductId($secondProduct->getId()) + ->setQtyOrdered(1) + ->setBasePrice($secondProduct->getPrice()) + ->setPrice($secondProduct->getPrice()) + ->setRowTotal($secondProduct->getPrice()) + ->setProductType(Type::TYPE_SIMPLE) + ->setName($secondProduct->getName()) + ->setSku($secondProduct->getSku()); + +$order = $orderFactory->create(); +$order->setIncrementId('100000555') + ->setState(Order::STATE_PROCESSING) + ->setStatus(Order::STATE_PROCESSING) + ->setSubtotal(20) + ->setShippingAmount(10) + ->setGrandTotal(30) + ->setBaseSubtotal(20) + ->setBaseShippingAmount(10) + ->setBaseGrandTotal(30) + ->setCustomerIsGuest(false) + ->setCustomerEmail($customerDataModel->getEmail()) + ->setCustomerId($customerDataModel->getId()) + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setShippingDescription('Flat Rate - Fixed') + ->setStoreId($mainWebsite->getDefaultStore()->getId()) + ->addItem($firstOrderItem) + ->addItem($secondOrderItem) + ->setPayment($orderPayment); +$orderRepository->save($order); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/customer_order_with_two_items_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/customer_order_with_two_items_rollback.php new file mode 100644 index 0000000000000..a6225b247466e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/customer_order_with_two_items_rollback.php @@ -0,0 +1,29 @@ +get(OrderRepositoryInterface::class); +/** @var OrderInterfaceFactory $orderFactory */ +$orderFactory = $objectManager->create(OrderInterfaceFactory::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +$order = $orderFactory->create()->loadByIncrementId('100000555'); +if ($order->getId()) { + $orderRepository->delete($order); +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/invoices_for_items.php b/dev/tests/integration/testsuite/Magento/Sales/_files/invoices_for_items.php new file mode 100644 index 0000000000000..dbec254b69482 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/invoices_for_items.php @@ -0,0 +1,23 @@ +get(InvoiceItemCreationInterfaceFactory::class); +/** @var InvoiceOrderInterface $invoiceOrder */ +$invoiceOrder = $objectManager->get(InvoiceOrderInterface::class); + +foreach ($order->getItems() as $orderItem) { + $invoiceItem = $invoiceItemFactory->create(); + $invoiceItem->setOrderItemId($orderItem->getItemId()); + $invoiceItem->setQty($orderItem->getQtyOrdered()); + $invoiceOrder->execute($order->getId(), false, [$invoiceItem]); +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/invoices_for_items_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/invoices_for_items_rollback.php new file mode 100644 index 0000000000000..91200f3c1b46c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/invoices_for_items_rollback.php @@ -0,0 +1,8 @@ +get(CreditmemoItemCreationInterfaceFactory::class); +/** @var RefundOrderInterface $refundOrder */ +$refundOrder = $objectManager->get(RefundOrderInterface::class); + +foreach ($order->getItems() as $item) { + $creditmemoItem = $creditmemoItemFactory->create(); + $creditmemoItem->setOrderItemId($item->getId()); + $creditmemoItem->setQty($item->getQtyOrdered()); + $refundOrder->execute($order->getId(), [$creditmemoItem]); +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/refunds_for_items_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/refunds_for_items_rollback.php new file mode 100644 index 0000000000000..67a4321c182ec --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/refunds_for_items_rollback.php @@ -0,0 +1,8 @@ + Date: Thu, 9 Apr 2020 16:25:28 +0300 Subject: [PATCH 4/6] MC-32704: Storefront: My Downloadable Products tab on customer profile page --- .../RemoveLinkPurchasedByOrderIncrementId.php | 48 +++++ .../Downloadable/Block/Account/LinkTest.php | 67 +++++++ .../Customer/Products/ListProductsTest.php | 181 ++++++++++++++++++ ...with_customer_and_downloadable_product.php | 78 ++++++++ ...omer_and_downloadable_product_rollback.php | 33 ++++ 5 files changed, 407 insertions(+) create mode 100644 dev/tests/integration/framework/Magento/TestFramework/Downloadable/Model/RemoveLinkPurchasedByOrderIncrementId.php create mode 100644 dev/tests/integration/testsuite/Magento/Downloadable/Block/Account/LinkTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Downloadable/Block/Customer/Products/ListProductsTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Downloadable/_files/order_with_customer_and_downloadable_product.php create mode 100644 dev/tests/integration/testsuite/Magento/Downloadable/_files/order_with_customer_and_downloadable_product_rollback.php diff --git a/dev/tests/integration/framework/Magento/TestFramework/Downloadable/Model/RemoveLinkPurchasedByOrderIncrementId.php b/dev/tests/integration/framework/Magento/TestFramework/Downloadable/Model/RemoveLinkPurchasedByOrderIncrementId.php new file mode 100644 index 0000000000000..7f27ab0932b42 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Downloadable/Model/RemoveLinkPurchasedByOrderIncrementId.php @@ -0,0 +1,48 @@ +linkCollectionFactory = $linkCollectionFactory; + $this->purchasedResource = $purchasedResource; + } + + /** + * Remove records from downloadable_link_purchased related to provided order + * + * @param string $orderIncrementId + * @return void + */ + public function execute(string $orderIncrementId): void + { + $collection = $this->linkCollectionFactory->create(); + $collection->addFieldToFilter('order_increment_id', $orderIncrementId); + foreach ($collection as $item) { + $this->purchasedResource->delete($item); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/Block/Account/LinkTest.php b/dev/tests/integration/testsuite/Magento/Downloadable/Block/Account/LinkTest.php new file mode 100644 index 0000000000000..8916fc4853b05 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Downloadable/Block/Account/LinkTest.php @@ -0,0 +1,67 @@ +objectManager = Bootstrap::getObjectManager(); + $this->page = $this->objectManager->get(PageFactory::class)->create(); + } + + /** + * @return void + */ + public function testMyDownloadableProductLink(): void + { + $this->preparePage(); + $block = $this->page->getLayout()->getBlock('customer-account-navigation-downloadable-products-link'); + $this->assertNotFalse($block); + $html = $block->toHtml(); + $this->assertContains('downloadable/customer/products', $html); + $this->assertEquals('My Downloadable Products', strip_tags($html)); + } + + /** + * Prepare page before render + * + * @return void + */ + private function preparePage(): void + { + $this->page->addHandle([ + 'default', + 'customer_account', + ]); + $this->page->getLayout()->generateXml(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/Block/Customer/Products/ListProductsTest.php b/dev/tests/integration/testsuite/Magento/Downloadable/Block/Customer/Products/ListProductsTest.php new file mode 100644 index 0000000000000..b1f68043198ca --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Downloadable/Block/Customer/Products/ListProductsTest.php @@ -0,0 +1,181 @@ +objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->customerSession = $this->objectManager->get(Session::class); + $this->orderRepository = $this->objectManager->get(OrderRepositoryInterface::class); + $this->invoiceOrder = $this->objectManager->get(InvoiceOrderInterface::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->customerSession->logout(); + + parent::tearDown(); + } + + /** + * @return void + */ + public function testNoItems(): void + { + $html = $this->createBlock()->toHtml(); + $this->assertContains((string)__('You have not purchased any downloadable products yet.'), strip_tags($html)); + } + + /** + * @magentoDataFixture Magento/Downloadable/_files/order_with_customer_and_downloadable_product.php + * + * @return void + */ + public function testPendingOrder(): void + { + $this->customerSession->loginById(1); + $this->assertEquals( + 0, + Xpath::getElementsCountForXpath( + sprintf($this->downloadLinkXpath, 'Downloadable Product Link'), + $this->createBlock()->toHtml() + ), + 'The download link displayed' + ); + } + + /** + * @magentoDataFixture Magento/Downloadable/_files/order_with_customer_and_downloadable_product.php + * + * @return void + */ + public function testCompleteOrder(): void + { + $order = $this->getOrder('100000001'); + $this->invoiceOrder->execute($order->getId()); + $this->customerSession->loginById(1); + $html = $this->createBlock()->toHtml(); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($this->downloadLinkXpath, 'Downloadable Product Link'), $html), + 'The download link is not found' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($this->statusXpath, (string)__('Available')), $html), + 'Wrong status displayed' + ); + } + + /** + * @magentoDataFixture Magento/Downloadable/_files/order_with_customer_and_downloadable_product.php + * + * @return void + */ + public function testClosedOrder(): void + { + $order = $this->getOrder('100000001'); + $this->invoiceOrder->execute($order->getId()); + $this->objectManager->removeSharedInstance(OrderRepository::class); + $refundOrder = $this->objectManager->create(RefundOrderInterface::class); + $refundOrder->execute($order->getId()); + $this->customerSession->loginById(1); + $html = $this->createBlock()->toHtml(); + $this->assertEquals( + 0, + Xpath::getElementsCountForXpath(sprintf($this->downloadLinkXpath, 'Downloadable Product Link'), $html), + 'The download link is displayed for closed order' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($this->statusXpath, (string)__('Expired')), $html), + 'Wrong status displayed' + ); + } + + /** + * Load order by increment id + * + * @param $orderIncrementId + * @return OrderInterface + */ + private function getOrder($orderIncrementId): OrderInterface + { + $order = $this->objectManager->get(OrderFactory::class)->create(); + + return $order->loadByIncrementId($orderIncrementId); + } + + /** + * Create ProductsList block + * + * @return ListProducts + */ + private function createBlock(): ListProducts + { + $block = $this->objectManager->create(ListProducts::class); + $block->setTemplate('Magento_Downloadable::customer/products/list.phtml'); + $this->layout->addBlock($block, 'downloadable_customer_products_list'); + + return $block; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/_files/order_with_customer_and_downloadable_product.php b/dev/tests/integration/testsuite/Magento/Downloadable/_files/order_with_customer_and_downloadable_product.php new file mode 100644 index 0000000000000..be5fa49f48eeb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Downloadable/_files/order_with_customer_and_downloadable_product.php @@ -0,0 +1,78 @@ +get(AddressFactory::class); +$billingAddress = $addressFactory->create(['data' => $addressData]); +$billingAddress->setAddressType(Address::TYPE_BILLING); +/** @var ItemFactory $orderItemFactory */ +$orderItemFactory = $objectManager->get(ItemFactory::class); +/** @var PaymentFactory $orderPaymentFactory */ +$orderPaymentFactory = $objectManager->get(PaymentFactory::class); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +/** @var OrderRepositoryInterface $orderRepository */ +$orderRepository = $objectManager->create(OrderRepositoryInterface::class); +/** @var OrderFactory $orderFactory */ +$orderFactory = $objectManager->get(OrderFactory::class); + +$payment = $orderPaymentFactory->create(); +$payment->setMethod('checkmo') + ->setAdditionalInformation('last_trans_id', '11122') + ->setAdditionalInformation( + 'metadata', + ['type' => 'free', 'fraudulent' => false] + ); +/** @var ProductInterface $product */ +$product = $productRepository->get('downloadable-product'); +/** @var LinkInterface $links */ +$links = $product->getExtensionAttributes()->getDownloadableProductLinks(); +$link = reset($links); + +$orderItem = $orderItemFactory->create(); +$orderItem->setProductId($product->getId()) + ->setQtyOrdered(1) + ->setBasePrice($product->getPrice()) + ->setProductOptions(['links' => [$link->getId()]]) + ->setPrice($product->getPrice()) + ->setRowTotal($product->getPrice()) + ->setProductType(Type::TYPE_DOWNLOADABLE) + ->setName($product->getName()) + ->setSku($product->getSku()); + +$order = $orderFactory->create(); +$order->setIncrementId('100000001') + ->setState(Order::STATE_PROCESSING) + ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_PROCESSING)) + ->setSubtotal(100) + ->setGrandTotal(100) + ->setBaseSubtotal(100) + ->setBaseGrandTotal(100) + ->setCustomerId($customer->getId()) + ->setCustomerEmail($customer->getEmail()) + ->setBillingAddress($billingAddress) + ->setStoreId($storeManager->getStore()->getId()) + ->addItem($orderItem) + ->setPayment($payment); + +$orderRepository->save($order); diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/_files/order_with_customer_and_downloadable_product_rollback.php b/dev/tests/integration/testsuite/Magento/Downloadable/_files/order_with_customer_and_downloadable_product_rollback.php new file mode 100644 index 0000000000000..c182a67495f89 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Downloadable/_files/order_with_customer_and_downloadable_product_rollback.php @@ -0,0 +1,33 @@ +unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var RemoveLinkPurchasedByOrderIncrementId $removeLinkPurchasedByOrderIncrementId */ +$removeLinkPurchasedByOrderIncrementId = $objectManager->get(RemoveLinkPurchasedByOrderIncrementId::class); +/** @var OrderRepositoryInterface $orderRepository */ +$orderRepository = $objectManager->get(OrderRepositoryInterface::class); +$orderIncrementIdToDelete = '100000001'; +$removeLinkPurchasedByOrderIncrementId->execute($orderIncrementIdToDelete); +/** @var OrderFactory $order */ +$order = $objectManager->get(OrderFactory::class)->create(); +$order->loadByIncrementId($orderIncrementIdToDelete); + +if ($order->getId()) { + $orderRepository->delete($order); +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); From 9a7be2d539e04069b43f97d8df3eb32040b36532 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha Date: Thu, 9 Apr 2020 16:41:02 +0300 Subject: [PATCH 5/6] MC-32711: Admin: View customer product review --- .../Block/Adminhtml/Edit/Tab/ReviewsTest.php | 50 +++++++++++++++++++ .../Adminhtml/Customer/ProductReviewsTest.php | 50 +++++++++++++++++-- 2 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Review/Block/Adminhtml/Edit/Tab/ReviewsTest.php diff --git a/dev/tests/integration/testsuite/Magento/Review/Block/Adminhtml/Edit/Tab/ReviewsTest.php b/dev/tests/integration/testsuite/Magento/Review/Block/Adminhtml/Edit/Tab/ReviewsTest.php new file mode 100644 index 0000000000000..0b9fbe9428b5a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Review/Block/Adminhtml/Edit/Tab/ReviewsTest.php @@ -0,0 +1,50 @@ +objectManager = Bootstrap::getObjectManager(); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Reviews::class); + } + + /** + * @magentoDataFixture Magento/Review/_files/customer_review.php + * + * @return void + */ + public function testReviewGrid(): void + { + $this->block->setCustomerId(1); + $this->assertCount(1, $this->block->getPreparedCollection()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Review/Controller/Adminhtml/Customer/ProductReviewsTest.php b/dev/tests/integration/testsuite/Magento/Review/Controller/Adminhtml/Customer/ProductReviewsTest.php index 4203fb9c16b29..961e029dfc38b 100644 --- a/dev/tests/integration/testsuite/Magento/Review/Controller/Adminhtml/Customer/ProductReviewsTest.php +++ b/dev/tests/integration/testsuite/Magento/Review/Controller/Adminhtml/Customer/ProductReviewsTest.php @@ -8,13 +8,30 @@ namespace Magento\Review\Controller\Adminhtml\Customer; use Magento\Framework\App\Request\Http; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\View\LayoutInterface; use Magento\TestFramework\TestCase\AbstractBackendController; /** * Test for customer product reviews page. + * + * @magentoAppArea adminhtml */ class ProductReviewsTest extends AbstractBackendController { + /** @var LayoutInterface */ + private $layout; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->layout = $this->_objectManager->get(LayoutInterface::class); + } + /** * Check Customer product review action. * @@ -23,9 +40,36 @@ class ProductReviewsTest extends AbstractBackendController */ public function testProductReviewsAction(): void { - $this->getRequest()->setPostValue(['id' => 1])->setMethod(Http::METHOD_POST); + $this->dispatchWithIdParam(1); + $this->assertContains('
getResponse()->getBody()); + } + + /** + * @return void + */ + public function testProductReviews(): void + { + $customerId = 1; + $this->dispatchWithIdParam($customerId); + $block = $this->layout->getBlock('admin.customer.reviews'); + $this->assertNotFalse($block); + $this->assertEquals( + $customerId, + $block->getCustomerId(), + 'Block customer id value does not match expected value' + ); + } + + /** + * Dispatch request with id parameter + * + * @param int $id + * @return void + */ + private function dispatchWithIdParam(int $id): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setParams(['id' => $id]); $this->dispatch('backend/review/customer/productReviews'); - $body = $this->getResponse()->getBody(); - $this->assertContains('
Date: Tue, 14 Apr 2020 17:41:29 +0300 Subject: [PATCH 6/6] MC-32691: Fix integration test Magento\CatalogImportExport\Model\ProductStagingTest::testImportExport --- .../Model/Export/ProductTest.php | 98 +++++++++++++------ .../_files/product_export_data.php | 2 - 2 files changed, 68 insertions(+), 32 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php index 508560d000271..1daa794165873 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php @@ -84,8 +84,10 @@ protected function setUp() /** * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data.php * @magentoDbIsolation enabled + * + * @return void */ - public function testExport() + public function testExport(): void { $this->model->setWriter( $this->objectManager->create( @@ -109,8 +111,10 @@ public function testExport() /** * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data_special_chars.php * @magentoDbIsolation enabled + * + * @return void */ - public function testExportSpecialChars() + public function testExportSpecialChars(): void { $this->model->setWriter( $this->objectManager->create( @@ -125,8 +129,10 @@ public function testExportSpecialChars() /** * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_with_product_links_data.php * @magentoDbIsolation enabled + * + * @return void */ - public function testExportWithProductLinks() + public function testExportWithProductLinks(): void { $this->model->setWriter( \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( @@ -143,8 +149,10 @@ public function testExportWithProductLinks() * @magentoDbIsolation enabled * @covers \Magento\CatalogImportExport\Model\Export\Product::export * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data.php + * + * @return void */ - public function testExportStockItemAttributesAreFilled() + public function testExportStockItemAttributesAreFilled(): void { $this->markTestSkipped('Test needs to be skipped.'); $fileWrite = $this->createMock(\Magento\Framework\Filesystem\File\Write::class); @@ -176,8 +184,9 @@ public function testExportStockItemAttributesAreFilled() * Verify header columns (that stock item attributes column headers are present) * * @param array $headerColumns + * @return void */ - public function verifyHeaderColumns(array $headerColumns) + public function verifyHeaderColumns(array $headerColumns): void { foreach (self::$stockItemAttributes as $stockItemAttribute) { $this->assertContains( @@ -192,8 +201,9 @@ public function verifyHeaderColumns(array $headerColumns) * Verify row data (stock item attribute values) * * @param array $rowData + * @return void */ - public function verifyRow(array $rowData) + public function verifyRow(array $rowData): void { foreach (self::$stockItemAttributes as $stockItemAttribute) { $this->assertNotSame( @@ -208,8 +218,10 @@ public function verifyRow(array $rowData) * Verifies if exception processing works properly * @magentoDbIsolation enabled * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data.php + * + * @return void */ - public function testExceptionInGetExportData() + public function testExceptionInGetExportData(): void { $this->markTestSkipped('Test needs to be skipped.'); $exception = new \Exception('Error'); @@ -258,8 +270,10 @@ public function testExceptionInGetExportData() * Verify if fields wrapping works correct when "Fields Enclosure" option enabled * * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data.php + * + * @return void */ - public function testExportWithFieldsEnclosure() + public function testExportWithFieldsEnclosure(): void { $this->model->setParameters( [ @@ -284,8 +298,10 @@ public function testExportWithFieldsEnclosure() * Verify that "category ids" filter correctly applies to export result * * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_with_categories.php + * + * @return void */ - public function testCategoryIdsFilter() + public function testCategoryIdsFilter(): void { $this->model->setWriter( $this->objectManager->create( @@ -313,8 +329,10 @@ public function testCategoryIdsFilter() * Verify that export processed successfully with wrong category path * * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_with_broken_categories_path.php + * + * @return void */ - public function testExportWithWrongCategoryPath() + public function testExportWithWrongCategoryPath(): void { $this->model->setWriter( $this->objectManager->create( @@ -329,8 +347,10 @@ public function testExportWithWrongCategoryPath() * Test 'hide from product page' export for non-default store. * * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_with_images.php + * + * @return void */ - public function testExportWithMedia() + public function testExportWithMedia(): void { /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ $productRepository = $this->objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); @@ -359,6 +379,7 @@ public function testExportWithMedia() /** * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data.php + * * @return void */ public function testExportWithCustomOptions(): void @@ -403,12 +424,19 @@ public function testExportWithCustomOptions(): void /** @var \Magento\Framework\File\Csv $csv */ $csv = $this->objectManager->get(\Magento\Framework\File\Csv::class); $data = $csv->getData($varDirectory->getAbsolutePath('test_product_with_custom_options_and_second_store.csv')); + $keys = array_shift($data); + $products = []; + foreach ($data as $productData) { + $products[] = array_combine($keys, $productData); + } + $products = array_filter($products, function (array $product) { + return $product['sku'] === 'simple'; + }); $customOptionData = []; - foreach ($data[0] as $columnNumber => $columnName) { - if ($columnName === 'custom_options') { - $customOptionData['admin_store'] = $this->parseExportedCustomOption($data[1][$columnNumber]); - $customOptionData[$storeCode] = $this->parseExportedCustomOption($data[2][$columnNumber]); - } + + foreach ($products as $product) { + $storeCode = $product['store_view_code'] ?: 'admin_store'; + $customOptionData[$storeCode] = $this->parseExportedCustomOption($product['custom_options']); } self::assertSame($expectedData, $customOptionData); @@ -418,8 +446,10 @@ public function testExportWithCustomOptions(): void * Check that no duplicate entities when multiple custom options used * * @magentoDataFixture Magento/Catalog/_files/product_simple_with_options.php + * + * @return void */ - public function testExportWithMultipleOptions() + public function testExportWithMultipleOptions(): void { $expectedCount = 1; $resultsFilename = 'export_results.csv'; @@ -442,6 +472,8 @@ public function testExportWithMultipleOptions() } /** + * Parse exported custom options + * * @param string $exportedCustomOption * @return array */ @@ -476,8 +508,10 @@ function ($input) { * @magentoConfigFixture current_store catalog/price/scope 1 * @magentoDbIsolation disabled * @magentoAppArea adminhtml + * + * @return void */ - public function testExportProductWithTwoWebsites() + public function testExportProductWithTwoWebsites(): void { $globalStoreCode = 'admin'; $secondStoreCode = 'fixture_second_store'; @@ -539,17 +573,19 @@ public function testExportProductWithTwoWebsites() /** * Verify that "stock status" filter correctly applies to export result * + * @magentoDataFixture Magento/Catalog/_files/multiple_products_with_few_out_of_stock.php + * @dataProvider filterByQuantityAndStockStatusDataProvider + * * @param string $value * @param array $productsIncluded * @param array $productsNotIncluded - * @magentoDataFixture Magento/Catalog/_files/multiple_products_with_few_out_of_stock.php - * @dataProvider filterByQuantityAndStockStatusDataProvider + * @return void */ public function testFilterByQuantityAndStockStatus( string $value, array $productsIncluded, array $productsNotIncluded - ) { + ): void { $exportData = $this->doExport(['quantity_and_stock_status' => $value]); foreach ($productsIncluded as $productName) { $this->assertContains($productName, $exportData); @@ -569,35 +605,37 @@ public function filterByQuantityAndStockStatusDataProvider(): array [ 'Simple Product OOS', 'Simple Product Not Visible', - 'Simple Product Visible and InStock' + 'Simple Product Visible and InStock', ], [ - ] + ], ], [ '1', [ 'Simple Product Not Visible', - 'Simple Product Visible and InStock' + 'Simple Product Visible and InStock', ], [ - 'Simple Product OOS' - ] + 'Simple Product OOS', + ], ], [ '0', [ - 'Simple Product OOS' + 'Simple Product OOS', ], [ 'Simple Product Not Visible', - 'Simple Product Visible and InStock' - ] - ] + 'Simple Product Visible and InStock', + ], + ], ]; } /** + * Perform export + * * @param array $filters * @return string */ diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php index 477494626b9fb..865cba4998e30 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php @@ -59,8 +59,6 @@ $productModel->setTypeId( \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE -)->setId( - 1 )->setAttributeSetId( 4 )->setName(