I18nDataTest.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. <?php
  2. declare(strict_types=1);
  3. require_once dirname(__DIR__, 3) . '/cli/i18n/I18nData.php';
  4. require_once dirname(__DIR__, 3) . '/cli/i18n/I18nValue.php';
  5. final class I18nDataTest extends \PHPUnit\Framework\TestCase {
  6. /** @var array<string,array<string,array<string,I18nValue>>> */
  7. private array $referenceData;
  8. /** @var I18nValue&PHPUnit\Framework\MockObject\MockObject */
  9. private $value;
  10. #[\Override]
  11. public function setUp(): void {
  12. $this->value = $this->getMockBuilder(I18nValue::class)
  13. ->disableOriginalConstructor()
  14. ->getMock();
  15. $this->referenceData = [
  16. 'en' => [
  17. 'file1.php' => [
  18. 'file1.l1.l2.k1' => $this->value,
  19. 'file1.l1.l2.k2' => $this->value,
  20. ],
  21. 'file2.php' => [
  22. 'file2.l1.l2._' => $this->value,
  23. 'file2.l1.l2.k1' => $this->value,
  24. 'file2.l1.l2.k2' => $this->value,
  25. ],
  26. 'file3.php' => [
  27. 'file3.l1.l2._' => $this->value,
  28. 'file3.l1.l2.k1' => $this->value,
  29. ],
  30. ],
  31. ];
  32. }
  33. public function testMoveKey(): void {
  34. $data = new I18nData($this->referenceData);
  35. $value = $data->getData()['en']['file2.php']['file2.l1.l2.k2'];
  36. self::assertTrue($data->isKnown('file2.l1.l2.k2'));
  37. self::assertFalse($data->isKnown('file2.l1.nkl2'));
  38. $data->moveKey('file2.l1.l2.k2', 'file2.l1.nkl2');
  39. self::assertFalse($data->isKnown('file2.l1.l2.k2'));
  40. self::assertTrue($data->isKnown('file2.l1.nkl2'));
  41. }
  42. public function testConstructWhenReferenceOnly(): void {
  43. $data = new I18nData($this->referenceData);
  44. self::assertSame($this->referenceData, $data->getData());
  45. }
  46. public function testConstructorWhenLanguageIsMissingFile(): void {
  47. $rawData = array_merge($this->referenceData, [
  48. 'fr' => [
  49. 'file1.php' => [
  50. 'file1.l1.l2.k1' => $this->value,
  51. ],
  52. ],
  53. ]);
  54. $data = new I18nData($rawData);
  55. self::assertEquals([
  56. 'en' => [
  57. 'file1.php' => [
  58. 'file1.l1.l2.k1' => $this->value,
  59. 'file1.l1.l2.k2' => $this->value,
  60. ],
  61. 'file2.php' => [
  62. 'file2.l1.l2._' => $this->value,
  63. 'file2.l1.l2.k1' => $this->value,
  64. 'file2.l1.l2.k2' => $this->value,
  65. ],
  66. 'file3.php' => [
  67. 'file3.l1.l2._' => $this->value,
  68. 'file3.l1.l2.k1' => $this->value,
  69. ],
  70. ],
  71. 'fr' => [
  72. 'file1.php' => [
  73. 'file1.l1.l2.k1' => $this->value,
  74. 'file1.l1.l2.k2' => $this->value,
  75. ],
  76. 'file2.php' => [
  77. 'file2.l1.l2._' => $this->value,
  78. 'file2.l1.l2.k1' => $this->value,
  79. 'file2.l1.l2.k2' => $this->value,
  80. ],
  81. 'file3.php' => [
  82. 'file3.l1.l2._' => $this->value,
  83. 'file3.l1.l2.k1' => $this->value,
  84. ],
  85. ],
  86. ], $data->getData());
  87. }
  88. public function testConstructorWhenLanguageIsMissingKeys(): void {
  89. $rawData = array_merge($this->referenceData, [
  90. 'fr' => [
  91. 'file1.php' => [
  92. 'file1.l1.l2.k1' => $this->value,
  93. ],
  94. 'file2.php' => [
  95. 'file2.l1.l2.k1' => $this->value,
  96. ],
  97. ],
  98. ]);
  99. $data = new I18nData($rawData);
  100. self::assertEquals([
  101. 'en' => [
  102. 'file1.php' => [
  103. 'file1.l1.l2.k1' => $this->value,
  104. 'file1.l1.l2.k2' => $this->value,
  105. ],
  106. 'file2.php' => [
  107. 'file2.l1.l2._' => $this->value,
  108. 'file2.l1.l2.k1' => $this->value,
  109. 'file2.l1.l2.k2' => $this->value,
  110. ],
  111. 'file3.php' => [
  112. 'file3.l1.l2._' => $this->value,
  113. 'file3.l1.l2.k1' => $this->value,
  114. ],
  115. ],
  116. 'fr' => [
  117. 'file1.php' => [
  118. 'file1.l1.l2.k1' => $this->value,
  119. 'file1.l1.l2.k2' => $this->value,
  120. ],
  121. 'file2.php' => [
  122. 'file2.l1.l2._' => $this->value,
  123. 'file2.l1.l2.k1' => $this->value,
  124. 'file2.l1.l2.k2' => $this->value,
  125. ],
  126. 'file3.php' => [
  127. 'file3.l1.l2._' => $this->value,
  128. 'file3.l1.l2.k1' => $this->value,
  129. ],
  130. ],
  131. ], $data->getData());
  132. }
  133. public function testConstructorWhenLanguageHasExtraKeys(): void {
  134. $rawData = array_merge($this->referenceData, [
  135. 'fr' => [
  136. 'file1.php' => [
  137. 'file1.l1.l2.k1' => $this->value,
  138. 'file1.l1.l2.k2' => $this->value,
  139. 'file1.l1.l2.k3' => $this->value,
  140. ],
  141. 'file2.php' => [
  142. 'file2.l1.l2.k1' => $this->value,
  143. 'file2.l1.l2.k2' => $this->value,
  144. 'file2.l1.l2.k3' => $this->value,
  145. ],
  146. 'file3.php' => [
  147. 'file3.l1.l2._' => $this->value,
  148. 'file3.l1.l2.k1' => $this->value,
  149. ],
  150. ],
  151. ]);
  152. $data = new I18nData($rawData);
  153. self::assertEquals([
  154. 'en' => [
  155. 'file1.php' => [
  156. 'file1.l1.l2.k1' => $this->value,
  157. 'file1.l1.l2.k2' => $this->value,
  158. ],
  159. 'file2.php' => [
  160. 'file2.l1.l2._' => $this->value,
  161. 'file2.l1.l2.k1' => $this->value,
  162. 'file2.l1.l2.k2' => $this->value,
  163. ],
  164. 'file3.php' => [
  165. 'file3.l1.l2._' => $this->value,
  166. 'file3.l1.l2.k1' => $this->value,
  167. ],
  168. ],
  169. 'fr' => [
  170. 'file1.php' => [
  171. 'file1.l1.l2.k1' => $this->value,
  172. 'file1.l1.l2.k2' => $this->value,
  173. ],
  174. 'file2.php' => [
  175. 'file2.l1.l2._' => $this->value,
  176. 'file2.l1.l2.k1' => $this->value,
  177. 'file2.l1.l2.k2' => $this->value,
  178. ],
  179. 'file3.php' => [
  180. 'file3.l1.l2._' => $this->value,
  181. 'file3.l1.l2.k1' => $this->value,
  182. ],
  183. ],
  184. ], $data->getData());
  185. }
  186. public function testConstructorWhenValueIsIdenticalAndIsMarkedAsIgnore(): void {
  187. $value = $this->getMockBuilder(I18nValue::class)
  188. ->disableOriginalConstructor()
  189. ->getMock();
  190. $value->expects(self::exactly(2))
  191. ->method('isIgnore')
  192. ->willReturn(true);
  193. $value->expects(self::never())
  194. ->method('markAsTodo');
  195. $value->expects(self::exactly(3))
  196. ->method('equal')
  197. ->with($value)
  198. ->willReturn(true);
  199. $rawData = array_merge($this->referenceData, [
  200. 'fr' => [
  201. 'file2.php' => [
  202. 'file2.l1.l2.k1' => $value,
  203. ],
  204. ],
  205. ]);
  206. $rawData['en']['file2.php']['file2.l1.l2.k1'] = $value;
  207. new I18nData($rawData);
  208. }
  209. public function testConstructorWhenValueIsIdenticalAndIsNotMarkedAsIgnore(): void {
  210. $value = $this->getMockBuilder(I18nValue::class)
  211. ->disableOriginalConstructor()
  212. ->getMock();
  213. $value->expects(self::exactly(2))
  214. ->method('isIgnore')
  215. ->willReturn(false);
  216. $value->expects(self::exactly(2))
  217. ->method('markAsTodo');
  218. $value->expects(self::exactly(2))
  219. ->method('equal')
  220. ->with($value)
  221. ->willReturn(true);
  222. $rawData = array_merge($this->referenceData, [
  223. 'fr' => [
  224. 'file2.php' => [
  225. 'file2.l1.l2.k1' => $value,
  226. ],
  227. ],
  228. ]);
  229. $rawData['en']['file2.php']['file2.l1.l2.k1'] = $value;
  230. new I18nData($rawData);
  231. }
  232. public function testConstructorWhenValueIsDifferentAndIsMarkedAsToDo(): void {
  233. $value = $this->getMockBuilder(I18nValue::class)
  234. ->disableOriginalConstructor()
  235. ->getMock();
  236. $value->expects(self::once())
  237. ->method('isTodo')
  238. ->willReturn(true);
  239. $value->expects(self::once())
  240. ->method('markAsDirty');
  241. $rawData = array_merge($this->referenceData, [
  242. 'fr' => [
  243. 'file2.php' => [
  244. 'file2.l1.l2.k1' => $value,
  245. ],
  246. ],
  247. ]);
  248. new I18nData($rawData);
  249. }
  250. public function testConstructorWhenValueIsDifferentAndIsNotMarkedAsTodo(): void {
  251. $value = $this->getMockBuilder(I18nValue::class)
  252. ->disableOriginalConstructor()
  253. ->getMock();
  254. $value->expects(self::once())
  255. ->method('isTodo')
  256. ->willReturn(false);
  257. $value->expects(self::never())
  258. ->method('markAsDirty');
  259. $rawData = array_merge($this->referenceData, [
  260. 'fr' => [
  261. 'file2.php' => [
  262. 'file2.l1.l2.k1' => $value,
  263. ],
  264. ],
  265. ]);
  266. new I18nData($rawData);
  267. }
  268. public function testGetAvailableLanguagesWhenTheyAreSorted(): void {
  269. $rawData = array_merge($this->referenceData, [
  270. 'fr' => [],
  271. 'nl' => [],
  272. ]);
  273. $data = new I18nData($rawData);
  274. self::assertSame([
  275. 'en',
  276. 'fr',
  277. 'nl',
  278. ], $data->getAvailableLanguages());
  279. }
  280. public function testGetAvailableLanguagesWhenTheyAreNotSorted(): void {
  281. $rawData = array_merge($this->referenceData, [
  282. 'nl' => [],
  283. 'fr' => [],
  284. 'de' => [],
  285. ]);
  286. $data = new I18nData($rawData);
  287. self::assertSame([
  288. 'de',
  289. 'en',
  290. 'fr',
  291. 'nl',
  292. ], $data->getAvailableLanguages());
  293. }
  294. public function testAddLanguageWhenLanguageExists(): void {
  295. $this->expectException(\Exception::class);
  296. $this->expectExceptionMessage('The selected language already exists.');
  297. $data = new I18nData($this->referenceData);
  298. $data->addLanguage('en');
  299. }
  300. public function testAddLanguageWhenNoReferenceProvided(): void {
  301. $data = new I18nData($this->referenceData);
  302. $data->addLanguage('fr');
  303. self::assertSame([
  304. 'en' => [
  305. 'file1.php' => [
  306. 'file1.l1.l2.k1' => $this->value,
  307. 'file1.l1.l2.k2' => $this->value,
  308. ],
  309. 'file2.php' => [
  310. 'file2.l1.l2._' => $this->value,
  311. 'file2.l1.l2.k1' => $this->value,
  312. 'file2.l1.l2.k2' => $this->value,
  313. ],
  314. 'file3.php' => [
  315. 'file3.l1.l2._' => $this->value,
  316. 'file3.l1.l2.k1' => $this->value,
  317. ],
  318. ],
  319. 'fr' => [
  320. 'file1.php' => [
  321. 'file1.l1.l2.k1' => $this->value,
  322. 'file1.l1.l2.k2' => $this->value,
  323. ],
  324. 'file2.php' => [
  325. 'file2.l1.l2._' => $this->value,
  326. 'file2.l1.l2.k1' => $this->value,
  327. 'file2.l1.l2.k2' => $this->value,
  328. ],
  329. 'file3.php' => [
  330. 'file3.l1.l2._' => $this->value,
  331. 'file3.l1.l2.k1' => $this->value,
  332. ],
  333. ],
  334. ], $data->getData());
  335. }
  336. public function testAddLanguageWhenUnknownReferenceProvided(): void {
  337. $data = new I18nData($this->referenceData);
  338. $data->addLanguage('fr', 'unknown');
  339. self::assertSame([
  340. 'en' => [
  341. 'file1.php' => [
  342. 'file1.l1.l2.k1' => $this->value,
  343. 'file1.l1.l2.k2' => $this->value,
  344. ],
  345. 'file2.php' => [
  346. 'file2.l1.l2._' => $this->value,
  347. 'file2.l1.l2.k1' => $this->value,
  348. 'file2.l1.l2.k2' => $this->value,
  349. ],
  350. 'file3.php' => [
  351. 'file3.l1.l2._' => $this->value,
  352. 'file3.l1.l2.k1' => $this->value,
  353. ],
  354. ],
  355. 'fr' => [
  356. 'file1.php' => [
  357. 'file1.l1.l2.k1' => $this->value,
  358. 'file1.l1.l2.k2' => $this->value,
  359. ],
  360. 'file2.php' => [
  361. 'file2.l1.l2._' => $this->value,
  362. 'file2.l1.l2.k1' => $this->value,
  363. 'file2.l1.l2.k2' => $this->value,
  364. ],
  365. 'file3.php' => [
  366. 'file3.l1.l2._' => $this->value,
  367. 'file3.l1.l2.k1' => $this->value,
  368. ],
  369. ],
  370. ], $data->getData());
  371. }
  372. public function testAddLanguageWhenKnownReferenceProvided(): void {
  373. $data = new I18nData($this->referenceData);
  374. $data->addLanguage('fr', 'en');
  375. self::assertSame([
  376. 'en' => [
  377. 'file1.php' => [
  378. 'file1.l1.l2.k1' => $this->value,
  379. 'file1.l1.l2.k2' => $this->value,
  380. ],
  381. 'file2.php' => [
  382. 'file2.l1.l2._' => $this->value,
  383. 'file2.l1.l2.k1' => $this->value,
  384. 'file2.l1.l2.k2' => $this->value,
  385. ],
  386. 'file3.php' => [
  387. 'file3.l1.l2._' => $this->value,
  388. 'file3.l1.l2.k1' => $this->value,
  389. ],
  390. ],
  391. 'fr' => [
  392. 'file1.php' => [
  393. 'file1.l1.l2.k1' => $this->value,
  394. 'file1.l1.l2.k2' => $this->value,
  395. ],
  396. 'file2.php' => [
  397. 'file2.l1.l2._' => $this->value,
  398. 'file2.l1.l2.k1' => $this->value,
  399. 'file2.l1.l2.k2' => $this->value,
  400. ],
  401. 'file3.php' => [
  402. 'file3.l1.l2._' => $this->value,
  403. 'file3.l1.l2.k1' => $this->value,
  404. ],
  405. ],
  406. ], $data->getData());
  407. }
  408. public function testIsKnownWhenKeyExists(): void {
  409. $data = new I18nData($this->referenceData);
  410. self::assertTrue($data->isKnown('file2.l1.l2.k2'));
  411. }
  412. public function testIsKnownWhenKeyDoesNotExist(): void {
  413. $data = new I18nData($this->referenceData);
  414. self::assertFalse($data->isKnown('file2.l1.l2.k3'));
  415. }
  416. public function testAddKeyWhenKeyExists(): void {
  417. $this->expectException(\Exception::class);
  418. $this->expectExceptionMessage('The selected key already exists.');
  419. $data = new I18nData($this->referenceData);
  420. $data->addKey('file2.l1.l2.k1', 'value');
  421. }
  422. public function testAddKeyWhenParentKeyExists(): void {
  423. $rawData = array_merge($this->referenceData, [
  424. 'fr' => [],
  425. ]);
  426. $data = new I18nData($rawData);
  427. self::assertTrue($data->isKnown('file2.l1.l2.k1'));
  428. self::assertFalse($data->isKnown('file2.l1.l2.k1._'));
  429. self::assertFalse($data->isKnown('file2.l1.l2.k1.sk1'));
  430. $data->addKey('file2.l1.l2.k1.sk1', 'value');
  431. self::assertFalse($data->isKnown('file2.l1.l2.k1'));
  432. self::assertTrue($data->isKnown('file2.l1.l2.k1._'));
  433. self::assertTrue($data->isKnown('file2.l1.l2.k1.sk1'));
  434. }
  435. public function testAddKeyWhenKeyIsParent(): void {
  436. $rawData = array_merge($this->referenceData, [
  437. 'fr' => [],
  438. ]);
  439. $data = new I18nData($rawData);
  440. self::assertFalse($data->isKnown('file1.l1.l2._'));
  441. self::assertTrue($data->isKnown('file1.l1.l2.k1'));
  442. self::assertTrue($data->isKnown('file1.l1.l2.k2'));
  443. $data->addKey('file1.l1.l2', 'value');
  444. self::assertTrue($data->isKnown('file1.l1.l2._'));
  445. self::assertTrue($data->isKnown('file1.l1.l2.k1'));
  446. self::assertTrue($data->isKnown('file1.l1.l2.k2'));
  447. }
  448. public function testAddKey(): void {
  449. $getTargetedValue = static fn(I18nData $data, string $language) => $data->getData()[$language]['file2.php']['file2.l1.l2.k3'];
  450. $rawData = array_merge($this->referenceData, [
  451. 'fr' => [],
  452. ]);
  453. $data = new I18nData($rawData);
  454. self::assertFalse($data->isKnown('file2.l1.l2.k3'));
  455. $data->addKey('file2.l1.l2.k3', 'value');
  456. self::assertTrue($data->isKnown('file2.l1.l2.k3'));
  457. $enValue = $getTargetedValue($data, 'en');
  458. $frValue = $getTargetedValue($data, 'fr');
  459. self::assertInstanceOf(I18nValue::class, $enValue);
  460. self::assertSame('value', $enValue->getValue());
  461. self::assertTrue($enValue->isTodo());
  462. self::assertSame($frValue, $enValue);
  463. }
  464. public function testAddFileWhenNotPhpFile(): void {
  465. $this->expectException(\Exception::class);
  466. $this->expectExceptionMessage('The selected file name is not supported.');
  467. $data = new I18nData($this->referenceData);
  468. $data->addFile('file2');
  469. }
  470. public function testAddFileWhenAlreadyExists(): void {
  471. $this->expectException(\Exception::class);
  472. $this->expectExceptionMessage('The selected file exists already.');
  473. $data = new I18nData($this->referenceData);
  474. self::assertTrue($data->exists('file2.php'));
  475. $data->addFile('file2.php');
  476. }
  477. public function testAddFileWhenNotExists(): void {
  478. $data = new I18nData($this->referenceData);
  479. self::assertFalse($data->exists('newfile.php'));
  480. $data->addFile('newfile.php');
  481. self::assertTrue($data->exists('newfile.php'));
  482. }
  483. public function testAddValueWhenLanguageDoesNotExist(): void {
  484. $this->expectException(\Exception::class);
  485. $this->expectExceptionMessage('The selected language does not exist.');
  486. $data = new I18nData($this->referenceData);
  487. $data->addValue('file2.l1.l2.k2', 'new value', 'fr');
  488. }
  489. public function testAddValueWhenKeyDoesNotExist(): void {
  490. $this->expectException(\Exception::class);
  491. $this->expectExceptionMessage('The selected key does not exist for the selected language.');
  492. $data = new I18nData($this->referenceData);
  493. $data->addValue('unknown key', 'new value', 'en');
  494. }
  495. public function testAddValueWhenLanguageIsReferenceAndValueInOtherLanguageHasNotChange(): void {
  496. $getTargetedValue = static fn(I18nData $data, string $language) => $data->getData()[$language]['file2.php']['file2.l1.l2.k2'];
  497. $this->value->expects(self::atLeast(2))
  498. ->method('equal')
  499. ->with($this->value)
  500. ->willReturn(true);
  501. $rawData = array_merge($this->referenceData, [
  502. 'fr' => [],
  503. ]);
  504. $data = new I18nData($rawData);
  505. $beforeEnValue = $getTargetedValue($data, 'en');
  506. $beforeFrValue = $getTargetedValue($data, 'fr');
  507. $data->addValue('file2.l1.l2.k2', 'new value', 'en');
  508. $afterEnValue = $getTargetedValue($data, 'en');
  509. $afterFrValue = $getTargetedValue($data, 'fr');
  510. self::assertEquals($this->value, $beforeEnValue);
  511. self::assertEquals($this->value, $beforeFrValue);
  512. self::assertInstanceOf(I18nValue::class, $afterEnValue);
  513. self::assertSame('new value', $afterEnValue->getValue());
  514. self::assertInstanceOf(I18nValue::class, $afterFrValue);
  515. self::assertSame('new value', $afterFrValue->getValue());
  516. }
  517. public function testAddValueWhenLanguageIsReferenceAndValueInOtherLanguageHasChange(): void {
  518. $getTargetedValue = static fn(I18nData $data, string $language) => $data->getData()[$language]['file2.php']['file2.l1.l2.k2'];
  519. $this->value->expects(self::any())
  520. ->method('equal')
  521. ->with($this->value)
  522. ->willReturn(true);
  523. $value = $this->getMockBuilder(I18nValue::class)
  524. ->disableOriginalConstructor()
  525. ->getMock();
  526. $rawData = array_merge($this->referenceData, [
  527. 'fr' => [
  528. 'file2.php' => [
  529. 'file2.l1.l2.k2' => $value,
  530. ]
  531. ],
  532. ]);
  533. $data = new I18nData($rawData);
  534. $beforeEnValue = $getTargetedValue($data, 'en');
  535. $beforeFrValue = $getTargetedValue($data, 'fr');
  536. $data->addValue('file2.l1.l2.k2', 'new value', 'en');
  537. $afterEnValue = $getTargetedValue($data, 'en');
  538. $afterFrValue = $getTargetedValue($data, 'fr');
  539. self::assertEquals($this->value, $beforeEnValue);
  540. self::assertEquals($value, $beforeFrValue);
  541. self::assertInstanceOf(I18nValue::class, $afterEnValue);
  542. self::assertSame('new value', $afterEnValue->getValue());
  543. self::assertEquals($value, $afterFrValue);
  544. }
  545. public function testAddValueWhenLanguageIsNotReference(): void {
  546. $getTargetedValue = static fn(I18nData $data, string $language) => $data->getData()[$language]['file2.php']['file2.l1.l2.k2'];
  547. $rawData = array_merge($this->referenceData, [
  548. 'fr' => [],
  549. ]);
  550. $data = new I18nData($rawData);
  551. $beforeEnValue = $getTargetedValue($data, 'en');
  552. $beforeFrValue = $getTargetedValue($data, 'fr');
  553. $data->addValue('file2.l1.l2.k2', 'new value', 'fr');
  554. $afterEnValue = $getTargetedValue($data, 'en');
  555. $afterFrValue = $getTargetedValue($data, 'fr');
  556. self::assertEquals($this->value, $beforeEnValue);
  557. self::assertEquals($this->value, $beforeFrValue);
  558. self::assertEquals($this->value, $afterEnValue);
  559. self::assertInstanceOf(I18nValue::class, $afterFrValue);
  560. self::assertSame('new value', $afterFrValue->getValue());
  561. }
  562. public function testRemoveKeyWhenKeyDoesNotExist(): void {
  563. $this->expectException(\Exception::class);
  564. $this->expectExceptionMessage('The selected key does not exist.');
  565. $data = new I18nData($this->referenceData);
  566. $data->removeKey('Unknown key');
  567. }
  568. public function testRemoveKeyWhenKeyHasNoEmptySibling(): void {
  569. $this->expectException(\Exception::class);
  570. $this->expectExceptionMessage('The selected key does not exist.');
  571. $data = new I18nData($this->referenceData);
  572. $data->removeKey('file1.l1.l2');
  573. }
  574. public function testRemoveKeyWhenKeyIsEmptySibling(): void {
  575. $rawData = array_merge($this->referenceData, [
  576. 'fr' => [],
  577. ]);
  578. $data = new I18nData($rawData);
  579. $data->removeKey('file2.l1.l2');
  580. self::assertEquals([
  581. 'en' => [
  582. 'file1.php' => [
  583. 'file1.l1.l2.k1' => $this->value,
  584. 'file1.l1.l2.k2' => $this->value,
  585. ],
  586. 'file2.php' => [
  587. 'file2.l1.l2.k1' => $this->value,
  588. 'file2.l1.l2.k2' => $this->value,
  589. ],
  590. 'file3.php' => [
  591. 'file3.l1.l2._' => $this->value,
  592. 'file3.l1.l2.k1' => $this->value,
  593. ],
  594. ],
  595. 'fr' => [
  596. 'file1.php' => [
  597. 'file1.l1.l2.k1' => $this->value,
  598. 'file1.l1.l2.k2' => $this->value,
  599. ],
  600. 'file2.php' => [
  601. 'file2.l1.l2.k1' => $this->value,
  602. 'file2.l1.l2.k2' => $this->value,
  603. ],
  604. 'file3.php' => [
  605. 'file3.l1.l2._' => $this->value,
  606. 'file3.l1.l2.k1' => $this->value,
  607. ],
  608. ],
  609. ], $data->getData());
  610. }
  611. public function testRemoveKeyWhenKeyIsTheOnlyChild(): void {
  612. $rawData = array_merge($this->referenceData, [
  613. 'fr' => [],
  614. ]);
  615. $data = new I18nData($rawData);
  616. $data->removeKey('file3.l1.l2.k1');
  617. self::assertEquals([
  618. 'en' => [
  619. 'file1.php' => [
  620. 'file1.l1.l2.k1' => $this->value,
  621. 'file1.l1.l2.k2' => $this->value,
  622. ],
  623. 'file2.php' => [
  624. 'file2.l1.l2._' => $this->value,
  625. 'file2.l1.l2.k1' => $this->value,
  626. 'file2.l1.l2.k2' => $this->value,
  627. ],
  628. 'file3.php' => [
  629. 'file3.l1.l2' => $this->value,
  630. ],
  631. ],
  632. 'fr' => [
  633. 'file1.php' => [
  634. 'file1.l1.l2.k1' => $this->value,
  635. 'file1.l1.l2.k2' => $this->value,
  636. ],
  637. 'file2.php' => [
  638. 'file2.l1.l2._' => $this->value,
  639. 'file2.l1.l2.k1' => $this->value,
  640. 'file2.l1.l2.k2' => $this->value,
  641. ],
  642. 'file3.php' => [
  643. 'file3.l1.l2' => $this->value,
  644. ],
  645. ],
  646. ], $data->getData());
  647. }
  648. public function testIgnore(): void {
  649. $value = $this->getMockBuilder(I18nValue::class)
  650. ->disableOriginalConstructor()
  651. ->getMock();
  652. $value->expects(self::once())
  653. ->method('unmarkAsIgnore');
  654. $value->expects(self::exactly(2))
  655. ->method('markAsIgnore');
  656. $rawData = array_merge($this->referenceData, [
  657. 'fr' => [
  658. 'file1.php' => [
  659. 'file1.l1.l2.k1' => $value,
  660. ],
  661. ],
  662. ]);
  663. $data = new I18nData($rawData);
  664. $data->ignore('file1.l1.l2.k1', 'fr');
  665. $data->ignore('file1.l1.l2.k1', 'fr', true);
  666. $data->ignore('file1.l1.l2.k1', 'fr', false);
  667. }
  668. public function testIgnoreUnmodified(): void {
  669. $value = $this->getMockBuilder(I18nValue::class)
  670. ->disableOriginalConstructor()
  671. ->getMock();
  672. $value->expects(self::once())
  673. ->method('unmarkAsIgnore');
  674. $value->expects(self::exactly(2))
  675. ->method('markAsIgnore');
  676. $this->value->expects(self::atLeast(2))
  677. ->method('equal')
  678. ->with($value)
  679. ->willReturn(true);
  680. $rawData = array_merge($this->referenceData, [
  681. 'fr' => [
  682. 'file1.php' => [
  683. 'file1.l1.l2.k1' => $value,
  684. ],
  685. ],
  686. ]);
  687. $data = new I18nData($rawData);
  688. $data->ignore_unmodified('fr');
  689. $data->ignore_unmodified('fr', true);
  690. $data->ignore_unmodified('fr', false);
  691. }
  692. public function testGetLanguage(): void {
  693. $rawData = array_merge($this->referenceData, [
  694. 'fr' => [],
  695. 'nl' => [],
  696. ]);
  697. $data = new I18nData($rawData);
  698. self::assertSame($this->referenceData['en'], $data->getLanguage('en'));
  699. }
  700. public function testGetReferenceLanguage(): void {
  701. $rawData = array_merge($this->referenceData, [
  702. 'fr' => [],
  703. 'nl' => [],
  704. ]);
  705. $data = new I18nData($rawData);
  706. self::assertSame($this->referenceData['en'], $data->getReferenceLanguage());
  707. }
  708. }