FactoryTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. <?php
  2. /**
  3. * Copyright (c) 2016 Joas Schilling <nickvergessen@owncloud.com>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file.
  7. */
  8. namespace Test\L10N;
  9. use OC\L10N\Factory;
  10. use OCP\IConfig;
  11. use OCP\IRequest;
  12. use OCP\IUser;
  13. use OCP\IUserSession;
  14. use Test\TestCase;
  15. /**
  16. * Class FactoryTest
  17. *
  18. * @package Test\L10N
  19. */
  20. class FactoryTest extends TestCase {
  21. /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
  22. protected $config;
  23. /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */
  24. protected $request;
  25. /** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */
  26. protected $userSession;
  27. /** @var string */
  28. protected $serverRoot;
  29. public function setUp() {
  30. parent::setUp();
  31. $this->config = $this->getMockBuilder(IConfig::class)
  32. ->disableOriginalConstructor()
  33. ->getMock();
  34. $this->request = $this->getMockBuilder(IRequest::class)
  35. ->disableOriginalConstructor()
  36. ->getMock();
  37. $this->userSession = $this->getMockBuilder(IUserSession::class)
  38. ->disableOriginalConstructor()
  39. ->getMock();
  40. $this->serverRoot = \OC::$SERVERROOT;
  41. }
  42. /**
  43. * @param array $methods
  44. * @return Factory|\PHPUnit_Framework_MockObject_MockObject
  45. */
  46. protected function getFactory(array $methods = []) {
  47. if (!empty($methods)) {
  48. return $this->getMockBuilder(Factory::class)
  49. ->setConstructorArgs([
  50. $this->config,
  51. $this->request,
  52. $this->userSession,
  53. $this->serverRoot,
  54. ])
  55. ->setMethods($methods)
  56. ->getMock();
  57. } else {
  58. return new Factory($this->config, $this->request, $this->userSession, $this->serverRoot);
  59. }
  60. }
  61. public function dataFindAvailableLanguages() {
  62. return [
  63. [null],
  64. ['files'],
  65. ];
  66. }
  67. public function testFindLanguageWithExistingRequestLanguageAndNoApp() {
  68. $factory = $this->getFactory(['languageExists']);
  69. $this->invokePrivate($factory, 'requestLanguage', ['de']);
  70. $factory->expects($this->once())
  71. ->method('languageExists')
  72. ->with(null, 'de')
  73. ->willReturn(true);
  74. $this->assertSame('de', $factory->findLanguage());
  75. }
  76. public function testFindLanguageWithExistingRequestLanguageAndApp() {
  77. $factory = $this->getFactory(['languageExists']);
  78. $this->invokePrivate($factory, 'requestLanguage', ['de']);
  79. $factory->expects($this->once())
  80. ->method('languageExists')
  81. ->with('MyApp', 'de')
  82. ->willReturn(true);
  83. $this->assertSame('de', $factory->findLanguage('MyApp'));
  84. }
  85. public function testFindLanguageWithNotExistingRequestLanguageAndExistingStoredUserLanguage() {
  86. $factory = $this->getFactory(['languageExists']);
  87. $this->invokePrivate($factory, 'requestLanguage', ['de']);
  88. $factory->expects($this->at(0))
  89. ->method('languageExists')
  90. ->with('MyApp', 'de')
  91. ->willReturn(false);
  92. $this->config
  93. ->expects($this->once())
  94. ->method('getSystemValue')
  95. ->with('installed', false)
  96. ->willReturn(true);
  97. $user = $this->getMockBuilder(IUser::class)
  98. ->getMock();
  99. $user->expects($this->once())
  100. ->method('getUID')
  101. ->willReturn('MyUserUid');
  102. $this->userSession
  103. ->expects($this->exactly(2))
  104. ->method('getUser')
  105. ->willReturn($user);
  106. $this->config
  107. ->expects($this->once())
  108. ->method('getUserValue')
  109. ->with('MyUserUid', 'core', 'lang', null)
  110. ->willReturn('jp');
  111. $factory->expects($this->at(1))
  112. ->method('languageExists')
  113. ->with('MyApp', 'jp')
  114. ->willReturn(true);
  115. $this->assertSame('jp', $factory->findLanguage('MyApp'));
  116. }
  117. public function testFindLanguageWithNotExistingRequestLanguageAndNotExistingStoredUserLanguage() {
  118. $factory = $this->getFactory(['languageExists']);
  119. $this->invokePrivate($factory, 'requestLanguage', ['de']);
  120. $factory->expects($this->at(0))
  121. ->method('languageExists')
  122. ->with('MyApp', 'de')
  123. ->willReturn(false);
  124. $this->config
  125. ->expects($this->at(0))
  126. ->method('getSystemValue')
  127. ->with('installed', false)
  128. ->willReturn(true);
  129. $user = $this->getMockBuilder(IUser::class)
  130. ->getMock();
  131. $user->expects($this->once())
  132. ->method('getUID')
  133. ->willReturn('MyUserUid');
  134. $this->userSession
  135. ->expects($this->exactly(2))
  136. ->method('getUser')
  137. ->willReturn($user);
  138. $this->config
  139. ->expects($this->once())
  140. ->method('getUserValue')
  141. ->with('MyUserUid', 'core', 'lang', null)
  142. ->willReturn('jp');
  143. $factory->expects($this->at(1))
  144. ->method('languageExists')
  145. ->with('MyApp', 'jp')
  146. ->willReturn(false);
  147. $this->config
  148. ->expects($this->at(2))
  149. ->method('getSystemValue')
  150. ->with('default_language', false)
  151. ->willReturn('es');
  152. $factory->expects($this->at(2))
  153. ->method('languageExists')
  154. ->with('MyApp', 'es')
  155. ->willReturn(true);
  156. $this->assertSame('es', $factory->findLanguage('MyApp'));
  157. }
  158. public function testFindLanguageWithNotExistingRequestLanguageAndNotExistingStoredUserLanguageAndNotExistingDefault() {
  159. $factory = $this->getFactory(['languageExists']);
  160. $this->invokePrivate($factory, 'requestLanguage', ['de']);
  161. $factory->expects($this->at(0))
  162. ->method('languageExists')
  163. ->with('MyApp', 'de')
  164. ->willReturn(false);
  165. $this->config
  166. ->expects($this->at(0))
  167. ->method('getSystemValue')
  168. ->with('installed', false)
  169. ->willReturn(true);
  170. $user = $this->getMockBuilder(IUser::class)
  171. ->getMock();
  172. $user->expects($this->once())
  173. ->method('getUID')
  174. ->willReturn('MyUserUid');
  175. $this->userSession
  176. ->expects($this->exactly(2))
  177. ->method('getUser')
  178. ->willReturn($user);
  179. $this->config
  180. ->expects($this->once())
  181. ->method('getUserValue')
  182. ->with('MyUserUid', 'core', 'lang', null)
  183. ->willReturn('jp');
  184. $factory->expects($this->at(1))
  185. ->method('languageExists')
  186. ->with('MyApp', 'jp')
  187. ->willReturn(false);
  188. $this->config
  189. ->expects($this->at(2))
  190. ->method('getSystemValue')
  191. ->with('default_language', false)
  192. ->willReturn('es');
  193. $factory->expects($this->at(2))
  194. ->method('languageExists')
  195. ->with('MyApp', 'es')
  196. ->willReturn(false);
  197. $this->config
  198. ->expects($this->never())
  199. ->method('setUserValue');
  200. $this->assertSame('en', $factory->findLanguage('MyApp'));
  201. }
  202. public function testFindLanguageWithNotExistingRequestLanguageAndNotExistingStoredUserLanguageAndNotExistingDefaultAndNoAppInScope() {
  203. $factory = $this->getFactory(['languageExists']);
  204. $this->invokePrivate($factory, 'requestLanguage', ['de']);
  205. $factory->expects($this->at(0))
  206. ->method('languageExists')
  207. ->with('MyApp', 'de')
  208. ->willReturn(false);
  209. $this->config
  210. ->expects($this->at(0))
  211. ->method('getSystemValue')
  212. ->with('installed', false)
  213. ->willReturn(true);
  214. $user = $this->getMockBuilder(IUser::class)
  215. ->getMock();
  216. $user->expects($this->once())
  217. ->method('getUID')
  218. ->willReturn('MyUserUid');
  219. $this->userSession
  220. ->expects($this->exactly(2))
  221. ->method('getUser')
  222. ->willReturn($user);
  223. $this->config
  224. ->expects($this->once())
  225. ->method('getUserValue')
  226. ->with('MyUserUid', 'core', 'lang', null)
  227. ->willReturn('jp');
  228. $factory->expects($this->at(1))
  229. ->method('languageExists')
  230. ->with('MyApp', 'jp')
  231. ->willReturn(false);
  232. $this->config
  233. ->expects($this->at(2))
  234. ->method('getSystemValue')
  235. ->with('default_language', false)
  236. ->willReturn('es');
  237. $factory->expects($this->at(2))
  238. ->method('languageExists')
  239. ->with('MyApp', 'es')
  240. ->willReturn(false);
  241. $this->config
  242. ->expects($this->never())
  243. ->method('setUserValue')
  244. ->with('MyUserUid', 'core', 'lang', 'en');
  245. $this->assertSame('en', $factory->findLanguage('MyApp'));
  246. }
  247. /**
  248. * @dataProvider dataFindAvailableLanguages
  249. *
  250. * @param string|null $app
  251. */
  252. public function testFindAvailableLanguages($app) {
  253. $factory = $this->getFactory(['findL10nDir']);
  254. $factory->expects($this->once())
  255. ->method('findL10nDir')
  256. ->with($app)
  257. ->willReturn(\OC::$SERVERROOT . '/tests/data/l10n/');
  258. $this->assertEquals(['cs', 'de', 'en', 'ru'], $factory->findAvailableLanguages($app), '', 0.0, 10, true);
  259. }
  260. public function dataLanguageExists() {
  261. return [
  262. [null, 'en', [], true],
  263. [null, 'de', [], false],
  264. [null, 'de', ['ru'], false],
  265. [null, 'de', ['ru', 'de'], true],
  266. ['files', 'en', [], true],
  267. ['files', 'de', [], false],
  268. ['files', 'de', ['ru'], false],
  269. ['files', 'de', ['de', 'ru'], true],
  270. ];
  271. }
  272. public function testFindAvailableLanguagesWithThemes() {
  273. $this->serverRoot .= '/tests/data';
  274. $app = 'files';
  275. $factory = $this->getFactory(['findL10nDir']);
  276. $factory->expects($this->once())
  277. ->method('findL10nDir')
  278. ->with($app)
  279. ->willReturn($this->serverRoot . '/apps/files/l10n/');
  280. $this->config
  281. ->expects($this->once())
  282. ->method('getSystemValue')
  283. ->with('theme')
  284. ->willReturn('abc');
  285. $this->assertEquals(['en', 'zz'], $factory->findAvailableLanguages($app), '', 0.0, 10, true);
  286. }
  287. /**
  288. * @dataProvider dataLanguageExists
  289. *
  290. * @param string|null $app
  291. * @param string $lang
  292. * @param string[] $availableLanguages
  293. * @param string $expected
  294. */
  295. public function testLanguageExists($app, $lang, array $availableLanguages, $expected) {
  296. $factory = $this->getFactory(['findAvailableLanguages']);
  297. $factory->expects(($lang === 'en') ? $this->never() : $this->once())
  298. ->method('findAvailableLanguages')
  299. ->with($app)
  300. ->willReturn($availableLanguages);
  301. $this->assertSame($expected, $factory->languageExists($app, $lang));
  302. }
  303. public function dataSetLanguageFromRequest() {
  304. return [
  305. // Language is available
  306. [null, 'de', null, ['de'], 'de', 'de'],
  307. [null, 'de,en', null, ['de'], 'de', 'de'],
  308. [null, 'de-DE,en-US;q=0.8,en;q=0.6', null, ['de'], 'de', 'de'],
  309. // Language is not available
  310. [null, 'de', null, ['ru'], 'en', 'en'],
  311. [null, 'de,en', null, ['ru', 'en'], 'en', 'en'],
  312. [null, 'de-DE,en-US;q=0.8,en;q=0.6', null, ['ru', 'en'], 'en', 'en'],
  313. // Language is available, but request language is set
  314. [null, 'de', 'ru', ['de'], 'de', 'ru'],
  315. [null, 'de,en', 'ru', ['de'], 'de', 'ru'],
  316. [null, 'de-DE,en-US;q=0.8,en;q=0.6', 'ru', ['de'], 'de', 'ru'],
  317. // Request lang should not be set for apps: Language is available
  318. ['files_pdfviewer', 'de', null, ['de'], 'de', ''],
  319. ['files_pdfviewer', 'de,en', null, ['de'], 'de', ''],
  320. ['files_pdfviewer', 'de-DE,en-US;q=0.8,en;q=0.6', null, ['de'], 'de', ''],
  321. // Request lang should not be set for apps: Language is not available
  322. ['files_pdfviewer', 'de', null, ['ru'], 'en', ''],
  323. ['files_pdfviewer', 'de,en', null, ['ru', 'en'], 'en', ''],
  324. ['files_pdfviewer', 'de-DE,en-US;q=0.8,en;q=0.6', null, ['ru', 'en'], 'en', ''],
  325. ];
  326. }
  327. /**
  328. * @dataProvider dataSetLanguageFromRequest
  329. *
  330. * @param string|null $app
  331. * @param string $header
  332. * @param string|null $requestLanguage
  333. * @param string[] $availableLanguages
  334. * @param string $expected
  335. * @param string $expectedLang
  336. */
  337. public function testSetLanguageFromRequest($app, $header, $requestLanguage, array $availableLanguages, $expected, $expectedLang) {
  338. $factory = $this->getFactory(['findAvailableLanguages']);
  339. $factory->expects($this->once())
  340. ->method('findAvailableLanguages')
  341. ->with($app)
  342. ->willReturn($availableLanguages);
  343. $this->request->expects($this->once())
  344. ->method('getHeader')
  345. ->with('ACCEPT_LANGUAGE')
  346. ->willReturn($header);
  347. if ($requestLanguage !== null) {
  348. $this->invokePrivate($factory, 'requestLanguage', [$requestLanguage]);
  349. }
  350. $this->assertSame($expected, $factory->setLanguageFromRequest($app), 'Asserting returned language');
  351. $this->assertSame($expectedLang, $this->invokePrivate($factory, 'requestLanguage'), 'Asserting stored language');
  352. }
  353. public function dataGetL10nFilesForApp() {
  354. return [
  355. [null, 'de', [\OC::$SERVERROOT . '/core/l10n/de.json']],
  356. ['core', 'ru', [\OC::$SERVERROOT . '/core/l10n/ru.json']],
  357. ['lib', 'ru', [\OC::$SERVERROOT . '/lib/l10n/ru.json']],
  358. ['settings', 'de', [\OC::$SERVERROOT . '/settings/l10n/de.json']],
  359. ['files', 'de', [\OC::$SERVERROOT . '/apps/files/l10n/de.json']],
  360. ['files', '_lang_never_exists_', []],
  361. ['_app_never_exists_', 'de', [\OC::$SERVERROOT . '/core/l10n/de.json']],
  362. ];
  363. }
  364. /**
  365. * @dataProvider dataGetL10nFilesForApp
  366. *
  367. * @param string|null $app
  368. * @param string $expected
  369. */
  370. public function testGetL10nFilesForApp($app, $lang, $expected) {
  371. $factory = $this->getFactory();
  372. $this->assertSame($expected, $this->invokePrivate($factory, 'getL10nFilesForApp', [$app, $lang]));
  373. }
  374. public function dataFindL10NDir() {
  375. return [
  376. [null, \OC::$SERVERROOT . '/core/l10n/'],
  377. ['core', \OC::$SERVERROOT . '/core/l10n/'],
  378. ['lib', \OC::$SERVERROOT . '/lib/l10n/'],
  379. ['settings', \OC::$SERVERROOT . '/settings/l10n/'],
  380. ['files', \OC::$SERVERROOT . '/apps/files/l10n/'],
  381. ['_app_never_exists_', \OC::$SERVERROOT . '/core/l10n/'],
  382. ];
  383. }
  384. /**
  385. * @dataProvider dataFindL10NDir
  386. *
  387. * @param string|null $app
  388. * @param string $expected
  389. */
  390. public function testFindL10NDir($app, $expected) {
  391. $factory = $this->getFactory();
  392. $this->assertSame($expected, $this->invokePrivate($factory, 'findL10nDir', [$app]));
  393. }
  394. public function dataCreatePluralFunction() {
  395. return [
  396. ['nplurals=2; plural=(n != 1);', 0, 1],
  397. ['nplurals=2; plural=(n != 1);', 1, 0],
  398. ['nplurals=2; plural=(n != 1);', 2, 1],
  399. ['nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;', 0, 2],
  400. ['nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;', 1, 0],
  401. ['nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;', 2, 1],
  402. ['nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;', 3, 1],
  403. ['nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;', 4, 1],
  404. ['nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;', 5, 2],
  405. ];
  406. }
  407. /**
  408. * @dataProvider dataCreatePluralFunction
  409. *
  410. * @param string $function
  411. * @param int $count
  412. * @param int $expected
  413. */
  414. public function testCreatePluralFunction($function, $count, $expected) {
  415. $factory = $this->getFactory();
  416. $fn = $factory->createPluralFunction($function);
  417. $this->assertEquals($expected, $fn($count));
  418. }
  419. public function dataFindLanguage() {
  420. return [
  421. // Not logged in
  422. [false, [], 'en'],
  423. [false, ['fr'], 'fr'],
  424. [false, ['de', 'fr'], 'de'],
  425. [false, ['nl', 'de', 'fr'], 'de'],
  426. [true, [], 'en'],
  427. [true, ['fr'], 'fr'],
  428. [true, ['de', 'fr'], 'de'],
  429. [true, ['nl', 'de', 'fr'], 'nl'],
  430. ];
  431. }
  432. /**
  433. * @dataProvider dataFindLanguage
  434. *
  435. * @param bool $loggedIn
  436. * @param array $availableLang
  437. * @param string $expected
  438. */
  439. public function testFindLanguage($loggedIn, $availableLang, $expected) {
  440. $userLang = 'nl';
  441. $browserLang = 'de';
  442. $defaultLang = 'fr';
  443. $this->config->expects($this->any())
  444. ->method('getSystemValue')
  445. ->will($this->returnCallback(function($var, $default) use ($defaultLang) {
  446. if ($var === 'installed') {
  447. return true;
  448. } else if ($var === 'default_language') {
  449. return $defaultLang;
  450. } else {
  451. return $default;
  452. }
  453. }));
  454. if ($loggedIn) {
  455. $user = $this->getMockBuilder(IUser::class)
  456. ->getMock();
  457. $user->expects($this->any())
  458. ->method('getUID')
  459. ->willReturn('MyUserUid');
  460. $this->userSession
  461. ->expects($this->any())
  462. ->method('getUser')
  463. ->willReturn($user);
  464. $this->config->expects($this->any())
  465. ->method('getUserValue')
  466. ->with('MyUserUid', 'core', 'lang', null)
  467. ->willReturn($userLang);
  468. } else {
  469. $this->userSession
  470. ->expects($this->any())
  471. ->method('getUser')
  472. ->willReturn(null);
  473. }
  474. $this->request->expects($this->any())
  475. ->method('getHeader')
  476. ->with($this->equalTo('ACCEPT_LANGUAGE'))
  477. ->willReturn($browserLang);
  478. $factory = $this->getFactory(['languageExists', 'findAvailableLanguages']);
  479. $factory->expects($this->any())
  480. ->method('languageExists')
  481. ->will($this->returnCallback(function ($app, $lang) use ($availableLang) {
  482. return in_array($lang, $availableLang);
  483. }));
  484. $factory->expects($this->any())
  485. ->method('findAvailableLanguages')
  486. ->will($this->returnCallback(function ($app) use ($availableLang) {
  487. return $availableLang;
  488. }));
  489. $lang = $factory->findLanguage(null);
  490. $this->assertSame($expected, $lang);
  491. }
  492. }