IconBuilderTest.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
  4. *
  5. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  6. * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
  7. * @author Joas Schilling <coding@schilljs.com>
  8. * @author Julius Haertl <jus@bitgrid.net>
  9. * @author Julius Härtl <jus@bitgrid.net>
  10. * @author Roeland Jago Douma <roeland@famdouma.nl>
  11. *
  12. * @license GNU AGPL version 3 or any later version
  13. *
  14. * This program is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU Affero General Public License as
  16. * published by the Free Software Foundation, either version 3 of the
  17. * License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU Affero General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU Affero General Public License
  25. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  26. *
  27. */
  28. namespace OCA\Theming\Tests;
  29. use OC\Files\AppData\AppData;
  30. use OCA\Theming\IconBuilder;
  31. use OCA\Theming\ImageManager;
  32. use OCA\Theming\ThemingDefaults;
  33. use OCA\Theming\Util;
  34. use OCP\App\IAppManager;
  35. use OCP\Files\NotFoundException;
  36. use OCP\IConfig;
  37. use PHPUnit\Framework\Error\Warning;
  38. use Test\TestCase;
  39. class IconBuilderTest extends TestCase {
  40. /** @var IConfig */
  41. protected $config;
  42. /** @var AppData */
  43. protected $appData;
  44. /** @var ThemingDefaults */
  45. protected $themingDefaults;
  46. /** @var Util */
  47. protected $util;
  48. /** @var ImageManager */
  49. protected $imageManager;
  50. /** @var IconBuilder */
  51. protected $iconBuilder;
  52. /** @var IAppManager */
  53. protected $appManager;
  54. protected function setUp(): void {
  55. parent::setUp();
  56. $this->config = $this->createMock(IConfig::class);
  57. $this->appData = $this->createMock(AppData::class);
  58. $this->themingDefaults = $this->createMock(ThemingDefaults::class);
  59. $this->appManager = $this->createMock(IAppManager::class);
  60. $this->imageManager = $this->createMock(ImageManager::class);
  61. $this->util = new Util($this->config, $this->appManager, $this->appData, $this->imageManager);
  62. $this->iconBuilder = new IconBuilder($this->themingDefaults, $this->util, $this->imageManager);
  63. }
  64. private function checkImagick() {
  65. if (!extension_loaded('imagick')) {
  66. $this->markTestSkipped('Imagemagick is required for dynamic icon generation.');
  67. }
  68. $checkImagick = new \Imagick();
  69. if (count($checkImagick->queryFormats('SVG')) < 1) {
  70. $this->markTestSkipped('No SVG provider present.');
  71. }
  72. if (count($checkImagick->queryFormats('PNG')) < 1) {
  73. $this->markTestSkipped('No PNG provider present.');
  74. }
  75. }
  76. public function dataRenderAppIcon() {
  77. return [
  78. ['core', '#0082c9', 'touch-original.png'],
  79. ['core', '#FF0000', 'touch-core-red.png'],
  80. ['testing', '#FF0000', 'touch-testing-red.png'],
  81. ['comments', '#0082c9', 'touch-comments.png'],
  82. ['core', '#0082c9', 'touch-original-png.png'],
  83. ];
  84. }
  85. /**
  86. * @dataProvider dataRenderAppIcon
  87. * @param $app
  88. * @param $color
  89. * @param $file
  90. */
  91. public function testRenderAppIcon($app, $color, $file) {
  92. $this->checkImagick();
  93. $this->themingDefaults->expects($this->once())
  94. ->method('getColorPrimary')
  95. ->willReturn($color);
  96. $this->appData->expects($this->once())
  97. ->method('getFolder')
  98. ->with('global/images')
  99. ->willThrowException(new NotFoundException());
  100. $expectedIcon = new \Imagick(realpath(dirname(__FILE__)). "/data/" . $file);
  101. $icon = $this->iconBuilder->renderAppIcon($app, 512);
  102. $this->assertEquals(true, $icon->valid());
  103. $this->assertEquals(512, $icon->getImageWidth());
  104. $this->assertEquals(512, $icon->getImageHeight());
  105. $this->assertEquals($icon, $expectedIcon);
  106. $icon->destroy();
  107. $expectedIcon->destroy();
  108. // FIXME: We may need some comparison of the generated and the test images
  109. // cloud be something like $expectedIcon->compareImages($icon, Imagick::METRIC_MEANABSOLUTEERROR)[1])
  110. }
  111. /**
  112. * @dataProvider dataRenderAppIcon
  113. * @param $app
  114. * @param $color
  115. * @param $file
  116. */
  117. public function testGetTouchIcon($app, $color, $file) {
  118. $this->checkImagick();
  119. $this->themingDefaults->expects($this->once())
  120. ->method('getColorPrimary')
  121. ->willReturn($color);
  122. $this->appData->expects($this->once())
  123. ->method('getFolder')
  124. ->with('global/images')
  125. ->willThrowException(new NotFoundException());
  126. $expectedIcon = new \Imagick(realpath(dirname(__FILE__)). "/data/" . $file);
  127. $icon = new \Imagick();
  128. $icon->readImageBlob($this->iconBuilder->getTouchIcon($app));
  129. $this->assertEquals(true, $icon->valid());
  130. $this->assertEquals(512, $icon->getImageWidth());
  131. $this->assertEquals(512, $icon->getImageHeight());
  132. $this->assertEquals($icon, $expectedIcon);
  133. $icon->destroy();
  134. $expectedIcon->destroy();
  135. // FIXME: We may need some comparison of the generated and the test images
  136. // cloud be something like $expectedIcon->compareImages($icon, Imagick::METRIC_MEANABSOLUTEERROR)[1])
  137. }
  138. /**
  139. * @dataProvider dataRenderAppIcon
  140. * @param $app
  141. * @param $color
  142. * @param $file
  143. */
  144. public function testGetFavicon($app, $color, $file) {
  145. $this->checkImagick();
  146. $this->imageManager->expects($this->once())
  147. ->method('shouldReplaceIcons')
  148. ->willReturn(true);
  149. $this->themingDefaults->expects($this->once())
  150. ->method('getColorPrimary')
  151. ->willReturn($color);
  152. $this->appData->expects($this->once())
  153. ->method('getFolder')
  154. ->with('global/images')
  155. ->willThrowException(new NotFoundException());
  156. $expectedIcon = new \Imagick(realpath(dirname(__FILE__)). "/data/" . $file);
  157. $actualIcon = $this->iconBuilder->getFavicon($app);
  158. $icon = new \Imagick();
  159. $icon->setFormat('ico');
  160. $icon->readImageBlob($actualIcon);
  161. $this->assertEquals(true, $icon->valid());
  162. $this->assertEquals(128, $icon->getImageWidth());
  163. $this->assertEquals(128, $icon->getImageHeight());
  164. $icon->destroy();
  165. $expectedIcon->destroy();
  166. // FIXME: We may need some comparison of the generated and the test images
  167. // cloud be something like $expectedIcon->compareImages($icon, Imagick::METRIC_MEANABSOLUTEERROR)[1])
  168. }
  169. public function testGetFaviconNotFound() {
  170. $this->checkImagick();
  171. $this->expectWarning(Warning::class);
  172. $util = $this->getMockBuilder(Util::class)->disableOriginalConstructor()->getMock();
  173. $iconBuilder = new IconBuilder($this->themingDefaults, $util, $this->imageManager);
  174. $this->imageManager->expects($this->once())
  175. ->method('shouldReplaceIcons')
  176. ->willReturn(true);
  177. $util->expects($this->once())
  178. ->method('getAppIcon')
  179. ->willReturn('notexistingfile');
  180. $this->assertFalse($iconBuilder->getFavicon('noapp'));
  181. }
  182. public function testGetTouchIconNotFound() {
  183. $this->checkImagick();
  184. $this->expectWarning(Warning::class);
  185. $util = $this->getMockBuilder(Util::class)->disableOriginalConstructor()->getMock();
  186. $iconBuilder = new IconBuilder($this->themingDefaults, $util, $this->imageManager);
  187. $util->expects($this->once())
  188. ->method('getAppIcon')
  189. ->willReturn('notexistingfile');
  190. $this->assertFalse($iconBuilder->getTouchIcon('noapp'));
  191. }
  192. public function testColorSvgNotFound() {
  193. $this->checkImagick();
  194. $this->expectWarning(Warning::class);
  195. $util = $this->getMockBuilder(Util::class)->disableOriginalConstructor()->getMock();
  196. $iconBuilder = new IconBuilder($this->themingDefaults, $util, $this->imageManager);
  197. $util->expects($this->once())
  198. ->method('getAppImage')
  199. ->willReturn('notexistingfile');
  200. $this->assertFalse($iconBuilder->colorSvg('noapp', 'noimage'));
  201. }
  202. }