client = static::createClient(server: ['HTTPS' => true]); $this->entityManager = self::getContainer()->get(EntityManagerInterface::class); $this->entityManager->createQuery(sprintf('DELETE FROM %s', SeasonTaskDocument::class))->execute(); $this->entityManager->createQuery(sprintf('DELETE FROM %s', Upload::class))->execute(); $this->entityManager->createQuery(sprintf('DELETE FROM %s', User::class))->execute(); $this->client->loginUser($this->administrative()); } /** * The mapping holds a foreign key on upload; left behind, it breaks every later test that * clears the upload table. */ protected function tearDown(): void { $this->entityManager->createQuery(sprintf('DELETE FROM %s', SeasonTaskDocument::class))->execute(); parent::tearDown(); } public function testTheModalOffersNoConfirmationForAnAssignedDocument(): void { $document = $this->assigned($this->document('Vertrag.pdf'), SeasonTask::CONTRACT); $crawler = $this->client->request('GET', $this->deleteUrl($document)); $this->assertSame(Response::HTTP_OK, $this->client->getResponse()->getStatusCode()); $this->assertStringContainsString('kann deshalb nicht gelöscht werden', $crawler->text()); $this->assertStringContainsString('Vertrag', $crawler->text()); $this->assertCount(0, $crawler->filter('button[hx-post]')); } public function testDeletingAnAssignedDocumentIsRefused(): void { $document = $this->assigned($this->document('Vertrag.pdf'), SeasonTask::CONTRACT); $id = $document->getId(); $this->client->request('POST', $this->deleteUrl($document)); $this->assertSame(Response::HTTP_OK, $this->client->getResponse()->getStatusCode()); $this->assertSame(self::LIST_URL, $this->client->getResponse()->headers->get('HX-Redirect')); $this->entityManager->clear(); $this->assertNotNull($this->entityManager->find(Upload::class, $id)); } /** * A row whose task key no longer resolves still holds the foreign key. */ public function testAnAssignmentToARemovedTaskStillBlocksDeletion(): void { $document = $this->document('Alt.pdf'); $this->entityManager->persist((new SeasonTaskDocument())->setTaskKey('removed_task')->setDocument($document)); $this->entityManager->flush(); $id = $document->getId(); $this->client->request('POST', $this->deleteUrl($document)); // Refused by the guard, not by the database: that would be the 500. $this->assertSame(self::LIST_URL, $this->client->getResponse()->headers->get('HX-Redirect')); $this->entityManager->clear(); $this->assertNotNull($this->entityManager->find(Upload::class, $id)); } public function testAnUnassignedDocumentIsDeleted(): void { $document = $this->document('Handbuch.pdf'); $id = $document->getId(); $crawler = $this->client->request('GET', $this->deleteUrl($document)); $this->assertCount(1, $crawler->filter('button[hx-post]')); $this->client->request('POST', $this->deleteUrl($document)); $this->assertSame(self::LIST_URL, $this->client->getResponse()->headers->get('HX-Redirect')); $this->entityManager->clear(); $this->assertNull($this->entityManager->find(Upload::class, $id)); } public function testTheListMarksAnAssignedDocumentAndOffersNoDelete(): void { $assigned = $this->assigned($this->document('Vertrag.pdf'), SeasonTask::CONTRACT); $free = $this->document('Handbuch.pdf'); $crawler = $this->client->request('GET', self::LIST_URL); $this->assertSame(Response::HTTP_OK, $this->client->getResponse()->getStatusCode()); $this->assertStringContainsString('Saisonteam: Vertrag', $crawler->text()); $this->assertCount(0, $crawler->filter(sprintf('button[hx-get="%s"]', $this->deleteUrl($assigned)))); $this->assertCount(1, $crawler->filter(sprintf('button[hx-get="%s"]', $this->deleteUrl($free)))); } private function deleteUrl(Upload $document): string { return sprintf('/administrative/system/document/delete/%s', $document->getUuid()); } private function assigned(Upload $document, SeasonTask $task): Upload { $this->entityManager->persist((new SeasonTaskDocument())->setTaskKey($task->value)->setDocument($document)); $this->entityManager->flush(); return $document; } private function document(string $filename): Upload { // No file on disk: neither the guard nor the list reads it, and deleting a missing file // is a no-op for UploadHandler::removeUploadedFile(). $upload = (new Upload()) ->setType(Upload::TYPE_DOCUMENT) ->setFilename(sprintf('test-%s-%s', bin2hex(random_bytes(4)), $filename)) ->setOriginalFilename($filename) ->setMimeType('application/pdf') ->setSize(1024) ; $this->entityManager->persist($upload); $this->entityManager->flush(); return $upload; } private function administrative(): User { $user = (new User()) ->setFirstName('Anna') ->setLastName('Administrative') ->setEmail('anna.administrative@example.com') ->setRoles(['ROLE_ADMINISTRATIVE']) ->setBusProAddressId(1) ->setBusProPersonId(1) ; $this->entityManager->persist($user); $this->entityManager->flush(); return $user; } }