PageRenderTime 45ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/web/core/tests/Drupal/Tests/Core/Image/ImageTest.php

https://gitlab.com/mohamed_hussein/prodt
PHP | 482 lines | 323 code | 52 blank | 107 comment | 0 complexity | efd1715b426cf422180e23bef4c23558 MD5 | raw file
  1. <?php
  2. namespace Drupal\Tests\Core\Image;
  3. use Drupal\Core\File\FileSystemInterface;
  4. use Drupal\Core\Image\Image;
  5. use Drupal\Core\ImageToolkit\ImageToolkitInterface;
  6. use Drupal\Tests\UnitTestCase;
  7. /**
  8. * Tests the image class.
  9. *
  10. * @requires extension gd
  11. * @group Image
  12. */
  13. class ImageTest extends UnitTestCase {
  14. /**
  15. * Image source path.
  16. *
  17. * @var string
  18. */
  19. protected $source;
  20. /**
  21. * Image object.
  22. *
  23. * @var \Drupal\Core\Image\Image
  24. */
  25. protected $image;
  26. /**
  27. * Mocked image toolkit.
  28. *
  29. * @var \Drupal\Core\ImageToolkit\ImageToolkitInterface
  30. */
  31. protected $toolkit;
  32. /**
  33. * Mocked image toolkit operation.
  34. *
  35. * @var \Drupal\Core\ImageToolkit\ImageToolkitOperationInterface
  36. */
  37. protected $toolkitOperation;
  38. /**
  39. * {@inheritdoc}
  40. */
  41. protected function setUp(): void {
  42. // Use the Druplicon image.
  43. $this->source = __DIR__ . '/../../../../../misc/druplicon.png';
  44. }
  45. /**
  46. * Mocks a toolkit.
  47. *
  48. * @param array $stubs
  49. * (optional) Array containing methods to be replaced with stubs.
  50. *
  51. * @return \PHPUnit\Framework\MockObject\MockObject
  52. */
  53. protected function getToolkitMock(array $stubs = []) {
  54. $mock_builder = $this->getMockBuilder('Drupal\system\Plugin\ImageToolkit\GDToolkit');
  55. $stubs = array_merge(['getPluginId', 'save'], $stubs);
  56. return $mock_builder
  57. ->disableOriginalConstructor()
  58. ->onlyMethods($stubs)
  59. ->getMock();
  60. }
  61. /**
  62. * Mocks a toolkit operation.
  63. *
  64. * @param string $class_name
  65. * The name of the GD toolkit operation class to be mocked.
  66. * @param \Drupal\Core\Image\ImageToolkitInterface $toolkit
  67. * The image toolkit object.
  68. *
  69. * @return \PHPUnit\Framework\MockObject\MockObject
  70. */
  71. protected function getToolkitOperationMock($class_name, ImageToolkitInterface $toolkit) {
  72. $mock_builder = $this->getMockBuilder('Drupal\system\Plugin\ImageToolkit\Operation\gd\\' . $class_name);
  73. $logger = $this->createMock('Psr\Log\LoggerInterface');
  74. return $mock_builder
  75. ->onlyMethods(['execute'])
  76. ->setConstructorArgs([[], '', [], $toolkit, $logger])
  77. ->getMock();
  78. }
  79. /**
  80. * Get an image with a mocked toolkit, for testing.
  81. *
  82. * @param bool $load_expected
  83. * (optional) Whether the load() method is expected to be called. Defaults
  84. * to TRUE.
  85. * @param array $stubs
  86. * (optional) Array containing toolkit methods to be replaced with stubs.
  87. *
  88. * @return \Drupal\Core\Image\Image
  89. * An image object.
  90. */
  91. protected function getTestImage($load_expected = TRUE, array $stubs = []) {
  92. if (!$load_expected && !in_array('load', $stubs)) {
  93. $stubs = array_merge(['load'], $stubs);
  94. }
  95. $this->toolkit = $this->getToolkitMock($stubs);
  96. $this->toolkit->expects($this->any())
  97. ->method('getPluginId')
  98. ->will($this->returnValue('gd'));
  99. if (!$load_expected) {
  100. $this->toolkit->expects($this->never())
  101. ->method('load');
  102. }
  103. $this->image = new Image($this->toolkit, $this->source);
  104. }
  105. /**
  106. * Get an image with mocked toolkit and operation, for operation testing.
  107. *
  108. * @param string $class_name
  109. * The name of the GD toolkit operation class to be mocked.
  110. *
  111. * @return \Drupal\Core\Image\Image
  112. * An image object.
  113. */
  114. protected function getTestImageForOperation($class_name) {
  115. $this->toolkit = $this->getToolkitMock(['getToolkitOperation']);
  116. $this->toolkitOperation = $this->getToolkitOperationMock($class_name, $this->toolkit);
  117. $this->toolkit->expects($this->any())
  118. ->method('getPluginId')
  119. ->will($this->returnValue('gd'));
  120. $this->toolkit->expects($this->any())
  121. ->method('getToolkitOperation')
  122. ->will($this->returnValue($this->toolkitOperation));
  123. $this->image = new Image($this->toolkit, $this->source);
  124. }
  125. /**
  126. * Tests \Drupal\Core\Image\Image::getHeight().
  127. */
  128. public function testGetHeight() {
  129. $this->getTestImage(FALSE);
  130. $this->assertEquals(100, $this->image->getHeight());
  131. }
  132. /**
  133. * Tests \Drupal\Core\Image\Image::getWidth().
  134. */
  135. public function testGetWidth() {
  136. $this->getTestImage(FALSE);
  137. $this->assertEquals(88, $this->image->getWidth());
  138. }
  139. /**
  140. * Tests \Drupal\Core\Image\Image::getFileSize.
  141. */
  142. public function testGetFileSize() {
  143. $this->getTestImage(FALSE);
  144. $this->assertEquals(3905, $this->image->getFileSize());
  145. }
  146. /**
  147. * Tests \Drupal\Core\Image\Image::getToolkit()->getType().
  148. */
  149. public function testGetType() {
  150. $this->getTestImage(FALSE);
  151. $this->assertEquals(IMAGETYPE_PNG, $this->image->getToolkit()->getType());
  152. }
  153. /**
  154. * Tests \Drupal\Core\Image\Image::getMimeType().
  155. */
  156. public function testGetMimeType() {
  157. $this->getTestImage(FALSE);
  158. $this->assertEquals('image/png', $this->image->getMimeType());
  159. }
  160. /**
  161. * Tests \Drupal\Core\Image\Image::isValid().
  162. */
  163. public function testIsValid() {
  164. $this->getTestImage(FALSE);
  165. $this->assertTrue($this->image->isValid());
  166. $this->assertFileIsReadable($this->image->getSource());
  167. }
  168. /**
  169. * Tests \Drupal\Core\Image\Image::getToolkitId().
  170. */
  171. public function testGetToolkitId() {
  172. $this->getTestImage(FALSE);
  173. $this->assertEquals('gd', $this->image->getToolkitId());
  174. }
  175. /**
  176. * Tests \Drupal\Core\Image\Image::save().
  177. */
  178. public function testSave() {
  179. $this->getTestImage();
  180. // This will fail if save() method isn't called on the toolkit.
  181. $toolkit = $this->getToolkitMock();
  182. $toolkit->expects($this->once())
  183. ->method('save')
  184. ->will($this->returnValue(TRUE));
  185. $image = $this->getMockBuilder('Drupal\Core\Image\Image')
  186. ->onlyMethods([])
  187. ->setConstructorArgs([$toolkit, $this->image->getSource()])
  188. ->getMock();
  189. $file_system = $this->prophesize(FileSystemInterface::class);
  190. $file_system->chmod($this->image->getSource())
  191. ->willReturn(TRUE);
  192. $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')
  193. ->onlyMethods(['get'])
  194. ->getMock();
  195. $container->expects($this->once())
  196. ->method('get')
  197. ->with('file_system')
  198. ->willReturn($file_system->reveal());
  199. \Drupal::setContainer($container);
  200. $image->save();
  201. }
  202. /**
  203. * Tests \Drupal\Core\Image\Image::save().
  204. */
  205. public function testSaveFails() {
  206. $this->getTestImage();
  207. // This will fail if save() method isn't called on the toolkit.
  208. $this->toolkit->expects($this->once())
  209. ->method('save')
  210. ->will($this->returnValue(FALSE));
  211. $this->assertFalse($this->image->save());
  212. }
  213. /**
  214. * Tests \Drupal\Core\Image\Image::save().
  215. */
  216. public function testChmodFails() {
  217. $this->getTestImage();
  218. // This will fail if save() method isn't called on the toolkit.
  219. $toolkit = $this->getToolkitMock();
  220. $toolkit->expects($this->once())
  221. ->method('save')
  222. ->will($this->returnValue(TRUE));
  223. $image = $this->getMockBuilder('Drupal\Core\Image\Image')
  224. ->onlyMethods([])
  225. ->setConstructorArgs([$toolkit, $this->image->getSource()])
  226. ->getMock();
  227. $file_system = $this->prophesize(FileSystemInterface::class);
  228. $file_system->chmod($this->image->getSource())
  229. ->willReturn(FALSE);
  230. $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')
  231. ->onlyMethods(['get'])
  232. ->getMock();
  233. $container->expects($this->once())
  234. ->method('get')
  235. ->with('file_system')
  236. ->willReturn($file_system->reveal());
  237. \Drupal::setContainer($container);
  238. $this->assertFalse($image->save());
  239. }
  240. /**
  241. * Tests \Drupal\Core\Image\Image::parseFile().
  242. */
  243. public function testParseFileFails() {
  244. $toolkit = $this->getToolkitMock();
  245. $image = new Image($toolkit, 'magic-foobars.png');
  246. $this->assertFalse($image->isValid());
  247. $this->assertFalse($image->save());
  248. }
  249. /**
  250. * Tests \Drupal\Core\Image\Image::scale().
  251. */
  252. public function testScaleWidth() {
  253. $this->getTestImageForOperation('Scale');
  254. $this->toolkitOperation->expects($this->once())
  255. ->method('execute')
  256. ->will($this->returnArgument(0));
  257. $ret = $this->image->scale(44, NULL, FALSE);
  258. $this->assertEquals(50, $ret['height']);
  259. }
  260. /**
  261. * Tests \Drupal\Core\Image\Image::scale().
  262. */
  263. public function testScaleHeight() {
  264. $this->getTestImageForOperation('Scale');
  265. $this->toolkitOperation->expects($this->once())
  266. ->method('execute')
  267. ->will($this->returnArgument(0));
  268. $ret = $this->image->scale(NULL, 50, FALSE);
  269. $this->assertEquals(44, $ret['width']);
  270. }
  271. /**
  272. * Tests \Drupal\Core\Image\Image::scale().
  273. */
  274. public function testScaleSame() {
  275. $this->getTestImageForOperation('Scale');
  276. // Dimensions are the same, resize should not be called.
  277. $this->toolkitOperation->expects($this->once())
  278. ->method('execute')
  279. ->will($this->returnArgument(0));
  280. $ret = $this->image->scale(88, 100, FALSE);
  281. $this->assertEquals(88, $ret['width']);
  282. $this->assertEquals(100, $ret['height']);
  283. }
  284. /**
  285. * Tests \Drupal\Core\Image\Image::scaleAndCrop().
  286. */
  287. public function testScaleAndCropWidth() {
  288. $this->getTestImageForOperation('ScaleAndCrop');
  289. $this->toolkitOperation->expects($this->once())
  290. ->method('execute')
  291. ->will($this->returnArgument(0));
  292. $ret = $this->image->scaleAndCrop(34, 50, FALSE);
  293. $this->assertEquals(5, $ret['x']);
  294. }
  295. /**
  296. * Tests \Drupal\Core\Image\Image::scaleAndCrop().
  297. */
  298. public function testScaleAndCropHeight() {
  299. $this->getTestImageForOperation('ScaleAndCrop');
  300. $this->toolkitOperation->expects($this->once())
  301. ->method('execute')
  302. ->will($this->returnArgument(0));
  303. $ret = $this->image->scaleAndCrop(44, 40);
  304. $this->assertEquals(5, $ret['y']);
  305. }
  306. /**
  307. * Tests \Drupal\Core\Image\Image::scaleAndCrop().
  308. */
  309. public function testScaleAndCropFails() {
  310. $this->getTestImageForOperation('ScaleAndCrop');
  311. $this->toolkitOperation->expects($this->once())
  312. ->method('execute')
  313. ->will($this->returnArgument(0));
  314. $ret = $this->image->scaleAndCrop(44, 40);
  315. $this->assertEquals(0, $ret['x']);
  316. $this->assertEquals(5, $ret['y']);
  317. $this->assertEquals(44, $ret['resize']['width']);
  318. $this->assertEquals(50, $ret['resize']['height']);
  319. }
  320. /**
  321. * Tests \Drupal\Core\Image\Image::crop().
  322. */
  323. public function testCropWidth() {
  324. $this->getTestImageForOperation('Crop');
  325. $this->toolkitOperation->expects($this->once())
  326. ->method('execute')
  327. ->will($this->returnArgument(0));
  328. // Cropping with width only should preserve the aspect ratio.
  329. $ret = $this->image->crop(0, 0, 44);
  330. $this->assertEquals(50, $ret['height']);
  331. }
  332. /**
  333. * Tests \Drupal\Core\Image\Image::crop().
  334. */
  335. public function testCropHeight() {
  336. $this->getTestImageForOperation('Crop');
  337. $this->toolkitOperation->expects($this->once())
  338. ->method('execute')
  339. ->will($this->returnArgument(0));
  340. // Cropping with height only should preserve the aspect ratio.
  341. $ret = $this->image->crop(0, 0, NULL, 50);
  342. $this->assertEquals(44, $ret['width']);
  343. }
  344. /**
  345. * Tests \Drupal\Core\Image\Image::crop().
  346. */
  347. public function testCrop() {
  348. $this->getTestImageForOperation('Crop');
  349. $this->toolkitOperation->expects($this->once())
  350. ->method('execute')
  351. ->will($this->returnArgument(0));
  352. $ret = $this->image->crop(0, 0, 44, 50);
  353. $this->assertEquals(44, $ret['width']);
  354. }
  355. /**
  356. * Tests \Drupal\Core\Image\Image::convert().
  357. */
  358. public function testConvert() {
  359. $this->getTestImageForOperation('Convert');
  360. $this->toolkitOperation->expects($this->once())
  361. ->method('execute')
  362. ->will($this->returnArgument(0));
  363. $ret = $this->image->convert('png');
  364. $this->assertEquals('png', $ret['extension']);
  365. }
  366. /**
  367. * Tests \Drupal\Core\Image\Image::resize().
  368. */
  369. public function testResize() {
  370. $this->getTestImageForOperation('Resize');
  371. $this->toolkitOperation->expects($this->once())
  372. ->method('execute')
  373. ->will($this->returnArgument(0));
  374. // Resize with integer for width and height.
  375. $ret = $this->image->resize(30, 40);
  376. $this->assertEquals(30, $ret['width']);
  377. $this->assertEquals(40, $ret['height']);
  378. }
  379. /**
  380. * Tests \Drupal\Core\Image\Image::resize().
  381. */
  382. public function testFloatResize() {
  383. $this->getTestImageForOperation('Resize');
  384. $this->toolkitOperation->expects($this->once())
  385. ->method('execute')
  386. ->will($this->returnArgument(0));
  387. // Pass a float for width.
  388. $ret = $this->image->resize(30.4, 40);
  389. // Ensure that the float was rounded to an integer first.
  390. $this->assertEquals(30, $ret['width']);
  391. }
  392. /**
  393. * Tests \Drupal\Core\Image\Image::desaturate().
  394. */
  395. public function testDesaturate() {
  396. $this->getTestImageForOperation('Desaturate');
  397. $this->toolkitOperation->expects($this->once())
  398. ->method('execute')
  399. ->will($this->returnArgument(0));
  400. $this->image->desaturate();
  401. }
  402. /**
  403. * Tests \Drupal\Core\Image\Image::rotate().
  404. */
  405. public function testRotate() {
  406. $this->getTestImageForOperation('Rotate');
  407. $this->toolkitOperation->expects($this->once())
  408. ->method('execute')
  409. ->will($this->returnArgument(0));
  410. $ret = $this->image->rotate(90);
  411. $this->assertEquals(90, $ret['degrees']);
  412. }
  413. }