Skip to content

Commit 2aeaf65

Browse files
committed
B2B-2677: [MediaGallery]Implement data caching for GraphQL results on resolver level
- Add test which saves product via admin product controller
1 parent 8494f1b commit 2aeaf65

File tree

1 file changed

+123
-30
lines changed

1 file changed

+123
-30
lines changed

dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ResolverCache/MediaGalleryTest.php

Lines changed: 123 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,21 @@
77

88
namespace Magento\GraphQl\Catalog\ResolverCache;
99

10+
use Magento\Catalog\Api\Data\ProductInterface;
11+
use Magento\Catalog\Api\ProductManagementInterface;
1012
use Magento\Catalog\Api\ProductRepositoryInterface;
13+
use Magento\Catalog\Controller\Adminhtml\Product\Save as AdminProductSaveController;
1114
use Magento\Catalog\Model\Product\Gallery\GalleryManagement;
15+
use Magento\Catalog\Test\Fixture\Product as ProductFixture;
1216
use Magento\CatalogGraphQl\Model\Resolver\Cache\Product\MediaGallery\ResolverCacheIdentity;
1317
use Magento\CatalogGraphQl\Model\Resolver\Product\MediaGallery;
14-
use Magento\Catalog\Api\Data\ProductInterface;
18+
use Magento\Framework\App\Area as AppArea;
19+
use Magento\Framework\App\ObjectManager\ConfigLoader;
20+
use Magento\Framework\App\State as AppState;
1521
use Magento\Framework\ObjectManagerInterface;
1622
use Magento\GraphQlResolverCache\Model\Resolver\Result\CacheKey\Calculator\ProviderInterface;
1723
use Magento\GraphQlResolverCache\Model\Resolver\Result\Type as GraphQlResolverCache;
24+
use Magento\TestFramework\Fixture\DataFixture;
1825
use Magento\TestFramework\Helper\Bootstrap;
1926
use Magento\TestFramework\TestCase\GraphQl\ResolverCacheAbstract;
2027

@@ -47,7 +54,87 @@ protected function setUp(): void
4754
parent::setUp();
4855
}
4956

