diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php
index d43b313c43b3e..5dabd48782b73 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php
@@ -108,8 +108,10 @@ public function execute()
$result['url'] = $this->productMediaConfig->getTmpMediaUrl($result['file']);
$result['file'] = $result['file'] . '.tmp';
- } catch (\Exception $e) {
+ } catch (LocalizedException $e) {
$result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
+ } catch (\Throwable $e) {
+ $result = ['error' => 'Something went wrong while saving the file(s).', 'errorcode' => 0];
}
/** @var \Magento\Framework\Controller\Result\Raw $response */
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontRemoveFirstProductFromCompareActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontRemoveFirstProductFromCompareActionGroup.xml
new file mode 100644
index 0000000000000..fefcdb6930c61
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontRemoveFirstProductFromCompareActionGroup.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ Open Compare Products list and remove a product
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductCompareMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductCompareMainSection.xml
index ad31be6b277ee..d120042fbe9a2 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductCompareMainSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductCompareMainSection.xml
@@ -14,5 +14,6 @@
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml
index d2de38c31dbb5..fad0b26262d0a 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml
@@ -78,8 +78,7 @@
-
-
+
@@ -92,11 +91,13 @@
-
+
-
+
+
+
@@ -108,11 +109,11 @@
-
-
+
+
-
+
diff --git a/app/code/Magento/Customer/Model/Validator/Name.php b/app/code/Magento/Customer/Model/Validator/Name.php
new file mode 100644
index 0000000000000..9bab241465d6c
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Validator/Name.php
@@ -0,0 +1,59 @@
+isValidName($customer->getFirstname())) {
+ parent::_addMessages([['firstname' => 'First Name is not valid!']]);
+ }
+
+ if (!$this->isValidName($customer->getLastname())) {
+ parent::_addMessages([['lastname' => 'Last Name is not valid!']]);
+ }
+
+ if (!$this->isValidName($customer->getMiddlename())) {
+ parent::_addMessages([['middlename' => 'Middle Name is not valid!']]);
+ }
+
+ return count($this->_messages) == 0;
+ }
+
+ /**
+ * Check if name field is valid.
+ *
+ * @param string|null $nameValue
+ * @return bool
+ */
+ private function isValidName($nameValue)
+ {
+ if ($nameValue != null) {
+ if (preg_match(self::PATTERN_NAME, $nameValue, $matches)) {
+ return $matches[0] == $nameValue;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminExactMatchSearchInCustomerGridTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminExactMatchSearchInCustomerGridTest.xml
index 14d569ed9101d..ef9c90847adec 100644
--- a/app/code/Magento/Customer/Test/Mftf/Test/AdminExactMatchSearchInCustomerGridTest.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminExactMatchSearchInCustomerGridTest.xml
@@ -21,7 +21,7 @@
- "Jane Doe"
+ Jane Doe
diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifyNoXssInjectionOnUpdateCustomerInformationAddAddressTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifyNoXssInjectionOnUpdateCustomerInformationAddAddressTest.xml
index 11aed4a3461e1..712ad61a9663e 100644
--- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifyNoXssInjectionOnUpdateCustomerInformationAddAddressTest.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifyNoXssInjectionOnUpdateCustomerInformationAddAddressTest.xml
@@ -11,12 +11,15 @@
-
+
+
+ Test outdated
+
diff --git a/app/code/Magento/Customer/etc/validation.xml b/app/code/Magento/Customer/etc/validation.xml
index 85d657dff266a..bac6e54afa7b5 100644
--- a/app/code/Magento/Customer/etc/validation.xml
+++ b/app/code/Magento/Customer/etc/validation.xml
@@ -18,11 +18,17 @@
+
+
+
+
+
+
diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php
index f7732b5fd68dd..95f7da88b0619 100644
--- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php
@@ -1058,4 +1058,204 @@ protected function _createCustomer(?array $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',
+ ],
+ ];
+ }
}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Gallery/UploadTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Gallery/UploadTest.php
index 283a3834eab59..b2494ba2ecb8a 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Gallery/UploadTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Gallery/UploadTest.php
@@ -198,7 +198,7 @@ public function uploadActionWithErrorsDataProvider(): array
'current_path' => '/../../../../_files',
],
'expectation' => [
- 'message' => 'Wrong file size.',
+ 'message' => 'Something went wrong while saving the file(s).',
'errorcode' => 0,
'tmp_media_path' => '/m/a/magento_empty.jpg',
],
@@ -206,10 +206,23 @@ public function uploadActionWithErrorsDataProvider(): array
'upload_without_image' => [
'file' => [],
'expectation' => [
- 'message' => '$_FILES array is empty',
+ 'message' => 'Something went wrong while saving the file(s).',
'errorcode' => 0,
],
],
+ 'upload_wrong_png' => [
+ 'file' => [
+ 'copy_file' => true,
+ 'name' => 'magento_wrong.png',
+ 'type' => 'image/png',
+ 'current_path' => '/../../../../_files',
+ ],
+ 'expectation' => [
+ 'message' => 'Something went wrong while saving the file(s).',
+ 'errorcode' => 0,
+ 'tmp_media_path' => '/m/w/magento_wrong.png',
+ ],
+ ]
];
}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/magento_wrong.png b/dev/tests/integration/testsuite/Magento/Catalog/_files/magento_wrong.png
new file mode 100644
index 0000000000000..7bca3ec1f1dea
Binary files /dev/null and b/dev/tests/integration/testsuite/Magento/Catalog/_files/magento_wrong.png differ