Skip to content

Commit 1d4c1b8

Browse files
ACQE-8152: Verify Rest-API updating product stock_item does not delete downloadable_product_links
- Added new test file to verify stock item update preserves links.
1 parent a6933f3 commit 1d4c1b8

File tree

1 file changed

+225
-0
lines changed

1 file changed

+225
-0
lines changed
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Downloadable\Api;
10+
11+
use Magento\Framework\Webapi\Rest\Request;
12+
use Magento\TestFramework\Helper\Bootstrap;
13+
use Magento\TestFramework\TestCase\WebapiAbstract;
14+
15+
/**
16+
* Test to verify REST-API updating product stock_item does not delete downloadable_product_links
17+
*
18+
* @magentoAppIsolation enabled
19+
*/
20+
class StockItemUpdatePreservesLinksTest extends WebapiAbstract
21+
{
22+
private const ADMIN_TOKEN_RESOURCE_PATH = '/V1/integration/admin/token';
23+
private const PRODUCT_RESOURCE_PATH = '/V1/products';
24+
private const TEST_PRODUCT_SKU = 'downloadable-product';
25+
26+
/**
27+
* @inheritDoc
28+
*/
29+
protected function setUp(): void
30+
{
31+
parent::setUp();
32+
$this->_markTestAsRestOnly();
33+
}
34+
35+
/**
36+
* Test the complete workflow from Steps 1-16
37+
* Verify that REST-API updating product stock_item does not delete downloadable_product_links
38+
*
39+
* @magentoApiDataFixture Magento/Webapi/_files/webapi_user.php
40+
* @magentoApiDataFixture Magento/Downloadable/_files/downloadable_product_with_files_and_sample_url.php
41+
*/
42+
public function testStockItemUpdatePreservesDownloadableLinks()
43+
{
44+
// Steps 1-7: Generate admin access token
45+
$adminToken = $this->generateAdminAccessToken();
46+
47+
// Get original product and verify it has downloadable links
48+
$originalProduct = $this->getProductBySku(self::TEST_PRODUCT_SKU);
49+
$this->verifyProductHasDownloadableLinks($originalProduct, 'Original product should have downloadable links');
50+
$originalLinks = $originalProduct['extension_attributes']['downloadable_product_links'];
51+
52+
// Steps 8-14: Update product stock_item via catalogProductRepositoryV1 PUT endpoint
53+
$updatedProduct = $this->updateProductStockItem($adminToken);
54+
55+
// Verify the API call was successful (Step 14: Server response Code=200)
56+
$this->assertNotEmpty($updatedProduct, 'API response should not be empty');
57+
$this->assertEquals(self::TEST_PRODUCT_SKU, $updatedProduct['sku']);
58+
$this->assertEquals('99.99', $updatedProduct['price']);
59+
$this->assertEquals('1', $updatedProduct['status']);
60+
61+
// Steps 15-16: Verify downloadable product links are preserved
62+
$this->verifyDownloadableLinksPreserved($originalLinks);
63+
}
64+
65+
/**
66+
* Generate Admin Access Token
67+
*/
68+
private function generateAdminAccessToken(): string
69+
{
70+
$serviceInfo = [
71+
'rest' => [
72+
'resourcePath' => self::ADMIN_TOKEN_RESOURCE_PATH,
73+
'httpMethod' => Request::HTTP_METHOD_POST,
74+
],
75+
];
76+
77+
$requestData = [
78+
'username' => 'webapi_user',
79+
'password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD,
80+
];
81+
82+
$accessToken = $this->_webApiCall($serviceInfo, $requestData);
83+
84+
$this->assertNotEmpty($accessToken, 'Admin access token should be generated');
85+
$this->assertIsString($accessToken, 'Access token should be a string');
86+
87+
return $accessToken;
88+
}
89+
90+
/**
91+
* Update Product Stock Item
92+
*/
93+
private function updateProductStockItem(string $adminToken): array
94+
{
95+
$serviceInfo = [
96+
'rest' => [
97+
'resourcePath' => self::PRODUCT_RESOURCE_PATH . '/' . self::TEST_PRODUCT_SKU,
98+
'httpMethod' => Request::HTTP_METHOD_PUT,
99+
'token' => $adminToken,
100+
],
101+
];
102+
103+
$productData = [
104+
'product' => [
105+
'sku' => self::TEST_PRODUCT_SKU,
106+
'status' => '1',
107+
'price' => '99.99',
108+
'type_id' => 'downloadable',
109+
'extension_attributes' => [
110+
'stock_item' => [
111+
'qty' => 1
112+
]
113+
]
114+
]
115+
];
116+
117+
return $this->_webApiCall($serviceInfo, $productData);
118+
}
119+
120+
/**
121+
* Verify Downloadable Links are Preserved
122+
*/
123+
private function verifyDownloadableLinksPreserved(array $originalLinks): void
124+
{
125+
$updatedProduct = $this->getProductBySku(self::TEST_PRODUCT_SKU);
126+
$this->verifyProductHasDownloadableLinks($updatedProduct, 'Updated product should preserve downloadable links');
127+
128+
$preservedLinks = $updatedProduct['extension_attributes']['downloadable_product_links'];
129+
130+
$this->assertCount(
131+
count($originalLinks),
132+
$preservedLinks,
133+
'Number of downloadable links should be preserved after stock_item update'
134+
);
135+
136+
foreach ($preservedLinks as $link) {
137+
$this->assertArrayHasKey('id', $link, 'Link should have an ID');
138+
$this->assertArrayHasKey('title', $link, 'Link should have a title');
139+
$this->assertArrayHasKey('price', $link, 'Link should have a price');
140+
$this->assertArrayHasKey('sort_order', $link, 'Link should have a sort order');
141+
}
142+
143+
$this->assertGreaterThan(0, count($preservedLinks), 'Should have at least one downloadable link preserved');
144+
145+
$linkTitles = array_column($preservedLinks, 'title');
146+
$this->assertContains('Downloadable Product Link', $linkTitles, 'Downloadable product link should be preserved');
147+
}
148+
149+
/**
150+
* Verify product has downloadable links
151+
*/
152+
private function verifyProductHasDownloadableLinks(array $product, string $message): void
153+
{
154+
$this->assertArrayHasKey('extension_attributes', $product, $message . ' - missing extension_attributes');
155+
$this->assertArrayHasKey(
156+
'downloadable_product_links',
157+
$product['extension_attributes'],
158+
$message . ' - missing downloadable_product_links'
159+
);
160+
$this->assertNotEmpty(
161+
$product['extension_attributes']['downloadable_product_links'],
162+
$message . ' - downloadable_product_links should not be empty'
163+
);
164+
}
165+
166+
/**
167+
* Get product by SKU
168+
*/
169+
private function getProductBySku(string $sku): array
170+
{
171+
$serviceInfo = [
172+
'rest' => [
173+
'resourcePath' => self::PRODUCT_RESOURCE_PATH . '/' . $sku,
174+
'httpMethod' => Request::HTTP_METHOD_GET,
175+
],
176+
];
177+
178+
return $this->_webApiCall($serviceInfo, []);
179+
}
180+
181+
/**
182+
* Test Steps 1-7: Admin Token Generation
183+
*
184+
* @magentoApiDataFixture Magento/Webapi/_files/webapi_user.php
185+
*/
186+
public function testSteps1Through7AdminTokenGeneration()
187+
{
188+
$token = $this->generateAdminAccessToken();
189+
$this->assertNotEmpty($token, 'Steps 1-7: Admin token should be generated successfully');
190+
}
191+
192+
/**
193+
* Test Steps 8-14: Product Stock Item Update
194+
*
195+
* @magentoApiDataFixture Magento/Webapi/_files/webapi_user.php
196+
* @magentoApiDataFixture Magento/Downloadable/_files/downloadable_product_with_files_and_sample_url.php
197+
*/
198+
public function testSteps8Through14ProductStockItemUpdate()
199+
{
200+
$token = $this->generateAdminAccessToken();
201+
$updatedProduct = $this->updateProductStockItem($token);
202+
203+
$this->assertNotEmpty($updatedProduct, 'Steps 8-14: Product should be updated successfully');
204+
$this->assertEquals('99.99', $updatedProduct['price'], 'Steps 8-14: Product price should be updated to 99.99');
205+
$this->assertEquals('1', $updatedProduct['status'], 'Steps 8-14: Product status should be enabled');
206+
}
207+
208+
/**
209+
* Test Steps 15-16: Downloadable Links Preservation
210+
*
211+
* @magentoApiDataFixture Magento/Webapi/_files/webapi_user.php
212+
* @magentoApiDataFixture Magento/Downloadable/_files/downloadable_product_with_files_and_sample_url.php
213+
*/
214+
public function testSteps15Through16DownloadableLinksPreservation()
215+
{
216+
$originalProduct = $this->getProductBySku(self::TEST_PRODUCT_SKU);
217+
$this->verifyProductHasDownloadableLinks($originalProduct, 'Original product should have downloadable links');
218+
$originalLinks = $originalProduct['extension_attributes']['downloadable_product_links'];
219+
220+
$token = $this->generateAdminAccessToken();
221+
$this->updateProductStockItem($token);
222+
223+
$this->verifyDownloadableLinksPreserved($originalLinks);
224+
}
225+
}

0 commit comments

Comments
 (0)