$amount * @return non-empty-array */ protected function importInvoiceFixtures(int $amount, ?array $status = null): array { $fixture = new InvoiceFixtures(); $fixture->setAmount($amount); if (\is_array($status)) { $fixture->setStatus($status); } return $this->importFixture($fixture); } public function testIsSecure(): void { $this->assertUrlIsSecured('/api/invoices'); } public function testGetCollection(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD); $this->importInvoiceFixtures(10); $this->assertAccessIsGranted($client, '/api/invoices'); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertNotEmpty($result); self::assertEquals(10, \count($result)); self::assertIsArray($result[0]); self::assertApiResponseTypeStructure('InvoiceCollection', $result[0]); } public function testGetCollectionWithQuery(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD); $this->importInvoiceFixtures(5, [Invoice::STATUS_PENDING]); $this->importInvoiceFixtures(2, [Invoice::STATUS_NEW]); $this->importInvoiceFixtures(7, [Invoice::STATUS_PAID]); $this->importInvoiceFixtures(1, [Invoice::STATUS_CANCELED]); $query = ['order' => 'ASC', 'orderBy' => 'name', 'status' => [Invoice::STATUS_PAID]]; $this->assertAccessIsGranted($client, '/api/invoices', 'GET', $query); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertNotEmpty($result); self::assertEquals(7, \count($result)); self::assertIsArray($result[0]); self::assertApiResponseTypeStructure('InvoiceCollection', $result[0]); } public function testGetCollectionWithPagination(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD); $this->importInvoiceFixtures(20); $query = ['page' => 2, 'size' => 4]; $this->assertAccessIsGranted($client, '/api/invoices', 'GET', $query); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertNotEmpty($result); self::assertEquals(4, \count($result)); $this->assertPagination($client->getResponse(), 2, 4, 5, 20); self::assertIsArray($result[0]); self::assertApiResponseTypeStructure('InvoiceCollection', $result[0]); } public function testGetEntityIsSecure(): void { $client = $this->getClientForAuthenticatedUser(); $invoices = $this->importInvoiceFixtures(1); $this->assertApiAccessDenied($client, '/api/invoices/' . $invoices[0]->getId()); } public function testGetEntity(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN); $invoices = $this->importInvoiceFixtures(1); $this->assertAccessIsGranted($client, '/api/invoices/' . $invoices[0]->getId()); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertApiResponseTypeStructure('Invoice', $result); self::assertArrayHasKey('metaFields', $result); self::assertCount(0, $result['metaFields']); } public function testNotFound(): void { $this->assertEntityNotFound(User::ROLE_USER, '/api/invoices/' . PHP_INT_MAX); } public function testGetEntityRespectsCustomerPermission(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD); $invoices = $this->importInvoiceFixtures(1, [Invoice::STATUS_NEW]); $invoice = $invoices[0]; $customer = $invoice->getCustomer(); self::assertInstanceOf(Customer::class, $customer); $this->assertAccessIsGranted($client, '/api/invoices/' . $invoice->getId()); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertApiResponseTypeStructure('Invoice', $result); $team = new Team('foo'); $team->addTeamlead($this->getUserByRole(User::ROLE_ADMIN)); $team->addCustomer($customer); $em = $this->getEntityManager(); /** @var TeamRepository $repository */ $repository = $em->getRepository(Team::class); $repository->saveTeam($team); $this->assertApiAccessDenied($client, '/api/invoices/' . $invoice->getId()); } public function testDownload(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN); $invoice = $this->importInvoiceFixtures(1)[0]; $filename = $invoice->getInvoiceFilename() . '.pdf'; $invoice->setFilename($filename); $em = $this->getEntityManager(); $em->persist($invoice); $em->flush(); /** @var FileHelper $fileHelper */ $fileHelper = $this->getPrivateService(FileHelper::class); $path = $fileHelper->getDataDirectory('invoices') . $filename; file_put_contents($path, '%PDF-1.4 test'); try { $this->assertAccessIsGranted($client, '/api/invoices/' . $invoice->getId() . '/download'); $response = $client->getResponse(); self::assertInstanceOf(BinaryFileResponse::class, $response); self::assertEquals('application/pdf', $response->headers->get('Content-Type')); self::assertStringContainsString('attachment; filename=' . $filename, $response->headers->get('Content-Disposition') ?? ''); } finally { $fileHelper->removeFile($path); } } public function testDownloadIsSecure(): void { $client = $this->getClientForAuthenticatedUser(); $invoices = $this->importInvoiceFixtures(1); $this->assertApiAccessDenied($client, '/api/invoices/' . $invoices[0]->getId() . '/download'); } public function testDownloadRespectsCustomerPermission(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD); $invoice = $this->importInvoiceFixtures(1, [Invoice::STATUS_NEW])[0]; $filename = $invoice->getInvoiceFilename() . '.pdf'; $invoice->setFilename($filename); $em = $this->getEntityManager(); $em->persist($invoice); $em->flush(); /** @var FileHelper $fileHelper */ $fileHelper = $this->getPrivateService(FileHelper::class); $path = $fileHelper->getDataDirectory('invoices') . $filename; file_put_contents($path, '%PDF-1.4 test'); try { $this->assertAccessIsGranted($client, '/api/invoices/' . $invoice->getId() . '/download'); $customer = $invoice->getCustomer(); self::assertInstanceOf(Customer::class, $customer); $team = new Team('foo'); $team->addTeamlead($this->getUserByRole(User::ROLE_ADMIN)); $team->addCustomer($customer); /** @var TeamRepository $repository */ $repository = $em->getRepository(Team::class); $repository->saveTeam($team); $this->assertApiAccessDenied($client, '/api/invoices/' . $invoice->getId() . '/download'); } finally { $fileHelper->removeFile($path); } } public function testCollectionRespectsCustomerPermission(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD); $invoices = $this->importInvoiceFixtures(1, [Invoice::STATUS_NEW]); $invoice = $invoices[0]; $customer = $invoice->getCustomer(); self::assertInstanceOf(Customer::class, $customer); $query = ['customers' => [$customer->getId()]]; $this->assertAccessIsGranted($client, '/api/invoices', 'GET', $query); $team = new Team('foo'); $team->addTeamlead($this->getUserByRole(User::ROLE_ADMIN)); $team->addCustomer($customer); $em = $this->getEntityManager(); /** @var TeamRepository $repository */ $repository = $em->getRepository(Team::class); $repository->saveTeam($team); $this->request($client, '/api/invoices', 'GET', $query); $this->assertApiResponseAccessDenied($client->getResponse()); } // ------------------------------------- [META FIELDS] ------------------------------------- public function testUpdateInvoiceMetaFieldsThrowsNotFound(): void { $this->assertEntityNotFoundForPatch(User::ROLE_ADMIN, '/api/invoices/42/custom-fields', []); } public function testUpdateInvoiceMetaFieldsThrowsExceptionOnWrongStructure(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN); $id = $this->importInvoiceFixtures(1)[0]->getId(); $this->assertExceptionForPatchAction($client, '/api/invoices/' . $id . '/custom-fields', ['name' => 'X', 'value' => 'X'], [ 'code' => Response::HTTP_BAD_REQUEST, 'message' => 'Bad Request' ]); } public function testUpdateInvoiceMetaFieldsThrowsExceptionOnMissingName(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN); $id = $this->importInvoiceFixtures(1)[0]->getId(); $this->assertExceptionForPatchAction($client, '/api/invoices/' . $id . '/custom-fields', [['value' => 'X']], [ 'code' => Response::HTTP_BAD_REQUEST, 'message' => 'Bad Request' ]); } public function testUpdateInvoiceMetaFieldsThrowsExceptionOnMissingValue(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN); $id = $this->importInvoiceFixtures(1)[0]->getId(); $this->assertExceptionForPatchAction($client, '/api/invoices/' . $id . '/custom-fields', [['name' => 'X']], [ 'code' => Response::HTTP_BAD_REQUEST, 'message' => 'Bad Request' ]); } public function testUpdateInvoiceMetaFieldsThrowsExceptionOnMissingMetafield(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN); $id = $this->importInvoiceFixtures(1)[0]->getId(); $this->assertExceptionForPatchAction($client, '/api/invoices/' . $id . '/custom-fields', [['name' => 'X', 'value' => 'Y']], [ 'code' => Response::HTTP_NOT_FOUND, 'message' => 'Not Found' ]); } public function testUpdateInvoiceMetaFields(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN); $invoices = $this->importInvoiceFixtures(1); $id = $invoices[0]->getId(); /** @var EventDispatcher $dispatcher */ $dispatcher = static::getContainer()->get('event_dispatcher'); $dispatcher->addSubscriber(new InvoiceTestMetaFieldSubscriberMock()); $data = [ [ 'name' => 'metatestmock', 'value' => 'another,testing,bar' ], [ 'name' => 'foobar', 'value' => 13081978 ], ]; $this->request($client, '/api/invoices/' . $id . '/custom-fields', 'PATCH', [], (string) json_encode($data)); self::assertTrue($client->getResponse()->isSuccessful()); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertApiResponseTypeStructure('Invoice', $result); self::assertArrayHasKey('metaFields', $result); // only visible should be returned self::assertCount(1, $result['metaFields']); self::assertEquals(['name' => 'metatestmock', 'value' => 'another,testing,bar'], $result['metaFields'][0]); $em = $this->getEntityManager(); /** @var Invoice $invoice */ $invoice = $em->getRepository(Invoice::class)->find($id); self::assertEquals('another,testing,bar', $invoice->getMetaField('metatestmock')?->getValue()); self::assertEquals(13081978, $invoice->getMetaField('foobar')?->getValue()); } }