![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/dev/tests/api-functional/testsuite/Magento/Customer/Api/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Customer\Api; use Magento\Customer\Api\Data\AddressInterface as Address; use Magento\Customer\Api\Data\CustomerInterfaceFactory; use Magento\Customer\Model\CustomerRegistry; use Magento\Framework\Api\DataObjectHelper; use Magento\Customer\Api\Data\CustomerInterface as Customer; use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\Search\FilterGroupBuilder; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Api\SortOrder; use Magento\Framework\Api\SortOrderBuilder; use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Reflection\DataObjectProcessor; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Webapi\Exception as HTTPExceptionCodes; use Magento\Framework\Webapi\Rest\Request; use Magento\Integration\Api\CustomerTokenServiceInterface; use Magento\Integration\Api\IntegrationServiceInterface; use Magento\Integration\Api\OauthServiceInterface; use Magento\Integration\Model\Integration; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\Helper\Customer as CustomerHelper; use Magento\TestFramework\TestCase\WebapiAbstract; /** * Test for \Magento\Customer\Api\CustomerRepositoryInterface. * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CustomerRepositoryTest extends WebapiAbstract { public const SERVICE_VERSION = 'V1'; public const SERVICE_NAME = 'customerCustomerRepositoryV1'; public const RESOURCE_PATH = '/V1/customers'; private const STUB_INVALID_CUSTOMER_GROUP_ID = 777; private const STUB_RETAILER_GROUP_ID = 3; /** * @var CustomerRepositoryInterface */ private $customerRepository; /** * @var DataObjectHelper */ private $dataObjectHelper; /** * @var CustomerInterfaceFactory */ private $customerDataFactory; /** * @var \Magento\Framework\Api\SearchCriteriaBuilder */ private $searchCriteriaBuilder; /** * @var \Magento\Framework\Api\SortOrderBuilder */ private $sortOrderBuilder; /** * @var \Magento\Framework\Api\Search\FilterGroupBuilder */ private $filterGroupBuilder; /** * @var CustomerRegistry */ private $customerRegistry; /** * @var CustomerHelper */ private $customerHelper; /** * @var array */ private $currentCustomerId; /** * @var \Magento\Framework\Reflection\DataObjectProcessor */ private $dataObjectProcessor; /** * Execute per test initialization. */ protected function setUp(): void { $this->customerRegistry = Bootstrap::getObjectManager()->get(CustomerRegistry::class); $this->customerRepository = Bootstrap::getObjectManager()->get( CustomerRepositoryInterface::class, ['customerRegistry' => $this->customerRegistry] ); $this->dataObjectHelper = Bootstrap::getObjectManager()->create(DataObjectHelper::class); $this->customerDataFactory = Bootstrap::getObjectManager()->create(CustomerInterfaceFactory::class); $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->create(SearchCriteriaBuilder::class); $this->sortOrderBuilder = Bootstrap::getObjectManager()->create(SortOrderBuilder::class); $this->filterGroupBuilder = Bootstrap::getObjectManager()->create(FilterGroupBuilder::class); $this->customerHelper = new CustomerHelper(); $this->dataObjectProcessor = Bootstrap::getObjectManager()->create(DataObjectProcessor::class); } protected function tearDown(): void { if (!empty($this->currentCustomerId)) { foreach ($this->currentCustomerId as $customerId) { $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/' . $customerId, 'httpMethod' => Request::HTTP_METHOD_DELETE, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'DeleteById', ], ]; $response = $this->_webApiCall($serviceInfo, ['customerId' => $customerId]); $this->assertTrue($response); } } $this->customerRepository = null; } /** * Validate update by invalid customer. * */ public function testInvalidCustomerUpdate() { $this->expectException(\Exception::class); //Create first customer and retrieve customer token. $firstCustomerData = $this->_createCustomer(); // get customer ID token /** @var \Magento\Integration\Api\CustomerTokenServiceInterface $customerTokenService */ //$customerTokenService = $this->objectManager->create(CustomerTokenServiceInterface::class); $customerTokenService = Bootstrap::getObjectManager()->create( \Magento\Integration\Api\CustomerTokenServiceInterface::class ); $token = $customerTokenService->createCustomerAccessToken( $firstCustomerData[Customer::EMAIL], 'test@123' ); //Create second customer and update lastname. $customerData = $this->_createCustomer(); $existingCustomerDataObject = $this->getCustomerData($customerData[Customer::ID]); $lastName = $existingCustomerDataObject->getLastname(); $customerData[Customer::LASTNAME] = $lastName . 'Updated'; $newCustomerDataObject = $this->customerDataFactory->create(); $this->dataObjectHelper->populateWithArray( $newCustomerDataObject, $customerData, Customer::class ); $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . "/{$customerData[Customer::ID]}", 'httpMethod' => Request::HTTP_METHOD_PUT, 'token' => $token, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'Save', 'token' => $token ] ]; $newCustomerDataObject = $this->dataObjectProcessor->buildOutputDataArray( $newCustomerDataObject, Customer::class ); $requestData = ['customer' => $newCustomerDataObject]; $this->_webApiCall($serviceInfo, $requestData); } /** * Create Integration and return token. * * @param string $name * @param array $resource * @return string */ private function createIntegrationToken(string $name, array $resource): string { /** @var IntegrationServiceInterface $integrationService */ $integrationService = Bootstrap::getObjectManager()->get(IntegrationServiceInterface::class); $oauthService = Bootstrap::getObjectManager()->get(OauthServiceInterface::class); /** @var Integration $integration */ $integration = $integrationService->create( [ 'name' => $name, 'resource' => $resource, ] ); /** @var OauthServiceInterface $oauthService */ $oauthService->createAccessToken($integration->getConsumerId()); return $integrationService->get($integration->getId())->getToken(); } public function testDeleteCustomer() { $customerData = $this->_createCustomer(); $this->currentCustomerId = []; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/' . $customerData[Customer::ID], 'httpMethod' => Request::HTTP_METHOD_DELETE, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'DeleteById', ], ]; if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) { $response = $this->_webApiCall($serviceInfo, ['customerId' => $customerData['id']]); } else { $response = $this->_webApiCall($serviceInfo); } $this->assertTrue($response); //Verify if the customer is deleted $this->expectException(NoSuchEntityException::class); $this->expectExceptionMessage(sprintf("No such entity with customerId = %s", $customerData[Customer::ID])); $this->getCustomerData($customerData[Customer::ID]); } /** * Check that non authorized consumer can`t delete customer. * * @return void */ public function testDeleteCustomerNonAuthorized(): void { $resource = [ 'Magento_Customer::customer', 'Magento_Customer::manage', ]; $token = $this->createIntegrationToken('TestAPI' . bin2hex(random_bytes(5)), $resource); $customerData = $this->_createCustomer(); $this->currentCustomerId = []; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/' . $customerData[Customer::ID], 'httpMethod' => Request::HTTP_METHOD_DELETE, 'token' => $token, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'DeleteById', 'token' => $token, ], ]; try { $this->_webApiCall($serviceInfo, ['customerId' => $customerData['id']]); $this->fail("Expected exception is not thrown."); } catch (\SoapFault $e) { } catch (\Exception $e) { $expectedMessage = 'The consumer isn\'t authorized to access %resources.'; $errorObj = $this->processRestExceptionResult($e); $this->assertEquals($expectedMessage, $errorObj['message']); $this->assertEquals(['resources' => 'Magento_Customer::delete'], $errorObj['parameters']); $this->assertEquals(HTTPExceptionCodes::HTTP_UNAUTHORIZED, $e->getCode()); } /** @var Customer $data */ $data = $this->getCustomerData($customerData[Customer::ID]); $this->assertNotNull($data->getId()); } /** * Test delete customer with invalid id * * @return void */ public function testDeleteCustomerInvalidCustomerId(): void { $invalidId = -1; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/' . $invalidId, 'httpMethod' => Request::HTTP_METHOD_DELETE, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'DeleteById', ], ]; $expectedMessage = 'No such entity with %fieldName = %fieldValue'; try { $this->_webApiCall($serviceInfo, ['customerId' => $invalidId]); $this->fail("Expected exception"); } catch (\SoapFault $e) { $this->assertStringContainsString( $expectedMessage, $e->getMessage(), "SoapFault does not contain expected message." ); } catch (\Exception $e) { $errorObj = $this->processRestExceptionResult($e); $this->assertEquals($expectedMessage, $errorObj['message']); $this->assertEquals(['fieldName' => 'customerId', 'fieldValue' => $invalidId], $errorObj['parameters']); $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode()); } } /** * Test customer update * * @magentoApiDataFixture Magento/Customer/_files/customer.php * * @return void */ public function testUpdateCustomer(): void { $customerId = 1; $updatedLastname = 'Updated lastname'; $customer = $this->getCustomerData($customerId); $customerData = $this->dataObjectProcessor->buildOutputDataArray($customer, Customer::class); $customerData[Customer::LASTNAME] = $updatedLastname; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/' . $customerId, 'httpMethod' => Request::HTTP_METHOD_PUT, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'Save', ], ]; $requestData['customer'] = TESTS_WEB_API_ADAPTER === self::ADAPTER_SOAP ? $customerData : [Customer::LASTNAME => $updatedLastname]; $response = $this->_webApiCall($serviceInfo, $requestData); $this->assertNotNull($response); //Verify if the customer is updated $existingCustomerDataObject = $this->getCustomerData($customerId); $this->assertEquals($updatedLastname, $existingCustomerDataObject->getLastname()); $this->assertEquals($customerData[Customer::FIRSTNAME], $existingCustomerDataObject->getFirstname()); } /** * Verify expected behavior when the website id is not set */ public function testUpdateCustomerNoWebsiteId() { $customerData = $this->customerHelper->createSampleCustomer(); $existingCustomerDataObject = $this->getCustomerData($customerData[Customer::ID]); $lastName = $existingCustomerDataObject->getLastname(); $customerData[Customer::LASTNAME] = $lastName . 'Updated'; $newCustomerDataObject = $this->customerDataFactory->create(); $this->dataObjectHelper->populateWithArray( $newCustomerDataObject, $customerData, Customer::class ); $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . "/{$customerData[Customer::ID]}", 'httpMethod' => Request::HTTP_METHOD_PUT, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'Save', ], ]; $newCustomerDataObject = $this->dataObjectProcessor->buildOutputDataArray( $newCustomerDataObject, Customer::class ); unset($newCustomerDataObject['website_id']); $requestData = ['customer' => $newCustomerDataObject]; try { $response = $this->_webApiCall($serviceInfo, $requestData); $this->assertEquals($customerData['website_id'], $response['website_id']); } catch (\SoapFault $e) { $this->assertStringContainsString('"Associate to Website" is a required value.', $e->getMessage()); } } /** * Test customer exception update * * @return void */ public function testUpdateCustomerException(): void { $customerData = $this->_createCustomer(); $existingCustomerDataObject = $this->getCustomerData($customerData[Customer::ID]); $lastName = $existingCustomerDataObject->getLastname(); //Set non-existent id = -1 $customerData[Customer::LASTNAME] = $lastName . 'Updated'; $customerData[Customer::ID] = -1; $newCustomerDataObject = $this->customerDataFactory->create(); $this->dataObjectHelper->populateWithArray( $newCustomerDataObject, $customerData, Customer::class ); $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . "/-1", 'httpMethod' => Request::HTTP_METHOD_PUT, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'Save', ], ]; $newCustomerDataObject = $this->dataObjectProcessor->buildOutputDataArray( $newCustomerDataObject, Customer::class ); $requestData = ['customer' => $newCustomerDataObject]; $expectedMessage = 'No such entity with %fieldName = %fieldValue'; try { $this->_webApiCall($serviceInfo, $requestData); $this->fail("Expected exception."); } catch (\SoapFault $e) { $this->assertStringContainsString( $expectedMessage, $e->getMessage(), "SoapFault does not contain expected message." ); } catch (\Exception $e) { $errorObj = $this->processRestExceptionResult($e); $this->assertEquals($expectedMessage, $errorObj['message']); $this->assertEquals(['fieldName' => 'customerId', 'fieldValue' => -1], $errorObj['parameters']); $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode()); } } /** * Test customer update with invalid customer group id * * @magentoApiDataFixture Magento/Customer/_files/customer.php * * @return void */ public function testUpdateCustomerWithInvalidGroupId(): void { $customerId = 1; $customerData = $this->dataObjectProcessor->buildOutputDataArray( $this->getCustomerData($customerId), Customer::class ); $customerData[Customer::GROUP_ID] = self::STUB_INVALID_CUSTOMER_GROUP_ID; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/' . $customerId, 'httpMethod' => Request::HTTP_METHOD_PUT, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'Save', ], ]; $requestData['customer'] = $customerData; $expectedMessage = 'The specified customer group id does not exist.'; try { $this->_webApiCall($serviceInfo, $requestData); $this->fail('Expected exception was not raised'); } catch (\SoapFault $e) { $this->assertStringContainsString($expectedMessage, $e->getMessage()); } catch (\Exception $e) { $errorObj = $this->processRestExceptionResult($e); $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode()); $this->assertEquals($expectedMessage, $errorObj['message']); } } /** * Test customer update quote with valid customer group id change * * @magentoApiDataFixture Magento/Customer/_files/customer.php * * @return void */ public function testUpdateCustomerQuoteOnGroupIdChange(): void { $customerId = 1; $customerData = $this->dataObjectProcessor->buildOutputDataArray( $this->getCustomerData($customerId), Customer::class ); $customerData[Customer::GROUP_ID] = self::STUB_RETAILER_GROUP_ID; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/' . $customerId, 'httpMethod' => Request::HTTP_METHOD_PUT, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'Save', ], ]; $requestData['customer'] = $customerData; $updateResults = $this->_webApiCall($serviceInfo, $requestData); $this->assertEquals($updateResults['group_id'], self::STUB_RETAILER_GROUP_ID); } /** * Test customer create with invalid customer group id * * @return void */ public function testCreateCustomerWithInvalidGroupId(): void { $customerData = $this->dataObjectProcessor->buildOutputDataArray( $this->customerHelper->createSampleCustomerDataObject(), Customer::class ); $customerData[Customer::GROUP_ID] = self::STUB_INVALID_CUSTOMER_GROUP_ID; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH, 'httpMethod' => Request::HTTP_METHOD_POST, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'Save', ], ]; $requestData = ['customer' => $customerData]; $expectedMessage = 'The specified customer group id does not exist.'; try { $this->_webApiCall($serviceInfo, $requestData); $this->fail('Expected exception was not raised'); } catch (\SoapFault $e) { $this->assertStringContainsString($expectedMessage, $e->getMessage()); } catch (\Exception $e) { $errorObj = $this->processRestExceptionResult($e); $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode()); $this->assertEquals($expectedMessage, $errorObj['message']); } } /** * Test creating a customer with absent required address fields * * @return void */ public function testCreateCustomerWithoutAddressRequiresException(): void { $customerDataArray = $this->dataObjectProcessor->buildOutputDataArray( $this->customerHelper->createSampleCustomerDataObject(), Customer::class ); foreach ($customerDataArray[Customer::KEY_ADDRESSES] as & $address) { $address[Address::FIRSTNAME] = null; } $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH, 'httpMethod' => Request::HTTP_METHOD_POST, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'Save', ], ]; $requestData = ['customer' => $customerDataArray]; try { $this->_webApiCall($serviceInfo, $requestData); $this->fail('Expected exception did not occur.'); } catch (\Exception $e) { if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) { $expectedException = new InputException(); $expectedException->addError( __( '"%fieldName" is required. Enter and try again.', ['fieldName' => Address::FIRSTNAME] ) ); $this->assertInstanceOf('SoapFault', $e); $this->checkSoapFault( $e, $expectedException->getRawMessage(), 'env:Sender', $expectedException->getParameters() // expected error parameters ); } else { $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode()); $exceptionData = $this->processRestExceptionResult($e); $expectedExceptionData = [ 'message' => '"%fieldName" is required. Enter and try again.', 'parameters' => ['fieldName' => Address::FIRSTNAME], ]; $this->assertEquals($expectedExceptionData, $exceptionData); } } try { $this->customerRegistry->retrieveByEmail( $customerDataArray[Customer::EMAIL], $customerDataArray[Customer::WEBSITE_ID] ); $this->fail('An expected NoSuchEntityException was not thrown.'); } catch (NoSuchEntityException $e) { $exception = NoSuchEntityException::doubleField( 'email', $customerDataArray[Customer::EMAIL], 'websiteId', $customerDataArray[Customer::WEBSITE_ID] ); $this->assertEquals( $exception->getMessage(), $e->getMessage(), 'Exception message does not match expected message.' ); } } /** * Test with a single filter * * @param bool $subscribeStatus * @return void * * @dataProvider subscriptionDataProvider */ public function testSearchCustomers(bool $subscribeStatus): void { $builder = Bootstrap::getObjectManager()->create(FilterBuilder::class); $subscribeData = $this->buildSubscriptionData($subscribeStatus); $customerData = $this->_createCustomer($subscribeData); $filter = $builder ->setField(Customer::EMAIL) ->setValue($customerData[Customer::EMAIL]) ->create(); $this->searchCriteriaBuilder->addFilters([$filter]); $searchData = $this->dataObjectProcessor->buildOutputDataArray( $this->searchCriteriaBuilder->create(), SearchCriteriaInterface::class ); $requestData = ['searchCriteria' => $searchData]; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData), 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'getList', ], ]; $searchResults = $this->_webApiCall($serviceInfo, $requestData); $this->assertEquals(1, $searchResults['total_count']); $this->assertEquals($customerData[Customer::ID], $searchResults['items'][0][Customer::ID]); $this->assertEquals($subscribeStatus, $searchResults['items'][0]['extension_attributes']['is_subscribed']); } /** * Build subscription extension attributes data * * @param bool $status * @return array */ private function buildSubscriptionData(bool $status): array { return [ 'extension_attributes' => [ 'is_subscribed' => $status, ], ]; } /** * Subscription customer data provider * * @return array */ public function subscriptionDataProvider(): array { return [ 'subscribed user' => [true], 'not subscribed user' => [false], ]; } /** * Test with a single filter using GET */ public function testSearchCustomersUsingGET() { $this->_markTestAsRestOnly('SOAP test is covered in testSearchCustomers'); $builder = Bootstrap::getObjectManager()->create(FilterBuilder::class); $customerData = $this->_createCustomer(); $filter = $builder ->setField(Customer::EMAIL) ->setValue($customerData[Customer::EMAIL]) ->create(); $this->searchCriteriaBuilder->addFilters([$filter]); $searchData = $this->searchCriteriaBuilder->create()->__toArray(); $requestData = ['searchCriteria' => $searchData]; $searchQueryString = http_build_query($requestData); $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/search?' . $searchQueryString, 'httpMethod' => Request::HTTP_METHOD_GET, ], ]; $searchResults = $this->_webApiCall($serviceInfo); $this->assertEquals(1, $searchResults['total_count']); $this->assertEquals($customerData[Customer::ID], $searchResults['items'][0][Customer::ID]); } /** * Test with empty GET based filter */ public function testSearchCustomersUsingGETEmptyFilter() { $this->_markTestAsRestOnly('Soap clients explicitly check for required fields based on WSDL.'); $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/search', 'httpMethod' => Request::HTTP_METHOD_GET, ], ]; try { $this->_webApiCall($serviceInfo); } catch (\Exception $e) { $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode()); $exceptionData = $this->processRestExceptionResult($e); $expectedExceptionData = [ 'message' => '"%fieldName" is required. Enter and try again.', 'parameters' => [ 'fieldName' => 'searchCriteria' ], ]; $this->assertEquals($expectedExceptionData, $exceptionData); } } /** * Test using multiple filters */ public function testSearchCustomersMultipleFiltersWithSort() { $builder = Bootstrap::getObjectManager()->create(FilterBuilder::class); $customerData1 = $this->_createCustomer(); $customerData2 = $this->_createCustomer(); $filter1 = $builder->setField(Customer::EMAIL) ->setValue($customerData1[Customer::EMAIL]) ->create(); $filter2 = $builder->setField(Customer::EMAIL) ->setValue($customerData2[Customer::EMAIL]) ->create(); $filter3 = $builder->setField(Customer::LASTNAME) ->setValue($customerData1[Customer::LASTNAME]) ->create(); $this->searchCriteriaBuilder->addFilters([$filter1, $filter2]); $this->searchCriteriaBuilder->addFilters([$filter3]); /**@var \Magento\Framework\Api\SortOrderBuilder $sortOrderBuilder */ $sortOrderBuilder = Bootstrap::getObjectManager()->create( SortOrderBuilder::class ); /** @var SortOrder $sortOrder */ $sortOrder = $sortOrderBuilder->setField(Customer::EMAIL)->setDirection(SortOrder::SORT_ASC)->create(); $this->searchCriteriaBuilder->setSortOrders([$sortOrder]); $searchCriteria = $this->searchCriteriaBuilder->create(); $searchData = $searchCriteria->__toArray(); $requestData = ['searchCriteria' => $searchData]; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData), 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'getList', ], ]; $searchResults = $this->_webApiCall($serviceInfo, $requestData); $this->assertEquals(2, $searchResults['total_count']); $this->assertEquals($customerData1[Customer::ID], $searchResults['items'][0][Customer::ID]); $this->assertEquals($customerData2[Customer::ID], $searchResults['items'][1][Customer::ID]); } /** * Test using multiple filters using GET */ public function testSearchCustomersMultipleFiltersWithSortUsingGET() { $this->_markTestAsRestOnly('SOAP test is covered in testSearchCustomers'); $builder = Bootstrap::getObjectManager()->create(FilterBuilder::class); $customerData1 = $this->_createCustomer(); $customerData2 = $this->_createCustomer(); $filter1 = $builder->setField(Customer::EMAIL) ->setValue($customerData1[Customer::EMAIL]) ->create(); $filter2 = $builder->setField(Customer::EMAIL) ->setValue($customerData2[Customer::EMAIL]) ->create(); $filter3 = $builder->setField(Customer::LASTNAME) ->setValue($customerData1[Customer::LASTNAME]) ->create(); $this->searchCriteriaBuilder->addFilters([$filter1, $filter2]); $this->searchCriteriaBuilder->addFilters([$filter3]); $this->searchCriteriaBuilder->setSortOrders([Customer::EMAIL => SortOrder::SORT_ASC]); $searchCriteria = $this->searchCriteriaBuilder->create(); $searchData = $searchCriteria->__toArray(); $requestData = ['searchCriteria' => $searchData]; $searchQueryString = http_build_query($requestData); $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/search?' . $searchQueryString, 'httpMethod' => Request::HTTP_METHOD_GET, ], ]; $searchResults = $this->_webApiCall($serviceInfo); $this->assertEquals(2, $searchResults['total_count']); $this->assertEquals($customerData1[Customer::ID], $searchResults['items'][0][Customer::ID]); $this->assertEquals($customerData2[Customer::ID], $searchResults['items'][1][Customer::ID]); } /** * Test and verify multiple filters using And-ed non-existent filter value */ public function testSearchCustomersNonExistentMultipleFilters() { $builder = Bootstrap::getObjectManager()->create(FilterBuilder::class); $customerData1 = $this->_createCustomer(); $customerData2 = $this->_createCustomer(); $filter1 = $filter1 = $builder->setField(Customer::EMAIL) ->setValue($customerData1[Customer::EMAIL]) ->create(); $filter2 = $builder->setField(Customer::EMAIL) ->setValue($customerData2[Customer::EMAIL]) ->create(); $filter3 = $builder->setField(Customer::LASTNAME) ->setValue('INVALID') ->create(); $this->searchCriteriaBuilder->addFilters([$filter1, $filter2]); $this->searchCriteriaBuilder->addFilters([$filter3]); $searchCriteria = $this->searchCriteriaBuilder->create(); $searchData = $searchCriteria->__toArray(); $requestData = ['searchCriteria' => $searchData]; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData), 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'getList', ], ]; $searchResults = $this->_webApiCall($serviceInfo, $requestData); $this->assertEquals(0, $searchResults['total_count'], 'No results expected for non-existent email.'); } /** * Test and verify multiple filters using And-ed non-existent filter value using GET */ public function testSearchCustomersNonExistentMultipleFiltersGET() { $this->_markTestAsRestOnly('SOAP test is covered in testSearchCustomers'); $builder = Bootstrap::getObjectManager()->create(FilterBuilder::class); $customerData1 = $this->_createCustomer(); $customerData2 = $this->_createCustomer(); $filter1 = $filter1 = $builder->setField(Customer::EMAIL) ->setValue($customerData1[Customer::EMAIL]) ->create(); $filter2 = $builder->setField(Customer::EMAIL) ->setValue($customerData2[Customer::EMAIL]) ->create(); $filter3 = $builder->setField(Customer::LASTNAME) ->setValue('INVALID') ->create(); $this->searchCriteriaBuilder->addFilters([$filter1, $filter2]); $this->searchCriteriaBuilder->addFilters([$filter3]); $searchCriteria = $this->searchCriteriaBuilder->create(); $searchData = $searchCriteria->__toArray(); $requestData = ['searchCriteria' => $searchData]; $searchQueryString = http_build_query($requestData); $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/search?' . $searchQueryString, 'httpMethod' => Request::HTTP_METHOD_GET, ], ]; $searchResults = $this->_webApiCall($serviceInfo, $requestData); $this->assertEquals(0, $searchResults['total_count'], 'No results expected for non-existent email.'); } /** * Test using multiple filters */ public function testSearchCustomersMultipleFilterGroups() { $customerData1 = $this->_createCustomer(); /** @var \Magento\Framework\Api\FilterBuilder $builder */ $builder = Bootstrap::getObjectManager()->create(FilterBuilder::class); $filter1 = $builder->setField(Customer::EMAIL) ->setValue($customerData1[Customer::EMAIL]) ->create(); $filter2 = $builder->setField(Customer::MIDDLENAME) ->setValue($customerData1[Customer::MIDDLENAME]) ->create(); $filter3 = $builder->setField(Customer::MIDDLENAME) ->setValue('invalid') ->create(); $filter4 = $builder->setField(Customer::LASTNAME) ->setValue($customerData1[Customer::LASTNAME]) ->create(); $this->searchCriteriaBuilder->addFilters([$filter1]); $this->searchCriteriaBuilder->addFilters([$filter2, $filter3]); $this->searchCriteriaBuilder->addFilters([$filter4]); $searchCriteria = $this->searchCriteriaBuilder->setCurrentPage(1)->setPageSize(10)->create(); $searchData = $searchCriteria->__toArray(); $requestData = ['searchCriteria' => $searchData]; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData), 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'getList', ], ]; $searchResults = $this->_webApiCall($serviceInfo, $requestData); $this->assertEquals(1, $searchResults['total_count']); $this->assertEquals($customerData1[Customer::ID], $searchResults['items'][0][Customer::ID]); // Add an invalid And-ed data with multiple groups to yield no result $filter4 = $builder->setField(Customer::LASTNAME) ->setValue('invalid') ->create(); $this->searchCriteriaBuilder->addFilters([$filter1]); $this->searchCriteriaBuilder->addFilters([$filter2, $filter3]); $this->searchCriteriaBuilder->addFilters([$filter4]); $searchCriteria = $this->searchCriteriaBuilder->create(); $searchData = $searchCriteria->__toArray(); $requestData = ['searchCriteria' => $searchData]; $serviceInfo['rest']['resourcePath'] = self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData); $searchResults = $this->_webApiCall($serviceInfo, $requestData); $this->assertEquals(0, $searchResults['total_count']); } /** * Test revoking all access Tokens for customer */ public function testRevokeAllAccessTokensForCustomer() { $customerData = $this->_createCustomer(); /** @var CustomerTokenServiceInterface $customerTokenService */ $customerTokenService = Bootstrap::getObjectManager()->create(CustomerTokenServiceInterface::class); $token = $customerTokenService->createCustomerAccessToken( $customerData[Customer::EMAIL], CustomerHelper::PASSWORD ); $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/me', 'httpMethod' => Request::HTTP_METHOD_GET, 'token' => $token, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'GetSelf', 'token' => $token, ], ]; $customerLoadedData = $this->_webApiCall($serviceInfo, ['customerId' => $customerData[Customer::ID]]); self::assertGreaterThanOrEqual($customerData[Customer::UPDATED_AT], $customerLoadedData[Customer::UPDATED_AT]); unset($customerData[Customer::UPDATED_AT]); unset($customerLoadedData[Customer::UPDATED_AT], $customerLoadedData[Customer::CONFIRMATION]); self::assertEquals($customerData, $customerLoadedData); $revokeToken = $customerTokenService->revokeCustomerAccessToken($customerData[Customer::ID]); self::assertTrue($revokeToken); try { $customerTokenService->revokeCustomerAccessToken($customerData[Customer::ID]); } catch (\Throwable $exception) { $this->assertInstanceOf(LocalizedException::class, $exception); $this->assertEquals('This customer has no tokens.', $exception->getMessage()); } $expectedMessage = 'The consumer isn\'t authorized to access %resources.'; try { $this->_webApiCall($serviceInfo, ['customerId' => $customerData[Customer::ID]]); } catch (\SoapFault $e) { $this->assertStringContainsString( $expectedMessage, $e->getMessage(), 'SoapFault does not contain expected message.' ); } catch (\Throwable $e) { $errorObj = $this->processRestExceptionResult($e); $this->assertEquals($expectedMessage, $errorObj['message']); $this->assertEquals(['resources' => 'self'], $errorObj['parameters']); $this->assertEquals(HTTPExceptionCodes::HTTP_UNAUTHORIZED, $e->getCode()); } } /** * Retrieve customer data by Id * * @param int $customerId * @return Customer */ private function getCustomerData($customerId): Customer { $customerData = $this->customerRepository->getById($customerId); $this->customerRegistry->remove($customerId); return $customerData; } /** * @param array|null $additionalData * @return array|bool|float|int|string */ protected function _createCustomer(?array $additionalData = []) { $customerData = $this->customerHelper->createSampleCustomer($additionalData); $this->currentCustomerId[] = $customerData['id']; return $customerData; } /** * Test customer create with invalid name's. * * @param string $fieldName * @param string $fieldValue * @param string $expectedMessage * @return void * * @dataProvider customerDataProvider */ public function testCreateCustomerWithInvalidCustomerFirstName( string $fieldName, string $fieldValue, string $expectedMessage ): void { $customerData = $this->dataObjectProcessor->buildOutputDataArray( $this->customerHelper->createSampleCustomerDataObject(), Customer::class ); $customerData[$fieldName] = $fieldValue; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH, 'httpMethod' => Request::HTTP_METHOD_POST, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'Save', ], ]; $requestData = ['customer' => $customerData]; try { $this->_webApiCall($serviceInfo, $requestData); $this->fail('Expected exception was not raised'); } catch (\SoapFault $e) { $this->assertStringContainsString($expectedMessage, $e->getMessage()); } catch (\Exception $e) { $errorObj = $this->processRestExceptionResult($e); $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode()); $this->assertEquals($expectedMessage, $errorObj['message']); } } /** * Invalid customer data provider * * @return array */ public function customerDataProvider(): array { return [ ['firstname', 'Jane ☺ ', 'First Name is not valid!'], ['lastname', '☏ - Doe', 'Last Name is not valid!'], ['middlename', '⚐ $(date)', 'Middle Name is not valid!'], [ 'firstname', str_repeat('खाना अच्छा है', 20), 'First Name is not valid!', ], [ 'lastname', str_repeat('المغلوطة حول استنكار النشوة وتمجيد الألمالمغلوطة حول', 5), 'Last Name is not valid!', ], ]; } /** * Test customer create with ultibyte chanracters in name's. * * @param string $fieldName * @param string $fieldValue * @return void * * @dataProvider customerWithMultiByteDataProvider */ public function testCreateCustomerWithMultibyteCharacters(string $fieldName, string $fieldValue): void { $customerData = $this->dataObjectProcessor->buildOutputDataArray( $this->customerHelper->createSampleCustomerDataObject(), Customer::class ); $customerData[$fieldName] = $fieldValue; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH, 'httpMethod' => Request::HTTP_METHOD_POST, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'Save', ], ]; $requestData = ['customer' => $customerData]; $response = $this->_webApiCall($serviceInfo, $requestData); $this->assertNotNull($response); $this->assertEquals($fieldValue, $response[$fieldName]); } /** * Customer with multibyte characters data provider. * * @return array */ public function customerWithMultiByteDataProvider(): array { return [ [ 'firstname', str_repeat('हैखान', 51), ], [ 'lastname', str_repeat('مغلوطة حول استنكار النشوة وتمجيد الألمالمغلوطة حول', 5), ], ]; } /** * Test customer create with valid name's. * * @param string $fieldName * @param string $fieldValue * @return void * * @dataProvider customerValidNameDataProvider */ public function testCreateCustomerWithValidName(string $fieldName, string $fieldValue): void { $customerData = $this->dataObjectProcessor->buildOutputDataArray( $this->customerHelper->createSampleCustomerDataObject(), Customer::class ); $customerData[$fieldName] = $fieldValue; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH, 'httpMethod' => Request::HTTP_METHOD_POST, ], 'soap' => [ 'service' => self::SERVICE_NAME, 'serviceVersion' => self::SERVICE_VERSION, 'operation' => self::SERVICE_NAME . 'Save', ], ]; $requestData = ['customer' => $customerData]; $response = $this->_webApiCall($serviceInfo, $requestData); $this->assertNotNull($response); $this->assertEquals($fieldValue, $response[$fieldName]); } /** * Customer valid name data provider. * * @return array */ public function customerValidNameDataProvider(): array { return [ [ 'firstname', 'Anne-Marie', ], [ 'lastname', 'D\'Artagnan', ], [ 'lastname', 'Guðmundsdóttir', ], [ 'lastname', 'María José Carreño Quiñones', ], [ 'lastname', 'Q. Public', ], [ 'firstname', 'Elizabeth II', ], [ 'firstname', 'X Æ A-12 Musk', ], ]; } }