From 9b4d5e9c27b563e6440dbfa898e333b2c083bbfd Mon Sep 17 00:00:00 2001 From: barisgit Date: Sat, 2 Aug 2025 22:38:59 +0200 Subject: [PATCH] Improve test coverage --- .../BulkInfoProviderImportControllerTest.php | 388 ++++++++++++++++-- tests/Controller/PartControllerTest.php | 334 +++++++++++++++ 2 files changed, 692 insertions(+), 30 deletions(-) create mode 100644 tests/Controller/PartControllerTest.php diff --git a/tests/Controller/BulkInfoProviderImportControllerTest.php b/tests/Controller/BulkInfoProviderImportControllerTest.php index 11807bb5..17a1c235 100644 --- a/tests/Controller/BulkInfoProviderImportControllerTest.php +++ b/tests/Controller/BulkInfoProviderImportControllerTest.php @@ -39,9 +39,9 @@ class BulkInfoProviderImportControllerTest extends WebTestCase { $client = static::createClient(); $this->loginAsUser($client, 'admin'); - + $client->request('GET', '/tools/bulk-info-provider-import/step1'); - + $this->assertResponseRedirects(); } @@ -49,9 +49,9 @@ class BulkInfoProviderImportControllerTest extends WebTestCase { $client = static::createClient(); $this->loginAsUser($client, 'admin'); - + $client->request('GET', '/tools/bulk-info-provider-import/step1?ids=999999,888888'); - + $this->assertResponseRedirects(); } @@ -59,32 +59,32 @@ class BulkInfoProviderImportControllerTest extends WebTestCase { $client = static::createClient(); $this->loginAsUser($client, 'admin'); - + $client->request('GET', '/tools/bulk-info-provider-import/manage'); - + // Follow any redirects (like locale redirects) if ($client->getResponse()->isRedirect()) { $client->followRedirect(); } - + $this->assertResponseStatusCodeSame(Response::HTTP_OK); } public function testAccessControlForStep1(): void { $client = static::createClient(); - + $client->request('GET', '/tools/bulk-info-provider-import/step1?ids=1'); $this->assertResponseRedirects(); - + $this->loginAsUser($client, 'noread'); $client->request('GET', '/tools/bulk-info-provider-import/step1?ids=1'); - + // Follow redirects if any, then check for 403 or final response if ($client->getResponse()->isRedirect()) { $client->followRedirect(); } - + // The user might get redirected to an error page instead of direct 403 $this->assertTrue( $client->getResponse()->getStatusCode() === Response::HTTP_FORBIDDEN || @@ -95,18 +95,18 @@ class BulkInfoProviderImportControllerTest extends WebTestCase public function testAccessControlForManage(): void { $client = static::createClient(); - + $client->request('GET', '/tools/bulk-info-provider-import/manage'); $this->assertResponseRedirects(); - + $this->loginAsUser($client, 'noread'); $client->request('GET', '/tools/bulk-info-provider-import/manage'); - + // Follow redirects if any, then check for 403 or final response if ($client->getResponse()->isRedirect()) { $client->followRedirect(); } - + // The user might get redirected to an error page instead of direct 403 $this->assertTrue( $client->getResponse()->getStatusCode() === Response::HTTP_FORBIDDEN || @@ -118,25 +118,25 @@ class BulkInfoProviderImportControllerTest extends WebTestCase { $client = static::createClient(); $this->loginAsUser($client, 'admin'); - + $entityManager = $client->getContainer()->get('doctrine')->getManager(); - + // Use an existing part from test fixtures (ID 1 should exist) $partRepository = $entityManager->getRepository(Part::class); $part = $partRepository->find(1); - + if (!$part) { $this->markTestSkipped('Test part with ID 1 not found in fixtures'); } - + // Get the admin user for the createdBy field $userRepository = $entityManager->getRepository(User::class); $user = $userRepository->findOneBy(['name' => 'admin']); - + if (!$user) { $this->markTestSkipped('Admin user not found in fixtures'); } - + // Create a test job with search results that include source_field and source_keyword $job = new BulkInfoProviderImportJob(); $job->setCreatedBy($user); @@ -165,25 +165,25 @@ class BulkInfoProviderImportControllerTest extends WebTestCase 'errors' => [] ] ]); - + $entityManager->persist($job); $entityManager->flush(); - + // Test that step2 renders correctly with the search results $client->request('GET', '/tools/bulk-info-provider-import/step2/' . $job->getId()); - + // Follow any redirects (like locale redirects) if ($client->getResponse()->isRedirect()) { $client->followRedirect(); } - + $this->assertResponseStatusCodeSame(Response::HTTP_OK); - + // Verify the template rendered the source_field and source_keyword correctly $content = $client->getResponse()->getContent(); $this->assertStringContainsString('test_field', $content); $this->assertStringContainsString('test_keyword', $content); - + // Clean up - find by ID to avoid detached entity issues $jobId = $job->getId(); $entityManager->clear(); // Clear all entities @@ -194,16 +194,344 @@ class BulkInfoProviderImportControllerTest extends WebTestCase } } + public function testStep1WithValidIds(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $partRepository = $entityManager->getRepository(Part::class); + $part = $partRepository->find(1); + + if (!$part) { + $this->markTestSkipped('Test part with ID 1 not found in fixtures'); + } + + $client->request('GET', '/tools/bulk-info-provider-import/step1?ids=' . $part->getId()); + + if ($client->getResponse()->isRedirect()) { + $client->followRedirect(); + } + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + } + + + public function testDeleteJobWithValidJob(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $userRepository = $entityManager->getRepository(User::class); + $user = $userRepository->findOneBy(['name' => 'admin']); + + if (!$user) { + $this->markTestSkipped('Admin user not found in fixtures'); + } + + // Create a completed job + $job = new BulkInfoProviderImportJob(); + $job->setCreatedBy($user); + $job->setPartIds([1]); + $job->setStatus(BulkImportJobStatus::COMPLETED); + $job->setSearchResults([]); + + $entityManager->persist($job); + $entityManager->flush(); + + $client->request('DELETE', '/en/tools/bulk-info-provider-import/job/' . $job->getId() . '/delete'); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $response = json_decode($client->getResponse()->getContent(), true); + $this->assertTrue($response['success']); + } + + public function testDeleteJobWithNonExistentJob(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $client->request('DELETE', '/en/tools/bulk-info-provider-import/job/999999/delete'); + + $this->assertResponseStatusCodeSame(Response::HTTP_NOT_FOUND); + $response = json_decode($client->getResponse()->getContent(), true); + $this->assertArrayHasKey('error', $response); + } + + public function testDeleteJobWithActiveJob(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $userRepository = $entityManager->getRepository(User::class); + $user = $userRepository->findOneBy(['name' => 'admin']); + + if (!$user) { + $this->markTestSkipped('Admin user not found in fixtures'); + } + + // Create an active job + $job = new BulkInfoProviderImportJob(); + $job->setCreatedBy($user); + $job->setPartIds([1]); + $job->setStatus(BulkImportJobStatus::IN_PROGRESS); + $job->setSearchResults([]); + + $entityManager->persist($job); + $entityManager->flush(); + + $client->request('DELETE', '/en/tools/bulk-info-provider-import/job/' . $job->getId() . '/delete'); + + $this->assertResponseStatusCodeSame(Response::HTTP_BAD_REQUEST); + $response = json_decode($client->getResponse()->getContent(), true); + $this->assertArrayHasKey('error', $response); + + // Clean up + $entityManager->remove($job); + $entityManager->flush(); + } + + public function testStopJobWithValidJob(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $userRepository = $entityManager->getRepository(User::class); + $user = $userRepository->findOneBy(['name' => 'admin']); + + if (!$user) { + $this->markTestSkipped('Admin user not found in fixtures'); + } + + // Create an active job + $job = new BulkInfoProviderImportJob(); + $job->setCreatedBy($user); + $job->setPartIds([1]); + $job->setStatus(BulkImportJobStatus::IN_PROGRESS); + $job->setSearchResults([]); + + $entityManager->persist($job); + $entityManager->flush(); + + $client->request('POST', '/en/tools/bulk-info-provider-import/job/' . $job->getId() . '/stop'); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $response = json_decode($client->getResponse()->getContent(), true); + $this->assertTrue($response['success']); + + // Clean up + $entityManager->remove($job); + $entityManager->flush(); + } + + public function testStopJobWithNonExistentJob(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $client->request('POST', '/en/tools/bulk-info-provider-import/job/999999/stop'); + + $this->assertResponseStatusCodeSame(Response::HTTP_NOT_FOUND); + $response = json_decode($client->getResponse()->getContent(), true); + $this->assertArrayHasKey('error', $response); + } + + public function testMarkPartCompleted(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $userRepository = $entityManager->getRepository(User::class); + $user = $userRepository->findOneBy(['name' => 'admin']); + + if (!$user) { + $this->markTestSkipped('Admin user not found in fixtures'); + } + + $job = new BulkInfoProviderImportJob(); + $job->setCreatedBy($user); + $job->setPartIds([1, 2]); + $job->setStatus(BulkImportJobStatus::IN_PROGRESS); + $job->setSearchResults([]); + + $entityManager->persist($job); + $entityManager->flush(); + + $client->request('POST', '/en/tools/bulk-info-provider-import/job/' . $job->getId() . '/part/1/mark-completed'); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $response = json_decode($client->getResponse()->getContent(), true); + $this->assertTrue($response['success']); + $this->assertArrayHasKey('progress', $response); + $this->assertArrayHasKey('completed_count', $response); + + // Clean up + $entityManager->remove($job); + $entityManager->flush(); + } + + public function testMarkPartSkipped(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $userRepository = $entityManager->getRepository(User::class); + $user = $userRepository->findOneBy(['name' => 'admin']); + + if (!$user) { + $this->markTestSkipped('Admin user not found in fixtures'); + } + + $job = new BulkInfoProviderImportJob(); + $job->setCreatedBy($user); + $job->setPartIds([1, 2]); + $job->setStatus(BulkImportJobStatus::IN_PROGRESS); + $job->setSearchResults([]); + + $entityManager->persist($job); + $entityManager->flush(); + + $client->request('POST', '/en/tools/bulk-info-provider-import/job/' . $job->getId() . '/part/1/mark-skipped', [ + 'reason' => 'Test skip reason' + ]); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $response = json_decode($client->getResponse()->getContent(), true); + $this->assertTrue($response['success']); + $this->assertArrayHasKey('skipped_count', $response); + + // Clean up + $entityManager->remove($job); + $entityManager->flush(); + } + + public function testMarkPartPending(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $userRepository = $entityManager->getRepository(User::class); + $user = $userRepository->findOneBy(['name' => 'admin']); + + if (!$user) { + $this->markTestSkipped('Admin user not found in fixtures'); + } + + $job = new BulkInfoProviderImportJob(); + $job->setCreatedBy($user); + $job->setPartIds([1]); + $job->setStatus(BulkImportJobStatus::IN_PROGRESS); + $job->setSearchResults([]); + + $entityManager->persist($job); + $entityManager->flush(); + + $client->request('POST', '/en/tools/bulk-info-provider-import/job/' . $job->getId() . '/part/1/mark-pending'); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $response = json_decode($client->getResponse()->getContent(), true); + $this->assertTrue($response['success']); + + // Clean up + $entityManager->remove($job); + $entityManager->flush(); + } + + public function testStep2WithNonExistentJob(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $client->request('GET', '/tools/bulk-info-provider-import/step2/999999'); + + $this->assertResponseRedirects(); + } + + public function testStep2WithUnauthorizedAccess(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $userRepository = $entityManager->getRepository(User::class); + $admin = $userRepository->findOneBy(['name' => 'admin']); + $readonly = $userRepository->findOneBy(['name' => 'noread']); + + if (!$admin || !$readonly) { + $this->markTestSkipped('Required test users not found in fixtures'); + } + + // Create job as admin + $job = new BulkInfoProviderImportJob(); + $job->setCreatedBy($admin); + $job->setPartIds([1]); + $job->setStatus(BulkImportJobStatus::IN_PROGRESS); + $job->setSearchResults([]); + + $entityManager->persist($job); + $entityManager->flush(); + + // Try to access as readonly user + $this->loginAsUser($client, 'noread'); + $client->request('GET', '/tools/bulk-info-provider-import/step2/' . $job->getId()); + + $this->assertResponseRedirects(); + + // Clean up + $entityManager->remove($job); + $entityManager->flush(); + } + + public function testJobAccessControlForDelete(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $userRepository = $entityManager->getRepository(User::class); + $admin = $userRepository->findOneBy(['name' => 'admin']); + $readonly = $userRepository->findOneBy(['name' => 'noread']); + + if (!$admin || !$readonly) { + $this->markTestSkipped('Required test users not found in fixtures'); + } + + // Create job as readonly user + $job = new BulkInfoProviderImportJob(); + $job->setCreatedBy($readonly); + $job->setPartIds([1]); + $job->setStatus(BulkImportJobStatus::COMPLETED); + $job->setSearchResults([]); + + $entityManager->persist($job); + $entityManager->flush(); + + // Try to delete as admin (should fail due to ownership) + $client->request('DELETE', '/en/tools/bulk-info-provider-import/job/' . $job->getId() . '/delete'); + + $this->assertResponseStatusCodeSame(Response::HTTP_NOT_FOUND); + + // Clean up + $entityManager->remove($job); + $entityManager->flush(); + } + private function loginAsUser($client, string $username): void { $entityManager = $client->getContainer()->get('doctrine')->getManager(); $userRepository = $entityManager->getRepository(User::class); $user = $userRepository->findOneBy(['name' => $username]); - + if (!$user) { - $this->markTestSkipped('User ' . $username . ' not found'); + $this->markTestSkipped("User {$username} not found"); } - + $client->loginUser($user); } } \ No newline at end of file diff --git a/tests/Controller/PartControllerTest.php b/tests/Controller/PartControllerTest.php new file mode 100644 index 00000000..b6a1ec19 --- /dev/null +++ b/tests/Controller/PartControllerTest.php @@ -0,0 +1,334 @@ +. + */ + +declare(strict_types=1); + +namespace App\Tests\Controller; + +use App\Entity\Parts\Part; +use App\Entity\Parts\PartLot; +use App\Entity\Parts\Category; +use App\Entity\Parts\Footprint; +use App\Entity\Parts\Manufacturer; +use App\Entity\Parts\StorageLocation; +use App\Entity\Parts\Supplier; +use App\Entity\UserSystem\User; +use App\Entity\BulkInfoProviderImportJob; +use App\Entity\BulkImportJobStatus; +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; +use Symfony\Component\HttpFoundation\Response; + +/** + * @group slow + * @group DB + */ +class PartControllerTest extends WebTestCase +{ + public function testShowPart(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $partRepository = $entityManager->getRepository(Part::class); + $part = $partRepository->find(1); + + if (!$part) { + $this->markTestSkipped('Test part with ID 1 not found in fixtures'); + } + + $client->request('GET', '/en/part/' . $part->getId()); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + } + + public function testShowPartWithTimestamp(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $partRepository = $entityManager->getRepository(Part::class); + $part = $partRepository->find(1); + + if (!$part) { + $this->markTestSkipped('Test part with ID 1 not found in fixtures'); + } + + $timestamp = time(); + $client->request('GET', "/en/part/{$part->getId()}/info/{$timestamp}"); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + } + + public function testEditPart(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $partRepository = $entityManager->getRepository(Part::class); + $part = $partRepository->find(1); + + if (!$part) { + $this->markTestSkipped('Test part with ID 1 not found in fixtures'); + } + + $client->request('GET', '/en/part/' . $part->getId() . '/edit'); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $this->assertSelectorExists('form[name="part_base"]'); + } + + public function testEditPartWithBulkJob(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $partRepository = $entityManager->getRepository(Part::class); + $part = $partRepository->find(1); + + $userRepository = $entityManager->getRepository(User::class); + $user = $userRepository->findOneBy(['name' => 'admin']); + + if (!$part || !$user) { + $this->markTestSkipped('Required test data not found in fixtures'); + } + + // Create a bulk job + $job = new BulkInfoProviderImportJob(); + $job->setCreatedBy($user); + $job->setPartIds([$part->getId()]); + $job->setStatus(BulkImportJobStatus::IN_PROGRESS); + $job->setSearchResults([]); + + $entityManager->persist($job); + $entityManager->flush(); + + $client->request('GET', '/en/part/' . $part->getId() . '/edit?jobId=' . $job->getId()); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + + // Clean up + $entityManager->remove($job); + $entityManager->flush(); + } + + + + public function testNewPart(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $client->request('GET', '/en/part/new'); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $this->assertSelectorExists('form[name="part_base"]'); + } + + public function testNewPartWithCategory(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $categoryRepository = $entityManager->getRepository(Category::class); + $category = $categoryRepository->find(1); + + if (!$category) { + $this->markTestSkipped('Test category with ID 1 not found in fixtures'); + } + + $client->request('GET', '/en/part/new?category=' . $category->getId()); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + } + + public function testNewPartWithFootprint(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $footprintRepository = $entityManager->getRepository(Footprint::class); + $footprint = $footprintRepository->find(1); + + if (!$footprint) { + $this->markTestSkipped('Test footprint with ID 1 not found in fixtures'); + } + + $client->request('GET', '/en/part/new?footprint=' . $footprint->getId()); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + } + + public function testNewPartWithManufacturer(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $manufacturerRepository = $entityManager->getRepository(Manufacturer::class); + $manufacturer = $manufacturerRepository->find(1); + + if (!$manufacturer) { + $this->markTestSkipped('Test manufacturer with ID 1 not found in fixtures'); + } + + $client->request('GET', '/en/part/new?manufacturer=' . $manufacturer->getId()); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + } + + public function testNewPartWithStorageLocation(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $storageLocationRepository = $entityManager->getRepository(StorageLocation::class); + $storageLocation = $storageLocationRepository->find(1); + + if (!$storageLocation) { + $this->markTestSkipped('Test storage location with ID 1 not found in fixtures'); + } + + $client->request('GET', '/en/part/new?storelocation=' . $storageLocation->getId()); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + } + + public function testNewPartWithSupplier(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $supplierRepository = $entityManager->getRepository(Supplier::class); + $supplier = $supplierRepository->find(1); + + if (!$supplier) { + $this->markTestSkipped('Test supplier with ID 1 not found in fixtures'); + } + + $client->request('GET', '/en/part/new?supplier=' . $supplier->getId()); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + } + + public function testClonePart(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $partRepository = $entityManager->getRepository(Part::class); + $part = $partRepository->find(1); + + if (!$part) { + $this->markTestSkipped('Test part with ID 1 not found in fixtures'); + } + + $client->request('GET', '/en/part/' . $part->getId() . '/clone'); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $this->assertSelectorExists('form[name="part_base"]'); + } + + public function testMergeParts(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'admin'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $categoryRepository = $entityManager->getRepository(Category::class); + $category = $categoryRepository->find(1); + + if (!$category) { + $this->markTestSkipped('Test category with ID 1 not found in fixtures'); + } + + // Create two test parts + $targetPart = new Part(); + $targetPart->setName('Target Part'); + $targetPart->setCategory($category); + + $otherPart = new Part(); + $otherPart->setName('Other Part'); + $otherPart->setCategory($category); + + $entityManager->persist($targetPart); + $entityManager->persist($otherPart); + $entityManager->flush(); + + $client->request('GET', "/en/part/{$targetPart->getId()}/merge/{$otherPart->getId()}"); + + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $this->assertSelectorExists('form[name="part_base"]'); + + // Clean up + $entityManager->remove($targetPart); + $entityManager->remove($otherPart); + $entityManager->flush(); + } + + + + + + public function testAccessControlForUnauthorizedUser(): void + { + $client = static::createClient(); + $this->loginAsUser($client, 'noread'); + + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $partRepository = $entityManager->getRepository(Part::class); + $part = $partRepository->find(1); + + if (!$part) { + $this->markTestSkipped('Test part with ID 1 not found in fixtures'); + } + + $client->request('GET', '/en/part/' . $part->getId()); + + // Should either be forbidden or redirected to error page + $this->assertTrue( + $client->getResponse()->getStatusCode() === Response::HTTP_FORBIDDEN || + $client->getResponse()->isRedirect() + ); + } + + private function loginAsUser($client, string $username): void + { + $entityManager = $client->getContainer()->get('doctrine')->getManager(); + $userRepository = $entityManager->getRepository(User::class); + $user = $userRepository->findOneBy(['name' => $username]); + + if (!$user) { + $this->markTestSkipped("User {$username} not found"); + } + + $client->loginUser($user); + } + +} \ No newline at end of file