2222
2323namespace App \Tests \Controller ;
2424
25+ use App \Controller \BulkInfoProviderImportController ;
2526use App \Entity \Parts \Part ;
2627use App \Entity \BulkInfoProviderImportJob ;
2728use App \Entity \BulkImportJobStatus ;
@@ -593,4 +594,321 @@ private function getTestParts($entityManager, array $ids): array
593594
594595 return $ parts ;
595596 }
597+
598+ public function testStep1Form (): void
599+ {
600+ $ client = static ::createClient ();
601+ $ this ->loginAsUser ($ client , 'admin ' );
602+
603+ $ entityManager = $ client ->getContainer ()->get ('doctrine ' )->getManager ();
604+ $ partRepository = $ entityManager ->getRepository (Part::class);
605+ $ part = $ partRepository ->find (1 );
606+
607+ if (!$ part ) {
608+ $ this ->markTestSkipped ('Test part with ID 1 not found in fixtures ' );
609+ }
610+
611+ $ client ->request ('GET ' , '/tools/bulk-info-provider-import/step1?ids= ' . $ part ->getId ());
612+
613+ if ($ client ->getResponse ()->isRedirect ()) {
614+ $ client ->followRedirect ();
615+ }
616+
617+ $ this ->assertResponseStatusCodeSame (Response::HTTP_OK );
618+ $ this ->assertStringContainsString ('Bulk Info Provider Import ' , $ client ->getResponse ()->getContent ());
619+ }
620+
621+ public function testStep1FormSubmissionWithErrors (): void
622+ {
623+ $ client = static ::createClient ();
624+ $ this ->loginAsUser ($ client , 'admin ' );
625+
626+ $ entityManager = $ client ->getContainer ()->get ('doctrine ' )->getManager ();
627+ $ partRepository = $ entityManager ->getRepository (Part::class);
628+ $ part = $ partRepository ->find (1 );
629+
630+ if (!$ part ) {
631+ $ this ->markTestSkipped ('Test part with ID 1 not found in fixtures ' );
632+ }
633+
634+ $ client ->request ('GET ' , '/tools/bulk-info-provider-import/step1?ids= ' . $ part ->getId ());
635+
636+ if ($ client ->getResponse ()->isRedirect ()) {
637+ $ client ->followRedirect ();
638+ }
639+
640+ $ this ->assertResponseStatusCodeSame (Response::HTTP_OK );
641+ $ this ->assertStringContainsString ('Bulk Info Provider Import ' , $ client ->getResponse ()->getContent ());
642+ }
643+
644+ public function testGetKeywordFromFieldPrivateMethod (): void
645+ {
646+ $ client = static ::createClient ();
647+ $ this ->loginAsUser ($ client , 'admin ' );
648+
649+ $ entityManager = $ client ->getContainer ()->get ('doctrine ' )->getManager ();
650+ $ partRepository = $ entityManager ->getRepository (Part::class);
651+ $ part = $ partRepository ->find (1 );
652+
653+ if (!$ part ) {
654+ $ this ->markTestSkipped ('Test part with ID 1 not found in fixtures ' );
655+ }
656+
657+ $ controller = $ client ->getContainer ()->get (BulkInfoProviderImportController::class);
658+ $ reflection = new \ReflectionClass ($ controller );
659+ $ method = $ reflection ->getMethod ('getKeywordFromField ' );
660+ $ method ->setAccessible (true );
661+
662+ $ result = $ method ->invokeArgs ($ controller , [$ part , 'name ' ]);
663+ $ this ->assertIsString ($ result );
664+
665+ $ result = $ method ->invokeArgs ($ controller , [$ part , 'mpn ' ]);
666+ $ this ->assertIsString ($ result );
667+ }
668+
669+ public function testSerializeAndDeserializeSearchResults (): void
670+ {
671+ $ client = static ::createClient ();
672+ $ this ->loginAsUser ($ client , 'admin ' );
673+
674+ $ entityManager = $ client ->getContainer ()->get ('doctrine ' )->getManager ();
675+ $ partRepository = $ entityManager ->getRepository (Part::class);
676+ $ part = $ partRepository ->find (1 );
677+
678+ if (!$ part ) {
679+ $ this ->markTestSkipped ('Test part with ID 1 not found in fixtures ' );
680+ }
681+
682+ $ controller = $ client ->getContainer ()->get (BulkInfoProviderImportController::class);
683+ $ reflection = new \ReflectionClass ($ controller );
684+
685+ $ serializeMethod = $ reflection ->getMethod ('serializeSearchResults ' );
686+ $ serializeMethod ->setAccessible (true );
687+
688+ $ deserializeMethod = $ reflection ->getMethod ('deserializeSearchResults ' );
689+ $ deserializeMethod ->setAccessible (true );
690+
691+ $ searchResults = [[
692+ 'part ' => $ part ,
693+ 'search_results ' => [[
694+ 'dto ' => new \App \Services \InfoProviderSystem \DTOs \SearchResultDTO (
695+ provider_key: 'test ' ,
696+ provider_id: 'TEST123 ' ,
697+ name: 'Test Component ' ,
698+ description: 'Test description ' ,
699+ manufacturer: 'Test Manufacturer ' ,
700+ mpn: 'TEST-MPN ' ,
701+ provider_url: 'https://example.com ' ,
702+ preview_image_url: null
703+ ),
704+ 'localPart ' => null ,
705+ 'source_field ' => 'mpn ' ,
706+ 'source_keyword ' => 'TEST123 '
707+ ]],
708+ 'errors ' => []
709+ ]];
710+
711+ $ serialized = $ serializeMethod ->invokeArgs ($ controller , [$ searchResults ]);
712+ $ this ->assertIsArray ($ serialized );
713+ $ this ->assertArrayHasKey (0 , $ serialized );
714+ $ this ->assertArrayHasKey ('part_id ' , $ serialized [0 ]);
715+
716+ $ deserialized = $ deserializeMethod ->invokeArgs ($ controller , [$ serialized , [$ part ]]);
717+ $ this ->assertIsArray ($ deserialized );
718+ $ this ->assertCount (1 , $ deserialized );
719+ }
720+
721+ public function testManagePageWithJobCleanup (): void
722+ {
723+ $ client = static ::createClient ();
724+ $ this ->loginAsUser ($ client , 'admin ' );
725+
726+ $ entityManager = $ client ->getContainer ()->get ('doctrine ' )->getManager ();
727+ $ userRepository = $ entityManager ->getRepository (User::class);
728+ $ user = $ userRepository ->findOneBy (['name ' => 'admin ' ]);
729+
730+ if (!$ user ) {
731+ $ this ->markTestSkipped ('Admin user not found in fixtures ' );
732+ }
733+
734+ $ partRepository = $ entityManager ->getRepository (Part::class);
735+ $ part = $ partRepository ->find (1 );
736+
737+ if (!$ part ) {
738+ $ this ->markTestSkipped ('Test part with ID 1 not found in fixtures ' );
739+ }
740+
741+ $ job = new BulkInfoProviderImportJob ();
742+ $ job ->setCreatedBy ($ user );
743+ $ job ->addPart ($ part );
744+ $ job ->setStatus (BulkImportJobStatus::IN_PROGRESS );
745+ $ job ->setSearchResults ([]);
746+
747+ $ entityManager ->persist ($ job );
748+ $ entityManager ->flush ();
749+
750+ $ client ->request ('GET ' , '/tools/bulk-info-provider-import/manage ' );
751+
752+ if ($ client ->getResponse ()->isRedirect ()) {
753+ $ client ->followRedirect ();
754+ }
755+
756+ $ this ->assertResponseStatusCodeSame (Response::HTTP_OK );
757+
758+ // Find job from database to avoid detached entity errors
759+ $ jobId = $ job ->getId ();
760+ $ entityManager ->clear ();
761+ $ persistedJob = $ entityManager ->find (BulkInfoProviderImportJob::class, $ jobId );
762+ if ($ persistedJob ) {
763+ $ entityManager ->remove ($ persistedJob );
764+ $ entityManager ->flush ();
765+ }
766+ }
767+
768+ public function testGetSupplierPartNumberPrivateMethod (): void
769+ {
770+ $ client = static ::createClient ();
771+ $ this ->loginAsUser ($ client , 'admin ' );
772+
773+ $ entityManager = $ client ->getContainer ()->get ('doctrine ' )->getManager ();
774+ $ partRepository = $ entityManager ->getRepository (Part::class);
775+ $ part = $ partRepository ->find (1 );
776+
777+ if (!$ part ) {
778+ $ this ->markTestSkipped ('Test part with ID 1 not found in fixtures ' );
779+ }
780+
781+ $ controller = $ client ->getContainer ()->get (BulkInfoProviderImportController::class);
782+ $ reflection = new \ReflectionClass ($ controller );
783+ $ method = $ reflection ->getMethod ('getSupplierPartNumber ' );
784+ $ method ->setAccessible (true );
785+
786+ $ result = $ method ->invokeArgs ($ controller , [$ part , 'invalid_field ' ]);
787+ $ this ->assertNull ($ result );
788+
789+ $ result = $ method ->invokeArgs ($ controller , [$ part , 'test_supplier_spn ' ]);
790+ $ this ->assertNull ($ result );
791+ }
792+
793+ public function testSearchLcscBatchPrivateMethod (): void
794+ {
795+ $ client = static ::createClient ();
796+ $ this ->loginAsUser ($ client , 'admin ' );
797+
798+ $ controller = $ client ->getContainer ()->get (BulkInfoProviderImportController::class);
799+ $ reflection = new \ReflectionClass ($ controller );
800+ $ method = $ reflection ->getMethod ('searchLcscBatch ' );
801+ $ method ->setAccessible (true );
802+
803+ $ result = $ method ->invokeArgs ($ controller , [['TEST123 ' , 'TEST456 ' ]]);
804+ $ this ->assertIsArray ($ result );
805+ }
806+
807+ public function testPrefetchDetailsForResultsPrivateMethod (): void
808+ {
809+ $ client = static ::createClient ();
810+ $ this ->loginAsUser ($ client , 'admin ' );
811+
812+ $ entityManager = $ client ->getContainer ()->get ('doctrine ' )->getManager ();
813+ $ partRepository = $ entityManager ->getRepository (Part::class);
814+ $ part = $ partRepository ->find (1 );
815+
816+ if (!$ part ) {
817+ $ this ->markTestSkipped ('Test part with ID 1 not found in fixtures ' );
818+ }
819+
820+ $ reflection = new \ReflectionClass (BulkInfoProviderImportController::class);
821+ $ method = $ reflection ->getMethod ('prefetchDetailsForResults ' );
822+ $ method ->setAccessible (true );
823+
824+ // Test the method exists and can be called
825+ $ this ->assertTrue ($ method ->isPrivate ());
826+ $ this ->assertEquals ('prefetchDetailsForResults ' , $ method ->getName ());
827+ }
828+
829+ public function testJobAccessControlForStopAndMarkOperations (): void
830+ {
831+ $ client = static ::createClient ();
832+ $ this ->loginAsUser ($ client , 'admin ' );
833+
834+ $ entityManager = $ client ->getContainer ()->get ('doctrine ' )->getManager ();
835+ $ userRepository = $ entityManager ->getRepository (User::class);
836+ $ admin = $ userRepository ->findOneBy (['name ' => 'admin ' ]);
837+ $ readonly = $ userRepository ->findOneBy (['name ' => 'noread ' ]);
838+
839+ if (!$ admin || !$ readonly ) {
840+ $ this ->markTestSkipped ('Required test users not found in fixtures ' );
841+ }
842+
843+ $ parts = $ this ->getTestParts ($ entityManager , [1 ]);
844+
845+ $ job = new BulkInfoProviderImportJob ();
846+ $ job ->setCreatedBy ($ readonly );
847+ foreach ($ parts as $ part ) {
848+ $ job ->addPart ($ part );
849+ }
850+ $ job ->setStatus (BulkImportJobStatus::IN_PROGRESS );
851+ $ job ->setSearchResults ([]);
852+
853+ $ entityManager ->persist ($ job );
854+ $ entityManager ->flush ();
855+
856+ $ client ->request ('POST ' , '/en/tools/bulk-info-provider-import/job/ ' . $ job ->getId () . '/stop ' );
857+ $ this ->assertResponseStatusCodeSame (Response::HTTP_NOT_FOUND );
858+
859+ $ client ->request ('POST ' , '/en/tools/bulk-info-provider-import/job/ ' . $ job ->getId () . '/part/1/mark-completed ' );
860+ $ this ->assertResponseStatusCodeSame (Response::HTTP_NOT_FOUND );
861+
862+ $ client ->request ('POST ' , '/en/tools/bulk-info-provider-import/job/ ' . $ job ->getId () . '/part/1/mark-skipped ' , [
863+ 'reason ' => 'Test reason '
864+ ]);
865+ $ this ->assertResponseStatusCodeSame (Response::HTTP_NOT_FOUND );
866+
867+ $ client ->request ('POST ' , '/en/tools/bulk-info-provider-import/job/ ' . $ job ->getId () . '/part/1/mark-pending ' );
868+ $ this ->assertResponseStatusCodeSame (Response::HTTP_NOT_FOUND );
869+
870+ // Find job from database to avoid detached entity errors
871+ $ jobId = $ job ->getId ();
872+ $ entityManager ->clear ();
873+ $ persistedJob = $ entityManager ->find (BulkInfoProviderImportJob::class, $ jobId );
874+ if ($ persistedJob ) {
875+ $ entityManager ->remove ($ persistedJob );
876+ $ entityManager ->flush ();
877+ }
878+ }
879+
880+ public function testOperationsOnCompletedJob (): void
881+ {
882+ $ client = static ::createClient ();
883+ $ this ->loginAsUser ($ client , 'admin ' );
884+
885+ $ entityManager = $ client ->getContainer ()->get ('doctrine ' )->getManager ();
886+ $ userRepository = $ entityManager ->getRepository (User::class);
887+ $ user = $ userRepository ->findOneBy (['name ' => 'admin ' ]);
888+
889+ if (!$ user ) {
890+ $ this ->markTestSkipped ('Admin user not found in fixtures ' );
891+ }
892+
893+ $ parts = $ this ->getTestParts ($ entityManager , [1 ]);
894+
895+ $ job = new BulkInfoProviderImportJob ();
896+ $ job ->setCreatedBy ($ user );
897+ foreach ($ parts as $ part ) {
898+ $ job ->addPart ($ part );
899+ }
900+ $ job ->setStatus (BulkImportJobStatus::COMPLETED );
901+ $ job ->setSearchResults ([]);
902+
903+ $ entityManager ->persist ($ job );
904+ $ entityManager ->flush ();
905+
906+ $ client ->request ('POST ' , '/en/tools/bulk-info-provider-import/job/ ' . $ job ->getId () . '/stop ' );
907+ $ this ->assertResponseStatusCodeSame (Response::HTTP_BAD_REQUEST );
908+ $ response = json_decode ($ client ->getResponse ()->getContent (), true );
909+ $ this ->assertArrayHasKey ('error ' , $ response );
910+
911+ $ entityManager ->remove ($ job );
912+ $ entityManager ->flush ();
913+ }
596914}
0 commit comments