em = static::getContainer()->get(EntityManagerInterface::class); /** @var \PDO $pdo */ $pdo = $this->em->getConnection()->getNativeConnection(); $this->backend = new CardDavBackend($pdo); $this->em->getConnection()->beginTransaction(); } protected function tearDown(): void { $this->em->getConnection()->rollBack(); parent::tearDown(); } private function addressBookFor(string $uri): array { foreach ($this->backend->getAddressBooksForUser(self::PRINCIPAL) as $book) { if ($uri === $book['uri']) { return $book; } } $this->fail(sprintf('No address book found for uri "%s"', $uri)); } /** * A display name is optional in CardDAV: an MKCOL without {DAV:}displayname must succeed. */ public function testAddressBookCanBeCreatedWithoutADisplayName(): void { $this->backend->createAddressBook(self::PRINCIPAL, 'nameless', []); $this->assertNull($this->addressBookFor('nameless')['{DAV:}displayname']); } public function testADisplayNameIsStillStoredWhenGiven(): void { $this->backend->createAddressBook(self::PRINCIPAL, 'named', ['{DAV:}displayname' => 'My contacts']); $this->assertSame('My contacts', $this->addressBookFor('named')['{DAV:}displayname']); } /** * Same column, the other way round: a client may remove the display name with a PROPPATCH. */ public function testADisplayNameCanBeRemovedAgain(): void { $id = $this->backend->createAddressBook(self::PRINCIPAL, 'transient', ['{DAV:}displayname' => 'Temporary']); $propPatch = new PropPatch(['{DAV:}displayname' => null]); $this->backend->updateAddressBook((string) $id, $propPatch); $this->assertTrue($propPatch->commit(), 'The PROPPATCH should succeed'); $this->assertNull($this->addressBookFor('transient')['{DAV:}displayname']); } }