ThemingControllerTest.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-License-Identifier: AGPL-3.0-or-later
  5. */
  6. namespace OCA\Theming\Tests\Controller;
  7. use OC\L10N\L10N;
  8. use OCA\Theming\Controller\ThemingController;
  9. use OCA\Theming\ImageManager;
  10. use OCA\Theming\Service\ThemesService;
  11. use OCA\Theming\ThemingDefaults;
  12. use OCP\App\IAppManager;
  13. use OCP\AppFramework\Http;
  14. use OCP\AppFramework\Http\DataResponse;
  15. use OCP\AppFramework\Utility\ITimeFactory;
  16. use OCP\Files\NotFoundException;
  17. use OCP\Files\SimpleFS\ISimpleFile;
  18. use OCP\IConfig;
  19. use OCP\IL10N;
  20. use OCP\IRequest;
  21. use OCP\IURLGenerator;
  22. use PHPUnit\Framework\MockObject\MockObject;
  23. use Test\TestCase;
  24. class ThemingControllerTest extends TestCase {
  25. /** @var IRequest|MockObject */
  26. private $request;
  27. /** @var IConfig|MockObject */
  28. private $config;
  29. /** @var ThemingDefaults|MockObject */
  30. private $themingDefaults;
  31. /** @var IL10N|MockObject */
  32. private $l10n;
  33. /** @var ThemingController */
  34. private $themingController;
  35. /** @var IAppManager|MockObject */
  36. private $appManager;
  37. /** @var ImageManager|MockObject */
  38. private $imageManager;
  39. /** @var IURLGenerator|MockObject */
  40. private $urlGenerator;
  41. /** @var ThemesService|MockObject */
  42. private $themesService;
  43. protected function setUp(): void {
  44. $this->request = $this->createMock(IRequest::class);
  45. $this->config = $this->createMock(IConfig::class);
  46. $this->themingDefaults = $this->createMock(ThemingDefaults::class);
  47. $this->l10n = $this->createMock(L10N::class);
  48. $this->appManager = $this->createMock(IAppManager::class);
  49. $this->urlGenerator = $this->createMock(IURLGenerator::class);
  50. $this->imageManager = $this->createMock(ImageManager::class);
  51. $this->themesService = $this->createMock(ThemesService::class);
  52. $timeFactory = $this->createMock(ITimeFactory::class);
  53. $timeFactory->expects($this->any())
  54. ->method('getTime')
  55. ->willReturn(123);
  56. $this->overwriteService(ITimeFactory::class, $timeFactory);
  57. $this->themingController = new ThemingController(
  58. 'theming',
  59. $this->request,
  60. $this->config,
  61. $this->themingDefaults,
  62. $this->l10n,
  63. $this->urlGenerator,
  64. $this->appManager,
  65. $this->imageManager,
  66. $this->themesService,
  67. );
  68. parent::setUp();
  69. }
  70. public function dataUpdateStylesheetSuccess() {
  71. return [
  72. ['name', str_repeat('a', 250), 'Saved'],
  73. ['url', 'https://nextcloud.com/' . str_repeat('a', 478), 'Saved'],
  74. ['slogan', str_repeat('a', 500), 'Saved'],
  75. ['color', '#0082c9', 'Saved'],
  76. ['color', '#0082C9', 'Saved'],
  77. ['color', '#0082C9', 'Saved'],
  78. ['imprintUrl', 'https://nextcloud.com/' . str_repeat('a', 478), 'Saved'],
  79. ['privacyUrl', 'https://nextcloud.com/' . str_repeat('a', 478), 'Saved'],
  80. ];
  81. }
  82. /**
  83. * @dataProvider dataUpdateStylesheetSuccess
  84. *
  85. * @param string $setting
  86. * @param string $value
  87. * @param string $message
  88. */
  89. public function testUpdateStylesheetSuccess($setting, $value, $message) {
  90. $this->themingDefaults
  91. ->expects($this->once())
  92. ->method('set')
  93. ->with($setting, $value);
  94. $this->l10n
  95. ->expects($this->once())
  96. ->method('t')
  97. ->willReturnCallback(function ($str) {
  98. return $str;
  99. });
  100. $expected = new DataResponse(
  101. [
  102. 'data' =>
  103. [
  104. 'message' => $message,
  105. ],
  106. 'status' => 'success',
  107. ]
  108. );
  109. $this->assertEquals($expected, $this->themingController->updateStylesheet($setting, $value));
  110. }
  111. public function dataUpdateStylesheetError() {
  112. return [
  113. ['name', str_repeat('a', 251), 'The given name is too long'],
  114. ['url', 'http://example.com/' . str_repeat('a', 501), 'The given web address is too long'],
  115. ['url', str_repeat('a', 501), 'The given web address is not a valid URL'],
  116. ['url', 'javascript:alert(1)', 'The given web address is not a valid URL'],
  117. ['slogan', str_repeat('a', 501), 'The given slogan is too long'],
  118. ['primary_color', '0082C9', 'The given color is invalid'],
  119. ['primary_color', '#0082Z9', 'The given color is invalid'],
  120. ['primary_color', 'Nextcloud', 'The given color is invalid'],
  121. ['background_color', '0082C9', 'The given color is invalid'],
  122. ['background_color', '#0082Z9', 'The given color is invalid'],
  123. ['background_color', 'Nextcloud', 'The given color is invalid'],
  124. ['imprintUrl', '0082C9', 'The given legal notice address is not a valid URL'],
  125. ['imprintUrl', '0082C9', 'The given legal notice address is not a valid URL'],
  126. ['imprintUrl', 'javascript:foo', 'The given legal notice address is not a valid URL'],
  127. ['privacyUrl', '#0082Z9', 'The given privacy policy address is not a valid URL'],
  128. ];
  129. }
  130. /**
  131. * @dataProvider dataUpdateStylesheetError
  132. *
  133. * @param string $setting
  134. * @param string $value
  135. * @param string $message
  136. */
  137. public function testUpdateStylesheetError($setting, $value, $message) {
  138. $this->themingDefaults
  139. ->expects($this->never())
  140. ->method('set')
  141. ->with($setting, $value);
  142. $this->l10n
  143. ->expects($this->any())
  144. ->method('t')
  145. ->willReturnCallback(function ($str) {
  146. return $str;
  147. });
  148. $expected = new DataResponse(
  149. [
  150. 'data' =>
  151. [
  152. 'message' => $message,
  153. ],
  154. 'status' => 'error',
  155. ],
  156. Http::STATUS_BAD_REQUEST
  157. );
  158. $this->assertEquals($expected, $this->themingController->updateStylesheet($setting, $value));
  159. }
  160. public function testUpdateLogoNoData() {
  161. $this->request
  162. ->expects($this->once())
  163. ->method('getParam')
  164. ->with('key')
  165. ->willReturn('logo');
  166. $this->request
  167. ->expects($this->once())
  168. ->method('getUploadedFile')
  169. ->with('image')
  170. ->willReturn(null);
  171. $this->l10n
  172. ->expects($this->any())
  173. ->method('t')
  174. ->willReturnCallback(function ($str) {
  175. return $str;
  176. });
  177. $expected = new DataResponse(
  178. [
  179. 'data' =>
  180. [
  181. 'message' => 'No file uploaded',
  182. ],
  183. 'status' => 'failure',
  184. ],
  185. Http::STATUS_UNPROCESSABLE_ENTITY
  186. );
  187. $this->assertEquals($expected, $this->themingController->uploadImage());
  188. }
  189. public function testUploadInvalidUploadKey() {
  190. $this->request
  191. ->expects($this->once())
  192. ->method('getParam')
  193. ->with('key')
  194. ->willReturn('invalid');
  195. $this->request
  196. ->expects($this->never())
  197. ->method('getUploadedFile');
  198. $this->l10n
  199. ->expects($this->any())
  200. ->method('t')
  201. ->willReturnCallback(function ($str) {
  202. return $str;
  203. });
  204. $expected = new DataResponse(
  205. [
  206. 'data' =>
  207. [
  208. 'message' => 'Invalid key',
  209. ],
  210. 'status' => 'failure',
  211. ],
  212. Http::STATUS_BAD_REQUEST
  213. );
  214. $this->assertEquals($expected, $this->themingController->uploadImage());
  215. }
  216. /**
  217. * Checks that trying to upload an SVG favicon without imagemagick
  218. * results in an unsupported media type response.
  219. *
  220. * @test
  221. * @return void
  222. */
  223. public function testUploadSVGFaviconWithoutImagemagick() {
  224. $this->imageManager
  225. ->method('shouldReplaceIcons')
  226. ->willReturn(false);
  227. $this->request
  228. ->expects($this->once())
  229. ->method('getParam')
  230. ->with('key')
  231. ->willReturn('favicon');
  232. $this->request
  233. ->expects($this->once())
  234. ->method('getUploadedFile')
  235. ->with('image')
  236. ->willReturn([
  237. 'tmp_name' => __DIR__ . '/../../../../tests/data/testimagelarge.svg',
  238. 'type' => 'image/svg',
  239. 'name' => 'testimagelarge.svg',
  240. 'error' => 0,
  241. ]);
  242. $this->l10n
  243. ->expects($this->any())
  244. ->method('t')
  245. ->willReturnCallback(function ($str) {
  246. return $str;
  247. });
  248. $this->imageManager->expects($this->once())
  249. ->method('updateImage')
  250. ->willThrowException(new \Exception('Unsupported image type'));
  251. $expected = new DataResponse(
  252. [
  253. 'data' =>
  254. [
  255. 'message' => 'Unsupported image type',
  256. ],
  257. 'status' => 'failure'
  258. ],
  259. Http::STATUS_UNPROCESSABLE_ENTITY
  260. );
  261. $this->assertEquals($expected, $this->themingController->uploadImage());
  262. }
  263. public function testUpdateLogoInvalidMimeType() {
  264. $this->request
  265. ->expects($this->once())
  266. ->method('getParam')
  267. ->with('key')
  268. ->willReturn('logo');
  269. $this->request
  270. ->expects($this->once())
  271. ->method('getUploadedFile')
  272. ->with('image')
  273. ->willReturn([
  274. 'tmp_name' => __DIR__ . '/../../../../tests/data/lorem.txt',
  275. 'type' => 'application/pdf',
  276. 'name' => 'logo.pdf',
  277. 'error' => 0,
  278. ]);
  279. $this->l10n
  280. ->expects($this->any())
  281. ->method('t')
  282. ->willReturnCallback(function ($str) {
  283. return $str;
  284. });
  285. $this->imageManager->expects($this->once())
  286. ->method('updateImage')
  287. ->willThrowException(new \Exception('Unsupported image type'));
  288. $expected = new DataResponse(
  289. [
  290. 'data' =>
  291. [
  292. 'message' => 'Unsupported image type',
  293. ],
  294. 'status' => 'failure'
  295. ],
  296. Http::STATUS_UNPROCESSABLE_ENTITY
  297. );
  298. $this->assertEquals($expected, $this->themingController->uploadImage());
  299. }
  300. public function dataUpdateImages() {
  301. return [
  302. ['image/jpeg', false],
  303. ['image/jpeg', true],
  304. ['image/gif'],
  305. ['image/png'],
  306. ['image/svg+xml'],
  307. ['image/svg']
  308. ];
  309. }
  310. /** @dataProvider dataUpdateImages */
  311. public function testUpdateLogoNormalLogoUpload($mimeType, $folderExists = true) {
  312. $tmpLogo = \OC::$server->getTempManager()->getTemporaryFolder() . '/logo.svg';
  313. $destination = \OC::$server->getTempManager()->getTemporaryFolder();
  314. touch($tmpLogo);
  315. copy(__DIR__ . '/../../../../tests/data/testimage.png', $tmpLogo);
  316. $this->request
  317. ->expects($this->once())
  318. ->method('getParam')
  319. ->with('key')
  320. ->willReturn('logo');
  321. $this->request
  322. ->expects($this->once())
  323. ->method('getUploadedFile')
  324. ->with('image')
  325. ->willReturn([
  326. 'tmp_name' => $tmpLogo,
  327. 'type' => $mimeType,
  328. 'name' => 'logo.svg',
  329. 'error' => 0,
  330. ]);
  331. $this->l10n
  332. ->expects($this->any())
  333. ->method('t')
  334. ->willReturnCallback(function ($str) {
  335. return $str;
  336. });
  337. $this->imageManager->expects($this->once())
  338. ->method('getImageUrl')
  339. ->with('logo')
  340. ->willReturn('imageUrl');
  341. $this->imageManager->expects($this->once())
  342. ->method('updateImage');
  343. $expected = new DataResponse(
  344. [
  345. 'data' =>
  346. [
  347. 'name' => 'logo.svg',
  348. 'message' => 'Saved',
  349. 'url' => 'imageUrl',
  350. ],
  351. 'status' => 'success'
  352. ]
  353. );
  354. $this->assertEquals($expected, $this->themingController->uploadImage());
  355. }
  356. /** @dataProvider dataUpdateImages */
  357. public function testUpdateLogoLoginScreenUpload($folderExists) {
  358. $tmpLogo = \OC::$server->getTempManager()->getTemporaryFolder() . 'logo.png';
  359. touch($tmpLogo);
  360. copy(__DIR__ . '/../../../../tests/data/desktopapp.png', $tmpLogo);
  361. $this->request
  362. ->expects($this->once())
  363. ->method('getParam')
  364. ->with('key')
  365. ->willReturn('background');
  366. $this->request
  367. ->expects($this->once())
  368. ->method('getUploadedFile')
  369. ->with('image')
  370. ->willReturn([
  371. 'tmp_name' => $tmpLogo,
  372. 'type' => 'image/svg+xml',
  373. 'name' => 'logo.svg',
  374. 'error' => 0,
  375. ]);
  376. $this->l10n
  377. ->expects($this->any())
  378. ->method('t')
  379. ->willReturnCallback(function ($str) {
  380. return $str;
  381. });
  382. $this->imageManager->expects($this->once())
  383. ->method('updateImage');
  384. $this->imageManager->expects($this->once())
  385. ->method('getImageUrl')
  386. ->with('background')
  387. ->willReturn('imageUrl');
  388. $expected = new DataResponse(
  389. [
  390. 'data' =>
  391. [
  392. 'name' => 'logo.svg',
  393. 'message' => 'Saved',
  394. 'url' => 'imageUrl',
  395. ],
  396. 'status' => 'success'
  397. ]
  398. );
  399. $this->assertEquals($expected, $this->themingController->uploadImage());
  400. }
  401. public function testUpdateLogoLoginScreenUploadWithInvalidImage() {
  402. $tmpLogo = \OC::$server->getTempManager()->getTemporaryFolder() . '/logo.svg';
  403. touch($tmpLogo);
  404. file_put_contents($tmpLogo, file_get_contents(__DIR__ . '/../../../../tests/data/data.zip'));
  405. $this->request
  406. ->expects($this->once())
  407. ->method('getParam')
  408. ->with('key')
  409. ->willReturn('logo');
  410. $this->request
  411. ->expects($this->once())
  412. ->method('getUploadedFile')
  413. ->with('image')
  414. ->willReturn([
  415. 'tmp_name' => $tmpLogo,
  416. 'type' => 'foobar',
  417. 'name' => 'logo.svg',
  418. 'error' => 0,
  419. ]);
  420. $this->l10n
  421. ->expects($this->any())
  422. ->method('t')
  423. ->willReturnCallback(function ($str) {
  424. return $str;
  425. });
  426. $this->imageManager->expects($this->once())
  427. ->method('updateImage')
  428. ->willThrowException(new \Exception('Unsupported image type'));
  429. $expected = new DataResponse(
  430. [
  431. 'data' =>
  432. [
  433. 'message' => 'Unsupported image type',
  434. ],
  435. 'status' => 'failure'
  436. ],
  437. Http::STATUS_UNPROCESSABLE_ENTITY
  438. );
  439. $this->assertEquals($expected, $this->themingController->uploadImage());
  440. }
  441. public function dataPhpUploadErrors() {
  442. return [
  443. [UPLOAD_ERR_INI_SIZE, 'The uploaded file exceeds the upload_max_filesize directive in php.ini'],
  444. [UPLOAD_ERR_FORM_SIZE, 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'],
  445. [UPLOAD_ERR_PARTIAL, 'The file was only partially uploaded'],
  446. [UPLOAD_ERR_NO_FILE, 'No file was uploaded'],
  447. [UPLOAD_ERR_NO_TMP_DIR, 'Missing a temporary folder'],
  448. [UPLOAD_ERR_CANT_WRITE, 'Could not write file to disk'],
  449. [UPLOAD_ERR_EXTENSION, 'A PHP extension stopped the file upload'],
  450. ];
  451. }
  452. /**
  453. * @dataProvider dataPhpUploadErrors
  454. */
  455. public function testUpdateLogoLoginScreenUploadWithInvalidImageUpload($error, $expectedErrorMessage) {
  456. $this->request
  457. ->expects($this->once())
  458. ->method('getParam')
  459. ->with('key')
  460. ->willReturn('background');
  461. $this->request
  462. ->expects($this->once())
  463. ->method('getUploadedFile')
  464. ->with('image')
  465. ->willReturn([
  466. 'tmp_name' => '',
  467. 'type' => 'image/svg+xml',
  468. 'name' => 'logo.svg',
  469. 'error' => $error,
  470. ]);
  471. $this->l10n
  472. ->expects($this->any())
  473. ->method('t')
  474. ->willReturnCallback(function ($str) {
  475. return $str;
  476. });
  477. $expected = new DataResponse(
  478. [
  479. 'data' =>
  480. [
  481. 'message' => $expectedErrorMessage,
  482. ],
  483. 'status' => 'failure'
  484. ],
  485. Http::STATUS_UNPROCESSABLE_ENTITY
  486. );
  487. $this->assertEquals($expected, $this->themingController->uploadImage());
  488. }
  489. /**
  490. * @dataProvider dataPhpUploadErrors
  491. */
  492. public function testUpdateLogoUploadWithInvalidImageUpload($error, $expectedErrorMessage) {
  493. $this->request
  494. ->expects($this->once())
  495. ->method('getParam')
  496. ->with('key')
  497. ->willReturn('background');
  498. $this->request
  499. ->expects($this->once())
  500. ->method('getUploadedFile')
  501. ->with('image')
  502. ->willReturn([
  503. 'tmp_name' => '',
  504. 'type' => 'text/svg',
  505. 'name' => 'logo.svg',
  506. 'error' => $error,
  507. ]);
  508. $this->l10n
  509. ->expects($this->any())
  510. ->method('t')
  511. ->willReturnCallback(function ($str) {
  512. return $str;
  513. });
  514. $expected = new DataResponse(
  515. [
  516. 'data' =>
  517. [
  518. 'message' => $expectedErrorMessage
  519. ],
  520. 'status' => 'failure'
  521. ],
  522. Http::STATUS_UNPROCESSABLE_ENTITY
  523. );
  524. $this->assertEquals($expected, $this->themingController->uploadImage());
  525. }
  526. public function testUndo() {
  527. $this->l10n
  528. ->expects($this->once())
  529. ->method('t')
  530. ->with('Saved')
  531. ->willReturn('Saved');
  532. $this->themingDefaults
  533. ->expects($this->once())
  534. ->method('undo')
  535. ->with('MySetting')
  536. ->willReturn('MyValue');
  537. $expected = new DataResponse(
  538. [
  539. 'data' =>
  540. [
  541. 'value' => 'MyValue',
  542. 'message' => 'Saved'
  543. ],
  544. 'status' => 'success'
  545. ]
  546. );
  547. $this->assertEquals($expected, $this->themingController->undo('MySetting'));
  548. }
  549. public function dataUndoDelete() {
  550. return [
  551. [ 'backgroundMime', 'background' ],
  552. [ 'logoMime', 'logo' ]
  553. ];
  554. }
  555. /** @dataProvider dataUndoDelete */
  556. public function testUndoDelete($value, $filename) {
  557. $this->l10n
  558. ->expects($this->once())
  559. ->method('t')
  560. ->with('Saved')
  561. ->willReturn('Saved');
  562. $this->themingDefaults
  563. ->expects($this->once())
  564. ->method('undo')
  565. ->with($value)
  566. ->willReturn($value);
  567. $expected = new DataResponse(
  568. [
  569. 'data' =>
  570. [
  571. 'value' => $value,
  572. 'message' => 'Saved',
  573. ],
  574. 'status' => 'success'
  575. ]
  576. );
  577. $this->assertEquals($expected, $this->themingController->undo($value));
  578. }
  579. public function testGetLogoNotExistent() {
  580. $this->imageManager->method('getImage')
  581. ->with($this->equalTo('logo'))
  582. ->willThrowException(new NotFoundException());
  583. $expected = new Http\NotFoundResponse();
  584. $this->assertEquals($expected, $this->themingController->getImage('logo'));
  585. }
  586. public function testGetLogo() {
  587. $file = $this->createMock(ISimpleFile::class);
  588. $file->method('getName')->willReturn('logo.svg');
  589. $file->method('getMTime')->willReturn(42);
  590. $this->imageManager->expects($this->once())
  591. ->method('getImage')
  592. ->willReturn($file);
  593. $this->config
  594. ->expects($this->any())
  595. ->method('getAppValue')
  596. ->with('theming', 'logoMime', '')
  597. ->willReturn('text/svg');
  598. @$expected = new Http\FileDisplayResponse($file);
  599. $expected->cacheFor(3600);
  600. $expected->addHeader('Content-Type', 'text/svg');
  601. $expected->addHeader('Content-Disposition', 'attachment; filename="logo"');
  602. $csp = new Http\ContentSecurityPolicy();
  603. $csp->allowInlineStyle();
  604. $expected->setContentSecurityPolicy($csp);
  605. @$this->assertEquals($expected, $this->themingController->getImage('logo'));
  606. }
  607. public function testGetLoginBackgroundNotExistent() {
  608. $this->imageManager->method('getImage')
  609. ->with($this->equalTo('background'))
  610. ->willThrowException(new NotFoundException());
  611. $expected = new Http\NotFoundResponse();
  612. $this->assertEquals($expected, $this->themingController->getImage('background'));
  613. }
  614. public function testGetLoginBackground() {
  615. $file = $this->createMock(ISimpleFile::class);
  616. $file->method('getName')->willReturn('background.png');
  617. $file->method('getMTime')->willReturn(42);
  618. $this->imageManager->expects($this->once())
  619. ->method('getImage')
  620. ->willReturn($file);
  621. $this->config
  622. ->expects($this->any())
  623. ->method('getAppValue')
  624. ->with('theming', 'backgroundMime', '')
  625. ->willReturn('image/png');
  626. @$expected = new Http\FileDisplayResponse($file);
  627. $expected->cacheFor(3600);
  628. $expected->addHeader('Content-Type', 'image/png');
  629. $expected->addHeader('Content-Disposition', 'attachment; filename="background"');
  630. $csp = new Http\ContentSecurityPolicy();
  631. $csp->allowInlineStyle();
  632. $expected->setContentSecurityPolicy($csp);
  633. @$this->assertEquals($expected, $this->themingController->getImage('background'));
  634. }
  635. public function testGetManifest() {
  636. $this->config
  637. ->expects($this->once())
  638. ->method('getAppValue')
  639. ->with('theming', 'cachebuster', '0')
  640. ->willReturn('0');
  641. $this->themingDefaults
  642. ->expects($this->any())
  643. ->method('getName')
  644. ->willReturn('Nextcloud');
  645. $this->urlGenerator
  646. ->expects($this->once())
  647. ->method('getBaseUrl')
  648. ->willReturn('localhost');
  649. $this->urlGenerator
  650. ->expects($this->exactly(2))
  651. ->method('linkToRoute')
  652. ->withConsecutive(
  653. ['theming.Icon.getTouchIcon', ['app' => 'core']],
  654. ['theming.Icon.getFavicon', ['app' => 'core']],
  655. )->willReturnOnConsecutiveCalls(
  656. 'touchicon',
  657. 'favicon',
  658. );
  659. $response = new Http\JSONResponse([
  660. 'name' => 'Nextcloud',
  661. 'start_url' => 'localhost',
  662. 'icons' =>
  663. [
  664. [
  665. 'src' => 'touchicon?v=0',
  666. 'type' => 'image/png',
  667. 'sizes' => '512x512'
  668. ],
  669. [
  670. 'src' => 'favicon?v=0',
  671. 'type' => 'image/svg+xml',
  672. 'sizes' => '16x16'
  673. ]
  674. ],
  675. 'display' => 'standalone',
  676. 'short_name' => 'Nextcloud',
  677. 'theme_color' => null,
  678. 'background_color' => null,
  679. 'description' => null
  680. ]);
  681. $response->cacheFor(3600);
  682. $this->assertEquals($response, $this->themingController->getManifest('core'));
  683. }
  684. }