ThemingDefaultsTest.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. * @author Bjoern Schiessle <bjoern@schiessle.org>
  7. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  8. * @author Guillaume COMPAGNON <gcompagnon@outlook.com>
  9. * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
  10. * @author Joas Schilling <coding@schilljs.com>
  11. * @author John Molakvoæ <skjnldsv@protonmail.com>
  12. * @author Julius Haertl <jus@bitgrid.net>
  13. * @author Julius Härtl <jus@bitgrid.net>
  14. * @author Lukas Reschke <lukas@statuscode.ch>
  15. * @author Michael Weimann <mail@michael-weimann.eu>
  16. * @author Morris Jobke <hey@morrisjobke.de>
  17. * @author Roeland Jago Douma <roeland@famdouma.nl>
  18. *
  19. * @license GNU AGPL version 3 or any later version
  20. *
  21. * This program is free software: you can redistribute it and/or modify
  22. * it under the terms of the GNU Affero General Public License as
  23. * published by the Free Software Foundation, either version 3 of the
  24. * License, or (at your option) any later version.
  25. *
  26. * This program is distributed in the hope that it will be useful,
  27. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  29. * GNU Affero General Public License for more details.
  30. *
  31. * You should have received a copy of the GNU Affero General Public License
  32. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  33. *
  34. */
  35. namespace OCA\Theming\Tests;
  36. use OCA\Theming\ImageManager;
  37. use OCA\Theming\Service\BackgroundService;
  38. use OCA\Theming\ThemingDefaults;
  39. use OCA\Theming\Util;
  40. use OCP\App\IAppManager;
  41. use OCP\Files\IAppData;
  42. use OCP\Files\NotFoundException;
  43. use OCP\ICache;
  44. use OCP\ICacheFactory;
  45. use OCP\IConfig;
  46. use OCP\IL10N;
  47. use OCP\INavigationManager;
  48. use OCP\IURLGenerator;
  49. use OCP\IUser;
  50. use OCP\IUserSession;
  51. use Test\TestCase;
  52. class ThemingDefaultsTest extends TestCase {
  53. /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
  54. private $config;
  55. /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
  56. private $l10n;
  57. /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
  58. private $userSession;
  59. /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
  60. private $urlGenerator;
  61. /** @var \OC_Defaults|\PHPUnit\Framework\MockObject\MockObject */
  62. private $defaults;
  63. /** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */
  64. private $appData;
  65. /** @var ICacheFactory|\PHPUnit\Framework\MockObject\MockObject */
  66. private $cacheFactory;
  67. /** @var ThemingDefaults */
  68. private $template;
  69. /** @var Util|\PHPUnit\Framework\MockObject\MockObject */
  70. private $util;
  71. /** @var ICache|\PHPUnit\Framework\MockObject\MockObject */
  72. private $cache;
  73. /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */
  74. private $appManager;
  75. /** @var ImageManager|\PHPUnit\Framework\MockObject\MockObject */
  76. private $imageManager;
  77. /** @var INavigationManager|\PHPUnit\Framework\MockObject\MockObject */
  78. private $navigationManager;
  79. /** @var BackgroundService|\PHPUnit\Framework\MockObject\MockObject */
  80. private $backgroundService;
  81. protected function setUp(): void {
  82. parent::setUp();
  83. $this->config = $this->createMock(IConfig::class);
  84. $this->l10n = $this->createMock(IL10N::class);
  85. $this->userSession = $this->createMock(IUserSession::class);
  86. $this->urlGenerator = $this->createMock(IURLGenerator::class);
  87. $this->cacheFactory = $this->createMock(ICacheFactory::class);
  88. $this->cache = $this->createMock(ICache::class);
  89. $this->util = $this->createMock(Util::class);
  90. $this->imageManager = $this->createMock(ImageManager::class);
  91. $this->appManager = $this->createMock(IAppManager::class);
  92. $this->navigationManager = $this->createMock(INavigationManager::class);
  93. $this->backgroundService = $this->createMock(BackgroundService::class);
  94. $this->defaults = new \OC_Defaults();
  95. $this->urlGenerator
  96. ->expects($this->any())
  97. ->method('getBaseUrl')
  98. ->willReturn('');
  99. $this->template = new ThemingDefaults(
  100. $this->config,
  101. $this->l10n,
  102. $this->userSession,
  103. $this->urlGenerator,
  104. $this->cacheFactory,
  105. $this->util,
  106. $this->imageManager,
  107. $this->appManager,
  108. $this->navigationManager,
  109. $this->backgroundService,
  110. );
  111. }
  112. public function testGetNameWithDefault() {
  113. $this->config
  114. ->expects($this->once())
  115. ->method('getAppValue')
  116. ->with('theming', 'name', 'Nextcloud')
  117. ->willReturn('Nextcloud');
  118. $this->assertEquals('Nextcloud', $this->template->getName());
  119. }
  120. public function testGetNameWithCustom() {
  121. $this->config
  122. ->expects($this->once())
  123. ->method('getAppValue')
  124. ->with('theming', 'name', 'Nextcloud')
  125. ->willReturn('MyCustomCloud');
  126. $this->assertEquals('MyCustomCloud', $this->template->getName());
  127. }
  128. public function testGetHTMLNameWithDefault() {
  129. $this->config
  130. ->expects($this->once())
  131. ->method('getAppValue')
  132. ->with('theming', 'name', 'Nextcloud')
  133. ->willReturn('Nextcloud');
  134. $this->assertEquals('Nextcloud', $this->template->getHTMLName());
  135. }
  136. public function testGetHTMLNameWithCustom() {
  137. $this->config
  138. ->expects($this->once())
  139. ->method('getAppValue')
  140. ->with('theming', 'name', 'Nextcloud')
  141. ->willReturn('MyCustomCloud');
  142. $this->assertEquals('MyCustomCloud', $this->template->getHTMLName());
  143. }
  144. public function testGetTitleWithDefault() {
  145. $this->config
  146. ->expects($this->once())
  147. ->method('getAppValue')
  148. ->with('theming', 'name', 'Nextcloud')
  149. ->willReturn('Nextcloud');
  150. $this->assertEquals('Nextcloud', $this->template->getTitle());
  151. }
  152. public function testGetTitleWithCustom() {
  153. $this->config
  154. ->expects($this->once())
  155. ->method('getAppValue')
  156. ->with('theming', 'name', 'Nextcloud')
  157. ->willReturn('MyCustomCloud');
  158. $this->assertEquals('MyCustomCloud', $this->template->getTitle());
  159. }
  160. public function testGetEntityWithDefault() {
  161. $this->config
  162. ->expects($this->once())
  163. ->method('getAppValue')
  164. ->with('theming', 'name', 'Nextcloud')
  165. ->willReturn('Nextcloud');
  166. $this->assertEquals('Nextcloud', $this->template->getEntity());
  167. }
  168. public function testGetEntityWithCustom() {
  169. $this->config
  170. ->expects($this->once())
  171. ->method('getAppValue')
  172. ->with('theming', 'name', 'Nextcloud')
  173. ->willReturn('MyCustomCloud');
  174. $this->assertEquals('MyCustomCloud', $this->template->getEntity());
  175. }
  176. public function testGetBaseUrlWithDefault() {
  177. $this->config
  178. ->expects($this->once())
  179. ->method('getAppValue')
  180. ->with('theming', 'url', $this->defaults->getBaseUrl())
  181. ->willReturn($this->defaults->getBaseUrl());
  182. $this->assertEquals($this->defaults->getBaseUrl(), $this->template->getBaseUrl());
  183. }
  184. public function testGetBaseUrlWithCustom() {
  185. $this->config
  186. ->expects($this->once())
  187. ->method('getAppValue')
  188. ->with('theming', 'url', $this->defaults->getBaseUrl())
  189. ->willReturn('https://example.com/');
  190. $this->assertEquals('https://example.com/', $this->template->getBaseUrl());
  191. }
  192. public function legalUrlProvider() {
  193. return [
  194. [ '' ],
  195. [ 'https://example.com/legal.html']
  196. ];
  197. }
  198. /**
  199. * @param $imprintUrl
  200. * @dataProvider legalUrlProvider
  201. */
  202. public function testGetImprintURL($imprintUrl) {
  203. $this->config
  204. ->expects($this->once())
  205. ->method('getAppValue')
  206. ->with('theming', 'imprintUrl', '')
  207. ->willReturn($imprintUrl);
  208. $this->assertEquals($imprintUrl, $this->template->getImprintUrl());
  209. }
  210. /**
  211. * @param $privacyUrl
  212. * @dataProvider legalUrlProvider
  213. */
  214. public function testGetPrivacyURL($privacyUrl) {
  215. $this->config
  216. ->expects($this->once())
  217. ->method('getAppValue')
  218. ->with('theming', 'privacyUrl', '')
  219. ->willReturn($privacyUrl);
  220. $this->assertEquals($privacyUrl, $this->template->getPrivacyUrl());
  221. }
  222. public function testGetSloganWithDefault() {
  223. $this->config
  224. ->expects($this->once())
  225. ->method('getAppValue')
  226. ->with('theming', 'slogan', $this->defaults->getSlogan())
  227. ->willReturn($this->defaults->getSlogan());
  228. $this->assertEquals($this->defaults->getSlogan(), $this->template->getSlogan());
  229. }
  230. public function testGetSloganWithCustom() {
  231. $this->config
  232. ->expects($this->once())
  233. ->method('getAppValue')
  234. ->with('theming', 'slogan', $this->defaults->getSlogan())
  235. ->willReturn('My custom Slogan');
  236. $this->assertEquals('My custom Slogan', $this->template->getSlogan());
  237. }
  238. public function testGetShortFooter() {
  239. $this->config
  240. ->expects($this->exactly(5))
  241. ->method('getAppValue')
  242. ->willReturnMap([
  243. ['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
  244. ['theming', 'name', 'Nextcloud', 'Name'],
  245. ['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
  246. ['theming', 'imprintUrl', '', ''],
  247. ['theming', 'privacyUrl', '', ''],
  248. ]);
  249. $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan', $this->template->getShortFooter());
  250. }
  251. public function testGetShortFooterEmptyUrl() {
  252. $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
  253. $this->config
  254. ->expects($this->exactly(5))
  255. ->method('getAppValue')
  256. ->willReturnMap([
  257. ['theming', 'url', $this->defaults->getBaseUrl(), ''],
  258. ['theming', 'name', 'Nextcloud', 'Name'],
  259. ['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
  260. ['theming', 'imprintUrl', '', ''],
  261. ['theming', 'privacyUrl', '', ''],
  262. ]);
  263. $this->assertEquals('<span class="entity-name">Name</span> – Slogan', $this->template->getShortFooter());
  264. }
  265. public function testGetShortFooterEmptySlogan() {
  266. $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
  267. $this->config
  268. ->expects($this->exactly(5))
  269. ->method('getAppValue')
  270. ->willReturnMap([
  271. ['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
  272. ['theming', 'name', 'Nextcloud', 'Name'],
  273. ['theming', 'slogan', $this->defaults->getSlogan(), ''],
  274. ['theming', 'imprintUrl', '', ''],
  275. ['theming', 'privacyUrl', '', ''],
  276. ]);
  277. $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a>', $this->template->getShortFooter());
  278. }
  279. public function testGetShortFooterImprint() {
  280. $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
  281. $this->config
  282. ->expects($this->exactly(5))
  283. ->method('getAppValue')
  284. ->willReturnMap([
  285. ['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
  286. ['theming', 'name', 'Nextcloud', 'Name'],
  287. ['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
  288. ['theming', 'imprintUrl', '', 'https://example.com/imprint'],
  289. ['theming', 'privacyUrl', '', ''],
  290. ]);
  291. $this->l10n
  292. ->expects($this->any())
  293. ->method('t')
  294. ->willReturnArgument(0);
  295. $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan<br/><a href="https://example.com/imprint" class="legal" target="_blank" rel="noreferrer noopener">Legal notice</a>', $this->template->getShortFooter());
  296. }
  297. public function testGetShortFooterPrivacy() {
  298. $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
  299. $this->config
  300. ->expects($this->exactly(5))
  301. ->method('getAppValue')
  302. ->willReturnMap([
  303. ['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
  304. ['theming', 'name', 'Nextcloud', 'Name'],
  305. ['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
  306. ['theming', 'imprintUrl', '', ''],
  307. ['theming', 'privacyUrl', '', 'https://example.com/privacy'],
  308. ]);
  309. $this->l10n
  310. ->expects($this->any())
  311. ->method('t')
  312. ->willReturnArgument(0);
  313. $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan<br/><a href="https://example.com/privacy" class="legal" target="_blank" rel="noreferrer noopener">Privacy policy</a>', $this->template->getShortFooter());
  314. }
  315. public function testGetShortFooterAllLegalLinks() {
  316. $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
  317. $this->config
  318. ->expects($this->exactly(5))
  319. ->method('getAppValue')
  320. ->willReturnMap([
  321. ['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
  322. ['theming', 'name', 'Nextcloud', 'Name'],
  323. ['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
  324. ['theming', 'imprintUrl', '', 'https://example.com/imprint'],
  325. ['theming', 'privacyUrl', '', 'https://example.com/privacy'],
  326. ]);
  327. $this->l10n
  328. ->expects($this->any())
  329. ->method('t')
  330. ->willReturnArgument(0);
  331. $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan<br/><a href="https://example.com/imprint" class="legal" target="_blank" rel="noreferrer noopener">Legal notice</a> · <a href="https://example.com/privacy" class="legal" target="_blank" rel="noreferrer noopener">Privacy policy</a>', $this->template->getShortFooter());
  332. }
  333. public function invalidLegalUrlProvider() {
  334. return [
  335. ['example.com/legal'], # missing scheme
  336. ['https:///legal'], # missing host
  337. ];
  338. }
  339. /**
  340. * @param $invalidImprintUrl
  341. * @dataProvider invalidLegalUrlProvider
  342. */
  343. public function testGetShortFooterInvalidImprint($invalidImprintUrl) {
  344. $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
  345. $this->config
  346. ->expects($this->exactly(5))
  347. ->method('getAppValue')
  348. ->willReturnMap([
  349. ['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
  350. ['theming', 'name', 'Nextcloud', 'Name'],
  351. ['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
  352. ['theming', 'imprintUrl', '', $invalidImprintUrl],
  353. ['theming', 'privacyUrl', '', ''],
  354. ]);
  355. $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan', $this->template->getShortFooter());
  356. }
  357. /**
  358. * @param $invalidPrivacyUrl
  359. * @dataProvider invalidLegalUrlProvider
  360. */
  361. public function testGetShortFooterInvalidPrivacy($invalidPrivacyUrl) {
  362. $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
  363. $this->config
  364. ->expects($this->exactly(5))
  365. ->method('getAppValue')
  366. ->willReturnMap([
  367. ['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
  368. ['theming', 'name', 'Nextcloud', 'Name'],
  369. ['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
  370. ['theming', 'imprintUrl', '', ''],
  371. ['theming', 'privacyUrl', '', $invalidPrivacyUrl],
  372. ]);
  373. $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan', $this->template->getShortFooter());
  374. }
  375. public function testGetColorPrimaryWithDefault() {
  376. $this->config
  377. ->expects($this->exactly(2))
  378. ->method('getAppValue')
  379. ->willReturnMap([
  380. ['theming', 'disable-user-theming', 'no', 'no'],
  381. ['theming', 'primary_color', '', $this->defaults->getColorPrimary()],
  382. ]);
  383. $this->assertEquals($this->defaults->getColorPrimary(), $this->template->getColorPrimary());
  384. }
  385. public function testGetColorPrimaryWithCustom() {
  386. $this->config
  387. ->expects($this->exactly(2))
  388. ->method('getAppValue')
  389. ->willReturnMap([
  390. ['theming', 'disable-user-theming', 'no', 'no'],
  391. ['theming', 'primary_color', '', '#fff'],
  392. ]);
  393. $this->assertEquals('#fff', $this->template->getColorPrimary());
  394. }
  395. public function dataGetColorPrimary() {
  396. return [
  397. 'with fallback default' => [
  398. 'disableTheming' => 'no',
  399. 'primaryColor' => '',
  400. 'userPrimaryColor' => '',
  401. 'expected' => BackgroundService::DEFAULT_COLOR,
  402. ],
  403. 'with custom admin primary' => [
  404. 'disableTheming' => 'no',
  405. 'primaryColor' => '#aaa',
  406. 'userPrimaryColor' => '',
  407. 'expected' => '#aaa',
  408. ],
  409. 'with custom invalid admin primary' => [
  410. 'disableTheming' => 'no',
  411. 'primaryColor' => 'invalid',
  412. 'userPrimaryColor' => '',
  413. 'expected' => BackgroundService::DEFAULT_COLOR,
  414. ],
  415. 'with custom invalid user primary' => [
  416. 'disableTheming' => 'no',
  417. 'primaryColor' => '',
  418. 'userPrimaryColor' => 'invalid-name',
  419. 'expected' => BackgroundService::DEFAULT_COLOR,
  420. ],
  421. 'with custom user primary' => [
  422. 'disableTheming' => 'no',
  423. 'primaryColor' => '',
  424. 'userPrimaryColor' => '#bbb',
  425. 'expected' => '#bbb',
  426. ],
  427. 'with disabled user theming primary' => [
  428. 'disableTheming' => 'yes',
  429. 'primaryColor' => '#aaa',
  430. 'userPrimaryColor' => '#bbb',
  431. 'expected' => '#aaa',
  432. ],
  433. ];
  434. }
  435. /**
  436. * @dataProvider dataGetColorPrimary
  437. */
  438. public function testGetColorPrimary(string $disableTheming, string $primaryColor, string $userPrimaryColor, string $expected) {
  439. $user = $this->createMock(IUser::class);
  440. $this->userSession->expects($this->any())
  441. ->method('getUser')
  442. ->willReturn($user);
  443. $user->expects($this->any())
  444. ->method('getUID')
  445. ->willReturn('user');
  446. $this->config
  447. ->expects($this->any())
  448. ->method('getAppValue')
  449. ->willReturnMap([
  450. ['theming', 'disable-user-theming', 'no', $disableTheming],
  451. ['theming', 'primary_color', '', $primaryColor],
  452. ]);
  453. $this->config
  454. ->expects($this->any())
  455. ->method('getUserValue')
  456. ->with('user', 'theming', 'primary_color', '')
  457. ->willReturn($userPrimaryColor);
  458. $this->assertEquals($expected, $this->template->getColorPrimary());
  459. }
  460. public function testSet() {
  461. $this->config
  462. ->expects($this->exactly(2))
  463. ->method('setAppValue')
  464. ->withConsecutive(
  465. ['theming', 'MySetting', 'MyValue'],
  466. ['theming', 'cachebuster', 16],
  467. );
  468. $this->config
  469. ->expects($this->once())
  470. ->method('getAppValue')
  471. ->with('theming', 'cachebuster', '0')
  472. ->willReturn('15');
  473. $this->cacheFactory
  474. ->expects($this->exactly(2))
  475. ->method('createDistributed')
  476. ->withConsecutive(
  477. ['theming-'],
  478. ['imagePath'],
  479. )
  480. ->willReturn($this->cache);
  481. $this->cache
  482. ->expects($this->any())
  483. ->method('clear')
  484. ->with('');
  485. $this->template->set('MySetting', 'MyValue');
  486. }
  487. public function testUndoName() {
  488. $this->config
  489. ->expects($this->once())
  490. ->method('deleteAppValue')
  491. ->with('theming', 'name');
  492. $this->config
  493. ->expects($this->exactly(2))
  494. ->method('getAppValue')
  495. ->withConsecutive(
  496. ['theming', 'cachebuster', '0'],
  497. ['theming', 'name', 'Nextcloud'],
  498. )->willReturnOnConsecutiveCalls(
  499. '15',
  500. 'Nextcloud',
  501. );
  502. $this->config
  503. ->expects($this->once())
  504. ->method('setAppValue')
  505. ->with('theming', 'cachebuster', 16);
  506. $this->assertSame('Nextcloud', $this->template->undo('name'));
  507. }
  508. public function testUndoBaseUrl() {
  509. $this->config
  510. ->expects($this->once())
  511. ->method('deleteAppValue')
  512. ->with('theming', 'url');
  513. $this->config
  514. ->expects($this->exactly(2))
  515. ->method('getAppValue')
  516. ->withConsecutive(
  517. ['theming', 'cachebuster', '0'],
  518. ['theming', 'url', $this->defaults->getBaseUrl()],
  519. )->willReturnOnConsecutiveCalls(
  520. '15',
  521. $this->defaults->getBaseUrl(),
  522. );
  523. $this->config
  524. ->expects($this->once())
  525. ->method('setAppValue')
  526. ->with('theming', 'cachebuster', 16);
  527. $this->assertSame($this->defaults->getBaseUrl(), $this->template->undo('url'));
  528. }
  529. public function testUndoSlogan() {
  530. $this->config
  531. ->expects($this->once())
  532. ->method('deleteAppValue')
  533. ->with('theming', 'slogan');
  534. $this->config
  535. ->expects($this->exactly(2))
  536. ->method('getAppValue')
  537. ->withConsecutive(
  538. ['theming', 'cachebuster', '0'],
  539. ['theming', 'slogan', $this->defaults->getSlogan()],
  540. )->willReturnOnConsecutiveCalls(
  541. '15',
  542. $this->defaults->getSlogan(),
  543. );
  544. $this->config
  545. ->expects($this->once())
  546. ->method('setAppValue')
  547. ->with('theming', 'cachebuster', 16);
  548. $this->assertSame($this->defaults->getSlogan(), $this->template->undo('slogan'));
  549. }
  550. public function testUndoPrimaryColor() {
  551. $this->config
  552. ->expects($this->once())
  553. ->method('deleteAppValue')
  554. ->with('theming', 'primary_color');
  555. $this->config
  556. ->expects($this->once())
  557. ->method('getAppValue')
  558. ->with('theming', 'cachebuster', '0')
  559. ->willReturn('15');
  560. $this->config
  561. ->expects($this->once())
  562. ->method('setAppValue')
  563. ->with('theming', 'cachebuster', 16);
  564. $this->assertSame($this->defaults->getColorPrimary(), $this->template->undo('primary_color'));
  565. }
  566. public function testUndoDefaultAction() {
  567. $this->config
  568. ->expects($this->once())
  569. ->method('deleteAppValue')
  570. ->with('theming', 'defaultitem');
  571. $this->config
  572. ->expects($this->once())
  573. ->method('getAppValue')
  574. ->with('theming', 'cachebuster', '0')
  575. ->willReturn('15');
  576. $this->config
  577. ->expects($this->once())
  578. ->method('setAppValue')
  579. ->with('theming', 'cachebuster', 16);
  580. $this->assertSame('', $this->template->undo('defaultitem'));
  581. }
  582. public function testGetBackground() {
  583. $this->imageManager
  584. ->expects($this->once())
  585. ->method('getImageUrl')
  586. ->with('background')
  587. ->willReturn('custom-background?v=0');
  588. $this->assertEquals('custom-background?v=0', $this->template->getBackground());
  589. }
  590. private function getLogoHelper($withName, $useSvg) {
  591. $this->imageManager->expects($this->any())
  592. ->method('getImage')
  593. ->with('logo')
  594. ->willThrowException(new NotFoundException());
  595. $this->config
  596. ->expects($this->exactly(2))
  597. ->method('getAppValue')
  598. ->withConsecutive(
  599. ['theming', 'logoMime'],
  600. ['theming', 'cachebuster', '0'],
  601. )->willReturnOnConsecutiveCalls(
  602. '',
  603. '0'
  604. );
  605. $this->urlGenerator->expects($this->once())
  606. ->method('imagePath')
  607. ->with('core', $withName)
  608. ->willReturn('core-logo');
  609. $this->assertEquals('core-logo?v=0', $this->template->getLogo($useSvg));
  610. }
  611. public function testGetLogoDefaultWithSvg() {
  612. $this->getLogoHelper('logo/logo.svg', true);
  613. }
  614. public function testGetLogoDefaultWithoutSvg() {
  615. $this->getLogoHelper('logo/logo.png', false);
  616. }
  617. public function testGetLogoCustom() {
  618. $this->config
  619. ->expects($this->exactly(2))
  620. ->method('getAppValue')
  621. ->withConsecutive(
  622. ['theming', 'logoMime', false],
  623. ['theming', 'cachebuster', '0'],
  624. )->willReturnOnConsecutiveCalls(
  625. 'image/svg+xml',
  626. '0',
  627. );
  628. $this->urlGenerator->expects($this->once())
  629. ->method('linkToRoute')
  630. ->with('theming.Theming.getImage')
  631. ->willReturn('custom-logo?v=0');
  632. $this->assertEquals('custom-logo' . '?v=0', $this->template->getLogo());
  633. }
  634. public function testGetScssVariablesCached() {
  635. $this->config->expects($this->any())->method('getAppValue')->with('theming', 'cachebuster', '0')->willReturn('1');
  636. $this->cacheFactory->expects($this->once())
  637. ->method('createDistributed')
  638. ->with('theming-1-')
  639. ->willReturn($this->cache);
  640. $this->cache->expects($this->once())->method('get')->with('getScssVariables')->willReturn(['foo' => 'bar']);
  641. $this->assertEquals(['foo' => 'bar'], $this->template->getScssVariables());
  642. }
  643. public function testGetScssVariables() {
  644. $this->config
  645. ->expects($this->any())
  646. ->method('getAppValue')
  647. ->willReturnMap([
  648. ['theming', 'cachebuster', '0', '0'],
  649. ['theming', 'logoMime', '', 'jpeg'],
  650. ['theming', 'backgroundMime', '', 'jpeg'],
  651. ['theming', 'logoheaderMime', '', 'jpeg'],
  652. ['theming', 'faviconMime', '', 'jpeg'],
  653. ['theming', 'primary_color', '', $this->defaults->getColorPrimary()],
  654. ['theming', 'primary_color', $this->defaults->getColorPrimary(), $this->defaults->getColorPrimary()],
  655. ]);
  656. $this->util->expects($this->any())->method('invertTextColor')->with($this->defaults->getColorPrimary())->willReturn(false);
  657. $this->util->expects($this->any())->method('elementColor')->with($this->defaults->getColorPrimary())->willReturn('#aaaaaa');
  658. $this->cacheFactory->expects($this->once())
  659. ->method('createDistributed')
  660. ->with('theming-0-')
  661. ->willReturn($this->cache);
  662. $this->cache->expects($this->once())->method('get')->with('getScssVariables')->willReturn(null);
  663. $this->imageManager->expects($this->exactly(4))
  664. ->method('getImageUrl')
  665. ->willReturnMap([
  666. ['logo', 'custom-logo?v=0'],
  667. ['logoheader', 'custom-logoheader?v=0'],
  668. ['favicon', 'custom-favicon?v=0'],
  669. ['background', 'custom-background?v=0'],
  670. ]);
  671. $expected = [
  672. 'theming-cachebuster' => '\'0\'',
  673. 'theming-logo-mime' => '\'jpeg\'',
  674. 'theming-background-mime' => '\'jpeg\'',
  675. 'image-logo' => "url('custom-logo?v=0')",
  676. 'image-login-background' => "url('custom-background?v=0')",
  677. 'color-primary' => $this->defaults->getColorPrimary(),
  678. 'color-primary-text' => '#ffffff',
  679. 'image-login-plain' => 'false',
  680. 'color-primary-element' => '#aaaaaa',
  681. 'theming-logoheader-mime' => '\'jpeg\'',
  682. 'theming-favicon-mime' => '\'jpeg\'',
  683. 'image-logoheader' => "url('custom-logoheader?v=0')",
  684. 'image-favicon' => "url('custom-favicon?v=0')",
  685. 'has-legal-links' => 'false'
  686. ];
  687. $this->assertEquals($expected, $this->template->getScssVariables());
  688. }
  689. public function testGetDefaultAndroidURL() {
  690. $this->config
  691. ->expects($this->once())
  692. ->method('getAppValue')
  693. ->with('theming', 'AndroidClientUrl', 'https://play.google.com/store/apps/details?id=com.nextcloud.client')
  694. ->willReturn('https://play.google.com/store/apps/details?id=com.nextcloud.client');
  695. $this->assertEquals('https://play.google.com/store/apps/details?id=com.nextcloud.client', $this->template->getAndroidClientUrl());
  696. }
  697. public function testGetCustomAndroidURL() {
  698. $this->config
  699. ->expects($this->once())
  700. ->method('getAppValue')
  701. ->with('theming', 'AndroidClientUrl', 'https://play.google.com/store/apps/details?id=com.nextcloud.client')
  702. ->willReturn('https://play.google.com/store/apps/details?id=com.mycloud.client');
  703. $this->assertEquals('https://play.google.com/store/apps/details?id=com.mycloud.client', $this->template->getAndroidClientUrl());
  704. }
  705. public function testGetDefaultiOSURL() {
  706. $this->config
  707. ->expects($this->once())
  708. ->method('getAppValue')
  709. ->with('theming', 'iOSClientUrl', 'https://geo.itunes.apple.com/us/app/nextcloud/id1125420102?mt=8')
  710. ->willReturn('https://geo.itunes.apple.com/us/app/nextcloud/id1125420102?mt=8');
  711. $this->assertEquals('https://geo.itunes.apple.com/us/app/nextcloud/id1125420102?mt=8', $this->template->getiOSClientUrl());
  712. }
  713. public function testGetCustomiOSURL() {
  714. $this->config
  715. ->expects($this->once())
  716. ->method('getAppValue')
  717. ->with('theming', 'iOSClientUrl', 'https://geo.itunes.apple.com/us/app/nextcloud/id1125420102?mt=8')
  718. ->willReturn('https://geo.itunes.apple.com/us/app/nextcloud/id1234567890?mt=8');
  719. $this->assertEquals('https://geo.itunes.apple.com/us/app/nextcloud/id1234567890?mt=8', $this->template->getiOSClientUrl());
  720. }
  721. public function testGetDefaultiTunesAppId() {
  722. $this->config
  723. ->expects($this->once())
  724. ->method('getAppValue')
  725. ->with('theming', 'iTunesAppId', '1125420102')
  726. ->willReturn('1125420102');
  727. $this->assertEquals('1125420102', $this->template->getiTunesAppId());
  728. }
  729. public function testGetCustomiTunesAppId() {
  730. $this->config
  731. ->expects($this->once())
  732. ->method('getAppValue')
  733. ->with('theming', 'iTunesAppId', '1125420102')
  734. ->willReturn('1234567890');
  735. $this->assertEquals('1234567890', $this->template->getiTunesAppId());
  736. }
  737. public function dataReplaceImagePath() {
  738. return [
  739. ['core', 'test.png', false],
  740. ['core', 'manifest.json'],
  741. ['core', 'favicon.ico'],
  742. ['core', 'favicon-touch.png']
  743. ];
  744. }
  745. /** @dataProvider dataReplaceImagePath */
  746. public function testReplaceImagePath($app, $image, $result = 'themingRoute?v=1234abcd') {
  747. $this->cache->expects($this->any())
  748. ->method('get')
  749. ->with('shouldReplaceIcons')
  750. ->willReturn(true);
  751. $this->config
  752. ->expects($this->any())
  753. ->method('getAppValue')
  754. ->with('theming', 'cachebuster', '0')
  755. ->willReturn('0');
  756. $this->urlGenerator
  757. ->expects($this->any())
  758. ->method('linkToRoute')
  759. ->willReturn('themingRoute');
  760. if ($result) {
  761. $this->util
  762. ->expects($this->once())
  763. ->method('getCacheBuster')
  764. ->willReturn('1234abcd');
  765. }
  766. $this->assertEquals($result, $this->template->replaceImagePath($app, $image));
  767. }
  768. }