57+
#[
58+
DataFixture(ProductFixture::class, ['sku' => 'product1', 'media_gallery_entries' => [[]]], as: 'product'),
59+
]
60+
public function testSavingProductInAdminWithoutChangesDoesNotInvalidateResolverCache()
61+
{
62+
$product = $this->productRepository->get('product1');
63+
64+
// Assert Media Gallery Resolver cache record does not exist before querying the product's media gallery
65+
$this->assertMediaGalleryResolverCacheRecordDoesNotExist($product);
66+
67+
$query = $this->getProductWithMediaGalleryQuery($product);
68+
$response = $this->graphQlQuery($query);
69+
70+
$this->assertNotEmpty($response['products']['items'][0]['media_gallery']);
71+
72+
// Assert Media Gallery Resolver cache record exists after querying the product's media gallery
73+
$this->assertMediaGalleryResolverCacheRecordExists($product);
74+
75+
// Save product in admin without changes
76+
$productManagement = $this->objectManager->create(ProductManagementInterface::class);
77+
78+
// get count of products
79+
$originalProductCount = $productManagement->getCount();
80+
$this->assertGreaterThan(0, $originalProductCount);
81+
82+
// emulate admin area
83+
Bootstrap::getInstance()->loadArea(AppArea::AREA_ADMINHTML);
84+
$this->objectManager->get(AppState::class)->setAreaCode(AppArea::AREA_ADMINHTML);
85+
$configLoader = $this->objectManager->get(ConfigLoader::class);
86+
$this->objectManager->configure($configLoader->load(AppArea::AREA_ADMINHTML));
87+
88+
$context = $this->objectManager->create(\Magento\Backend\App\Action\Context::class);
89+
90+
// overwrite $context's messageManager
91+
$messageManager = $this->getMockBuilder(\Magento\Framework\Message\ManagerInterface::class)
92+
->enableProxyingToOriginalMethods()
93+
->getMockForAbstractClass();
94+
95+
$reflectionClass = new \ReflectionClass($context);
96+
$reflectionProperty = $reflectionClass->getProperty('messageManager');
97+
$reflectionProperty->setAccessible(true);
98+
$reflectionProperty->setValue($context, $messageManager);
99+
100+
/** @var AdminProductSaveController $adminProductSaveController */
101+
$adminProductSaveController = $this->objectManager->create(AdminProductSaveController::class, [
102+
'context' => $context,
103+
]);
104+
105+
$productData = $product->getData();
106+
unset($productData['entity_id']);
107+
108+
$adminProductSaveController->getRequest()->setPostValue([
109+
'id' => $product->getId(),
110+
'product' => $productData,
111+
'set' => 4, // attribute set id
112+
'type' => 'simple',
113+
]);
114+
115+
$messageManager->expects($this->never())->method('addErrorMessage');
116+
$messageManager->expects($this->never())->method('addExceptionMessage');
117+
$messageManager->expects($this->atLeastOnce())->method('addSuccessMessage');
118+
119+
$adminProductSaveController->execute();
120+
121+
// assert that product count is the same (i.e. product was not created, but "updated")
122+
$this->assertEquals(
123+
$originalProductCount,
124+
$productManagement->getCount(),
125+
);
126+
127+
// Assert Media Gallery Resolver cache record exists after saving the product in admin without changes
128+
$this->assertMediaGalleryResolverCacheRecordExists($product);
129+
}
130+
50131
/**
132+
* - product_simple_with_media_gallery_entries.php creates product with "simple" sku containing
133+
* link to 1 external YouTube video using an image placeholder in gallery
134+
*
135+
* - product_with_media_gallery.php creates product with "simple_product_with_media product" SKU
136+
* containing 1 image in gallery
137+
*
51138
* @magentoDbIsolation disabled
52139
* @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_media_gallery_entries.php
53140
* @magentoApiDataFixture Magento/Catalog/_files/product_with_media_gallery.php
@@ -58,25 +145,26 @@ protected function setUp(): void
58145
public function testMediaGalleryForProductVideos(callable $actionMechanismCallable, bool $isInvalidationAction)
59146
{
60147
// Test simple product with media
61-
$simpleProductWithMediaSku = 'simple_product_with_media';
62-
$simpleProductWithMedia = $this->productRepository->get($simpleProductWithMediaSku);
148+
$simpleProductWithMedia = $this->productRepository->get('simple_product_with_media');
149+
63150
// Query the simple product with media
64-
$simpleProductWithMediaQuery = $this->getQuery($simpleProductWithMediaSku);
65-
$simpleProductWithMediaQueryResponse =$this->graphQlQuery($simpleProductWithMediaQuery);
151+
$simpleProductWithMediaQuery = $this->getProductWithMediaGalleryQuery($simpleProductWithMedia);
152+
$simpleProductWithMediaQueryResponse = $this->graphQlQuery($simpleProductWithMediaQuery);
66153
$this->assertNotEmpty($simpleProductWithMediaQueryResponse['products']['items'][0]['media_gallery']);
154+
155+
// Assert Media Gallery Resolver cache record exists after querying the product's media gallery
67156
$this->assertMediaGalleryResolverCacheRecordExists($simpleProductWithMedia);
68157

69158
// Test simple product
70-
$productSku = 'simple';
71-
$product = $this->productRepository->get($productSku);
159+
$product = $this->productRepository->get('simple');
72160
$this->assertMediaGalleryResolverCacheRecordDoesNotExist($product);
73-
$simpleProductQuerry = $this->getQuery($productSku);
74-
$response = $this->graphQlQuery($simpleProductQuerry);
161+
$simpleProductQuery = $this->getProductWithMediaGalleryQuery($product);
162+
$response = $this->graphQlQuery($simpleProductQuery);
75163
$this->assertNotEmpty($response['products']['items'][0]['media_gallery']);
76164
$this->assertMediaGalleryResolverCacheRecordExists($product);
77165

78166
// Query simple product the 2nd time
79-
$response2 = $this->graphQlQuery($simpleProductQuerry);
167+
$response2 = $this->graphQlQuery($simpleProductQuery);
80168
$this->assertEquals($response, $response2);
81169

82170
// change product media gallery data
@@ -94,23 +182,28 @@ public function testMediaGalleryForProductVideos(callable $actionMechanismCallab
94182
$this->assertMediaGalleryResolverCacheRecordExists($simpleProductWithMedia);
95183

96184
// Query simple product the 3rd time
97-
$response3 = $this->graphQlQuery($simpleProductQuerry);
185+
$response3 = $this->graphQlQuery($simpleProductQuery);
186+
98187
if ($isInvalidationAction) {
99-
// response is updated.
188+
// assert response is updated
100189
$this->assertNotEquals($response, $response3);
101190
} else {
102-
// response is not changed
191+
// assert response is the same
103192
$this->assertEquals($response, $response3);
104193
}
105194
}
106195

107196
public function actionMechanismProvider(): array
108197
{
109198
// provider is invoked before setUp() is called so need to init here
199+
$objectManager = Bootstrap::getObjectManager();
200+
110201
/** @var GalleryManagement $galleryManagement */
111-
$galleryManagement = Bootstrap::getObjectManager()->get(GalleryManagement::class);
202+
$galleryManagement = $objectManager->get(GalleryManagement::class);
203+
112204
/** @var ProductRepositoryInterface $productRepository */
113-
$productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class);
205+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
206+
114207
return [
115208
'update media label' => [
116209
function (ProductInterface $product) use ($galleryManagement) {
@@ -144,7 +237,7 @@ function (ProductInterface $product) use ($productRepository) {
144237
}
145238

146239
/**
147-
* Media gallery resolver cache tags and cache key vary when query different product.
240+
* Assert that media gallery resolver cache tags and cache key vary when querying a different product.
148241
*
149242
* @magentoDbIsolation disabled
150243
* @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_media_gallery_entries.php
@@ -153,31 +246,31 @@ function (ProductInterface $product) use ($productRepository) {
153246
public function testMediaGalleryResolverCacheKeyAndTags()
154247
{
155248
// Test simple product
156-
$simpleProductSku = 'simple';
249+
$simpleProduct = $this->productRepository->get('simple');
157250
// Query the simple product
158-
$simpleProductQuery = $this->getQuery($simpleProductSku);
251+
$simpleProductQuery = $this->getProductWithMediaGalleryQuery($simpleProduct);
159252
$simpleProductQueryResponse = $this->graphQlQuery($simpleProductQuery);
160253
// Query the simple product again
161254
$simpleProductQueryResponse2 = $this->graphQlQuery($simpleProductQuery);
162255
$this->assertEquals($simpleProductQueryResponse, $simpleProductQueryResponse2);
163256

164-
$simpleProduct = $this->productRepository->get($simpleProductSku);
165257
$simpleProductCacheKey = $this->getCacheKeyForMediaGalleryResolver($simpleProduct);
166258
$simpleProductCacheTags = $this->getCacheTagsUsedInMediaGalleryResolverCache($simpleProductCacheKey);
259+
167260
// Verify cache tags are generated correctly for the simple product
168261
$this->assertEquals(
169262
$this->getExpectedCacheTags($simpleProduct),
170263
$simpleProductCacheTags
171264
);
172265

173266
// Test simple product with media
174-
$simpleProductWithMediaSku = 'simple_product_with_media';
267+
$simpleProductWithMedia = $this->productRepository->get('simple_product_with_media');
268+
175269
// Query the simple product with media
176-
$simpleProductWithMediaQuery = $this->getQuery($simpleProductWithMediaSku);
270+
$simpleProductWithMediaQuery = $this->getProductWithMediaGalleryQuery($simpleProductWithMedia);
177271
$simpleProductWithMediaQueryResponse =$this->graphQlQuery($simpleProductWithMediaQuery);
178272
$this->assertNotEquals($simpleProductQueryResponse, $simpleProductWithMediaQueryResponse);
179273

180-
$simpleProductWithMedia = $this->productRepository->get($simpleProductWithMediaSku);
181274
$simpleProductWithMediaCacheKey = $this->getCacheKeyForMediaGalleryResolver($simpleProductWithMedia);
182275
$simpleProductWithMediaCacheTags = $this->getCacheTagsUsedInMediaGalleryResolverCache(
183276
$simpleProductWithMediaCacheKey
@@ -196,7 +289,7 @@ public function testMediaGalleryResolverCacheKeyAndTags()
196289
}
197290

198291
/**
199-
* Assert that cache record exists.
292+
* Assert that media gallery cache record exists for the $product.
200293
*
201294
* @param ProductInterface $product
202295
* @return void
@@ -214,7 +307,7 @@ private function assertMediaGalleryResolverCacheRecordExists(ProductInterface $p
214307
}
215308

216309
/**
217-
* Assert that cache record does not exist.
310+
* Assert that media gallery cache record does not exist for the $product.
218311
*
219312
* @param ProductInterface $product
220313
* @return void
@@ -228,7 +321,7 @@ private function assertMediaGalleryResolverCacheRecordDoesNotExist(ProductInterf
228321
}
229322

230323
/**
231-
* Get the expected cache tags.
324+
* Get the expected media gallery cache tags based on the $product.
232325
*
233326
* @param ProductInterface $product
234327
* @return array
@@ -258,7 +351,7 @@ private function getCacheTagsUsedInMediaGalleryResolverCache(string $cacheKey):
258351
}
259352

260353
/**
261-
* Get cache key for media gallery resolver
354+
* Get cache key for media gallery resolver based on the $product
262355
*
263356
* @param ProductInterface $product
264357
* @return string
@@ -289,16 +382,16 @@ private function getCacheKeyForMediaGalleryResolver(ProductInterface $product):
289382
}
290383

291384
/**
292-
* Get query
385+
* Compile GraphQL query for getting product data with media gallery
293386
*
294-
* @param string $productSku
387+
* @param ProductInterface $product
295388
* @return string
296389
*/
297-
private function getQuery(string $productSku): string
390+
private function getProductWithMediaGalleryQuery(ProductInterface $product): string
298391
{
299392
return <<<QUERY
300393
{
301-
products(filter: {sku: {eq: "{$productSku}"}}) {
394+
products(filter: {sku: {eq: "{$product->getSku()}"}}) {
302395
items {
303396
small_image {
304397
url

0 commit comments

Comments
 (0)