7
7
8
8
namespace Magento \GraphQl \Catalog \ResolverCache ;
9
9
10
+ use Magento \Catalog \Api \Data \ProductInterface ;
11
+ use Magento \Catalog \Api \ProductManagementInterface ;
10
12
use Magento \Catalog \Api \ProductRepositoryInterface ;
13
+ use Magento \Catalog \Controller \Adminhtml \Product \Save as AdminProductSaveController ;
11
14
use Magento \Catalog \Model \Product \Gallery \GalleryManagement ;
15
+ use Magento \Catalog \Test \Fixture \Product as ProductFixture ;
12
16
use Magento \CatalogGraphQl \Model \Resolver \Cache \Product \MediaGallery \ResolverCacheIdentity ;
13
17
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 ;
15
21
use Magento \Framework \ObjectManagerInterface ;
16
22
use Magento \GraphQlResolverCache \Model \Resolver \Result \CacheKey \Calculator \ProviderInterface ;
17
23
use Magento \GraphQlResolverCache \Model \Resolver \Result \Type as GraphQlResolverCache ;
24
+ use Magento \TestFramework \Fixture \DataFixture ;
18
25
use Magento \TestFramework \Helper \Bootstrap ;
19
26
use Magento \TestFramework \TestCase \GraphQl \ResolverCacheAbstract ;
20
27
@@ -47,7 +54,87 @@ protected function setUp(): void
47
54
parent ::setUp ();
48
55
}
49
56
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
+
50
131
/**
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
+ *
51
138
* @magentoDbIsolation disabled
52
139
* @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_media_gallery_entries.php
53
140
* @magentoApiDataFixture Magento/Catalog/_files/product_with_media_gallery.php
@@ -58,25 +145,26 @@ protected function setUp(): void
58
145
public function testMediaGalleryForProductVideos (callable $ actionMechanismCallable , bool $ isInvalidationAction )
59
146
{
60
147
// 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
+
63
150
// 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 );
66
153
$ this ->assertNotEmpty ($ simpleProductWithMediaQueryResponse ['products ' ]['items ' ][0 ]['media_gallery ' ]);
154
+
155
+ // Assert Media Gallery Resolver cache record exists after querying the product's media gallery
67
156
$ this ->assertMediaGalleryResolverCacheRecordExists ($ simpleProductWithMedia );
68
157
69
158
// Test simple product
70
- $ productSku = 'simple ' ;
71
- $ product = $ this ->productRepository ->get ($ productSku );
159
+ $ product = $ this ->productRepository ->get ('simple ' );
72
160
$ this ->assertMediaGalleryResolverCacheRecordDoesNotExist ($ product );
73
- $ simpleProductQuerry = $ this ->getQuery ( $ productSku );
74
- $ response = $ this ->graphQlQuery ($ simpleProductQuerry );
161
+ $ simpleProductQuery = $ this ->getProductWithMediaGalleryQuery ( $ product );
162
+ $ response = $ this ->graphQlQuery ($ simpleProductQuery );
75
163
$ this ->assertNotEmpty ($ response ['products ' ]['items ' ][0 ]['media_gallery ' ]);
76
164
$ this ->assertMediaGalleryResolverCacheRecordExists ($ product );
77
165
78
166
// Query simple product the 2nd time
79
- $ response2 = $ this ->graphQlQuery ($ simpleProductQuerry );
167
+ $ response2 = $ this ->graphQlQuery ($ simpleProductQuery );
80
168
$ this ->assertEquals ($ response , $ response2 );
81
169
82
170
// change product media gallery data
@@ -94,23 +182,28 @@ public function testMediaGalleryForProductVideos(callable $actionMechanismCallab
94
182
$ this ->assertMediaGalleryResolverCacheRecordExists ($ simpleProductWithMedia );
95
183
96
184
// Query simple product the 3rd time
97
- $ response3 = $ this ->graphQlQuery ($ simpleProductQuerry );
185
+ $ response3 = $ this ->graphQlQuery ($ simpleProductQuery );
186
+
98
187
if ($ isInvalidationAction ) {
99
- // response is updated.
188
+ // assert response is updated
100
189
$ this ->assertNotEquals ($ response , $ response3 );
101
190
} else {
102
- // response is not changed
191
+ // assert response is the same
103
192
$ this ->assertEquals ($ response , $ response3 );
104
193
}
105
194
}
106
195
107
196
public function actionMechanismProvider (): array
108
197
{
109
198
// provider is invoked before setUp() is called so need to init here
199
+ $ objectManager = Bootstrap::getObjectManager ();
200
+
110
201
/** @var GalleryManagement $galleryManagement */
111
- $ galleryManagement = Bootstrap::getObjectManager ()->get (GalleryManagement::class);
202
+ $ galleryManagement = $ objectManager ->get (GalleryManagement::class);
203
+
112
204
/** @var ProductRepositoryInterface $productRepository */
113
- $ productRepository = Bootstrap::getObjectManager ()->get (ProductRepositoryInterface::class);
205
+ $ productRepository = $ objectManager ->get (ProductRepositoryInterface::class);
206
+
114
207
return [
115
208
'update media label ' => [
116
209
function (ProductInterface $ product ) use ($ galleryManagement ) {
@@ -144,7 +237,7 @@ function (ProductInterface $product) use ($productRepository) {
144
237
}
145
238
146
239
/**
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.
148
241
*
149
242
* @magentoDbIsolation disabled
150
243
* @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_media_gallery_entries.php
@@ -153,31 +246,31 @@ function (ProductInterface $product) use ($productRepository) {
153
246
public function testMediaGalleryResolverCacheKeyAndTags ()
154
247
{
155
248
// Test simple product
156
- $ simpleProductSku = 'simple ' ;
249
+ $ simpleProduct = $ this -> productRepository -> get ( 'simple ' ) ;
157
250
// Query the simple product
158
- $ simpleProductQuery = $ this ->getQuery ( $ simpleProductSku );
251
+ $ simpleProductQuery = $ this ->getProductWithMediaGalleryQuery ( $ simpleProduct );
159
252
$ simpleProductQueryResponse = $ this ->graphQlQuery ($ simpleProductQuery );
160
253
// Query the simple product again
161
254
$ simpleProductQueryResponse2 = $ this ->graphQlQuery ($ simpleProductQuery );
162
255
$ this ->assertEquals ($ simpleProductQueryResponse , $ simpleProductQueryResponse2 );
163
256
164
- $ simpleProduct = $ this ->productRepository ->get ($ simpleProductSku );
165
257
$ simpleProductCacheKey = $ this ->getCacheKeyForMediaGalleryResolver ($ simpleProduct );
166
258
$ simpleProductCacheTags = $ this ->getCacheTagsUsedInMediaGalleryResolverCache ($ simpleProductCacheKey );
259
+
167
260
// Verify cache tags are generated correctly for the simple product
168
261
$ this ->assertEquals (
169
262
$ this ->getExpectedCacheTags ($ simpleProduct ),
170
263
$ simpleProductCacheTags
171
264
);
172
265
173
266
// Test simple product with media
174
- $ simpleProductWithMediaSku = 'simple_product_with_media ' ;
267
+ $ simpleProductWithMedia = $ this ->productRepository ->get ('simple_product_with_media ' );
268
+
175
269
// Query the simple product with media
176
- $ simpleProductWithMediaQuery = $ this ->getQuery ( $ simpleProductWithMediaSku );
270
+ $ simpleProductWithMediaQuery = $ this ->getProductWithMediaGalleryQuery ( $ simpleProductWithMedia );
177
271
$ simpleProductWithMediaQueryResponse =$ this ->graphQlQuery ($ simpleProductWithMediaQuery );
178
272
$ this ->assertNotEquals ($ simpleProductQueryResponse , $ simpleProductWithMediaQueryResponse );
179
273
180
- $ simpleProductWithMedia = $ this ->productRepository ->get ($ simpleProductWithMediaSku );
181
274
$ simpleProductWithMediaCacheKey = $ this ->getCacheKeyForMediaGalleryResolver ($ simpleProductWithMedia );
182
275
$ simpleProductWithMediaCacheTags = $ this ->getCacheTagsUsedInMediaGalleryResolverCache (
183
276
$ simpleProductWithMediaCacheKey
@@ -196,7 +289,7 @@ public function testMediaGalleryResolverCacheKeyAndTags()
196
289
}
197
290
198
291
/**
199
- * Assert that cache record exists.
292
+ * Assert that media gallery cache record exists for the $product .
200
293
*
201
294
* @param ProductInterface $product
202
295
* @return void
@@ -214,7 +307,7 @@ private function assertMediaGalleryResolverCacheRecordExists(ProductInterface $p
214
307
}
215
308
216
309
/**
217
- * Assert that cache record does not exist.
310
+ * Assert that media gallery cache record does not exist for the $product .
218
311
*
219
312
* @param ProductInterface $product
220
313
* @return void
@@ -228,7 +321,7 @@ private function assertMediaGalleryResolverCacheRecordDoesNotExist(ProductInterf
228
321
}
229
322
230
323
/**
231
- * Get the expected cache tags.
324
+ * Get the expected media gallery cache tags based on the $product .
232
325
*
233
326
* @param ProductInterface $product
234
327
* @return array
@@ -258,7 +351,7 @@ private function getCacheTagsUsedInMediaGalleryResolverCache(string $cacheKey):
258
351
}
259
352
260
353
/**
261
- * Get cache key for media gallery resolver
354
+ * Get cache key for media gallery resolver based on the $product
262
355
*
263
356
* @param ProductInterface $product
264
357
* @return string
@@ -289,16 +382,16 @@ private function getCacheKeyForMediaGalleryResolver(ProductInterface $product):
289
382
}
290
383
291
384
/**
292
- * Get query
385
+ * Compile GraphQL query for getting product data with media gallery
293
386
*
294
- * @param string $productSku
387
+ * @param ProductInterface $product
295
388
* @return string
296
389
*/
297
- private function getQuery ( string $ productSku ): string
390
+ private function getProductWithMediaGalleryQuery ( ProductInterface $ product ): string
298
391
{
299
392
return <<<QUERY
300
393
{
301
- products(filter: {sku: {eq: " {$ productSku }"}}) {
394
+ products(filter: {sku: {eq: " {$ product -> getSku () }"}}) {
302
395
items {
303
396
small_image {
304
397
url
0 commit comments