em = self::getContainer()->get(EntityManagerInterface::class); $this->admin = new User(); $this->admin->setUsername('mcp-address-admin-'.uniqid()); $this->admin->setPassword('x'); $this->admin->setRoles(['ROLE_ADMIN']); $this->em->persist($this->admin); $this->client = new Client(); $this->client->setName('Test Client '.uniqid()); $this->em->persist($this->client); $this->prospect = new Prospect(); $this->prospect->setCompany('Test Prospect '.uniqid()); $this->em->persist($this->prospect); $this->prestataire = new Prestataire(); $this->prestataire->setName('Test Prestataire '.uniqid()); $this->em->persist($this->prestataire); $this->em->flush(); } public function testCreateRequiresExactlyOneParent(): void { try { ($this->createTool())(null, null, null, 'Home'); self::fail('Expected error when no parent provided.'); } catch (InvalidArgumentException $e) { self::assertStringContainsString('Exactly one of clientId, prospectId or prestataireId', $e->getMessage()); } try { ($this->createTool())($this->client->getId(), null, $this->prestataire->getId(), 'Dup'); self::fail('Expected error when two parents provided.'); } catch (InvalidArgumentException $e) { self::assertStringContainsString('Exactly one of clientId, prospectId or prestataireId', $e->getMessage()); } } public function testCreateCountryDefaultsToFRWhenOmitted(): void { $data = json_decode(($this->createTool())($this->client->getId(), null, null, 'HQ'), true); self::assertSame('FR', $data['country']); } public function testCreateRejectsNonIso3166Country(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('country must be a 2-letter ISO 3166 alpha-2 code'); ($this->createTool())($this->client->getId(), null, null, 'HQ', null, null, null, null, 'France'); } public function testCreateNormalizesCountryToUppercase(): void { $data = json_decode(($this->createTool())($this->client->getId(), null, null, 'HQ', null, null, null, null, 'be'), true); self::assertSame('BE', $data['country']); } public function testCreateOnEachParentWorks(): void { $clientAddr = json_decode(($this->createTool())($this->client->getId(), null, null, 'CHQ'), true); self::assertSame($this->client->getId(), $clientAddr['clientId']); self::assertNull($clientAddr['prospectId']); $prospectAddr = json_decode(($this->createTool())(null, $this->prospect->getId(), null, 'PHQ'), true); self::assertSame($this->prospect->getId(), $prospectAddr['prospectId']); $prestAddr = json_decode(($this->createTool())(null, null, $this->prestataire->getId(), 'XHQ'), true); self::assertSame($this->prestataire->getId(), $prestAddr['prestataireId']); } public function testGetReturnsAddress(): void { $created = json_decode(($this->createTool())($this->client->getId(), null, null, 'Office', '1 rue X', null, '75001', 'Paris', 'FR'), true); $data = json_decode(($this->getTool())((int) $created['id']), true); self::assertSame('Office', $data['label']); self::assertSame('1 rue X', $data['street']); self::assertSame('75001', $data['postalCode']); self::assertSame('Paris', $data['city']); self::assertSame('FR', $data['country']); } public function testListFilteredByClient(): void { ($this->createTool())($this->client->getId(), null, null, 'A'); ($this->createTool())($this->client->getId(), null, null, 'B'); ($this->createTool())(null, null, $this->prestataire->getId(), 'Z'); $data = json_decode(($this->listTool())($this->client->getId(), null, null), true); self::assertCount(2, $data); self::assertSame('A', $data[0]['label']); self::assertSame('B', $data[1]['label']); } public function testUpdateRejectsNonIso3166Country(): void { $created = json_decode(($this->createTool())($this->client->getId(), null, null, 'X'), true); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('country must be a 2-letter ISO 3166 alpha-2 code'); ($this->updateTool())((int) $created['id'], null, null, null, null, null, 'Belgium'); } public function testUpdateOnlyTouchesProvidedFields(): void { $created = json_decode(($this->createTool())($this->client->getId(), null, null, 'Old', '1 rue X', null, '75001', 'Paris', 'FR'), true); $data = json_decode(($this->updateTool())((int) $created['id'], 'New', null, null, '75002', null, 'be'), true); self::assertSame('New', $data['label']); // changed self::assertSame('1 rue X', $data['street']); // unchanged self::assertSame('75002', $data['postalCode']); // changed self::assertSame('Paris', $data['city']); // unchanged self::assertSame('BE', $data['country']); // changed + uppercased } public function testDeleteRemovesAddress(): void { $created = json_decode(($this->createTool())($this->client->getId(), null, null, 'Bye'), true); $id = (int) $created['id']; $data = json_decode(($this->deleteTool())($id), true); self::assertTrue($data['success']); $this->em->clear(); self::assertNull(self::getContainer()->get(AddressRepositoryInterface::class)->findById($id)); } private function securityFor(bool $admin = true): Security { $security = $this->createMock(Security::class); $security->method('isGranted')->willReturn($admin); $security->method('getUser')->willReturn($admin ? $this->admin : null); return $security; } private function createTool(): CreateAddressTool { $c = self::getContainer(); return new CreateAddressTool( $this->em, $c->get(ClientRepositoryInterface::class), $c->get(ProspectRepositoryInterface::class), $c->get(PrestataireRepositoryInterface::class), $this->securityFor(), ); } private function getTool(): GetAddressTool { return new GetAddressTool( self::getContainer()->get(AddressRepositoryInterface::class), $this->securityFor(), ); } private function listTool(): ListAddressesTool { return new ListAddressesTool( self::getContainer()->get(AddressRepositoryInterface::class), $this->securityFor(), ); } private function updateTool(): UpdateAddressTool { return new UpdateAddressTool( self::getContainer()->get(AddressRepositoryInterface::class), $this->em, $this->securityFor(), ); } private function deleteTool(): DeleteAddressTool { return new DeleteAddressTool( self::getContainer()->get(AddressRepositoryInterface::class), $this->em, $this->securityFor(), ); } }