AddressBookImplTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Björn Schießle <bjoern@schiessle.org>
  6. * @author Georg Ehrke <oc.list@georgehrke.com>
  7. * @author Joas Schilling <coding@schilljs.com>
  8. * @author Roeland Jago Douma <roeland@famdouma.nl>
  9. * @author Thomas Müller <thomas.mueller@tmit.eu>
  10. *
  11. * @license AGPL-3.0
  12. *
  13. * This code is free software: you can redistribute it and/or modify
  14. * it under the terms of the GNU Affero General Public License, version 3,
  15. * as published by the Free Software Foundation.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU Affero General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Affero General Public License, version 3,
  23. * along with this program. If not, see <http://www.gnu.org/licenses/>
  24. *
  25. */
  26. namespace OCA\DAV\Tests\unit\CardDAV;
  27. use OCA\DAV\CardDAV\AddressBook;
  28. use OCA\DAV\CardDAV\AddressBookImpl;
  29. use OCA\DAV\CardDAV\CardDavBackend;
  30. use OCP\IURLGenerator;
  31. use Sabre\VObject\Component\VCard;
  32. use Sabre\VObject\Property\Text;
  33. use Test\TestCase;
  34. class AddressBookImplTest extends TestCase {
  35. /** @var AddressBookImpl */
  36. private $addressBookImpl;
  37. /** @var array */
  38. private $addressBookInfo;
  39. /** @var AddressBook | \PHPUnit_Framework_MockObject_MockObject */
  40. private $addressBook;
  41. /** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject */
  42. private $urlGenerator;
  43. /** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject */
  44. private $backend;
  45. /** @var VCard | \PHPUnit_Framework_MockObject_MockObject */
  46. private $vCard;
  47. public function setUp() {
  48. parent::setUp();
  49. $this->addressBookInfo = [
  50. 'id' => 42,
  51. 'uri' => 'system',
  52. 'principaluri' => 'principals/system/system',
  53. '{DAV:}displayname' => 'display name',
  54. ];
  55. $this->addressBook = $this->getMockBuilder(AddressBook::class)
  56. ->disableOriginalConstructor()->getMock();
  57. $this->backend = $this->getMockBuilder(CardDavBackend::class)
  58. ->disableOriginalConstructor()->getMock();
  59. $this->vCard = $this->createMock(VCard::class);
  60. $this->urlGenerator = $this->createMock(IURLGenerator::class);
  61. $this->addressBookImpl = new AddressBookImpl(
  62. $this->addressBook,
  63. $this->addressBookInfo,
  64. $this->backend,
  65. $this->urlGenerator
  66. );
  67. }
  68. public function testGetKey() {
  69. $this->assertSame($this->addressBookInfo['id'],
  70. $this->addressBookImpl->getKey());
  71. }
  72. public function testGetDisplayName() {
  73. $this->assertSame($this->addressBookInfo['{DAV:}displayname'],
  74. $this->addressBookImpl->getDisplayName());
  75. }
  76. public function testSearch() {
  77. /** @var \PHPUnit_Framework_MockObject_MockObject | AddressBookImpl $addressBookImpl */
  78. $addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
  79. ->setConstructorArgs(
  80. [
  81. $this->addressBook,
  82. $this->addressBookInfo,
  83. $this->backend,
  84. $this->urlGenerator,
  85. ]
  86. )
  87. ->setMethods(['vCard2Array', 'readCard'])
  88. ->getMock();
  89. $pattern = 'pattern';
  90. $searchProperties = 'properties';
  91. $this->backend->expects($this->once())->method('search')
  92. ->with($this->addressBookInfo['id'], $pattern, $searchProperties)
  93. ->willReturn(
  94. [
  95. ['uri' => 'foo.vcf', 'carddata' => 'cardData1'],
  96. ['uri' => 'bar.vcf', 'carddata' => 'cardData2']
  97. ]
  98. );
  99. $addressBookImpl->expects($this->exactly(2))->method('readCard')
  100. ->willReturn($this->vCard);
  101. $addressBookImpl->expects($this->exactly(2))->method('vCard2Array')
  102. ->withConsecutive(
  103. ['foo.vcf', $this->vCard],
  104. ['bar.vcf', $this->vCard]
  105. )->willReturn('vCard');
  106. $result = $addressBookImpl->search($pattern, $searchProperties, []);
  107. $this->assertTrue((is_array($result)));
  108. $this->assertSame(2, count($result));
  109. }
  110. /**
  111. * @dataProvider dataTestCreate
  112. *
  113. * @param array $properties
  114. */
  115. public function testCreate($properties) {
  116. $uid = 'uid';
  117. /** @var \PHPUnit_Framework_MockObject_MockObject | AddressBookImpl $addressBookImpl */
  118. $addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
  119. ->setConstructorArgs(
  120. [
  121. $this->addressBook,
  122. $this->addressBookInfo,
  123. $this->backend,
  124. $this->urlGenerator,
  125. ]
  126. )
  127. ->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard'])
  128. ->getMock();
  129. $addressBookImpl->expects($this->once())->method('createUid')
  130. ->willReturn($uid);
  131. $addressBookImpl->expects($this->once())->method('createEmptyVCard')
  132. ->with($uid)->willReturn($this->vCard);
  133. $this->vCard->expects($this->exactly(count($properties)))
  134. ->method('createProperty');
  135. $this->backend->expects($this->once())->method('createCard');
  136. $this->backend->expects($this->never())->method('updateCard');
  137. $this->backend->expects($this->never())->method('getCard');
  138. $addressBookImpl->expects($this->once())->method('vCard2Array')
  139. ->with('uid.vcf', $this->vCard)->willReturn(true);
  140. $this->assertTrue($addressBookImpl->createOrUpdate($properties));
  141. }
  142. public function dataTestCreate() {
  143. return [
  144. [[]],
  145. [['FN' => 'John Doe']]
  146. ];
  147. }
  148. public function testUpdate() {
  149. $uid = 'uid';
  150. $uri = 'bla.vcf';
  151. $properties = ['URI' => $uri, 'UID' => $uid, 'FN' => 'John Doe'];
  152. /** @var \PHPUnit_Framework_MockObject_MockObject | AddressBookImpl $addressBookImpl */
  153. $addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
  154. ->setConstructorArgs(
  155. [
  156. $this->addressBook,
  157. $this->addressBookInfo,
  158. $this->backend,
  159. $this->urlGenerator,
  160. ]
  161. )
  162. ->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard'])
  163. ->getMock();
  164. $addressBookImpl->expects($this->never())->method('createUid');
  165. $addressBookImpl->expects($this->never())->method('createEmptyVCard');
  166. $this->backend->expects($this->once())->method('getCard')
  167. ->with($this->addressBookInfo['id'], $uri)
  168. ->willReturn(['carddata' => 'data']);
  169. $addressBookImpl->expects($this->once())->method('readCard')
  170. ->with('data')->willReturn($this->vCard);
  171. $this->vCard->expects($this->exactly(count($properties)))
  172. ->method('createProperty');
  173. $this->backend->expects($this->never())->method('createCard');
  174. $this->backend->expects($this->once())->method('updateCard');
  175. $addressBookImpl->expects($this->once())->method('vCard2Array')
  176. ->with($uri, $this->vCard)->willReturn(true);
  177. $this->assertTrue($addressBookImpl->createOrUpdate($properties));
  178. }
  179. /**
  180. * @dataProvider dataTestGetPermissions
  181. *
  182. * @param array $permissions
  183. * @param int $expected
  184. */
  185. public function testGetPermissions($permissions, $expected) {
  186. $this->addressBook->expects($this->once())->method('getACL')
  187. ->willReturn($permissions);
  188. $this->assertSame($expected,
  189. $this->addressBookImpl->getPermissions()
  190. );
  191. }
  192. public function dataTestGetPermissions() {
  193. return [
  194. [[], 0],
  195. [[['privilege' => '{DAV:}read']], 1],
  196. [[['privilege' => '{DAV:}write']], 6],
  197. [[['privilege' => '{DAV:}all']], 31],
  198. [[['privilege' => '{DAV:}read'],['privilege' => '{DAV:}write']], 7],
  199. [[['privilege' => '{DAV:}read'],['privilege' => '{DAV:}all']], 31],
  200. [[['privilege' => '{DAV:}all'],['privilege' => '{DAV:}write']], 31],
  201. [[['privilege' => '{DAV:}read'],['privilege' => '{DAV:}write'],['privilege' => '{DAV:}all']], 31],
  202. [[['privilege' => '{DAV:}all'],['privilege' => '{DAV:}read'],['privilege' => '{DAV:}write']], 31],
  203. ];
  204. }
  205. public function testDelete() {
  206. $cardId = 1;
  207. $cardUri = 'cardUri';
  208. $this->backend->expects($this->once())->method('getCardUri')
  209. ->with($cardId)->willReturn($cardUri);
  210. $this->backend->expects($this->once())->method('deleteCard')
  211. ->with($this->addressBookInfo['id'], $cardUri)
  212. ->willReturn(true);
  213. $this->assertTrue($this->addressBookImpl->delete($cardId));
  214. }
  215. public function testReadCard() {
  216. $vCard = new VCard();
  217. $vCard->add(new Text($vCard, 'UID', 'uid'));
  218. $vCardSerialized = $vCard->serialize();
  219. $result = $this->invokePrivate($this->addressBookImpl, 'readCard', [$vCardSerialized]);
  220. $resultSerialized = $result->serialize();
  221. $this->assertSame($vCardSerialized, $resultSerialized);
  222. }
  223. public function testCreateUid() {
  224. /** @var \PHPUnit_Framework_MockObject_MockObject | AddressBookImpl $addressBookImpl */
  225. $addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
  226. ->setConstructorArgs(
  227. [
  228. $this->addressBook,
  229. $this->addressBookInfo,
  230. $this->backend,
  231. $this->urlGenerator,
  232. ]
  233. )
  234. ->setMethods(['getUid'])
  235. ->getMock();
  236. $addressBookImpl->expects($this->at(0))->method('getUid')->willReturn('uid0');
  237. $addressBookImpl->expects($this->at(1))->method('getUid')->willReturn('uid1');
  238. // simulate that 'uid0' already exists, so the second uid will be returned
  239. $this->backend->expects($this->exactly(2))->method('getContact')
  240. ->willReturnCallback(
  241. function($id, $uid) {
  242. return ($uid === 'uid0.vcf');
  243. }
  244. );
  245. $this->assertSame('uid1',
  246. $this->invokePrivate($addressBookImpl, 'createUid', [])
  247. );
  248. }
  249. public function testCreateEmptyVCard() {
  250. $uid = 'uid';
  251. $expectedVCard = new VCard();
  252. $expectedVCard->UID = $uid;
  253. $expectedVCardSerialized = $expectedVCard->serialize();
  254. $result = $this->invokePrivate($this->addressBookImpl, 'createEmptyVCard', [$uid]);
  255. $resultSerialized = $result->serialize();
  256. $this->assertSame($expectedVCardSerialized, $resultSerialized);
  257. }
  258. public function testVCard2Array() {
  259. $vCard = new VCard();
  260. $vCard->add($vCard->createProperty('FN', 'Full Name'));
  261. // Multi-value properties
  262. $vCard->add($vCard->createProperty('CLOUD', 'cloud-user1@localhost'));
  263. $vCard->add($vCard->createProperty('CLOUD', 'cloud-user2@example.tld'));
  264. $vCard->add($vCard->createProperty('EMAIL', 'email-user1@localhost'));
  265. $vCard->add($vCard->createProperty('EMAIL', 'email-user2@example.tld'));
  266. $vCard->add($vCard->createProperty('IMPP', 'impp-user1@localhost'));
  267. $vCard->add($vCard->createProperty('IMPP', 'impp-user2@example.tld'));
  268. $vCard->add($vCard->createProperty('TEL', '+49 123456789'));
  269. $vCard->add($vCard->createProperty('TEL', '+1 555 123456789'));
  270. $vCard->add($vCard->createProperty('URL', 'https://localhost'));
  271. $vCard->add($vCard->createProperty('URL', 'https://example.tld'));
  272. // Type depending properties
  273. $property = $vCard->createProperty('X-SOCIALPROFILE', 'tw-example');
  274. $property->add('TYPE', 'twitter');
  275. $vCard->add($property);
  276. $property = $vCard->createProperty('X-SOCIALPROFILE', 'tw-example-2');
  277. $property->add('TYPE', 'twitter');
  278. $vCard->add($property);
  279. $property = $vCard->createProperty('X-SOCIALPROFILE', 'fb-example');
  280. $property->add('TYPE', 'facebook');
  281. $vCard->add($property);
  282. $array = $this->invokePrivate($this->addressBookImpl, 'vCard2Array', ['uri', $vCard]);
  283. unset($array['PRODID']);
  284. unset($array['UID']);
  285. $this->assertEquals([
  286. 'URI' => 'uri',
  287. 'VERSION' => '4.0',
  288. 'FN' => 'Full Name',
  289. 'CLOUD' => [
  290. 'cloud-user1@localhost',
  291. 'cloud-user2@example.tld',
  292. ],
  293. 'EMAIL' => [
  294. 'email-user1@localhost',
  295. 'email-user2@example.tld',
  296. ],
  297. 'IMPP' => [
  298. 'impp-user1@localhost',
  299. 'impp-user2@example.tld',
  300. ],
  301. 'TEL' => [
  302. '+49 123456789',
  303. '+1 555 123456789',
  304. ],
  305. 'URL' => [
  306. 'https://localhost',
  307. 'https://example.tld',
  308. ],
  309. 'X-SOCIALPROFILE' => [
  310. 'tw-example',
  311. 'tw-example-2',
  312. 'fb-example',
  313. ],
  314. 'isLocalSystemBook' => true,
  315. ], $array);
  316. }
  317. public function testVCard2ArrayWithTypes() {
  318. $vCard = new VCard();
  319. $vCard->add($vCard->createProperty('FN', 'Full Name'));
  320. // Multi-value properties
  321. $vCard->add($vCard->createProperty('CLOUD', 'cloud-user1@localhost'));
  322. $vCard->add($vCard->createProperty('CLOUD', 'cloud-user2@example.tld'));
  323. $property = $vCard->createProperty('EMAIL', 'email-user1@localhost');
  324. $property->add('TYPE', 'HOME');
  325. $vCard->add($property);
  326. $property = $vCard->createProperty('EMAIL', 'email-user2@example.tld');
  327. $property->add('TYPE', 'WORK');
  328. $vCard->add($property);
  329. $vCard->add($vCard->createProperty('IMPP', 'impp-user1@localhost'));
  330. $vCard->add($vCard->createProperty('IMPP', 'impp-user2@example.tld'));
  331. $property = $vCard->createProperty('TEL', '+49 123456789');
  332. $property->add('TYPE', 'HOME,VOICE');
  333. $vCard->add($property);
  334. $property = $vCard->createProperty('TEL', '+1 555 123456789');
  335. $property->add('TYPE', 'WORK');
  336. $vCard->add($property);
  337. $vCard->add($vCard->createProperty('URL', 'https://localhost'));
  338. $vCard->add($vCard->createProperty('URL', 'https://example.tld'));
  339. // Type depending properties
  340. $property = $vCard->createProperty('X-SOCIALPROFILE', 'tw-example');
  341. $property->add('TYPE', 'twitter');
  342. $vCard->add($property);
  343. $property = $vCard->createProperty('X-SOCIALPROFILE', 'tw-example-2');
  344. $property->add('TYPE', 'twitter');
  345. $vCard->add($property);
  346. $property = $vCard->createProperty('X-SOCIALPROFILE', 'fb-example');
  347. $property->add('TYPE', 'facebook');
  348. $vCard->add($property);
  349. $array = $this->invokePrivate($this->addressBookImpl, 'vCard2Array', ['uri', $vCard, true]);
  350. unset($array['PRODID']);
  351. unset($array['UID']);
  352. $this->assertEquals([
  353. 'URI' => 'uri',
  354. 'VERSION' => '4.0',
  355. 'FN' => 'Full Name',
  356. 'CLOUD' => [
  357. ['type' => '', 'value' => 'cloud-user1@localhost'],
  358. ['type' => '', 'value' => 'cloud-user2@example.tld'],
  359. ],
  360. 'EMAIL' => [
  361. ['type' => 'HOME', 'value' => 'email-user1@localhost'],
  362. ['type' => 'WORK', 'value' => 'email-user2@example.tld'],
  363. ],
  364. 'IMPP' => [
  365. ['type' => '', 'value' => 'impp-user1@localhost'],
  366. ['type' => '', 'value' => 'impp-user2@example.tld'],
  367. ],
  368. 'TEL' => [
  369. ['type' => 'HOME,VOICE', 'value' => '+49 123456789'],
  370. ['type' => 'WORK', 'value' => '+1 555 123456789'],
  371. ],
  372. 'URL' => [
  373. ['type' => '', 'value' => 'https://localhost'],
  374. ['type' => '', 'value' => 'https://example.tld'],
  375. ],
  376. 'X-SOCIALPROFILE' => [
  377. ['type' => 'twitter', 'value' => 'tw-example'],
  378. ['type' => 'twitter', 'value' => 'tw-example-2'],
  379. ['type' => 'facebook', 'value' => 'fb-example'],
  380. ],
  381. 'isLocalSystemBook' => true,
  382. ], $array);
  383. }
  384. }