Skip to content

Commit 8865386

Browse files
MC-21715: Storefront: view product images
1 parent b169e62 commit 8865386

File tree

2 files changed

+641
-34
lines changed

2 files changed

+641
-34
lines changed
Lines changed: 363 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,363 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Catalog\Block\Product\View;
9+
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Catalog\Model\Product;
12+
use Magento\Catalog\Model\Product\Gallery\Processor;
13+
use Magento\Catalog\Model\ResourceModel\Product as ProductResource;
14+
use Magento\Framework\Serialize\Serializer\Json;
15+
use Magento\Framework\View\LayoutInterface;
16+
use Magento\Store\Api\StoreRepositoryInterface;
17+
use Magento\TestFramework\Helper\Bootstrap;
18+
use Magento\TestFramework\ObjectManager;
19+
20+
/**
21+
* Provide tests for displaying images on product page.
22+
*
23+
* @magentoAppArea frontend
24+
*/
25+
class GalleryTest extends \PHPUnit\Framework\TestCase
26+
{
27+
/**
28+
* @var ObjectManager
29+
*/
30+
private $objectManager;
31+
32+
/**
33+
* @var ProductRepositoryInterface
34+
*/
35+
private $productRepository;
36+
37+
/**
38+
* @var ProductResource
39+
*/
40+
private $productResource;
41+
42+
/**
43+
* @var StoreRepositoryInterface
44+
*/
45+
private $storeRepository;
46+
47+
/**
48+
* @var Processor
49+
*/
50+
private $galleryProcessor;
51+
52+
/**
53+
* @var Json
54+
*/
55+
private $serializer;
56+
57+
/**
58+
* @var Product
59+
*/
60+
private $product;
61+
62+
/**
63+
* @var Gallery
64+
*/
65+
private $block;
66+
67+
/**
68+
* @var array
69+
*/
70+
private $imageExpectation = [
71+
'thumb' => '/m/a/magento_image.jpg',
72+
'img' => '/m/a/magento_image.jpg',
73+
'full' => '/m/a/magento_image.jpg',
74+
'caption' => 'Image Alt Text',
75+
'position' => '1',
76+
'isMain' => false,
77+
'type' => 'image',
78+
'videoUrl' => null,
79+
];
80+
81+
/**
82+
* @var array
83+
*/
84+
private $thumbnailExpectation = [
85+
'thumb' => '/m/a/magento_thumbnail.jpg',
86+
'img' => '/m/a/magento_thumbnail.jpg',
87+
'full' => '/m/a/magento_thumbnail.jpg',
88+
'caption' => 'Thumbnail Image',
89+
'position' => '2',
90+
'isMain' => false,
91+
'type' => 'image',
92+
'videoUrl' => null,
93+
];
94+
95+
/**
96+
* @var array
97+
*/
98+
private $placeholderExpectation = [
99+
'thumb' => '/placeholder/thumbnail.jpg',
100+
'img' => '/placeholder/image.jpg',
101+
'full' => '/placeholder/image.jpg',
102+
'caption' => '',
103+
'position' => '0',
104+
'isMain' => true,
105+
'type' => 'image',
106+
'videoUrl' => null,
107+
];
108+
109+
/**
110+
* @inheritdoc
111+
*/
112+
protected function setUp()
113+
{
114+
$this->objectManager = Bootstrap::getObjectManager();
115+
$this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class);
116+
$this->productResource = $this->objectManager->get(ProductResource::class);
117+
$this->storeRepository = $this->objectManager->create(StoreRepositoryInterface::class);
118+
$this->galleryProcessor = $this->objectManager->create(Processor::class);
119+
$this->serializer = $this->objectManager->get(Json::class);
120+
$this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Gallery::class);
121+
}
122+
123+
/**
124+
* @magentoDataFixture Magento/Catalog/_files/product_simple.php
125+
* @magentoDbIsolation enabled
126+
* @return void
127+
*/
128+
public function testGetGalleryImagesJsonWithoutImages(): void
129+
{
130+
$this->block->setData('product', $this->getProduct());
131+
$result = $this->serializer->unserialize($this->block->getGalleryImagesJson());
132+
$this->assertImages(reset($result), $this->placeholderExpectation);
133+
}
134+
135+
/**
136+
* @dataProvider galleryDisabledImagesDataProvider
137+
* @magentoDataFixture Magento/Catalog/_files/product_with_multiple_images.php
138+
* @magentoDbIsolation enabled
139+
* @param array $images
140+
* @param array $expectation
141+
* @return void
142+
*/
143+
public function testGetGalleryImagesJsonWithDisabledImage(array $images, array $expectation): void
144+
{
145+
$product = $this->getProduct();
146+
$this->setGalleryImages($product, $images);
147+
$this->block->setData('product', $this->getProduct());
148+
$firstImage = $this->serializer->unserialize($this->block->getGalleryImagesJson());
149+
$this->assertImages(reset($firstImage), $expectation);
150+
}
151+
152+
153+
/**
154+
* @dataProvider galleryDisabledImagesDataProvider
155+
* @magentoDataFixture Magento/Catalog/_files/product_with_multiple_images.php
156+
* @magentoDataFixture Magento/Store/_files/second_store.php
157+
* @magentoDbIsolation enabled
158+
* @param array $images
159+
* @param array $expectation
160+
* @return void
161+
*/
162+
public function testGetGalleryImagesJsonOnStoreWithDisabledImage(array $images, array $expectation): void
163+
{
164+
$secondStoreId = (int)$this->storeRepository->get('fixture_second_store')->getId();
165+
$product = $this->getProduct($secondStoreId);
166+
$this->setGalleryImages($product, $images);
167+
$this->block->setData('product', $this->getProduct($secondStoreId));
168+
$firstImage = $this->serializer->unserialize($this->block->getGalleryImagesJson());
169+
$this->assertImages(reset($firstImage), $expectation);
170+
}
171+
172+
/**
173+
* @return array
174+
*/
175+
public function galleryDisabledImagesDataProvider(): array
176+
{
177+
return [
178+
[
179+
'images' => [
180+
'/m/a/magento_image.jpg' => ['disabled' => true],
181+
'/m/a/magento_thumbnail.jpg' => [],
182+
],
183+
'expectation' => $this->thumbnailExpectation,
184+
],
185+
];
186+
}
187+
188+
/**
189+
* @dataProvider galleryImagesDataProvider
190+
* @magentoDataFixture Magento/Catalog/_files/product_with_multiple_images.php
191+
* @magentoDbIsolation enabled
192+
* @param array $images
193+
* @param array $expectation
194+
* @return void
195+
*/
196+
public function testGetGalleryImagesJson(array $images, array $expectation): void
197+
{
198+
$product = $this->getProduct();
199+
$this->setGalleryImages($product, $images);
200+
$this->block->setData('product', $this->getProduct());
201+
[$firstImage, $secondImage] = $this->serializer->unserialize($this->block->getGalleryImagesJson());
202+
[$firstExpectedImage, $secondExpectedImage] = $expectation;
203+
$this->assertImages($firstImage, $firstExpectedImage);
204+
$this->assertImages($secondImage, $secondExpectedImage);
205+
}
206+
207+
/**
208+
* @return array
209+
*/
210+
public function galleryImagesDataProvider(): array
211+
{
212+
return [
213+
'with_main_image' => [
214+
'images' => [
215+
'/m/a/magento_image.jpg' => [],
216+
'/m/a/magento_thumbnail.jpg' => ['main' => true],
217+
],
218+
'expectation' => [
219+
$this->imageExpectation,
220+
array_merge($this->thumbnailExpectation, ['isMain' => true]),
221+
],
222+
],
223+
'without_main_image' => [
224+
'images' => [
225+
'/m/a/magento_image.jpg' => [],
226+
'/m/a/magento_thumbnail.jpg' => [],
227+
],
228+
'expectation' => [
229+
array_merge($this->imageExpectation, ['isMain' => true]),
230+
$this->thumbnailExpectation,
231+
],
232+
],
233+
'with_changed_position' => [
234+
'images' => [
235+
'/m/a/magento_image.jpg' => ['position' => '2'],
236+
'/m/a/magento_thumbnail.jpg' => ['position' => '1'],
237+
],
238+
'expectation' => [
239+
array_merge($this->thumbnailExpectation, ['position' => '1']),
240+
array_merge($this->imageExpectation, ['position' => '2', 'isMain' => true]),
241+
],
242+
],
243+
];
244+
}
245+
246+
/**
247+
* @dataProvider galleryImagesOnStoreViewDataProvider
248+
* @magentoDataFixture Magento/Catalog/_files/product_with_multiple_images.php
249+
* @magentoDataFixture Magento/Store/_files/second_store.php
250+
* @magentoDbIsolation enabled
251+
* @param array $images
252+
* @param array $expectation
253+
* @return void
254+
*/
255+
public function testGetGalleryImagesJsonOnStoreView(array $images, array $expectation): void
256+
{
257+
$secondStoreId = (int)$this->storeRepository->get('fixture_second_store')->getId();
258+
$product = $this->getProduct($secondStoreId);
259+
$this->setGalleryImages($product, $images);
260+
$this->block->setData('product', $this->getProduct($secondStoreId));
261+
[$firstImage, $secondImage] = $this->serializer->unserialize($this->block->getGalleryImagesJson());
262+
[$firstExpectedImage, $secondExpectedImage] = $expectation;
263+
$this->assertImages($firstImage, $firstExpectedImage);
264+
$this->assertImages($secondImage, $secondExpectedImage);
265+
}
266+
267+
/**
268+
* @return array
269+
*/
270+
public function galleryImagesOnStoreViewDataProvider(): array
271+
{
272+
return [
273+
'with_store_labels' => [
274+
'images' => [
275+
'/m/a/magento_image.jpg' => ['label' => 'Some store label'],
276+
'/m/a/magento_thumbnail.jpg' => [],
277+
],
278+
'expectation' => [
279+
array_merge($this->imageExpectation, ['isMain' => true, 'caption' => 'Some store label']),
280+
$this->thumbnailExpectation,
281+
],
282+
],
283+
'with_changed_position' => [
284+
'images' => [
285+
'/m/a/magento_image.jpg' => ['position' => '3'],
286+
'/m/a/magento_thumbnail.jpg' => [],
287+
],
288+
'expectation' => [
289+
array_merge($this->thumbnailExpectation, ['position' => '2']),
290+
array_merge($this->imageExpectation, ['position' => '3', 'isMain' => true]),
291+
],
292+
],
293+
'with_main_store_image' => [
294+
'images' => [
295+
'/m/a/magento_image.jpg' => [],
296+
'/m/a/magento_thumbnail.jpg' => ['main' => true],
297+
],
298+
'expectation' => [
299+
$this->imageExpectation,
300+
array_merge($this->thumbnailExpectation, ['isMain' => true]),
301+
],
302+
],
303+
];
304+
}
305+
306+
/**
307+
* Updates product gallery images and saves product.
308+
*
309+
* @param Product $product
310+
* @param array $images
311+
* @param int|null $storeId
312+
* @return void
313+
*/
314+
private function setGalleryImages(Product $product, array $images, int $storeId = null): void
315+
{
316+
$product->setImage(null);
317+
foreach ($images as $file => $data) {
318+
if (!empty($data)) {
319+
$this->galleryProcessor->updateImage($product, $file, $data);
320+
}
321+
322+
if (!empty($data['main'])) {
323+
$product->setImage($file);
324+
}
325+
}
326+
327+
if ($storeId) {
328+
$product->setStoreId($storeId);
329+
}
330+
331+
$this->productResource->save($product);
332+
}
333+
334+
/**
335+
* Returns current product.
336+
*
337+
* @param int|null $storeId
338+
* @return Product
339+
*/
340+
private function getProduct(int $storeId = null): Product
341+
{
342+
return $this->product = $this->productRepository->get('simple', false, $storeId, true);
343+
}
344+
345+
/**
346+
* Asserts gallery image data.
347+
*
348+
* @param array $image
349+
* @param array $expectedImage
350+
* @return void
351+
*/
352+
private function assertImages(array $image, array $expectedImage): void
353+
{
354+
$this->assertStringEndsWith($expectedImage['thumb'], $image['thumb']);
355+
$this->assertStringEndsWith($expectedImage['img'], $image['img']);
356+
$this->assertStringEndsWith($expectedImage['full'], $image['full']);
357+
$this->assertEquals($expectedImage['caption'], $image['caption']);
358+
$this->assertEquals($expectedImage['position'], $image['position']);
359+
$this->assertEquals($expectedImage['isMain'], $image['isMain']);
360+
$this->assertEquals($expectedImage['type'], $image['type']);
361+
$this->assertEquals($expectedImage['videoUrl'], $image['videoUrl']);
362+
}
363+
}

0 commit comments

Comments
 (0)