6 declare(strict_types=1);
43 private $productData = [
63 $productData = $this->productData[0];
66 $this->assertEquals($productData[$key],
$response[$key]);
80 'resourcePath' => self::RESOURCE_PATH .
'/' . $sku,
86 'operation' => self::SERVICE_NAME .
'Get',
96 $invalidSku =
'(nonExistingSku)';
99 'resourcePath' => self::RESOURCE_PATH .
'/' . $invalidSku,
105 'operation' => self::SERVICE_NAME .
'Get',
109 $expectedMessage =
"The product that was requested doesn't exist. Verify the product and try again.";
112 $this->
_webApiCall($serviceInfo, [
'sku' => $invalidSku]);
113 $this->fail(
"Expected throwing exception");
114 }
catch (\SoapFault $e) {
115 $this->assertContains(
118 "SoapFault does not contain expected message." 120 }
catch (\Exception $e) {
122 $this->assertEquals($expectedMessage, $errorObj[
'message']);
123 $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
132 $productBuilder =
function (
$data) {
133 return array_replace_recursive(
155 }
catch (NoSuchEntityException $e) {
156 $this->fail(
"Couldn`t load website: {$websiteCode}");
166 public function testUpdateWithDeleteWebsites()
170 $website = $this->loadWebsiteByCode(
'second_website');
181 $websitesData[
"website_ids"]
200 $websitesData[
"website_ids"]
207 public function testCreateWithMultipleWebsites()
213 $website = $this->loadWebsiteByCode(
'test_website');
225 $websitesData[
"website_ids"]
235 public function testCreateWithNonDefaultStoreWebsite()
241 $website = $this->loadWebsiteByCode(
'test');
251 $websitesData[
"website_ids"],
263 public function testUpdateWithNonDefaultStoreWebsite()
267 $website = $this->loadWebsiteByCode(
'test');
279 $websitesData[
"website_ids"],
293 $newName =
'Updated Product';
323 public function testCreateAllStoreCode($fixtureProduct)
338 $this->assertArrayHasKey(
352 public function testCreateAllStoreCodeForSingleWebsite($fixtureProduct)
359 \
Magento\Store\Model\StoreManagerInterface::class
367 $this->assertArrayHasKey(
377 $this->
_markTestAsRestOnly(
"In case of SOAP type casting is handled by PHP SoapServer, no need to test it");
378 $expectedMessage =
'Error occurred during "price" processing. ' 379 .
'The "invalid_format" value\'s type is invalid. The "float" type was expected. Verify and try again.';
382 $this->
saveProduct([
'name' =>
'simple',
'price' =>
'invalid_format',
'sku' =>
'simple']);
383 $this->fail(
"Expected exception was not raised");
384 }
catch (\Exception $e) {
386 $this->assertEquals($expectedMessage, $errorObj[
'message']);
387 $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
401 $this->expectException(
'Exception');
402 $this->expectExceptionMessage(
403 "The product that was requested doesn't exist. Verify the product and try again." 424 'stock_item' => $this->getStockItemData()
431 "sku" =>
"product_simple_with_related_500",
432 "link_type" =>
"related",
433 "linked_product_sku" =>
"product_simple_500",
434 "linked_product_type" =>
"simple",
437 $productWithRelatedData = [
446 "product_links" => [$productLinkData]
452 $this->assertArrayHasKey(
'product_links',
$response);
454 $this->assertEquals(1, count(
$links));
455 $this->assertEquals($productLinkData,
$links[0]);
459 "sku" =>
"product_simple_with_related_500",
460 "link_type" =>
"upsell",
461 "linked_product_sku" =>
"product_simple_500",
462 "linked_product_type" =>
"simple",
465 $productWithUpsellData = [
473 "product_links" => [$productLinkData]
479 $this->assertArrayHasKey(
'product_links',
$response);
481 $this->assertEquals(1, count(
$links));
482 $this->assertEquals($productLinkData,
$links[0]);
485 $productWithNoLinkData = [
493 "product_links" => []
498 $this->assertArrayHasKey(
'product_links',
$response);
500 $this->assertEquals([],
$links);
514 "product_sku" => $productSku,
515 "title" =>
"DropdownOption",
516 "type" =>
"drop_down",
518 "is_require" =>
true,
521 "title" =>
"DropdownOption2_1",
524 "price_type" =>
"fixed",
529 "product_sku" => $productSku,
530 "title" =>
"CheckboxOption",
531 "type" =>
"checkbox",
533 "is_require" =>
false,
536 "title" =>
"CheckBoxValue1",
538 "price_type" =>
"fixed",
551 $productData[
'options'] = $optionsDataInput;
555 $this->assertArrayHasKey(
'options',
$response);
557 $this->assertEquals(2, count(
$options));
558 $this->assertEquals(1, count(
$options[0][
'values']));
559 $this->assertEquals(1, count(
$options[1][
'values']));
565 "price_type" =>
"fixed",
569 "product_sku" => $productData[
'sku'],
570 "title" =>
"DropdownOption2",
571 "type" =>
"drop_down",
573 "is_require" =>
false,
578 "price_type" =>
"fixed",
585 $this->assertArrayHasKey(
'options',
$response);
587 $this->assertEquals(2, count(
$options));
588 $this->assertEquals(2, count(
$options[0][
'values']));
589 $this->assertEquals(1, count(
$options[1][
'values']));
595 $this->assertArrayHasKey(
'options',
$response);
597 $this->assertEquals(2, count(
$options));
602 $this->assertEmpty(
$response[
'options']);
612 $filename1 =
'tiny1' .
time() .
'.jpg';
613 $filename2 =
'tiny2' .
time() .
'.jpeg';
615 $productData[
'media_gallery_entries'] = $this->getMediaGalleryData($filename1, $encodedImage, $filename2);
617 $this->assertArrayHasKey(
'media_gallery_entries',
$response);
618 $mediaGalleryEntries =
$response[
'media_gallery_entries'];
619 $this->assertEquals(2, count($mediaGalleryEntries));
620 $id = $mediaGalleryEntries[0][
'id'];
621 foreach ($mediaGalleryEntries as &$entry) {
628 'media_type' =>
'image',
631 'file' =>
'/t/i/' . $filename1,
636 'media_type' =>
'image',
638 'types' => [
'image',
'small_image'],
639 'file' =>
'/t/i/' . $filename2,
642 $this->assertEquals($expectedValue, $mediaGalleryEntries);
647 'media_type' =>
'image',
648 'label' =>
'tiny1_new_label',
651 'types' => [
'image',
'small_image'],
652 'file' =>
'/t/i/' . $filename1,
656 $mediaGalleryEntries =
$response[
'media_gallery_entries'];
657 $this->assertEquals(1, count($mediaGalleryEntries));
658 unset($mediaGalleryEntries[0][
'id']);
661 'label' =>
'tiny1_new_label',
662 'media_type' =>
'image',
665 'types' => [
'image',
'small_image'],
666 'file' =>
'/t/i/' . $filename1,
669 $this->assertEquals($expectedValue, $mediaGalleryEntries);
671 unset(
$response[
'media_gallery_entries']);
673 $mediaGalleryEntries =
$response[
'media_gallery_entries'];
674 $this->assertEquals(1, count($mediaGalleryEntries));
675 unset($mediaGalleryEntries[0][
'id']);
676 $this->assertEquals($expectedValue, $mediaGalleryEntries);
680 $this->assertEquals(
true, empty(
$response[
'media_gallery_entries']));
709 $sku =
'downloadable-product';
710 $linksKey =
'downloadable_product_links';
723 self::assertArrayHasKey(Link::KEY_LINK_URL,
$linkData);
724 self::assertEquals(
'http://example.com/downloadable.txt',
$linkData[Link::KEY_LINK_URL]);
733 if (isset(
$product[
'custom_attributes'])) {
735 if (
$product[
'custom_attributes'][
$i][
'attribute_code'] ==
'category_ids' 736 && !is_array(
$product[
'custom_attributes'][
$i][
'value'])
738 $product[
'custom_attributes'][
$i][
'value'] = [
""];
743 if (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) {
749 'resourcePath' => self::RESOURCE_PATH .
'/' . $sku,
755 'operation' => self::SERVICE_NAME .
'Save',
778 'searchCriteria' => [
785 'condition_type' =>
'eq',
797 'resourcePath' => self::RESOURCE_PATH .
'?' . http_build_query(
$searchCriteria),
803 'operation' => self::SERVICE_NAME .
'GetList',
809 $this->assertArrayHasKey(
'search_criteria',
$response);
810 $this->assertArrayHasKey(
'total_count',
$response);
811 $this->assertArrayHasKey(
'items',
$response);
814 $this->assertTrue(
$response[
'total_count'] > 0);
815 $this->assertTrue(count(
$response[
'items']) > 0);
817 $this->assertNotNull(
$response[
'items'][0][
'sku']);
819 $this->assertEquals(
'simple',
$response[
'items'][0][
'sku']);
822 foreach (
$response[
'items'][0][
'custom_attributes'] as $key => $customAttribute) {
823 if ($customAttribute[
'attribute_code'] ==
'category_ids') {
828 $this->assertNotNull(
$index,
'Category information wasn\'t set');
830 $expectedResult = (TESTS_WEB_API_ADAPTER ==
self::ADAPTER_SOAP) ? [
'string' =>
'2'] : [
'2'];
831 $this->assertEquals($expectedResult,
$response[
'items'][0][
'custom_attributes'][
$index][
'value']);
841 'searchCriteria' => [
846 $additionalParams = urlencode(
'items[id,custom_attributes[description]]');
850 'resourcePath' => self::RESOURCE_PATH .
'?' . http_build_query(
$searchCriteria) .
'&fields=' .
858 $this->assertArrayHasKey(
'items',
$response);
859 $this->assertTrue(count(
$response[
'items']) > 0);
861 $indexDescription =
null;
862 foreach (
$response[
'items'][0][
'custom_attributes'] as $key => $customAttribute) {
863 if ($customAttribute[
'attribute_code'] ==
'description') {
864 $indexDescription = $key;
868 $this->assertNotNull(
$response[
'items'][0][
'custom_attributes'][$indexDescription][
'attribute_code']);
869 $this->assertNotNull(
$response[
'items'][0][
'custom_attributes'][$indexDescription][
'value']);
870 $this->assertTrue(count(
$response[
'items'][0][
'custom_attributes']) == 1);
879 $website = $this->loadWebsiteByCode(
'test');
881 'searchCriteria' => [
886 'field' =>
'website_id',
888 'condition_type' =>
'eq',
899 'resourcePath' => self::RESOURCE_PATH .
'?' . http_build_query(
$searchCriteria),
905 'operation' => self::SERVICE_NAME .
'GetList',
910 $this->assertArrayHasKey(
'search_criteria',
$response);
911 $this->assertArrayHasKey(
'total_count',
$response);
912 $this->assertArrayHasKey(
'items',
$response);
913 $this->assertTrue(count(
$response[
'items']) == 1);
914 $this->assertTrue(isset(
$response[
'items'][0][
'sku']));
915 $this->assertEquals(
'simple-2',
$response[
'items'][0][
'sku']);
932 'resourcePath' => self::RESOURCE_PATH .
'?' . http_build_query(
$searchCriteria),
938 'operation' => self::SERVICE_NAME .
'GetList',
943 $this->assertArrayHasKey(
'search_criteria',
$response);
944 $this->assertArrayHasKey(
'total_count',
$response);
945 $this->assertArrayHasKey(
'items',
$response);
946 if ($expectedProductCount) {
947 $this->assertTrue(count(
$response[
'items']) == $expectedProductCount);
950 $isResultValid =
false;
951 foreach (
$skus as $sku) {
953 if (
$item[
'sku'] == $sku) {
954 $isResultValid =
true;
957 $this->assertTrue($isResultValid);
966 'searchCriteria' => [
972 'value' =>
'fixture_second_store',
973 'condition_type' =>
'eq',
987 'searchCriteria' => [
988 'filter_groups' => [],
993 [
'simple-2',
'simple-1'],
1002 public function testGetListWithMultipleFilterGroupsAndSortingAndPagination()
1008 ->setValue(
'search product 2')
1011 ->setValue(
'search product 3')
1014 ->setValue(
'search product 4')
1017 ->setValue(
'search product 5')
1021 ->setConditionType(
'lt')
1023 $filter6 = $filterBuilder->setField(
'category_id')
1031 $sortOrder = $sortOrderBuilder->setField(
'meta_title')->setDirection(
SortOrder::SORT_DESC)->create();
1048 'resourcePath' => self::RESOURCE_PATH .
'?' . http_build_query(
$requestData),
1054 'operation' => self::SERVICE_NAME .
'GetList',
1060 $this->assertEquals(3, $searchResult[
'total_count']);
1061 $this->assertEquals(1, count($searchResult[
'items']));
1063 $this->assertNotNull(
1075 foreach ($customAttributes as $customAttribute) {
1076 $converted[$customAttribute[
'attribute_code']] = $customAttribute[
'value'];
1087 $customAttributes = [];
1089 $customAttributes[] = [
'attribute_code' =>
$attributeCode,
'value' => $attributeValue];
1091 return $customAttributes;
1101 $this->assertNotEmpty(
$response[
'custom_attributes']);
1103 $this->assertNotTrue(isset($customAttributesData[
'name']));
1104 $this->assertNotTrue(isset($customAttributesData[
'tier_price']));
1107 $descriptionValue =
"new description";
1108 $customAttributesData[
'description'] = $descriptionValue;
1112 $this->assertNotEmpty(
$response[
'custom_attributes']);
1115 $this->assertTrue(isset($customAttributesData[
'description']));
1116 $this->assertEquals($descriptionValue, $customAttributesData[
'description']);
1140 'custom_attributes' => [
1141 [
'attribute_code' =>
'cost',
'value' =>
''],
1142 [
'attribute_code' =>
'description',
'value' =>
'Description'],
1154 if (isset(
$product[
'custom_attributes'])) {
1156 if (
$product[
'custom_attributes'][
$i][
'attribute_code'] ==
'category_ids' 1157 && !is_array(
$product[
'custom_attributes'][
$i][
'value'])
1159 $product[
'custom_attributes'][
$i][
'value'] = [
""];
1171 'operation' => self::SERVICE_NAME .
'Save',
1188 'resourcePath' => self::RESOURCE_PATH .
'/' . $sku,
1194 'operation' => self::SERVICE_NAME .
'DeleteById',
1198 return (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) ?
1210 'customer_group_id' => $custGroup1,
1215 'customer_group_id' => $custGroup2,
1223 $this->assertArrayHasKey(self::KEY_TIER_PRICES,
$response);
1225 $this->assertNotNull(
$tierPrices,
"CREATE: expected to have tier prices");
1226 $this->assertCount(2,
$tierPrices,
"CREATE: expected to have 2 'tier_prices' objects");
1227 $this->assertEquals(3.14,
$tierPrices[0][
'value']);
1229 $this->assertEquals($custGroup1,
$tierPrices[0][
'customer_group_id']);
1230 $this->assertEquals(3.45,
$tierPrices[1][
'value']);
1232 $this->assertEquals($custGroup2,
$tierPrices[1][
'customer_group_id']);
1239 'customer_group_id' => $custGroup3,
1246 $this->assertArrayHasKey(self::KEY_TIER_PRICES,
$response);
1248 $this->assertNotNull(
$tierPrices,
"UPDATE 1: expected to have tier prices");
1249 $this->assertCount(2,
$tierPrices,
"UPDATE 1: expected to have 2 'tier_prices' objects");
1250 $this->assertEquals(3.33,
$tierPrices[0][
'value']);
1252 $this->assertEquals($custGroup1,
$tierPrices[0][
'customer_group_id']);
1253 $this->assertEquals(2.10,
$tierPrices[1][
'value']);
1255 $this->assertEquals($custGroup3,
$tierPrices[1][
'customer_group_id']);
1259 unset(
$response[self::KEY_TIER_PRICES]);
1262 $this->assertArrayHasKey(self::KEY_TIER_PRICES,
$response);
1264 $this->assertNotNull(
$tierPrices,
"UPDATE 2: expected to have tier prices");
1265 $this->assertCount(2,
$tierPrices,
"UPDATE 2: expected to have 2 'tier_prices' objects");
1266 $this->assertEquals(3.33,
$tierPrices[0][
'value']);
1268 $this->assertEquals($custGroup1,
$tierPrices[0][
'customer_group_id']);
1269 $this->assertEquals(2.10,
$tierPrices[1][
'value']);
1271 $this->assertEquals($custGroup3,
$tierPrices[1][
'customer_group_id']);
1277 $this->assertArrayHasKey(self::KEY_TIER_PRICES,
$response,
"expected to have the 'tier_prices' key");
1278 $this->assertEmpty(
$response[self::KEY_TIER_PRICES],
"expected to have an empty array of 'tier_prices'");
1288 private function getStockItemData()
1325 self::KEY_CATEGORY_LINKS => [[
'category_id' => 333,
'position' => 0]]
1328 $this->assertEquals(
1329 [[
'category_id' => 333,
'position' => 0]],
1336 $this->assertEquals([[
'category_id' => 333,
'position' => 0]],
$extensionAttributes[self::KEY_CATEGORY_LINKS]);
1348 $this->assertEquals(
1349 [[
'category_id' => 333,
'position' => 0]],
1354 $this->assertEquals(
1355 [[
'category_id' => 333,
'position' => 0]],
1368 [
'category_id' => 333,
'position' => 10]
1371 $this->assertEquals(
1372 [[
'category_id' => 333,
'position' => 10]],
1395 private function getMediaGalleryData($filename1, $encodedImage, $filename2)
1400 'media_type' =>
'image',
1405 'type' =>
'image/jpeg',
1406 'name' => $filename1,
1407 'base64_encoded_data' => $encodedImage,
1412 'media_type' =>
'image',
1413 'disabled' =>
false,
1415 'types' => [
'image',
'small_image'],
1417 'type' =>
'image/jpeg',
1418 'name' => $filename2,
1419 'base64_encoded_data' => $encodedImage,
1428 $productData[
'custom_attributes'] = [
1433 $customAttributes =
$response[
'custom_attributes'];
1434 $this->assertNotEmpty($customAttributes);
1435 $missingAttributes = [
'news_from_date',
'custom_design_from'];
1436 $expectedAttribute = [
'special_price',
'special_from_date'];
1438 $this->assertEquals(0, count(array_intersect(
$attributeCodes, $missingAttributes)));
1439 $this->assertEquals(2, count(array_intersect(
$attributeCodes, $expectedAttribute)));
1453 'In order to properly run this test for SOAP, XML must be used to specify <value></value> ' .
1454 'for the special_price value. Otherwise, the null value gets processed as a string and ' .
1455 'cast to a double value of 0.0.' 1458 $productData[
'custom_attributes'] = [
1463 $customAttributes = array_column(
$response[
'custom_attributes'],
'value',
'attribute_code');
1464 $this->assertEquals(5, $customAttributes[self::KEY_SPECIAL_PRICE]);
1465 $productData[
'custom_attributes'] = [
1470 $customAttributes = array_column(
$response[
'custom_attributes'],
'value',
'attribute_code');
1471 $this->assertFalse(array_key_exists(self::KEY_SPECIAL_PRICE, $customAttributes));
1491 $this->assertEquals(0,
$response[
'status']);
1499 $this->assertEquals(0,
$response[
'status']);
1501 $this->assertEquals(200,
$response[
'price']);
1517 $multiselectAttributeCode =
'multiselect_attribute';
1523 $productData[
'custom_attributes'] = [
1524 [
'attribute_code' => $multiselectAttributeCode,
'value' =>
"{$option1},{$option2}"]
1528 $this->assertMultiselectValue(
1530 $multiselectAttributeCode,
1531 "{$option1},{$option2}" 1534 $productData[
'custom_attributes'] = [
1535 [
'attribute_code' => $multiselectAttributeCode,
'value' =>
""]
1538 $this->assertMultiselectValue(
1540 $multiselectAttributeCode,
1553 'resourcePath' =>
'/V1/products/attributes/' .
$attributeCode .
'/options',
1557 'service' =>
'catalogProductAttributeOptionManagementV1',
1558 'serviceVersion' =>
'V1',
1559 'operation' =>
'catalogProductAttributeOptionManagementV1getItems',
1571 private function assertMultiselectValue($productSku, $multiselectAttributeCode, $expectedMultiselectValue)
1574 $customAttributes =
$response[
'custom_attributes'];
1575 $this->assertNotEmpty($customAttributes);
1576 $multiselectValue =
null;
1577 foreach ($customAttributes as $customAttribute) {
1578 if ($customAttribute[
'attribute_code'] == $multiselectAttributeCode) {
1579 $multiselectValue = $customAttribute[
'value'];
1583 $this->assertEquals($expectedMultiselectValue, $multiselectValue);
const STOCK_STATUS_CHANGED_AUTO
testUpdateProductCategoryLinksPosistion()
testProductWithMediaGallery()
convertCustomAttributesToAssociativeArray($customAttributes)
_markTestAsRestOnly($message=null)
getSimpleProductData($productData=[])
const SHOW_DEFAULT_NOTIFICATION_MESSAGE
_webApiCall( $serviceInfo, $arguments=[], $webApiAdapterCode=null, $storeCode=null, $integration=null)
defined('TESTS_BP')||define('TESTS_BP' __DIR__
getProduct($sku, $storeCode=null)
const USE_CONFIG_ENABLE_QTY_INC
productCreationProvider()
const USE_CONFIG_MANAGE_STOCK
const USE_CONFIG_BACKORDERS
testGetListWithFilteringByStore(array $searchCriteria, array $skus, $expectedProductCount=null)
foreach($websiteCodes as $websiteCode) $skus
testGetListWithFilteringByWebsite()
const USE_CONFIG_NOTIFY_STOCK_QTY
saveProduct($product, $storeCode=null)
const USE_CONFIG_MAX_SALE_QTY
const EXTENSION_ATTRIBUTES_KEY
testDeleteAllStoreCode($fixtureProduct)
testGetListWithFilteringByStoreDataProvider()
const USE_CONFIG_QTY_INCREMENTS
testGetListWithAdditionalParams()
testUpdateWithExtensionAttributes()
processRestExceptionResult(\Exception $e)
testUpdateMultiselectAttributes()
testProductCategoryLinks()
const USE_CONFIG_MIN_SALE_QTY
testGetNoSuchEntityException()
testCreateInvalidPriceFormat()
const ENABLE_QTY_INCREMENTS
getOptionsData($productSku)
testUpdateProductCategoryLinksUnassign()
testDeleteAllWebsiteAssociations()
if(!isset($_GET['website_code'])) $websiteCode
testUpdateWithoutWebsiteIds()
testUpdateProductCategoryLinksNullOrNotExists()
convertAssociativeArrayToCustomAttributes($data)
static getObjectManager()